tesseract 3.04.01

ccutil/elst2.h

Go to the documentation of this file.
00001 /**********************************************************************
00002  * File:        elst2.h  (Formerly elist2.h)
00003  * Description: Double linked embedded list module include file.
00004  * Author:      Phil Cheatle
00005  * Created:     Wed Jan 23 11:04:47 GMT 1991
00006  *
00007  * (C) Copyright 1991, Hewlett-Packard Ltd.
00008  ** Licensed under the Apache License, Version 2.0 (the "License");
00009  ** you may not use this file except in compliance with the License.
00010  ** You may obtain a copy of the License at
00011  ** http://www.apache.org/licenses/LICENSE-2.0
00012  ** Unless required by applicable law or agreed to in writing, software
00013  ** distributed under the License is distributed on an "AS IS" BASIS,
00014  ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00015  ** See the License for the specific language governing permissions and
00016  ** limitations under the License.
00017  *
00018  **********************************************************************/
00019 
00020 #ifndef ELST2_H
00021 #define ELST2_H
00022 
00023 #include <stdio.h>
00024 #include "host.h"
00025 #include "serialis.h"
00026 #include "lsterr.h"
00027 
00028 class ELIST2_ITERATOR;
00029 
00030 /**********************************************************************
00031 DESIGN NOTE
00032 ===========
00033 
00034 It would probably be possible to implement the ELIST2 classes as derived
00035 classes from ELIST.  I haven't done this because:
00036 
00037 a) I think it would be harder to understand the code
00038 (Though the problem with not inheriting is that changes to ELIST must be
00039   reflected in ELIST2 and vice versa)
00040 
00041 b) Most of the code is inline so:
00042 i)  The duplication in source does not affect the run time code size - the
00043     code is copied inline anyway!
00044 
00045   ii) The compiler should have a bit less work to do!
00046 **********************************************************************/
00047 
00048 /**********************************************************************
00049  *                                                      CLASS - ELIST2_LINK
00050  *
00051  *                                                      Generic link class for doubly linked lists with embedded links
00052  *
00053  *  Note:  No destructor - elements are assumed to be destroyed EITHER after
00054  *  they have been extracted from a list OR by the ELIST2 destructor which
00055  *  walks the list.
00056  **********************************************************************/
00057 
00058 class DLLSYM ELIST2_LINK
00059 {
00060   friend class ELIST2_ITERATOR;
00061   friend class ELIST2;
00062 
00063   ELIST2_LINK *prev;
00064   ELIST2_LINK *next;
00065 
00066   public:
00067     ELIST2_LINK() {  //constructor
00068       prev = next = NULL;
00069     }
00070 
00071     ELIST2_LINK(                        //copy constructor
00072                 const ELIST2_LINK &) {  //don't copy link
00073       prev = next = NULL;
00074     }
00075 
00076     void operator= (             //don't copy links
00077     const ELIST2_LINK &) {
00078       prev = next = NULL;
00079     }
00080 };
00081 
00082 /**********************************************************************
00083  * CLASS - ELIST2
00084  *
00085  * Generic list class for doubly linked lists with embedded links
00086  **********************************************************************/
00087 
00088 class DLLSYM ELIST2
00089 {
00090   friend class ELIST2_ITERATOR;
00091 
00092   ELIST2_LINK *last;             //End of list
00093   //(Points to head)
00094   ELIST2_LINK *First() {  // return first
00095     return last ? last->next : NULL;
00096   }
00097 
00098   public:
00099     ELIST2() {  //constructor
00100       last = NULL;
00101     }
00102 
00103     void internal_clear (        //destroy all links
00104       void (*zapper) (ELIST2_LINK *));
00105     //ptr to zapper functn
00106 
00107     bool empty() const {  //is list empty?
00108       return !last;
00109     }
00110 
00111     bool singleton() const {
00112       return last ? (last == last->next) : false;
00113     }
00114 
00115     void shallow_copy(                      //dangerous!!
00116                       ELIST2 *from_list) {  //beware destructors!!
00117       last = from_list->last;
00118     }
00119 
00120                                  //ptr to copier functn
00121     void internal_deep_copy (ELIST2_LINK * (*copier) (ELIST2_LINK *),
00122       const ELIST2 * list);      //list being copied
00123 
00124     void assign_to_sublist(                            //to this list
00125                            ELIST2_ITERATOR *start_it,  //from list start
00126                            ELIST2_ITERATOR *end_it);   //from list end
00127 
00128     inT32 length() const;  // # elements in list
00129 
00130     void sort (                  //sort elements
00131       int comparator (           //comparison routine
00132       const void *, const void *));
00133 
00134     // Assuming list has been sorted already, insert new_link to
00135     // keep the list sorted according to the same comparison function.
00136     // Comparison function is the same as used by sort, i.e. uses double
00137     // indirection. Time is O(1) to add to beginning or end.
00138     // Time is linear to add pre-sorted items to an empty list.
00139     void add_sorted(int comparator(const void*, const void*),
00140                     ELIST2_LINK* new_link);
00141 
00142 };
00143 
00144 /***********************************************************************
00145  *                                                      CLASS - ELIST2_ITERATOR
00146  *
00147  *                                                      Generic iterator class for doubly linked lists with embedded links
00148  **********************************************************************/
00149 
00150 class DLLSYM ELIST2_ITERATOR
00151 {
00152   friend void ELIST2::assign_to_sublist(ELIST2_ITERATOR *, ELIST2_ITERATOR *);
00153 
00154   ELIST2 *list;                  //List being iterated
00155   ELIST2_LINK *prev;             //prev element
00156   ELIST2_LINK *current;          //current element
00157   ELIST2_LINK *next;             //next element
00158   BOOL8 ex_current_was_last;     //current extracted
00159   //was end of list
00160   BOOL8 ex_current_was_cycle_pt; //current extracted
00161   //was cycle point
00162   ELIST2_LINK *cycle_pt;         //point we are cycling
00163   //the list to.
00164   BOOL8 started_cycling;         //Have we moved off
00165   //the start?
00166 
00167   ELIST2_LINK *extract_sublist(                             //from this current...
00168                                ELIST2_ITERATOR *other_it);  //to other current
00169 
00170   public:
00171     ELIST2_ITERATOR() {  //constructor
00172       list = NULL;
00173     }                            //unassigned list
00174 
00175     ELIST2_ITERATOR(  //constructor
00176                     ELIST2 *list_to_iterate);
00177 
00178     void set_to_list(  //change list
00179                      ELIST2 *list_to_iterate);
00180 
00181     void add_after_then_move(                         //add after current &
00182                              ELIST2_LINK *new_link);  //move to new
00183 
00184     void add_after_stay_put(                         //add after current &
00185                             ELIST2_LINK *new_link);  //stay at current
00186 
00187     void add_before_then_move(                         //add before current &
00188                               ELIST2_LINK *new_link);  //move to new
00189 
00190     void add_before_stay_put(                         //add before current &
00191                              ELIST2_LINK *new_link);  //stay at current
00192 
00193     void add_list_after(                       //add a list &
00194                         ELIST2 *list_to_add);  //stay at current
00195 
00196     void add_list_before(                       //add a list &
00197                          ELIST2 *list_to_add);  //move to it 1st item
00198 
00199     ELIST2_LINK *data() {  //get current data
00200     #ifndef NDEBUG
00201       if (!current)
00202         NULL_DATA.error ("ELIST2_ITERATOR::data", ABORT, NULL);
00203       if (!list)
00204         NO_LIST.error ("ELIST2_ITERATOR::data", ABORT, NULL);
00205     #endif
00206       return current;
00207     }
00208 
00209     ELIST2_LINK *data_relative(               //get data + or - ...
00210                                inT8 offset);  //offset from current
00211 
00212     ELIST2_LINK *forward();  //move to next element
00213 
00214     ELIST2_LINK *backward();  //move to prev element
00215 
00216     ELIST2_LINK *extract();  //remove from list
00217 
00218                                  //go to start of list
00219     ELIST2_LINK *move_to_first();
00220 
00221     ELIST2_LINK *move_to_last();  //go to end of list
00222 
00223     void mark_cycle_pt();  //remember current
00224 
00225     BOOL8 empty() {  //is list empty?
00226     #ifndef NDEBUG
00227       if (!list)
00228         NO_LIST.error ("ELIST2_ITERATOR::empty", ABORT, NULL);
00229     #endif
00230       return list->empty ();
00231     }
00232 
00233     BOOL8 current_extracted() {  //current extracted?
00234       return !current;
00235     }
00236 
00237     BOOL8 at_first();  //Current is first?
00238 
00239     BOOL8 at_last();  //Current is last?
00240 
00241     BOOL8 cycled_list();  //Completed a cycle?
00242 
00243     void add_to_end(                         //add at end &
00244                     ELIST2_LINK *new_link);  //don't move
00245 
00246     void exchange(                             //positions of 2 links
00247                   ELIST2_ITERATOR *other_it);  //other iterator
00248 
00249     inT32 length();  //# elements in list
00250 
00251     void sort (                  //sort elements
00252       int comparator (           //comparison routine
00253       const void *, const void *));
00254 
00255 };
00256 
00257 /***********************************************************************
00258  *                                                      ELIST2_ITERATOR::set_to_list
00259  *
00260  *  (Re-)initialise the iterator to point to the start of the list_to_iterate
00261  *  over.
00262  **********************************************************************/
00263 
00264 inline void ELIST2_ITERATOR::set_to_list(  //change list
00265                                          ELIST2 *list_to_iterate) {
00266   #ifndef NDEBUG
00267   if (!list_to_iterate)
00268     BAD_PARAMETER.error ("ELIST2_ITERATOR::set_to_list", ABORT,
00269       "list_to_iterate is NULL");
00270   #endif
00271 
00272   list = list_to_iterate;
00273   prev = list->last;
00274   current = list->First ();
00275   next = current ? current->next : NULL;
00276   cycle_pt = NULL;               //await explicit set
00277   started_cycling = FALSE;
00278   ex_current_was_last = FALSE;
00279   ex_current_was_cycle_pt = FALSE;
00280 }
00281 
00282 
00283 /***********************************************************************
00284  *                                                      ELIST2_ITERATOR::ELIST2_ITERATOR
00285  *
00286  *  CONSTRUCTOR - set iterator to specified list;
00287  **********************************************************************/
00288 
00289 inline ELIST2_ITERATOR::ELIST2_ITERATOR(ELIST2 *list_to_iterate) {
00290   set_to_list(list_to_iterate);
00291 }
00292 
00293 
00294 /***********************************************************************
00295  *                                                      ELIST2_ITERATOR::add_after_then_move
00296  *
00297  *  Add a new element to the list after the current element and move the
00298  *  iterator to the new element.
00299  **********************************************************************/
00300 
00301 inline void ELIST2_ITERATOR::add_after_then_move(  // element to add
00302                                                  ELIST2_LINK *new_element) {
00303   #ifndef NDEBUG
00304   if (!list)
00305     NO_LIST.error ("ELIST2_ITERATOR::add_after_then_move", ABORT, NULL);
00306   if (!new_element)
00307     BAD_PARAMETER.error ("ELIST2_ITERATOR::add_after_then_move", ABORT,
00308       "new_element is NULL");
00309   if (new_element->next)
00310     STILL_LINKED.error ("ELIST2_ITERATOR::add_after_then_move", ABORT, NULL);
00311   #endif
00312 
00313   if (list->empty ()) {
00314     new_element->next = new_element;
00315     new_element->prev = new_element;
00316     list->last = new_element;
00317     prev = next = new_element;
00318   }
00319   else {
00320     new_element->next = next;
00321     next->prev = new_element;
00322 
00323     if (current) {               //not extracted
00324       new_element->prev = current;
00325       current->next = new_element;
00326       prev = current;
00327       if (current == list->last)
00328         list->last = new_element;
00329     }
00330     else {                       //current extracted
00331       new_element->prev = prev;
00332       prev->next = new_element;
00333       if (ex_current_was_last)
00334         list->last = new_element;
00335       if (ex_current_was_cycle_pt)
00336         cycle_pt = new_element;
00337     }
00338   }
00339   current = new_element;
00340 }
00341 
00342 
00343 /***********************************************************************
00344  *                                                      ELIST2_ITERATOR::add_after_stay_put
00345  *
00346  *  Add a new element to the list after the current element but do not move
00347  *  the iterator to the new element.
00348  **********************************************************************/
00349 
00350 inline void ELIST2_ITERATOR::add_after_stay_put(  // element to add
00351                                                 ELIST2_LINK *new_element) {
00352   #ifndef NDEBUG
00353   if (!list)
00354     NO_LIST.error ("ELIST2_ITERATOR::add_after_stay_put", ABORT, NULL);
00355   if (!new_element)
00356     BAD_PARAMETER.error ("ELIST2_ITERATOR::add_after_stay_put", ABORT,
00357       "new_element is NULL");
00358   if (new_element->next)
00359     STILL_LINKED.error ("ELIST2_ITERATOR::add_after_stay_put", ABORT, NULL);
00360   #endif
00361 
00362   if (list->empty ()) {
00363     new_element->next = new_element;
00364     new_element->prev = new_element;
00365     list->last = new_element;
00366     prev = next = new_element;
00367     ex_current_was_last = FALSE;
00368     current = NULL;
00369   }
00370   else {
00371     new_element->next = next;
00372     next->prev = new_element;
00373 
00374     if (current) {               //not extracted
00375       new_element->prev = current;
00376       current->next = new_element;
00377       if (prev == current)
00378         prev = new_element;
00379       if (current == list->last)
00380         list->last = new_element;
00381     }
00382     else {                       //current extracted
00383       new_element->prev = prev;
00384       prev->next = new_element;
00385       if (ex_current_was_last) {
00386         list->last = new_element;
00387         ex_current_was_last = FALSE;
00388       }
00389     }
00390     next = new_element;
00391   }
00392 }
00393 
00394 
00395 /***********************************************************************
00396  *                                                      ELIST2_ITERATOR::add_before_then_move
00397  *
00398  *  Add a new element to the list before the current element and move the
00399  *  iterator to the new element.
00400  **********************************************************************/
00401 
00402 inline void ELIST2_ITERATOR::add_before_then_move(  // element to add
00403                                                   ELIST2_LINK *new_element) {
00404   #ifndef NDEBUG
00405   if (!list)
00406     NO_LIST.error ("ELIST2_ITERATOR::add_before_then_move", ABORT, NULL);
00407   if (!new_element)
00408     BAD_PARAMETER.error ("ELIST2_ITERATOR::add_before_then_move", ABORT,
00409       "new_element is NULL");
00410   if (new_element->next)
00411     STILL_LINKED.error ("ELIST2_ITERATOR::add_before_then_move", ABORT, NULL);
00412   #endif
00413 
00414   if (list->empty ()) {
00415     new_element->next = new_element;
00416     new_element->prev = new_element;
00417     list->last = new_element;
00418     prev = next = new_element;
00419   }
00420   else {
00421     prev->next = new_element;
00422     new_element->prev = prev;
00423 
00424     if (current) {               //not extracted
00425       new_element->next = current;
00426       current->prev = new_element;
00427       next = current;
00428     }
00429     else {                       //current extracted
00430       new_element->next = next;
00431       next->prev = new_element;
00432       if (ex_current_was_last)
00433         list->last = new_element;
00434       if (ex_current_was_cycle_pt)
00435         cycle_pt = new_element;
00436     }
00437   }
00438   current = new_element;
00439 }
00440 
00441 
00442 /***********************************************************************
00443  *                                                      ELIST2_ITERATOR::add_before_stay_put
00444  *
00445  *  Add a new element to the list before the current element but don't move the
00446  *  iterator to the new element.
00447  **********************************************************************/
00448 
00449 inline void ELIST2_ITERATOR::add_before_stay_put(  // element to add
00450                                                  ELIST2_LINK *new_element) {
00451   #ifndef NDEBUG
00452   if (!list)
00453     NO_LIST.error ("ELIST2_ITERATOR::add_before_stay_put", ABORT, NULL);
00454   if (!new_element)
00455     BAD_PARAMETER.error ("ELIST2_ITERATOR::add_before_stay_put", ABORT,
00456       "new_element is NULL");
00457   if (new_element->next)
00458     STILL_LINKED.error ("ELIST2_ITERATOR::add_before_stay_put", ABORT, NULL);
00459   #endif
00460 
00461   if (list->empty ()) {
00462     new_element->next = new_element;
00463     new_element->prev = new_element;
00464     list->last = new_element;
00465     prev = next = new_element;
00466     ex_current_was_last = TRUE;
00467     current = NULL;
00468   }
00469   else {
00470     prev->next = new_element;
00471     new_element->prev = prev;
00472 
00473     if (current) {               //not extracted
00474       new_element->next = current;
00475       current->prev = new_element;
00476       if (next == current)
00477         next = new_element;
00478     }
00479     else {                       //current extracted
00480       new_element->next = next;
00481       next->prev = new_element;
00482       if (ex_current_was_last)
00483         list->last = new_element;
00484     }
00485     prev = new_element;
00486   }
00487 }
00488 
00489 
00490 /***********************************************************************
00491  *                                                      ELIST2_ITERATOR::add_list_after
00492  *
00493  *  Insert another list to this list after the current element but don't move the
00494  *  iterator.
00495  **********************************************************************/
00496 
00497 inline void ELIST2_ITERATOR::add_list_after(ELIST2 *list_to_add) {
00498   #ifndef NDEBUG
00499   if (!list)
00500     NO_LIST.error ("ELIST2_ITERATOR::add_list_after", ABORT, NULL);
00501   if (!list_to_add)
00502     BAD_PARAMETER.error ("ELIST2_ITERATOR::add_list_after", ABORT,
00503       "list_to_add is NULL");
00504   #endif
00505 
00506   if (!list_to_add->empty ()) {
00507     if (list->empty ()) {
00508       list->last = list_to_add->last;
00509       prev = list->last;
00510       next = list->First ();
00511       ex_current_was_last = TRUE;
00512       current = NULL;
00513     }
00514     else {
00515       if (current) {             //not extracted
00516         current->next = list_to_add->First ();
00517         current->next->prev = current;
00518         if (current == list->last)
00519           list->last = list_to_add->last;
00520         list_to_add->last->next = next;
00521         next->prev = list_to_add->last;
00522         next = current->next;
00523       }
00524       else {                     //current extracted
00525         prev->next = list_to_add->First ();
00526         prev->next->prev = prev;
00527         if (ex_current_was_last) {
00528           list->last = list_to_add->last;
00529           ex_current_was_last = FALSE;
00530         }
00531         list_to_add->last->next = next;
00532         next->prev = list_to_add->last;
00533         next = prev->next;
00534       }
00535     }
00536     list_to_add->last = NULL;
00537   }
00538 }
00539 
00540 
00541 /***********************************************************************
00542  *                                                      ELIST2_ITERATOR::add_list_before
00543  *
00544  *  Insert another list to this list before the current element. Move the
00545  *  iterator to the start of the inserted elements
00546  *  iterator.
00547  **********************************************************************/
00548 
00549 inline void ELIST2_ITERATOR::add_list_before(ELIST2 *list_to_add) {
00550   #ifndef NDEBUG
00551   if (!list)
00552     NO_LIST.error ("ELIST2_ITERATOR::add_list_before", ABORT, NULL);
00553   if (!list_to_add)
00554     BAD_PARAMETER.error ("ELIST2_ITERATOR::add_list_before", ABORT,
00555       "list_to_add is NULL");
00556   #endif
00557 
00558   if (!list_to_add->empty ()) {
00559     if (list->empty ()) {
00560       list->last = list_to_add->last;
00561       prev = list->last;
00562       current = list->First ();
00563       next = current->next;
00564       ex_current_was_last = FALSE;
00565     }
00566     else {
00567       prev->next = list_to_add->First ();
00568       prev->next->prev = prev;
00569 
00570       if (current) {             //not extracted
00571         list_to_add->last->next = current;
00572         current->prev = list_to_add->last;
00573       }
00574       else {                     //current extracted
00575         list_to_add->last->next = next;
00576         next->prev = list_to_add->last;
00577         if (ex_current_was_last)
00578           list->last = list_to_add->last;
00579         if (ex_current_was_cycle_pt)
00580           cycle_pt = prev->next;
00581       }
00582       current = prev->next;
00583       next = current->next;
00584     }
00585     list_to_add->last = NULL;
00586   }
00587 }
00588 
00589 
00590 /***********************************************************************
00591  *                                                      ELIST2_ITERATOR::extract
00592  *
00593  *  Do extraction by removing current from the list, returning it to the
00594  *  caller, but NOT updating the iterator.  (So that any calling loop can do
00595  *  this.)   The iterator's current points to NULL.  If the extracted element
00596  *  is to be deleted, this is the callers responsibility.
00597  **********************************************************************/
00598 
00599 inline ELIST2_LINK *ELIST2_ITERATOR::extract() {
00600   ELIST2_LINK *extracted_link;
00601 
00602   #ifndef NDEBUG
00603   if (!list)
00604     NO_LIST.error ("ELIST2_ITERATOR::extract", ABORT, NULL);
00605   if (!current)                  //list empty or
00606                                  //element extracted
00607     NULL_CURRENT.error ("ELIST2_ITERATOR::extract",
00608       ABORT, NULL);
00609   #endif
00610 
00611   if (list->singleton()) {
00612     // Special case where we do need to change the iterator.
00613     prev = next = list->last = NULL;
00614   } else {
00615     prev->next = next;           //remove from list
00616     next->prev = prev;
00617 
00618     if (current == list->last) {
00619       list->last = prev;
00620       ex_current_was_last = TRUE;
00621     } else {
00622       ex_current_was_last = FALSE;
00623     }
00624   }
00625   // Always set ex_current_was_cycle_pt so an add/forward will work in a loop.
00626   ex_current_was_cycle_pt = (current == cycle_pt) ? TRUE : FALSE;
00627   extracted_link = current;
00628   extracted_link->next = NULL;   //for safety
00629   extracted_link->prev = NULL;   //for safety
00630   current = NULL;
00631   return extracted_link;
00632 }
00633 
00634 
00635 /***********************************************************************
00636  *                                                      ELIST2_ITERATOR::move_to_first()
00637  *
00638  *  Move current so that it is set to the start of the list.
00639  *  Return data just in case anyone wants it.
00640  **********************************************************************/
00641 
00642 inline ELIST2_LINK *ELIST2_ITERATOR::move_to_first() {
00643   #ifndef NDEBUG
00644   if (!list)
00645     NO_LIST.error ("ELIST2_ITERATOR::move_to_first", ABORT, NULL);
00646   #endif
00647 
00648   current = list->First ();
00649   prev = list->last;
00650   next = current ? current->next : NULL;
00651   return current;
00652 }
00653 
00654 
00655 /***********************************************************************
00656  *                                                      ELIST2_ITERATOR::move_to_last()
00657  *
00658  *  Move current so that it is set to the end of the list.
00659  *  Return data just in case anyone wants it.
00660  **********************************************************************/
00661 
00662 inline ELIST2_LINK *ELIST2_ITERATOR::move_to_last() {
00663   #ifndef NDEBUG
00664   if (!list)
00665     NO_LIST.error ("ELIST2_ITERATOR::move_to_last", ABORT, NULL);
00666   #endif
00667 
00668   current = list->last;
00669   prev = current ? current->prev : NULL;
00670   next = current ? current->next : NULL;
00671   return current;
00672 }
00673 
00674 
00675 /***********************************************************************
00676  *                                                      ELIST2_ITERATOR::mark_cycle_pt()
00677  *
00678  *  Remember the current location so that we can tell whether we've returned
00679  *  to this point later.
00680  *
00681  *  If the current point is deleted either now, or in the future, the cycle
00682  *  point will be set to the next item which is set to current.  This could be
00683  *  by a forward, add_after_then_move or add_after_then_move.
00684  **********************************************************************/
00685 
00686 inline void ELIST2_ITERATOR::mark_cycle_pt() {
00687   #ifndef NDEBUG
00688   if (!list)
00689     NO_LIST.error ("ELIST2_ITERATOR::mark_cycle_pt", ABORT, NULL);
00690   #endif
00691 
00692   if (current)
00693     cycle_pt = current;
00694   else
00695     ex_current_was_cycle_pt = TRUE;
00696   started_cycling = FALSE;
00697 }
00698 
00699 
00700 /***********************************************************************
00701  *                                                      ELIST2_ITERATOR::at_first()
00702  *
00703  *  Are we at the start of the list?
00704  *
00705  **********************************************************************/
00706 
00707 inline BOOL8 ELIST2_ITERATOR::at_first() {
00708   #ifndef NDEBUG
00709   if (!list)
00710     NO_LIST.error ("ELIST2_ITERATOR::at_first", ABORT, NULL);
00711   #endif
00712 
00713                                  //we're at a deleted
00714   return ((list->empty ()) || (current == list->First ()) || ((current == NULL) &&
00715     (prev == list->last) &&      //NON-last pt between
00716     !ex_current_was_last));      //first and last
00717 }
00718 
00719 
00720 /***********************************************************************
00721  *                                                      ELIST2_ITERATOR::at_last()
00722  *
00723  *  Are we at the end of the list?
00724  *
00725  **********************************************************************/
00726 
00727 inline BOOL8 ELIST2_ITERATOR::at_last() {
00728   #ifndef NDEBUG
00729   if (!list)
00730     NO_LIST.error ("ELIST2_ITERATOR::at_last", ABORT, NULL);
00731   #endif
00732 
00733                                  //we're at a deleted
00734   return ((list->empty ()) || (current == list->last) || ((current == NULL) &&
00735     (prev == list->last) &&      //last point between
00736     ex_current_was_last));       //first and last
00737 }
00738 
00739 
00740 /***********************************************************************
00741  *                                                      ELIST2_ITERATOR::cycled_list()
00742  *
00743  *  Have we returned to the cycle_pt since it was set?
00744  *
00745  **********************************************************************/
00746 
00747 inline BOOL8 ELIST2_ITERATOR::cycled_list() {
00748   #ifndef NDEBUG
00749   if (!list)
00750     NO_LIST.error ("ELIST2_ITERATOR::cycled_list", ABORT, NULL);
00751   #endif
00752 
00753   return ((list->empty ()) || ((current == cycle_pt) && started_cycling));
00754 
00755 }
00756 
00757 
00758 /***********************************************************************
00759  *                                                      ELIST2_ITERATOR::length()
00760  *
00761  *  Return the length of the list
00762  *
00763  **********************************************************************/
00764 
00765 inline inT32 ELIST2_ITERATOR::length() {
00766   #ifndef NDEBUG
00767   if (!list)
00768     NO_LIST.error ("ELIST2_ITERATOR::length", ABORT, NULL);
00769   #endif
00770 
00771   return list->length ();
00772 }
00773 
00774 
00775 /***********************************************************************
00776  *                                                      ELIST2_ITERATOR::sort()
00777  *
00778  *  Sort the elements of the list, then reposition at the start.
00779  *
00780  **********************************************************************/
00781 
00782 inline void
00783 ELIST2_ITERATOR::sort (          //sort elements
00784 int comparator (                 //comparison routine
00785 const void *, const void *)) {
00786   #ifndef NDEBUG
00787   if (!list)
00788     NO_LIST.error ("ELIST2_ITERATOR::sort", ABORT, NULL);
00789   #endif
00790 
00791   list->sort (comparator);
00792   move_to_first();
00793 }
00794 
00795 
00796 /***********************************************************************
00797  *                                                      ELIST2_ITERATOR::add_to_end
00798  *
00799  *  Add a new element to the end of the list without moving the iterator.
00800  *  This is provided because a single linked list cannot move to the last as
00801  *  the iterator couldn't set its prev pointer.  Adding to the end is
00802  *  essential for implementing
00803               queues.
00804 **********************************************************************/
00805 
00806 inline void ELIST2_ITERATOR::add_to_end(  // element to add
00807                                         ELIST2_LINK *new_element) {
00808   #ifndef NDEBUG
00809   if (!list)
00810     NO_LIST.error ("ELIST2_ITERATOR::add_to_end", ABORT, NULL);
00811   if (!new_element)
00812     BAD_PARAMETER.error ("ELIST2_ITERATOR::add_to_end", ABORT,
00813       "new_element is NULL");
00814   if (new_element->next)
00815     STILL_LINKED.error ("ELIST2_ITERATOR::add_to_end", ABORT, NULL);
00816   #endif
00817 
00818   if (this->at_last ()) {
00819     this->add_after_stay_put (new_element);
00820   }
00821   else {
00822     if (this->at_first ()) {
00823       this->add_before_stay_put (new_element);
00824       list->last = new_element;
00825     }
00826     else {                       //Iteratr is elsewhere
00827       new_element->next = list->last->next;
00828       new_element->prev = list->last;
00829       list->last->next->prev = new_element;
00830       list->last->next = new_element;
00831       list->last = new_element;
00832     }
00833   }
00834 }
00835 
00836 
00837 /***********************************************************************
00838   QUOTE_IT   MACRO DEFINITION
00839   ===========================
00840 Replace <parm> with "<parm>".  <parm> may be an arbitrary number of tokens
00841 ***********************************************************************/
00842 
00843 #define QUOTE_IT( parm ) #parm
00844 
00845 /***********************************************************************
00846   ELIST2IZE( CLASSNAME ) MACRO DEFINITION
00847   ======================================
00848 
00849 CLASSNAME is assumed to be the name of a class which has a baseclass of
00850 ELIST2_LINK.
00851 
00852 NOTE:  Because we don't use virtual functions in the list code, the list code
00853 will NOT work correctly for classes derived from this.
00854 
00855 The macro generates:
00856   - An element deletion function:      CLASSNAME##_zapper
00857   - An E_LIST2 subclass:        CLASSNAME##_LIST
00858   - An E_LIST2_ITERATOR subclass:
00859               CLASSNAME##_IT
00860 
00861 NOTE: Generated names are DELIBERATELY designed to clash with those for
00862 ELISTIZE but NOT with those for CLISTIZE and CLIST2IZE
00863 
00864 Two macros are provided: ELIST2IZE and ELIST2IZEH
00865 The ...IZEH macros just define the class names for use in .h files
00866 The ...IZE macros define the code use in .c files
00867 ***********************************************************************/
00868 
00869 /***********************************************************************
00870   ELIST2IZEH( CLASSNAME ) MACRO
00871 
00872 ELIST2IZEH is a concatenation of 3 fragments ELIST2IZEH_A, ELIST2IZEH_B and
00873 ELIST2IZEH_C.
00874 ***********************************************************************/
00875 
00876 #define ELIST2IZEH_A( CLASSNAME )                                                                                                       \
00877                                                                                                                                                                                                                 \
00878 extern DLLSYM void                      CLASSNAME##_zapper(                     /*delete a link*/               \
00879 ELIST2_LINK*                            link);                                          /*link to delete*/
00880 
00881 #define ELIST2IZEH_B( CLASSNAME )                                                                                                       \
00882                                                                                                                                                                                                                 \
00883 /***********************************************************************                \
00884 *                                                       CLASS - CLASSNAME##_LIST                                                                                                                                        \
00885 *                                                                                                                                                                                                               \
00886 *                                                       List class for class CLASSNAME                                                                                                                  \
00887 *                                                                                                                                                                                                               \
00888 **********************************************************************/                 \
00889                                                                                                                                                                                                                 \
00890 class DLLSYM                            CLASSNAME##_LIST : public ELIST2                                                        \
00891 {                                                                                                                                                                                                               \
00892 public:                                                                                                                                                                                         \
00893                                                         CLASSNAME##_LIST():ELIST2() {} \
00894                                                                                                                 /* constructor */               \
00895                                                                                                                                                                                                                 \
00896                                                         CLASSNAME##_LIST(                       /* don't construct */ \
00897         const CLASSNAME##_LIST&)                                                        /*by initial assign*/\
00898         { DONT_CONSTRUCT_LIST_BY_COPY.error( QUOTE_IT( CLASSNAME##_LIST ),      \
00899                                                                                                                 ABORT, NULL ); }                                                        \
00900                                                                                                                                                                                                                 \
00901 void                                            clear()                                         /* delete elements */\
00902         { ELIST2::internal_clear( &CLASSNAME##_zapper ); }                                                              \
00903                                                                                                                                                                                                                 \
00904                                                                         ~CLASSNAME##_LIST()     /* destructor */                \
00905         { clear(); }                                                                                                                                                            \
00906 \
00907 /* Become a deep copy of src_list*/ \
00908 void deep_copy(const CLASSNAME##_LIST* src_list, \
00909                CLASSNAME* (*copier)(const CLASSNAME*)); \
00910 \
00911 void                                            operator=(                                      /* prevent assign */    \
00912         const CLASSNAME##_LIST&)                                                                                                                                \
00913         { DONT_ASSIGN_LISTS.error( QUOTE_IT( CLASSNAME##_LIST ),                                                \
00914                                                                                         ABORT, NULL ); }
00915 
00916 #define ELIST2IZEH_C( CLASSNAME )                                                                                                       \
00917 };                                                                                                                                                                                                              \
00918                                                                                                                                                                                                                 \
00919                                                                                                                                                                                                                 \
00920                                                                                                                                                                                                                 \
00921 /***********************************************************************                \
00922 *                                                       CLASS - CLASSNAME##_IT                                                                                                                                          \
00923 *                                                                                                                                                                                                               \
00924 *                                                       Iterator class for class CLASSNAME##_LIST                                                                                       \
00925 *                                                                                                                                                                                                               \
00926 *  Note: We don't need to coerce pointers to member functions input                             \
00927 *  parameters as these are automatically converted to the type of the base              \
00928 *  type. ("A ptr to a class may be converted to a pointer to a public base              \
00929 *  class of that class")                                                                                                                                                \
00930 **********************************************************************/                 \
00931                                                                                                                                                                                                                 \
00932 class DLLSYM                            CLASSNAME##_IT : public ELIST2_ITERATOR                         \
00933 {                                                                                                                                                                                                               \
00934 public:                                                                                                                                                                                         \
00935                                                                 CLASSNAME##_IT():ELIST2_ITERATOR(){}                                    \
00936                                                                                                                                                                                                                 \
00937                                                                 CLASSNAME##_IT(                                                                                         \
00938 CLASSNAME##_LIST*                       list):ELIST2_ITERATOR(list){}                                                           \
00939                                                                                                                                                                                                                 \
00940         CLASSNAME*                      data()                                                                                                                  \
00941                 { return (CLASSNAME*) ELIST2_ITERATOR::data(); }                                                                \
00942                                                                                                                                                                                                                 \
00943         CLASSNAME*                      data_relative(                                                                                                  \
00944         inT8                                    offset)                                                                                                                 \
00945                 { return (CLASSNAME*) ELIST2_ITERATOR::data_relative( offset ); }               \
00946                                                                                                                                                                                                                 \
00947         CLASSNAME*                      forward()                                                                                                               \
00948                 { return (CLASSNAME*) ELIST2_ITERATOR::forward(); }                                                     \
00949                                                                                                                                                                                                                 \
00950         CLASSNAME*                      backward()                                                                                                              \
00951                 { return (CLASSNAME*) ELIST2_ITERATOR::backward(); }                                            \
00952                                                                                                                                                                                                                 \
00953         CLASSNAME*                      extract()                                                                                                               \
00954                 { return (CLASSNAME*) ELIST2_ITERATOR::extract(); }                                                     \
00955                                                                                                                                                                                                                 \
00956         CLASSNAME*                      move_to_first()                                                                                         \
00957                 { return (CLASSNAME*) ELIST2_ITERATOR::move_to_first(); }                                       \
00958                                                                                                                                                                                                                 \
00959         CLASSNAME*                      move_to_last()                                                                                                  \
00960                 { return (CLASSNAME*) ELIST2_ITERATOR::move_to_last(); }                                        \
00961 };
00962 
00963 #define ELIST2IZEH( CLASSNAME )                                                                                                         \
00964                                                                                                                                                                                                                 \
00965 ELIST2IZEH_A( CLASSNAME )                                                                                                                                               \
00966                                                                                                                                                                                                                 \
00967 ELIST2IZEH_B( CLASSNAME )                                                                                                                                               \
00968                                                                                                                                                                                                                 \
00969 ELIST2IZEH_C( CLASSNAME )
00970 
00971 
00972 /***********************************************************************
00973   ELIST2IZE( CLASSNAME ) MACRO
00974 ***********************************************************************/
00975 
00976 #define ELIST2IZE( CLASSNAME )                                                \
00977                                                                                                                                                                                                                 \
00978 /***********************************************************************                \
00979 *                                                       CLASSNAME##_zapper                                                                                                                                                      \
00980 *                                                                                                                                                                                                               \
00981 *  A function which can delete a CLASSNAME element.  This is passed to the              \
00982 *  generic clear list member function so that when a list is cleared the                \
00983 *  elements on the list are properly destroyed from the base class, even                \
00984 *  though we don't use a virtual destructor function.                                                                   \
00985 **********************************************************************/                 \
00986                                                                                                                                                                                                                 \
00987 DLLSYM void                                     CLASSNAME##_zapper(                     /*delete a link*/               \
00988 ELIST2_LINK*                            link)                                           /*link to delete*/      \
00989 {                                                                                                                                                                                                               \
00990 delete (CLASSNAME *) link;                                                                                                                                      \
00991 }                                                                                                                                                                                                               \
00992 \
00993 /* Become a deep copy of src_list*/ \
00994 void CLASSNAME##_LIST::deep_copy(const CLASSNAME##_LIST* src_list, \
00995                CLASSNAME* (*copier)(const CLASSNAME*)) { \
00996 \
00997   CLASSNAME##_IT from_it(const_cast<CLASSNAME##_LIST*>(src_list)); \
00998   CLASSNAME##_IT to_it(this); \
00999 \
01000   for (from_it.mark_cycle_pt(); !from_it.cycled_list(); from_it.forward()) \
01001     to_it.add_after_then_move((*copier)(from_it.data())); \
01002 }
01003 
01004 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines