All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules 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 
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 
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 
145 {
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 
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 
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 
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 
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 
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 
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
void * extract()
Definition: clst.h:590
void * move_to_first()
Definition: clst.h:633
BOOL8 empty()
Definition: clst.h:216
void mark_cycle_pt()
Definition: clst.h:659
LIST last(LIST var_list)
Definition: oldlist.cpp:277
BOOL8 cycled_list()
Definition: clst.h:726
unsigned char BOOL8
Definition: host.h:113
void set_to_list(CLIST *list_to_iterate)
Definition: clst.h:255
Definition: clst.h:70
void assign_to_sublist(CLIST_ITERATOR *start_it, CLIST_ITERATOR *end_it)
Definition: clst.cpp:108
void add_before_stay_put(void *new_data)
Definition: clst.h:444
void add_list_after(CLIST *list_to_add)
Definition: clst.h:492
CLIST_ITERATOR()
Definition: clst.h:165
bool singleton() const
Definition: clst.h:99
Definition: errcode.h:30
inT32 length()
Definition: clst.h:746
void add_after_stay_put(void *new_data)
Definition: clst.h:344
~CLIST()
Definition: clst.h:85
const ERRCODE BAD_PARAMETER
Definition: lsterr.h:39
BOOL8 at_last()
Definition: clst.h:704
const ERRCODE NO_LIST
Definition: lsterr.h:32
CLIST_LINK()
Definition: clst.h:49
void add_after_then_move(void *new_data)
Definition: clst.h:294
void sort(int comparator(const void *, const void *))
Definition: clst.h:766
const ERRCODE NULL_CURRENT
Definition: lsterr.h:35
void shallow_copy(CLIST *from_list)
Definition: clst.h:103
inT32 length() const
Definition: clst.cpp:132
void error(const char *caller, TessErrorLogCode action, const char *format,...) const
Definition: errcode.cpp:40
CLIST_LINK(const CLIST_LINK &)
Definition: clst.h:53
void add_list_before(CLIST *list_to_add)
Definition: clst.h:542
bool empty() const
Definition: clst.h:95
BOOL8 at_first()
Definition: clst.h:682
CLIST()
Definition: clst.h:81
BOOL8 current_extracted()
Definition: clst.h:224
const ERRCODE NULL_DATA
Definition: lsterr.h:34
void sort(int comparator(const void *, const void *))
Definition: clst.cpp:154
void add_before_then_move(void *new_data)
Definition: clst.h:397
#define FALSE
Definition: capi.h:29
void add_to_end(void *new_data)
Definition: clst.h:791
#define TRUE
Definition: capi.h:28
#define NULL
Definition: host.h:144
SIGNED char inT8
Definition: host.h:98
const ERRCODE NULL_OBJECT
Definition: lsterr.h:33
void * data()
Definition: clst.h:193
#define DLLSYM
Definition: platform.h:25
int inT32
Definition: host.h:102