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.

248 lines
7.5 KiB

  1. //===--- ImmutableIntervalMap.h - Immutable (functional) map ---*- 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 ImmutableIntervalMap class.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #ifndef LLVM_ADT_IMMUTABLEINTERVALMAP_H
  14. #define LLVM_ADT_IMMUTABLEINTERVALMAP_H
  15. #include "llvm/ADT/ImmutableMap.h"
  16. namespace llvm {
  17. class Interval {
  18. private:
  19. int64_t Start;
  20. int64_t End;
  21. public:
  22. Interval(int64_t S, int64_t E) : Start(S), End(E) {}
  23. int64_t getStart() const { return Start; }
  24. int64_t getEnd() const { return End; }
  25. };
  26. template <typename T>
  27. struct ImutIntervalInfo {
  28. typedef const std::pair<Interval, T> value_type;
  29. typedef const value_type &value_type_ref;
  30. typedef const Interval key_type;
  31. typedef const Interval &key_type_ref;
  32. typedef const T data_type;
  33. typedef const T &data_type_ref;
  34. static key_type_ref KeyOfValue(value_type_ref V) {
  35. return V.first;
  36. }
  37. static data_type_ref DataOfValue(value_type_ref V) {
  38. return V.second;
  39. }
  40. static bool isEqual(key_type_ref L, key_type_ref R) {
  41. return L.getStart() == R.getStart() && L.getEnd() == R.getEnd();
  42. }
  43. static bool isDataEqual(data_type_ref L, data_type_ref R) {
  44. return ImutContainerInfo<T>::isEqual(L,R);
  45. }
  46. static bool isLess(key_type_ref L, key_type_ref R) {
  47. // Assume L and R does not overlap.
  48. if (L.getStart() < R.getStart()) {
  49. assert(L.getEnd() < R.getStart());
  50. return true;
  51. } else if (L.getStart() == R.getStart()) {
  52. assert(L.getEnd() == R.getEnd());
  53. return false;
  54. } else {
  55. assert(L.getStart() > R.getEnd());
  56. return false;
  57. }
  58. }
  59. static bool isContainedIn(key_type_ref K, key_type_ref L) {
  60. if (K.getStart() >= L.getStart() && K.getEnd() <= L.getEnd())
  61. return true;
  62. else
  63. return false;
  64. }
  65. static void Profile(FoldingSetNodeID &ID, value_type_ref V) {
  66. ID.AddInteger(V.first.getStart());
  67. ID.AddInteger(V.first.getEnd());
  68. ImutProfileInfo<T>::Profile(ID, V.second);
  69. }
  70. };
  71. template <typename ImutInfo>
  72. class ImutIntervalAVLFactory : public ImutAVLFactory<ImutInfo> {
  73. typedef ImutAVLTree<ImutInfo> TreeTy;
  74. typedef typename ImutInfo::value_type value_type;
  75. typedef typename ImutInfo::value_type_ref value_type_ref;
  76. typedef typename ImutInfo::key_type key_type;
  77. typedef typename ImutInfo::key_type_ref key_type_ref;
  78. typedef typename ImutInfo::data_type data_type;
  79. typedef typename ImutInfo::data_type_ref data_type_ref;
  80. public:
  81. ImutIntervalAVLFactory(BumpPtrAllocator &Alloc)
  82. : ImutAVLFactory<ImutInfo>(Alloc) {}
  83. TreeTy *Add(TreeTy *T, value_type_ref V) {
  84. T = add_internal(V,T);
  85. this->MarkImmutable(T);
  86. return T;
  87. }
  88. TreeTy *Find(TreeTy *T, key_type_ref K) {
  89. if (!T)
  90. return NULL;
  91. key_type_ref CurrentKey = ImutInfo::KeyOfValue(this->getValue(T));
  92. if (ImutInfo::isContainedIn(K, CurrentKey))
  93. return T;
  94. else if (ImutInfo::isLess(K, CurrentKey))
  95. return Find(this->getLeft(T), K);
  96. else
  97. return Find(this->getRight(T), K);
  98. }
  99. private:
  100. TreeTy *add_internal(value_type_ref V, TreeTy *T) {
  101. key_type_ref K = ImutInfo::KeyOfValue(V);
  102. T = removeAllOverlaps(T, K);
  103. if (this->isEmpty(T))
  104. return this->CreateNode(NULL, V, NULL);
  105. assert(!T->isMutable());
  106. key_type_ref KCurrent = ImutInfo::KeyOfValue(this->Value(T));
  107. if (ImutInfo::isLess(K, KCurrent))
  108. return this->Balance(add_internal(V, this->Left(T)), this->Value(T),
  109. this->Right(T));
  110. else
  111. return this->Balance(this->Left(T), this->Value(T),
  112. add_internal(V, this->Right(T)));
  113. }
  114. // Remove all overlaps from T.
  115. TreeTy *removeAllOverlaps(TreeTy *T, key_type_ref K) {
  116. bool Changed;
  117. do {
  118. Changed = false;
  119. T = removeOverlap(T, K, Changed);
  120. this->markImmutable(T);
  121. } while (Changed);
  122. return T;
  123. }
  124. // Remove one overlap from T.
  125. TreeTy *removeOverlap(TreeTy *T, key_type_ref K, bool &Changed) {
  126. if (!T)
  127. return NULL;
  128. Interval CurrentK = ImutInfo::KeyOfValue(this->Value(T));
  129. // If current key does not overlap the inserted key.
  130. if (CurrentK.getStart() > K.getEnd())
  131. return this->Balance(removeOverlap(this->Left(T), K, Changed),
  132. this->Value(T), this->Right(T));
  133. else if (CurrentK.getEnd() < K.getStart())
  134. return this->Balance(this->Left(T), this->Value(T),
  135. removeOverlap(this->Right(T), K, Changed));
  136. // Current key overlaps with the inserted key.
  137. // Remove the current key.
  138. Changed = true;
  139. data_type_ref OldData = ImutInfo::DataOfValue(this->Value(T));
  140. T = this->Remove_internal(CurrentK, T);
  141. // Add back the unoverlapped part of the current key.
  142. if (CurrentK.getStart() < K.getStart()) {
  143. if (CurrentK.getEnd() <= K.getEnd()) {
  144. Interval NewK(CurrentK.getStart(), K.getStart()-1);
  145. return add_internal(std::make_pair(NewK, OldData), T);
  146. } else {
  147. Interval NewK1(CurrentK.getStart(), K.getStart()-1);
  148. T = add_internal(std::make_pair(NewK1, OldData), T);
  149. Interval NewK2(K.getEnd()+1, CurrentK.getEnd());
  150. return add_internal(std::make_pair(NewK2, OldData), T);
  151. }
  152. } else {
  153. if (CurrentK.getEnd() > K.getEnd()) {
  154. Interval NewK(K.getEnd()+1, CurrentK.getEnd());
  155. return add_internal(std::make_pair(NewK, OldData), T);
  156. } else
  157. return T;
  158. }
  159. }
  160. };
  161. /// ImmutableIntervalMap maps an interval [start, end] to a value. The intervals
  162. /// in the map are guaranteed to be disjoint.
  163. template <typename ValT>
  164. class ImmutableIntervalMap
  165. : public ImmutableMap<Interval, ValT, ImutIntervalInfo<ValT> > {
  166. typedef typename ImutIntervalInfo<ValT>::value_type value_type;
  167. typedef typename ImutIntervalInfo<ValT>::value_type_ref value_type_ref;
  168. typedef typename ImutIntervalInfo<ValT>::key_type key_type;
  169. typedef typename ImutIntervalInfo<ValT>::key_type_ref key_type_ref;
  170. typedef typename ImutIntervalInfo<ValT>::data_type data_type;
  171. typedef typename ImutIntervalInfo<ValT>::data_type_ref data_type_ref;
  172. typedef ImutAVLTree<ImutIntervalInfo<ValT> > TreeTy;
  173. public:
  174. explicit ImmutableIntervalMap(TreeTy *R)
  175. : ImmutableMap<Interval, ValT, ImutIntervalInfo<ValT> >(R) {}
  176. class Factory {
  177. ImutIntervalAVLFactory<ImutIntervalInfo<ValT> > F;
  178. public:
  179. Factory(BumpPtrAllocator& Alloc) : F(Alloc) {}
  180. ImmutableIntervalMap getEmptyMap() {
  181. return ImmutableIntervalMap(F.getEmptyTree());
  182. }
  183. ImmutableIntervalMap add(ImmutableIntervalMap Old,
  184. key_type_ref K, data_type_ref D) {
  185. TreeTy *T = F.add(Old.Root, std::pair<key_type, data_type>(K, D));
  186. return ImmutableIntervalMap(F.getCanonicalTree(T));
  187. }
  188. ImmutableIntervalMap remove(ImmutableIntervalMap Old, key_type_ref K) {
  189. TreeTy *T = F.remove(Old.Root, K);
  190. return ImmutableIntervalMap(F.getCanonicalTree(T));
  191. }
  192. data_type *lookup(ImmutableIntervalMap M, key_type_ref K) {
  193. TreeTy *T = F.Find(M.getRoot(), K);
  194. if (T)
  195. return &T->getValue().second;
  196. else
  197. return 0;
  198. }
  199. };
  200. private:
  201. // For ImmutableIntervalMap, the lookup operation has to be done by the
  202. // factory.
  203. data_type* lookup(key_type_ref K) const;
  204. };
  205. } // end namespace llvm
  206. #endif