Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

465 lines
15 KiB

  1. //===--- StringMap.h - String Hash table map interface ----------*- C++ -*-===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // This file defines the StringMap class.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #ifndef LLVM_ADT_STRINGMAP_H
  14. #define LLVM_ADT_STRINGMAP_H
  15. #include "llvm/ADT/StringRef.h"
  16. #include "llvm/Support/Allocator.h"
  17. #include <cstring>
  18. namespace llvm {
  19. template<typename ValueT>
  20. class StringMapConstIterator;
  21. template<typename ValueT>
  22. class StringMapIterator;
  23. template<typename ValueTy>
  24. class StringMapEntry;
  25. /// StringMapEntryInitializer - This datatype can be partially specialized for
  26. /// various datatypes in a stringmap to allow them to be initialized when an
  27. /// entry is default constructed for the map.
  28. template<typename ValueTy>
  29. class StringMapEntryInitializer {
  30. public:
  31. template <typename InitTy>
  32. static void Initialize(StringMapEntry<ValueTy> &T, InitTy InitVal) {
  33. T.second = InitVal;
  34. }
  35. };
  36. /// StringMapEntryBase - Shared base class of StringMapEntry instances.
  37. class StringMapEntryBase {
  38. unsigned StrLen;
  39. public:
  40. explicit StringMapEntryBase(unsigned Len) : StrLen(Len) {}
  41. unsigned getKeyLength() const { return StrLen; }
  42. };
  43. /// StringMapImpl - This is the base class of StringMap that is shared among
  44. /// all of its instantiations.
  45. class StringMapImpl {
  46. protected:
  47. // Array of NumBuckets pointers to entries, null pointers are holes.
  48. // TheTable[NumBuckets] contains a sentinel value for easy iteration. Followed
  49. // by an array of the actual hash values as unsigned integers.
  50. StringMapEntryBase **TheTable;
  51. unsigned NumBuckets;
  52. unsigned NumItems;
  53. unsigned NumTombstones;
  54. unsigned ItemSize;
  55. protected:
  56. explicit StringMapImpl(unsigned itemSize) : ItemSize(itemSize) {
  57. // Initialize the map with zero buckets to allocation.
  58. TheTable = 0;
  59. NumBuckets = 0;
  60. NumItems = 0;
  61. NumTombstones = 0;
  62. }
  63. StringMapImpl(unsigned InitSize, unsigned ItemSize);
  64. void RehashTable();
  65. /// LookupBucketFor - Look up the bucket that the specified string should end
  66. /// up in. If it already exists as a key in the map, the Item pointer for the
  67. /// specified bucket will be non-null. Otherwise, it will be null. In either
  68. /// case, the FullHashValue field of the bucket will be set to the hash value
  69. /// of the string.
  70. unsigned LookupBucketFor(StringRef Key);
  71. /// FindKey - Look up the bucket that contains the specified key. If it exists
  72. /// in the map, return the bucket number of the key. Otherwise return -1.
  73. /// This does not modify the map.
  74. int FindKey(StringRef Key) const;
  75. /// RemoveKey - Remove the specified StringMapEntry from the table, but do not
  76. /// delete it. This aborts if the value isn't in the table.
  77. void RemoveKey(StringMapEntryBase *V);
  78. /// RemoveKey - Remove the StringMapEntry for the specified key from the
  79. /// table, returning it. If the key is not in the table, this returns null.
  80. StringMapEntryBase *RemoveKey(StringRef Key);
  81. private:
  82. void init(unsigned Size);
  83. public:
  84. static StringMapEntryBase *getTombstoneVal() {
  85. return (StringMapEntryBase*)-1;
  86. }
  87. unsigned getNumBuckets() const { return NumBuckets; }
  88. unsigned getNumItems() const { return NumItems; }
  89. bool empty() const { return NumItems == 0; }
  90. unsigned size() const { return NumItems; }
  91. };
  92. /// StringMapEntry - This is used to represent one value that is inserted into
  93. /// a StringMap. It contains the Value itself and the key: the string length
  94. /// and data.
  95. template<typename ValueTy>
  96. class StringMapEntry : public StringMapEntryBase {
  97. public:
  98. ValueTy second;
  99. explicit StringMapEntry(unsigned strLen)
  100. : StringMapEntryBase(strLen), second() {}
  101. StringMapEntry(unsigned strLen, const ValueTy &V)
  102. : StringMapEntryBase(strLen), second(V) {}
  103. StringRef getKey() const {
  104. return StringRef(getKeyData(), getKeyLength());
  105. }
  106. const ValueTy &getValue() const { return second; }
  107. ValueTy &getValue() { return second; }
  108. void setValue(const ValueTy &V) { second = V; }
  109. /// getKeyData - Return the start of the string data that is the key for this
  110. /// value. The string data is always stored immediately after the
  111. /// StringMapEntry object.
  112. const char *getKeyData() const {return reinterpret_cast<const char*>(this+1);}
  113. StringRef first() const { return StringRef(getKeyData(), getKeyLength()); }
  114. /// Create - Create a StringMapEntry for the specified key and default
  115. /// construct the value.
  116. template<typename AllocatorTy, typename InitType>
  117. static StringMapEntry *Create(const char *KeyStart, const char *KeyEnd,
  118. AllocatorTy &Allocator,
  119. InitType InitVal) {
  120. unsigned KeyLength = static_cast<unsigned>(KeyEnd-KeyStart);
  121. // Okay, the item doesn't already exist, and 'Bucket' is the bucket to fill
  122. // in. Allocate a new item with space for the string at the end and a null
  123. // terminator.
  124. unsigned AllocSize = static_cast<unsigned>(sizeof(StringMapEntry))+
  125. KeyLength+1;
  126. unsigned Alignment = alignOf<StringMapEntry>();
  127. StringMapEntry *NewItem =
  128. static_cast<StringMapEntry*>(Allocator.Allocate(AllocSize,Alignment));
  129. // Default construct the value.
  130. new (NewItem) StringMapEntry(KeyLength);
  131. // Copy the string information.
  132. char *StrBuffer = const_cast<char*>(NewItem->getKeyData());
  133. memcpy(StrBuffer, KeyStart, KeyLength);
  134. StrBuffer[KeyLength] = 0; // Null terminate for convenience of clients.
  135. // Initialize the value if the client wants to.
  136. StringMapEntryInitializer<ValueTy>::Initialize(*NewItem, InitVal);
  137. return NewItem;
  138. }
  139. template<typename AllocatorTy>
  140. static StringMapEntry *Create(const char *KeyStart, const char *KeyEnd,
  141. AllocatorTy &Allocator) {
  142. return Create(KeyStart, KeyEnd, Allocator, 0);
  143. }
  144. /// Create - Create a StringMapEntry with normal malloc/free.
  145. template<typename InitType>
  146. static StringMapEntry *Create(const char *KeyStart, const char *KeyEnd,
  147. InitType InitVal) {
  148. MallocAllocator A;
  149. return Create(KeyStart, KeyEnd, A, InitVal);
  150. }
  151. static StringMapEntry *Create(const char *KeyStart, const char *KeyEnd) {
  152. return Create(KeyStart, KeyEnd, ValueTy());
  153. }
  154. /// GetStringMapEntryFromValue - Given a value that is known to be embedded
  155. /// into a StringMapEntry, return the StringMapEntry itself.
  156. static StringMapEntry &GetStringMapEntryFromValue(ValueTy &V) {
  157. StringMapEntry *EPtr = 0;
  158. char *Ptr = reinterpret_cast<char*>(&V) -
  159. (reinterpret_cast<char*>(&EPtr->second) -
  160. reinterpret_cast<char*>(EPtr));
  161. return *reinterpret_cast<StringMapEntry*>(Ptr);
  162. }
  163. static const StringMapEntry &GetStringMapEntryFromValue(const ValueTy &V) {
  164. return GetStringMapEntryFromValue(const_cast<ValueTy&>(V));
  165. }
  166. /// GetStringMapEntryFromKeyData - Given key data that is known to be embedded
  167. /// into a StringMapEntry, return the StringMapEntry itself.
  168. static StringMapEntry &GetStringMapEntryFromKeyData(const char *KeyData) {
  169. char *Ptr = const_cast<char*>(KeyData) - sizeof(StringMapEntry<ValueTy>);
  170. return *reinterpret_cast<StringMapEntry*>(Ptr);
  171. }
  172. /// Destroy - Destroy this StringMapEntry, releasing memory back to the
  173. /// specified allocator.
  174. template<typename AllocatorTy>
  175. void Destroy(AllocatorTy &Allocator) {
  176. // Free memory referenced by the item.
  177. this->~StringMapEntry();
  178. Allocator.Deallocate(this);
  179. }
  180. /// Destroy this object, releasing memory back to the malloc allocator.
  181. void Destroy() {
  182. MallocAllocator A;
  183. Destroy(A);
  184. }
  185. };
  186. /// StringMap - This is an unconventional map that is specialized for handling
  187. /// keys that are "strings", which are basically ranges of bytes. This does some
  188. /// funky memory allocation and hashing things to make it extremely efficient,
  189. /// storing the string data *after* the value in the map.
  190. template<typename ValueTy, typename AllocatorTy = MallocAllocator>
  191. class StringMap : public StringMapImpl {
  192. AllocatorTy Allocator;
  193. public:
  194. typedef StringMapEntry<ValueTy> MapEntryTy;
  195. StringMap() : StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))) {}
  196. explicit StringMap(unsigned InitialSize)
  197. : StringMapImpl(InitialSize, static_cast<unsigned>(sizeof(MapEntryTy))) {}
  198. explicit StringMap(AllocatorTy A)
  199. : StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))), Allocator(A) {}
  200. StringMap(unsigned InitialSize, AllocatorTy A)
  201. : StringMapImpl(InitialSize, static_cast<unsigned>(sizeof(MapEntryTy))),
  202. Allocator(A) {}
  203. StringMap(const StringMap &RHS)
  204. : StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))) {
  205. assert(RHS.empty() &&
  206. "Copy ctor from non-empty stringmap not implemented yet!");
  207. (void)RHS;
  208. }
  209. void operator=(const StringMap &RHS) {
  210. assert(RHS.empty() &&
  211. "assignment from non-empty stringmap not implemented yet!");
  212. (void)RHS;
  213. clear();
  214. }
  215. typedef typename ReferenceAdder<AllocatorTy>::result AllocatorRefTy;
  216. typedef typename ReferenceAdder<const AllocatorTy>::result AllocatorCRefTy;
  217. AllocatorRefTy getAllocator() { return Allocator; }
  218. AllocatorCRefTy getAllocator() const { return Allocator; }
  219. typedef const char* key_type;
  220. typedef ValueTy mapped_type;
  221. typedef StringMapEntry<ValueTy> value_type;
  222. typedef size_t size_type;
  223. typedef StringMapConstIterator<ValueTy> const_iterator;
  224. typedef StringMapIterator<ValueTy> iterator;
  225. iterator begin() {
  226. return iterator(TheTable, NumBuckets == 0);
  227. }
  228. iterator end() {
  229. return iterator(TheTable+NumBuckets, true);
  230. }
  231. const_iterator begin() const {
  232. return const_iterator(TheTable, NumBuckets == 0);
  233. }
  234. const_iterator end() const {
  235. return const_iterator(TheTable+NumBuckets, true);
  236. }
  237. iterator find(StringRef Key) {
  238. int Bucket = FindKey(Key);
  239. if (Bucket == -1) return end();
  240. return iterator(TheTable+Bucket, true);
  241. }
  242. const_iterator find(StringRef Key) const {
  243. int Bucket = FindKey(Key);
  244. if (Bucket == -1) return end();
  245. return const_iterator(TheTable+Bucket, true);
  246. }
  247. /// lookup - Return the entry for the specified key, or a default
  248. /// constructed value if no such entry exists.
  249. ValueTy lookup(StringRef Key) const {
  250. const_iterator it = find(Key);
  251. if (it != end())
  252. return it->second;
  253. return ValueTy();
  254. }
  255. ValueTy &operator[](StringRef Key) {
  256. return GetOrCreateValue(Key).getValue();
  257. }
  258. size_type count(StringRef Key) const {
  259. return find(Key) == end() ? 0 : 1;
  260. }
  261. /// insert - Insert the specified key/value pair into the map. If the key
  262. /// already exists in the map, return false and ignore the request, otherwise
  263. /// insert it and return true.
  264. bool insert(MapEntryTy *KeyValue) {
  265. unsigned BucketNo = LookupBucketFor(KeyValue->getKey());
  266. StringMapEntryBase *&Bucket = TheTable[BucketNo];
  267. if (Bucket && Bucket != getTombstoneVal())
  268. return false; // Already exists in map.
  269. if (Bucket == getTombstoneVal())
  270. --NumTombstones;
  271. Bucket = KeyValue;
  272. ++NumItems;
  273. assert(NumItems + NumTombstones <= NumBuckets);
  274. RehashTable();
  275. return true;
  276. }
  277. // clear - Empties out the StringMap
  278. void clear() {
  279. if (empty()) return;
  280. // Zap all values, resetting the keys back to non-present (not tombstone),
  281. // which is safe because we're removing all elements.
  282. for (unsigned I = 0, E = NumBuckets; I != E; ++I) {
  283. StringMapEntryBase *&Bucket = TheTable[I];
  284. if (Bucket && Bucket != getTombstoneVal()) {
  285. static_cast<MapEntryTy*>(Bucket)->Destroy(Allocator);
  286. }
  287. Bucket = 0;
  288. }
  289. NumItems = 0;
  290. NumTombstones = 0;
  291. }
  292. /// GetOrCreateValue - Look up the specified key in the table. If a value
  293. /// exists, return it. Otherwise, default construct a value, insert it, and
  294. /// return.
  295. template <typename InitTy>
  296. MapEntryTy &GetOrCreateValue(StringRef Key, InitTy Val) {
  297. unsigned BucketNo = LookupBucketFor(Key);
  298. StringMapEntryBase *&Bucket = TheTable[BucketNo];
  299. if (Bucket && Bucket != getTombstoneVal())
  300. return *static_cast<MapEntryTy*>(Bucket);
  301. MapEntryTy *NewItem =
  302. MapEntryTy::Create(Key.begin(), Key.end(), Allocator, Val);
  303. if (Bucket == getTombstoneVal())
  304. --NumTombstones;
  305. ++NumItems;
  306. assert(NumItems + NumTombstones <= NumBuckets);
  307. // Fill in the bucket for the hash table. The FullHashValue was already
  308. // filled in by LookupBucketFor.
  309. Bucket = NewItem;
  310. RehashTable();
  311. return *NewItem;
  312. }
  313. MapEntryTy &GetOrCreateValue(StringRef Key) {
  314. return GetOrCreateValue(Key, ValueTy());
  315. }
  316. /// remove - Remove the specified key/value pair from the map, but do not
  317. /// erase it. This aborts if the key is not in the map.
  318. void remove(MapEntryTy *KeyValue) {
  319. RemoveKey(KeyValue);
  320. }
  321. void erase(iterator I) {
  322. MapEntryTy &V = *I;
  323. remove(&V);
  324. V.Destroy(Allocator);
  325. }
  326. bool erase(StringRef Key) {
  327. iterator I = find(Key);
  328. if (I == end()) return false;
  329. erase(I);
  330. return true;
  331. }
  332. ~StringMap() {
  333. clear();
  334. free(TheTable);
  335. }
  336. };
  337. template<typename ValueTy>
  338. class StringMapConstIterator {
  339. protected:
  340. StringMapEntryBase **Ptr;
  341. public:
  342. typedef StringMapEntry<ValueTy> value_type;
  343. explicit StringMapConstIterator(StringMapEntryBase **Bucket,
  344. bool NoAdvance = false)
  345. : Ptr(Bucket) {
  346. if (!NoAdvance) AdvancePastEmptyBuckets();
  347. }
  348. const value_type &operator*() const {
  349. return *static_cast<StringMapEntry<ValueTy>*>(*Ptr);
  350. }
  351. const value_type *operator->() const {
  352. return static_cast<StringMapEntry<ValueTy>*>(*Ptr);
  353. }
  354. bool operator==(const StringMapConstIterator &RHS) const {
  355. return Ptr == RHS.Ptr;
  356. }
  357. bool operator!=(const StringMapConstIterator &RHS) const {
  358. return Ptr != RHS.Ptr;
  359. }
  360. inline StringMapConstIterator& operator++() { // Preincrement
  361. ++Ptr;
  362. AdvancePastEmptyBuckets();
  363. return *this;
  364. }
  365. StringMapConstIterator operator++(int) { // Postincrement
  366. StringMapConstIterator tmp = *this; ++*this; return tmp;
  367. }
  368. private:
  369. void AdvancePastEmptyBuckets() {
  370. while (*Ptr == 0 || *Ptr == StringMapImpl::getTombstoneVal())
  371. ++Ptr;
  372. }
  373. };
  374. template<typename ValueTy>
  375. class StringMapIterator : public StringMapConstIterator<ValueTy> {
  376. public:
  377. explicit StringMapIterator(StringMapEntryBase **Bucket,
  378. bool NoAdvance = false)
  379. : StringMapConstIterator<ValueTy>(Bucket, NoAdvance) {
  380. }
  381. StringMapEntry<ValueTy> &operator*() const {
  382. return *static_cast<StringMapEntry<ValueTy>*>(*this->Ptr);
  383. }
  384. StringMapEntry<ValueTy> *operator->() const {
  385. return static_cast<StringMapEntry<ValueTy>*>(*this->Ptr);
  386. }
  387. };
  388. }
  389. #endif