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.

373 lines
8.8 KiB

  1. /*****************************************************************************
  2. *
  3. * (C) COPYRIGHT MICROSOFT CORPORATION, 2000
  4. *
  5. * TITLE: cntutils.h
  6. *
  7. * VERSION: 1.0
  8. *
  9. * AUTHOR: LazarI
  10. *
  11. * DATE: 23-Dec-2000
  12. *
  13. * DESCRIPTION: Containers and algorithms utility templates
  14. *
  15. *****************************************************************************/
  16. #ifndef _CNTUTILS_H
  17. #define _CNTUTILS_H
  18. // the generic smart pointers & handles
  19. #include "gensph.h"
  20. ////////////////////////////////////////////////
  21. // Algorithms
  22. //
  23. namespace Alg
  24. {
  25. ///////////////////////////////////////////////////////////////
  26. // CDefaultAdaptor<T,K> - default adaptor class.
  27. //
  28. // T - type
  29. // K - key for sorting
  30. //
  31. template <class T, class K = T>
  32. class CDefaultAdaptor
  33. {
  34. public:
  35. // assumes the key is the item itself
  36. static const K& Key(const T &i) { return (const K&)i; }
  37. // assumes K has less operator defined
  38. static int Compare(const K &k1, const K &k2) { return (k2 < k1) - (k1 < k2); }
  39. // assumes assignment operator defined
  40. static T& Assign(T &i1, const T &i2) { return (i1 = i2); }
  41. };
  42. //////////////////////////////////////////////////////////
  43. // _LowerBound<T,K,A> - lowerbound search alg.
  44. // assumes the array is sorted.
  45. //
  46. // returns the position where this key (item) should be inserted.
  47. // all the items before that position will be less or equal to the input key
  48. //
  49. // T - type
  50. // K - key for sorting
  51. // A - adaptor
  52. //
  53. template <class T, class K, class A>
  54. int _LowerBound(const K &k, const T *base, int lo, int hi)
  55. {
  56. while( lo <= hi )
  57. {
  58. if( lo == hi )
  59. {
  60. // boundary case
  61. if( A::Compare(k, A::Key(base[lo])) >= 0 )
  62. {
  63. // k >= lo
  64. lo++;
  65. }
  66. break;
  67. }
  68. else
  69. {
  70. // divide & conquer
  71. int mid = (lo+hi)/2;
  72. if( A::Compare(k, A::Key(base[mid])) < 0 )
  73. {
  74. // k < mid
  75. hi = mid;
  76. }
  77. else
  78. {
  79. // k >= mid
  80. lo = mid+1;
  81. }
  82. }
  83. }
  84. return lo;
  85. }
  86. ///////////////////////////////////////////////////////////////
  87. // CSearchAlgorithms<T,K,A> - search alg.
  88. //
  89. // T - type
  90. // K - key for sorting
  91. // A - adaptor
  92. //
  93. // default template arguments are allowed only on classes
  94. template <class T, class K = T, class A = CDefaultAdaptor<T,K> >
  95. class CSearchAlgorithms
  96. {
  97. public:
  98. // lower bound
  99. static int LowerBound(const K &k, const T *base, int count)
  100. {
  101. return _LowerBound<T,K,A>(k, base, 0, count-1);
  102. }
  103. // binary search
  104. static bool Find(const K &k, const T *base, int count, int *pi)
  105. {
  106. int iPos = _LowerBound<T,K,A>(k, base, 0, count-1)-1;
  107. bool bFound = (0 <= iPos && iPos < count && 0 == A::Compare(k, A::Key(base[iPos])));
  108. if( bFound && pi ) *pi = iPos;
  109. return bFound;
  110. };
  111. };
  112. } // namespace Alg
  113. ////////////////////////////////////////////////
  114. //
  115. // class CSimpleArray
  116. //
  117. // a simple array implementation based on
  118. // shell DSA_* stuff (not MT safe)
  119. //
  120. // turn off debugging new for a while
  121. #if defined(_DEBUG) && defined(_CRTDBG_MAP_ALLOC)
  122. #undef new
  123. #endif
  124. template <class T>
  125. class CSimpleArray
  126. {
  127. // in-place construct/destruct wrapper
  128. class CWrapper
  129. {
  130. public:
  131. // proper copy semantics
  132. CWrapper() { }
  133. CWrapper(const T &t): m_t(t) { }
  134. T& operator = (const T &t) { m_t = t; return t; }
  135. // placed new & delete
  136. void *operator new(size_t, CWrapper *p) { ASSERT(p); return p; }
  137. void operator delete(void *p) { }
  138. T m_t;
  139. };
  140. public:
  141. enum { DEFAULT_GROW = 32 };
  142. typedef int (*PFN_COMPARE)(const T &i1, const T &i2);
  143. CSimpleArray(int iGrow = DEFAULT_GROW) { Create(iGrow); }
  144. ~CSimpleArray() { Destroy(); }
  145. HRESULT Create(int iGrow = DEFAULT_GROW)
  146. {
  147. m_shDSA = DSA_Create(sizeof(CWrapper), iGrow);
  148. return m_shDSA ? S_OK : E_OUTOFMEMORY;
  149. }
  150. HRESULT Destroy()
  151. {
  152. if( m_shDSA )
  153. {
  154. DeleteAll();
  155. m_shDSA = NULL;
  156. }
  157. return S_OK;
  158. }
  159. // the array interface
  160. int Count() const
  161. {
  162. ASSERT(m_shDSA);
  163. return _DSA_GetItemCount(m_shDSA);
  164. }
  165. const T& operator [] (int i) const
  166. {
  167. return _GetWrapperAt(i)->m_t;
  168. }
  169. T& operator [] (int i)
  170. {
  171. return _GetWrapperAt(i)->m_t;
  172. }
  173. // returns true if created/initialized
  174. operator bool () const
  175. {
  176. return m_shDSA;
  177. }
  178. // returns -1 if failed to grow - i.e. out of memory
  179. int Append(const T &item)
  180. {
  181. ASSERT(m_shDSA);
  182. int i = DSA_InsertItem(m_shDSA, DA_LAST, (void *)_GetZeroMemWrapper()); // allocate
  183. if( -1 != i )
  184. {
  185. new (_GetWrapperAt(i)) CWrapper(item); // construct
  186. }
  187. return i;
  188. }
  189. // returns -1 if failed to grow - i.e. out of memory
  190. int Insert(int i, const T &item)
  191. {
  192. ASSERT(m_shDSA && 0 <= i && i <= _DSA_GetItemCount(m_shDSA));
  193. i = DSA_InsertItem(m_shDSA, i, (void *)_GetZeroMemWrapper()); // allocate
  194. if( -1 != i )
  195. {
  196. new (_GetWrapperAt(i)) CWrapper(item); // construct
  197. }
  198. return i;
  199. }
  200. BOOL Delete(int i)
  201. {
  202. ASSERT(m_shDSA && 0 <= i && i < _DSA_GetItemCount(m_shDSA));
  203. delete _GetWrapperAt(i); // destruct
  204. return DSA_DeleteItem(m_shDSA, i); // free
  205. }
  206. void DeleteAll()
  207. {
  208. ASSERT(m_shDSA);
  209. // destruct all
  210. if( Count() )
  211. {
  212. int i, iCount = Count();
  213. CWrapper *p = _GetWrapperAt(0);
  214. for( i=0; i<iCount; i++ )
  215. {
  216. delete (p+i);
  217. }
  218. }
  219. // free all
  220. DSA_DeleteAllItems(m_shDSA);
  221. }
  222. HRESULT Sort(PFN_COMPARE pfnCompare)
  223. {
  224. // would be nice to have it
  225. return E_NOTIMPL;
  226. }
  227. private:
  228. static CWrapper* _GetZeroMemWrapper()
  229. {
  230. // returns zero initialized memory of size - sizeof(CWrapper)
  231. static BYTE buffer[sizeof(CWrapper)];
  232. return reinterpret_cast<CWrapper*>(buffer);
  233. }
  234. CWrapper* _GetWrapperAt(int i) const
  235. {
  236. ASSERT(m_shDSA && 0 <= i && i < _DSA_GetItemCount(m_shDSA));
  237. return reinterpret_cast<CWrapper*>(DSA_GetItemPtr(m_shDSA, i));
  238. }
  239. int _DSA_GetItemCount(HDSA hdsa) const
  240. {
  241. // DSA_GetItemCount is a macro, which is casting to int* (somewhat illegal),
  242. // so we need to do a static cast here, so our casting operator gets invoked
  243. return DSA_GetItemCount(static_cast<HDSA>(m_shDSA));
  244. }
  245. CAutoHandleHDSA m_shDSA; // shell dynamic structure array
  246. };
  247. // turn back on debugging new
  248. #if defined(_DEBUG) && defined(_CRTDBG_MAP_ALLOC)
  249. #define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
  250. #endif
  251. ////////////////////////////////////////////////
  252. //
  253. // class CSortedArray<T,K,A>
  254. //
  255. // a sorted array implementation based on DSA_*
  256. // (not MT safe)
  257. //
  258. // T - type
  259. // K - key for sorting
  260. // A - adaptor
  261. //
  262. template <class T, class K = T, class A = Alg::CDefaultAdaptor<T,K> >
  263. class CSortedArray: public CSimpleArray<T>
  264. {
  265. public:
  266. CSortedArray() { }
  267. CSortedArray(int iGrow): CSimpleArray<T>(iGrow) { }
  268. ~CSortedArray() { }
  269. // returns -1 if failed to grow - i.e. out of memory
  270. int SortedInsert(const T &item)
  271. {
  272. return CSimpleArray<T>::Insert(
  273. Count() ? Alg::CSearchAlgorithms<T,K,A>::LowerBound(A::Key(item), &operator[](0), Count()) : 0,
  274. item);
  275. }
  276. // true if found and false otherwise
  277. bool FindItem(const K &k, int *pi) const
  278. {
  279. return Count() ? Alg::CSearchAlgorithms<T,K,A>::Find(k, &operator[](0), Count(), pi) : false;
  280. }
  281. private:
  282. // those APIs shouldn't be visible, so make them private.
  283. int Append(const T &item) { CSimpleArray<T>::Append(item); }
  284. int Insert(int i, const T &item) { CSimpleArray<T>::Insert(i, item); }
  285. HRESULT Sort(PFN_COMPARE pfnCompare) { CSimpleArray<T>::Sort(pfnCompare); }
  286. };
  287. ////////////////////////////////////////////////
  288. //
  289. // class CFastHeap<T>
  290. //
  291. // fast cached heap for fixed chunks
  292. // of memory (MT safe)
  293. //
  294. template <class T>
  295. class CFastHeap
  296. {
  297. public:
  298. enum { DEFAULT_CACHE_SIZE = 32 };
  299. // construction/destruction
  300. CFastHeap(int iCacheSize = DEFAULT_CACHE_SIZE);
  301. ~CFastHeap();
  302. // the fast heap interface
  303. HRESULT Alloc(const T &data, HANDLE *ph);
  304. HRESULT Free(HANDLE h);
  305. HRESULT GetItem(HANDLE h, T **ppData);
  306. #if DBG
  307. int m_iPhysicalAllocs;
  308. int m_iLogicalAllocs;
  309. #else
  310. private:
  311. #endif
  312. // private stuff/impl.
  313. struct HeapItem
  314. {
  315. HeapItem *pNext;
  316. T data;
  317. };
  318. CCSLock m_csLock;
  319. HeapItem *m_pFreeList;
  320. int m_iCacheSize;
  321. int m_iCached;
  322. };
  323. // include the implementation of the template classes here
  324. #include "cntutils.inl"
  325. #endif // endif _CNTUTILS_H