PTLib  Version 2.12.9
 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 
63  value_type newKey = 0
64  ) : m_key(newKey) { }
65 
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 
154 
155 
157 
158 // Member variables
160 {
165  PINDEX bucket;
166 
168 };
169 
170 class PHashTableInfo : public PBaseArray<PHashTableElement *>
171 {
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;
190 
192 
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 
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
311 };
312 
313 
315 
318 class PAbstractSet : public PHashTable
319 {
320  PCONTAINERINFO(PAbstractSet, PHashTable);
321  public:
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 
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 
568  const T & obj // New object to exclude in the set.
569  ) { this->erase(this->find(obj)); return *this; }
570 
580  const T & key
581  ) const { return this->AbstractContains(key); }
582 
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:
621  : table(NULL)
622  , element(NULL)
623  { }
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 
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:
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:
673  const_iterator(PHashTableInfo * t, const T & k) : iterator_base(t, k) { }
674 
675  public:
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)
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 
751 {
752  PCLASSINFO(PAbstractDictionary, PHashTable);
753  public:
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 
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;
974 
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)); }
1013  const K & key
1014  ) { return dynamic_cast<D &>(this->GetRefAt(key)); }
1015 
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 
1099  PINDEX index
1100  ) const
1101  { return dynamic_cast<D &>(this->AbstractGetDataAt(index)); }
1102 
1106  {
1107  PArray<K> keys;
1108  this->AbstractGetKeys(keys);
1109  return keys;
1110  }
1112 
1115  class iterator;
1116  class const_iterator;
1118  protected:
1119  K * m_internal_first; // Must be first two members
1121 
1124 
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 
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>
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 
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:
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 
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 {
1286  PCLASSINFO(POrdinalDictionary, ParentClass);
1287 
1288  public:
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 
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:
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 ///////////////////////////////////////////////////////////////