|
tesseract 3.04.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 &) { //don't copy link 00055 data = next = NULL; 00056 } 00057 00058 void operator= ( //don't 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 don't 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 // Comparison 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); //don't 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 (!list_to_iterate) 00259 BAD_PARAMETER.error ("CLIST_ITERATOR::set_to_list", ABORT, 00260 "list_to_iterate is NULL"); 00261 #endif 00262 00263 list = list_to_iterate; 00264 prev = list->last; 00265 current = list->First (); 00266 next = current != NULL ? current->next : NULL; 00267 cycle_pt = NULL; //await explicit set 00268 started_cycling = FALSE; 00269 ex_current_was_last = FALSE; 00270 ex_current_was_cycle_pt = FALSE; 00271 } 00272 00273 00274 /*********************************************************************** 00275 * CLIST_ITERATOR::CLIST_ITERATOR 00276 * 00277 * CONSTRUCTOR - set iterator to specified list; 00278 **********************************************************************/ 00279 00280 inline CLIST_ITERATOR::CLIST_ITERATOR(CLIST *list_to_iterate) { 00281 set_to_list(list_to_iterate); 00282 } 00283 00284 00285 /*********************************************************************** 00286 * CLIST_ITERATOR::add_after_then_move 00287 * 00288 * Add a new element to the list after the current element and move the 00289 * iterator to the new element. 00290 **********************************************************************/ 00291 00292 inline void CLIST_ITERATOR::add_after_then_move( // element to add 00293 void *new_data) { 00294 CLIST_LINK *new_element; 00295 00296 #ifndef NDEBUG 00297 if (!list) 00298 NO_LIST.error ("CLIST_ITERATOR::add_after_then_move", ABORT, NULL); 00299 if (!new_data) 00300 BAD_PARAMETER.error ("CLIST_ITERATOR::add_after_then_move", ABORT, 00301 "new_data is NULL"); 00302 #endif 00303 00304 new_element = new CLIST_LINK; 00305 new_element->data = new_data; 00306 00307 if (list->empty ()) { 00308 new_element->next = new_element; 00309 list->last = new_element; 00310 prev = next = new_element; 00311 } 00312 else { 00313 new_element->next = next; 00314 00315 if (current) { //not extracted 00316 current->next = new_element; 00317 prev = current; 00318 if (current == list->last) 00319 list->last = new_element; 00320 } 00321 else { //current extracted 00322 prev->next = new_element; 00323 if (ex_current_was_last) 00324 list->last = new_element; 00325 if (ex_current_was_cycle_pt) 00326 cycle_pt = new_element; 00327 } 00328 } 00329 current = new_element; 00330 } 00331 00332 00333 /*********************************************************************** 00334 * CLIST_ITERATOR::add_after_stay_put 00335 * 00336 * Add a new element to the list after the current element but do not move 00337 * the iterator to the new element. 00338 **********************************************************************/ 00339 00340 inline void CLIST_ITERATOR::add_after_stay_put( // element to add 00341 void *new_data) { 00342 CLIST_LINK *new_element; 00343 00344 #ifndef NDEBUG 00345 if (!list) 00346 NO_LIST.error ("CLIST_ITERATOR::add_after_stay_put", ABORT, NULL); 00347 if (!new_data) 00348 BAD_PARAMETER.error ("CLIST_ITERATOR::add_after_stay_put", ABORT, 00349 "new_data is NULL"); 00350 #endif 00351 00352 new_element = new CLIST_LINK; 00353 new_element->data = new_data; 00354 00355 if (list->empty ()) { 00356 new_element->next = new_element; 00357 list->last = new_element; 00358 prev = next = new_element; 00359 ex_current_was_last = FALSE; 00360 current = NULL; 00361 } 00362 else { 00363 new_element->next = next; 00364 00365 if (current) { //not extracted 00366 current->next = new_element; 00367 if (prev == current) 00368 prev = new_element; 00369 if (current == list->last) 00370 list->last = new_element; 00371 } 00372 else { //current extracted 00373 prev->next = new_element; 00374 if (ex_current_was_last) { 00375 list->last = new_element; 00376 ex_current_was_last = FALSE; 00377 } 00378 } 00379 next = new_element; 00380 } 00381 } 00382 00383 00384 /*********************************************************************** 00385 * CLIST_ITERATOR::add_before_then_move 00386 * 00387 * Add a new element to the list before the current element and move the 00388 * iterator to the new element. 00389 **********************************************************************/ 00390 00391 inline void CLIST_ITERATOR::add_before_then_move( // element to add 00392 void *new_data) { 00393 CLIST_LINK *new_element; 00394 00395 #ifndef NDEBUG 00396 if (!list) 00397 NO_LIST.error ("CLIST_ITERATOR::add_before_then_move", ABORT, NULL); 00398 if (!new_data) 00399 BAD_PARAMETER.error ("CLIST_ITERATOR::add_before_then_move", ABORT, 00400 "new_data is NULL"); 00401 #endif 00402 00403 new_element = new CLIST_LINK; 00404 new_element->data = new_data; 00405 00406 if (list->empty ()) { 00407 new_element->next = new_element; 00408 list->last = new_element; 00409 prev = next = new_element; 00410 } 00411 else { 00412 prev->next = new_element; 00413 if (current) { //not extracted 00414 new_element->next = current; 00415 next = current; 00416 } 00417 else { //current extracted 00418 new_element->next = next; 00419 if (ex_current_was_last) 00420 list->last = new_element; 00421 if (ex_current_was_cycle_pt) 00422 cycle_pt = new_element; 00423 } 00424 } 00425 current = new_element; 00426 } 00427 00428 00429 /*********************************************************************** 00430 * CLIST_ITERATOR::add_before_stay_put 00431 * 00432 * Add a new element to the list before the current element but don't move the 00433 * iterator to the new element. 00434 **********************************************************************/ 00435 00436 inline void CLIST_ITERATOR::add_before_stay_put( // element to add 00437 void *new_data) { 00438 CLIST_LINK *new_element; 00439 00440 #ifndef NDEBUG 00441 if (!list) 00442 NO_LIST.error ("CLIST_ITERATOR::add_before_stay_put", ABORT, NULL); 00443 if (!new_data) 00444 BAD_PARAMETER.error ("CLIST_ITERATOR::add_before_stay_put", ABORT, 00445 "new_data is NULL"); 00446 #endif 00447 00448 new_element = new CLIST_LINK; 00449 new_element->data = new_data; 00450 00451 if (list->empty ()) { 00452 new_element->next = new_element; 00453 list->last = new_element; 00454 prev = next = new_element; 00455 ex_current_was_last = TRUE; 00456 current = NULL; 00457 } 00458 else { 00459 prev->next = new_element; 00460 if (current) { //not extracted 00461 new_element->next = current; 00462 if (next == current) 00463 next = new_element; 00464 } 00465 else { //current extracted 00466 new_element->next = next; 00467 if (ex_current_was_last) 00468 list->last = new_element; 00469 } 00470 prev = new_element; 00471 } 00472 } 00473 00474 00475 /*********************************************************************** 00476 * CLIST_ITERATOR::add_list_after 00477 * 00478 * Insert another list to this list after the current element but don't move the 00479 * iterator. 00480 **********************************************************************/ 00481 00482 inline void CLIST_ITERATOR::add_list_after(CLIST *list_to_add) { 00483 #ifndef NDEBUG 00484 if (!list) 00485 NO_LIST.error ("CLIST_ITERATOR::add_list_after", ABORT, NULL); 00486 if (!list_to_add) 00487 BAD_PARAMETER.error ("CLIST_ITERATOR::add_list_after", ABORT, 00488 "list_to_add is NULL"); 00489 #endif 00490 00491 if (!list_to_add->empty ()) { 00492 if (list->empty ()) { 00493 list->last = list_to_add->last; 00494 prev = list->last; 00495 next = list->First (); 00496 ex_current_was_last = TRUE; 00497 current = NULL; 00498 } 00499 else { 00500 if (current) { //not extracted 00501 current->next = list_to_add->First (); 00502 if (current == list->last) 00503 list->last = list_to_add->last; 00504 list_to_add->last->next = next; 00505 next = current->next; 00506 } 00507 else { //current extracted 00508 prev->next = list_to_add->First (); 00509 if (ex_current_was_last) { 00510 list->last = list_to_add->last; 00511 ex_current_was_last = FALSE; 00512 } 00513 list_to_add->last->next = next; 00514 next = prev->next; 00515 } 00516 } 00517 list_to_add->last = NULL; 00518 } 00519 } 00520 00521 00522 /*********************************************************************** 00523 * CLIST_ITERATOR::add_list_before 00524 * 00525 * Insert another list to this list before the current element. Move the 00526 * iterator to the start of the inserted elements 00527 * iterator. 00528 **********************************************************************/ 00529 00530 inline void CLIST_ITERATOR::add_list_before(CLIST *list_to_add) { 00531 #ifndef NDEBUG 00532 if (!list) 00533 NO_LIST.error ("CLIST_ITERATOR::add_list_before", ABORT, NULL); 00534 if (!list_to_add) 00535 BAD_PARAMETER.error ("CLIST_ITERATOR::add_list_before", ABORT, 00536 "list_to_add is NULL"); 00537 #endif 00538 00539 if (!list_to_add->empty ()) { 00540 if (list->empty ()) { 00541 list->last = list_to_add->last; 00542 prev = list->last; 00543 current = list->First (); 00544 next = current->next; 00545 ex_current_was_last = FALSE; 00546 } 00547 else { 00548 prev->next = list_to_add->First (); 00549 if (current) { //not extracted 00550 list_to_add->last->next = current; 00551 } 00552 else { //current extracted 00553 list_to_add->last->next = next; 00554 if (ex_current_was_last) 00555 list->last = list_to_add->last; 00556 if (ex_current_was_cycle_pt) 00557 cycle_pt = prev->next; 00558 } 00559 current = prev->next; 00560 next = current->next; 00561 } 00562 list_to_add->last = NULL; 00563 } 00564 } 00565 00566 00567 /*********************************************************************** 00568 * CLIST_ITERATOR::extract 00569 * 00570 * Do extraction by removing current from the list, deleting the cons cell 00571 * and returning the data to the caller, but NOT updating the iterator. (So 00572 * that any calling loop can do this.) The iterator's current points to 00573 * NULL. If the data is to be deleted, this is the callers responsibility. 00574 **********************************************************************/ 00575 00576 inline void *CLIST_ITERATOR::extract() { 00577 void *extracted_data; 00578 00579 #ifndef NDEBUG 00580 if (!list) 00581 NO_LIST.error ("CLIST_ITERATOR::extract", ABORT, NULL); 00582 if (!current) //list empty or 00583 //element extracted 00584 NULL_CURRENT.error ("CLIST_ITERATOR::extract", 00585 ABORT, NULL); 00586 #endif 00587 00588 if (list->singleton()) { 00589 // Special case where we do need to change the iterator. 00590 prev = next = list->last = NULL; 00591 } else { 00592 prev->next = next; //remove from list 00593 00594 if (current == list->last) { 00595 list->last = prev; 00596 ex_current_was_last = TRUE; 00597 } else { 00598 ex_current_was_last = FALSE; 00599 } 00600 } 00601 // Always set ex_current_was_cycle_pt so an add/forward will work in a loop. 00602 ex_current_was_cycle_pt = (current == cycle_pt) ? TRUE : FALSE; 00603 extracted_data = current->data; 00604 delete(current); //destroy CONS cell 00605 current = NULL; 00606 return extracted_data; 00607 } 00608 00609 00610 /*********************************************************************** 00611 * CLIST_ITERATOR::move_to_first() 00612 * 00613 * Move current so that it is set to the start of the list. 00614 * Return data just in case anyone wants it. 00615 **********************************************************************/ 00616 00617 inline void *CLIST_ITERATOR::move_to_first() { 00618 #ifndef NDEBUG 00619 if (!list) 00620 NO_LIST.error ("CLIST_ITERATOR::move_to_first", ABORT, NULL); 00621 #endif 00622 00623 current = list->First (); 00624 prev = list->last; 00625 next = current != NULL ? current->next : NULL; 00626 return current != NULL ? current->data : NULL; 00627 } 00628 00629 00630 /*********************************************************************** 00631 * CLIST_ITERATOR::mark_cycle_pt() 00632 * 00633 * Remember the current location so that we can tell whether we've returned 00634 * to this point later. 00635 * 00636 * If the current point is deleted either now, or in the future, the cycle 00637 * point will be set to the next item which is set to current. This could be 00638 * by a forward, add_after_then_move or add_after_then_move. 00639 **********************************************************************/ 00640 00641 inline void CLIST_ITERATOR::mark_cycle_pt() { 00642 #ifndef NDEBUG 00643 if (!list) 00644 NO_LIST.error ("CLIST_ITERATOR::mark_cycle_pt", ABORT, NULL); 00645 #endif 00646 00647 if (current) 00648 cycle_pt = current; 00649 else 00650 ex_current_was_cycle_pt = TRUE; 00651 started_cycling = FALSE; 00652 } 00653 00654 00655 /*********************************************************************** 00656 * CLIST_ITERATOR::at_first() 00657 * 00658 * Are we at the start of the list? 00659 * 00660 **********************************************************************/ 00661 00662 inline BOOL8 CLIST_ITERATOR::at_first() { 00663 #ifndef NDEBUG 00664 if (!list) 00665 NO_LIST.error ("CLIST_ITERATOR::at_first", ABORT, NULL); 00666 #endif 00667 00668 //we're at a deleted 00669 return ((list->empty ()) || (current == list->First ()) || ((current == NULL) && 00670 (prev == list->last) && //NON-last pt between 00671 !ex_current_was_last)); //first and last 00672 } 00673 00674 00675 /*********************************************************************** 00676 * CLIST_ITERATOR::at_last() 00677 * 00678 * Are we at the end of the list? 00679 * 00680 **********************************************************************/ 00681 00682 inline BOOL8 CLIST_ITERATOR::at_last() { 00683 #ifndef NDEBUG 00684 if (!list) 00685 NO_LIST.error ("CLIST_ITERATOR::at_last", ABORT, NULL); 00686 #endif 00687 00688 //we're at a deleted 00689 return ((list->empty ()) || (current == list->last) || ((current == NULL) && 00690 (prev == list->last) && //last point between 00691 ex_current_was_last)); //first and last 00692 } 00693 00694 00695 /*********************************************************************** 00696 * CLIST_ITERATOR::cycled_list() 00697 * 00698 * Have we returned to the cycle_pt since it was set? 00699 * 00700 **********************************************************************/ 00701 00702 inline BOOL8 CLIST_ITERATOR::cycled_list() { 00703 #ifndef NDEBUG 00704 if (!list) 00705 NO_LIST.error ("CLIST_ITERATOR::cycled_list", ABORT, NULL); 00706 #endif 00707 00708 return ((list->empty ()) || ((current == cycle_pt) && started_cycling)); 00709 00710 } 00711 00712 00713 /*********************************************************************** 00714 * CLIST_ITERATOR::length() 00715 * 00716 * Return the length of the list 00717 * 00718 **********************************************************************/ 00719 00720 inline inT32 CLIST_ITERATOR::length() { 00721 #ifndef NDEBUG 00722 if (!list) 00723 NO_LIST.error ("CLIST_ITERATOR::length", ABORT, NULL); 00724 #endif 00725 00726 return list->length (); 00727 } 00728 00729 00730 /*********************************************************************** 00731 * CLIST_ITERATOR::sort() 00732 * 00733 * Sort the elements of the list, then reposition at the start. 00734 * 00735 **********************************************************************/ 00736 00737 inline void 00738 CLIST_ITERATOR::sort ( //sort elements 00739 int comparator ( //comparison routine 00740 const void *, const void *)) { 00741 #ifndef NDEBUG 00742 if (!list) 00743 NO_LIST.error ("CLIST_ITERATOR::sort", ABORT, NULL); 00744 #endif 00745 00746 list->sort (comparator); 00747 move_to_first(); 00748 } 00749 00750 00751 /*********************************************************************** 00752 * CLIST_ITERATOR::add_to_end 00753 * 00754 * Add a new element to the end of the list without moving the iterator. 00755 * This is provided because a single linked list cannot move to the last as 00756 * the iterator couldn't set its prev pointer. Adding to the end is 00757 * essential for implementing 00758 queues. 00759 **********************************************************************/ 00760 00761 inline void CLIST_ITERATOR::add_to_end( // element to add 00762 void *new_data) { 00763 CLIST_LINK *new_element; 00764 00765 #ifndef NDEBUG 00766 if (!list) 00767 NO_LIST.error ("CLIST_ITERATOR::add_to_end", ABORT, NULL); 00768 if (!new_data) 00769 BAD_PARAMETER.error ("CLIST_ITERATOR::add_to_end", ABORT, 00770 "new_data is NULL"); 00771 #endif 00772 00773 if (this->at_last ()) { 00774 this->add_after_stay_put (new_data); 00775 } 00776 else { 00777 if (this->at_first ()) { 00778 this->add_before_stay_put (new_data); 00779 list->last = prev; 00780 } 00781 else { //Iteratr is elsewhere 00782 new_element = new CLIST_LINK; 00783 new_element->data = new_data; 00784 00785 new_element->next = list->last->next; 00786 list->last->next = new_element; 00787 list->last = new_element; 00788 } 00789 } 00790 } 00791 00792 00793 /*********************************************************************** 00794 QUOTE_IT MACRO DEFINITION 00795 =========================== 00796 Replace <parm> with "<parm>". <parm> may be an arbitrary number of tokens 00797 ***********************************************************************/ 00798 00799 #define QUOTE_IT( parm ) #parm 00800 00801 /*********************************************************************** 00802 CLISTIZE( CLASSNAME ) MACRO DEFINITION 00803 ====================================== 00804 00805 CLASSNAME is assumed to be the name of a class to be used in a CONS list 00806 00807 NOTE: Because we don't use virtual functions in the list code, the list code 00808 will NOT work correctly for classes derived from this. 00809 00810 The macro generates: 00811 - An element deletion function: CLASSNAME##_c1_zapper 00812 - An element copier function: 00813 CLASSNAME##_c1_copier 00814 - A CLIST subclass: CLASSNAME##_CLIST 00815 - A CLIST_ITERATOR subclass: 00816 CLASSNAME##_C_IT 00817 00818 NOTE: Generated names do NOT clash with those generated by ELISTIZE, 00819 ELIST2ISE and CLIST2IZE 00820 00821 Two macros are provided: CLISTIZE and CLISTIZEH 00822 The ...IZEH macros just define the class names for use in .h files 00823 The ...IZE macros define the code use in .c files 00824 ***********************************************************************/ 00825 00826 /*********************************************************************** 00827 CLISTIZEH( CLASSNAME ) MACRO 00828 00829 CLISTIZEH is a concatenation of 3 fragments CLISTIZEH_A, CLISTIZEH_B and 00830 CLISTIZEH_C. 00831 ***********************************************************************/ 00832 00833 #define CLISTIZEH_A( CLASSNAME ) \ 00834 \ 00835 extern DLLSYM void CLASSNAME##_c1_zapper( /*delete a link*/ \ 00836 void* link); /*link to delete*/ \ 00837 \ 00838 extern DLLSYM void* CLASSNAME##_c1_copier( /*deep copy a link*/ \ 00839 void* old_element); /*source link */ 00840 00841 #define CLISTIZEH_B( CLASSNAME ) \ 00842 \ 00843 /*********************************************************************** \ 00844 * CLASS - CLASSNAME##_CLIST \ 00845 * \ 00846 * List class for class CLASSNAME \ 00847 * \ 00848 **********************************************************************/ \ 00849 \ 00850 class DLLSYM CLASSNAME##_CLIST : public CLIST \ 00851 { \ 00852 public: \ 00853 CLASSNAME##_CLIST():CLIST() {} \ 00854 /* constructor */ \ 00855 \ 00856 CLASSNAME##_CLIST( /* don't construct */ \ 00857 const CLASSNAME##_CLIST&) /*by initial assign*/ \ 00858 { DONT_CONSTRUCT_LIST_BY_COPY.error( QUOTE_IT( CLASSNAME##_CLIST ), \ 00859 ABORT, NULL ); } \ 00860 \ 00861 void deep_clear() /* delete elements */ \ 00862 { CLIST::internal_deep_clear( &CLASSNAME##_c1_zapper ); } \ 00863 \ 00864 void operator=( /* prevent assign */ \ 00865 const CLASSNAME##_CLIST&) \ 00866 { DONT_ASSIGN_LISTS.error( QUOTE_IT( CLASSNAME##_CLIST ), \ 00867 ABORT, NULL ); } 00868 00869 #define CLISTIZEH_C( CLASSNAME ) \ 00870 \ 00871 }; \ 00872 \ 00873 \ 00874 \ 00875 /*********************************************************************** \ 00876 * CLASS - CLASSNAME##_C_IT \ 00877 * \ 00878 * Iterator class for class CLASSNAME##_CLIST \ 00879 * \ 00880 * Note: We don't need to coerce pointers to member functions input \ 00881 * parameters as these are automatically converted to the type of the base \ 00882 * type. ("A ptr to a class may be converted to a pointer to a public base \ 00883 * class of that class") \ 00884 **********************************************************************/ \ 00885 \ 00886 class DLLSYM CLASSNAME##_C_IT : public CLIST_ITERATOR \ 00887 { \ 00888 public: \ 00889 CLASSNAME##_C_IT():CLIST_ITERATOR(){} \ 00890 \ 00891 CLASSNAME##_C_IT( \ 00892 CLASSNAME##_CLIST* list):CLIST_ITERATOR(list){} \ 00893 \ 00894 CLASSNAME* data() \ 00895 { return (CLASSNAME*) CLIST_ITERATOR::data(); } \ 00896 \ 00897 CLASSNAME* data_relative( \ 00898 inT8 offset) \ 00899 { return (CLASSNAME*) CLIST_ITERATOR::data_relative( offset ); } \ 00900 \ 00901 CLASSNAME* forward() \ 00902 { return (CLASSNAME*) CLIST_ITERATOR::forward(); } \ 00903 \ 00904 CLASSNAME* extract() \ 00905 { return (CLASSNAME*) CLIST_ITERATOR::extract(); } \ 00906 \ 00907 CLASSNAME* move_to_first() \ 00908 { return (CLASSNAME*) CLIST_ITERATOR::move_to_first(); } \ 00909 \ 00910 CLASSNAME* move_to_last() \ 00911 { return (CLASSNAME*) CLIST_ITERATOR::move_to_last(); } \ 00912 }; 00913 00914 #define CLISTIZEH( CLASSNAME ) \ 00915 \ 00916 CLISTIZEH_A( CLASSNAME ) \ 00917 \ 00918 CLISTIZEH_B( CLASSNAME ) \ 00919 \ 00920 CLISTIZEH_C( CLASSNAME ) 00921 00922 /*********************************************************************** 00923 CLISTIZE( CLASSNAME ) MACRO 00924 ***********************************************************************/ 00925 00926 #define CLISTIZE( CLASSNAME ) \ 00927 \ 00928 /*********************************************************************** \ 00929 * CLASSNAME##_c1_zapper \ 00930 * \ 00931 * A function which can delete a CLASSNAME element. This is passed to the \ 00932 * generic deep_clear list member function so that when a list is cleared the \ 00933 * elements on the list are properly destroyed from the base class, even \ 00934 * though we don't use a virtual destructor function. \ 00935 **********************************************************************/ \ 00936 \ 00937 DLLSYM void CLASSNAME##_c1_zapper( /*delete a link*/ \ 00938 void* link) /*link to delete*/ \ 00939 { \ 00940 delete (CLASSNAME *) link; \ 00941 } \ 00942 00943 #endif