#ifndef LLVM_ADT_SMALLPTRSET_H
#define LLVM_ADT_SMALLPTRSET_H
#include "llvm/Support/Compiler.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/PointerLikeTypeTraits.h"
#include <cassert>
#include <cstddef>
#include <cstring>
#include <iterator>
namespace llvm {
class SmallPtrSetIteratorImpl;
class SmallPtrSetImplBase {
friend class SmallPtrSetIteratorImpl;
protected:
const void **SmallArray;
const void **CurArray;
unsigned CurArraySize;
unsigned NumElements;
unsigned NumTombstones;
SmallPtrSetImplBase(const void **SmallStorage, const SmallPtrSetImplBase &that);
#if LLVM_HAS_RVALUE_REFERENCES
SmallPtrSetImplBase(const void **SmallStorage, unsigned SmallSize,
SmallPtrSetImplBase &&that);
#endif
explicit SmallPtrSetImplBase(const void **SmallStorage, unsigned SmallSize) :
SmallArray(SmallStorage), CurArray(SmallStorage), CurArraySize(SmallSize) {
assert(SmallSize && (SmallSize & (SmallSize-1)) == 0 &&
"Initial size must be a power of two!");
clear();
}
~SmallPtrSetImplBase();
public:
bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const { return size() == 0; }
unsigned size() const { return NumElements; }
void clear() {
if (!isSmall() && NumElements*4 < CurArraySize && CurArraySize > 32)
return shrink_and_clear();
memset(CurArray, -1, CurArraySize*sizeof(void*));
NumElements = 0;
NumTombstones = 0;
}
protected:
static void *getTombstoneMarker() { return reinterpret_cast<void*>(-2); }
static void *getEmptyMarker() {
return reinterpret_cast<void*>(-1);
}
bool insert_imp(const void * Ptr);
bool erase_imp(const void * Ptr);
bool count_imp(const void * Ptr) const {
if (isSmall()) {
for (const void *const *APtr = SmallArray,
*const *E = SmallArray+NumElements; APtr != E; ++APtr)
if (*APtr == Ptr)
return true;
return false;
}
return *FindBucketFor(Ptr) == Ptr;
}
private:
bool isSmall() const { return CurArray == SmallArray; }
const void * const *FindBucketFor(const void *Ptr) const;
void shrink_and_clear();
void Grow(unsigned NewSize);
void operator=(const SmallPtrSetImplBase &RHS) LLVM_DELETED_FUNCTION;
protected:
void swap(SmallPtrSetImplBase &RHS);
void CopyFrom(const SmallPtrSetImplBase &RHS);
#if LLVM_HAS_RVALUE_REFERENCES
void MoveFrom(unsigned SmallSize, SmallPtrSetImplBase &&RHS);
#endif
};
class SmallPtrSetIteratorImpl {
protected:
const void *const *Bucket;
const void *const *End;
public:
explicit SmallPtrSetIteratorImpl(const void *const *BP, const void*const *E)
: Bucket(BP), End(E) {
AdvanceIfNotValid();
}
bool operator==(const SmallPtrSetIteratorImpl &RHS) const {
return Bucket == RHS.Bucket;
}
bool operator!=(const SmallPtrSetIteratorImpl &RHS) const {
return Bucket != RHS.Bucket;
}
protected:
void AdvanceIfNotValid() {
assert(Bucket <= End);
while (Bucket != End &&
(*Bucket == SmallPtrSetImplBase::getEmptyMarker() ||
*Bucket == SmallPtrSetImplBase::getTombstoneMarker()))
++Bucket;
}
};
template<typename PtrTy>
class SmallPtrSetIterator : public SmallPtrSetIteratorImpl {
typedef PointerLikeTypeTraits<PtrTy> PtrTraits;
public:
typedef PtrTy value_type;
typedef PtrTy reference;
typedef PtrTy pointer;
typedef std::ptrdiff_t difference_type;
typedef std::forward_iterator_tag iterator_category;
explicit SmallPtrSetIterator(const void *const *BP, const void *const *E)
: SmallPtrSetIteratorImpl(BP, E) {}
const PtrTy operator*() const {
assert(Bucket < End);
return PtrTraits::getFromVoidPointer(const_cast<void*>(*Bucket));
}
inline SmallPtrSetIterator& operator++() { ++Bucket;
AdvanceIfNotValid();
return *this;
}
SmallPtrSetIterator operator++(int) { SmallPtrSetIterator tmp = *this; ++*this; return tmp;
}
};
template<unsigned N>
struct RoundUpToPowerOfTwo;
template<unsigned N, bool isPowerTwo>
struct RoundUpToPowerOfTwoH {
enum { Val = N };
};
template<unsigned N>
struct RoundUpToPowerOfTwoH<N, false> {
enum {
Val = RoundUpToPowerOfTwo<(N|(N-1)) + 1>::Val
};
};
template<unsigned N>
struct RoundUpToPowerOfTwo {
enum { Val = RoundUpToPowerOfTwoH<N, (N&(N-1)) == 0>::Val };
};
template <typename PtrType>
class SmallPtrSetImpl : public SmallPtrSetImplBase {
typedef PointerLikeTypeTraits<PtrType> PtrTraits;
protected:
SmallPtrSetImpl(const void **SmallStorage, const SmallPtrSetImpl &that)
: SmallPtrSetImplBase(SmallStorage, that) {}
#if LLVM_HAS_RVALUE_REFERENCES
SmallPtrSetImpl(const void **SmallStorage, unsigned SmallSize,
SmallPtrSetImpl &&that)
: SmallPtrSetImplBase(SmallStorage, SmallSize, std::move(that)) {}
#endif
explicit SmallPtrSetImpl(const void **SmallStorage, unsigned SmallSize)
: SmallPtrSetImplBase(SmallStorage, SmallSize) {}
public:
bool insert(PtrType Ptr) {
return insert_imp(PtrTraits::getAsVoidPointer(Ptr));
}
bool erase(PtrType Ptr) {
return erase_imp(PtrTraits::getAsVoidPointer(Ptr));
}
unsigned count(PtrType Ptr) const {
return count_imp(PtrTraits::getAsVoidPointer(Ptr)) ? 1 : 0;
}
template <typename IterT>
void insert(IterT I, IterT E) {
for (; I != E; ++I)
insert(*I);
}
typedef SmallPtrSetIterator<PtrType> iterator;
typedef SmallPtrSetIterator<PtrType> const_iterator;
inline iterator begin() const {
return iterator(CurArray, CurArray+CurArraySize);
}
inline iterator end() const {
return iterator(CurArray+CurArraySize, CurArray+CurArraySize);
}
};
template<class PtrType, unsigned SmallSize>
class SmallPtrSet : public SmallPtrSetImpl<PtrType> {
typedef SmallPtrSetImpl<PtrType> BaseT;
enum { SmallSizePowTwo = RoundUpToPowerOfTwo<SmallSize>::Val };
const void *SmallStorage[SmallSizePowTwo];
public:
SmallPtrSet() : BaseT(SmallStorage, SmallSizePowTwo) {}
SmallPtrSet(const SmallPtrSet &that) : BaseT(SmallStorage, that) {}
#if LLVM_HAS_RVALUE_REFERENCES
SmallPtrSet(SmallPtrSet &&that)
: BaseT(SmallStorage, SmallSizePowTwo, std::move(that)) {}
#endif
template<typename It>
SmallPtrSet(It I, It E) : BaseT(SmallStorage, SmallSizePowTwo) {
this->insert(I, E);
}
SmallPtrSet<PtrType, SmallSize> &
operator=(const SmallPtrSet<PtrType, SmallSize> &RHS) {
if (&RHS != this)
this->CopyFrom(RHS);
return *this;
}
#if LLVM_HAS_RVALUE_REFERENCES
SmallPtrSet<PtrType, SmallSize>&
operator=(SmallPtrSet<PtrType, SmallSize> &&RHS) {
if (&RHS != this)
this->MoveFrom(SmallSizePowTwo, std::move(RHS));
return *this;
}
#endif
void swap(SmallPtrSet<PtrType, SmallSize> &RHS) {
SmallPtrSetImplBase::swap(RHS);
}
};
}
namespace std {
template<class T, unsigned N>
inline void swap(llvm::SmallPtrSet<T, N> &LHS, llvm::SmallPtrSet<T, N> &RHS) {
LHS.swap(RHS);
}
}
#endif