Tesseract 3.02

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
clst.h
Go to the documentation of this file.
1 /**********************************************************************
2 * File: clst.h (Formerly clist.h)
3 * Description: CONS cell list module include file.
4 * Author: Phil Cheatle
5 * Created: Mon Jan 28 08:33:13 GMT 1991
6 *
7 * (C) Copyright 1991, Hewlett-Packard Ltd.
8 ** Licensed under the Apache License, Version 2.0 (the "License");
9 ** you may not use this file except in compliance with the License.
10 ** You may obtain a copy of the License at
11 ** http://www.apache.org/licenses/LICENSE-2.0
12 ** Unless required by applicable law or agreed to in writing, software
13 ** distributed under the License is distributed on an "AS IS" BASIS,
14 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 ** See the License for the specific language governing permissions and
16 ** limitations under the License.
17 *
18 **********************************************************************/
19
20 #ifndef CLST_H
21 #define CLST_H
22
23 #include <stdio.h>
24 #include "host.h"
25 #include "serialis.h"
26 #include "lsterr.h"
27
28 class CLIST_ITERATOR;
29
30 /**********************************************************************
31 * CLASS - CLIST_LINK
32 *
33 * Generic link class for singly linked CONS cell lists
34 *
35 * Note: No destructor - elements are assumed to be destroyed EITHER after
36 * they have been extracted from a list OR by the CLIST destructor which
37 * walks the list.
38 **********************************************************************/
39
40 class DLLSYM CLIST_LINK
41 {
42 friend class CLIST_ITERATOR;
43 friend class CLIST;
44
45 CLIST_LINK *next;
46 void *data;
47
48 public:
49 CLIST_LINK() { //constructor
50 data = next = NULL;
51 }
52
53 CLIST_LINK( //copy constructor
54 const CLIST_LINK &) { //dont copy link
55 data = next = NULL;
56 }
57
58 void operator= ( //dont copy links
59 const CLIST_LINK &) {
60 data = next = NULL;
61 }
62 };
63
64 /**********************************************************************
65 * CLASS - CLIST
66 *
67 * Generic list class for singly linked CONS cell lists
68 **********************************************************************/
69
70 class DLLSYM CLIST
71 {
72 friend class CLIST_ITERATOR;
73
74 CLIST_LINK *last; //End of list
75 //(Points to head)
76 CLIST_LINK *First() { // return first
77 return last != NULL ? last->next : NULL;
78 }
79
80 public:
81 CLIST() { //constructor
82 last = NULL;
83 }
84
85 ~CLIST () { //destructor
86 shallow_clear();
87 }
88
89 void internal_deep_clear ( //destroy all links
90 void (*zapper) (void *)); //ptr to zapper functn
91
92 void shallow_clear(); //clear list but dont
93 //delete data elements
94
95 bool empty() const { //is list empty?
96 return !last;
97 }
98
99 bool singleton() const {
100 return last != NULL ? (last == last->next) : false;
101 }
102
103 void shallow_copy( //dangerous!!
104 CLIST *from_list) { //beware destructors!!
105 last = from_list->last;
106 }
107
108 void assign_to_sublist( //to this list
109 CLIST_ITERATOR *start_it, //from list start
110 CLIST_ITERATOR *end_it); //from list end
111
112 inT32 length() const; //# elements in list
113
114 void sort ( //sort elements
115 int comparator ( //comparison routine
116 const void *, const void *));
117
118 // Assuming list has been sorted already, insert new_data to
119 // keep the list sorted according to the same comparison function.
120 // Comparision function is the same as used by sort, i.e. uses double
121 // indirection. Time is O(1) to add to beginning or end.
122 // Time is linear to add pre-sorted items to an empty list.
123 // If unique, then don't add duplicate entries.
124 // Returns true if the element was added to the list.
125 bool add_sorted(int comparator(const void*, const void*),
126 bool unique, void* new_data);
127
128 // Assuming that the minuend and subtrahend are already sorted with
129 // the same comparison function, shallow clears this and then copies
130 // the set difference minuend - subtrahend to this, being the elements
131 // of minuend that do not compare equal to anything in subtrahend.
132 // If unique is true, any duplicates in minuend are also eliminated.
133 void set_subtract(int comparator(const void*, const void*), bool unique,
134 CLIST* minuend, CLIST* subtrahend);
135
136 };
137
138 /***********************************************************************
139 * CLASS - CLIST_ITERATOR
140 *
141 * Generic iterator class for singly linked lists with embedded links
142 **********************************************************************/
143
144 class DLLSYM CLIST_ITERATOR
145 {
146 friend void CLIST::assign_to_sublist(CLIST_ITERATOR *, CLIST_ITERATOR *);
147
148 CLIST *list; //List being iterated
149 CLIST_LINK *prev; //prev element
150 CLIST_LINK *current; //current element
151 CLIST_LINK *next; //next element
152 BOOL8 ex_current_was_last; //current extracted
153 //was end of list
154 BOOL8 ex_current_was_cycle_pt; //current extracted
155 //was cycle point
156 CLIST_LINK *cycle_pt; //point we are cycling
157 //the list to.
158 BOOL8 started_cycling; //Have we moved off
159 //the start?
160
161 CLIST_LINK *extract_sublist( //from this current...
162 CLIST_ITERATOR *other_it); //to other current
163
164 public:
165 CLIST_ITERATOR() { //constructor
166 list = NULL;
167 } //unassigned list
168
169 CLIST_ITERATOR( //constructor
170 CLIST *list_to_iterate);
171
172 void set_to_list( //change list
173 CLIST *list_to_iterate);
174
175 void add_after_then_move( //add after current &
176 void *new_data); //move to new
177
178 void add_after_stay_put( //add after current &
179 void *new_data); //stay at current
180
181 void add_before_then_move( //add before current &
182 void *new_data); //move to new
183
184 void add_before_stay_put( //add before current &
185 void *new_data); //stay at current
186
187 void add_list_after( //add a list &
188 CLIST *list_to_add); //stay at current
189
190 void add_list_before( //add a list &
191 CLIST *list_to_add); //move to it 1st item
192
193 void *data() { //get current data
194 #ifndef NDEBUG
195 if (!list)
196 NO_LIST.error ("CLIST_ITERATOR::data", ABORT, NULL);
197 if (!current)
198 NULL_DATA.error ("CLIST_ITERATOR::data", ABORT, NULL);
199 #endif
200 return current->data;
201 }
202
203 void *data_relative( //get data + or - ...
204 inT8 offset); //offset from current
205
206 void *forward(); //move to next element
207
208 void *extract(); //remove from list
209
210 void *move_to_first(); //go to start of list
211
212 void *move_to_last(); //go to end of list
213
214 void mark_cycle_pt(); //remember current
215
216 BOOL8 empty() { //is list empty?
217 #ifndef NDEBUG
218 if (!list)
219 NO_LIST.error ("CLIST_ITERATOR::empty", ABORT, NULL);
220 #endif
221 return list->empty ();
222 }
223
224 BOOL8 current_extracted() { //current extracted?
225 return !current;
226 }
227
228 BOOL8 at_first(); //Current is first?
229
230 BOOL8 at_last(); //Current is last?
231
232 BOOL8 cycled_list(); //Completed a cycle?
233
234 void add_to_end( //add at end &
235 void *new_data); //dont move
236
237 void exchange( //positions of 2 links
238 CLIST_ITERATOR *other_it); //other iterator
239
240 inT32 length(); //# elements in list
241
242 void sort ( //sort elements
243 int comparator ( //comparison routine
244 const void *, const void *));
245
246 };
247
248 /***********************************************************************
249 * CLIST_ITERATOR::set_to_list
250 *
251 * (Re-)initialise the iterator to point to the start of the list_to_iterate
252 * over.
253 **********************************************************************/
254
255 inline void CLIST_ITERATOR::set_to_list( //change list
256 CLIST *list_to_iterate) {
257 #ifndef NDEBUG
258 if (!this)
259 NULL_OBJECT.error ("CLIST_ITERATOR::set_to_list", ABORT, NULL);
260 if (!list_to_iterate)
261 BAD_PARAMETER.error ("CLIST_ITERATOR::set_to_list", ABORT,
262 "list_to_iterate is NULL");
263 #endif
264
265 list = list_to_iterate;
266 prev = list->last;
267 current = list->First ();
268 next = current != NULL ? current->next : NULL;
269 cycle_pt = NULL; //await explicit set
270 started_cycling = FALSE;
271 ex_current_was_last = FALSE;
272 ex_current_was_cycle_pt = FALSE;
273 }
274
275
276 /***********************************************************************
277 * CLIST_ITERATOR::CLIST_ITERATOR
278 *
279 * CONSTRUCTOR - set iterator to specified list;
280 **********************************************************************/
281
282 inline CLIST_ITERATOR::CLIST_ITERATOR(CLIST *list_to_iterate) {
283 set_to_list(list_to_iterate);
284 }
285
286
287 /***********************************************************************
288 * CLIST_ITERATOR::add_after_then_move
289 *
290 * Add a new element to the list after the current element and move the
291 * iterator to the new element.
292 **********************************************************************/
293
294 inline void CLIST_ITERATOR::add_after_then_move( // element to add
295 void *new_data) {
296 CLIST_LINK *new_element;
297
298 #ifndef NDEBUG
299 if (!this)
300 NULL_OBJECT.error ("CLIST_ITERATOR::add_after_then_move", ABORT, NULL);
301 if (!list)
302 NO_LIST.error ("CLIST_ITERATOR::add_after_then_move", ABORT, NULL);
303 if (!new_data)
304 BAD_PARAMETER.error ("CLIST_ITERATOR::add_after_then_move", ABORT,
305 "new_data is NULL");
306 #endif
307
308 new_element = new CLIST_LINK;
309 new_element->data = new_data;
310
311 if (list->empty ()) {
312 new_element->next = new_element;
313 list->last = new_element;
314 prev = next = new_element;
315 }
316 else {
317 new_element->next = next;
318
319 if (current) { //not extracted
320 current->next = new_element;
321 prev = current;
322 if (current == list->last)
323 list->last = new_element;
324 }
325 else { //current extracted
326 prev->next = new_element;
327 if (ex_current_was_last)
328 list->last = new_element;
329 if (ex_current_was_cycle_pt)
330 cycle_pt = new_element;
331 }
332 }
333 current = new_element;
334 }
335
336
337 /***********************************************************************
338 * CLIST_ITERATOR::add_after_stay_put
339 *
340 * Add a new element to the list after the current element but do not move
341 * the iterator to the new element.
342 **********************************************************************/
343
344 inline void CLIST_ITERATOR::add_after_stay_put( // element to add
345 void *new_data) {
346 CLIST_LINK *new_element;
347
348 #ifndef NDEBUG
349 if (!this)
350 NULL_OBJECT.error ("CLIST_ITERATOR::add_after_stay_put", ABORT, NULL);
351 if (!list)
352 NO_LIST.error ("CLIST_ITERATOR::add_after_stay_put", ABORT, NULL);
353 if (!new_data)
354 BAD_PARAMETER.error ("CLIST_ITERATOR::add_after_stay_put", ABORT,
355 "new_data is NULL");
356 #endif
357
358 new_element = new CLIST_LINK;
359 new_element->data = new_data;
360
361 if (list->empty ()) {
362 new_element->next = new_element;
363 list->last = new_element;
364 prev = next = new_element;
365 ex_current_was_last = FALSE;
366 current = NULL;
367 }
368 else {
369 new_element->next = next;
370
371 if (current) { //not extracted
372 current->next = new_element;
373 if (prev == current)
374 prev = new_element;
375 if (current == list->last)
376 list->last = new_element;
377 }
378 else { //current extracted
379 prev->next = new_element;
380 if (ex_current_was_last) {
381 list->last = new_element;
382 ex_current_was_last = FALSE;
383 }
384 }
385 next = new_element;
386 }
387 }
388
389
390 /***********************************************************************
391 * CLIST_ITERATOR::add_before_then_move
392 *
393 * Add a new element to the list before the current element and move the
394 * iterator to the new element.
395 **********************************************************************/
396
397 inline void CLIST_ITERATOR::add_before_then_move( // element to add
398 void *new_data) {
399 CLIST_LINK *new_element;
400
401 #ifndef NDEBUG
402 if (!this)
403 NULL_OBJECT.error ("CLIST_ITERATOR::add_before_then_move", ABORT, NULL);
404 if (!list)
405 NO_LIST.error ("CLIST_ITERATOR::add_before_then_move", ABORT, NULL);
406 if (!new_data)
407 BAD_PARAMETER.error ("CLIST_ITERATOR::add_before_then_move", ABORT,
408 "new_data is NULL");
409 #endif
410
411 new_element = new CLIST_LINK;
412 new_element->data = new_data;
413
414 if (list->empty ()) {
415 new_element->next = new_element;
416 list->last = new_element;
417 prev = next = new_element;
418 }
419 else {
420 prev->next = new_element;
421 if (current) { //not extracted
422 new_element->next = current;
423 next = current;
424 }
425 else { //current extracted
426 new_element->next = next;
427 if (ex_current_was_last)
428 list->last = new_element;
429 if (ex_current_was_cycle_pt)
430 cycle_pt = new_element;
431 }
432 }
433 current = new_element;
434 }
435
436
437 /***********************************************************************
438 * CLIST_ITERATOR::add_before_stay_put
439 *
440 * Add a new element to the list before the current element but dont move the
441 * iterator to the new element.
442 **********************************************************************/
443
444 inline void CLIST_ITERATOR::add_before_stay_put( // element to add
445 void *new_data) {
446 CLIST_LINK *new_element;
447
448 #ifndef NDEBUG
449 if (!this)
450 NULL_OBJECT.error ("CLIST_ITERATOR::add_before_stay_put", ABORT, NULL);
451 if (!list)
452 NO_LIST.error ("CLIST_ITERATOR::add_before_stay_put", ABORT, NULL);
453 if (!new_data)
454 BAD_PARAMETER.error ("CLIST_ITERATOR::add_before_stay_put", ABORT,
455 "new_data is NULL");
456 #endif
457
458 new_element = new CLIST_LINK;
459 new_element->data = new_data;
460
461 if (list->empty ()) {
462 new_element->next = new_element;
463 list->last = new_element;
464 prev = next = new_element;
465 ex_current_was_last = TRUE;
466 current = NULL;
467 }
468 else {
469 prev->next = new_element;
470 if (current) { //not extracted
471 new_element->next = current;
472 if (next == current)
473 next = new_element;
474 }
475 else { //current extracted
476 new_element->next = next;
477 if (ex_current_was_last)
478 list->last = new_element;
479 }
480 prev = new_element;
481 }
482 }
483
484
485 /***********************************************************************
486 * CLIST_ITERATOR::add_list_after
487 *
488 * Insert another list to this list after the current element but dont move the
489 * iterator.
490 **********************************************************************/
491
492 inline void CLIST_ITERATOR::add_list_after(CLIST *list_to_add) {
493 #ifndef NDEBUG
494 if (!this)
495 NULL_OBJECT.error ("CLIST_ITERATOR::add_list_after", ABORT, NULL);
496 if (!list)
497 NO_LIST.error ("CLIST_ITERATOR::add_list_after", ABORT, NULL);
498 if (!list_to_add)
499 BAD_PARAMETER.error ("CLIST_ITERATOR::add_list_after", ABORT,
500 "list_to_add is NULL");
501 #endif
502
503 if (!list_to_add->empty ()) {
504 if (list->empty ()) {
505 list->last = list_to_add->last;
506 prev = list->last;
507 next = list->First ();
508 ex_current_was_last = TRUE;
509 current = NULL;
510 }
511 else {
512 if (current) { //not extracted
513 current->next = list_to_add->First ();
514 if (current == list->last)
515 list->last = list_to_add->last;
516 list_to_add->last->next = next;
517 next = current->next;
518 }
519 else { //current extracted
520 prev->next = list_to_add->First ();
521 if (ex_current_was_last) {
522 list->last = list_to_add->last;
523 ex_current_was_last = FALSE;
524 }
525 list_to_add->last->next = next;
526 next = prev->next;
527 }
528 }
529 list_to_add->last = NULL;
530 }
531 }
532
533
534 /***********************************************************************
535 * CLIST_ITERATOR::add_list_before
536 *
537 * Insert another list to this list before the current element. Move the
538 * iterator to the start of the inserted elements
539 * iterator.
540 **********************************************************************/
541
542 inline void CLIST_ITERATOR::add_list_before(CLIST *list_to_add) {
543 #ifndef NDEBUG
544 if (!this)
545 NULL_OBJECT.error ("CLIST_ITERATOR::add_list_before", ABORT, NULL);
546 if (!list)
547 NO_LIST.error ("CLIST_ITERATOR::add_list_before", ABORT, NULL);
548 if (!list_to_add)
549 BAD_PARAMETER.error ("CLIST_ITERATOR::add_list_before", ABORT,
550 "list_to_add is NULL");
551 #endif
552
553 if (!list_to_add->empty ()) {
554 if (list->empty ()) {
555 list->last = list_to_add->last;
556 prev = list->last;
557 current = list->First ();
558 next = current->next;
559 ex_current_was_last = FALSE;
560 }
561 else {
562 prev->next = list_to_add->First ();
563 if (current) { //not extracted
564 list_to_add->last->next = current;
565 }
566 else { //current extracted
567 list_to_add->last->next = next;
568 if (ex_current_was_last)
569 list->last = list_to_add->last;
570 if (ex_current_was_cycle_pt)
571 cycle_pt = prev->next;
572 }
573 current = prev->next;
574 next = current->next;
575 }
576 list_to_add->last = NULL;
577 }
578 }
579
580
581 /***********************************************************************
582 * CLIST_ITERATOR::extract
583 *
584 * Do extraction by removing current from the list, deleting the cons cell
585 * and returning the data to the caller, but NOT updating the iterator. (So
586 * that any calling loop can do this.) The iterator's current points to
587 * NULL. If the data is to be deleted, this is the callers responsibility.
588 **********************************************************************/
589
590 inline void *CLIST_ITERATOR::extract() {
591 void *extracted_data;
592
593 #ifndef NDEBUG
594 if (!this)
595 NULL_OBJECT.error ("CLIST_ITERATOR::extract", ABORT, NULL);
596 if (!list)
597 NO_LIST.error ("CLIST_ITERATOR::extract", ABORT, NULL);
598 if (!current) //list empty or
599 //element extracted
600 NULL_CURRENT.error ("CLIST_ITERATOR::extract",
601 ABORT, NULL);
602 #endif
603
604 if (list->singleton()) {
605 // Special case where we do need to change the iterator.
606 prev = next = list->last = NULL;
607 } else {
608 prev->next = next; //remove from list
609
610 if (current == list->last) {
611 list->last = prev;
612 ex_current_was_last = TRUE;
613 } else {
614 ex_current_was_last = FALSE;
615 }
616 }
617 // Always set ex_current_was_cycle_pt so an add/forward will work in a loop.
618 ex_current_was_cycle_pt = (current == cycle_pt) ? TRUE : FALSE;
619 extracted_data = current->data;
620 delete(current); //destroy CONS cell
621 current = NULL;
622 return extracted_data;
623 }
624
625
626 /***********************************************************************
627 * CLIST_ITERATOR::move_to_first()
628 *
629 * Move current so that it is set to the start of the list.
630 * Return data just in case anyone wants it.
631 **********************************************************************/
632
633 inline void *CLIST_ITERATOR::move_to_first() {
634 #ifndef NDEBUG
635 if (!this)
636 NULL_OBJECT.error ("CLIST_ITERATOR::move_to_first", ABORT, NULL);
637 if (!list)
638 NO_LIST.error ("CLIST_ITERATOR::move_to_first", ABORT, NULL);
639 #endif
640
641 current = list->First ();
642 prev = list->last;
643 next = current != NULL ? current->next : NULL;
644 return current != NULL ? current->data : NULL;
645 }
646
647
648 /***********************************************************************
649 * CLIST_ITERATOR::mark_cycle_pt()
650 *
651 * Remember the current location so that we can tell whether we've returned
652 * to this point later.
653 *
654 * If the current point is deleted either now, or in the future, the cycle
655 * point will be set to the next item which is set to current. This could be
656 * by a forward, add_after_then_move or add_after_then_move.
657 **********************************************************************/
658
659 inline void CLIST_ITERATOR::mark_cycle_pt() {
660 #ifndef NDEBUG
661 if (!this)
662 NULL_OBJECT.error ("CLIST_ITERATOR::mark_cycle_pt", ABORT, NULL);
663 if (!list)
664 NO_LIST.error ("CLIST_ITERATOR::mark_cycle_pt", ABORT, NULL);
665 #endif
666
667 if (current)
668 cycle_pt = current;
669 else
670 ex_current_was_cycle_pt = TRUE;
671 started_cycling = FALSE;
672 }
673
674
675 /***********************************************************************
676 * CLIST_ITERATOR::at_first()
677 *
678 * Are we at the start of the list?
679 *
680 **********************************************************************/
681
682 inline BOOL8 CLIST_ITERATOR::at_first() {
683 #ifndef NDEBUG
684 if (!this)
685 NULL_OBJECT.error ("CLIST_ITERATOR::at_first", ABORT, NULL);
686 if (!list)
687 NO_LIST.error ("CLIST_ITERATOR::at_first", ABORT, NULL);
688 #endif
689
690 //we're at a deleted
691 return ((list->empty ()) || (current == list->First ()) || ((current == NULL) &&
692 (prev == list->last) && //NON-last pt between
693 !ex_current_was_last)); //first and last
694 }
695
696
697 /***********************************************************************
698 * CLIST_ITERATOR::at_last()
699 *
700 * Are we at the end of the list?
701 *
702 **********************************************************************/
703
704 inline BOOL8 CLIST_ITERATOR::at_last() {
705 #ifndef NDEBUG
706 if (!this)
707 NULL_OBJECT.error ("CLIST_ITERATOR::at_last", ABORT, NULL);
708 if (!list)
709 NO_LIST.error ("CLIST_ITERATOR::at_last", ABORT, NULL);
710 #endif
711
712 //we're at a deleted
713 return ((list->empty ()) || (current == list->last) || ((current == NULL) &&
714 (prev == list->last) && //last point between
715 ex_current_was_last)); //first and last
716 }
717
718
719 /***********************************************************************
720 * CLIST_ITERATOR::cycled_list()
721 *
722 * Have we returned to the cycle_pt since it was set?
723 *
724 **********************************************************************/
725
726 inline BOOL8 CLIST_ITERATOR::cycled_list() {
727 #ifndef NDEBUG
728 if (!this)
729 NULL_OBJECT.error ("CLIST_ITERATOR::cycled_list", ABORT, NULL);
730 if (!list)
731 NO_LIST.error ("CLIST_ITERATOR::cycled_list", ABORT, NULL);
732 #endif
733
734 return ((list->empty ()) || ((current == cycle_pt) && started_cycling));
735
736 }
737
738
739 /***********************************************************************
740 * CLIST_ITERATOR::length()
741 *
742 * Return the length of the list
743 *
744 **********************************************************************/
745
746 inline inT32 CLIST_ITERATOR::length() {
747 #ifndef NDEBUG
748 if (!this)
749 NULL_OBJECT.error ("CLIST_ITERATOR::length", ABORT, NULL);
750 if (!list)
751 NO_LIST.error ("CLIST_ITERATOR::length", ABORT, NULL);
752 #endif
753
754 return list->length ();
755 }
756
757
758 /***********************************************************************
759 * CLIST_ITERATOR::sort()
760 *
761 * Sort the elements of the list, then reposition at the start.
762 *
763 **********************************************************************/
764
765 inline void
766 CLIST_ITERATOR::sort ( //sort elements
767 int comparator ( //comparison routine
768 const void *, const void *)) {
769 #ifndef NDEBUG
770 if (!this)
771 NULL_OBJECT.error ("CLIST_ITERATOR::sort", ABORT, NULL);
772 if (!list)
773 NO_LIST.error ("CLIST_ITERATOR::sort", ABORT, NULL);
774 #endif
775
776 list->sort (comparator);
777 move_to_first();
778 }
779
780
781 /***********************************************************************
782 * CLIST_ITERATOR::add_to_end
783 *
784 * Add a new element to the end of the list without moving the iterator.
785 * This is provided because a single linked list cannot move to the last as
786 * the iterator couldn't set its prev pointer. Adding to the end is
787 * essential for implementing
788 queues.
789 **********************************************************************/
790
791 inline void CLIST_ITERATOR::add_to_end( // element to add
792 void *new_data) {
793 CLIST_LINK *new_element;
794
795 #ifndef NDEBUG
796 if (!this)
797 NULL_OBJECT.error ("CLIST_ITERATOR::add_to_end", ABORT, NULL);
798 if (!list)
799 NO_LIST.error ("CLIST_ITERATOR::add_to_end", ABORT, NULL);
800 if (!new_data)
801 BAD_PARAMETER.error ("CLIST_ITERATOR::add_to_end", ABORT,
802 "new_data is NULL");
803 #endif
804
805 if (this->at_last ()) {
806 this->add_after_stay_put (new_data);
807 }
808 else {
809 if (this->at_first ()) {
810 this->add_before_stay_put (new_data);
811 list->last = prev;
812 }
813 else { //Iteratr is elsewhere
814 new_element = new CLIST_LINK;
815 new_element->data = new_data;
816
817 new_element->next = list->last->next;
818 list->last->next = new_element;
819 list->last = new_element;
820 }
821 }
822 }
823
824
825 /***********************************************************************
826 QUOTE_IT MACRO DEFINITION
827 ===========================
828 Replace <parm> with "<parm>". <parm> may be an arbitrary number of tokens
829 ***********************************************************************/
830
831 #define QUOTE_IT( parm ) #parm
832
833 /***********************************************************************
834 CLISTIZE( CLASSNAME ) MACRO DEFINITION
835 ======================================
836
837 CLASSNAME is assumed to be the name of a class to be used in a CONS list
838
839 NOTE: Because we dont use virtual functions in the list code, the list code
840 will NOT work correctly for classes derived from this.
841
842 The macro generates:
843 - An element deletion function: CLASSNAME##_c1_zapper
844 - An element copier function:
845 CLASSNAME##_c1_copier
846 - A CLIST subclass: CLASSNAME##_CLIST
847 - A CLIST_ITERATOR subclass:
848 CLASSNAME##_C_IT
849
850 NOTE: Generated names do NOT clash with those generated by ELISTIZE,
851 ELIST2ISE and CLIST2IZE
852
853 Two macros are provided: CLISTIZE and CLISTIZEH
854 The ...IZEH macros just define the class names for use in .h files
855 The ...IZE macros define the code use in .c files
856 ***********************************************************************/
857
858 /***********************************************************************
859 CLISTIZEH( CLASSNAME ) MACRO
860
861 CLISTIZEH is a concatenation of 3 fragments CLISTIZEH_A, CLISTIZEH_B and
862 CLISTIZEH_C.
863 ***********************************************************************/
864
865 #define CLISTIZEH_A( CLASSNAME ) \
866 \
867 extern DLLSYM void CLASSNAME##_c1_zapper( /*delete a link*/ \
868 void* link); /*link to delete*/ \
869 \
870 extern DLLSYM void* CLASSNAME##_c1_copier( /*deep copy a link*/ \
871 void* old_element); /*source link */
872
873 #define CLISTIZEH_B( CLASSNAME ) \
874 \
875 /*********************************************************************** \
876 * CLASS - CLASSNAME##_CLIST \
877 * \
878 * List class for class CLASSNAME \
879 * \
880 **********************************************************************/ \
881 \
882 class DLLSYM CLASSNAME##_CLIST : public CLIST \
883 { \
884 public: \
885 CLASSNAME##_CLIST():CLIST() {} \
886 /* constructor */ \
887 \
888 CLASSNAME##_CLIST( /* dont construct */ \
889 const CLASSNAME##_CLIST&) /*by initial assign*/ \
890 { DONT_CONSTRUCT_LIST_BY_COPY.error( QUOTE_IT( CLASSNAME##_CLIST ), \
891 ABORT, NULL ); } \
892 \
893 void deep_clear() /* delete elements */ \
894 { CLIST::internal_deep_clear( &CLASSNAME##_c1_zapper ); } \
895 \
896 void operator=( /* prevent assign */ \
897 const CLASSNAME##_CLIST&) \
898 { DONT_ASSIGN_LISTS.error( QUOTE_IT( CLASSNAME##_CLIST ), \
899 ABORT, NULL ); }
900
901 #define CLISTIZEH_C( CLASSNAME ) \
902 \
903 }; \
904 \
905 \
906 \
907 /*********************************************************************** \
908 * CLASS - CLASSNAME##_C_IT \
909 * \
910 * Iterator class for class CLASSNAME##_CLIST \
911 * \
912 * Note: We don't need to coerce pointers to member functions input \
913 * parameters as these are automatically converted to the type of the base \
914 * type. ("A ptr to a class may be converted to a pointer to a public base \
915 * class of that class") \
916 **********************************************************************/ \
917 \
918 class DLLSYM CLASSNAME##_C_IT : public CLIST_ITERATOR \
919 { \
920 public: \
921 CLASSNAME##_C_IT():CLIST_ITERATOR(){} \
922 \
923 CLASSNAME##_C_IT( \
924 CLASSNAME##_CLIST* list):CLIST_ITERATOR(list){} \
925 \
926 CLASSNAME* data() \
927 { return (CLASSNAME*) CLIST_ITERATOR::data(); } \
928 \
929 CLASSNAME* data_relative( \
930 inT8 offset) \
931 { return (CLASSNAME*) CLIST_ITERATOR::data_relative( offset ); } \
932 \
933 CLASSNAME* forward() \
934 { return (CLASSNAME*) CLIST_ITERATOR::forward(); } \
935 \
936 CLASSNAME* extract() \
937 { return (CLASSNAME*) CLIST_ITERATOR::extract(); } \
938 \
939 CLASSNAME* move_to_first() \
940 { return (CLASSNAME*) CLIST_ITERATOR::move_to_first(); } \
941 \
942 CLASSNAME* move_to_last() \
943 { return (CLASSNAME*) CLIST_ITERATOR::move_to_last(); } \
944 };
945
946 #define CLISTIZEH( CLASSNAME ) \
947 \
948 CLISTIZEH_A( CLASSNAME ) \
949 \
950 CLISTIZEH_B( CLASSNAME ) \
951 \
952 CLISTIZEH_C( CLASSNAME )
953
954 /***********************************************************************
955 CLISTIZE( CLASSNAME ) MACRO
956 ***********************************************************************/
957
958 #define CLISTIZE( CLASSNAME ) \
959 \
960 /*********************************************************************** \
961 * CLASSNAME##_c1_zapper \
962 * \
963 * A function which can delete a CLASSNAME element. This is passed to the \
964 * generic deep_clear list member function so that when a list is cleared the \
965 * elements on the list are properly destroyed from the base class, even \
966 * though we dont use a virtual destructor function. \
967 **********************************************************************/ \
968 \
969 DLLSYM void CLASSNAME##_c1_zapper( /*delete a link*/ \
970 void* link) /*link to delete*/ \
971 { \
972 delete (CLASSNAME *) link; \
973 } \
974
975 #endif