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
|
---|