DCL 4.0
Loading...
Searching...
No Matches
__HashMapT-MSC.h
Go to the documentation of this file.
1
2/*
3Visual C++ 의 경우 템클레이트 클래스의 맴버 클래스의 맴버들에
4대하여 코드를 생성하지 못하는 버그가 있다.
5
6BUG: LNK2001 on Member Function When Use Nested Class Template
7Last reviewed: July 24, 1997
8Article ID: Q128789
9The information in this article applies to:
10The Microsoft C/C++ Compiler (CL.EXE) included with:
11 - Microsoft Visual C++, 32-bit Edition, versions 2.0, 2.1, 4.0, 4.1, 4.2, 5.0
12*/
13
14#ifndef __DCL_HASH_MAP_T_H__
15#error "Never include <dcl/__HashMapT-MSC.h> directly; use <dcl/HashMapT.h> instead."
16#endif
17
18__DCL_BEGIN_NAMESPACE
19
20#if __DCL_HAVE_THIS_FILE__
21 static const char_t __szHashMap_h__[] = __T("dcl/__HashMapT-MSC.h");
22 #undef __THIS_FILE__
23 #define __THIS_FILE__ __szHashMap_h__
24#endif
25
26template<typename KEY, typename VALUE, typename HASH_FUN = HashFun<KEY> >
27class HashMap : public Object
28{
30public:
31 struct Assoc
32 {
33 KEY key;
34 VALUE value;
35
36 Assoc() {}
37 Assoc(const KEY& _key, const VALUE& _value)
38 {
39 this->key = _key;
40 this->value = _value;
41 }
42 };
43
44 struct HashNode : public Assoc
45 {
46 HashNode* pNext;
47 };
48
49 class ConstIterator;
50 class Iterator
51 {
52 public:
53 Iterator(HashNode* _pNode, HashMap* _pMap)
54 {
55 __pNode = _pNode;
56 __pMap = _pMap;
57 }
58
59 Iterator& operator=(const Iterator& _it)
60 {
61 __pNode = _it.__pNode;
62 __pMap = _it.__pMap;
63 return *this;
64 }
65
66 Iterator& operator++()
67 {
68 __DCL_ASSERT(__pNode != NULL);
69 __DCL_ASSERT(__pMap != NULL);
70
71 const HashNode* pOldNode = __pNode;
72 __pNode = __pNode->pNext;
73 if (__pNode == NULL)
74 {
75 size_t index = __pMap->bucketIndex(pOldNode->key);
76 while((__pNode == NULL) && (++index < __pMap->__buckets.size()))
77 __pNode = (HashNode*)__pMap->__buckets[index];
78 }
79 return *this;
80 }
81
82 Iterator operator++(int)
83 {
84 Iterator itTemp = *this;
85 ++(*this);
86 return itTemp;
87 }
88
89 bool operator==(const Iterator& _it) const
90 {
91 return __pNode != _it.__pNode;
92 }
93
94 bool operator!=(const Iterator& _it) const
95 {
96 return __pNode != _it.__pNode;
97 }
98
99 Assoc& operator*() const
100 {
101 return *__pNode;
102 }
103
104 protected:
105 HashMap* __pMap;
106 HashNode* __pNode;
107 friend typename ConstIterator;
108 };
109
110 class ConstIterator
111 {
112 public:
113 ConstIterator(const HashNode* _pNode, const HashMap* _pMap)
114 {
115 __pNode = _pNode;
116 __pMap = _pMap;
117 }
118
119 ConstIterator(const ConstIterator& _it)
120 {
121 __pNode = _it.__pNode;
122 __pMap = _it.__pMap;
123 }
124
125 ConstIterator(const Iterator& _it)
126 {
127 __pNode = _it.__pNode;
128 __pMap = _it.__pMap;
129 }
130
131 ConstIterator& operator=(const ConstIterator& _it)
132 {
133 __pNode = _it.__pNode;
134 __pMap = _it.__pMap;
135 return *this;
136 }
137
138 ConstIterator& operator++()
139 {
140 __DCL_ASSERT(__pNode != NULL);
141 __DCL_ASSERT(__pMap != NULL);
142
143 const HashNode* pOldNode = __pNode;
144 __pNode = __pNode->pNext;
145 if (__pNode == NULL)
146 {
147 size_t index = __pMap->bucketIndex(pOldNode->key);
148 while((__pNode == NULL) && (++index < __pMap->__buckets.size()))
149 __pNode = (HashNode*)__pMap->__buckets[index];
150 }
151 return *this;
152 }
153
154 ConstIterator operator++(int)
155 {
156 ConstIterator itTemp = *this;
157 ++(*this);
158 return itTemp;
159 }
160
161 bool operator==(const ConstIterator& _it) const
162 {
163 return __pNode == _it.__pNode;
164 }
165
166 bool operator!=(const ConstIterator& _it) const
167 {
168 return __pNode != _it.__pNode;
169 }
170
171 const Assoc& operator*() const
172 {
173 return *__pNode;
174 }
175
176 protected:
177 const HashMap* __pMap;
178 const HashNode* __pNode;
179 };
180
181public:
182 virtual ~HashMap();
183 void initBuckets(size_t _bucketSize);
184 HashMap(size_t _bucketSize = 21);
185
186 HashMap(const HashMap& _src);
187 const HashMap& operator=(const HashMap& _src);
188
189 ConstIterator begin() const;
190 ConstIterator end() const;
191 Iterator begin();
192 Iterator end();
193
194 size_t bucketSize() const;
195 size_t size() const;
196 size_t sizeOfBucket(size_t index) const;
197 bool isEmpty() const;
198 Iterator find(const KEY& _key);
199 ConstIterator find(const KEY& _key) const;
200 bool lookup(const KEY& _key, VALUE& _rValue) const;
201 VALUE& operator[](const KEY& _key);
202 size_t erase(const KEY& _key);
203 size_t erase(const Iterator& _it);
204 void clear();
205
206protected:
207 size_t bucketIndex(const KEY& _key) const;
208 HashNode* createNode(const KEY& _key);
209 void destroyNode(HashNode* _pNode);
210
211protected:
212 HASH_FUN __hashFun;
213 size_t __size; // count of all elements
214 PointerArray __buckets;
215
216 friend class Iterator;
217 friend class ConstIterator;
218};
219
221
222template<typename KEY, typename VALUE, typename HASH_FUN>
223inline
224typename HashMap<KEY, VALUE, HASH_FUN>::Iterator
226{
227 return Iterator(NULL, this);
228}
229
230template<typename KEY, typename VALUE, typename HASH_FUN>
231inline
232typename HashMap<KEY, VALUE, HASH_FUN>::ConstIterator
234{
235 return ConstIterator(NULL, this);
236}
237
238template<typename KEY, typename VALUE, typename HASH_FUN>
239inline
240size_t
242{
243 return __buckets.size();
244}
245
246template<typename KEY, typename VALUE, typename HASH_FUN>
247inline
248size_t
250{
251 return __size;
252}
253
254template<typename KEY, typename VALUE, typename HASH_FUN>
255inline
256bool
258{
259 return __size == 0;
260}
261
263
264// IMPLEMENT_CLASSINFO(HashMap<KEY, VALUE, HASH_FUN>, Object)
265#ifdef __DCL_NO_RTTI
266template<typename KEY, typename VALUE, typename HASH_FUN>
267const Object::ClassInfo HashMap<KEY, VALUE, HASH_FUN>::m_classInfo =
268{
269 __DCL_NAMESPACE_STRING __S(HashMap),
270 sizeof(class HashMap),
271 &Object::m_classInfo
272};
273
274template<typename KEY, typename VALUE, typename HASH_FUN>
275const Object::ClassInfo* HashMap<KEY, VALUE, HASH_FUN>::classInfo() const
276{
277 return CLASSINFO(class_name);
278}
279#else
280template<typename KEY, typename VALUE, typename HASH_FUN>
281const std::type_info& HashMap<KEY, VALUE, HASH_FUN>::typeInfo() const
282{
283 return typeid(HashMap);
284}
285#endif
286
287template<typename KEY, typename VALUE, typename HASH_FUN>
289{
290 clear();
291}
292
293template<typename KEY, typename VALUE, typename HASH_FUN>
294HashMap<KEY, VALUE, HASH_FUN>::HashMap(size_t _bucketSize /* = 10 */)
295 : __buckets(DCLGetNextPrimNumber(_bucketSize))
296{
297 __size = 0;
298// __buckets.resize(DCLGetNextPrimNumber(_bucketSize));
299}
300
301template<typename KEY, typename VALUE, typename HASH_FUN>
302void
304{
305 clear();
306 __buckets.resize(DCLGetNextPrimNumber(_bucketSize));
307}
308
309template<typename KEY, typename VALUE, typename HASH_FUN>
311{
312 *this = _src;
313}
314
315template<typename KEY, typename VALUE, typename HASH_FUN>
318{
319 if (&_src != this)
320 {
321 clear();
322 __size = _src.__size;
323 __buckets.resize(_src.__buckets.size());
324
325 for(size_t index = 0; index < _src.__buckets.size(); index++)
326 {
327 const HashNode* pNode = (HashNode*) _src.__buckets[index];
328 if (pNode != NULL)
329 {
330 HashNode* pNewNode = createNode(pNode->key);
331 pNewNode->value = pNode->value;
332 __buckets[index] = pNewNode;
333 for(pNode = pNode->pNext; pNode != NULL; pNode = pNode->pNext)
334 {
335 pNewNode->pNext = createNode(pNode->key);
336 pNewNode = pNewNode->pNext;
337 pNewNode->value = pNode->value;
338 }
339 }
340 }
341 }
342 return *this;
343}
344
345template<typename KEY, typename VALUE, typename HASH_FUN>
346typename HashMap<KEY, VALUE, HASH_FUN>::ConstIterator
348{
349 for(size_t i = 0; i < __buckets.size(); i++)
350 {
351 if (__buckets[i] != NULL)
352 return ConstIterator((HashNode*)__buckets[i], this);
353 }
354 return ConstIterator(NULL, this);
355}
356
357template<typename KEY, typename VALUE, typename HASH_FUN>
358typename HashMap<KEY, VALUE, HASH_FUN>::Iterator
360{
361 for(size_t i = 0; i < __buckets.size(); i++)
362 {
363 if (__buckets[i] != NULL)
364 return Iterator((HashNode*)__buckets[i], this);
365 }
366 return Iterator(NULL, this);
367}
368
369template<typename KEY, typename VALUE, typename HASH_FUN>
370size_t
372{
373 __DCL_ASSERT(_index < __buckets.size());
374
375 size_t nCount = 0;
376 HashNode* pNode = (HashNode*)__buckets[_index];
377 for(; pNode != NULL; pNode = pNode->pNext)
378 nCount++;
379 return nCount;
380}
381
382template<typename KEY, typename VALUE, typename HASH_FUN>
383typename HashMap<KEY, VALUE, HASH_FUN>::Iterator
385{
386 size_t index = bucketIndex(_key);
387 HashNode* pNode = (HashNode*)__buckets[index];
388 while (pNode) {
389 if (pNode->key == _key) {
390 break;
391 }
392 pNode = pNode->pNext;
393 }
394 return Iterator(pNode, this);
395}
396
397template<typename KEY, typename VALUE, typename HASH_FUN>
398typename HashMap<KEY, VALUE, HASH_FUN>::ConstIterator
399HashMap<KEY, VALUE, HASH_FUN>::find(const KEY& _key) const
400{
401 size_t index = bucketIndex(_key);
402 const HashNode* pNode = (HashNode*)__buckets[index];
403 while (pNode) {
404 if (pNode->key == _key) {
405 break;
406 }
407 pNode = pNode->pNext;
408 }
409 return ConstIterator(pNode, this);
410}
411
412template<typename KEY, typename VALUE, typename HASH_FUN>
413bool
414HashMap<KEY, VALUE, HASH_FUN>::lookup(const KEY& _key, VALUE& _rValue) const
415{
416 size_t index = bucketIndex(_key);
417 HashNode* pNode = (HashNode*)__buckets[index];
418 while(pNode != NULL) {
419 if (pNode->key == _key) {
420 _rValue = pNode->value;
421 return true;
422 }
423 pNode = pNode->pNext;
424 }
425 return false;
426}
427
428template<typename KEY, typename VALUE, typename HASH_FUN>
429VALUE&
431{
432 size_t index = bucketIndex(_key);
433 HashNode* pFirstNode = (HashNode*)__buckets[index];
434 for(HashNode* pCurrentNode = pFirstNode; pCurrentNode!= NULL;
435 pCurrentNode = pCurrentNode->pNext)
436 {
437 if (pCurrentNode->key == _key)
438 return pCurrentNode->value;
439 }
440
441 HashNode* pNewNode = createNode(_key);
442 pNewNode->pNext = pFirstNode;
443 __buckets[index] = pNewNode;
444 __size++;
445 return pNewNode->value;
446}
447
448template<typename KEY, typename VALUE, typename HASH_FUN>
449inline
450size_t
452{
453 return __hashFun.hashKey(_key) % __buckets.size();
454}
455
456template<typename KEY, typename VALUE, typename HASH_FUN>
457typename HashMap<KEY, VALUE, HASH_FUN>::HashNode*
459{
460 HashNode* pNode = (HashNode*) malloc(sizeof(HashNode));
461 // FIXME!
462 // if (pNode == NULL)
463 // throw new BadAllocException(sizeof(HashNode), __THIS_FILE__, __LINE__);
464 __DCL_ASSERT(pNode != NULL);
465
466 memset(pNode, 0, sizeof(HashNode));
467
468#if __DCL_HAVE_ALLOC_DEBUG
469#undef new
470#endif
471
472 new(&(pNode->key)) KEY;
473 new(&(pNode->value)) VALUE;
474
475#if __DCL_HAVE_ALLOC_DEBUG
476#define new __DCL_DEBUG_NEW
477#endif
478
479 pNode->key = _key;
480 return pNode;
481}
482
483template<typename KEY, typename VALUE, typename HASH_FUN>
484void
486{
487 _pNode->key.~KEY();
488 _pNode->value.~VALUE();
489 free(_pNode);
490}
491
492template<typename KEY, typename VALUE, typename HASH_FUN>
493size_t
495{
496 size_t nErased = 0;
497 size_t index = bucketIndex(_key);
498 HashNode* pCurrentNode = (HashNode*)__buckets[index];
499 if (pCurrentNode != NULL)
500 {
501 if (pCurrentNode->key == _key) // first
502 {
503 __buckets[index] = pCurrentNode->pNext;
504 destroyNode(pCurrentNode);
505 nErased++;
506 __size--;
507 }
508 else
509 {
510 HashNode* pNextNode = pCurrentNode->pNext;
511 while(pNextNode != NULL)
512 {
513 if (pNextNode->key == _key)
514 {
515 pCurrentNode->pNext = pNextNode->pNext;
516 destroyNode(pNextNode);
517 nErased++;
518 __size--;
519 break;
520 }
521 else
522 {
523 pCurrentNode = pNextNode;
524 pNextNode = pCurrentNode->pNext;
525 }
526 }
527 }
528 }
529 return nErased;
530}
531
532template<typename KEY, typename VALUE, typename HASH_FUN>
533void
535{
536 for(size_t i = 0; i < __buckets.size(); i++)
537 {
538 HashNode* pNode = (HashNode*)__buckets[i];
539 while(pNode)
540 {
541 HashNode* pNext = pNode->pNext;
542 destroyNode(pNode);
543 pNode = pNext;
544 }
545 __buckets[i] = NULL;
546 }
547 __size = 0;
548}
549
550#if __DCL_HAVE_THIS_FILE__
551 #undef __THIS_FILE__
552 #define __THIS_FILE__ __T(__FILE__)
553#endif
554
555__DCL_END_NAMESPACE
#define NULL
Definition Config.h:340
wchar_t char_t
Definition Config.h:275
DCLCAPI size_t DCLGetNextPrimNumber(size_t _n)
Definition HashFun.cpp:23
#define DECLARE_CLASSINFO(class_name)
Definition Object.h:210
#define CLASSINFO(class_name)
Definition Object.h:209
#define __DCL_ASSERT(expr)
Definition Object.h:371
#define __T(str)
Definition Object.h:44
void CharsetConvertException *__fields clear()
ConstIterator end() const
virtual ~HashMap()
void clear()
ConstIterator begin() const
Iterator begin()
ConstIterator end() const
PointerArray __buckets
HashNode * createNode(const KEY &_key)
const HashMap & operator=(const HashMap &_src)
const HashMap & operator=(const HashMap &_src)
size_t sizeOfBucket(size_t _index) const
friend class ConstIterator
bool lookup(const KEY &_key, VALUE &_rValue) const
HashMap(size_t _bucketSize=21)
ConstIterator begin() const
VALUE & operator[](const KEY &_key)
void initBuckets(size_t _bucketSize)
virtual ~HashMap()
bool isEmpty() const
size_t size() const
friend class Iterator
size_t sizeOfBucket(size_t index) const
ConstIterator find(const KEY &_key) const
size_t erase(const KEY &_key)
void destroyNode(HashNode *_pNode)
Iterator find(const KEY &_key)
HashMap(const HashMap &_src)
HashNode * createNode(const KEY &_key)
size_t bucketSize() const
Iterator find(const KEY &_key)
Iterator end()
size_t erase(const Iterator &_it)
size_t bucketIndex(const KEY &_key) const
virtual const std::type_info & typeInfo() const
Definition Object.cpp:126