PTLib  Version 2.14.3
 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: 31640 $
30  * $Author: rjongbloed $
31  * $Date: 2014-03-31 14:01:38 +1100 (Mon, 31 Mar 2014) $
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 m_bucket;
166 
168 };
169 
171 {
172  PHashTableList() : m_head(NULL), m_tail(NULL) { }
175 #if PTRACING
176  PINDEX m_size;
177 #endif
178 };
179 __inline std::ostream & operator<<(std::ostream & strm, const PHashTableList & hash) { return strm << (void *)hash.m_head; }
180 
181 class PHashTable;
182 
183 
184 class PHashTableInfo : public PBaseArray<PHashTableList>
185 {
187  PCLASSINFO(PCharArray, ParentClass);
188  public:
189  PHashTableInfo(PINDEX initialSize = 0)
190  : ParentClass(initialSize) { }
191  PHashTableInfo(PHashTableList const * buffer, PINDEX length, PBoolean dynamic = true)
192  : ParentClass(buffer, length, dynamic) { }
193  virtual PObject * Clone() const { return PNEW PHashTableInfo(*this, GetSize()); }
194  virtual ~PHashTableInfo() { Destruct(); }
195  virtual void DestroyContents();
196 
197  void AppendElement(PObject * key, PObject * data PTRACE_PARAM(, PHashTable * owner));
198  PObject * RemoveElement(const PObject & key);
199  PHashTableElement * GetElementAt(PINDEX index);
200  PHashTableElement * GetElementAt(const PObject & key);
201  PINDEX GetElementsIndex(const PObject*obj,PBoolean byVal,PBoolean keys) const;
204 
206 
207  friend class PHashTable;
208  friend class PAbstractSet;
209 };
210 
211 
222 class PHashTable : public PCollection
223 {
224  PCONTAINERINFO(PHashTable, PCollection);
225 
226  public:
229 
230  PHashTable();
232 
244  virtual Comparison Compare(
245  const PObject & obj
246  ) const;
248 
249 
259  virtual PBoolean SetSize(
260  PINDEX newSize
261  );
263 
264 
276  const PObject & key
277  ) const;
278 
295  virtual const PObject & AbstractGetKeyAt(
296  PINDEX index
297  ) const;
298 
315  virtual PObject & AbstractGetDataAt(
316  PINDEX index
317  ) const;
319 
321 };
322 
323 
325 
328 class PAbstractSet : public PHashTable
329 {
330  PCONTAINERINFO(PAbstractSet, PHashTable);
331  public:
341 
352  virtual PINDEX Append(
353  PObject * obj
354  );
355 
368  virtual PINDEX Insert(
369  const PObject & before,
370  PObject * obj
371  );
372 
385  virtual PINDEX InsertAt(
386  PINDEX index,
387  PObject * obj
388  );
389 
400  virtual PBoolean Remove(
401  const PObject * obj
402  );
403 
415  virtual PObject * RemoveAt(
416  PINDEX index
417  );
418 
429  virtual PObject * GetAt(
430  PINDEX index
431  ) const;
432 
445  virtual PBoolean SetAt(
446  PINDEX index,
447  PObject * val
448  );
449 
461  virtual PINDEX GetObjectsIndex(
462  const PObject * obj
463  ) const;
464 
473  virtual PINDEX GetValuesIndex(
474  const PObject & obj
475  ) const;
476 
480  bool Union(
481  const PAbstractSet & set
482  );
483 
487  static bool Intersection(
488  const PAbstractSet & set1,
489  const PAbstractSet & set2,
490  PAbstractSet * intersection = NULL
491  );
493 };
494 
495 
506 template <class T> class PSet : public PAbstractSet
507 {
508  PCLASSINFO(PSet, PAbstractSet);
509 
510  public:
520  inline PSet(PBoolean initialDeleteObjects = false)
521  : PAbstractSet() { this->AllowDeleteObjects(initialDeleteObjects); }
523 
529  virtual PObject * Clone() const
530  { return PNEW PSet(0, this); }
532 
544  void Include(
545  const T * obj // New object to include in the set.
546  ) { this->Append((PObject *)obj); }
547 
556  const T & obj // New object to include in the set.
557  ) { this->Append(obj.Clone()); return *this; }
558 
566  void Exclude(
567  const T * obj // New object to exclude in the set.
568  ) { this->Remove(obj); }
569 
578  const T & obj // New object to exclude in the set.
579  ) { this->erase(this->find(obj)); return *this; }
580 
590  const T & key
591  ) const { return this->AbstractContains(key); }
592 
602  const T & key
603  ) const { return this->AbstractContains(key); }
604 
618  virtual const T & GetKeyAt(
619  PINDEX index
620  ) const
621  { return dynamic_cast<const T &>(this->AbstractGetKeyAt(index)); }
623 
626  class iterator;
627  class const_iterator;
628  class iterator_base : public std::iterator<std::forward_iterator_tag, T> {
629  protected:
631  : table(NULL)
632  , element(NULL)
633  { }
635  : table(t)
636  , element(t->GetElementAt((PINDEX)0))
637  { }
638  iterator_base(PHashTableInfo * t, const T & k)
639  : table(t)
640  , element(t->GetElementAt(k))
641  { }
642 
645 
646  void Next() { this->element = PAssertNULL(this->table)->NextElement(this->element); }
647  void Prev() { this->element = PAssertNULL(this->table)->PrevElement(this->element); }
648 
649  T * Ptr() const { return dynamic_cast<T *>(PAssertNULL(this->element)->m_key); }
650 
651  public:
652  bool operator==(const iterator_base & it) const { return this->element == it.element; }
653  bool operator!=(const iterator_base & it) const { return this->element != it.element; }
654  };
655 
656  class iterator : public iterator_base {
657  protected:
659  iterator(PHashTableInfo * t, const T & k) : iterator_base(t, k) { }
660 
661  public:
662  iterator() { }
663 
664  iterator operator++() { this->Next(); return *this; }
665  iterator operator--() { this->Prev(); return *this; }
666  iterator operator++(int) { iterator it = *this; this->Next(); return it; }
667  iterator operator--(int) { iterator it = *this; this->Prev(); return it; }
668 
669  T * operator->() const { return this->Ptr(); }
670  T & operator* () const { return *this->Ptr(); }
671 
672  friend class PSet<T>;
673  };
674 
675  iterator begin() { return iterator(this->hashTable); }
676  iterator end() { return iterator(); }
677  iterator find(const T & k) { return iterator(this->hashTable, k); }
678 
679 
680  class const_iterator : public iterator_base {
681  protected:
683  const_iterator(PHashTableInfo * t, const T & k) : iterator_base(t, k) { }
684 
685  public:
687 
688  const_iterator operator++() { this->Next(); return *this; }
689  const_iterator operator--() { this->Prev(); return *this; }
690  const_iterator operator++(int) { const_iterator it = *this; this->Next(); return it; }
691  const_iterator operator--(int) { const_iterator it = *this; this->Prev(); return it; }
692 
693  const T * operator->() const { return this->Ptr(); }
694  const T & operator* () const { return *this->Ptr(); }
695 
696  friend class PSet<T>;
697  };
698 
699  const_iterator begin() const { return const_iterator(this->hashTable); }
700  const_iterator end() const { return const_iterator(); }
701  const_iterator find(const T & k) const { return const_iterator(this->hashTable, k); }
702 
703  void erase(const iterator & it) { this->Remove(&*it); }
704  void erase(const const_iterator & it) { this->Remove(&*it); }
706 
707  protected:
708  PSet(int dummy, const PSet * c)
709  : PAbstractSet(dummy, c)
711 };
712 
713 
725 #define PSET(cls, T) typedef PSet<T> cls
726 
727 
739 #define PDECLARE_SET(cls, T, initDelObj) \
740  class cls : public PSet<T> { \
741  typedef PSet<T> BaseClass; PCLASSINFO(cls, BaseClass) \
742  protected: \
743  cls(int dummy, const cls * c) \
744  : BaseClass(dummy, c) { } \
745  public: \
746  cls(PBoolean initialDeleteObjects = initDelObj) \
747  : BaseClass(initialDeleteObjects) { } \
748  virtual PObject * Clone() const \
749  { return PNEW cls(0, this); } \
750 
751 
753 PDECLARE_SET(POrdinalSet, POrdinalKey, true)
754 };
755 
757 
761 {
762  PCLASSINFO(PAbstractDictionary, PHashTable);
763  public:
773 
782  virtual void PrintOn(
783  ostream &strm
784  ) const;
786 
797  virtual PINDEX Insert(
798  const PObject & key,
799  PObject * obj
800  );
801 
808  virtual PINDEX InsertAt(
809  PINDEX index,
810  PObject * obj
811  );
812 
822  virtual PObject * RemoveAt(
823  PINDEX index
824  );
825 
834  virtual PBoolean SetAt(
835  PINDEX index,
836  PObject * val
837  );
838 
845  virtual PObject * GetAt(
846  PINDEX index
847  ) const;
848 
860  virtual PINDEX GetObjectsIndex(
861  const PObject * obj
862  ) const;
863 
872  virtual PINDEX GetValuesIndex(
873  const PObject & obj
874  ) const;
876 
877 
889  PINDEX index,
890  PObject * obj
891  );
892 
904  virtual PObject * AbstractSetAt(
905  const PObject & key,
906  PObject * obj
907  );
908 
918  virtual PObject & GetRefAt(
919  const PObject & key
920  ) const;
921 
928  virtual PObject * AbstractGetAt(
929  const PObject & key
930  ) const;
931 
934  virtual void AbstractGetKeys(
935  PArrayObjects & keys
936  ) const;
938 
939  protected:
940  PINLINE PAbstractDictionary(int dummy, const PAbstractDictionary * c);
941 
942  private:
948  virtual PINDEX Append(
949  PObject * obj
950  );
951 
962  virtual PBoolean Remove(
963  const PObject * obj
964  );
965 
966 };
967 
968 
976 template <class K, class D> class PDictionary : public PAbstractDictionary
977 {
978  PCLASSINFO(PDictionary, PAbstractDictionary);
979 
980  public:
981  typedef K key_type;
982  typedef D data_type;
984 
994  : PAbstractDictionary() { }
996 
1003  virtual PObject * Clone() const
1004  { return PNEW PDictionary(0, this); }
1006 
1019  const D & operator[](
1020  const K & key
1021  ) const { return dynamic_cast<const D &>(this->GetRefAt(key)); }
1023  const K & key
1024  ) { return dynamic_cast<D &>(this->GetRefAt(key)); }
1025 
1035  const K & key
1036  ) const { return this->AbstractContains(key); }
1037 
1047  virtual D * RemoveAt(
1048  const K & key
1049  ) { return dynamic_cast<D *>(this->AbstractSetAt(key, NULL)); }
1050 
1062  virtual PBoolean SetAt(
1063  const K & key, // Key for position in dictionary to add object.
1064  D * obj // New object to put into the dictionary.
1065  ) { return this->AbstractSetAt(key, obj) != NULL; }
1066 
1073  virtual D * GetAt(
1074  const K & key // Key for position in dictionary to get object.
1075  ) const { return dynamic_cast<D *>(this->AbstractGetAt(key)); }
1076 
1090  const K & GetKeyAt(
1091  PINDEX index
1092  ) const
1093  { return dynamic_cast<const K &>(this->AbstractGetKeyAt(index)); }
1094 
1109  PINDEX index
1110  ) const
1111  { return dynamic_cast<D &>(this->AbstractGetDataAt(index)); }
1112 
1116  {
1117  PArray<K> keys;
1118  this->AbstractGetKeys(keys);
1119  return keys;
1120  }
1122 
1125  class iterator;
1126  class const_iterator;
1128  protected:
1129  K * m_internal_first; // Must be first two members
1131 
1134 
1136  : m_internal_first(NULL)
1137  , m_internal_second(NULL)
1138  , m_table(NULL)
1139  , m_element(NULL)
1140  {
1141  }
1142 
1143  iterator_base(const dict_type * dict)
1144  : m_table(dict->hashTable)
1145  {
1146  this->SetElement(this->m_table->GetElementAt((PINDEX)0));
1147  }
1148 
1149  iterator_base(const dict_type * dict, const K & key)
1150  : m_table(dict->hashTable)
1151  {
1152  this->SetElement(this->m_table->GetElementAt(key));
1153  }
1154 
1156  {
1157  this->m_element = element;
1158  if (element != NULL) {
1159  this->m_internal_first = dynamic_cast<K *>(element->m_key);
1160  this->m_internal_second = dynamic_cast<D *>(element->m_data);
1161  }
1162  else {
1163  this->m_internal_first = NULL;
1164  this->m_internal_second = NULL;
1165  }
1166  }
1167 
1168  void Next() { this->SetElement(PAssertNULL(this->m_table)->NextElement(this->m_element)); }
1169  void Prev() { this->SetElement(PAssertNULL(this->m_table)->PrevElement(this->m_element)); }
1170 
1171  public:
1172  bool operator==(const iterator_base & it) const { return this->m_element == it.m_element; }
1173  bool operator!=(const iterator_base & it) const { return this->m_element != it.m_element; }
1174  };
1175 
1176  template<class CK, class CD>
1178  public:
1179  CK & first;
1180  CD & second;
1181 
1182  private:
1183  iterator_pair() : first(reinterpret_cast<CK&>(0)), second(reinterpret_cast<CD&>(0)) { }
1184  };
1185 
1186  class iterator : public iterator_base, public std::iterator<std::forward_iterator_tag, iterator_pair<K,D> > {
1187  protected:
1188  iterator(dict_type * dict) : iterator_base(dict) { }
1189  iterator(dict_type * dict, const K & key) : iterator_base(dict, key) { }
1190 
1191  public:
1192  iterator() { }
1193 
1194  iterator operator++() { this->Next(); return *this; }
1195  iterator operator--() { this->Prev(); return *this; }
1196  iterator operator++(int) { iterator it = *this; this->Next(); return it; }
1197  iterator operator--(int) { iterator it = *this; this->Prev(); return it; }
1198 
1200  const pair * operator->() const { return reinterpret_cast<const pair *>(this); }
1201  const pair & operator* () const { return *reinterpret_cast<const pair *>(this); }
1202 
1203  friend class PDictionary<K, D>;
1204  };
1205 
1206  iterator begin() { return iterator(this); }
1207  iterator end() { return iterator(); }
1208  iterator find(const K & key) { return iterator(this, key); }
1209 
1210 
1211  class const_iterator : public iterator_base, public std::iterator<std::forward_iterator_tag, iterator_pair<const K,const D> > {
1212  protected:
1213  const_iterator(const dict_type * dict) : iterator_base(dict) { }
1214  const_iterator(const dict_type * dict, const K & key) : iterator_base(dict, key) { }
1215 
1216  public:
1219 
1220  const_iterator operator++() { this->Next(); return *this; }
1221  const_iterator operator--() { this->Prev(); return *this; }
1222  const_iterator operator++(int) { const_iterator it = *this; this->Next(); return it; }
1223  const_iterator operator--(int) { const_iterator it = *this; this->Prev(); return it; }
1224 
1226  const pair * operator->() const { return reinterpret_cast<const pair *>(this); }
1227  const pair & operator* () const { return *reinterpret_cast<const pair *>(this); }
1228 
1229  friend class PDictionary<K, D>;
1230  };
1231 
1232  const_iterator begin() const { return const_iterator(this); }
1233  const_iterator end() const { return const_iterator(); }
1234  const_iterator find(const K & k) const { return const_iterator(this, k); }
1235 
1236  void erase(const iterator & it) { this->AbstractSetAt(*it.m_element->m_key, NULL); }
1237  void erase(const const_iterator & it) { this->AbstractSetAt(*it.m_element->m_key, NULL); }
1239 
1240  protected:
1241  PDictionary(int dummy, const PDictionary * c)
1242  : PAbstractDictionary(dummy, c) { }
1243 };
1244 
1245 
1258 #define PDICTIONARY(cls, K, D) typedef PDictionary<K, D> cls
1259 
1260 
1273 #define PDECLARE_DICTIONARY(cls, K, D) \
1274  PDICTIONARY(cls##_PTemplate, K, D); \
1275  PDECLARE_CLASS(cls, cls##_PTemplate) \
1276  protected: \
1277  cls(int dummy, const cls * c) \
1278  : cls##_PTemplate(dummy, c) { } \
1279  public: \
1280  cls() \
1281  : cls##_PTemplate() { } \
1282  virtual PObject * Clone() const \
1283  { return PNEW cls(0, this); } \
1284 
1285 
1293 template <class K> class POrdinalDictionary : public PDictionary<K, POrdinalKey>
1294 {
1296  PCLASSINFO(POrdinalDictionary, ParentClass);
1297 
1298  public:
1308  : ParentClass() { }
1310 
1317  virtual PObject * Clone() const
1318  { return PNEW POrdinalDictionary(0, this); }
1320 
1333  PINDEX operator[](
1334  const K & key // Key to look for in the dictionary.
1335  ) const
1336  { return dynamic_cast<POrdinalKey &>(this->GetRefAt(key)); }
1337 
1352  PINDEX index,
1353  PINDEX ordinal
1354  ) { return this->AbstractSetAt(this->AbstractGetKeyAt(index), PNEW POrdinalKey(ordinal)) != NULL; }
1355 
1367  virtual PBoolean SetAt(
1368  const K & key,
1369  PINDEX ordinal
1370  ) { return this->AbstractSetAt(key, PNEW POrdinalKey(ordinal)) != NULL; }
1371 
1385  const K & GetKeyAt(
1386  PINDEX index
1387  ) const
1388  { return dynamic_cast<const K &>(this->AbstractGetKeyAt(index)); }
1389 
1406  PINDEX GetDataAt(
1407  PINDEX index
1408  ) const
1409  { return dynamic_cast<POrdinalKey &>(this->AbstractGetDataAt(index)); }
1411 
1412  protected:
1414  : ParentClass(dummy, c) { }
1415 };
1416 
1417 
1430 #define PORDINAL_DICTIONARY(cls, K) typedef POrdinalDictionary<K> cls
1431 
1432 
1447 #define PDECLARE_ORDINAL_DICTIONARY(cls, K) \
1448  PORDINAL_DICTIONARY(cls##_PTemplate, K); \
1449  PDECLARE_CLASS(cls, POrdinalDictionary<K>) \
1450  protected: \
1451  cls(int dummy, const cls * c) \
1452  : cls##_PTemplate(dummy, c) { } \
1453  public: \
1454  cls() \
1455  : cls##_PTemplate() { } \
1456  virtual PObject * Clone() const \
1457  { return PNEW cls(0, this); } \
1458 
1459 
1460 #endif // PTLIB_DICT_H
1461 
1462 // End Of File ///////////////////////////////////////////////////////////////