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