collect.cxx
上传用户:hzhsqp
上传日期:2007-01-06
资源大小:1600k
文件大小:38k
源码类别:

IP电话/视频会议

开发平台:

Visual C++

  1. /*
  2.  * collect.cxx
  3.  *
  4.  * Container Classes
  5.  *
  6.  * Portable Windows 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.  * $Log: collect.cxx,v $
  30.  * Revision 1.48  1999/08/22 12:54:35  robertj
  31.  * Fixed warnings about inlines on older GNU compiler
  32.  *
  33.  * Revision 1.47  1999/02/16 08:08:06  robertj
  34.  * MSVC 6.0 compatibility changes.
  35.  *
  36.  * Revision 1.46  1998/11/02 12:53:52  robertj
  37.  * Fixed yet another bug in the object array SetSize() for unix systems.
  38.  *
  39.  * Revision 1.45  1998/10/31 14:01:58  robertj
  40.  * Fixed ANSI scoping of for loop variable.
  41.  *
  42.  * Revision 1.44  1998/10/30 10:41:57  robertj
  43.  * Fixed bug cause by previous bug fix in PObjectArray, deleting deleted entries.
  44.  *
  45.  * Revision 1.43  1998/10/28 00:57:43  robertj
  46.  * Fixed memory leak in PObjectArray.
  47.  * Fixed crash when doing GetValuesIndex() on array with NULL elements.
  48.  *
  49.  * Revision 1.42  1998/10/13 14:06:16  robertj
  50.  * Complete rewrite of memory leak detection code.
  51.  *
  52.  * Revision 1.41  1998/09/23 06:21:52  robertj
  53.  * Added open source copyright license.
  54.  *
  55.  * Revision 1.40  1998/09/14 12:32:45  robertj
  56.  * Fixed bug in ordinal dictionary GetAt() and SetAt() for scalar integer types.
  57.  *
  58.  * Revision 1.39  1998/08/20 05:48:51  robertj
  59.  * Fixed bug on removing entries by index from a PSet().
  60.  *
  61.  * Revision 1.38  1998/05/17 02:29:46  robertj
  62.  * Fixed GetObjectsIndex()/GetValuesIndex() finding elements that have a hash clash.
  63.  *
  64.  * Revision 1.37  1998/03/26 23:31:50  robertj
  65.  * Fixed bug in RemoveAll() deleting objects twice.
  66.  *
  67.  * Revision 1.36  1998/03/26 11:19:50  robertj
  68.  * Fix bug with unsigned PINDEX in array SetSize.
  69.  *
  70.  * Revision 1.35  1998/03/25 12:58:41  robertj
  71.  * Fixed memory leak if resize PArray
  72.  *
  73.  * Revision 1.34  1998/03/24 02:58:52  robertj
  74.  * Fixed uninitialised variable in dictionary MakeUnique() function.
  75.  *
  76.  * Revision 1.33  1998/01/26 01:41:19  robertj
  77.  * GNU compatibility.
  78.  *
  79.  * Revision 1.32  1998/01/26 00:36:10  robertj
  80.  * Fixed MakeUnique() function for dictionaries and sets.
  81.  *
  82.  * Revision 1.31  1998/01/06 12:00:15  robertj
  83.  * Fixed "typesafe" templates/macros for dictionaries, especially on GNU.
  84.  *
  85.  * Revision 1.30  1997/12/11 10:30:02  robertj
  86.  * Added type correct Contains() function to dictionaries.
  87.  *
  88.  * Revision 1.29  1997/06/08 04:48:30  robertj
  89.  * Fixed problems in sorted list with multiple identical entries.
  90.  *
  91.  * Revision 1.28  1997/04/27 05:50:14  robertj
  92.  * DLL support.
  93.  *
  94.  * Revision 1.27  1997/02/14 13:59:09  robertj
  95.  * Rewrite of sorted list to use sentinel record rather than NULL pointer.
  96.  *
  97.  * Revision 1.26  1996/08/17 09:55:23  robertj
  98.  * Optimised RemoveAll() for object arrays.
  99.  *
  100.  * Revision 1.25  1996/08/08 10:08:43  robertj
  101.  * Directory structure changes for common files.
  102.  *
  103.  * Revision 1.24  1996/07/15 10:32:52  robertj
  104.  * Fixed bug in sorted list (crash on remove).
  105.  *
  106.  * Revision 1.23  1996/05/26 03:46:24  robertj
  107.  * Compatibility to GNU 2.7.x
  108.  *
  109.  * Revision 1.22  1996/03/26 00:52:38  robertj
  110.  * Fixed bug in dictionary decrementing size when removing element even if already removed.
  111.  *
  112.  * Revision 1.21  1996/02/19 13:32:31  robertj
  113.  * Fixed yet another bug in PSortedList, not setting cache index value correctly.
  114.  *
  115.  * Revision 1.20  1996/02/08 12:24:13  robertj
  116.  * Added default print for dictionaries in form key=datan.
  117.  * Added missing GetAt() function on PSet to be consistent with all others.
  118.  *
  119.  * Revision 1.19  1996/02/03 11:07:59  robertj
  120.  * A bit more bullet proofing of sorted list class.
  121.  *
  122.  * Revision 1.18  1996/01/30 23:30:40  robertj
  123.  * Added optimisation to sorted list GetAt() to use cached element.
  124.  *
  125.  * Revision 1.17  1996/01/28 14:11:45  robertj
  126.  * Fixed bug in sorted list for when getting entry one before last one cached.
  127.  *
  128.  * Revision 1.16  1996/01/28 02:52:45  robertj
  129.  * Added assert into all Compare functions to assure comparison between compatible objects.
  130.  *
  131.  * Revision 1.15  1996/01/23 13:18:29  robertj
  132.  * Fixed bug in sorted list GetObjectsIndex not checking if is same object
  133.  * Fixed bug in sorted list append not returning correct value.
  134.  *
  135.  * Revision 1.14  1995/01/27 11:12:38  robertj
  136.  * Fixed nasty bug in sorted lists.
  137.  *
  138.  * Revision 1.13  1995/01/09  12:31:49  robertj
  139.  * Removed unnecesary return value from I/O functions.
  140.  *
  141.  * Revision 1.12  1994/12/13  11:50:52  robertj
  142.  * Added MakeUnique() function to all container classes.
  143.  *
  144.  * Revision 1.11  1994/12/12  10:16:25  robertj
  145.  * Restructuring and documentation of container classes.
  146.  * Renaming of some macros for declaring container classes.
  147.  * Added some extra functionality to PString.
  148.  * Added start to 2 byte characters in PString.
  149.  * Fixed incorrect overrides in PCaselessString.
  150.  *
  151.  * Revision 1.10  1994/12/05  11:24:58  robertj
  152.  * Fixed bugs in InsertAt and RemoveAt in PObjectArray.
  153.  *
  154.  * Revision 1.9  1994/10/30  11:34:49  robertj
  155.  * Fixed ObjectArray to have pointer to array object pointers.
  156.  *
  157.  * Revision 1.8  1994/10/23  03:41:31  robertj
  158.  * Fixed dictionary functions that should work by index not key.
  159.  *
  160.  * Revision 1.7  1994/09/25  10:49:09  robertj
  161.  * Removed redundent PAssertNULL.
  162.  *
  163.  * Revision 1.6  1994/08/21  23:43:02  robertj
  164.  * Fixed bug in lists when inserting element.
  165.  *
  166.  * Revision 1.5  1994/07/27  05:58:07  robertj
  167.  * Synchronisation.
  168.  *
  169.  * Revision 1.4  1994/07/17  10:46:06  robertj
  170.  * Fixed searching in sorted lists.
  171.  *
  172.  * Revision 1.3  1994/07/02  03:03:49  robertj
  173.  * Added container searching facilities..
  174.  *
  175.  * Revision 1.2  1994/06/25  11:55:15  robertj
  176.  * Unix version synchronisation.
  177.  *
  178. // Revision 1.1  1994/04/20  12:17:44  robertj
  179. // Initial revision
  180. //
  181.  */
  182. #include <ptlib.h>
  183. #define new PNEW
  184. ///////////////////////////////////////////////////////////////////////////////
  185. void PCollection::PrintOn(ostream &strm) const
  186. {
  187.   for (PINDEX  i = 0; i < GetSize(); i++) {
  188.     PObject * obj = GetAt(i);
  189.     if (obj != NULL)
  190.       strm << *obj;
  191.   }
  192. }
  193. void PCollection::RemoveAll()
  194. {
  195.   while (GetSize() > 0)
  196.     RemoveAt(0);
  197. }
  198. ///////////////////////////////////////////////////////////////////////////////
  199. void PArrayObjects::CopyContents(const PArrayObjects & array)
  200. {
  201.   theArray = array.theArray;
  202. }
  203. void PArrayObjects::DestroyContents()
  204. {
  205.   if (reference->deleteObjects) {
  206.     for (PINDEX i = 0; i < theArray->GetSize(); i++) {
  207.       if ((*theArray)[i] != NULL)
  208.         delete (*theArray)[i];
  209.     }
  210.   }
  211.   delete theArray;
  212. }
  213. void PArrayObjects::RemoveAll()
  214. {
  215.   SetSize(0);
  216. }
  217. void PArrayObjects::CloneContents(const PArrayObjects * array)
  218. {
  219.   ObjPtrArray & oldArray = *array->theArray;
  220.   theArray = new ObjPtrArray(oldArray.GetSize());
  221.   for (PINDEX i = 0; i < GetSize(); i++) {
  222.     PObject * ptr = oldArray[i];
  223.     if (ptr != NULL)
  224.       SetAt(i, ptr->Clone());
  225.   }
  226. }
  227. PObject::Comparison PArrayObjects::Compare(const PObject & obj) const
  228. {
  229.   PAssert(obj.IsDescendant(PArrayObjects::Class()), PInvalidCast);
  230.   const PArrayObjects & other = (const PArrayObjects &)obj;
  231.   PINDEX i;
  232.   for (i = 0; i < GetSize(); i++) {
  233.     if (i >= other.GetSize() || *(*theArray)[i] < *(*other.theArray)[i])
  234.       return LessThan;
  235.     if (*(*theArray)[i] > *(*other.theArray)[i])
  236.       return GreaterThan;
  237.   }
  238.   return i < other.GetSize() ? GreaterThan : EqualTo;
  239. }
  240. PINDEX PArrayObjects::GetSize() const
  241. {
  242.   return theArray->GetSize();
  243. }
  244. BOOL PArrayObjects::SetSize(PINDEX newSize)
  245. {
  246.   PINDEX sz = theArray->GetSize();
  247.   if (reference->deleteObjects && sz > 0) {
  248.     for (PINDEX i = sz; i > newSize; i--) {
  249.       PObject * obj = theArray->GetAt(i-1);
  250.       if (obj != NULL)
  251.         delete obj;
  252.     }
  253.   }
  254.   return theArray->SetSize(newSize);
  255. }
  256. PINDEX PArrayObjects::Append(PObject * obj)
  257. {
  258.   PINDEX where = GetSize();
  259.   SetAt(where, obj);
  260.   return where;
  261. }
  262. PINDEX PArrayObjects::Insert(const PObject & before, PObject * obj)
  263. {
  264.   PINDEX where = GetObjectsIndex(&before);
  265.   InsertAt(where, obj);
  266.   return where;
  267. }
  268. BOOL PArrayObjects::Remove(const PObject * obj)
  269. {
  270.   PINDEX i = GetObjectsIndex(obj);
  271.   if (i == P_MAX_INDEX)
  272.     return FALSE;
  273.   RemoveAt(i);
  274.   return TRUE;
  275. }
  276. PObject * PArrayObjects::GetAt(PINDEX index) const
  277. {
  278.   return (*theArray)[index];
  279. }
  280. BOOL PArrayObjects::SetAt(PINDEX index, PObject * obj)
  281. {
  282.   if (!theArray->SetMinSize(index+1))
  283.     return FALSE;
  284.   PObject * oldObj = theArray->GetAt(index);
  285.   if (oldObj != NULL && reference->deleteObjects)
  286.     delete oldObj;
  287.   (*theArray)[index] = obj;
  288.   return TRUE;
  289. }
  290. PINDEX PArrayObjects::InsertAt(PINDEX index, PObject * obj)
  291. {
  292.   for (PINDEX i = GetSize(); i > index; i--)
  293.     (*theArray)[i] = (*theArray)[i-1];
  294.   (*theArray)[index] = obj;
  295.   return index;
  296. }
  297. PObject * PArrayObjects::RemoveAt(PINDEX index)
  298. {
  299.   PObject * obj = (*theArray)[index];
  300.   PINDEX size = GetSize()-1;
  301.   PINDEX i;
  302.   for (i = index; i < size; i++)
  303.     (*theArray)[i] = (*theArray)[i+1];
  304.   (*theArray)[i] = NULL;
  305.   SetSize(size);
  306.   if (obj != NULL && reference->deleteObjects) {
  307.     delete obj;
  308.     obj = NULL;
  309.   }
  310.   return obj;
  311. }
  312. PINDEX PArrayObjects::GetObjectsIndex(const PObject * obj) const
  313. {
  314.   for (PINDEX i = 0; i < GetSize(); i++) {
  315.     if ((*theArray)[i] == obj)
  316.       return i;
  317.   }
  318.   return P_MAX_INDEX;
  319. }
  320. PINDEX PArrayObjects::GetValuesIndex(const PObject & obj) const
  321. {
  322.   for (PINDEX i = 0; i < GetSize(); i++) {
  323.     PObject * elmt = (*theArray)[i];
  324.     if (elmt != NULL && *elmt == obj)
  325.       return i;
  326.   }
  327.   return P_MAX_INDEX;
  328. }
  329. ///////////////////////////////////////////////////////////////////////////////
  330. void PAbstractList::DestroyContents()
  331. {
  332.   RemoveAll();
  333.   delete info;
  334. }
  335. void PAbstractList::CopyContents(const PAbstractList & list)
  336. {
  337.   info = list.info;
  338. }
  339. void PAbstractList::CloneContents(const PAbstractList * list)
  340. {
  341.   Element * element = list->info->head;
  342.   info = new Info;
  343.   PAssertNULL(info);
  344.   while (element != NULL) {
  345.     Append(element->data->Clone());
  346.     element = element->next;
  347.   }
  348. }
  349. PObject::Comparison PAbstractList::Compare(const PObject & obj) const
  350. {
  351.   PAssert(obj.IsDescendant(PAbstractList::Class()), PInvalidCast);
  352.   Element * elmt1 = info->head;
  353.   Element * elmt2 = ((const PAbstractList &)obj).info->head;
  354.   while (elmt1 != NULL && elmt2 != NULL) {
  355.     if (elmt1 == NULL)
  356.       return LessThan;
  357.     if (elmt2 == NULL)
  358.       return GreaterThan;
  359.     if (*elmt1->data < *elmt2->data)
  360.       return LessThan;
  361.     if (*elmt1->data > *elmt2->data)
  362.       return GreaterThan;
  363.     elmt1 = elmt1->next;
  364.     elmt2 = elmt2->next;
  365.   }
  366.   return EqualTo;
  367. }
  368. BOOL PAbstractList::SetSize(PINDEX)
  369. {
  370.   return TRUE;
  371. }
  372. PINDEX PAbstractList::Append(PObject * obj)
  373. {
  374.   Element * element = new Element(PAssertNULL(obj));
  375.   if (info->tail != NULL)
  376.     info->tail->next = element;
  377.   element->prev = info->tail;
  378.   element->next = NULL;
  379.   if (info->head == NULL)
  380.     info->head = element;
  381.   info->tail = element;
  382.   info->lastElement = element;
  383.   info->lastIndex = GetSize();
  384.   reference->size++;
  385.   return info->lastIndex;
  386. }
  387. PINDEX PAbstractList::Insert(const PObject & before, PObject * obj)
  388. {
  389.   PAssertNULL(obj);
  390.   
  391.   PINDEX where = GetObjectsIndex(&before);
  392.   InsertAt(where, obj);
  393.   return where;
  394. }
  395. PINDEX PAbstractList::InsertAt(PINDEX index, PObject * obj)
  396. {
  397.   PAssertNULL(obj);
  398.   if (index >= GetSize())
  399.     return Append(obj);
  400.   PAssert(SetCurrent(index), PInvalidArrayIndex);
  401.   Element * newElement = new Element(obj);
  402.   if (info->lastElement->prev != NULL)
  403.     info->lastElement->prev->next = newElement;
  404.   else
  405.     info->head = newElement;
  406.   newElement->prev = info->lastElement->prev;
  407.   newElement->next = info->lastElement;
  408.   info->lastElement->prev = newElement;
  409.   info->lastElement = newElement;
  410.   info->lastIndex = index;
  411.   reference->size++;
  412.   return index;
  413. }
  414. BOOL PAbstractList::Remove(const PObject * obj)
  415. {
  416.   PINDEX i = GetObjectsIndex(obj);
  417.   if (i == P_MAX_INDEX)
  418.     return FALSE;
  419.   RemoveAt(i);
  420.   return TRUE;
  421. }
  422. PObject * PAbstractList::RemoveAt(PINDEX index)
  423. {
  424.   PAssert(SetCurrent(index), PInvalidArrayIndex);
  425.   Element * elmt = info->lastElement;
  426.   if (elmt->prev != NULL)
  427.     elmt->prev->next = elmt->next;
  428.   else {
  429.     info->head = elmt->next;
  430.     if (info->head != NULL)
  431.       info->head->prev = NULL;
  432.   }
  433.   if (elmt->next != NULL)
  434.     elmt->next->prev = elmt->prev;
  435.   else {
  436.     info->tail = elmt->prev;
  437.     if (info->tail != NULL)
  438.       info->tail->next = NULL;
  439.   }
  440.   if (elmt->next != NULL)
  441.     info->lastElement = elmt->next;
  442.   else {
  443.     info->lastElement = elmt->prev;
  444.     info->lastIndex--;
  445.   }
  446.   reference->size--;
  447.   PObject * obj = elmt->data;
  448.   if (obj != NULL && reference->deleteObjects) {
  449.     delete obj;
  450.     obj = NULL;
  451.   }
  452.   delete elmt;
  453.   return obj;
  454. }
  455. PObject * PAbstractList::GetAt(PINDEX index) const
  456. {
  457.   return SetCurrent(index) ? info->lastElement->data : (PObject *)NULL;
  458. }
  459. BOOL PAbstractList::SetAt(PINDEX index, PObject * val)
  460. {
  461.   if (!SetCurrent(index))
  462.     return FALSE;
  463.   info->lastElement->data = val;
  464.   return TRUE;
  465. }
  466. PINDEX PAbstractList::GetObjectsIndex(const PObject * obj) const
  467. {
  468.   PINDEX index = 0;
  469.   Element * element = info->head;
  470.   while (element != NULL) {
  471.     if (element->data == obj) {
  472.       info->lastElement = element;
  473.       info->lastIndex = index;
  474.       return index;
  475.     }
  476.     element = element->next;
  477.     index++;
  478.   }
  479.   return P_MAX_INDEX;
  480. }
  481. PINDEX PAbstractList::GetValuesIndex(const PObject & obj) const
  482. {
  483.   PINDEX index = 0;
  484.   Element * element = info->head;
  485.   while (element != NULL) {
  486.     if (*element->data == obj) {
  487.       info->lastElement = element;
  488.       info->lastIndex = index;
  489.       return index;
  490.     }
  491.     element = element->next;
  492.     index++;
  493.   }
  494.   return P_MAX_INDEX;
  495. }
  496. BOOL PAbstractList::SetCurrent(PINDEX index) const
  497. {
  498.   if (index >= GetSize())
  499.     return FALSE;
  500.   if (info->lastElement == NULL || info->lastIndex >= GetSize() || 
  501.       index < info->lastIndex/2 || index > (info->lastIndex+GetSize())/2) {
  502.     if (index < GetSize()/2) {
  503.       info->lastIndex = 0;
  504.       info->lastElement = info->head;
  505.     }
  506.     else {
  507.       info->lastIndex = GetSize()-1;
  508.       info->lastElement = info->tail;
  509.     }
  510.   }
  511.   while (info->lastIndex < index) {
  512.     info->lastElement = info->lastElement->next;
  513.     info->lastIndex++;
  514.   }
  515.   while (info->lastIndex > index) {
  516.     info->lastElement = info->lastElement->prev;
  517.     info->lastIndex--;
  518.   }
  519.   return TRUE;
  520. }
  521. PAbstractList::Element::Element(PObject * theData)
  522. {
  523.   next = prev = NULL;
  524.   data = theData;
  525. }
  526. ///////////////////////////////////////////////////////////////////////////////
  527. PAbstractSortedList::Element nil = NULL;
  528. PAbstractSortedList::PAbstractSortedList()
  529. {
  530.   info = new Info;
  531.   PAssert(info != NULL, POutOfMemory);
  532. }
  533. void PAbstractSortedList::DestroyContents()
  534. {
  535.   RemoveAll();
  536.   delete info;
  537. }
  538. void PAbstractSortedList::CopyContents(const PAbstractSortedList & list)
  539. {
  540.   info = list.info;
  541. }
  542. void PAbstractSortedList::CloneContents(const PAbstractSortedList * list)
  543. {
  544.   Element * element = list->info->root;
  545.   while (element->left != &nil)
  546.     element = element->left;
  547.   info = new Info;
  548.   PAssertNULL(info);
  549.   while (element != &nil) {
  550.     Append(element->data->Clone());
  551.     element = element->Successor();
  552.   }
  553. }
  554. BOOL PAbstractSortedList::SetSize(PINDEX)
  555. {
  556.   return TRUE;
  557. }
  558. PObject::Comparison PAbstractSortedList::Compare(const PObject & obj) const
  559. {
  560.   PAssert(obj.IsDescendant(PAbstractSortedList::Class()), PInvalidCast);
  561.   Element * elmt1 = info->root;
  562.   while (elmt1->left != &nil)
  563.     elmt1 = elmt1->left;
  564.   Element * elmt2 = ((const PAbstractSortedList &)obj).info->root;
  565.   while (elmt2->left != &nil)
  566.     elmt2 = elmt2->left;
  567.   while (elmt1 != &nil && elmt2 != &nil) {
  568.     if (elmt1 == &nil)
  569.       return LessThan;
  570.     if (elmt2 == &nil)
  571.       return GreaterThan;
  572.     if (*elmt1->data < *elmt2->data)
  573.       return LessThan;
  574.     if (*elmt1->data > *elmt2->data)
  575.       return GreaterThan;
  576.     elmt1 = elmt1->Successor();
  577.     elmt2 = elmt2->Successor();
  578.   }
  579.   return EqualTo;
  580. }
  581. PINDEX PAbstractSortedList::Append(PObject * obj)
  582. {
  583.   Element * z = new Element(PAssertNULL(obj));
  584.   Element * x = info->root;
  585.   Element * y = &nil;
  586.   while (x != &nil) {
  587.     x->subTreeSize++;
  588.     y = x;
  589.     x = *z->data < *x->data ? x->left : x->right;
  590.   }
  591.   z->parent = y;
  592.   if (y == &nil)
  593.     info->root = z;
  594.   else if (*z->data < *y->data)
  595.     y->left = z;
  596.   else
  597.     y->right = z;
  598.   info->lastElement = x = z;
  599.   x->colour = Element::Red;
  600.   while (x != info->root && x->parent->colour == Element::Red) {
  601.     if (x->parent == x->parent->parent->left) {
  602.       y = x->parent->parent->right;
  603.       if (y->colour == Element::Red) {
  604.         x->parent->colour = Element::Black;
  605.         y->colour = Element::Black;
  606.         x->parent->parent->colour = Element::Red;
  607.         x = x->parent->parent;
  608.       }
  609.       else {
  610.         if (x == x->parent->right) {
  611.           x = x->parent;
  612.           LeftRotate(x);
  613.         }
  614.         x->parent->colour = Element::Black;
  615.         x->parent->parent->colour = Element::Red;
  616.         RightRotate(x->parent->parent);
  617.       }
  618.     }
  619.     else {
  620.       y = x->parent->parent->left;
  621.       if (y->colour == Element::Red) {
  622.         x->parent->colour = Element::Black;
  623.         y->colour = Element::Black;
  624.         x->parent->parent->colour = Element::Red;
  625.         x = x->parent->parent;
  626.       }
  627.       else {
  628.         if (x == x->parent->left) {
  629.           x = x->parent;
  630.           RightRotate(x);
  631.         }
  632.         x->parent->colour = Element::Black;
  633.         x->parent->parent->colour = Element::Red;
  634.         LeftRotate(x->parent->parent);
  635.       }
  636.     }
  637.   }
  638.   info->root->colour = Element::Black;
  639.   x = info->lastElement;
  640.   info->lastIndex = x->left->subTreeSize;
  641.   while (x != info->root) {
  642.     if (x != x->parent->left)
  643.       info->lastIndex += x->parent->left->subTreeSize+1;
  644.     x = x->parent;
  645.   }
  646.   reference->size++;
  647.   return info->lastIndex;
  648. }
  649. BOOL PAbstractSortedList::Remove(const PObject * obj)
  650. {
  651.   Element * element = info->root;
  652.   while (element != &nil && element->data != obj)
  653.     element = *obj < *element->data ? element->left : element->right;
  654.   if (element == &nil)
  655.     return FALSE;
  656.   RemoveElement(element);
  657.   return TRUE;
  658. }
  659. PObject * PAbstractSortedList::RemoveAt(PINDEX index)
  660. {
  661.   Element * node = info->root->OrderSelect(index+1);
  662.   PObject * data = node->data;
  663.   RemoveElement(node);
  664.   return reference->deleteObjects ? (PObject *)NULL : data;
  665. }
  666. void PAbstractSortedList::RemoveAll()
  667. {
  668.   if (info->root != &nil) {
  669.     info->root->DeleteSubTrees(reference->deleteObjects);
  670.     delete info->root;
  671.     info->root = &nil;
  672.     reference->size = 0;
  673.   }
  674. }
  675. PINDEX PAbstractSortedList::Insert(const PObject &, PObject * obj)
  676. {
  677.   return Append(obj);
  678. }
  679. PINDEX PAbstractSortedList::InsertAt(PINDEX, PObject * obj)
  680. {
  681.   return Append(obj);
  682. }
  683. BOOL PAbstractSortedList::SetAt(PINDEX, PObject *)
  684. {
  685.   return FALSE;
  686. }
  687. PObject * PAbstractSortedList::GetAt(PINDEX index) const
  688. {
  689.   if (index >= GetSize())
  690.     return NULL;
  691.   if (index != info->lastIndex) {
  692.     if (index == info->lastIndex-1) {
  693.       info->lastIndex--;
  694.       info->lastElement = info->lastElement->Predecessor();
  695.     }
  696.     else if (index == info->lastIndex+1 && info->lastElement != NULL) {
  697.       info->lastIndex++;
  698.       info->lastElement = info->lastElement->Successor();
  699.     }
  700.     else {
  701.       info->lastIndex = index;
  702.       info->lastElement = info->root->OrderSelect(index+1);
  703.     }
  704.   }
  705.   return PAssertNULL(info->lastElement)->data;
  706. }
  707. PINDEX PAbstractSortedList::GetObjectsIndex(const PObject * obj) const
  708. {
  709.   Element * elmt = NULL;
  710.   PINDEX pos = info->root->ValueSelect(*obj, elmt);
  711.   if (pos == P_MAX_INDEX)
  712.     return P_MAX_INDEX;
  713.   if (elmt->data != obj) {
  714.     PINDEX savePos = pos;
  715.     Element * saveElmt = elmt;
  716.     while (elmt->data != obj &&
  717.             (elmt = elmt->Predecessor()) != &nil &&
  718.             *obj == *elmt->data)
  719.       pos--;
  720.     if (elmt->data != obj) {
  721.       pos = savePos;
  722.       elmt = saveElmt;
  723.       while (elmt->data != obj &&
  724.               (elmt = elmt->Successor()) != &nil &&
  725.               *obj == *elmt->data)
  726.         pos++;
  727.       if (elmt->data != obj)
  728.         return P_MAX_INDEX;
  729.     }
  730.   }
  731.   info->lastIndex = pos;
  732.   info->lastElement = elmt;
  733.   return pos;
  734. }
  735. PINDEX PAbstractSortedList::GetValuesIndex(const PObject & obj) const
  736. {
  737.   PINDEX pos = info->root->ValueSelect(obj, info->lastElement);
  738.   if (pos == P_MAX_INDEX)
  739.     return P_MAX_INDEX;
  740.   info->lastIndex = pos;
  741.   Element * prev;
  742.   while ((prev = info->lastElement->Predecessor()) != &nil && obj == *prev->data) {
  743.     info->lastElement = prev;
  744.     info->lastIndex--;
  745.   }
  746.   return info->lastIndex;
  747. }
  748. void PAbstractSortedList::RemoveElement(Element * node)
  749. {
  750.   PAssertNULL(node);
  751.   if (node->data != NULL && reference->deleteObjects)
  752.     delete node->data;
  753.   Element * y = node->left == &nil || node->right == &nil ? node : node->Successor();
  754.   Element * t = y;
  755.   while (t != &nil) {
  756.     t->subTreeSize--;
  757.     t = t->parent;
  758.   }
  759.   Element * x = y->left != &nil ? y->left : y->right;
  760.   x->parent = y->parent;
  761.   if (y->parent == &nil)
  762.     info->root = x;
  763.   else if (y == y->parent->left)
  764.     y->parent->left = x;
  765.   else
  766.     y->parent->right = x;
  767.   if (y != node)
  768.     node->data = y->data;
  769.   if (y->colour == Element::Black) {
  770.     while (x != info->root && x->colour == Element::Black) {
  771.       if (x == x->parent->left) {
  772.         Element * w = x->parent->right;
  773.         if (w->colour == Element::Red) {
  774.           w->colour = Element::Black;
  775.           x->parent->colour = Element::Red;
  776.           LeftRotate(x->parent);
  777.           w = x->parent->right;
  778.         }
  779.         if (w->left->colour == Element::Black && w->right->colour == Element::Black) {
  780.           w->colour = Element::Red;
  781.           x = x->parent;
  782.         }
  783.         else {
  784.           if (w->right->colour == Element::Black) {
  785.             w->left->colour = Element::Black;
  786.             w->colour = Element::Red;
  787.             RightRotate(w);
  788.             w = x->parent->right;
  789.           }
  790.           w->colour = x->parent->colour;
  791.           x->parent->colour = Element::Black;
  792.           w->right->colour = Element::Black;
  793.           LeftRotate(x->parent);
  794.           x = info->root;
  795.         }
  796.       }
  797.       else {
  798.         Element * w = x->parent->left;
  799.         if (w->colour == Element::Red) {
  800.           w->colour = Element::Black;
  801.           x->parent->colour = Element::Red;
  802.           RightRotate(x->parent);
  803.           w = x->parent->left;
  804.         }
  805.         if (w->right->colour == Element::Black && w->left->colour == Element::Black) {
  806.           w->colour = Element::Red;
  807.           x = x->parent;
  808.         }
  809.         else {
  810.           if (w->left->colour == Element::Black) {
  811.             w->right->colour = Element::Black;
  812.             w->colour = Element::Red;
  813.             LeftRotate(w);
  814.             w = x->parent->left;
  815.           }
  816.           w->colour = x->parent->colour;
  817.           x->parent->colour = Element::Black;
  818.           w->left->colour = Element::Black;
  819.           RightRotate(x->parent);
  820.           x = info->root;
  821.         }
  822.       }
  823.     }
  824.     x->colour = Element::Black;
  825.   }
  826.   delete y;
  827.   reference->size--;
  828.   info->lastIndex = P_MAX_INDEX;
  829.   info->lastElement = NULL;
  830. }
  831. void PAbstractSortedList::LeftRotate(Element * node)
  832. {
  833.   Element * pivot = PAssertNULL(node)->right;
  834.   node->right = pivot->left;
  835.   if (pivot->left != &nil)
  836.     pivot->left->parent = node;
  837.   pivot->parent = node->parent;
  838.   if (node->parent == &nil)
  839.     info->root = pivot;
  840.   else if (node == node->parent->left)
  841.     node->parent->left = pivot;
  842.   else
  843.     node->parent->right = pivot;
  844.   pivot->left = node;
  845.   node->parent = pivot;
  846.   pivot->subTreeSize = node->subTreeSize;
  847.   node->subTreeSize = node->left->subTreeSize + node->right->subTreeSize + 1;
  848. }
  849. void PAbstractSortedList::RightRotate(Element * node)
  850. {
  851.   Element * pivot = PAssertNULL(node)->left;
  852.   node->left = pivot->right;
  853.   if (pivot->right != &nil)
  854.     pivot->right->parent = node;
  855.   pivot->parent = node->parent;
  856.   if (node->parent == &nil)
  857.     info->root = pivot;
  858.   else if (node == node->parent->right)
  859.     node->parent->right = pivot;
  860.   else
  861.     node->parent->left = pivot;
  862.   pivot->right = node;
  863.   node->parent = pivot;
  864.   pivot->subTreeSize = node->subTreeSize;
  865.   node->subTreeSize = node->left->subTreeSize + node->right->subTreeSize + 1;
  866. }
  867. PAbstractSortedList::Element::Element(PObject * theData)
  868. {
  869.   parent = left = right = &nil;
  870.   colour = Black;
  871.   subTreeSize = theData != NULL ? 1 : 0;
  872.   data = theData;
  873. }
  874. PAbstractSortedList::Element * PAbstractSortedList::Element::Successor() const
  875. {
  876.   Element * next;
  877.   if (right != &nil) {
  878.     next = right;
  879.     while (next->left != &nil)
  880.       next = next->left;
  881.   }
  882.   else {
  883.     next = parent;
  884.     const Element * node = this;
  885.     while (next != &nil && node == next->right) {
  886.       node = next;
  887.       next = node->parent;
  888.     }
  889.   }
  890.   return next;
  891. }
  892. PAbstractSortedList::Element*PAbstractSortedList::Element::Predecessor() const
  893. {
  894.   Element * pred;
  895.   if (left != &nil) {
  896.     pred = left;
  897.     while (pred->right != &nil)
  898.       pred = pred->right;
  899.   }
  900.   else {
  901.     pred = parent;
  902.     const Element * node = this;
  903.     while (pred != &nil && node == pred->left) {
  904.       node = pred;
  905.       pred = node->parent;
  906.     }
  907.   }
  908.   return pred;
  909. }
  910. PAbstractSortedList::Element * PAbstractSortedList::Element::OrderSelect(PINDEX index)
  911. {
  912.   PINDEX r = left->subTreeSize+1;
  913.   if (index == r)
  914.     return this;
  915.   if (index < r) {
  916.     if (left != &nil)
  917.       return left->OrderSelect(index);
  918.   }
  919.   else {
  920.     if (right != &nil)
  921.       return right->OrderSelect(index - r);
  922.   }
  923.   PAssertAlways("Order select failed!");
  924.   return &nil;
  925. }
  926. PINDEX PAbstractSortedList::Element::ValueSelect(const PObject & obj,
  927.                                                  Element * & lastElement)
  928. {
  929.   if (this != &nil) {
  930.     switch (data->Compare(obj)) {
  931.       case PObject::LessThan :
  932.       {
  933.         PINDEX index = right->ValueSelect(obj, lastElement);
  934.         if (index != P_MAX_INDEX)
  935.           return left->subTreeSize + index + 1;
  936.         break;
  937.       }
  938.       case PObject::GreaterThan :
  939.         return left->ValueSelect(obj, lastElement);
  940.       default :
  941.         lastElement = this;
  942.         return left->subTreeSize;
  943.     }
  944.   }
  945.   return P_MAX_INDEX;
  946. }
  947. void PAbstractSortedList::Element::DeleteSubTrees(BOOL deleteObject)
  948. {
  949.   if (left != &nil) {
  950.     left->DeleteSubTrees(deleteObject);
  951.     delete left;
  952.     left = &nil;
  953.   }
  954.   if (right != &nil) {
  955.     right->DeleteSubTrees(deleteObject);
  956.     delete right;
  957.     right = &nil;
  958.   }
  959.   if (deleteObject) {
  960.     delete data;
  961.     data = NULL;
  962.   }
  963. }
  964. PAbstractSortedList::Info::Info()
  965. {
  966.   root = &nil;
  967.   lastElement = NULL;
  968.   lastIndex = P_MAX_INDEX;
  969. }
  970. ///////////////////////////////////////////////////////////////////////////////
  971. PObject * POrdinalKey::Clone() const
  972. {
  973.   return new POrdinalKey(theKey);
  974. }
  975. PObject::Comparison POrdinalKey::Compare(const PObject & obj) const
  976. {
  977.   PAssert(obj.IsDescendant(POrdinalKey::Class()), PInvalidCast);
  978.   const POrdinalKey & other = (const POrdinalKey &)obj;
  979.   
  980.   if (theKey < other.theKey)
  981.     return LessThan;
  982.   if (theKey > other.theKey)
  983.     return GreaterThan;
  984.   return EqualTo;
  985. }
  986. PINDEX POrdinalKey::HashFunction() const
  987. {
  988.   return PABSINDEX(theKey)%23;
  989. }
  990. void POrdinalKey::PrintOn(ostream & strm) const
  991. {
  992.   strm << theKey;
  993. }
  994. ///////////////////////////////////////////////////////////////////////////////
  995. void PHashTable::Table::DestroyContents()
  996. {
  997.   for (PINDEX i = 0; i < GetSize(); i++) {
  998.     Element * list = GetAt(i);
  999.     if (list != NULL) {
  1000.       Element * elmt = list;
  1001.       do {
  1002.         Element * nextElmt = elmt->next;
  1003.         if (elmt->data != NULL && reference->deleteObjects)
  1004.           delete elmt->data;
  1005.         if (deleteKeys)
  1006.           delete elmt->key;
  1007.         delete elmt;
  1008.         elmt = nextElmt;
  1009.       } while (elmt != list);
  1010.     }
  1011.   }
  1012.   PAbstractArray::DestroyContents();
  1013. }
  1014. PINDEX PHashTable::Table::AppendElement(PObject * key, PObject * data)
  1015. {
  1016.   lastElement = NULL;
  1017.   PINDEX bucket = PAssertNULL(key)->HashFunction();
  1018.   Element * list = GetAt(bucket);
  1019.   Element * element = new Element;
  1020.   PAssertNULL(element);
  1021.   element->key = key;
  1022.   element->data = data;
  1023.   if (list == NULL) {
  1024.     element->next = element->prev = element;
  1025.     SetAt(bucket, element);
  1026.   }
  1027.   else if (list == list->prev) {
  1028.     list->next = list->prev = element;
  1029.     element->next = element->prev = list;
  1030.   }
  1031.   else {
  1032.     element->next = list;
  1033.     element->prev = list->prev;
  1034.     list->prev->next = element;
  1035.     list->prev = element;
  1036.   }
  1037.   lastElement = element;
  1038.   lastIndex = P_MAX_INDEX;
  1039.   return bucket;
  1040. }
  1041. PObject * PHashTable::Table::RemoveElement(const PObject & key)
  1042. {
  1043.   PObject * obj = NULL;
  1044.   if (GetElementAt(key) != NULL) {
  1045.     if (lastElement == lastElement->prev)
  1046.       SetAt(key.HashFunction(), NULL);
  1047.     else {
  1048.       lastElement->prev->next = lastElement->next;
  1049.       lastElement->next->prev = lastElement->prev;
  1050.       SetAt(key.HashFunction(), lastElement->next);
  1051.     }
  1052.     obj = lastElement->data;
  1053.     if (deleteKeys)
  1054.       delete lastElement->key;
  1055.     delete lastElement;
  1056.     lastElement = NULL;
  1057.   }
  1058.   return obj;
  1059. }
  1060. BOOL PHashTable::Table::SetLastElementAt(PINDEX index)
  1061. {
  1062.   if (index == 0 || lastElement == NULL || lastIndex == P_MAX_INDEX) {
  1063.     lastIndex = 0;
  1064.     lastBucket = 0;
  1065.     while ((lastElement = GetAt(lastBucket)) == NULL) {
  1066.       if (lastBucket >= GetSize())
  1067.         return FALSE;
  1068.       lastBucket++;
  1069.     }
  1070.   }
  1071.   if (lastIndex == index)
  1072.     return TRUE;
  1073.   if (lastIndex < index) {
  1074.     while (lastIndex != index) {
  1075.       if (lastElement->next != operator[](lastBucket))
  1076.         lastElement = lastElement->next;
  1077.       else {
  1078.         do {
  1079.           if (++lastBucket >= GetSize())
  1080.             return FALSE;
  1081.         } while ((lastElement = operator[](lastBucket)) == NULL);
  1082.       }
  1083.       lastIndex++;
  1084.     }
  1085.   }
  1086.   else {
  1087.     while (lastIndex != index) {
  1088.       if (lastElement != operator[](lastBucket))
  1089.         lastElement = lastElement->prev;
  1090.       else {
  1091.         do {
  1092.           if (lastBucket-- == 0)
  1093.             return FALSE;
  1094.         } while ((lastElement = operator[](lastBucket)) == NULL);
  1095.         lastElement = lastElement->prev;
  1096.       }
  1097.       lastIndex--;
  1098.     }
  1099.   }
  1100.   return TRUE;
  1101. }
  1102. PHashTable::Element * PHashTable::Table::GetElementAt(const PObject & key)
  1103. {
  1104.   if (lastElement != NULL && *lastElement->key == key)
  1105.     return lastElement;
  1106.   Element * list = GetAt(key.HashFunction());
  1107.   if (list != NULL) {
  1108.     Element * element = list;
  1109.     do {
  1110.       if (*element->key == key) {
  1111.         lastElement = element;
  1112.         lastIndex = P_MAX_INDEX;
  1113.         return lastElement;
  1114.       }
  1115.       element = element->next;
  1116.     } while (element != list);
  1117.   }
  1118.   return NULL;
  1119. }
  1120. PINDEX PHashTable::Table::GetElementsIndex(
  1121.                            const PObject * obj, BOOL byValue, BOOL keys) const
  1122. {
  1123.   PINDEX index = 0;
  1124.   for (PINDEX i = 0; i < GetSize(); i++) {
  1125.     Element * list = operator[](i);
  1126.     if (list != NULL) {
  1127.       Element * element = list;
  1128.       do {
  1129.         PObject * keydata = keys ? element->key : element->data;
  1130.         if (byValue ? (*keydata == *obj) : (keydata == obj))
  1131.           return index;
  1132.         element = element->next;
  1133.         index++;
  1134.       } while (element != list);
  1135.     }
  1136.   }
  1137.   return P_MAX_INDEX;
  1138. }
  1139. ///////////////////////////////////////////////////////////////////////////////
  1140. PHashTable::PHashTable()
  1141.   : hashTable(new PHashTable::Table)
  1142. {
  1143.   PAssertNULL(hashTable);
  1144.   hashTable->lastElement = NULL;
  1145. }
  1146. void PHashTable::DestroyContents()
  1147. {
  1148.   hashTable->reference->deleteObjects = reference->deleteObjects;
  1149.   delete hashTable;
  1150. }
  1151. void PHashTable::CopyContents(const PHashTable & hash)
  1152. {
  1153.   hashTable = hash.hashTable;
  1154. }
  1155.   
  1156. void PHashTable::CloneContents(const PHashTable * hash)
  1157. {
  1158.   PAssertNULL(hash);
  1159.   PINDEX sz = hash->GetSize();
  1160.   PAssertNULL(hash->hashTable);
  1161.   PHashTable::Table * original = hash->hashTable;
  1162.   hashTable = new PHashTable::Table(original->GetSize());
  1163.   PAssertNULL(hashTable);
  1164.   hashTable->lastElement = NULL;
  1165.   for (PINDEX i = 0; i < sz; i++) {
  1166.     original->SetLastElementAt(i);
  1167.     PObject * data = original->lastElement->data;
  1168.     if (data != NULL)
  1169.       data = data->Clone();
  1170.     hashTable->AppendElement(original->lastElement->key->Clone(), data);
  1171.   }
  1172. }
  1173. PObject::Comparison PHashTable::Compare(const PObject & obj) const
  1174. {
  1175.   PAssert(obj.IsDescendant(PHashTable::Class()), PInvalidCast);
  1176.   return reference != ((const PHashTable &)obj).reference
  1177.                                                       ? GreaterThan : EqualTo;
  1178. }
  1179. BOOL PHashTable::SetSize(PINDEX)
  1180. {
  1181.   return TRUE;
  1182. }
  1183. PObject & PHashTable::AbstractGetDataAt(PINDEX index) const
  1184. {
  1185.   PAssert(hashTable->SetLastElementAt(index), PInvalidArrayIndex);
  1186.   return *hashTable->lastElement->data;
  1187. }
  1188. const PObject & PHashTable::AbstractGetKeyAt(PINDEX index) const
  1189. {
  1190.   PAssert(hashTable->SetLastElementAt(index), PInvalidArrayIndex);
  1191.   return *hashTable->lastElement->key;
  1192. }
  1193. ///////////////////////////////////////////////////////////////////////////////
  1194. void PAbstractSet::DestroyContents()
  1195. {
  1196.   hashTable->deleteKeys = reference->deleteObjects;
  1197.   PHashTable::DestroyContents();
  1198. }
  1199. void PAbstractSet::CopyContents(const PAbstractSet & )
  1200. {
  1201. }
  1202.   
  1203. void PAbstractSet::CloneContents(const PAbstractSet * )
  1204. {
  1205. }
  1206. PINDEX PAbstractSet::Append(PObject * obj)
  1207. {
  1208.   if (AbstractContains(*obj)) {
  1209.     if (reference->deleteObjects)
  1210.       delete obj;
  1211.     return P_MAX_INDEX;
  1212.   }
  1213.   reference->size++;
  1214.   return hashTable->AppendElement(obj, NULL);
  1215. }
  1216. PINDEX PAbstractSet::Insert(const PObject &, PObject * obj)
  1217. {
  1218.   return Append(obj);
  1219. }
  1220. PINDEX PAbstractSet::InsertAt(PINDEX, PObject * obj)
  1221. {
  1222.   return Append(obj);
  1223. }
  1224. BOOL PAbstractSet::Remove(const PObject * obj)
  1225. {
  1226.   if (hashTable->GetElementAt(*PAssertNULL(obj)) == NULL)
  1227.     return FALSE;
  1228.   hashTable->deleteKeys = hashTable->reference->deleteObjects = reference->deleteObjects;
  1229.   hashTable->RemoveElement(*obj);
  1230.   reference->size--;
  1231.   return TRUE;
  1232. }
  1233. PObject * PAbstractSet::RemoveAt(PINDEX index)
  1234. {
  1235.   if (!hashTable->SetLastElementAt(index))
  1236.     return NULL;
  1237.   PObject * obj = hashTable->lastElement->key;
  1238.   hashTable->deleteKeys = hashTable->reference->deleteObjects = reference->deleteObjects;
  1239.   hashTable->RemoveElement(*obj);
  1240.   reference->size--;
  1241.   return obj;
  1242. }
  1243. PINDEX PAbstractSet::GetObjectsIndex(const PObject * obj) const
  1244. {
  1245.   return hashTable->GetElementsIndex(obj, FALSE, TRUE);
  1246. }
  1247. PINDEX PAbstractSet::GetValuesIndex(const PObject & obj) const
  1248. {
  1249.   return hashTable->GetElementsIndex(&obj, TRUE, TRUE);
  1250. }
  1251. PObject * PAbstractSet::GetAt(PINDEX index) const
  1252. {
  1253.   return (PObject *)&AbstractGetKeyAt(index);
  1254. }
  1255. BOOL PAbstractSet::SetAt(PINDEX, PObject * obj)
  1256. {
  1257.   return Append(obj);
  1258. }
  1259. ///////////////////////////////////////////////////////////////////////////////
  1260. PINDEX PAbstractDictionary::Append(PObject *)
  1261. {
  1262.   PAssertAlways(PUnimplementedFunction);
  1263.   return 0;
  1264. }
  1265. PINDEX PAbstractDictionary::Insert(const PObject & before, PObject * obj)
  1266. {
  1267.   AbstractSetAt(before, obj);
  1268.   return 0;
  1269. }
  1270. PINDEX PAbstractDictionary::InsertAt(PINDEX index, PObject * obj)
  1271. {
  1272.   AbstractSetAt(AbstractGetKeyAt(index), obj);
  1273.   return index;
  1274. }
  1275.  
  1276.  
  1277. BOOL PAbstractDictionary::Remove(const PObject *)
  1278. {
  1279.   PAssertAlways(PUnimplementedFunction);
  1280.   return FALSE;
  1281. }
  1282. PObject * PAbstractDictionary::RemoveAt(PINDEX index)
  1283. {
  1284.   PObject & obj = AbstractGetDataAt(index);
  1285.   AbstractSetAt(AbstractGetKeyAt(index), NULL);
  1286.   return &obj;
  1287. }
  1288. PINDEX PAbstractDictionary::GetObjectsIndex(const PObject * obj) const
  1289. {
  1290.   return hashTable->GetElementsIndex(obj, FALSE, FALSE);
  1291. }
  1292. PINDEX PAbstractDictionary::GetValuesIndex(const PObject & obj) const
  1293. {
  1294.   return hashTable->GetElementsIndex(&obj, TRUE, FALSE);
  1295. }
  1296. BOOL PAbstractDictionary::SetAt(PINDEX index, PObject * val)
  1297. {
  1298.   return AbstractSetAt(POrdinalKey(index), val);
  1299. }
  1300. PObject * PAbstractDictionary::GetAt(PINDEX index) const
  1301. {
  1302.   return AbstractGetAt(POrdinalKey(index));
  1303. }
  1304.  
  1305.  
  1306. BOOL PAbstractDictionary::SetDataAt(PINDEX index, PObject * val)
  1307. {
  1308.   return AbstractSetAt(AbstractGetKeyAt(index), val);
  1309. }
  1310. BOOL PAbstractDictionary::AbstractSetAt(const PObject & key, PObject * obj)
  1311. {
  1312.   if (obj == NULL) {
  1313.     obj = hashTable->RemoveElement(key);
  1314.     if (obj != NULL) {
  1315.       if (reference->deleteObjects)
  1316.         delete obj;
  1317.       reference->size--;
  1318.     }
  1319.   }
  1320.   else {
  1321.     Element * element = hashTable->GetElementAt(key);
  1322.     if (element == NULL) {
  1323.       hashTable->AppendElement(key.Clone(), obj);
  1324.       reference->size++;
  1325.     }
  1326.     else {
  1327.       if (reference->deleteObjects)
  1328.         delete hashTable->lastElement->data;
  1329.       hashTable->lastElement->data = obj;
  1330.     }
  1331.   }
  1332.   return TRUE;
  1333. }
  1334. PObject * PAbstractDictionary::AbstractGetAt(const PObject & key) const
  1335. {
  1336.   Element * element = hashTable->GetElementAt(key);
  1337.   return element != NULL ? element->data : (PObject *)NULL;
  1338. }
  1339. PObject & PAbstractDictionary::GetRefAt(const PObject & key) const
  1340. {
  1341.   Element * element = hashTable->GetElementAt(key);
  1342.   return *PAssertNULL(element)->data;
  1343. }
  1344. void PAbstractDictionary::PrintOn(ostream &strm) const
  1345. {
  1346.   for (PINDEX  i = 0; i < GetSize(); i++)
  1347.     strm << AbstractGetKeyAt(i) << '=' << AbstractGetDataAt(i) << endl;
  1348. }
  1349. // End Of File ///////////////////////////////////////////////////////////////