dxtmpl.h 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882
  1. /**
  2. * This file has no copyright assigned and is placed in the Public Domain.
  3. * This file is part of the mingw-w64 runtime package.
  4. * No warranty is given; refer to the file DISCLAIMER.PD within this package.
  5. */
  6. #ifndef DXTmpl_h
  7. #define DXTmpl_h
  8. #include <limits.h>
  9. #include <string.h>
  10. #include <stdlib.h>
  11. #include <search.h>
  12. #define DXASSERT_VALID(pObj)
  13. #ifndef PASCAL_INLINE
  14. #define PASCAL_INLINE WINAPI
  15. #endif
  16. typedef void *DXLISTPOS;
  17. typedef DWORD DXLISTHANDLE;
  18. #define DX_BEFORE_START_POSITION ((void*)(INT_PTR)-1)
  19. #ifndef __CRT__NO_INLINE
  20. __CRT_INLINE WINBOOL DXIsValidAddress(const void *lp,UINT nBytes,WINBOOL bReadWrite) { return (lp!=NULL && !IsBadReadPtr(lp,nBytes) && (!bReadWrite || !IsBadWritePtr((LPVOID)lp,nBytes))); }
  21. #endif
  22. #ifdef __cplusplus
  23. template<class TYPE>
  24. inline void DXConstructElements(TYPE *pElements,int nCount) {
  25. _ASSERT(nCount==0 || DXIsValidAddress(pElements,nCount *sizeof(TYPE),TRUE));
  26. memset((void*)pElements,0,nCount *sizeof(TYPE));
  27. }
  28. template<class TYPE>
  29. inline void DXDestructElements(TYPE *pElements,int nCount) {
  30. _ASSERT((nCount==0 || DXIsValidAddress(pElements,nCount *sizeof(TYPE),TRUE)));
  31. pElements;
  32. nCount;
  33. }
  34. template<class TYPE>
  35. inline void DXCopyElements(TYPE *pDest,const TYPE *pSrc,int nCount) {
  36. _ASSERT((nCount==0 || DXIsValidAddress(pDest,nCount *sizeof(TYPE),TRUE)));
  37. _ASSERT((nCount==0 || DXIsValidAddress(pSrc,nCount *sizeof(TYPE),FALSE)));
  38. memcpy(pDest,pSrc,nCount *sizeof(TYPE));
  39. }
  40. template<class TYPE,class ARG_TYPE>
  41. WINBOOL DXCompareElements(const TYPE *pElement1,const ARG_TYPE *pElement2) {
  42. _ASSERT(DXIsValidAddress(pElement1,sizeof(TYPE),FALSE));
  43. _ASSERT(DXIsValidAddress(pElement2,sizeof(ARG_TYPE),FALSE));
  44. return *pElement1==*pElement2;
  45. }
  46. template<class ARG_KEY>
  47. inline UINT DXHashKey(ARG_KEY key) { return ((UINT)(void*)(DWORD)key) >> 4; }
  48. struct CDXPlex {
  49. CDXPlex *pNext;
  50. UINT nMax;
  51. UINT nCur;
  52. void *data() { return this+1; }
  53. static CDXPlex *PASCAL_INLINE Create(CDXPlex *&pHead,UINT nMax,UINT cbElement) {
  54. CDXPlex *p = (CDXPlex*) new BYTE[sizeof(CDXPlex) + nMax *cbElement];
  55. if(!p) return NULL;
  56. p->nMax = nMax;
  57. p->nCur = 0;
  58. p->pNext = pHead;
  59. pHead = p;
  60. return p;
  61. }
  62. void FreeDataChain() {
  63. CDXPlex *p = this;
  64. while(p!=NULL) {
  65. BYTE *bytes = (BYTE*) p;
  66. CDXPlex *pNext = p->pNext;
  67. delete [] bytes;
  68. p = pNext;
  69. }
  70. }
  71. };
  72. template<class TYPE,class ARG_TYPE>
  73. class CDXArray {
  74. public:
  75. CDXArray();
  76. int GetSize() const;
  77. int GetUpperBound() const;
  78. void SetSize(int nNewSize,int nGrowBy = -1);
  79. void FreeExtra();
  80. void RemoveAll();
  81. TYPE GetAt(int nIndex) const;
  82. void SetAt(int nIndex,ARG_TYPE newElement);
  83. TYPE &ElementAt(int nIndex);
  84. const TYPE *GetData() const;
  85. TYPE *GetData();
  86. void SetAtGrow(int nIndex,ARG_TYPE newElement);
  87. int Add(ARG_TYPE newElement);
  88. int Append(const CDXArray &src);
  89. void Copy(const CDXArray &src);
  90. TYPE operator[](int nIndex) const;
  91. TYPE &operator[](int nIndex);
  92. void InsertAt(int nIndex,ARG_TYPE newElement,int nCount = 1);
  93. void RemoveAt(int nIndex,int nCount = 1);
  94. void InsertAt(int nStartIndex,CDXArray *pNewArray);
  95. void Sort(int (__cdecl *compare)(const void *elem1,const void *elem2));
  96. protected:
  97. TYPE *m_pData;
  98. int m_nSize;
  99. int m_nMaxSize;
  100. int m_nGrowBy;
  101. public:
  102. ~CDXArray();
  103. };
  104. template<class TYPE,class ARG_TYPE>
  105. inline int CDXArray<TYPE,ARG_TYPE>::GetSize() const { return m_nSize; }
  106. template<class TYPE,class ARG_TYPE>
  107. inline int CDXArray<TYPE,ARG_TYPE>::GetUpperBound() const { return m_nSize-1; }
  108. template<class TYPE,class ARG_TYPE>
  109. inline void CDXArray<TYPE,ARG_TYPE>::RemoveAll() { SetSize(0,-1); }
  110. template<class TYPE,class ARG_TYPE>
  111. inline TYPE CDXArray<TYPE,ARG_TYPE>::GetAt(int nIndex) const { _ASSERT((nIndex >= 0 && nIndex < m_nSize)); return m_pData[nIndex]; }
  112. template<class TYPE,class ARG_TYPE>
  113. inline void CDXArray<TYPE,ARG_TYPE>::SetAt(int nIndex,ARG_TYPE newElement) { _ASSERT((nIndex >= 0 && nIndex < m_nSize)); m_pData[nIndex] = newElement; }
  114. template<class TYPE,class ARG_TYPE>
  115. inline TYPE &CDXArray<TYPE,ARG_TYPE>::ElementAt(int nIndex) { _ASSERT((nIndex >= 0 && nIndex < m_nSize)); return m_pData[nIndex]; }
  116. template<class TYPE,class ARG_TYPE>
  117. inline const TYPE *CDXArray<TYPE,ARG_TYPE>::GetData() const { return (const TYPE*)m_pData; }
  118. template<class TYPE,class ARG_TYPE>
  119. inline TYPE *CDXArray<TYPE,ARG_TYPE>::GetData() { return (TYPE*)m_pData; }
  120. template<class TYPE,class ARG_TYPE>
  121. inline int CDXArray<TYPE,ARG_TYPE>::Add(ARG_TYPE newElement) {
  122. int nIndex = m_nSize;
  123. SetAtGrow(nIndex,newElement);
  124. return nIndex;
  125. }
  126. template<class TYPE,class ARG_TYPE>
  127. inline TYPE CDXArray<TYPE,ARG_TYPE>::operator[](int nIndex) const { return GetAt(nIndex); }
  128. template<class TYPE,class ARG_TYPE>
  129. inline TYPE &CDXArray<TYPE,ARG_TYPE>::operator[](int nIndex) { return ElementAt(nIndex); }
  130. template<class TYPE,class ARG_TYPE>
  131. CDXArray<TYPE,ARG_TYPE>::CDXArray() { m_pData = NULL; m_nSize = m_nMaxSize = m_nGrowBy = 0; }
  132. emplate<class TYPE,class ARG_TYPE>
  133. CDXArray<TYPE,ARG_TYPE>::~CDXArray() {
  134. DXASSERT_VALID(this);
  135. if(m_pData!=NULL) {
  136. DXDestructElements(m_pData,m_nSize);
  137. delete[] (BYTE*)m_pData;
  138. }
  139. }
  140. template<class TYPE,class ARG_TYPE>
  141. void CDXArray<TYPE,ARG_TYPE>::SetSize(int nNewSize,int nGrowBy) {
  142. DXASSERT_VALID(this);
  143. _ASSERT(nNewSize >= 0);
  144. if(nGrowBy!=-1) m_nGrowBy = nGrowBy;
  145. if(nNewSize==0) {
  146. if(m_pData!=NULL) {
  147. DXDestructElements(m_pData,m_nSize);
  148. delete[] (BYTE*)m_pData;
  149. m_pData = NULL;
  150. }
  151. m_nSize = m_nMaxSize = 0;
  152. } else if(!m_pData) {
  153. #ifdef SIZE_T_MAX
  154. _ASSERT(nNewSize <= SIZE_T_MAX/sizeof(TYPE));
  155. #endif
  156. m_pData = (TYPE*) new BYTE[nNewSize *sizeof(TYPE)];
  157. DXConstructElements(m_pData,nNewSize);
  158. m_nSize = m_nMaxSize = nNewSize;
  159. } else if(nNewSize <= m_nMaxSize) {
  160. if(nNewSize > m_nSize) {
  161. DXConstructElements(&m_pData[m_nSize],nNewSize-m_nSize);
  162. } else if(m_nSize > nNewSize) {
  163. DXDestructElements(&m_pData[nNewSize],m_nSize-nNewSize);
  164. }
  165. m_nSize = nNewSize;
  166. } else {
  167. int nGrowBy = m_nGrowBy;
  168. if(!nGrowBy) nGrowBy = min(1024,max(4,m_nSize / 8));
  169. int nNewMax;
  170. if(nNewSize < m_nMaxSize + nGrowBy) nNewMax = m_nMaxSize + nGrowBy;
  171. else nNewMax = nNewSize;
  172. _ASSERT(nNewMax >= m_nMaxSize);
  173. #ifdef SIZE_T_MAX
  174. _ASSERT(nNewMax <= SIZE_T_MAX/sizeof(TYPE));
  175. #endif
  176. TYPE *pNewData = (TYPE*) new BYTE[nNewMax *sizeof(TYPE)];
  177. if(!pNewData) return;
  178. memcpy(pNewData,m_pData,m_nSize *sizeof(TYPE));
  179. _ASSERT(nNewSize > m_nSize);
  180. DXConstructElements(&pNewData[m_nSize],nNewSize-m_nSize);
  181. delete[] (BYTE*)m_pData;
  182. m_pData = pNewData;
  183. m_nSize = nNewSize;
  184. m_nMaxSize = nNewMax;
  185. }
  186. }
  187. template<class TYPE,class ARG_TYPE>
  188. int CDXArray<TYPE,ARG_TYPE>::Append(const CDXArray &src) {
  189. DXASSERT_VALID(this);
  190. _ASSERT(this!=&src);
  191. int nOldSize = m_nSize;
  192. SetSize(m_nSize + src.m_nSize);
  193. DXCopyElements(m_pData + nOldSize,src.m_pData,src.m_nSize);
  194. return nOldSize;
  195. }
  196. template<class TYPE,class ARG_TYPE>
  197. void CDXArray<TYPE,ARG_TYPE>::Copy(const CDXArray &src) {
  198. DXASSERT_VALID(this);
  199. _ASSERT(this!=&src);
  200. SetSize(src.m_nSize);
  201. DXCopyElements(m_pData,src.m_pData,src.m_nSize);
  202. }
  203. template<class TYPE,class ARG_TYPE>
  204. void CDXArray<TYPE,ARG_TYPE>::FreeExtra() {
  205. DXASSERT_VALID(this);
  206. if(m_nSize!=m_nMaxSize) {
  207. #ifdef SIZE_T_MAX
  208. _ASSERT(m_nSize <= SIZE_T_MAX/sizeof(TYPE));
  209. #endif
  210. TYPE *pNewData = NULL;
  211. if(m_nSize!=0) {
  212. pNewData = (TYPE*) new BYTE[m_nSize *sizeof(TYPE)];
  213. if(!pNewData) return;
  214. memcpy(pNewData,m_pData,m_nSize *sizeof(TYPE));
  215. }
  216. delete[] (BYTE*)m_pData;
  217. m_pData = pNewData;
  218. m_nMaxSize = m_nSize;
  219. }
  220. }
  221. template<class TYPE,class ARG_TYPE>
  222. void CDXArray<TYPE,ARG_TYPE>::SetAtGrow(int nIndex,ARG_TYPE newElement) {
  223. DXASSERT_VALID(this);
  224. _ASSERT(nIndex >= 0);
  225. if(nIndex >= m_nSize) SetSize(nIndex+1,-1);
  226. m_pData[nIndex] = newElement;
  227. }
  228. template<class TYPE,class ARG_TYPE>
  229. void CDXArray<TYPE,ARG_TYPE>::InsertAt(int nIndex,ARG_TYPE newElement,int nCount) {
  230. DXASSERT_VALID(this);
  231. _ASSERT(nIndex >= 0);
  232. _ASSERT(nCount > 0);
  233. if(nIndex >= m_nSize) SetSize(nIndex + nCount,-1);
  234. else {
  235. int nOldSize = m_nSize;
  236. SetSize(m_nSize + nCount,-1);
  237. memmove(&m_pData[nIndex+nCount],&m_pData[nIndex],(nOldSize-nIndex) *sizeof(TYPE));
  238. DXConstructElements(&m_pData[nIndex],nCount);
  239. }
  240. _ASSERT(nIndex + nCount <= m_nSize);
  241. while(nCount--)
  242. m_pData[nIndex++] = newElement;
  243. }
  244. template<class TYPE,class ARG_TYPE>
  245. void CDXArray<TYPE,ARG_TYPE>::RemoveAt(int nIndex,int nCount) {
  246. DXASSERT_VALID(this);
  247. _ASSERT(nIndex >= 0);
  248. _ASSERT(nCount >= 0);
  249. _ASSERT(nIndex + nCount <= m_nSize);
  250. int nMoveCount = m_nSize - (nIndex + nCount);
  251. DXDestructElements(&m_pData[nIndex],nCount);
  252. if(nMoveCount)
  253. memcpy(&m_pData[nIndex],&m_pData[nIndex + nCount],nMoveCount *sizeof(TYPE));
  254. m_nSize -= nCount;
  255. }
  256. template<class TYPE,class ARG_TYPE>
  257. void CDXArray<TYPE,ARG_TYPE>::InsertAt(int nStartIndex,CDXArray *pNewArray) {
  258. DXASSERT_VALID(this);
  259. DXASSERT_VALID(pNewArray);
  260. _ASSERT(nStartIndex >= 0);
  261. if(pNewArray->GetSize() > 0) {
  262. InsertAt(nStartIndex,pNewArray->GetAt(0),pNewArray->GetSize());
  263. for(int i = 0;i < pNewArray->GetSize();i++)
  264. SetAt(nStartIndex + i,pNewArray->GetAt(i));
  265. }
  266. }
  267. template<class TYPE,class ARG_TYPE>
  268. void CDXArray<TYPE,ARG_TYPE>::Sort(int (__cdecl *compare)(const void *elem1,const void *elem2)) {
  269. DXASSERT_VALID(this);
  270. _ASSERT(m_pData!=NULL);
  271. qsort(m_pData,m_nSize,sizeof(TYPE),compare);
  272. }
  273. #ifdef _DEBUG
  274. template<class TYPE,class ARG_TYPE>
  275. void CDXArray<TYPE,ARG_TYPE>::AssertValid() const {
  276. if(!m_pData) {
  277. _ASSERT(m_nSize==0);
  278. _ASSERT(m_nMaxSize==0);
  279. } else {
  280. _ASSERT(m_nSize >= 0);
  281. _ASSERT(m_nMaxSize >= 0);
  282. _ASSERT(m_nSize <= m_nMaxSize);
  283. _ASSERT(DXIsValidAddress(m_pData,m_nMaxSize *sizeof(TYPE),TRUE));
  284. }
  285. }
  286. #endif
  287. template<class TYPE,class ARG_TYPE>
  288. class CDXList {
  289. protected:
  290. struct CNode {
  291. CNode *pNext;
  292. CNode *pPrev;
  293. TYPE data;
  294. };
  295. public:
  296. CDXList(int nBlockSize = 10);
  297. int GetCount() const;
  298. WINBOOL IsEmpty() const;
  299. TYPE &GetHead();
  300. TYPE GetHead() const;
  301. TYPE &GetTail();
  302. TYPE GetTail() const;
  303. TYPE RemoveHead();
  304. TYPE RemoveTail();
  305. DXLISTPOS AddHead(ARG_TYPE newElement);
  306. DXLISTPOS AddTail(ARG_TYPE newElement);
  307. void AddHead(CDXList *pNewList);
  308. void AddTail(CDXList *pNewList);
  309. void RemoveAll();
  310. DXLISTPOS GetHeadPosition() const;
  311. DXLISTPOS GetTailPosition() const;
  312. TYPE &GetNext(DXLISTPOS &rPosition);
  313. TYPE GetNext(DXLISTPOS &rPosition) const;
  314. TYPE &GetPrev(DXLISTPOS &rPosition);
  315. TYPE GetPrev(DXLISTPOS &rPosition) const;
  316. TYPE &GetAt(DXLISTPOS position);
  317. TYPE GetAt(DXLISTPOS position) const;
  318. void SetAt(DXLISTPOS pos,ARG_TYPE newElement);
  319. void RemoveAt(DXLISTPOS position);
  320. DXLISTPOS InsertBefore(DXLISTPOS position,ARG_TYPE newElement);
  321. DXLISTPOS InsertAfter(DXLISTPOS position,ARG_TYPE newElement);
  322. DXLISTPOS Find(ARG_TYPE searchValue,DXLISTPOS startAfter = NULL) const;
  323. DXLISTPOS FindIndex(int nIndex) const;
  324. protected:
  325. CNode *m_pNodeHead;
  326. CNode *m_pNodeTail;
  327. int m_nCount;
  328. CNode *m_pNodeFree;
  329. struct CDXPlex *m_pBlocks;
  330. int m_nBlockSize;
  331. CNode *NewNode(CNode *,CNode *);
  332. void FreeNode(CNode *);
  333. public:
  334. ~CDXList();
  335. #ifdef _DEBUG
  336. void AssertValid() const;
  337. #endif
  338. };
  339. template<class TYPE,class ARG_TYPE>
  340. inline int CDXList<TYPE,ARG_TYPE>::GetCount() const { return m_nCount; }
  341. template<class TYPE,class ARG_TYPE>
  342. inline WINBOOL CDXList<TYPE,ARG_TYPE>::IsEmpty() const { return m_nCount==0; }
  343. template<class TYPE,class ARG_TYPE>
  344. inline TYPE &CDXList<TYPE,ARG_TYPE>::GetHead() { _ASSERT(m_pNodeHead!=NULL); return m_pNodeHead->data; }
  345. template<class TYPE,class ARG_TYPE>
  346. inline TYPE CDXList<TYPE,ARG_TYPE>::GetHead() const { _ASSERT(m_pNodeHead!=NULL); return m_pNodeHead->data; }
  347. template<class TYPE,class ARG_TYPE>
  348. inline TYPE &CDXList<TYPE,ARG_TYPE>::GetTail() { _ASSERT(m_pNodeTail!=NULL); return m_pNodeTail->data; }
  349. template<class TYPE,class ARG_TYPE>
  350. inline TYPE CDXList<TYPE,ARG_TYPE>::GetTail() const { _ASSERT(m_pNodeTail!=NULL); return m_pNodeTail->data; }
  351. template<class TYPE,class ARG_TYPE>
  352. inline DXLISTPOS CDXList<TYPE,ARG_TYPE>::GetHeadPosition() const { return (DXLISTPOS) m_pNodeHead; }
  353. template<class TYPE,class ARG_TYPE>
  354. inline DXLISTPOS CDXList<TYPE,ARG_TYPE>::GetTailPosition() const { return (DXLISTPOS) m_pNodeTail; }
  355. template<class TYPE,class ARG_TYPE>
  356. inline TYPE &CDXList<TYPE,ARG_TYPE>::GetNext(DXLISTPOS &rPosition) {
  357. CNode *pNode = (CNode *) rPosition;
  358. _ASSERT(DXIsValidAddress(pNode,sizeof(CNode),TRUE));
  359. rPosition = (DXLISTPOS) pNode->pNext;
  360. return pNode->data;
  361. }
  362. template<class TYPE,class ARG_TYPE>
  363. inline TYPE CDXList<TYPE,ARG_TYPE>::GetNext(DXLISTPOS &rPosition) const {
  364. CNode *pNode = (CNode *) rPosition;
  365. _ASSERT(DXIsValidAddress(pNode,sizeof(CNode),TRUE));
  366. rPosition = (DXLISTPOS) pNode->pNext;
  367. return pNode->data;
  368. }
  369. template<class TYPE,class ARG_TYPE>
  370. inline TYPE &CDXList<TYPE,ARG_TYPE>::GetPrev(DXLISTPOS &rPosition) {
  371. CNode *pNode = (CNode *) rPosition;
  372. _ASSERT(DXIsValidAddress(pNode,sizeof(CNode),TRUE));
  373. rPosition = (DXLISTPOS) pNode->pPrev;
  374. return pNode->data;
  375. }
  376. template<class TYPE,class ARG_TYPE>
  377. inline TYPE CDXList<TYPE,ARG_TYPE>::GetPrev(DXLISTPOS &rPosition) const {
  378. CNode *pNode = (CNode *) rPosition;
  379. _ASSERT(DXIsValidAddress(pNode,sizeof(CNode),TRUE));
  380. rPosition = (DXLISTPOS) pNode->pPrev;
  381. return pNode->data;
  382. }
  383. template<class TYPE,class ARG_TYPE>
  384. inline TYPE &CDXList<TYPE,ARG_TYPE>::GetAt(DXLISTPOS position) {
  385. CNode *pNode = (CNode *) position;
  386. _ASSERT(DXIsValidAddress(pNode,sizeof(CNode),TRUE));
  387. return pNode->data;
  388. }
  389. template<class TYPE,class ARG_TYPE>
  390. inline TYPE CDXList<TYPE,ARG_TYPE>::GetAt(DXLISTPOS position) const {
  391. CNode *pNode = (CNode *) position;
  392. _ASSERT(DXIsValidAddress(pNode,sizeof(CNode),TRUE));
  393. return pNode->data;
  394. }
  395. template<class TYPE,class ARG_TYPE>
  396. inline void CDXList<TYPE,ARG_TYPE>::SetAt(DXLISTPOS pos,ARG_TYPE newElement) {
  397. CNode *pNode = (CNode *) pos;
  398. _ASSERT(DXIsValidAddress(pNode,sizeof(CNode),TRUE));
  399. pNode->data = newElement;
  400. }
  401. template<class TYPE,class ARG_TYPE>
  402. CDXList<TYPE,ARG_TYPE>::CDXList(int nBlockSize) {
  403. _ASSERT(nBlockSize > 0);
  404. m_nCount = 0;
  405. m_pNodeHead = m_pNodeTail = m_pNodeFree = NULL;
  406. m_pBlocks = NULL;
  407. m_nBlockSize = nBlockSize;
  408. }
  409. template<class TYPE,class ARG_TYPE>
  410. void CDXList<TYPE,ARG_TYPE>::RemoveAll() {
  411. DXASSERT_VALID(this);
  412. CNode *pNode;
  413. for(pNode = m_pNodeHead;pNode!=NULL;pNode = pNode->pNext)
  414. DXDestructElements(&pNode->data,1);
  415. m_nCount = 0;
  416. m_pNodeHead = m_pNodeTail = m_pNodeFree = NULL;
  417. m_pBlocks->FreeDataChain();
  418. m_pBlocks = NULL;
  419. }
  420. template<class TYPE,class ARG_TYPE>
  421. CDXList<TYPE,ARG_TYPE>::~CDXList() {
  422. RemoveAll();
  423. _ASSERT(m_nCount==0);
  424. }
  425. template<class TYPE,class ARG_TYPE>
  426. typename CDXList<TYPE,ARG_TYPE>::CNode *
  427. CDXList<TYPE,ARG_TYPE>::NewNode(CNode *pPrev,CNode *pNext) {
  428. if(!m_pNodeFree) {
  429. CDXPlex *pNewBlock = CDXPlex::Create(m_pBlocks,m_nBlockSize,sizeof(CNode));
  430. CNode *pNode = (CNode *) pNewBlock->data();
  431. pNode += m_nBlockSize - 1;
  432. for(int i = m_nBlockSize-1;i >= 0;i--,pNode--) {
  433. pNode->pNext = m_pNodeFree;
  434. m_pNodeFree = pNode;
  435. }
  436. }
  437. _ASSERT(m_pNodeFree!=NULL);
  438. CDXList::CNode *pNode = m_pNodeFree;
  439. m_pNodeFree = m_pNodeFree->pNext;
  440. pNode->pPrev = pPrev;
  441. pNode->pNext = pNext;
  442. m_nCount++;
  443. _ASSERT(m_nCount > 0);
  444. DXConstructElements(&pNode->data,1);
  445. return pNode;
  446. }
  447. template<class TYPE,class ARG_TYPE>
  448. void CDXList<TYPE,ARG_TYPE>::FreeNode(CNode *pNode) {
  449. DXDestructElements(&pNode->data,1);
  450. pNode->pNext = m_pNodeFree;
  451. m_pNodeFree = pNode;
  452. m_nCount--;
  453. _ASSERT(m_nCount >= 0);
  454. }
  455. template<class TYPE,class ARG_TYPE>
  456. DXLISTPOS CDXList<TYPE,ARG_TYPE>::AddHead(ARG_TYPE newElement) {
  457. DXASSERT_VALID(this);
  458. CNode *pNewNode = NewNode(NULL,m_pNodeHead);
  459. pNewNode->data = newElement;
  460. if(m_pNodeHead!=NULL) m_pNodeHead->pPrev = pNewNode;
  461. else m_pNodeTail = pNewNode;
  462. m_pNodeHead = pNewNode;
  463. return (DXLISTPOS) pNewNode;
  464. }
  465. template<class TYPE,class ARG_TYPE>
  466. DXLISTPOS CDXList<TYPE,ARG_TYPE>::AddTail(ARG_TYPE newElement) {
  467. DXASSERT_VALID(this);
  468. CNode *pNewNode = NewNode(m_pNodeTail,NULL);
  469. pNewNode->data = newElement;
  470. if(m_pNodeTail!=NULL) m_pNodeTail->pNext = pNewNode;
  471. else m_pNodeHead = pNewNode;
  472. m_pNodeTail = pNewNode;
  473. return (DXLISTPOS) pNewNode;
  474. }
  475. template<class TYPE,class ARG_TYPE>
  476. void CDXList<TYPE,ARG_TYPE>::AddHead(CDXList *pNewList) {
  477. DXASSERT_VALID(this);
  478. DXASSERT_VALID(pNewList);
  479. DXLISTPOS pos = pNewList->GetTailPosition();
  480. while(pos!=NULL)
  481. AddHead(pNewList->GetPrev(pos));
  482. }
  483. template<class TYPE,class ARG_TYPE>
  484. void CDXList<TYPE,ARG_TYPE>::AddTail(CDXList *pNewList) {
  485. DXASSERT_VALID(this);
  486. DXASSERT_VALID(pNewList);
  487. DXLISTPOS pos = pNewList->GetHeadPosition();
  488. while(pos!=NULL)
  489. AddTail(pNewList->GetNext(pos));
  490. }
  491. template<class TYPE,class ARG_TYPE>
  492. TYPE CDXList<TYPE,ARG_TYPE>::RemoveHead() {
  493. DXASSERT_VALID(this);
  494. _ASSERT(m_pNodeHead!=NULL);
  495. _ASSERT(DXIsValidAddress(m_pNodeHead,sizeof(CNode),TRUE));
  496. CNode *pOldNode = m_pNodeHead;
  497. TYPE returnValue = pOldNode->data;
  498. m_pNodeHead = pOldNode->pNext;
  499. if(m_pNodeHead!=NULL) m_pNodeHead->pPrev = NULL;
  500. else m_pNodeTail = NULL;
  501. FreeNode(pOldNode);
  502. return returnValue;
  503. }
  504. template<class TYPE,class ARG_TYPE>
  505. TYPE CDXList<TYPE,ARG_TYPE>::RemoveTail() {
  506. DXASSERT_VALID(this);
  507. _ASSERT(m_pNodeTail!=NULL);
  508. _ASSERT(DXIsValidAddress(m_pNodeTail,sizeof(CNode),TRUE));
  509. CNode *pOldNode = m_pNodeTail;
  510. TYPE returnValue = pOldNode->data;
  511. m_pNodeTail = pOldNode->pPrev;
  512. if(m_pNodeTail!=NULL) m_pNodeTail->pNext = NULL;
  513. else m_pNodeHead = NULL;
  514. FreeNode(pOldNode);
  515. return returnValue;
  516. }
  517. template<class TYPE,class ARG_TYPE>
  518. DXLISTPOS CDXList<TYPE,ARG_TYPE>::InsertBefore(DXLISTPOS position,ARG_TYPE newElement) {
  519. DXASSERT_VALID(this);
  520. if(!position) return AddHead(newElement);
  521. CNode *pOldNode = (CNode *) position;
  522. CNode *pNewNode = NewNode(pOldNode->pPrev,pOldNode);
  523. pNewNode->data = newElement;
  524. if(pOldNode->pPrev!=NULL) {
  525. _ASSERT(DXIsValidAddress(pOldNode->pPrev,sizeof(CNode),TRUE));
  526. pOldNode->pPrev->pNext = pNewNode;
  527. } else {
  528. _ASSERT(pOldNode==m_pNodeHead);
  529. m_pNodeHead = pNewNode;
  530. }
  531. pOldNode->pPrev = pNewNode;
  532. return (DXLISTPOS) pNewNode;
  533. }
  534. template<class TYPE,class ARG_TYPE>
  535. DXLISTPOS CDXList<TYPE,ARG_TYPE>::InsertAfter(DXLISTPOS position,ARG_TYPE newElement) {
  536. DXASSERT_VALID(this);
  537. if(!position) return AddTail(newElement);
  538. CNode *pOldNode = (CNode *) position;
  539. _ASSERT(DXIsValidAddress(pOldNode,sizeof(CNode),TRUE));
  540. CNode *pNewNode = NewNode(pOldNode,pOldNode->pNext);
  541. pNewNode->data = newElement;
  542. if(pOldNode->pNext!=NULL) {
  543. _ASSERT(DXIsValidAddress(pOldNode->pNext,sizeof(CNode),TRUE));
  544. pOldNode->pNext->pPrev = pNewNode;
  545. } else {
  546. _ASSERT(pOldNode==m_pNodeTail);
  547. m_pNodeTail = pNewNode;
  548. }
  549. pOldNode->pNext = pNewNode;
  550. return (DXLISTPOS) pNewNode;
  551. }
  552. template<class TYPE,class ARG_TYPE>
  553. void CDXList<TYPE,ARG_TYPE>::RemoveAt(DXLISTPOS position) {
  554. DXASSERT_VALID(this);
  555. CNode *pOldNode = (CNode *) position;
  556. _ASSERT(DXIsValidAddress(pOldNode,sizeof(CNode),TRUE));
  557. if(pOldNode==m_pNodeHead) {
  558. m_pNodeHead = pOldNode->pNext;
  559. } else {
  560. _ASSERT(DXIsValidAddress(pOldNode->pPrev,sizeof(CNode),TRUE));
  561. pOldNode->pPrev->pNext = pOldNode->pNext;
  562. }
  563. if(pOldNode==m_pNodeTail) m_pNodeTail = pOldNode->pPrev;
  564. else {
  565. _ASSERT(DXIsValidAddress(pOldNode->pNext,sizeof(CNode),TRUE));
  566. pOldNode->pNext->pPrev = pOldNode->pPrev;
  567. }
  568. FreeNode(pOldNode);
  569. }
  570. template<class TYPE,class ARG_TYPE>
  571. DXLISTPOS CDXList<TYPE,ARG_TYPE>::FindIndex(int nIndex) const {
  572. DXASSERT_VALID(this);
  573. _ASSERT(nIndex >= 0);
  574. if(nIndex >= m_nCount) return NULL;
  575. CNode *pNode = m_pNodeHead;
  576. while(nIndex--) {
  577. _ASSERT(DXIsValidAddress(pNode,sizeof(CNode),TRUE));
  578. pNode = pNode->pNext;
  579. }
  580. return (DXLISTPOS) pNode;
  581. }
  582. template<class TYPE,class ARG_TYPE>
  583. DXLISTPOS CDXList<TYPE,ARG_TYPE>::Find(ARG_TYPE searchValue,DXLISTPOS startAfter) const {
  584. DXASSERT_VALID(this);
  585. CNode *pNode = (CNode *) startAfter;
  586. if(!pNode) pNode = m_pNodeHead;
  587. else {
  588. _ASSERT(DXIsValidAddress(pNode,sizeof(CNode),TRUE));
  589. pNode = pNode->pNext;
  590. }
  591. for(;pNode!=NULL;pNode = pNode->pNext)
  592. if(DXCompareElements(&pNode->data,&searchValue)) return (DXLISTPOS)pNode;
  593. return NULL;
  594. }
  595. #ifdef _DEBUG
  596. template<class TYPE,class ARG_TYPE>
  597. void CDXList<TYPE,ARG_TYPE>::AssertValid() const {
  598. if(!m_nCount) {
  599. _ASSERT(!m_pNodeHead);
  600. _ASSERT(!m_pNodeTail);
  601. } else {
  602. _ASSERT(DXIsValidAddress(m_pNodeHead,sizeof(CNode),TRUE));
  603. _ASSERT(DXIsValidAddress(m_pNodeTail,sizeof(CNode),TRUE));
  604. }
  605. }
  606. #endif
  607. template<class KEY,class ARG_KEY,class VALUE,class ARG_VALUE>
  608. class CDXMap {
  609. protected:
  610. struct CAssoc {
  611. CAssoc *pNext;
  612. UINT nHashValue;
  613. KEY key;
  614. VALUE value;
  615. };
  616. public:
  617. CDXMap(int nBlockSize = 10);
  618. int GetCount() const;
  619. WINBOOL IsEmpty() const;
  620. WINBOOL Lookup(ARG_KEY key,VALUE& rValue) const;
  621. VALUE& operator[](ARG_KEY key);
  622. void SetAt(ARG_KEY key,ARG_VALUE newValue);
  623. WINBOOL RemoveKey(ARG_KEY key);
  624. void RemoveAll();
  625. DXLISTPOS GetStartPosition() const;
  626. void GetNextAssoc(DXLISTPOS &rNextPosition,KEY& rKey,VALUE& rValue) const;
  627. UINT GetHashTableSize() const;
  628. void InitHashTable(UINT hashSize,WINBOOL bAllocNow = TRUE);
  629. protected:
  630. CAssoc **m_pHashTable;
  631. UINT m_nHashTableSize;
  632. int m_nCount;
  633. CAssoc *m_pFreeList;
  634. struct CDXPlex *m_pBlocks;
  635. int m_nBlockSize;
  636. CAssoc *NewAssoc();
  637. void FreeAssoc(CAssoc*);
  638. CAssoc *GetAssocAt(ARG_KEY,UINT&) const;
  639. public:
  640. ~CDXMap();
  641. #ifdef _DEBUG
  642. void AssertValid() const;
  643. #endif
  644. };
  645. template<class KEY,class ARG_KEY,class VALUE,class ARG_VALUE>
  646. inline int CDXMap<KEY,ARG_KEY,VALUE,ARG_VALUE>::GetCount() const { return m_nCount; }
  647. template<class KEY,class ARG_KEY,class VALUE,class ARG_VALUE>
  648. inline WINBOOL CDXMap<KEY,ARG_KEY,VALUE,ARG_VALUE>::IsEmpty() const { return m_nCount==0; }
  649. template<class KEY,class ARG_KEY,class VALUE,class ARG_VALUE>
  650. inline void CDXMap<KEY,ARG_KEY,VALUE,ARG_VALUE>::SetAt(ARG_KEY key,ARG_VALUE newValue) { (*this)[key] = newValue; }
  651. template<class KEY,class ARG_KEY,class VALUE,class ARG_VALUE>
  652. inline DXLISTPOS CDXMap<KEY,ARG_KEY,VALUE,ARG_VALUE>::GetStartPosition() const { return (m_nCount==0) ? NULL : DX_BEFORE_START_POSITION; }
  653. template<class KEY,class ARG_KEY,class VALUE,class ARG_VALUE>
  654. inline UINT CDXMap<KEY,ARG_KEY,VALUE,ARG_VALUE>::GetHashTableSize() const { return m_nHashTableSize; }
  655. template<class KEY,class ARG_KEY,class VALUE,class ARG_VALUE>
  656. CDXMap<KEY,ARG_KEY,VALUE,ARG_VALUE>::CDXMap(int nBlockSize) {
  657. _ASSERT(nBlockSize > 0);
  658. m_pHashTable = NULL;
  659. m_nHashTableSize = 17;
  660. m_nCount = 0;
  661. m_pFreeList = NULL;
  662. m_pBlocks = NULL;
  663. m_nBlockSize = nBlockSize;
  664. }
  665. template<class KEY,class ARG_KEY,class VALUE,class ARG_VALUE>
  666. void CDXMap<KEY,ARG_KEY,VALUE,ARG_VALUE>::InitHashTable(UINT nHashSize,WINBOOL bAllocNow) {
  667. DXASSERT_VALID(this);
  668. _ASSERT(m_nCount==0);
  669. _ASSERT(nHashSize > 0);
  670. if(m_pHashTable!=NULL) {
  671. delete[] m_pHashTable;
  672. m_pHashTable = NULL;
  673. }
  674. if(bAllocNow) {
  675. m_pHashTable = new CAssoc *[nHashSize];
  676. if(!m_pHashTable) return;
  677. memset(m_pHashTable,0,sizeof(CAssoc*) *nHashSize);
  678. }
  679. m_nHashTableSize = nHashSize;
  680. }
  681. template<class KEY,class ARG_KEY,class VALUE,class ARG_VALUE>
  682. void CDXMap<KEY,ARG_KEY,VALUE,ARG_VALUE>::RemoveAll() {
  683. DXASSERT_VALID(this);
  684. if(m_pHashTable!=NULL) {
  685. for(UINT nHash = 0;nHash < m_nHashTableSize;nHash++) {
  686. CAssoc *pAssoc;
  687. for(pAssoc = m_pHashTable[nHash]; pAssoc!=NULL;
  688. pAssoc = pAssoc->pNext)
  689. {
  690. DXDestructElements(&pAssoc->value,1);
  691. DXDestructElements(&pAssoc->key,1);
  692. }
  693. }
  694. }
  695. delete[] m_pHashTable;
  696. m_pHashTable = NULL;
  697. m_nCount = 0;
  698. m_pFreeList = NULL;
  699. m_pBlocks->FreeDataChain();
  700. m_pBlocks = NULL;
  701. }
  702. template<class KEY,class ARG_KEY,class VALUE,class ARG_VALUE>
  703. CDXMap<KEY,ARG_KEY,VALUE,ARG_VALUE>::~CDXMap() {
  704. RemoveAll();
  705. _ASSERT(m_nCount==0);
  706. }
  707. template<class KEY,class ARG_KEY,class VALUE,class ARG_VALUE>
  708. typename CDXMap<KEY,ARG_KEY,VALUE,ARG_VALUE>::CAssoc*
  709. CDXMap<KEY,ARG_KEY,VALUE,ARG_VALUE>::NewAssoc() {
  710. if(!m_pFreeList) {
  711. CDXPlex *newBlock = CDXPlex::Create(m_pBlocks,m_nBlockSize,sizeof(CDXMap::CAssoc));
  712. CDXMap::CAssoc *pAssoc = (CDXMap::CAssoc*) newBlock->data();
  713. pAssoc += m_nBlockSize - 1;
  714. for(int i = m_nBlockSize-1;i >= 0;i--,pAssoc--) {
  715. pAssoc->pNext = m_pFreeList;
  716. m_pFreeList = pAssoc;
  717. }
  718. }
  719. _ASSERT(m_pFreeList!=NULL);
  720. CDXMap::CAssoc *pAssoc = m_pFreeList;
  721. m_pFreeList = m_pFreeList->pNext;
  722. m_nCount++;
  723. _ASSERT(m_nCount > 0);
  724. DXConstructElements(&pAssoc->key,1);
  725. DXConstructElements(&pAssoc->value,1);
  726. return pAssoc;
  727. }
  728. template<class KEY,class ARG_KEY,class VALUE,class ARG_VALUE>
  729. void CDXMap<KEY,ARG_KEY,VALUE,ARG_VALUE>::FreeAssoc(CAssoc *pAssoc) {
  730. DXDestructElements(&pAssoc->value,1);
  731. DXDestructElements(&pAssoc->key,1);
  732. pAssoc->pNext = m_pFreeList;
  733. m_pFreeList = pAssoc;
  734. m_nCount--;
  735. _ASSERT(m_nCount >= 0);
  736. }
  737. template<class KEY,class ARG_KEY,class VALUE,class ARG_VALUE>
  738. typename CDXMap<KEY,ARG_KEY,VALUE,ARG_VALUE>::CAssoc*
  739. CDXMap<KEY,ARG_KEY,VALUE,ARG_VALUE>::GetAssocAt(ARG_KEY key,UINT& nHash) const {
  740. nHash = DXHashKey(key) % m_nHashTableSize;
  741. if(!m_pHashTable) return NULL;
  742. CAssoc *pAssoc;
  743. for(pAssoc = m_pHashTable[nHash];pAssoc!=NULL;pAssoc = pAssoc->pNext) {
  744. if(DXCompareElements(&pAssoc->key,&key)) return pAssoc;
  745. }
  746. return NULL;
  747. }
  748. template<class KEY,class ARG_KEY,class VALUE,class ARG_VALUE>
  749. WINBOOL CDXMap<KEY,ARG_KEY,VALUE,ARG_VALUE>::Lookup(ARG_KEY key,VALUE& rValue) const {
  750. DXASSERT_VALID(this);
  751. UINT nHash;
  752. CAssoc *pAssoc = GetAssocAt(key,nHash);
  753. if(!pAssoc) return FALSE;
  754. rValue = pAssoc->value;
  755. return TRUE;
  756. }
  757. template<class KEY,class ARG_KEY,class VALUE,class ARG_VALUE>
  758. VALUE& CDXMap<KEY,ARG_KEY,VALUE,ARG_VALUE>::operator[](ARG_KEY key) {
  759. DXASSERT_VALID(this);
  760. UINT nHash;
  761. CAssoc *pAssoc;
  762. if(!(pAssoc = GetAssocAt(key,nHash))) {
  763. if(!m_pHashTable) InitHashTable(m_nHashTableSize);
  764. pAssoc = NewAssoc();
  765. pAssoc->nHashValue = nHash;
  766. pAssoc->key = key;
  767. pAssoc->pNext = m_pHashTable[nHash];
  768. m_pHashTable[nHash] = pAssoc;
  769. }
  770. return pAssoc->value;
  771. }
  772. template<class KEY,class ARG_KEY,class VALUE,class ARG_VALUE>
  773. WINBOOL CDXMap<KEY,ARG_KEY,VALUE,ARG_VALUE>::RemoveKey(ARG_KEY key) {
  774. DXASSERT_VALID(this);
  775. if(!m_pHashTable) return FALSE;
  776. CAssoc **ppAssocPrev;
  777. ppAssocPrev = &m_pHashTable[DXHashKey(key) % m_nHashTableSize];
  778. CAssoc *pAssoc;
  779. for(pAssoc = *ppAssocPrev;pAssoc!=NULL;pAssoc = pAssoc->pNext) {
  780. if(DXCompareElements(&pAssoc->key,&key)) {
  781. *ppAssocPrev = pAssoc->pNext;
  782. FreeAssoc(pAssoc);
  783. return TRUE;
  784. }
  785. ppAssocPrev = &pAssoc->pNext;
  786. }
  787. return FALSE;
  788. }
  789. template<class KEY,class ARG_KEY,class VALUE,class ARG_VALUE>
  790. void CDXMap<KEY,ARG_KEY,VALUE,ARG_VALUE>::GetNextAssoc(DXLISTPOS &rNextPosition,KEY& rKey,VALUE& rValue) const {
  791. DXASSERT_VALID(this);
  792. _ASSERT(m_pHashTable!=NULL);
  793. CAssoc *pAssocRet = (CAssoc*)rNextPosition;
  794. _ASSERT(pAssocRet!=NULL);
  795. if(pAssocRet==(CAssoc*) DX_BEFORE_START_POSITION) {
  796. for(UINT nBucket = 0;nBucket < m_nHashTableSize;nBucket++)
  797. if((pAssocRet = m_pHashTable[nBucket])!=NULL)
  798. break;
  799. _ASSERT(pAssocRet!=NULL);
  800. }
  801. _ASSERT(DXIsValidAddress(pAssocRet,sizeof(CAssoc),TRUE));
  802. CAssoc *pAssocNext;
  803. if(!(pAssocNext = pAssocRet->pNext)) {
  804. for(UINT nBucket = pAssocRet->nHashValue + 1;nBucket < m_nHashTableSize;nBucket++)
  805. if((pAssocNext = m_pHashTable[nBucket])!=NULL)
  806. break;
  807. }
  808. rNextPosition = (DXLISTPOS) pAssocNext;
  809. rKey = pAssocRet->key;
  810. rValue = pAssocRet->value;
  811. }
  812. #ifdef _DEBUG
  813. template<class KEY,class ARG_KEY,class VALUE,class ARG_VALUE>
  814. void CDXMap<KEY,ARG_KEY,VALUE,ARG_VALUE>::AssertValid() const {
  815. _ASSERT(m_nHashTableSize > 0);
  816. _ASSERT((m_nCount==0 || m_pHashTable!=NULL));
  817. }
  818. #endif
  819. #endif /* __cplusplus */
  820. #endif