Collections.h 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. #pragma once
  2. #include <algorithm>
  3. #include <vector>
  4. #include <functional>
  5. #include "NonCopyable.h"
  6. namespace il2cpp
  7. {
  8. namespace utils
  9. {
  10. namespace collections
  11. {
  12. // Memory compact, map-like data structure that stores values and
  13. // is a able to compute the key from the value with the provided converter
  14. // This data structure is perfect to storing values that will not be changed
  15. // for the duration of program (like type metadata) and need fast querying
  16. //
  17. // It is able to store multiple values associated with a single key, and query them through find()
  18. // find_first() is a special case find() which improves performance for cases where we don't store multiple values for each key
  19. template<typename TKey, typename TValue, typename TValueToKeyConverter, typename TKeyLess = std::less<TKey>, typename TKeyEquals = std::equal_to<TKey> >
  20. class ArrayValueMap : NonCopyable
  21. {
  22. public:
  23. typedef ArrayValueMap<TKey, TValue, TValueToKeyConverter, TKeyLess, TKeyEquals> map_type;
  24. typedef const TValue* iterator;
  25. private:
  26. const TValue* m_Values;
  27. const size_t m_ValueCount;
  28. bool m_OwnStorage;
  29. const TValueToKeyConverter m_ValueToKeyConverter;
  30. const TKeyLess m_KeyLessComparer;
  31. const TKeyEquals m_KeyEqualsComparer;
  32. struct SortComparer
  33. {
  34. private:
  35. const TValueToKeyConverter m_ValueToKeyConverter;
  36. const TKeyLess m_KeyComparer;
  37. public:
  38. SortComparer(TValueToKeyConverter valueToKeyConverter, TKeyLess keyComparer) :
  39. m_ValueToKeyConverter(valueToKeyConverter), m_KeyComparer(keyComparer)
  40. {
  41. }
  42. inline bool operator()(const TValue& left, const TValue& right) const
  43. {
  44. return m_KeyComparer(m_ValueToKeyConverter(left), m_ValueToKeyConverter(right));
  45. }
  46. };
  47. struct LowerBoundFindComparer
  48. {
  49. private:
  50. const TValueToKeyConverter m_ValueToKeyConverter;
  51. const TKeyLess m_KeyComparer;
  52. public:
  53. LowerBoundFindComparer(TValueToKeyConverter valueToKeyConverter, TKeyLess keyComparer) :
  54. m_ValueToKeyConverter(valueToKeyConverter), m_KeyComparer(keyComparer)
  55. {
  56. }
  57. inline bool operator()(const TValue& left, const TKey& right) const
  58. {
  59. return m_KeyComparer(m_ValueToKeyConverter(left), right);
  60. }
  61. };
  62. struct UpperBoundFindComparer
  63. {
  64. private:
  65. const TValueToKeyConverter m_ValueToKeyConverter;
  66. const TKeyLess m_KeyComparer;
  67. public:
  68. UpperBoundFindComparer(TValueToKeyConverter valueToKeyConverter, TKeyLess keyComparer) :
  69. m_ValueToKeyConverter(valueToKeyConverter), m_KeyComparer(keyComparer)
  70. {
  71. }
  72. inline bool operator()(const TKey& left, const TValue& right) const
  73. {
  74. return m_KeyComparer(left, m_ValueToKeyConverter(right));
  75. }
  76. };
  77. inline static TValue* InitializeInPlace(TValue* values, size_t valueCount, TValueToKeyConverter valueToKeyConverter, TKeyLess keyLessComparer)
  78. {
  79. std::sort(values, values + valueCount, SortComparer(valueToKeyConverter, keyLessComparer));
  80. return values;
  81. }
  82. inline static TValue* AllocateAndInitialize(const TValue* originalValues, size_t valueCount, TValueToKeyConverter valueToKeyConverter, TKeyLess keyLessComparer)
  83. {
  84. TValue* values = new TValue[valueCount];
  85. memcpy(values, originalValues, valueCount * sizeof(TValue));
  86. return InitializeInPlace(values, valueCount, valueToKeyConverter, keyLessComparer);
  87. }
  88. public:
  89. inline ArrayValueMap() :
  90. m_Values(NULL),
  91. m_ValueCount(0),
  92. m_OwnStorage(false),
  93. m_ValueToKeyConverter(TValueToKeyConverter()),
  94. m_KeyLessComparer(TKeyLess()),
  95. m_KeyEqualsComparer(TKeyEquals())
  96. {
  97. }
  98. // Non-allocating constructor. It will take a pointer and will not allocate any storage
  99. // It WILL sort existing values
  100. inline ArrayValueMap(TValue* values, size_t valueCount, TValueToKeyConverter valueToKeyConverter = TValueToKeyConverter(),
  101. TKeyLess keyLessComparer = TKeyLess(), TKeyEquals keyEqualsComparer = TKeyEquals()) :
  102. m_Values(InitializeInPlace(values, valueCount, valueToKeyConverter, keyLessComparer)),
  103. m_ValueCount(valueCount),
  104. m_ValueToKeyConverter(valueToKeyConverter),
  105. m_KeyLessComparer(keyLessComparer),
  106. m_KeyEqualsComparer(keyEqualsComparer),
  107. m_OwnStorage(false)
  108. {
  109. }
  110. // Allocating constructor
  111. // Will copy values to newly allocated storage
  112. inline ArrayValueMap(const std::vector<TValue>& values, TValueToKeyConverter valueToKeyConverter = TValueToKeyConverter(),
  113. TKeyLess keyLessComparer = TKeyLess(), TKeyEquals keyEqualsComparer = TKeyEquals()) :
  114. m_Values(AllocateAndInitialize(values.data(), values.size(), valueToKeyConverter, keyLessComparer)),
  115. m_ValueCount(values.size()),
  116. m_ValueToKeyConverter(valueToKeyConverter),
  117. m_KeyLessComparer(keyLessComparer),
  118. m_KeyEqualsComparer(keyEqualsComparer),
  119. m_OwnStorage(true)
  120. {
  121. }
  122. ~ArrayValueMap()
  123. {
  124. if (m_OwnStorage)
  125. {
  126. delete[] m_Values;
  127. }
  128. }
  129. inline void assign_external(TValue* values, size_t valueCount, TValueToKeyConverter valueToKeyConverter = TValueToKeyConverter(),
  130. TKeyLess keyLessComparer = TKeyLess(), TKeyEquals keyEqualsComparer = TKeyEquals())
  131. {
  132. this->~ArrayValueMap();
  133. new(this) map_type(values, valueCount, valueToKeyConverter, keyLessComparer, keyEqualsComparer);
  134. }
  135. // Constructs map that contains pointers to original array
  136. inline void assign_addresses(const TValue& valueArray, size_t valueCount, TValueToKeyConverter valueToKeyConverter = TValueToKeyConverter(),
  137. TKeyLess keyLessComparer = TKeyLess(), TKeyEquals keyEqualsComparer = TKeyEquals())
  138. {
  139. this->~ArrayValueMap();
  140. TValue* storage = NULL;
  141. if (valueCount > 0)
  142. {
  143. storage = new TValue[valueCount];
  144. for (size_t i = 0; i < valueCount; i++)
  145. {
  146. storage[i] = &valueArray[i];
  147. }
  148. }
  149. new(this) map_type(storage, valueCount, valueToKeyConverter, keyLessComparer, keyEqualsComparer);
  150. m_OwnStorage = true;
  151. }
  152. inline void assign(const std::vector<TValue>& values, TValueToKeyConverter valueToKeyConverter = TValueToKeyConverter(),
  153. TKeyLess keyLessComparer = TKeyLess(), TKeyEquals keyEqualsComparer = TKeyEquals())
  154. {
  155. this->~ArrayValueMap();
  156. new(this) map_type(values, valueToKeyConverter, keyLessComparer, keyEqualsComparer);
  157. }
  158. inline iterator begin() const
  159. {
  160. return m_Values;
  161. }
  162. inline iterator end() const
  163. {
  164. return m_Values + m_ValueCount;
  165. }
  166. template<typename EqualsPredicate>
  167. inline iterator find(const TKey& key, const EqualsPredicate& equalsPredicate) const
  168. {
  169. iterator dataStart = begin();
  170. iterator dataEnd = end();
  171. iterator ptr = std::lower_bound(dataStart, dataEnd, key, LowerBoundFindComparer(m_ValueToKeyConverter, m_KeyLessComparer));
  172. for (; ptr != dataEnd && m_KeyEqualsComparer(m_ValueToKeyConverter(*ptr), key); ptr++)
  173. {
  174. if (equalsPredicate(*ptr))
  175. return ptr;
  176. }
  177. return dataEnd;
  178. }
  179. inline iterator find_first(const TKey& key) const
  180. {
  181. iterator dataStart = begin();
  182. iterator dataEnd = end();
  183. iterator ptr = std::lower_bound(dataStart, dataEnd, key, LowerBoundFindComparer(m_ValueToKeyConverter, m_KeyLessComparer));
  184. if (ptr != dataEnd && m_KeyEqualsComparer(m_ValueToKeyConverter(*ptr), key))
  185. return ptr;
  186. return dataEnd;
  187. }
  188. inline iterator lower_bound(const TKey& key) const
  189. {
  190. return std::lower_bound(begin(), end(), key, LowerBoundFindComparer(m_ValueToKeyConverter, m_KeyLessComparer));
  191. }
  192. inline iterator upper_bound(const TKey& key) const
  193. {
  194. return std::upper_bound(begin(), end(), key, UpperBoundFindComparer(m_ValueToKeyConverter, m_KeyLessComparer));
  195. }
  196. inline size_t size() const
  197. {
  198. return m_ValueCount;
  199. }
  200. inline const TValue& operator[](size_t i) const
  201. {
  202. return m_Values[i];
  203. }
  204. template<typename Mutator>
  205. inline void mutate(Mutator& mutator)
  206. {
  207. size_t count = m_ValueCount;
  208. const TValue* values = m_Values;
  209. for (size_t i = 0; i < count; i++)
  210. mutator(const_cast<TValue*>(values + i));
  211. m_Values = InitializeInPlace(const_cast<TValue*>(values), count, m_ValueToKeyConverter, m_KeyLessComparer);
  212. }
  213. };
  214. }
  215. } // namespace utils
  216. } // namespace il2cpp