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