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