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