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