tesseract  5.0.0
elst.h
Go to the documentation of this file.
1 /**********************************************************************
2  * File: elst.h (Formerly elist.h)
3  * Description: Embedded 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 ELST_H
20 #define ELST_H
21 
22 #include "list.h"
23 #include "lsterr.h"
24 #include "serialis.h"
25 
26 #include <cstdio>
27 
28 namespace tesseract {
29 
30 class ELIST_ITERATOR;
31 
32 /**********************************************************************
33 This module implements list classes and iterators.
34 The following list types and iterators are provided:
35 
36  List type List Class Iterator Class Element Class
37  --------- ---------- -------------- -------------
38 
39  Embedded list ELIST
40  ELIST_ITERATOR
41  ELIST_LINK
42  (Single linked)
43 
44  Embedded list ELIST2
45  ELIST2_ITERATOR
46  ELIST2_LINK
47  (Double linked)
48 
49  Cons List CLIST
50  CLIST_ITERATOR
51  CLIST_LINK
52  (Single linked)
53 
54 An embedded list is where the list pointers are provided by a generic class.
55 Data types to be listed inherit from the generic class. Data is thus linked
56 in only ONE list at any one time.
57 
58 A cons list has a separate structure for a "cons cell". This contains the
59 list pointer(s) AND a pointer to the data structure held on the list. A
60 structure can be on many cons lists at the same time, and the structure does
61 not need to inherit from any generic class in order to be on the list.
62 
63 The implementation of lists is very careful about space and speed overheads.
64 This is why many embedded lists are provided. The same concerns mean that
65 in-line type coercion is done, rather than use virtual functions. This is
66 cumbersome in that each data type to be listed requires its own iterator and
67 list class - though macros can generate these. It also prevents heterogeneous
68 lists.
69 **********************************************************************/
70 
71 /**********************************************************************
72  * CLASS - ELIST_LINK
73  *
74  * Generic link class for singly linked lists with
75  *embedded links
76  *
77  * Note: No destructor - elements are assumed to be destroyed EITHER after
78  * they have been extracted from a list OR by the ELIST destructor which
79  * walks the list.
80  **********************************************************************/
81 
82 class ELIST_LINK {
83  friend class ELIST_ITERATOR;
84  friend class ELIST;
85 
86  ELIST_LINK *next;
87 
88 public:
90  next = nullptr;
91  }
92  // constructor
93 
94  // The special copy constructor is used by lots of classes.
96  next = nullptr;
97  }
98 
99  // The special assignment operator is used by lots of classes.
100  void operator=(const ELIST_LINK &) {
101  next = nullptr;
102  }
103 };
104 
105 /**********************************************************************
106  * CLASS - ELIST
107  *
108  * Generic list class for singly linked lists with embedded links
109  **********************************************************************/
110 
112  friend class ELIST_ITERATOR;
113 
114  ELIST_LINK *last = nullptr; // End of list
115  //(Points to head)
116  ELIST_LINK *First() { // return first
117  return last ? last->next : nullptr;
118  }
119 
120 public:
121  // destroy all links
122  void internal_clear(void (*zapper)(void *));
123 
124  bool empty() const {
125  return !last;
126  }
127 
128  bool singleton() const {
129  return last ? (last == last->next) : false;
130  }
131 
132  void shallow_copy( // dangerous!!
133  ELIST *from_list) { // beware destructors!!
134  last = from_list->last;
135  }
136 
137  // ptr to copier functn
139  const ELIST *list); // list being copied
140 
141  void assign_to_sublist( // to this list
142  ELIST_ITERATOR *start_it, // from list start
143  ELIST_ITERATOR *end_it); // from list end
144 
145  // # elements in list
146  int32_t length() const {
147  int32_t count = 0;
148  if (last != nullptr) {
149  count = 1;
150  for (auto it = last->next; it != last; it = it->next) {
151  count++;
152  }
153  }
154  return count;
155  }
156 
157  void sort( // sort elements
158  int comparator( // comparison routine
159  const void *, const void *));
160 
161  // Assuming list has been sorted already, insert new_link to
162  // keep the list sorted according to the same comparison function.
163  // Comparison function is the same as used by sort, i.e. uses double
164  // indirection. Time is O(1) to add to beginning or end.
165  // Time is linear to add pre-sorted items to an empty list.
166  // If unique is set to true and comparator() returns 0 (an entry with the
167  // same information as the one contained in new_link is already in the
168  // list) - new_link is not added to the list and the function returns the
169  // pointer to the identical entry that already exists in the list
170  // (otherwise the function returns new_link).
171  ELIST_LINK *add_sorted_and_find(int comparator(const void *, const void *), bool unique,
172  ELIST_LINK *new_link);
173 
174  // Same as above, but returns true if the new entry was inserted, false
175  // if the identical entry already existed in the list.
176  bool add_sorted(int comparator(const void *, const void *), bool unique, ELIST_LINK *new_link) {
177  return (add_sorted_and_find(comparator, unique, new_link) == new_link);
178  }
179 };
180 
181 /***********************************************************************
182  * CLASS - ELIST_ITERATOR
183  *
184  * Generic iterator class for singly linked lists with
185  *embedded links
186  **********************************************************************/
187 
190 
191  ELIST *list; // List being iterated
192  ELIST_LINK *prev; // prev element
193  ELIST_LINK *current; // current element
194  ELIST_LINK *next; // next element
195  ELIST_LINK *cycle_pt; // point we are cycling the list to.
196  bool ex_current_was_last; // current extracted was end of list
197  bool ex_current_was_cycle_pt; // current extracted was cycle point
198  bool started_cycling; // Have we moved off the start?
199 
200  ELIST_LINK *extract_sublist( // from this current...
201  ELIST_ITERATOR *other_it); // to other current
202 
203 public:
204  ELIST_ITERATOR() { // constructor
205  list = nullptr;
206  } // unassigned list
207 
208  explicit ELIST_ITERATOR(ELIST *list_to_iterate);
209 
210  void set_to_list( // change list
211  ELIST *list_to_iterate);
212 
213  void add_after_then_move( // add after current &
214  ELIST_LINK *new_link); // move to new
215 
216  void add_after_stay_put( // add after current &
217  ELIST_LINK *new_link); // stay at current
218 
219  void add_before_then_move( // add before current &
220  ELIST_LINK *new_link); // move to new
221 
222  void add_before_stay_put( // add before current &
223  ELIST_LINK *new_link); // stay at current
224 
225  void add_list_after( // add a list &
226  ELIST *list_to_add); // stay at current
227 
228  void add_list_before( // add a list &
229  ELIST *list_to_add); // move to it 1st item
230 
231  ELIST_LINK *data() { // get current data
232 #ifndef NDEBUG
233  if (!list) {
234  NO_LIST.error("ELIST_ITERATOR::data", ABORT, nullptr);
235  }
236  if (!current) {
237  NULL_DATA.error("ELIST_ITERATOR::data", ABORT, nullptr);
238  }
239 #endif
240  return current;
241  }
242 
243  ELIST_LINK *data_relative( // get data + or - ...
244  int8_t offset); // offset from current
245 
246  ELIST_LINK *forward(); // move to next element
247 
248  ELIST_LINK *extract(); // remove from list
249 
250  ELIST_LINK *move_to_first(); // go to start of list
251 
252  ELIST_LINK *move_to_last(); // go to end of list
253 
254  void mark_cycle_pt(); // remember current
255 
256  bool empty() const { // is list empty?
257 #ifndef NDEBUG
258  if (!list) {
259  NO_LIST.error("ELIST_ITERATOR::empty", ABORT, nullptr);
260  }
261 #endif
262  return list->empty();
263  }
264 
265  bool current_extracted() const { // current extracted?
266  return !current;
267  }
268 
269  bool at_first() const; // Current is first?
270 
271  bool at_last() const; // Current is last?
272 
273  bool cycled_list() const; // Completed a cycle?
274 
275  void add_to_end( // add at end &
276  ELIST_LINK *new_link); // don't move
277 
278  void exchange( // positions of 2 links
279  ELIST_ITERATOR *other_it); // other iterator
280 
281  //# elements in list
282  int32_t length() const {
283  return list->length();
284  }
285 
286  void sort( // sort elements
287  int comparator( // comparison routine
288  const void *, const void *));
289 };
290 
291 /***********************************************************************
292  * ELIST_ITERATOR::set_to_list
293  *
294  * (Re-)initialise the iterator to point to the start of the list_to_iterate
295  * over.
296  **********************************************************************/
297 
298 inline void ELIST_ITERATOR::set_to_list( // change list
299  ELIST *list_to_iterate) {
300 #ifndef NDEBUG
301  if (!list_to_iterate) {
302  BAD_PARAMETER.error("ELIST_ITERATOR::set_to_list", ABORT, "list_to_iterate is nullptr");
303  }
304 #endif
305 
306  list = list_to_iterate;
307  prev = list->last;
308  current = list->First();
309  next = current ? current->next : nullptr;
310  cycle_pt = nullptr; // await explicit set
311  started_cycling = false;
312  ex_current_was_last = false;
313  ex_current_was_cycle_pt = false;
314 }
315 
316 /***********************************************************************
317  * ELIST_ITERATOR::ELIST_ITERATOR
318  *
319  * CONSTRUCTOR - set iterator to specified list;
320  **********************************************************************/
321 
322 inline ELIST_ITERATOR::ELIST_ITERATOR(ELIST *list_to_iterate) {
323  set_to_list(list_to_iterate);
324 }
325 
326 /***********************************************************************
327  * ELIST_ITERATOR::add_after_then_move
328  *
329  * Add a new element to the list after the current element and move the
330  * iterator to the new element.
331  **********************************************************************/
332 
333 inline void ELIST_ITERATOR::add_after_then_move( // element to add
334  ELIST_LINK *new_element) {
335 #ifndef NDEBUG
336  if (!list) {
337  NO_LIST.error("ELIST_ITERATOR::add_after_then_move", ABORT, nullptr);
338  }
339  if (!new_element) {
340  BAD_PARAMETER.error("ELIST_ITERATOR::add_after_then_move", ABORT, "new_element is nullptr");
341  }
342  if (new_element->next) {
343  STILL_LINKED.error("ELIST_ITERATOR::add_after_then_move", ABORT, nullptr);
344  }
345 #endif
346 
347  if (list->empty()) {
348  new_element->next = new_element;
349  list->last = new_element;
350  prev = next = new_element;
351  } else {
352  new_element->next = next;
353 
354  if (current) { // not extracted
355  current->next = new_element;
356  prev = current;
357  if (current == list->last) {
358  list->last = new_element;
359  }
360  } else { // current extracted
361  prev->next = new_element;
362  if (ex_current_was_last) {
363  list->last = new_element;
364  }
365  if (ex_current_was_cycle_pt) {
366  cycle_pt = new_element;
367  }
368  }
369  }
370  current = new_element;
371 }
372 
373 /***********************************************************************
374  * ELIST_ITERATOR::add_after_stay_put
375  *
376  * Add a new element to the list after the current element but do not move
377  * the iterator to the new element.
378  **********************************************************************/
379 
380 inline void ELIST_ITERATOR::add_after_stay_put( // element to add
381  ELIST_LINK *new_element) {
382 #ifndef NDEBUG
383  if (!list) {
384  NO_LIST.error("ELIST_ITERATOR::add_after_stay_put", ABORT, nullptr);
385  }
386  if (!new_element) {
387  BAD_PARAMETER.error("ELIST_ITERATOR::add_after_stay_put", ABORT, "new_element is nullptr");
388  }
389  if (new_element->next) {
390  STILL_LINKED.error("ELIST_ITERATOR::add_after_stay_put", ABORT, nullptr);
391  }
392 #endif
393 
394  if (list->empty()) {
395  new_element->next = new_element;
396  list->last = new_element;
397  prev = next = new_element;
398  ex_current_was_last = false;
399  current = nullptr;
400  } else {
401  new_element->next = next;
402 
403  if (current) { // not extracted
404  current->next = new_element;
405  if (prev == current) {
406  prev = new_element;
407  }
408  if (current == list->last) {
409  list->last = new_element;
410  }
411  } else { // current extracted
412  prev->next = new_element;
413  if (ex_current_was_last) {
414  list->last = new_element;
415  ex_current_was_last = false;
416  }
417  }
418  next = new_element;
419  }
420 }
421 
422 /***********************************************************************
423  * ELIST_ITERATOR::add_before_then_move
424  *
425  * Add a new element to the list before the current element and move the
426  * iterator to the new element.
427  **********************************************************************/
428 
429 inline void ELIST_ITERATOR::add_before_then_move( // element to add
430  ELIST_LINK *new_element) {
431 #ifndef NDEBUG
432  if (!list) {
433  NO_LIST.error("ELIST_ITERATOR::add_before_then_move", ABORT, nullptr);
434  }
435  if (!new_element) {
436  BAD_PARAMETER.error("ELIST_ITERATOR::add_before_then_move", ABORT, "new_element is nullptr");
437  }
438  if (new_element->next) {
439  STILL_LINKED.error("ELIST_ITERATOR::add_before_then_move", ABORT, nullptr);
440  }
441 #endif
442 
443  if (list->empty()) {
444  new_element->next = new_element;
445  list->last = new_element;
446  prev = next = new_element;
447  } else {
448  prev->next = new_element;
449  if (current) { // not extracted
450  new_element->next = current;
451  next = current;
452  } else { // current extracted
453  new_element->next = next;
454  if (ex_current_was_last) {
455  list->last = new_element;
456  }
457  if (ex_current_was_cycle_pt) {
458  cycle_pt = new_element;
459  }
460  }
461  }
462  current = new_element;
463 }
464 
465 /***********************************************************************
466  * ELIST_ITERATOR::add_before_stay_put
467  *
468  * Add a new element to the list before the current element but don't move the
469  * iterator to the new element.
470  **********************************************************************/
471 
472 inline void ELIST_ITERATOR::add_before_stay_put( // element to add
473  ELIST_LINK *new_element) {
474 #ifndef NDEBUG
475  if (!list) {
476  NO_LIST.error("ELIST_ITERATOR::add_before_stay_put", ABORT, nullptr);
477  }
478  if (!new_element) {
479  BAD_PARAMETER.error("ELIST_ITERATOR::add_before_stay_put", ABORT, "new_element is nullptr");
480  }
481  if (new_element->next) {
482  STILL_LINKED.error("ELIST_ITERATOR::add_before_stay_put", ABORT, nullptr);
483  }
484 #endif
485 
486  if (list->empty()) {
487  new_element->next = new_element;
488  list->last = new_element;
489  prev = next = new_element;
490  ex_current_was_last = true;
491  current = nullptr;
492  } else {
493  prev->next = new_element;
494  if (current) { // not extracted
495  new_element->next = current;
496  if (next == current) {
497  next = new_element;
498  }
499  } else { // current extracted
500  new_element->next = next;
501  if (ex_current_was_last) {
502  list->last = new_element;
503  }
504  }
505  prev = new_element;
506  }
507 }
508 
509 /***********************************************************************
510  * ELIST_ITERATOR::add_list_after
511  *
512  * Insert another list to this list after the current element but don't move
513  *the
514  * iterator.
515  **********************************************************************/
516 
517 inline void ELIST_ITERATOR::add_list_after(ELIST *list_to_add) {
518 #ifndef NDEBUG
519  if (!list) {
520  NO_LIST.error("ELIST_ITERATOR::add_list_after", ABORT, nullptr);
521  }
522  if (!list_to_add) {
523  BAD_PARAMETER.error("ELIST_ITERATOR::add_list_after", ABORT, "list_to_add is nullptr");
524  }
525 #endif
526 
527  if (!list_to_add->empty()) {
528  if (list->empty()) {
529  list->last = list_to_add->last;
530  prev = list->last;
531  next = list->First();
532  ex_current_was_last = true;
533  current = nullptr;
534  } else {
535  if (current) { // not extracted
536  current->next = list_to_add->First();
537  if (current == list->last) {
538  list->last = list_to_add->last;
539  }
540  list_to_add->last->next = next;
541  next = current->next;
542  } else { // current extracted
543  prev->next = list_to_add->First();
544  if (ex_current_was_last) {
545  list->last = list_to_add->last;
546  ex_current_was_last = false;
547  }
548  list_to_add->last->next = next;
549  next = prev->next;
550  }
551  }
552  list_to_add->last = nullptr;
553  }
554 }
555 
556 /***********************************************************************
557  * ELIST_ITERATOR::add_list_before
558  *
559  * Insert another list to this list before the current element. Move the
560  * iterator to the start of the inserted elements
561  * iterator.
562  **********************************************************************/
563 
564 inline void ELIST_ITERATOR::add_list_before(ELIST *list_to_add) {
565 #ifndef NDEBUG
566  if (!list) {
567  NO_LIST.error("ELIST_ITERATOR::add_list_before", ABORT, nullptr);
568  }
569  if (!list_to_add) {
570  BAD_PARAMETER.error("ELIST_ITERATOR::add_list_before", ABORT, "list_to_add is nullptr");
571  }
572 #endif
573 
574  if (!list_to_add->empty()) {
575  if (list->empty()) {
576  list->last = list_to_add->last;
577  prev = list->last;
578  current = list->First();
579  next = current->next;
580  ex_current_was_last = false;
581  } else {
582  prev->next = list_to_add->First();
583  if (current) { // not extracted
584  list_to_add->last->next = current;
585  } else { // current extracted
586  list_to_add->last->next = next;
587  if (ex_current_was_last) {
588  list->last = list_to_add->last;
589  }
590  if (ex_current_was_cycle_pt) {
591  cycle_pt = prev->next;
592  }
593  }
594  current = prev->next;
595  next = current->next;
596  }
597  list_to_add->last = nullptr;
598  }
599 }
600 
601 /***********************************************************************
602  * ELIST_ITERATOR::extract
603  *
604  * Do extraction by removing current from the list, returning it to the
605  * caller, but NOT updating the iterator. (So that any calling loop can do
606  * this.) The iterator's current points to nullptr. If the extracted element
607  * is to be deleted, this is the callers responsibility.
608  **********************************************************************/
609 
611  ELIST_LINK *extracted_link;
612 
613 #ifndef NDEBUG
614  if (!list) {
615  NO_LIST.error("ELIST_ITERATOR::extract", ABORT, nullptr);
616  }
617  if (!current) { // list empty or
618  // element extracted
619  NULL_CURRENT.error("ELIST_ITERATOR::extract", ABORT, nullptr);
620  }
621 #endif
622 
623  if (list->singleton()) {
624  // Special case where we do need to change the iterator.
625  prev = next = list->last = nullptr;
626  } else {
627  prev->next = next; // remove from list
628 
629  ex_current_was_last = (current == list->last);
630  if (ex_current_was_last) {
631  list->last = prev;
632  }
633  }
634  // Always set ex_current_was_cycle_pt so an add/forward will work in a loop.
635  ex_current_was_cycle_pt = (current == cycle_pt);
636  extracted_link = current;
637  extracted_link->next = nullptr; // for safety
638  current = nullptr;
639  return extracted_link;
640 }
641 
642 /***********************************************************************
643  * ELIST_ITERATOR::move_to_first()
644  *
645  * Move current so that it is set to the start of the list.
646  * Return data just in case anyone wants it.
647  **********************************************************************/
648 
650 #ifndef NDEBUG
651  if (!list) {
652  NO_LIST.error("ELIST_ITERATOR::move_to_first", ABORT, nullptr);
653  }
654 #endif
655 
656  current = list->First();
657  prev = list->last;
658  next = current ? current->next : nullptr;
659  return current;
660 }
661 
662 /***********************************************************************
663  * ELIST_ITERATOR::mark_cycle_pt()
664  *
665  * Remember the current location so that we can tell whether we've returned
666  * to this point later.
667  *
668  * If the current point is deleted either now, or in the future, the cycle
669  * point will be set to the next item which is set to current. This could be
670  * by a forward, add_after_then_move or add_after_then_move.
671  **********************************************************************/
672 
674 #ifndef NDEBUG
675  if (!list) {
676  NO_LIST.error("ELIST_ITERATOR::mark_cycle_pt", ABORT, nullptr);
677  }
678 #endif
679 
680  if (current) {
681  cycle_pt = current;
682  } else {
683  ex_current_was_cycle_pt = true;
684  }
685  started_cycling = false;
686 }
687 
688 /***********************************************************************
689  * ELIST_ITERATOR::at_first()
690  *
691  * Are we at the start of the list?
692  *
693  **********************************************************************/
694 
695 inline bool ELIST_ITERATOR::at_first() const {
696 #ifndef NDEBUG
697  if (!list) {
698  NO_LIST.error("ELIST_ITERATOR::at_first", ABORT, nullptr);
699  }
700 #endif
701 
702  // we're at a deleted
703  return ((list->empty()) || (current == list->First()) ||
704  ((current == nullptr) && (prev == list->last) && // NON-last pt between
705  !ex_current_was_last)); // first and last
706 }
707 
708 /***********************************************************************
709  * ELIST_ITERATOR::at_last()
710  *
711  * Are we at the end of the list?
712  *
713  **********************************************************************/
714 
715 inline bool ELIST_ITERATOR::at_last() const {
716 #ifndef NDEBUG
717  if (!list) {
718  NO_LIST.error("ELIST_ITERATOR::at_last", ABORT, nullptr);
719  }
720 #endif
721 
722  // we're at a deleted
723  return ((list->empty()) || (current == list->last) ||
724  ((current == nullptr) && (prev == list->last) && // last point between
725  ex_current_was_last)); // first and last
726 }
727 
728 /***********************************************************************
729  * ELIST_ITERATOR::cycled_list()
730  *
731  * Have we returned to the cycle_pt since it was set?
732  *
733  **********************************************************************/
734 
735 inline bool ELIST_ITERATOR::cycled_list() const {
736 #ifndef NDEBUG
737  if (!list) {
738  NO_LIST.error("ELIST_ITERATOR::cycled_list", ABORT, nullptr);
739  }
740 #endif
741 
742  return ((list->empty()) || ((current == cycle_pt) && started_cycling));
743 }
744 
745 /***********************************************************************
746  * ELIST_ITERATOR::sort()
747  *
748  * Sort the elements of the list, then reposition at the start.
749  *
750  **********************************************************************/
751 
752 inline void ELIST_ITERATOR::sort( // sort elements
753  int comparator( // comparison routine
754  const void *, const void *)) {
755 #ifndef NDEBUG
756  if (!list) {
757  NO_LIST.error("ELIST_ITERATOR::sort", ABORT, nullptr);
758  }
759 #endif
760 
761  list->sort(comparator);
762  move_to_first();
763 }
764 
765 /***********************************************************************
766  * ELIST_ITERATOR::add_to_end
767  *
768  * Add a new element to the end of the list without moving the iterator.
769  * This is provided because a single linked list cannot move to the last as
770  * the iterator couldn't set its prev pointer. Adding to the end is
771  * essential for implementing
772  queues.
773 **********************************************************************/
774 
775 inline void ELIST_ITERATOR::add_to_end( // element to add
776  ELIST_LINK *new_element) {
777 #ifndef NDEBUG
778  if (!list) {
779  NO_LIST.error("ELIST_ITERATOR::add_to_end", ABORT, nullptr);
780  }
781  if (!new_element) {
782  BAD_PARAMETER.error("ELIST_ITERATOR::add_to_end", ABORT, "new_element is nullptr");
783  }
784  if (new_element->next) {
785  STILL_LINKED.error("ELIST_ITERATOR::add_to_end", ABORT, nullptr);
786  }
787 #endif
788 
789  if (this->at_last()) {
790  this->add_after_stay_put(new_element);
791  } else {
792  if (this->at_first()) {
793  this->add_before_stay_put(new_element);
794  list->last = new_element;
795  } else { // Iteratr is elsewhere
796  new_element->next = list->last->next;
797  list->last->next = new_element;
798  list->last = new_element;
799  }
800  }
801 }
802 
803 #define ELISTIZEH(CLASSNAME) \
804  class CLASSNAME##_LIST : public X_LIST<ELIST, ELIST_ITERATOR, CLASSNAME> { \
805  public: \
806  using X_LIST<ELIST, ELIST_ITERATOR, CLASSNAME>::X_LIST; \
807  }; \
808  class CLASSNAME##_IT : public X_ITER<ELIST_ITERATOR, CLASSNAME> { \
809  public: \
810  using X_ITER<ELIST_ITERATOR, CLASSNAME>::X_ITER; \
811  CLASSNAME##_IT(CLASSNAME##_LIST *list) : X_ITER(list) {} \
812  };
813 
814 } // namespace tesseract
815 
816 #endif
LIST last(LIST var_list)
Definition: oldlist.cpp:153
constexpr ERRCODE BAD_PARAMETER("List parameter error")
constexpr ERRCODE STILL_LINKED("Attempting to add an element with non nullptr links, to a list")
constexpr ERRCODE NULL_CURRENT("List current position is nullptr")
constexpr ERRCODE NO_LIST("Iterator not set to a list")
@ ABORT
Definition: errcode.h:31
constexpr ERRCODE NULL_DATA("List would have returned a nullptr data pointer")
ELIST_LINK(const ELIST_LINK &)
Definition: elst.h:95
void operator=(const ELIST_LINK &)
Definition: elst.h:100
int32_t length() const
Definition: elst.h:146
void sort(int comparator(const void *, const void *))
Definition: elst.cpp:87
void shallow_copy(ELIST *from_list)
Definition: elst.h:132
void assign_to_sublist(ELIST_ITERATOR *start_it, ELIST_ITERATOR *end_it)
Definition: elst.cpp:67
void internal_deep_copy(ELIST_LINK *(*copier)(ELIST_LINK *), const ELIST *list)
bool empty() const
Definition: elst.h:124
bool add_sorted(int comparator(const void *, const void *), bool unique, ELIST_LINK *new_link)
Definition: elst.h:176
bool singleton() const
Definition: elst.h:128
void set_to_list(ELIST *list_to_iterate)
Definition: elst.h:298
void add_list_after(ELIST *list_to_add)
Definition: elst.h:517
void add_after_stay_put(ELIST_LINK *new_link)
Definition: elst.h:380
int32_t length() const
Definition: elst.h:282
ELIST_LINK * move_to_first()
Definition: elst.h:649
bool at_last() const
Definition: elst.h:715
void add_before_stay_put(ELIST_LINK *new_link)
Definition: elst.h:472
void add_to_end(ELIST_LINK *new_link)
Definition: elst.h:775
void add_list_before(ELIST *list_to_add)
Definition: elst.h:564
void add_before_then_move(ELIST_LINK *new_link)
Definition: elst.h:429
bool empty() const
Definition: elst.h:256
void add_after_then_move(ELIST_LINK *new_link)
Definition: elst.h:333
bool cycled_list() const
Definition: elst.h:735
void sort(int comparator(const void *, const void *))
Definition: elst.h:752
bool current_extracted() const
Definition: elst.h:265
ELIST_LINK * data()
Definition: elst.h:231
ELIST_LINK * extract()
Definition: elst.h:610
bool at_first() const
Definition: elst.h:695
void error(const char *caller, TessErrorLogCode action, const char *format,...) const __attribute__((format(printf
Definition: errcode.cpp:38
list_rec * next
Definition: oldlist.h:105
#define TESS_API
Definition: export.h:34