4 * Dictionary (hash table) Container classes.
6 * Portable Windows Library
8 * Copyright (c) 1993-1998 Equivalence Pty. Ltd.
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/
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
20 * The Original Code is Portable Windows Library.
22 * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
24 * Portions are Copyright (C) 1993 Free Software Foundation, Inc.
25 * All Rights Reserved.
27 * Contributor(s): ______________________________________.
30 * Revision 1.33 2004/04/09 03:42:34 csoutheren
31 * Removed all usages of "virtual inline" and "inline virtual"
33 * Revision 1.32 2004/04/03 23:53:09 csoutheren
34 * Added various changes to improce compatibility with the Sun Forte compiler
35 * Thanks to Brian Cameron
36 * Added detection of readdir_r version
38 * Revision 1.31 2003/09/17 01:18:02 csoutheren
39 * Removed recursive include file system and removed all references
40 * to deprecated coooperative threading support
42 * Revision 1.30 2003/03/31 01:23:56 robertj
43 * Added ReadFrom functions for standard container classes such as
44 * PIntArray and PStringList etc
46 * Revision 1.29 2002/10/04 01:47:29 robertj
47 * Added various increment and decrement operators to POrdinalKey.
49 * Revision 1.28 2002/09/16 01:08:59 robertj
50 * Added #define so can select if #pragma interface/implementation is used on
51 * platform basis (eg MacOS) rather than compiler, thanks Robert Monaghan.
53 * Revision 1.27 2002/06/14 13:22:12 robertj
54 * Fixed ability to remove elements from a PSet by value.
55 * Added by value add and remove functions to a PSet.
56 * Added a POrdinalSet class.
57 * Fixed some documentation.
59 * Revision 1.26 2002/02/06 00:53:25 robertj
60 * Fixed missing const on PSet::Contains and operator[], thanks Francisco Olarte Sanz
62 * Revision 1.25 1999/11/30 00:22:54 robertj
63 * Updated documentation for doc++
65 * Revision 1.24 1999/08/22 12:13:43 robertj
66 * Fixed warning when using inlines on older GNU compiler
68 * Revision 1.23 1999/03/09 02:59:49 robertj
69 * Changed comments to doc++ compatible documentation.
71 * Revision 1.22 1999/02/16 08:07:11 robertj
72 * MSVC 6.0 compatibility changes.
74 * Revision 1.21 1998/09/23 06:20:27 robertj
75 * Added open source copyright license.
77 * Revision 1.20 1998/01/05 10:39:34 robertj
78 * Fixed "typesafe" templates/macros for dictionaries, especially on GNU.
80 * Revision 1.19 1997/12/11 10:27:16 robertj
81 * Added type correct Contains() function to dictionaries.
83 * Revision 1.18 1997/07/08 13:15:05 robertj
86 * Revision 1.17 1997/06/08 04:49:11 robertj
87 * Fixed non-template class descendent order.
89 * Revision 1.16 1996/08/17 10:00:22 robertj
90 * Changes for Windows DLL support.
92 * Revision 1.15 1996/03/31 08:44:10 robertj
93 * Added RemoveAt() function to remove entries from dictionaries.
95 * Revision 1.14 1996/02/08 11:50:01 robertj
96 * Moved Contains function from PSet to PHashTable so available for dictionaries.
97 * Added print for dictionaries key=data\n.
98 * Added GetAt(PINDEX) to template classes to make identical to macro.
100 * Revision 1.13 1996/02/03 11:00:28 robertj
101 * Temporary removal of SetAt() and GetAt() functions in dictionary macro.
103 * Revision 1.12 1996/01/24 14:43:11 robertj
104 * Added initialisers to string dictionaries.
106 * Revision 1.11 1996/01/23 13:11:12 robertj
107 * Mac Metrowerks compiler support.
109 * Revision 1.10 1995/06/17 11:12:29 robertj
110 * Documentation update.
112 * Revision 1.9 1995/06/04 08:45:57 robertj
113 * Better C++ compatibility (with BC++)
115 * Revision 1.8 1995/03/14 12:41:19 robertj
116 * Updated documentation to use HTML codes.
118 * Revision 1.7 1995/02/22 10:50:29 robertj
119 * Changes required for compiling release (optimised) version.
121 * Revision 1.6 1995/02/11 04:10:35 robertj
122 * Fixed dictionary MACRO for templates.
124 * Revision 1.5 1995/02/05 00:48:03 robertj
125 * Fixed template version.
127 * Revision 1.4 1995/01/09 12:35:31 robertj
128 * Removed unnecesary return value from I/O functions.
129 * Changes due to Mac port.
131 * Revision 1.3 1994/12/21 11:52:51 robertj
132 * Documentation and variable normalisation.
134 * Revision 1.2 1994/12/17 01:36:57 robertj
135 * Fixed memory leak in PStringSet
137 * Revision 1.1 1994/12/12 09:59:32 robertj
147 ///////////////////////////////////////////////////////////////////////////////
148 // PDictionary classes
150 /**This class is used when an ordinal index value is the key for #PSet#
151 and #PDictionary# classes.
153 class POrdinalKey
: public PObject
155 PCLASSINFO(POrdinalKey
, PObject
);
158 /**@name Construction */
160 /** Create a new key for ordinal index values.
163 PINDEX newKey
= 0 /// Ordinal index value to use as a key.
166 /**Operator to assign the ordinal.
168 PINLINE POrdinalKey
& operator=(PINDEX
);
171 /**@name Overrides from class PObject */
173 /// Create a duplicate of the POrdinalKey.
174 virtual PObject
* Clone() const;
176 /* Get the relative rank of the ordinal index. This is a simpel comparison
177 of the objects PINDEX values.
180 comparison of the two objects, #EqualTo# for same,
181 #LessThan# for #obj# logically less than the
182 object and #GreaterThan# for #obj# logically
183 greater than the object.
185 virtual Comparison
Compare(const PObject
& obj
) const;
187 /**This function calculates a hash table index value for the implementation
188 of #PSet# and #PDictionary# classes.
191 hash table bucket number.
193 virtual PINDEX
HashFunction() const;
195 /**Output the ordinal index to the specified stream. This is identical to
196 outputting the PINDEX, ie integer, value.
199 stream that the index was output to.
201 virtual void PrintOn(ostream
& strm
) const;
204 /**@name New functions for class */
206 /** Operator so that a POrdinalKey can be used as a PINDEX value.
208 PINLINE
operator PINDEX() const;
210 /**Operator to pre-increment the ordinal.
212 PINLINE PINDEX
operator++();
214 /**Operator to post-increment the ordinal.
216 PINLINE PINDEX
operator++(int);
218 /**Operator to pre-decrement the ordinal.
220 PINLINE PINDEX
operator--();
222 /**Operator to post-decrement the ordinal.
224 PINLINE PINDEX
operator--(int);
226 /**Operator to add the ordinal.
228 PINLINE POrdinalKey
& operator+=(PINDEX
);
230 /**Operator to subtract from the ordinal.
232 PINLINE POrdinalKey
& operator-=(PINDEX
);
240 //////////////////////////////////////////////////////////////////////////////
242 /**The hash table class is the basis for implementing the #PSet# and
243 #PDictionary# classes.
245 The hash table allows for very fast searches for an object based on a "hash
246 function". This function yields an index into an array which is directly
247 looked up to locate the object. When two key values have the same hash
248 function value, then a linear search of a linked list is made to locate
249 the object. Thus the efficiency of the hash table is highly dependent on the
250 quality of the hash function for the data being used as keys.
252 class PHashTable
: public PCollection
254 PCONTAINERINFO(PHashTable
, PCollection
);
257 /**@name Construction */
259 /// Create a new, empty, hash table.
263 /**@name Overrides from class PObject */
265 /**Get the relative rank of the two hash tables. Actally ranking hash
266 tables is really meaningless, so only equality is returned by the
267 comparison. Equality is only achieved if the two instances reference the
271 comparison of the two objects, #EqualTo# if the same
272 reference and #GreaterThan# if not.
274 virtual Comparison
Compare(
275 const PObject
& obj
/// Other PHashTable to compare against.
281 /**@name Overrides from class PContainer */
283 /**This function is meaningless for hash table. The size of the collection
284 is determined by the addition and removal of objects. The size cannot be
285 set in any other way.
290 virtual BOOL
SetSize(
291 PINDEX newSize
/// New size for the hash table, this is ignored.
296 /**@name New functions for class */
298 /**Determine if the value of the object is contained in the hash table. The
299 object values are compared, not the pointers. So the objects in the
300 collection must correctly implement the #PObject::Compare()#
301 function. The hash table is used to locate the entry.
304 TRUE if the object value is in the set.
306 PINLINE BOOL
AbstractContains(
307 const PObject
& key
/// Key to look for in the set.
310 /**Get the key in the hash table at the ordinal index position.
312 The ordinal position in the hash table is determined by the hash values
313 of the keys and the order of insertion.
315 The last key/data pair is remembered by the class so that subseqent
318 This function is primarily used by the descendent template classes, or
319 macro, with the appropriate type conversion.
322 reference to key at the index position.
324 virtual const PObject
& AbstractGetKeyAt(
325 PINDEX index
/// Ordinal position in the hash table.
328 /**Get the data in the hash table at the ordinal index position.
330 The ordinal position in the hash table is determined by the hash values
331 of the keys and the order of insertion.
333 The last key/data pair is remembered by the class so that subseqent
336 This function is primarily used by the descendent template classes, or
337 macro, with the appropriate type conversion.
340 reference to key at the index position.
342 virtual PObject
& AbstractGetDataAt(
343 PINDEX index
/// Ordinal position in the hash table.
358 PDECLARE_BASEARRAY(Table
, Element
*)
363 virtual ~Table() { Destruct(); }
364 virtual void DestroyContents();
366 PINDEX
AppendElement(PObject
* key
, PObject
* data
);
367 PObject
* RemoveElement(const PObject
& key
);
368 BOOL
SetLastElementAt(PINDEX index
);
369 Element
* GetElementAt(const PObject
& key
);
370 PINDEX
GetElementsIndex(const PObject
*obj
,BOOL byVal
,BOOL keys
) const;
374 Element
* lastElement
;
378 friend class PHashTable
;
379 friend class PAbstractSet
;
388 //////////////////////////////////////////////////////////////////////////////
390 /** Abstract set of PObjects.
392 class PAbstractSet
: public PHashTable
394 PCONTAINERINFO(PAbstractSet
, PHashTable
);
396 /**@name Construction */
398 /**Create a new, empty, set.
400 Note that by default, objects placed into the list will be deleted when
401 removed or when all references to the list are destroyed.
403 PINLINE
PAbstractSet();
406 /**@name Overrides from class PCollection */
408 /**Add a new object to the collection. If the objects value is already in
409 the set then the object is {\bf not} included. If the
410 #AllowDeleteObjects# option is set then the #obj# parameter
414 hash function value of the newly added object.
416 virtual PINDEX
Append(
417 PObject
* obj
/// New object to place into the collection.
420 /**Add a new object to the collection. If the objects value is already in
421 the set then the object is {\bf not} included. If the
422 AllowDeleteObjects option is set then the #obj# parameter is
425 The object is always placed in the an ordinal position dependent on its
426 hash function. It is not placed at the specified position. The
427 #before# parameter is ignored.
430 hash function value of the newly added object.
432 virtual PINDEX
Insert(
433 const PObject
& before
, /// Object value to insert before.
434 PObject
* obj
/// New object to place into the collection.
437 /**Add a new object to the collection. If the objects value is already in
438 the set then the object is {\bf not} included. If the
439 AllowDeleteObjects option is set then the #obj# parameter is
442 The object is always placed in the an ordinal position dependent on its
443 hash function. It is not placed at the specified position. The
444 #index# parameter is ignored.
447 hash function value of the newly added object.
449 virtual PINDEX
InsertAt(
450 PINDEX index
, /// Index position in collection to place the object.
451 PObject
* obj
/// New object to place into the collection.
454 /**Remove the object from the collection. If the AllowDeleteObjects option
455 is set then the object is also deleted.
457 Note that the comparison for searching for the object in collection is
458 made by pointer, not by value. Thus the parameter must point to the
459 same instance of the object that is in the collection.
462 TRUE if the object was in the collection.
465 const PObject
* obj
/// Existing object to remove from the collection.
468 /**Remove an object at the specified index. If the #AllowDeleteObjects#
469 option is set then the object is also deleted.
472 pointer to the object being removed, or NULL if it was deleted.
474 virtual PObject
* RemoveAt(
475 PINDEX index
/// Index position in collection to place the object.
478 /**This function is the same as PHashTable::AbstractGetKeyAt().
483 virtual PObject
* GetAt(
484 PINDEX index
/// Index position in the collection of the object.
487 /**Add a new object to the collection. If the objects value is already in
488 the set then the object is {\bf not} included. If the
489 AllowDeleteObjects option is set then the #obj# parameter is
492 The object is always placed in the an ordinal position dependent on its
493 hash function. It is not placed at the specified position. The
494 #index# parameter is ignored.
497 TRUE if the object was successfully added.
500 PINDEX index
, /// Index position in collection to set.
501 PObject
* val
/// New value to place into the collection.
504 /**Search the collection for the specific instance of the object. The
505 object pointers are compared, not the values. The hash table is used
508 Note that that will require value comparisons to be made to find the
509 equivalent entry and then a final check is made with the pointers to
510 see if they are the same instance.
513 ordinal index position of the object, or P_MAX_INDEX.
515 virtual PINDEX
GetObjectsIndex(
516 const PObject
* obj
/// Object to find.
519 /**Search the collection for the specified value of the object. The object
520 values are compared, not the pointers. So the objects in the
521 collection must correctly implement the #PObject::Compare()#
522 function. The hash table is used to locate the entry.
525 ordinal index position of the object, or P_MAX_INDEX.
527 virtual PINDEX
GetValuesIndex(
528 const PObject
& obj
/// Object to find equal value.
534 #ifdef PHAS_TEMPLATES
536 /**This template class maps the PAbstractSet to a specific object type. The
537 functions in this class primarily do all the appropriate casting of types.
539 By default, objects placed into the set will {\bf not} be deleted when
540 removed or when all references to the set are destroyed. This is different
541 from the default on most collection classes.
543 Note that if templates are not used the #PDECLARE_SET# macro will
544 simulate the template instantiation.
546 template <class T
> class PSet
: public PAbstractSet
548 PCLASSINFO(PSet
, PAbstractSet
);
551 /**@name Construction */
553 /**Create a new, empty, dictionary. The parameter indicates whether to
554 delete objects that are removed from the set.
556 Note that by default, objects placed into the set will {\bf not} be
557 deleted when removed or when all references to the set are destroyed.
558 This is different from the default on most collection classes.
560 inline PSet(BOOL initialDeleteObjects
= FALSE
)
561 : PAbstractSet() { AllowDeleteObjects(initialDeleteObjects
); }
564 /**@name Overrides from class PObject */
566 /**Make a complete duplicate of the set. Note that all objects in the
567 array are also cloned, so this will make a complete copy of the set.
569 virtual PObject
* Clone() const
570 { return PNEW
PSet(0, this); }
573 /**@name New functions for class */
575 /**Include the specified object into the set. If the objects value is
576 already in the set then the object is {\bf not} included. If the
577 AllowDeleteObjects option is set then the #obj# parameter is
580 The object values are compared, not the pointers. So the objects in
581 the collection must correctly implement the #PObject::Compare()#
582 function. The hash table is used to locate the entry.
585 const T
* obj
// New object to include in the set.
586 ) { Append((PObject
*)obj
); }
588 /**Include the specified objects value into the set. If the objects value
589 is already in the set then the object is {\bf not} included.
591 The object values are compared, not the pointers. So the objects in
592 the collection must correctly implement the #PObject::Compare()#
593 function. The hash table is used to locate the entry.
596 const T
& obj
// New object to include in the set.
597 ) { Append(obj
.Clone()); return *this; }
599 /**Remove the object from the set. If the AllowDeleteObjects option is set
600 then the object is also deleted.
602 The object values are compared, not the pointers. So the objects in
603 the collection must correctly implement the #PObject::Compare()#
604 function. The hash table is used to locate the entry.
607 const T
* obj
// New object to exclude in the set.
610 /**Remove the objects value from the set. If the AllowDeleteObjects
611 option is set then the object is also deleted.
613 The object values are compared, not the pointers. So the objects in
614 the collection must correctly implement the #PObject::Compare()#
615 function. The hash table is used to locate the entry.
618 const T
& obj
// New object to exclude in the set.
619 ) { RemoveAt(GetValuesIndex(obj
)); return *this; }
621 /**Determine if the value of the object is contained in the set. The
622 object values are compared, not the pointers. So the objects in the
623 collection must correctly implement the #PObject::Compare()#
624 function. The hash table is used to locate the entry.
627 TRUE if the object value is in the set.
630 const T
& key
/// Key to look for in the set.
631 ) const { return AbstractContains(key
); }
633 /**Determine if the value of the object is contained in the set. The
634 object values are compared, not the pointers. So the objects in the
635 collection must correctly implement the #PObject::Compare()#
636 function. The hash table is used to locate the entry.
639 TRUE if the object value is in the set.
642 const T
& key
/// Key to look for in the set.
643 ) const { return AbstractContains(key
); }
645 /**Get the key in the set at the ordinal index position.
647 The ordinal position in the set is determined by the hash values of the
648 keys and the order of insertion.
650 The last key/data pair is remembered by the class so that subseqent
654 reference to key at the index position.
656 virtual const T
& GetKeyAt(
657 PINDEX index
/// Index of value to get.
659 { return (const T
&)AbstractGetKeyAt(index
); }
664 PSet(int dummy
, const PSet
* c
)
665 : PAbstractSet(dummy
, c
)
666 { reference
->deleteObjects
= c
->reference
->deleteObjects
; }
670 /**Declare set class.
671 This macro is used to declare a descendent of PAbstractSet class,
672 customised for a particular object type {\bf T}. This macro closes the
673 class declaration off so no additional members can be added.
675 If the compilation is using templates then this macro produces a typedef
676 of the #PSet# template class.
678 See the #PSet# class and #PDECLARE_SET# macro for more
681 #define PSET(cls, T) typedef PSet<T> cls
684 /**Begin declaration of a set class.
685 This macro is used to declare a descendent of PAbstractSet class,
686 customised for a particular object type {\bf T}.
688 If the compilation is using templates then this macro produces a descendent
689 of the #PSet# template class. If templates are not being used then the
690 macro defines a set of inline functions to do all casting of types. The
691 resultant classes have an identical set of functions in either case.
693 See the #PSet# and #PAbstractSet# classes for more information.
695 #define PDECLARE_SET(cls, T, initDelObj) \
696 PSET(cls##_PTemplate, T); \
697 PDECLARE_CLASS(cls, cls##_PTemplate) \
699 cls(int dummy, const cls * c) \
700 : cls##_PTemplate(dummy, c) { } \
702 cls(BOOL initialDeleteObjects = initDelObj) \
703 : cls##_PTemplate(initialDeleteObjects) { } \
704 virtual PObject * Clone() const \
705 { return PNEW cls(0, this); } \
708 #else // PHAS_TEMPLATES
711 #define PSET(cls, K) \
712 class cls : public PAbstractSet { \
713 PCLASSINFO(cls, PAbstractSet); \
715 inline cls(int dummy, const cls * c) \
716 : PAbstractSet(dummy, c) \
717 { reference->deleteObjects = c->reference->deleteObjects; } \
719 inline cls(BOOL initialDeleteObjects = FALSE) \
720 : PAbstractSet() { AllowDeleteObjects(initialDeleteObjects); } \
721 virtual PObject * Clone() const \
722 { return PNEW cls(0, this); } \
723 inline void Include(const PObject * key) \
724 { Append((PObject *)key); } \
725 inline void Exclude(const PObject * key) \
727 inline BOOL operator[](const K & key) const \
728 { return AbstractContains(key); } \
729 inline BOOL Contains(const K & key) const \
730 { return AbstractContains(key); } \
731 virtual const K & GetKeyAt(PINDEX index) const \
732 { return (const K &)AbstractGetKeyAt(index); } \
735 #define PDECLARE_SET(cls, K, initDelObj) \
736 PSET(cls##_PTemplate, K); \
737 PDECLARE_CLASS(cls, cls##_PTemplate) \
739 inline cls(int dummy, const cls * c) \
740 : cls##_PTemplate(dummy, c) { } \
742 inline cls(BOOL initialDeleteObjects = initDelObj) \
743 : cls##_PTemplate() { AllowDeleteObjects(initialDeleteObjects); } \
744 virtual PObject * Clone() const \
745 { return PNEW cls(0, this); } \
748 #endif // PHAS_TEMPLATES
751 PSET(POrdinalSet
, POrdinalKey
);
754 //////////////////////////////////////////////////////////////////////////////
756 /**An abstract dictionary container.
758 class PAbstractDictionary
: public PHashTable
760 PCLASSINFO(PAbstractDictionary
, PHashTable
);
762 /**@name Construction */
764 /**Create a new, empty, dictionary.
766 Note that by default, objects placed into the dictionary will be deleted
767 when removed or when all references to the dictionary are destroyed.
769 PINLINE
PAbstractDictionary();
772 /**@name Overrides from class PObject */
774 /**Output the contents of the object to the stream. The exact output is
775 dependent on the exact semantics of the descendent class. This is
776 primarily used by the standard ##operator<<## function.
778 The default behaviour is to print the class name.
780 virtual void PrintOn(
781 ostream
&strm
/// Stream to print the object into.
785 /**@name Overrides from class PCollection */
787 /**Insert a new object into the dictionary. The semantics of this function
788 is different from that of the #PCollection# class. This function is
789 exactly equivalent to the SetAt() function that sets a data value at
790 the key value location.
795 virtual PINDEX
Insert(
796 const PObject
& key
, /// Object value to use as the key.
797 PObject
* obj
/// New object to place into the collection.
800 /**Insert a new object at the specified index. The index is as is used in
801 the #GetKeyAt()# function.
806 virtual PINDEX
InsertAt(
807 PINDEX index
, /// Index position in collection to place the object.
808 PObject
* obj
/// New object to place into the collection.
811 /**Remove an object at the specified index. The index is as is used in
812 the #GetKeyAt()# function. The returned pointer is then removed using
813 the #SetAt()# function to set that key value to NULL. If the
814 #AllowDeleteObjects# option is set then the object is also
818 pointer to the object being removed, or NULL if it was deleted.
820 virtual PObject
* RemoveAt(
821 PINDEX index
/// Index position in collection to place the object.
824 /**Set the object at the specified index to the new value. The index is
825 as is used in the #GetKeyAt()# function. This will overwrite the
826 existing entry. If the AllowDeleteObjects option is set then the old
827 object is also deleted.
830 TRUE if the object was successfully added.
833 PINDEX index
, /// Index position in collection to set.
834 PObject
* val
/// New value to place into the collection.
837 /**Get the object at the specified index position. The index is as is
838 used in the #GetKeyAt()# function. If the index was not in the
839 collection then NULL is returned.
842 pointer to object at the specified index.
844 virtual PObject
* GetAt(
845 PINDEX index
/// Index position in the collection of the object.
848 /**Search the collection for the specific instance of the object. The
849 object pointers are compared, not the values. The hash table is used
852 Note that that will require value comparisons to be made to find the
853 equivalent entry and then a final check is made with the pointers to
854 see if they are the same instance.
857 ordinal index position of the object, or P_MAX_INDEX.
859 virtual PINDEX
GetObjectsIndex(
860 const PObject
* obj
/// Object to find.
863 /**Search the collection for the specified value of the object. The object
864 values are compared, not the pointers. So the objects in the
865 collection must correctly implement the #PObject::Compare()#
866 function. The hash table is used to locate the entry.
869 ordinal index position of the object, or P_MAX_INDEX.
871 virtual PINDEX
GetValuesIndex(
872 const PObject
& obj
/// Object to find value of.
877 /**@name New functions for class */
879 /**Set the data at the specified ordinal index position in the dictionary.
881 The ordinal position in the dictionary is determined by the hash values
882 of the keys and the order of insertion.
885 TRUE if the new object could be placed into the dictionary.
887 virtual BOOL
SetDataAt(
888 PINDEX index
, /// Ordinal index in the dictionary.
889 PObject
* obj
/// New object to put into the dictionary.
892 /**Add a new object to the collection. If the objects value is already in
893 the dictionary then the object is overrides the previous value. If the
894 AllowDeleteObjects option is set then the old object is also deleted.
896 The object is placed in the an ordinal position dependent on the keys
897 hash function. Subsequent searches use the has function to speed access
901 TRUE if the object was successfully added.
903 virtual BOOL
AbstractSetAt(
904 const PObject
& key
, /// Key for position in dictionary to add object.
905 PObject
* obj
/// New object to put into the dictionary.
908 /**Get the object at the specified key position. If the key was not in the
909 collection then this function asserts.
911 This function is primarily for use by the #operator[]# function is
912 descendent template classes.
915 reference to object at the specified key.
917 virtual PObject
& GetRefAt(
918 const PObject
& key
/// Key for position in dictionary to get object.
921 /**Get the object at the specified key position. If the key was not in the
922 collection then NULL is returned.
925 pointer to object at the specified key.
927 virtual PObject
* AbstractGetAt(
928 const PObject
& key
/// Key for position in dictionary to get object.
933 PINLINE
PAbstractDictionary(int dummy
, const PAbstractDictionary
* c
);
936 virtual PINDEX
Append(
937 PObject
* obj
// New object to place into the collection.
939 /* This function is meaningless and will assert.
946 const PObject
* obj
// Existing object to remove from the collection.
948 /* Remove the object from the collection. If the AllowDeleteObjects option
949 is set then the object is also deleted.
951 Note that the comparison for searching for the object in collection is
952 made by pointer, not by value. Thus the parameter must point to the
953 same instance of the object that is in the collection.
956 TRUE if the object was in the collection.
962 #ifdef PHAS_TEMPLATES
964 /**This template class maps the PAbstractDictionary to a specific key and data
965 types. The functions in this class primarily do all the appropriate casting
968 Note that if templates are not used the #PDECLARE_DICTIONARY# macro
969 will simulate the template instantiation.
971 template <class K
, class D
> class PDictionary
: public PAbstractDictionary
973 PCLASSINFO(PDictionary
, PAbstractDictionary
);
976 /**@name Construction */
978 /**Create a new, empty, dictionary.
980 Note that by default, objects placed into the dictionary will be
981 deleted when removed or when all references to the dictionary are
985 : PAbstractDictionary() { }
988 /**@name Overrides from class PObject */
990 /**Make a complete duplicate of the dictionary. Note that all objects in
991 the array are also cloned, so this will make a complete copy of the
994 virtual PObject
* Clone() const
995 { return PNEW
PDictionary(0, this); }
998 /**@name New functions for class */
1000 /**Get the object contained in the dictionary at the #key#
1001 position. The hash table is used to locate the data quickly via the
1002 hash function provided by the #key#.
1004 The last key/data pair is remembered by the class so that subseqent
1005 access is very fast.
1008 reference to the object indexed by the key.
1011 const K
& key
/// Key to look for in the dictionary.
1013 { return (D
&)GetRefAt(key
); }
1015 /**Determine if the value of the object is contained in the hash table. The
1016 object values are compared, not the pointers. So the objects in the
1017 collection must correctly implement the #PObject::Compare()#
1018 function. The hash table is used to locate the entry.
1021 TRUE if the object value is in the dictionary.
1024 const K
& key
/// Key to look for in the dictionary.
1025 ) const { return AbstractContains(key
); }
1027 /**Remove an object at the specified key. The returned pointer is then
1028 removed using the #SetAt()# function to set that key value to
1029 NULL. If the #AllowDeleteObjects# option is set then the
1030 object is also deleted.
1033 pointer to the object being removed, or NULL if it was deleted.
1035 virtual D
* RemoveAt(
1036 const K
& key
/// Key for position in dictionary to get object.
1037 ) { D
* obj
= GetAt(key
); AbstractSetAt(key
, NULL
); return obj
; }
1039 /**Add a new object to the collection. If the objects value is already in
1040 the dictionary then the object is overrides the previous value. If the
1041 AllowDeleteObjects option is set then the old object is also deleted.
1043 The object is placed in the an ordinal position dependent on the keys
1044 hash function. Subsequent searches use the has function to speed access
1048 TRUE if the object was successfully added.
1051 const K
& key
, // Key for position in dictionary to add object.
1052 D
* obj
// New object to put into the dictionary.
1053 ) { return AbstractSetAt(key
, obj
); }
1055 /**Get the object at the specified key position. If the key was not in the
1056 collection then NULL is returned.
1059 pointer to object at the specified key.
1062 const K
& key
// Key for position in dictionary to get object.
1063 ) const { return (D
*)AbstractGetAt(key
); }
1065 /**Get the key in the dictionary at the ordinal index position.
1067 The ordinal position in the dictionary is determined by the hash values
1068 of the keys and the order of insertion.
1070 The last key/data pair is remembered by the class so that subseqent
1071 access is very fast.
1074 reference to key at the index position.
1077 PINDEX index
/// Ordinal position in dictionary for key.
1079 { return (const K
&)AbstractGetKeyAt(index
); }
1081 /**Get the data in the dictionary at the ordinal index position.
1083 The ordinal position in the dictionary is determined by the hash values
1084 of the keys and the order of insertion.
1086 The last key/data pair is remembered by the class so that subseqent
1087 access is very fast.
1090 reference to data at the index position.
1093 PINDEX index
/// Ordinal position in dictionary for data.
1095 { return (D
&)AbstractGetDataAt(index
); }
1099 PDictionary(int dummy
, const PDictionary
* c
)
1100 : PAbstractDictionary(dummy
, c
) { }
1104 /**Declare a dictionary class.
1105 This macro is used to declare a descendent of PAbstractDictionary class,
1106 customised for a particular key type {\bf K} and data object type {\bf D}.
1107 This macro closes the class declaration off so no additional members can
1110 If the compilation is using templates then this macro produces a typedef
1111 of the #PDictionary# template class.
1113 See the #PDictionary# class and #PDECLARE_DICTIONARY# macro for
1116 #define PDICTIONARY(cls, K, D) typedef PDictionary<K, D> cls
1119 /**Begin declaration of dictionary class.
1120 This macro is used to declare a descendent of PAbstractDictionary class,
1121 customised for a particular key type {\bf K} and data object type {\bf D}.
1123 If the compilation is using templates then this macro produces a descendent
1124 of the #PDictionary# template class. If templates are not being used
1125 then the macro defines a set of inline functions to do all casting of types.
1126 The resultant classes have an identical set of functions in either case.
1128 See the #PDictionary# and #PAbstractDictionary# classes for more
1131 #define PDECLARE_DICTIONARY(cls, K, D) \
1132 PDICTIONARY(cls##_PTemplate, K, D); \
1133 PDECLARE_CLASS(cls, cls##_PTemplate) \
1135 cls(int dummy, const cls * c) \
1136 : cls##_PTemplate(dummy, c) { } \
1139 : cls##_PTemplate() { } \
1140 virtual PObject * Clone() const \
1141 { return PNEW cls(0, this); } \
1144 /**This template class maps the #PAbstractDictionary# to a specific key
1145 type and a #POrdinalKey# data type. The functions in this class
1146 primarily do all the appropriate casting of types.
1148 Note that if templates are not used the #PDECLARE_ORDINAL_DICTIONARY#
1149 macro will simulate the template instantiation.
1151 template <class K
> class POrdinalDictionary
: public PAbstractDictionary
1153 PCLASSINFO(POrdinalDictionary
, PAbstractDictionary
);
1156 /**@name Construction */
1158 /**Create a new, empty, dictionary.
1160 Note that by default, objects placed into the dictionary will be
1161 deleted when removed or when all references to the dictionary are
1164 POrdinalDictionary()
1165 : PAbstractDictionary() { }
1168 /**@name Overrides from class PObject */
1170 /**Make a complete duplicate of the dictionary. Note that all objects in
1171 the array are also cloned, so this will make a complete copy of the
1174 virtual PObject
* Clone() const
1175 { return PNEW
POrdinalDictionary(0, this); }
1178 /**@name New functions for class */
1180 /**Get the object contained in the dictionary at the #key#
1181 position. The hash table is used to locate the data quickly via the
1182 hash function provided by the key.
1184 The last key/data pair is remembered by the class so that subseqent
1185 access is very fast.
1188 reference to the object indexed by the key.
1191 const K
& key
// Key to look for in the dictionary.
1193 { return (POrdinalKey
&)GetRefAt(key
); }
1195 /**Determine if the value of the object is contained in the hash table. The
1196 object values are compared, not the pointers. So the objects in the
1197 collection must correctly implement the #PObject::Compare()#
1198 function. The hash table is used to locate the entry.
1201 TRUE if the object value is in the dictionary.
1204 const K
& key
/// Key to look for in the dictionary.
1205 ) const { return AbstractContains(key
); }
1207 virtual POrdinalKey
* GetAt(
1208 const K
& key
/// Key for position in dictionary to get object.
1209 ) const { return (POrdinalKey
*)AbstractGetAt(key
); }
1210 /* Get the object at the specified key position. If the key was not in the
1211 collection then NULL is returned.
1214 pointer to object at the specified key.
1217 /**Set the data at the specified ordinal index position in the dictionary.
1219 The ordinal position in the dictionary is determined by the hash values
1220 of the keys and the order of insertion.
1223 TRUE if the new object could be placed into the dictionary.
1225 virtual BOOL
SetDataAt(
1226 PINDEX index
, /// Ordinal index in the dictionary.
1227 PINDEX ordinal
/// New ordinal value to put into the dictionary.
1228 ) { return PAbstractDictionary::SetDataAt(index
, PNEW
POrdinalKey(ordinal
)); }
1230 /**Add a new object to the collection. If the objects value is already in
1231 the dictionary then the object is overrides the previous value. If the
1232 AllowDeleteObjects option is set then the old object is also deleted.
1234 The object is placed in the an ordinal position dependent on the keys
1235 hash function. Subsequent searches use the has function to speed access
1239 TRUE if the object was successfully added.
1242 const K
& key
, /// Key for position in dictionary to add object.
1243 PINDEX ordinal
/// New ordinal value to put into the dictionary.
1244 ) { return AbstractSetAt(key
, PNEW
POrdinalKey(ordinal
)); }
1246 /**Remove an object at the specified key. The returned pointer is then
1247 removed using the #SetAt()# function to set that key value to
1248 NULL. If the #AllowDeleteObjects# option is set then the
1249 object is also deleted.
1252 pointer to the object being removed, or NULL if it was deleted.
1254 virtual PINDEX
RemoveAt(
1255 const K
& key
/// Key for position in dictionary to get object.
1256 ) { PINDEX ord
= *GetAt(key
); AbstractSetAt(key
, NULL
); return ord
; }
1258 /**Get the key in the dictionary at the ordinal index position.
1260 The ordinal position in the dictionary is determined by the hash values
1261 of the keys and the order of insertion.
1263 The last key/data pair is remembered by the class so that subseqent
1264 access is very fast.
1267 reference to key at the index position.
1270 PINDEX index
/// Ordinal position in dictionary for key.
1272 { return (const K
&)AbstractGetKeyAt(index
); }
1274 /**Get the data in the dictionary at the ordinal index position.
1276 The ordinal position in the dictionary is determined by the hash values
1277 of the keys and the order of insertion.
1279 The last key/data pair is remembered by the class so that subseqent
1280 access is very fast.
1283 reference to data at the index position.
1286 PINDEX index
/// Ordinal position in dictionary for data.
1288 { return (POrdinalKey
&)AbstractGetDataAt(index
); }
1292 POrdinalDictionary(int dummy
, const POrdinalDictionary
* c
)
1293 : PAbstractDictionary(dummy
, c
) { }
1297 /**Declare an ordinal dictionary class.
1298 This macro is used to declare a descendent of PAbstractDictionary class,
1299 customised for a particular key type {\bf K} and data object type of
1300 #POrdinalKey#. This macro closes the class declaration off so no
1301 additional members can be added.
1303 If the compilation is using templates then this macro produces a typedef
1304 of the #POrdinalDictionary# template class.
1306 See the #POrdinalDictionary# class and
1307 #PDECLARE_ORDINAL_DICTIONARY# macro for more information.
1309 #define PORDINAL_DICTIONARY(cls, K) typedef POrdinalDictionary<K> cls
1312 /**Begin declaration of an ordinal dictionary class.
1313 This macro is used to declare a descendent of PAbstractList class,
1314 customised for a particular key type {\bf K} and data object type of
1317 If the compilation is using templates then this macro produces a descendent
1318 of the #POrdinalDictionary# template class. If templates are not being
1319 used then the macro defines a set of inline functions to do all casting of
1320 types. The resultant classes have an identical set of functions in either
1323 See the #POrdinalDictionary# and #PAbstractDictionary# classes
1324 for more information.
1326 #define PDECLARE_ORDINAL_DICTIONARY(cls, K) \
1327 PORDINAL_DICTIONARY(cls##_PTemplate, K); \
1328 PDECLARE_CLASS(cls, POrdinalDictionary<K>) \
1330 cls(int dummy, const cls * c) \
1331 : cls##_PTemplate(dummy, c) { } \
1334 : cls##_PTemplate() { } \
1335 virtual PObject * Clone() const \
1336 { return PNEW cls(0, this); } \
1339 #else // PHAS_TEMPLATES
1342 #define PDICTIONARY(cls, K, D) \
1343 class cls : public PAbstractDictionary { \
1344 PCLASSINFO(cls, PAbstractDictionary); \
1346 inline cls(int dummy, const cls * c) \
1347 : PAbstractDictionary(dummy, c) { } \
1350 : PAbstractDictionary() { } \
1351 virtual PObject * Clone() const \
1352 { return PNEW cls(0, this); } \
1353 D & operator[](const K & key) const \
1354 { return (D &)GetRefAt(key); } \
1355 virtual BOOL Contains(const K & key) const \
1356 { return AbstractContains(key); } \
1357 virtual D * RemoveAt(const K & key) \
1358 { D * obj = GetAt(key); AbstractSetAt(key, NULL); return obj; } \
1359 virtual BOOL SetAt(const K & key, D * obj) \
1360 { return AbstractSetAt(key, obj); } \
1361 virtual D * GetAt(const K & key) const \
1362 { return (D *)AbstractGetAt(key); } \
1363 const K & GetKeyAt(PINDEX index) const \
1364 { return (const K &)AbstractGetKeyAt(index); } \
1365 D & GetDataAt(PINDEX index) const \
1366 { return (D &)AbstractGetDataAt(index); } \
1369 #define PDECLARE_DICTIONARY(cls, K, D) \
1370 PDICTIONARY(cls##_PTemplate, K, D); \
1371 PDECLARE_CLASS(cls, cls##_PTemplate) \
1373 cls(int dummy, const cls * c) \
1374 : cls##_PTemplate(dummy, c) { } \
1377 : cls##_PTemplate() { } \
1378 virtual PObject * Clone() const \
1379 { return PNEW cls(0, this); } \
1382 #define PORDINAL_DICTIONARY(cls, K) \
1383 class cls : public PAbstractDictionary { \
1384 PCLASSINFO(cls, PAbstractDictionary); \
1386 inline cls(int dummy, const cls * c) \
1387 : PAbstractDictionary(dummy, c) { } \
1390 : PAbstractDictionary() { } \
1391 virtual PObject * Clone() const \
1392 { return PNEW cls(0, this); } \
1393 inline PINDEX operator[](const K & key) const \
1394 { return (POrdinalKey &)GetRefAt(key); } \
1395 virtual BOOL Contains(const K & key) const \
1396 { return AbstractContains(key); } \
1397 virtual POrdinalKey * GetAt(const K & key) const \
1398 { return (POrdinalKey *)AbstractGetAt(key); } \
1399 virtual BOOL SetDataAt(PINDEX index, PINDEX ordinal) \
1400 { return PAbstractDictionary::SetDataAt(index, PNEW POrdinalKey(ordinal)); } \
1401 virtual BOOL SetAt(const K & key, PINDEX ordinal) \
1402 { return AbstractSetAt(key, PNEW POrdinalKey(ordinal)); } \
1403 virtual PINDEX RemoveAt(const K & key) \
1404 { PINDEX ord = *GetAt(key); AbstractSetAt(key, NULL); return ord; } \
1405 inline const K & GetKeyAt(PINDEX index) const \
1406 { return (const K &)AbstractGetKeyAt(index); } \
1407 inline PINDEX GetDataAt(PINDEX index) const \
1408 { return (POrdinalKey &)AbstractGetDataAt(index); } \
1411 #define PDECLARE_ORDINAL_DICTIONARY(cls, K) \
1412 PORDINAL_DICTIONARY(cls##_PTemplate, K); \
1413 PDECLARE_CLASS(cls, cls##_PTemplate) \
1415 cls(int dummy, const cls * c) \
1416 : cls##_PTemplate(dummy, c) { } \
1419 : cls##_PTemplate() { } \
1420 virtual PObject * Clone() const \
1421 { return PNEW cls(0, this); } \
1424 #endif // PHAS_TEMPLATES
1426 // End Of File ///////////////////////////////////////////////////////////////