Source code of Windows XP (NT5)
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.

354 lines
9.6 KiB

  1. //____________________________________________________________________________
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996 - 1999
  5. //
  6. // File: Containr.h
  7. //
  8. // Contents: declarations of map and pair container classes
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 10/8/98 VivekJ Created
  15. //
  16. //____________________________________________________________________________
  17. //#define MAPDBG
  18. #pragma warning(disable : 4786)
  19. template<typename _T1, typename _T2> class Pair
  20. {
  21. public:
  22. typedef _T1 First;
  23. typedef _T2 Second;
  24. Pair() {}
  25. Pair(const First& f, const Second& s) : m_First(f), m_Second(s) {}
  26. Pair(const Pair& p) : m_First(p.m_First), m_Second(p.m_Second) {}
  27. ~Pair() {}
  28. Pair& operator=(const Pair& p) { if (this != &p) {m_First = p.m_First; m_Second = p.m_Second; } return *this; }
  29. //bool operator==(const Pair& p) const { return m_First == p.m_First && m_Second == p.m_Second; }
  30. //bool operator!=(const Pair& p) const { return !operator==(p); }
  31. const First& GetFirst() const { return m_First; }
  32. void SetFirst(const First& f) { m_First = f; };
  33. const Second& GetSecond() const { return m_Second; }
  34. void SetSecond(const Second& s) { m_Second = s; };
  35. First* GetFirstPtr() { return reinterpret_cast<First*>(reinterpret_cast<char*>(this) + offsetof(Pair, m_First)); }
  36. Second* GetSecondPtr() { return reinterpret_cast<Second*>(reinterpret_cast<char*>(this) + offsetof(Pair, m_Second)); }
  37. const First* GetFirstPtr() const { return reinterpret_cast<const First*>(reinterpret_cast<const char*>(this) + offsetof(Pair, m_First)); }
  38. const Second* GetSecondPtr() const { return reinterpret_cast<const Second*>(reinterpret_cast<const char*>(this) + offsetof(Pair, m_Second)); }
  39. private:
  40. First m_First;
  41. Second m_Second;
  42. }; // class Pair
  43. template<typename _T, typename _Key> class Map
  44. // This is a temporary class which should be replaced by something that can
  45. // hold smart pointers
  46. {
  47. public:
  48. typedef _T T;
  49. typedef _Key Key;
  50. typedef Pair<T, Key> Element;
  51. typedef Element* iterator;
  52. typedef const Element* const_iterator;
  53. explicit Map(size_t initialSize = 0)
  54. : m_nSize(0), m_nUsed(0), m_pMap(NULL), m_pNext(NULL)
  55. #ifdef MAPDBG
  56. , m_nFinds(0), m_nCompares(0)
  57. #endif //MAPDBG
  58. {
  59. const bool bAllocated = Allocate(initialSize);
  60. ASSERT(m_nSize == initialSize);
  61. ASSERT(bAllocated);
  62. }
  63. Map(const Map& m)
  64. : m_nSize(0), m_nUsed(0), m_pMap(NULL), m_pNext(NULL)
  65. #ifdef MAPDBG
  66. , m_nFinds(0), m_nCompares(0)
  67. #endif //MAPDBG
  68. {
  69. ASSERT(&m != NULL);
  70. if (m.m_nUsed == 0)
  71. return;
  72. const bool bAllocated = Allocate(m.m_nUsed);
  73. ASSERT(bAllocated);
  74. if (!bAllocated)
  75. return;
  76. ASSERT(m_nSize == m.m_nUsed);
  77. ASSERT(m_pMap != NULL);
  78. m_pNext = UninitializedCopy(m_pMap, m.m_pMap, m_nSize);
  79. m_nUsed = m_nSize;
  80. }
  81. ~Map()
  82. {
  83. Destroy();
  84. }
  85. Map& operator=(const Map& m)
  86. {
  87. ASSERT(&m != NULL);
  88. if (&m == this)
  89. return *this;
  90. Destroy();
  91. if (m.m_nUsed == 0)
  92. return *this;
  93. const bool bAllocated = Allocate(m.m_nUsed);
  94. ASSERT(bAllocated);
  95. if (!bAllocated)
  96. return *this;
  97. ASSERT(m_nSize == m.m_nUsed);
  98. ASSERT(m_pMap != NULL);
  99. m_pNext = UninitializedCopy(m_pMap, m.m_pMap, m_nSize);
  100. m_nUsed = m_nSize;
  101. return *this;
  102. }
  103. const_iterator GetBegin() const
  104. {
  105. return m_pMap;
  106. }
  107. size_t GetSize() const
  108. {
  109. return m_nUsed;
  110. }
  111. Element* GetPair(size_t n) const
  112. {
  113. if (n >= m_nUsed)
  114. return NULL;
  115. else
  116. return m_pMap + n;
  117. }
  118. const_iterator GetEnd() const
  119. {
  120. return m_pMap + m_nUsed;
  121. }
  122. bool Allocate(size_t nSize)
  123. {
  124. ASSERT(m_nSize == 0 || nSize > m_nSize);
  125. if (nSize <= m_nSize)
  126. return true;
  127. Element* pNewMap = reinterpret_cast<Element*>(new char[nSize * sizeof(Element)]);
  128. ASSERT(pNewMap != NULL);
  129. if (pNewMap == NULL)
  130. return false;
  131. const size_t nUsed = m_nUsed;
  132. Element* const pCopied = UninitializedCopy(pNewMap, m_pMap, nUsed);
  133. ASSERT(pCopied != NULL);
  134. if (pCopied == NULL)
  135. return false;
  136. Destroy();
  137. m_pMap = m_pNext = pNewMap;
  138. m_nSize = nSize;
  139. m_nUsed = nUsed;
  140. return true;
  141. }
  142. bool Insert(const T& t, const Key& key)
  143. {
  144. ASSERT(&t != NULL);
  145. ASSERT(&key != NULL);
  146. Element* const pUnique = FindElement(key, false);
  147. if (pUnique != NULL)
  148. return false;
  149. ASSERT(m_nUsed <= m_nSize);
  150. if (m_nUsed >= m_nSize)
  151. {
  152. const unsigned long nNewSize = m_nSize == 0 ? 1 : m_nSize + (m_nSize + 1) / 2;
  153. const bool bMoreAllocated = Allocate(nNewSize);
  154. ASSERT(bMoreAllocated);
  155. if (!bMoreAllocated)
  156. return false;
  157. }
  158. Element e(t, key);
  159. Element* const dest = m_pMap + m_nUsed++;
  160. m_pNext = UninitializedCopy(dest, &e, 1);
  161. ASSERT(m_pNext != NULL);
  162. return true;
  163. }
  164. bool Remove(const Key& key)
  165. {
  166. ASSERT(&key != NULL);
  167. Element* const e = FindElement(key);
  168. if (e == NULL)
  169. return false;
  170. Element* endOfUsed = m_pMap + m_nUsed--;
  171. ASSERT(e < endOfUsed);
  172. ASSERT(e >= m_pMap);
  173. const size_t numberToCopy = endOfUsed - (e + 1);
  174. Copy(const_cast<Element*>(e), e+1, numberToCopy);
  175. (endOfUsed - 1)->~Pair<T, Key>();
  176. if (m_pNext >= endOfUsed)
  177. m_pNext = m_pMap;
  178. return true;
  179. }
  180. T& operator[](const Key& key) const
  181. {
  182. ASSERT(&key != NULL);
  183. T* const t = Find(key);
  184. ASSERT(t != NULL);
  185. return *t;
  186. }
  187. T* Find(const Key& key) const
  188. {
  189. ASSERT(&key != NULL);
  190. Element* const e = FindElement(key);
  191. return e != NULL ? e->GetFirstPtr() : NULL;
  192. }
  193. size_t Size() const
  194. {
  195. return m_nUsed;
  196. }
  197. size_t MaxSize() const
  198. {
  199. return m_nSize;
  200. }
  201. bool Empty() const
  202. {
  203. return m_nUsed > 0;
  204. }
  205. void Clear()
  206. {
  207. Destroy();
  208. }
  209. private:
  210. Element* m_pMap;
  211. size_t m_nSize;
  212. size_t m_nUsed;
  213. mutable Element* m_pNext;
  214. #ifdef MAPDBG
  215. mutable unsigned long m_nFinds;
  216. mutable unsigned long m_nCompares;
  217. #endif //MAPDBG
  218. void Destroy()
  219. {
  220. if (m_pMap == NULL)
  221. return;
  222. Element* const end = m_pMap + m_nUsed;
  223. Element* i = m_pMap;
  224. while (i != end)
  225. (i++)->~Pair<T, Key>();
  226. delete [] reinterpret_cast<char*>(m_pMap);
  227. m_pNext = m_pMap = NULL;
  228. m_nSize = 0;
  229. m_nUsed = 0;
  230. }
  231. Element* FindElement(const Key& key, bool bIncludeInStats = true) const
  232. {
  233. ASSERT(&key != NULL);
  234. #ifdef MAPDBG
  235. if (bIncludeInStats)
  236. ++m_nFinds;
  237. #endif //MAPDBG
  238. Element* const pNext = m_pNext;
  239. Element* const end = m_pMap + m_nUsed;
  240. ASSERT(pNext <= end);
  241. while (m_pNext != end)
  242. {
  243. if (m_pNext->GetSecond() == key)
  244. {
  245. #ifdef MAPDBG
  246. if (bIncludeInStats)
  247. TotalStats(m_pNext - pNext);
  248. #endif //MAPDBG
  249. return m_pNext++;
  250. }
  251. ++m_pNext;
  252. }
  253. m_pNext = m_pMap;
  254. ASSERT(m_pNext != NULL || pNext == NULL);
  255. ASSERT(m_pNext <= pNext);
  256. while (m_pNext != pNext)
  257. {
  258. if (m_pNext->GetSecond() == key)
  259. {
  260. #ifdef MAPDBG
  261. if (bIncludeInStats)
  262. TotalStats((m_pNext - m_pMap) + (end - pNext));
  263. #endif //MAPDBG
  264. return m_pNext++;
  265. }
  266. ++m_pNext;
  267. }
  268. #ifdef MAPDBG
  269. if (bIncludeInStats)
  270. TotalStats(m_nUsed);
  271. #endif //MAPDBG
  272. return NULL;
  273. }
  274. #ifdef MAPDBG
  275. void TotalStats(unsigned long nComparesPerformed) const
  276. {
  277. m_nCompares += nComparesPerformed;
  278. double average = double(m_nCompares) / double(m_nFinds);
  279. double const successRatio = nComparesPerformed == 0 ? 100.0 :
  280. (1.0 - (double(nComparesPerformed) / double(m_nUsed))) * 100.0;
  281. const size_t nOffset = m_pNext - m_pMap;
  282. TRACE("Map::find(%u), #%u, offset: %u, comps: %u, ave: %u, %%%u\n",
  283. (unsigned)(this), m_nFinds, nOffset, nComparesPerformed, (unsigned long)(average),
  284. (unsigned long)(successRatio));
  285. }
  286. #endif // MAPDBG
  287. static Element* UninitializedCopy(Element* dest, Element* src, size_t nCount)
  288. {
  289. if (nCount == 0)
  290. return dest;
  291. ASSERT(src != NULL || nCount == 0);
  292. ASSERT(dest != NULL);
  293. ASSERT(nCount > 0);
  294. if (nCount <= 0 || dest == NULL || src == NULL)
  295. return NULL;
  296. Element* const originalDest = dest;
  297. Element* const end = dest + nCount;
  298. while (dest != end)
  299. new(dest++) Element(*src++);
  300. return originalDest;
  301. }
  302. static void Copy(Element* dest, const Element* src, size_t nCount)
  303. {
  304. ASSERT(dest != NULL);
  305. ASSERT(src != NULL);
  306. ASSERT(static_cast<SSIZE_T>(nCount) >= 0);
  307. ASSERT(dest < src);
  308. if (nCount <= 0 || dest == NULL || src == NULL || dest >= src)
  309. return;
  310. Element* const end = dest + nCount;
  311. while (dest != end)
  312. *dest++ = *src++;
  313. }
  314. }; // class Map