Tesseract 3.01
|
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