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