tesseract v5.3.3.20231005
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
28namespace tesseract {
29
30class ELIST_ITERATOR;
31
32/**********************************************************************
33This module implements list classes and iterators.
34The 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
54An embedded list is where the list pointers are provided by a generic class.
55Data types to be listed inherit from the generic class. Data is thus linked
56in only ONE list at any one time.
57
58A cons list has a separate structure for a "cons cell". This contains the
59list pointer(s) AND a pointer to the data structure held on the list. A
60structure can be on many cons lists at the same time, and the structure does
61not need to inherit from any generic class in order to be on the list.
62
63The implementation of lists is very careful about space and speed overheads.
64This is why many embedded lists are provided. The same concerns mean that
65in-line type coercion is done, rather than use virtual functions. This is
66cumbersome in that each data type to be listed requires its own iterator and
67list class - though macros can generate these. It also prevents heterogeneous
68lists.
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
83 friend class ELIST_ITERATOR;
84 friend class ELIST;
85
87
88public:
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
120public:
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
203public:
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);
235 }
236 if (!current) {
237 NULL_DATA.error("ELIST_ITERATOR::data", ABORT);
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);
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
298inline 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
322inline 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
333inline 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);
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);
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
380inline 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);
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);
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
429inline 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);
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);
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
472inline 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);
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);
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
517inline 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);
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
564inline 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);
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);
616 }
617 if (!current) { // list empty or
618 // element extracted
619 NULL_CURRENT.error("ELIST_ITERATOR::extract", ABORT);
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);
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);
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
695inline bool ELIST_ITERATOR::at_first() const {
696#ifndef NDEBUG
697 if (!list) {
698 NO_LIST.error("ELIST_ITERATOR::at_first", ABORT);
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
715inline bool ELIST_ITERATOR::at_last() const {
716#ifndef NDEBUG
717 if (!list) {
718 NO_LIST.error("ELIST_ITERATOR::at_last", ABORT);
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
735inline bool ELIST_ITERATOR::cycled_list() const {
736#ifndef NDEBUG
737 if (!list) {
738 NO_LIST.error("ELIST_ITERATOR::cycled_list", ABORT);
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
752inline 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);
758 }
759#endif
760
761 list->sort(comparator);
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
775inline 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);
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);
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 using X_LIST<ELIST, ELIST_ITERATOR, CLASSNAME>::X_LIST; \
806 }; \
807 class CLASSNAME##_IT : public X_ITER<ELIST_ITERATOR, CLASSNAME> { \
808 using X_ITER<ELIST_ITERATOR, CLASSNAME>::X_ITER; \
809 };
810
811} // namespace tesseract
812
813#endif
int * count
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")
def next(obj)
Definition: ast.py:56
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
ELIST_LINK * data()
Definition: elst.h:231
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 * 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(gnu_printf
Definition: errcode.cpp:40
list_rec * next
Definition: oldlist.h:105
#define TESS_API
Definition: export.h:32