#ifndef LLVM_ADT_SMALLPTRSET_H
#define LLVM_ADT_SMALLPTRSET_H
#include <cassert>
#include <cstring>
#include <iterator>
#include "llvm/System/DataTypes.h"
#include "llvm/Support/PointerLikeTypeTraits.h"
namespace llvm {
class SmallPtrSetIteratorImpl;
class SmallPtrSetImpl {
friend class SmallPtrSetIteratorImpl;
protected:
const void **CurArray;
unsigned CurArraySize;
unsigned NumElements;
unsigned NumTombstones;
const void *SmallArray[1];
SmallPtrSetImpl(const SmallPtrSetImpl& that);
explicit SmallPtrSetImpl(unsigned SmallSize) {
assert(SmallSize && (SmallSize & (SmallSize-1)) == 0 &&
"Initial size must be a power of two!");
CurArray = &SmallArray[0];
CurArraySize = SmallSize;
CurArray[SmallSize] = 0;
clear();
}
~SmallPtrSetImpl();
public:
bool 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[0]; }
unsigned Hash(const void *Ptr) const {
return static_cast<unsigned>(((uintptr_t)Ptr >> 4) & (CurArraySize-1));
}
const void * const *FindBucketFor(const void *Ptr) const;
void shrink_and_clear();
void Grow();
void operator=(const SmallPtrSetImpl &RHS); protected:
void CopyFrom(const SmallPtrSetImpl &RHS);
};
class SmallPtrSetIteratorImpl {
protected:
const void *const *Bucket;
public:
explicit SmallPtrSetIteratorImpl(const void *const *BP) : Bucket(BP) {
AdvanceIfNotValid();
}
bool operator==(const SmallPtrSetIteratorImpl &RHS) const {
return Bucket == RHS.Bucket;
}
bool operator!=(const SmallPtrSetIteratorImpl &RHS) const {
return Bucket != RHS.Bucket;
}
protected:
void AdvanceIfNotValid() {
while (*Bucket == SmallPtrSetImpl::getEmptyMarker() ||
*Bucket == SmallPtrSetImpl::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)
: SmallPtrSetIteratorImpl(BP) {}
const PtrTy operator*() const {
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 NextPowerOfTwo;
template<unsigned N, bool isPowerTwo>
struct NextPowerOfTwoH {
enum { Val = N };
};
template<unsigned N>
struct NextPowerOfTwoH<N, false> {
enum {
Val = NextPowerOfTwo<(N|(N-1)) + 1>::Val
};
};
template<unsigned N>
struct NextPowerOfTwo {
enum { Val = NextPowerOfTwoH<N, (N&(N-1)) == 0>::Val };
};
template<class PtrType, unsigned SmallSize>
class SmallPtrSet : public SmallPtrSetImpl {
enum { SmallSizePowTwo = NextPowerOfTwo<SmallSize>::Val };
void *SmallArray[SmallSizePowTwo];
typedef PointerLikeTypeTraits<PtrType> PtrTraits;
public:
SmallPtrSet() : SmallPtrSetImpl(NextPowerOfTwo<SmallSizePowTwo>::Val) {}
SmallPtrSet(const SmallPtrSet &that) : SmallPtrSetImpl(that) {}
template<typename It>
SmallPtrSet(It I, It E)
: SmallPtrSetImpl(NextPowerOfTwo<SmallSizePowTwo>::Val) {
insert(I, E);
}
bool insert(PtrType Ptr) {
return insert_imp(PtrTraits::getAsVoidPointer(Ptr));
}
bool erase(PtrType Ptr) {
return erase_imp(PtrTraits::getAsVoidPointer(Ptr));
}
bool count(PtrType Ptr) const {
return count_imp(PtrTraits::getAsVoidPointer(Ptr));
}
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);
}
inline iterator end() const {
return iterator(CurArray+CurArraySize);
}
const SmallPtrSet<PtrType, SmallSize>&
operator=(const SmallPtrSet<PtrType, SmallSize> &RHS) {
CopyFrom(RHS);
return *this;
}
};
}
#endif