00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #ifndef LLVM_ADT_SMALLPTRSET_H
00016 #define LLVM_ADT_SMALLPTRSET_H
00017
00018 #include <cassert>
00019 #include <cstddef>
00020 #include <cstring>
00021 #include <iterator>
00022 #include "llvm/Support/DataTypes.h"
00023 #include "llvm/Support/PointerLikeTypeTraits.h"
00024
00025 namespace llvm {
00026
00027 class SmallPtrSetIteratorImpl;
00028
00047 class SmallPtrSetImpl {
00048 friend class SmallPtrSetIteratorImpl;
00049 protected:
00051 const void **SmallArray;
00054 const void **CurArray;
00058 unsigned CurArraySize;
00059
00060
00061 unsigned NumElements;
00062 unsigned NumTombstones;
00063
00064
00065 SmallPtrSetImpl(const void **SmallStorage, const SmallPtrSetImpl& that);
00066 explicit SmallPtrSetImpl(const void **SmallStorage, unsigned SmallSize) :
00067 SmallArray(SmallStorage), CurArray(SmallStorage), CurArraySize(SmallSize) {
00068 assert(SmallSize && (SmallSize & (SmallSize-1)) == 0 &&
00069 "Initial size must be a power of two!");
00070
00071
00072 CurArray[SmallSize] = 0;
00073 clear();
00074 }
00075 ~SmallPtrSetImpl();
00076
00077 public:
00078 bool empty() const { return size() == 0; }
00079 unsigned size() const { return NumElements; }
00080
00081 void clear() {
00082
00083
00084 if (!isSmall() && NumElements*4 < CurArraySize && CurArraySize > 32)
00085 return shrink_and_clear();
00086
00087
00088 memset(CurArray, -1, CurArraySize*sizeof(void*));
00089 NumElements = 0;
00090 NumTombstones = 0;
00091 }
00092
00093 protected:
00094 static void *getTombstoneMarker() { return reinterpret_cast<void*>(-2); }
00095 static void *getEmptyMarker() {
00096
00097
00098 return reinterpret_cast<void*>(-1);
00099 }
00100
00104 bool insert_imp(const void * Ptr);
00105
00110 bool erase_imp(const void * Ptr);
00111
00112 bool count_imp(const void * Ptr) const {
00113 if (isSmall()) {
00114
00115 for (const void *const *APtr = SmallArray,
00116 *const *E = SmallArray+NumElements; APtr != E; ++APtr)
00117 if (*APtr == Ptr)
00118 return true;
00119 return false;
00120 }
00121
00122
00123 return *FindBucketFor(Ptr) == Ptr;
00124 }
00125
00126 private:
00127 bool isSmall() const { return CurArray == SmallArray; }
00128
00129 unsigned Hash(const void *Ptr) const {
00130 return static_cast<unsigned>(((uintptr_t)Ptr >> 4) & (CurArraySize-1));
00131 }
00132 const void * const *FindBucketFor(const void *Ptr) const;
00133 void shrink_and_clear();
00134
00136 void Grow(unsigned NewSize);
00137
00138 void operator=(const SmallPtrSetImpl &RHS);
00139 protected:
00140 void CopyFrom(const SmallPtrSetImpl &RHS);
00141 };
00142
00145 class SmallPtrSetIteratorImpl {
00146 protected:
00147 const void *const *Bucket;
00148 public:
00149 explicit SmallPtrSetIteratorImpl(const void *const *BP) : Bucket(BP) {
00150 AdvanceIfNotValid();
00151 }
00152
00153 bool operator==(const SmallPtrSetIteratorImpl &RHS) const {
00154 return Bucket == RHS.Bucket;
00155 }
00156 bool operator!=(const SmallPtrSetIteratorImpl &RHS) const {
00157 return Bucket != RHS.Bucket;
00158 }
00159
00160 protected:
00164 void AdvanceIfNotValid() {
00165 while (*Bucket == SmallPtrSetImpl::getEmptyMarker() ||
00166 *Bucket == SmallPtrSetImpl::getTombstoneMarker())
00167 ++Bucket;
00168 }
00169 };
00170
00172 template<typename PtrTy>
00173 class SmallPtrSetIterator : public SmallPtrSetIteratorImpl {
00174 typedef PointerLikeTypeTraits<PtrTy> PtrTraits;
00175
00176 public:
00177 typedef PtrTy value_type;
00178 typedef PtrTy reference;
00179 typedef PtrTy pointer;
00180 typedef std::ptrdiff_t difference_type;
00181 typedef std::forward_iterator_tag iterator_category;
00182
00183 explicit SmallPtrSetIterator(const void *const *BP)
00184 : SmallPtrSetIteratorImpl(BP) {}
00185
00186
00187
00188 const PtrTy operator*() const {
00189 return PtrTraits::getFromVoidPointer(const_cast<void*>(*Bucket));
00190 }
00191
00192 inline SmallPtrSetIterator& operator++() {
00193 ++Bucket;
00194 AdvanceIfNotValid();
00195 return *this;
00196 }
00197
00198 SmallPtrSetIterator operator++(int) {
00199 SmallPtrSetIterator tmp = *this; ++*this; return tmp;
00200 }
00201 };
00202
00205 template<unsigned N>
00206 struct RoundUpToPowerOfTwo;
00207
00210 template<unsigned N, bool isPowerTwo>
00211 struct RoundUpToPowerOfTwoH {
00212 enum { Val = N };
00213 };
00214 template<unsigned N>
00215 struct RoundUpToPowerOfTwoH<N, false> {
00216 enum {
00217
00218
00219 Val = RoundUpToPowerOfTwo<(N|(N-1)) + 1>::Val
00220 };
00221 };
00222
00223 template<unsigned N>
00224 struct RoundUpToPowerOfTwo {
00225 enum { Val = RoundUpToPowerOfTwoH<N, (N&(N-1)) == 0>::Val };
00226 };
00227
00228
00233 template<class PtrType, unsigned SmallSize>
00234 class SmallPtrSet : public SmallPtrSetImpl {
00235
00236 enum { SmallSizePowTwo = RoundUpToPowerOfTwo<SmallSize>::Val };
00239 const void *SmallStorage[SmallSizePowTwo+1];
00240 typedef PointerLikeTypeTraits<PtrType> PtrTraits;
00241 public:
00242 SmallPtrSet() : SmallPtrSetImpl(SmallStorage, SmallSizePowTwo) {}
00243 SmallPtrSet(const SmallPtrSet &that) : SmallPtrSetImpl(SmallStorage, that) {}
00244
00245 template<typename It>
00246 SmallPtrSet(It I, It E) : SmallPtrSetImpl(SmallStorage, SmallSizePowTwo) {
00247 insert(I, E);
00248 }
00249
00252 bool insert(PtrType Ptr) {
00253 return insert_imp(PtrTraits::getAsVoidPointer(Ptr));
00254 }
00255
00258 bool erase(PtrType Ptr) {
00259 return erase_imp(PtrTraits::getAsVoidPointer(Ptr));
00260 }
00261
00263 bool count(PtrType Ptr) const {
00264 return count_imp(PtrTraits::getAsVoidPointer(Ptr));
00265 }
00266
00267 template <typename IterT>
00268 void insert(IterT I, IterT E) {
00269 for (; I != E; ++I)
00270 insert(*I);
00271 }
00272
00273 typedef SmallPtrSetIterator<PtrType> iterator;
00274 typedef SmallPtrSetIterator<PtrType> const_iterator;
00275 inline iterator begin() const {
00276 return iterator(CurArray);
00277 }
00278 inline iterator end() const {
00279 return iterator(CurArray+CurArraySize);
00280 }
00281
00282
00283
00284 const SmallPtrSet<PtrType, SmallSize>&
00285 operator=(const SmallPtrSet<PtrType, SmallSize> &RHS) {
00286 CopyFrom(RHS);
00287 return *this;
00288 }
00289
00290 };
00291
00292 }
00293
00294 #endif