PTLib Version 2.12.9

- Main Page
- Related Pages
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
dict.h
Go to the documentation of this file.
1 /*
2 * dict.h
3 *
4 * Dictionary (hash table) Container classes.
5 *
6 * Portable Tools Library
7 *
8 * Copyright (c) 1993-1998 Equivalence Pty. Ltd.
9 *
10 * The contents of this file are subject to the Mozilla Public License
11 * Version 1.0 (the "License"); you may not use this file except in
12 * compliance with the License. You may obtain a copy of the License at
13 * http://www.mozilla.org/MPL/
14 *
15 * Software distributed under the License is distributed on an "AS IS"
16 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
17 * the License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * The Original Code is Portable Windows Library.
21 *
22 * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
23 *
24 * Portions are Copyright (C) 1993 Free Software Foundation, Inc.
25 * All Rights Reserved.
26 *
27 * Contributor(s): ______________________________________.
28 *
29 * $Revision: 29567 $
30 * $Author: rjongbloed $
31 * $Date: 2013-04-25 13:31:57 +1000 (Thu, 25 Apr 2013) $
32 */
33
34
35 #ifndef PTLIB_DICT_H
36 #define PTLIB_DICT_H
37
38 #ifdef P_USE_PRAGMA
39 #pragma interface
40 #endif
41
42 #include <ptlib/array.h>
43
45 // PDictionary classes
46
50 template <typename T>
51 class PKey : public PObject
52 {
53 PCLASSINFO(PKey, PObject);
54 public:
55 typedef T value_type;
56 typedef PKey<T> my_type;
57
62 PINLINE PKey(
63 value_type newKey = 0
64 ) : m_key(newKey) { }
65
68 PINLINE PKey & operator=(value_type newKey)
69 { this->m_key = newKey; return *this; }
71
74
75 virtual PObject * Clone() const { return new PKey(this->m_key); }
76
77 /* Get the relative rank of the ordinal index. This is a simpel comparison
78 of the objects PINDEX values.
79
80 @return
81 comparison of the two objects, <code>EqualTo</code> for same,
82 <code>LessThan</code> for \p obj logically less than the
83 object and <code>GreaterThan</code> for \p obj logically
84 greater than the object.
85 */
86 virtual Comparison Compare(const PObject & obj) const
87 {
88 const my_type * other = dynamic_cast<const my_type *>(&obj);
89 if (!PAssert(other != NULL, PInvalidCast))
90 return GreaterThan;
91
92 if (this->m_key < other->m_key)
93 return LessThan;
94
95 if (this->m_key > other->m_key)
96 return GreaterThan;
97
98 return EqualTo;
99 }
100
107 virtual PINDEX HashFunction() const { return PABSINDEX(this->m_key)%23; }
108
115 virtual void PrintOn(ostream & strm) const { strm << this->m_key; }
117
122 PINLINE operator value_type() const { return this->m_key; }
123
126 PINLINE value_type operator++() { return ++this->m_key; }
127
130 PINLINE value_type operator++(int) { return this->m_key++; }
131
134 PINLINE value_type operator--() { return --this->m_key; }
135
138 PINLINE value_type operator--(int) { return this->m_key--; }
139
142 PINLINE PKey & operator+=(value_type add) { this->m_key += add; return *this; }
143
146 PINLINE PKey & operator-=(value_type minus) { this->m_key -= minus; return *this; }
148
149 private:
150 value_type m_key;
151 };
152
153 typedef PKey<PINDEX> POrdinalKey;
154
155
157
158 // Member variables
159 struct PHashTableElement
160 {
161 PObject * key;
162 PObject * data;
163 PHashTableElement * next;
164 PHashTableElement * prev;
165 PINDEX bucket;
166
167 PDECLARE_POOL_ALLOCATOR();
168 };
169
170 class PHashTableInfo : public PBaseArray<PHashTableElement *>
171 {
172 typedef PBaseArray<PHashTableElement *> ParentClass;
173 PCLASSINFO(PCharArray, ParentClass);
174 public:
175 PHashTableInfo(PINDEX initialSize = 0)
176 : ParentClass(initialSize) { }
177 PHashTableInfo(PHashTableElement * const * buffer, PINDEX length, PBoolean dynamic = true)
178 : ParentClass(buffer, length, dynamic) { }
179 virtual PObject * Clone() const { return PNEW PHashTableInfo(*this, GetSize()); }
180 virtual ~PHashTableInfo() { Destruct(); }
181 virtual void DestroyContents();
182
183 PINDEX AppendElement(PObject * key, PObject * data);
184 PObject * RemoveElement(const PObject & key);
185 PHashTableElement * GetElementAt(PINDEX index);
186 PHashTableElement * GetElementAt(const PObject & key);
187 PINDEX GetElementsIndex(const PObject*obj,PBoolean byVal,PBoolean keys) const;
188 PHashTableElement * NextElement(PHashTableElement * element) const;
189 PHashTableElement * PrevElement(PHashTableElement * element) const;
190
191 PBoolean deleteKeys;
192
193 typedef PHashTableElement Element;
194 friend class PHashTable;
195 friend class PAbstractSet;
196 };
197
198
209 class PHashTable : public PCollection
210 {
211 PCONTAINERINFO(PHashTable, PCollection);
212
213 public:
216
217 PHashTable();
219
231 virtual Comparison Compare(
232 const PObject & obj
233 ) const;
235
236
246 virtual PBoolean SetSize(
247 PINDEX newSize
248 );
250
251
262 PINLINE PBoolean AbstractContains(
263 const PObject & key
264 ) const;
265
282 virtual const PObject & AbstractGetKeyAt(
283 PINDEX index
284 ) const;
285
302 virtual PObject & AbstractGetDataAt(
303 PINDEX index
304 ) const;
306
307 // The type below cannot be nested as DevStudio 2005 AUTOEXP.DAT doesn't like it
308 typedef PHashTableElement Element;
309 typedef PHashTableInfo Table;
310 PHashTableInfo * hashTable;
311 };
312
313
315
318 class PAbstractSet : public PHashTable
319 {
320 PCONTAINERINFO(PAbstractSet, PHashTable);
321 public:
329 PINLINE PAbstractSet();
331
342 virtual PINDEX Append(
343 PObject * obj
344 );
345
358 virtual PINDEX Insert(
359 const PObject & before,
360 PObject * obj
361 );
362
375 virtual PINDEX InsertAt(
376 PINDEX index,
377 PObject * obj
378 );
379
390 virtual PBoolean Remove(
391 const PObject * obj
392 );
393
405 virtual PObject * RemoveAt(
406 PINDEX index
407 );
408
419 virtual PObject * GetAt(
420 PINDEX index
421 ) const;
422
435 virtual PBoolean SetAt(
436 PINDEX index,
437 PObject * val
438 );
439
451 virtual PINDEX GetObjectsIndex(
452 const PObject * obj
453 ) const;
454
463 virtual PINDEX GetValuesIndex(
464 const PObject & obj
465 ) const;
466
470 bool Union(
471 const PAbstractSet & set
472 );
473
477 static bool Intersection(
478 const PAbstractSet & set1,
479 const PAbstractSet & set2,
480 PAbstractSet * intersection = NULL
481 );
483 };
484
485
496 template <class T> class PSet : public PAbstractSet
497 {
498 PCLASSINFO(PSet, PAbstractSet);
499
500 public:
510 inline PSet(PBoolean initialDeleteObjects = false)
511 : PAbstractSet() { this->AllowDeleteObjects(initialDeleteObjects); }
513
519 virtual PObject * Clone() const
520 { return PNEW PSet(0, this); }
522
534 void Include(
535 const T * obj // New object to include in the set.
536 ) { this->Append((PObject *)obj); }
537
545 PSet & operator+=(
546 const T & obj // New object to include in the set.
547 ) { this->Append(obj.Clone()); return *this; }
548
556 void Exclude(
557 const T * obj // New object to exclude in the set.
558 ) { this->Remove(obj); }
559
567 PSet & operator-=(
568 const T & obj // New object to exclude in the set.
569 ) { this->erase(this->find(obj)); return *this; }
570
579 PBoolean Contains(
580 const T & key
581 ) const { return this->AbstractContains(key); }
582
591 PBoolean operator[](
592 const T & key
593 ) const { return this->AbstractContains(key); }
594
608 virtual const T & GetKeyAt(
609 PINDEX index
610 ) const
611 { return dynamic_cast<const T &>(this->AbstractGetKeyAt(index)); }
613
616 class iterator;
617 class const_iterator;
618 class iterator_base : public std::iterator<std::forward_iterator_tag, T> {
619 protected:
620 iterator_base()
621 : table(NULL)
622 , element(NULL)
623 { }
624 iterator_base(PHashTableInfo * t)
625 : table(t)
626 , element(t->GetElementAt((PINDEX)0))
627 { }
628 iterator_base(PHashTableInfo * t, const T & k)
629 : table(t)
630 , element(t->GetElementAt(k))
631 { }
632
633 PHashTableInfo * table;
634 PHashTableElement * element;
635
636 void Next() { this->element = PAssertNULL(this->table)->NextElement(this->element); }
637 void Prev() { this->element = PAssertNULL(this->table)->PrevElement(this->element); }
638
639 T * Ptr() const { return dynamic_cast<T *>(PAssertNULL(this->element)->key); }
640
641 public:
642 bool operator==(const iterator_base & it) const { return this->element == it.element; }
643 bool operator!=(const iterator_base & it) const { return this->element != it.element; }
644 };
645
646 class iterator : public iterator_base {
647 protected:
648 iterator(PHashTableInfo * t) : iterator_base(t) { }
649 iterator(PHashTableInfo * t, const T & k) : iterator_base(t, k) { }
650
651 public:
652 iterator() { }
653
654 iterator operator++() { this->Next(); return *this; }
655 iterator operator--() { this->Prev(); return *this; }
656 iterator operator++(int) { iterator it = *this; this->Next(); return it; }
657 iterator operator--(int) { iterator it = *this; this->Prev(); return it; }
658
659 T * operator->() const { return this->Ptr(); }
660 T & operator* () const { return *this->Ptr(); }
661
662 friend class PSet<T>;
663 };
664
665 iterator begin() { return iterator(this->hashTable); }
666 iterator end() { return iterator(); }
667 iterator find(const T & k) { return iterator(this->hashTable, k); }
668
669
670 class const_iterator : public iterator_base {
671 protected:
672 const_iterator(PHashTableInfo * t) : iterator_base(t) { }
673 const_iterator(PHashTableInfo * t, const T & k) : iterator_base(t, k) { }
674
675 public:
676 const_iterator() { }
677
678 const_iterator operator++() { this->Next(); return *this; }
679 const_iterator operator--() { this->Prev(); return *this; }
680 const_iterator operator++(int) { const_iterator it = *this; this->Next(); return it; }
681 const_iterator operator--(int) { const_iterator it = *this; this->Prev(); return it; }
682
683 const T * operator->() const { return this->Ptr(); }
684 const T & operator* () const { return *this->Ptr(); }
685
686 friend class PSet<T>;
687 };
688
689 const_iterator begin() const { return const_iterator(this->hashTable); }
690 const_iterator end() const { return const_iterator(); }
691 const_iterator find(const T & k) const { return const_iterator(this->hashTable, k); }
692
693 void erase(const iterator & it) { this->Remove(&*it); }
694 void erase(const const_iterator & it) { this->Remove(&*it); }
696
697 protected:
698 PSet(int dummy, const PSet * c)
699 : PAbstractSet(dummy, c)
700 { this->reference->deleteObjects = c->reference->deleteObjects; }
701 };
702
703
715 #define PSET(cls, T) typedef PSet<T> cls
716
717
729 #define PDECLARE_SET(cls, T, initDelObj) \
730 class cls : public PSet<T> { \
731 typedef PSet<T> BaseClass; PCLASSINFO(cls, BaseClass) \
732 protected: \
733 cls(int dummy, const cls * c) \
734 : BaseClass(dummy, c) { } \
735 public: \
736 cls(PBoolean initialDeleteObjects = initDelObj) \
737 : BaseClass(initialDeleteObjects) { } \
738 virtual PObject * Clone() const \
739 { return PNEW cls(0, this); } \
740
741
743 PDECLARE_SET(POrdinalSet, POrdinalKey, true)
744 };
745
747
750 class PAbstractDictionary : public PHashTable
751 {
752 PCLASSINFO(PAbstractDictionary, PHashTable);
753 public:
761 PINLINE PAbstractDictionary();
763
772 virtual void PrintOn(
773 ostream &strm
774 ) const;
776
787 virtual PINDEX Insert(
788 const PObject & key,
789 PObject * obj
790 );
791
798 virtual PINDEX InsertAt(
799 PINDEX index,
800 PObject * obj
801 );
802
812 virtual PObject * RemoveAt(
813 PINDEX index
814 );
815
824 virtual PBoolean SetAt(
825 PINDEX index,
826 PObject * val
827 );
828
835 virtual PObject * GetAt(
836 PINDEX index
837 ) const;
838
850 virtual PINDEX GetObjectsIndex(
851 const PObject * obj
852 ) const;
853
862 virtual PINDEX GetValuesIndex(
863 const PObject & obj
864 ) const;
866
867
878 P_DEPRECATED virtual PBoolean SetDataAt(
879 PINDEX index,
880 PObject * obj
881 );
882
894 virtual PObject * AbstractSetAt(
895 const PObject & key,
896 PObject * obj
897 );
898
908 virtual PObject & GetRefAt(
909 const PObject & key
910 ) const;
911
918 virtual PObject * AbstractGetAt(
919 const PObject & key
920 ) const;
921
924 virtual void AbstractGetKeys(
925 PArrayObjects & keys
926 ) const;
928
929 protected:
930 PINLINE PAbstractDictionary(int dummy, const PAbstractDictionary * c);
931
932 private:
938 virtual PINDEX Append(
939 PObject * obj
940 );
941
952 virtual PBoolean Remove(
953 const PObject * obj
954 );
955
956 };
957
958
966 template <class K, class D> class PDictionary : public PAbstractDictionary
967 {
968 PCLASSINFO(PDictionary, PAbstractDictionary);
969
970 public:
971 typedef K key_type;
972 typedef D data_type;
973 typedef PDictionary<K, D> dict_type;
974
983 PDictionary()
984 : PAbstractDictionary() { }
986
993 virtual PObject * Clone() const
994 { return PNEW PDictionary(0, this); }
996
1009 const D & operator[](
1010 const K & key
1011 ) const { return dynamic_cast<const D &>(this->GetRefAt(key)); }
1012 D & operator[](
1013 const K & key
1014 ) { return dynamic_cast<D &>(this->GetRefAt(key)); }
1015
1024 PBoolean Contains(
1025 const K & key
1026 ) const { return this->AbstractContains(key); }
1027
1037 virtual D * RemoveAt(
1038 const K & key
1039 ) { return dynamic_cast<D *>(this->AbstractSetAt(key, NULL)); }
1040
1052 virtual PBoolean SetAt(
1053 const K & key, // Key for position in dictionary to add object.
1054 D * obj // New object to put into the dictionary.
1055 ) { return this->AbstractSetAt(key, obj) != NULL; }
1056
1063 virtual D * GetAt(
1064 const K & key // Key for position in dictionary to get object.
1065 ) const { return dynamic_cast<D *>(this->AbstractGetAt(key)); }
1066
1080 const K & GetKeyAt(
1081 PINDEX index
1082 ) const
1083 { return dynamic_cast<const K &>(this->AbstractGetKeyAt(index)); }
1084
1098 D & GetDataAt(
1099 PINDEX index
1100 ) const
1101 { return dynamic_cast<D &>(this->AbstractGetDataAt(index)); }
1102
1105 PArray<K> GetKeys() const
1106 {
1107 PArray<K> keys;
1108 this->AbstractGetKeys(keys);
1109 return keys;
1110 }
1112
1115 class iterator;
1116 class const_iterator;
1117 class iterator_base {
1118 protected:
1119 K * m_internal_first; // Must be first two members
1120 D * m_internal_second;
1121
1122 PHashTableInfo * m_table;
1123 PHashTableElement * m_element;
1124
1125 iterator_base()
1126 : m_internal_first(NULL)
1127 , m_internal_second(NULL)
1128 , m_table(NULL)
1129 , m_element(NULL)
1130 {
1131 }
1132
1133 iterator_base(const dict_type * dict)
1134 : m_table(dict->hashTable)
1135 {
1136 this->SetElement(this->m_table->GetElementAt((PINDEX)0));
1137 }
1138
1139 iterator_base(const dict_type * dict, const K & key)
1140 : m_table(dict->hashTable)
1141 {
1142 this->SetElement(this->m_table->GetElementAt(key));
1143 }
1144
1145 void SetElement(PHashTableElement * element)
1146 {
1147 this->m_element = element;
1148 if (element != NULL) {
1149 this->m_internal_first = dynamic_cast<K *>(element->key);
1150 this->m_internal_second = dynamic_cast<D *>(element->data);
1151 }
1152 else {
1153 this->m_internal_first = NULL;
1154 this->m_internal_second = NULL;
1155 }
1156 }
1157
1158 void Next() { this->SetElement(PAssertNULL(this->m_table)->NextElement(this->m_element)); }
1159 void Prev() { this->SetElement(PAssertNULL(this->m_table)->PrevElement(this->m_element)); }
1160
1161 public:
1162 bool operator==(const iterator_base & it) const { return this->m_element == it.m_element; }
1163 bool operator!=(const iterator_base & it) const { return this->m_element != it.m_element; }
1164 };
1165
1166 template<class CK, class CD>
1167 class iterator_pair {
1168 public:
1169 CK & first;
1170 CD & second;
1171
1172 private:
1173 iterator_pair() : first(reinterpret_cast<CK&>(0)), second(reinterpret_cast<CD&>(0)) { }
1174 };
1175
1176 class iterator : public iterator_base, public std::iterator<std::forward_iterator_tag, iterator_pair<K,D> > {
1177 protected:
1178 iterator(dict_type * dict) : iterator_base(dict) { }
1179 iterator(dict_type * dict, const K & key) : iterator_base(dict, key) { }
1180
1181 public:
1182 iterator() { }
1183
1184 iterator operator++() { this->Next(); return *this; }
1185 iterator operator--() { this->Prev(); return *this; }
1186 iterator operator++(int) { iterator it = *this; this->Next(); return it; }
1187 iterator operator--(int) { iterator it = *this; this->Prev(); return it; }
1188
1189 typedef iterator_pair<K,D> pair;
1190 const pair * operator->() const { return reinterpret_cast<const pair *>(this); }
1191 const pair & operator* () const { return *reinterpret_cast<const pair *>(this); }
1192
1193 friend class PDictionary<K, D>;
1194 };
1195
1196 iterator begin() { return iterator(this); }
1197 iterator end() { return iterator(); }
1198 iterator find(const K & key) { return iterator(this, key); }
1199
1200
1201 class const_iterator : public iterator_base, public std::iterator<std::forward_iterator_tag, iterator_pair<const K,const D> > {
1202 protected:
1203 const_iterator(const dict_type * dict) : iterator_base(dict) { }
1204 const_iterator(const dict_type * dict, const K & key) : iterator_base(dict, key) { }
1205
1206 public:
1207 const_iterator() { }
1208 const_iterator(iterator it) : iterator_base(it) { }
1209
1210 const_iterator operator++() { this->Next(); return *this; }
1211 const_iterator operator--() { this->Prev(); return *this; }
1212 const_iterator operator++(int) { const_iterator it = *this; this->Next(); return it; }
1213 const_iterator operator--(int) { const_iterator it = *this; this->Prev(); return it; }
1214
1215 typedef iterator_pair<const K, const D> pair;
1216 const pair * operator->() const { return reinterpret_cast<const pair *>(this); }
1217 const pair & operator* () const { return *reinterpret_cast<const pair *>(this); }
1218
1219 friend class PDictionary<K, D>;
1220 };
1221
1222 const_iterator begin() const { return const_iterator(this); }
1223 const_iterator end() const { return const_iterator(); }
1224 const_iterator find(const K & k) const { return const_iterator(this, k); }
1225
1226 void erase(const iterator & it) { this->AbstractSetAt(*it.m_element->key, NULL); }
1227 void erase(const const_iterator & it) { this->AbstractSetAt(*it.m_element->key, NULL); }
1229
1230 protected:
1231 PDictionary(int dummy, const PDictionary * c)
1232 : PAbstractDictionary(dummy, c) { }
1233 };
1234
1235
1248 #define PDICTIONARY(cls, K, D) typedef PDictionary<K, D> cls
1249
1250
1263 #define PDECLARE_DICTIONARY(cls, K, D) \
1264 PDICTIONARY(cls##_PTemplate, K, D); \
1265 PDECLARE_CLASS(cls, cls##_PTemplate) \
1266 protected: \
1267 cls(int dummy, const cls * c) \
1268 : cls##_PTemplate(dummy, c) { } \
1269 public: \
1270 cls() \
1271 : cls##_PTemplate() { } \
1272 virtual PObject * Clone() const \
1273 { return PNEW cls(0, this); } \
1274
1275
1283 template <class K> class POrdinalDictionary : public PDictionary<K, POrdinalKey>
1284 {
1285 typedef PDictionary<K, POrdinalKey> ParentClass;
1286 PCLASSINFO(POrdinalDictionary, ParentClass);
1287
1288 public:
1297 POrdinalDictionary()
1298 : ParentClass() { }
1300
1307 virtual PObject * Clone() const
1308 { return PNEW POrdinalDictionary(0, this); }
1310
1323 PINDEX operator[](
1324 const K & key // Key to look for in the dictionary.
1325 ) const
1326 { return dynamic_cast<POrdinalKey &>(this->GetRefAt(key)); }
1327
1341 virtual PBoolean SetDataAt(
1342 PINDEX index,
1343 PINDEX ordinal
1344 ) { return this->AbstractSetAt(this->AbstractGetKeyAt(index), PNEW POrdinalKey(ordinal)) != NULL; }
1345
1357 virtual PBoolean SetAt(
1358 const K & key,
1359 PINDEX ordinal
1360 ) { return this->AbstractSetAt(key, PNEW POrdinalKey(ordinal)) != NULL; }
1361
1375 const K & GetKeyAt(
1376 PINDEX index
1377 ) const
1378 { return dynamic_cast<const K &>(this->AbstractGetKeyAt(index)); }
1379
1396 PINDEX GetDataAt(
1397 PINDEX index
1398 ) const
1399 { return dynamic_cast<POrdinalKey &>(this->AbstractGetDataAt(index)); }
1401
1402 protected:
1403 POrdinalDictionary(int dummy, const POrdinalDictionary * c)
1404 : ParentClass(dummy, c) { }
1405 };
1406
1407
1420 #define PORDINAL_DICTIONARY(cls, K) typedef POrdinalDictionary<K> cls
1421
1422
1437 #define PDECLARE_ORDINAL_DICTIONARY(cls, K) \
1438 PORDINAL_DICTIONARY(cls##_PTemplate, K); \
1439 PDECLARE_CLASS(cls, POrdinalDictionary<K>) \
1440 protected: \
1441 cls(int dummy, const cls * c) \
1442 : cls##_PTemplate(dummy, c) { } \
1443 public: \
1444 cls() \
1445 : cls##_PTemplate() { } \
1446 virtual PObject * Clone() const \
1447 { return PNEW cls(0, this); } \
1448
1449
1450 #endif // PTLIB_DICT_H
1451
1452 // End Of File ///////////////////////////////////////////////////////////////