tesseract  3.04.01
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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  * Created: Mon Jan 07 08:35:34 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 ELST_H
21 #define ELST_H
22 
23 #include <stdio.h>
24 #include "host.h"
25 #include "serialis.h"
26 #include "lsterr.h"
27 
28 class ELIST_ITERATOR;
29 
30 /**********************************************************************
31 This module implements list classes and iterators.
32 The following list types and iterators are provided:
33 
34  List type List Class Iterator Class Element Class
35  --------- ---------- -------------- -------------
36 
37  Embedded list ELIST
38  ELIST_ITERATOR
39  ELIST_LINK
40  (Single linked)
41 
42  Embedded list ELIST2
43  ELIST2_ITERATOR
44  ELIST2_LINK
45  (Double linked)
46 
47  Cons List CLIST
48  CLIST_ITERATOR
49  CLIST_LINK
50  (Single linked)
51 
52  Cons List CLIST2
53  CLIST2_ITERATOR
54  CLIST2_LINK
55  (Double linked)
56 
57 An embedded list is where the list pointers are provided by a generic class.
58 Data types to be listed inherit from the generic class. Data is thus linked
59 in only ONE list at any one time.
60 
61 A cons list has a separate structure for a "cons cell". This contains the
62 list pointer(s) AND a pointer to the data structure held on the list. A
63 structure can be on many cons lists at the same time, and the structure does
64 not need to inherit from any generic class in order to be on the list.
65 
66 The implementation of lists is very careful about space and speed overheads.
67 This is why many embedded lists are provided. The same concerns mean that
68 in-line type coercion is done, rather than use virtual functions. This is
69 cumbersome in that each data type to be listed requires its own iterator and
70 list class - though macros can gererate these. It also prevents heterogeneous
71 lists.
72 **********************************************************************/
73 
74 /**********************************************************************
75  * CLASS - ELIST_LINK
76  *
77  * Generic link class for singly linked lists with embedded links
78  *
79  * Note: No destructor - elements are assumed to be destroyed EITHER after
80  * they have been extracted from a list OR by the ELIST destructor which
81  * walks the list.
82  **********************************************************************/
83 
85 {
86  friend class ELIST_ITERATOR;
87  friend class ELIST;
88 
89  ELIST_LINK *next;
90 
91  public:
93  next = NULL;
94  }
95  //constructor
96 
97  ELIST_LINK(const ELIST_LINK &) { // don't copy link.
98  next = NULL;
99  }
100 
101  void operator= ( //don't copy links
102  const ELIST_LINK &) {
103  next = NULL;
104  }
105 };
106 
107 /**********************************************************************
108  * CLASS - ELIST
109  *
110  * Generic list class for singly linked lists with embedded links
111  **********************************************************************/
112 
114 {
115  friend class ELIST_ITERATOR;
116 
117  ELIST_LINK *last; //End of list
118  //(Points to head)
119  ELIST_LINK *First() { // return first
120  return last ? last->next : NULL;
121  }
122 
123  public:
124  ELIST() { //constructor
125  last = NULL;
126  }
127 
128  void internal_clear ( //destroy all links
129  //ptr to zapper functn
130  void (*zapper) (ELIST_LINK *));
131 
132  bool empty() const { //is list empty?
133  return !last;
134  }
135 
136  bool singleton() const {
137  return last ? (last == last->next) : false;
138  }
139 
140  void shallow_copy( //dangerous!!
141  ELIST *from_list) { //beware destructors!!
142  last = from_list->last;
143  }
144 
145  //ptr to copier functn
146  void internal_deep_copy (ELIST_LINK * (*copier) (ELIST_LINK *),
147  const ELIST * list); //list being copied
148 
149  void assign_to_sublist( //to this list
150  ELIST_ITERATOR *start_it, //from list start
151  ELIST_ITERATOR *end_it); //from list end
152 
153  inT32 length() const; // # elements in list
154 
155  void sort ( //sort elements
156  int comparator ( //comparison routine
157  const void *, const void *));
158 
159  // Assuming list has been sorted already, insert new_link to
160  // keep the list sorted according to the same comparison function.
161  // Comparison function is the same as used by sort, i.e. uses double
162  // indirection. Time is O(1) to add to beginning or end.
163  // Time is linear to add pre-sorted items to an empty list.
164  // If unique is set to true and comparator() returns 0 (an entry with the
165  // same information as the one contained in new_link is already in the
166  // list) - new_link is not added to the list and the function returns the
167  // pointer to the identical entry that already exists in the list
168  // (otherwise the function returns new_link).
169  ELIST_LINK *add_sorted_and_find(int comparator(const void*, const void*),
170  bool unique, ELIST_LINK* new_link);
171 
172  // Same as above, but returns true if the new entry was inserted, false
173  // if the identical entry already existed in the list.
174  bool add_sorted(int comparator(const void*, const void*),
175  bool unique, ELIST_LINK* new_link) {
176  return (add_sorted_and_find(comparator, unique, new_link) == new_link);
177  }
178 
179 };
180 
181 /***********************************************************************
182  * CLASS - ELIST_ITERATOR
183  *
184  * Generic iterator class for singly linked lists with embedded links
185  **********************************************************************/
186 
188 {
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  bool ex_current_was_last; //current extracted
196  //was end of list
197  bool ex_current_was_cycle_pt; //current extracted
198  //was cycle point
199  ELIST_LINK *cycle_pt; //point we are cycling
200  //the list to.
201  bool started_cycling; //Have we moved off
202  //the start?
203 
204  ELIST_LINK *extract_sublist( //from this current...
205  ELIST_ITERATOR *other_it); //to other current
206 
207  public:
208  ELIST_ITERATOR() { //constructor
209  list = NULL;
210  } //unassigned list
211 
212  explicit ELIST_ITERATOR(ELIST *list_to_iterate);
213 
214  void set_to_list( //change list
215  ELIST *list_to_iterate);
216 
217  void add_after_then_move( //add after current &
218  ELIST_LINK *new_link); //move to new
219 
220  void add_after_stay_put( //add after current &
221  ELIST_LINK *new_link); //stay at current
222 
223  void add_before_then_move( //add before current &
224  ELIST_LINK *new_link); //move to new
225 
226  void add_before_stay_put( //add before current &
227  ELIST_LINK *new_link); //stay at current
228 
229  void add_list_after( //add a list &
230  ELIST *list_to_add); //stay at current
231 
232  void add_list_before( //add a list &
233  ELIST *list_to_add); //move to it 1st item
234 
235  ELIST_LINK *data() { //get current data
236  #ifndef NDEBUG
237  if (!list)
238  NO_LIST.error ("ELIST_ITERATOR::data", ABORT, NULL);
239  if (!current)
240  NULL_DATA.error ("ELIST_ITERATOR::data", ABORT, NULL);
241  #endif
242  return current;
243  }
244 
245  ELIST_LINK *data_relative( //get data + or - ...
246  inT8 offset); //offset from current
247 
248  ELIST_LINK *forward(); //move to next element
249 
250  ELIST_LINK *extract(); //remove from list
251 
252  ELIST_LINK *move_to_first(); //go to start of list
253 
254  ELIST_LINK *move_to_last(); //go to end of list
255 
256  void mark_cycle_pt(); //remember current
257 
258  bool empty() { //is list empty?
259  #ifndef NDEBUG
260  if (!list)
261  NO_LIST.error ("ELIST_ITERATOR::empty", ABORT, NULL);
262  #endif
263  return list->empty ();
264  }
265 
266  bool current_extracted() { //current extracted?
267  return !current;
268  }
269 
270  bool at_first(); //Current is first?
271 
272  bool at_last(); //Current is last?
273 
274  bool cycled_list(); //Completed a cycle?
275 
276  void add_to_end( //add at end &
277  ELIST_LINK *new_link); //don't move
278 
279  void exchange( //positions of 2 links
280  ELIST_ITERATOR *other_it); //other iterator
281 
282  inT32 length(); //# elements in list
283 
284  void sort ( //sort elements
285  int comparator ( //comparison routine
286  const void *, const void *));
287 
288 };
289 
290 /***********************************************************************
291  * ELIST_ITERATOR::set_to_list
292  *
293  * (Re-)initialise the iterator to point to the start of the list_to_iterate
294  * over.
295  **********************************************************************/
296 
297 inline void ELIST_ITERATOR::set_to_list( //change list
298  ELIST *list_to_iterate) {
299  #ifndef NDEBUG
300  if (!list_to_iterate)
301  BAD_PARAMETER.error ("ELIST_ITERATOR::set_to_list", ABORT,
302  "list_to_iterate is NULL");
303  #endif
304 
305  list = list_to_iterate;
306  prev = list->last;
307  current = list->First ();
308  next = current ? current->next : NULL;
309  cycle_pt = NULL; //await explicit set
310  started_cycling = FALSE;
311  ex_current_was_last = FALSE;
312  ex_current_was_cycle_pt = FALSE;
313 }
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 /***********************************************************************
328  * ELIST_ITERATOR::add_after_then_move
329  *
330  * Add a new element to the list after the current element and move the
331  * iterator to the new element.
332  **********************************************************************/
333 
334 inline void ELIST_ITERATOR::add_after_then_move( // element to add
335  ELIST_LINK *new_element) {
336  #ifndef NDEBUG
337  if (!list)
338  NO_LIST.error ("ELIST_ITERATOR::add_after_then_move", ABORT, NULL);
339  if (!new_element)
340  BAD_PARAMETER.error ("ELIST_ITERATOR::add_after_then_move", ABORT,
341  "new_element is NULL");
342  if (new_element->next)
343  STILL_LINKED.error ("ELIST_ITERATOR::add_after_then_move", ABORT, NULL);
344  #endif
345 
346  if (list->empty ()) {
347  new_element->next = new_element;
348  list->last = new_element;
349  prev = next = new_element;
350  }
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  if (ex_current_was_cycle_pt)
365  cycle_pt = new_element;
366  }
367  }
368  current = new_element;
369 }
370 
371 
372 /***********************************************************************
373  * ELIST_ITERATOR::add_after_stay_put
374  *
375  * Add a new element to the list after the current element but do not move
376  * the iterator to the new element.
377  **********************************************************************/
378 
379 inline void ELIST_ITERATOR::add_after_stay_put( // element to add
380  ELIST_LINK *new_element) {
381  #ifndef NDEBUG
382  if (!list)
383  NO_LIST.error ("ELIST_ITERATOR::add_after_stay_put", ABORT, NULL);
384  if (!new_element)
385  BAD_PARAMETER.error ("ELIST_ITERATOR::add_after_stay_put", ABORT,
386  "new_element is NULL");
387  if (new_element->next)
388  STILL_LINKED.error ("ELIST_ITERATOR::add_after_stay_put", ABORT, NULL);
389  #endif
390 
391  if (list->empty ()) {
392  new_element->next = new_element;
393  list->last = new_element;
394  prev = next = new_element;
395  ex_current_was_last = FALSE;
396  current = NULL;
397  }
398  else {
399  new_element->next = next;
400 
401  if (current) { //not extracted
402  current->next = new_element;
403  if (prev == current)
404  prev = new_element;
405  if (current == list->last)
406  list->last = new_element;
407  }
408  else { //current extracted
409  prev->next = new_element;
410  if (ex_current_was_last) {
411  list->last = new_element;
412  ex_current_was_last = FALSE;
413  }
414  }
415  next = new_element;
416  }
417 }
418 
419 
420 /***********************************************************************
421  * ELIST_ITERATOR::add_before_then_move
422  *
423  * Add a new element to the list before the current element and move the
424  * iterator to the new element.
425  **********************************************************************/
426 
427 inline void ELIST_ITERATOR::add_before_then_move( // element to add
428  ELIST_LINK *new_element) {
429  #ifndef NDEBUG
430  if (!list)
431  NO_LIST.error ("ELIST_ITERATOR::add_before_then_move", ABORT, NULL);
432  if (!new_element)
433  BAD_PARAMETER.error ("ELIST_ITERATOR::add_before_then_move", ABORT,
434  "new_element is NULL");
435  if (new_element->next)
436  STILL_LINKED.error ("ELIST_ITERATOR::add_before_then_move", ABORT, NULL);
437  #endif
438 
439  if (list->empty ()) {
440  new_element->next = new_element;
441  list->last = new_element;
442  prev = next = new_element;
443  }
444  else {
445  prev->next = new_element;
446  if (current) { //not extracted
447  new_element->next = current;
448  next = current;
449  }
450  else { //current extracted
451  new_element->next = next;
452  if (ex_current_was_last)
453  list->last = new_element;
454  if (ex_current_was_cycle_pt)
455  cycle_pt = new_element;
456  }
457  }
458  current = new_element;
459 }
460 
461 
462 /***********************************************************************
463  * ELIST_ITERATOR::add_before_stay_put
464  *
465  * Add a new element to the list before the current element but don't move the
466  * iterator to the new element.
467  **********************************************************************/
468 
469 inline void ELIST_ITERATOR::add_before_stay_put( // element to add
470  ELIST_LINK *new_element) {
471  #ifndef NDEBUG
472  if (!list)
473  NO_LIST.error ("ELIST_ITERATOR::add_before_stay_put", ABORT, NULL);
474  if (!new_element)
475  BAD_PARAMETER.error ("ELIST_ITERATOR::add_before_stay_put", ABORT,
476  "new_element is NULL");
477  if (new_element->next)
478  STILL_LINKED.error ("ELIST_ITERATOR::add_before_stay_put", ABORT, NULL);
479  #endif
480 
481  if (list->empty ()) {
482  new_element->next = new_element;
483  list->last = new_element;
484  prev = next = new_element;
485  ex_current_was_last = TRUE;
486  current = NULL;
487  }
488  else {
489  prev->next = new_element;
490  if (current) { //not extracted
491  new_element->next = current;
492  if (next == current)
493  next = new_element;
494  }
495  else { //current extracted
496  new_element->next = next;
497  if (ex_current_was_last)
498  list->last = new_element;
499  }
500  prev = new_element;
501  }
502 }
503 
504 
505 /***********************************************************************
506  * ELIST_ITERATOR::add_list_after
507  *
508  * Insert another list to this list after the current element but don't move the
509  * iterator.
510  **********************************************************************/
511 
512 inline void ELIST_ITERATOR::add_list_after(ELIST *list_to_add) {
513  #ifndef NDEBUG
514  if (!list)
515  NO_LIST.error ("ELIST_ITERATOR::add_list_after", ABORT, NULL);
516  if (!list_to_add)
517  BAD_PARAMETER.error ("ELIST_ITERATOR::add_list_after", ABORT,
518  "list_to_add is NULL");
519  #endif
520 
521  if (!list_to_add->empty ()) {
522  if (list->empty ()) {
523  list->last = list_to_add->last;
524  prev = list->last;
525  next = list->First ();
526  ex_current_was_last = TRUE;
527  current = NULL;
528  }
529  else {
530  if (current) { //not extracted
531  current->next = list_to_add->First ();
532  if (current == list->last)
533  list->last = list_to_add->last;
534  list_to_add->last->next = next;
535  next = current->next;
536  }
537  else { //current extracted
538  prev->next = list_to_add->First ();
539  if (ex_current_was_last) {
540  list->last = list_to_add->last;
541  ex_current_was_last = FALSE;
542  }
543  list_to_add->last->next = next;
544  next = prev->next;
545  }
546  }
547  list_to_add->last = NULL;
548  }
549 }
550 
551 
552 /***********************************************************************
553  * ELIST_ITERATOR::add_list_before
554  *
555  * Insert another list to this list before the current element. Move the
556  * iterator to the start of the inserted elements
557  * iterator.
558  **********************************************************************/
559 
560 inline void ELIST_ITERATOR::add_list_before(ELIST *list_to_add) {
561  #ifndef NDEBUG
562  if (!list)
563  NO_LIST.error ("ELIST_ITERATOR::add_list_before", ABORT, NULL);
564  if (!list_to_add)
565  BAD_PARAMETER.error ("ELIST_ITERATOR::add_list_before", ABORT,
566  "list_to_add is NULL");
567  #endif
568 
569  if (!list_to_add->empty ()) {
570  if (list->empty ()) {
571  list->last = list_to_add->last;
572  prev = list->last;
573  current = list->First ();
574  next = current->next;
575  ex_current_was_last = FALSE;
576  }
577  else {
578  prev->next = list_to_add->First ();
579  if (current) { //not extracted
580  list_to_add->last->next = current;
581  }
582  else { //current extracted
583  list_to_add->last->next = next;
584  if (ex_current_was_last)
585  list->last = list_to_add->last;
586  if (ex_current_was_cycle_pt)
587  cycle_pt = prev->next;
588  }
589  current = prev->next;
590  next = current->next;
591  }
592  list_to_add->last = NULL;
593  }
594 }
595 
596 
597 /***********************************************************************
598  * ELIST_ITERATOR::extract
599  *
600  * Do extraction by removing current from the list, returning it to the
601  * caller, but NOT updating the iterator. (So that any calling loop can do
602  * this.) The iterator's current points to NULL. If the extracted element
603  * is to be deleted, this is the callers responsibility.
604  **********************************************************************/
605 
607  ELIST_LINK *extracted_link;
608 
609  #ifndef NDEBUG
610  if (!list)
611  NO_LIST.error ("ELIST_ITERATOR::extract", ABORT, NULL);
612  if (!current) //list empty or
613  //element extracted
614  NULL_CURRENT.error ("ELIST_ITERATOR::extract",
615  ABORT, NULL);
616  #endif
617 
618  if (list->singleton()) {
619  // Special case where we do need to change the iterator.
620  prev = next = list->last = NULL;
621  } else {
622  prev->next = next; //remove from list
623 
624  if (current == list->last) {
625  list->last = prev;
626  ex_current_was_last = TRUE;
627  } else {
628  ex_current_was_last = FALSE;
629  }
630  }
631  // Always set ex_current_was_cycle_pt so an add/forward will work in a loop.
632  ex_current_was_cycle_pt = (current == cycle_pt) ? TRUE : FALSE;
633  extracted_link = current;
634  extracted_link->next = NULL; //for safety
635  current = NULL;
636  return extracted_link;
637 }
638 
639 
640 /***********************************************************************
641  * ELIST_ITERATOR::move_to_first()
642  *
643  * Move current so that it is set to the start of the list.
644  * Return data just in case anyone wants it.
645  **********************************************************************/
646 
648  #ifndef NDEBUG
649  if (!list)
650  NO_LIST.error ("ELIST_ITERATOR::move_to_first", ABORT, NULL);
651  #endif
652 
653  current = list->First ();
654  prev = list->last;
655  next = current ? current->next : NULL;
656  return current;
657 }
658 
659 
660 /***********************************************************************
661  * ELIST_ITERATOR::mark_cycle_pt()
662  *
663  * Remember the current location so that we can tell whether we've returned
664  * to this point later.
665  *
666  * If the current point is deleted either now, or in the future, the cycle
667  * point will be set to the next item which is set to current. This could be
668  * by a forward, add_after_then_move or add_after_then_move.
669  **********************************************************************/
670 
672  #ifndef NDEBUG
673  if (!list)
674  NO_LIST.error ("ELIST_ITERATOR::mark_cycle_pt", ABORT, NULL);
675  #endif
676 
677  if (current)
678  cycle_pt = current;
679  else
680  ex_current_was_cycle_pt = TRUE;
681  started_cycling = FALSE;
682 }
683 
684 
685 /***********************************************************************
686  * ELIST_ITERATOR::at_first()
687  *
688  * Are we at the start of the list?
689  *
690  **********************************************************************/
691 
693  #ifndef NDEBUG
694  if (!list)
695  NO_LIST.error ("ELIST_ITERATOR::at_first", ABORT, NULL);
696  #endif
697 
698  //we're at a deleted
699  return ((list->empty ()) || (current == list->First ()) || ((current == NULL) &&
700  (prev == list->last) && //NON-last pt between
701  !ex_current_was_last)); //first and last
702 }
703 
704 
705 /***********************************************************************
706  * ELIST_ITERATOR::at_last()
707  *
708  * Are we at the end of the list?
709  *
710  **********************************************************************/
711 
712 inline bool ELIST_ITERATOR::at_last() {
713  #ifndef NDEBUG
714  if (!list)
715  NO_LIST.error ("ELIST_ITERATOR::at_last", ABORT, NULL);
716  #endif
717 
718  //we're at a deleted
719  return ((list->empty ()) || (current == list->last) || ((current == NULL) &&
720  (prev == list->last) && //last point between
721  ex_current_was_last)); //first and last
722 }
723 
724 
725 /***********************************************************************
726  * ELIST_ITERATOR::cycled_list()
727  *
728  * Have we returned to the cycle_pt since it was set?
729  *
730  **********************************************************************/
731 
733  #ifndef NDEBUG
734  if (!list)
735  NO_LIST.error ("ELIST_ITERATOR::cycled_list", ABORT, NULL);
736  #endif
737 
738  return ((list->empty ()) || ((current == cycle_pt) && started_cycling));
739 
740 }
741 
742 
743 /***********************************************************************
744  * ELIST_ITERATOR::length()
745  *
746  * Return the length of the list
747  *
748  **********************************************************************/
749 
751  #ifndef NDEBUG
752  if (!list)
753  NO_LIST.error ("ELIST_ITERATOR::length", ABORT, NULL);
754  #endif
755 
756  return list->length ();
757 }
758 
759 
760 /***********************************************************************
761  * ELIST_ITERATOR::sort()
762  *
763  * Sort the elements of the list, then reposition at the start.
764  *
765  **********************************************************************/
766 
767 inline void
768 ELIST_ITERATOR::sort ( //sort elements
769 int comparator ( //comparison routine
770 const void *, const void *)) {
771  #ifndef NDEBUG
772  if (!list)
773  NO_LIST.error ("ELIST_ITERATOR::sort", ABORT, NULL);
774  #endif
775 
776  list->sort (comparator);
777  move_to_first();
778 }
779 
780 
781 /***********************************************************************
782  * ELIST_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 ELIST_ITERATOR::add_to_end( // element to add
792  ELIST_LINK *new_element) {
793  #ifndef NDEBUG
794  if (!list)
795  NO_LIST.error ("ELIST_ITERATOR::add_to_end", ABORT, NULL);
796  if (!new_element)
797  BAD_PARAMETER.error ("ELIST_ITERATOR::add_to_end", ABORT,
798  "new_element is NULL");
799  if (new_element->next)
800  STILL_LINKED.error ("ELIST_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  list->last->next = new_element;
814  list->last = new_element;
815  }
816  }
817 }
818 
819 
820 /***********************************************************************
821  ******************** MACROS **************************************
822  ***********************************************************************/
823 
824 /***********************************************************************
825  QUOTE_IT MACRO DEFINITION
826  ===========================
827 Replace <parm> with "<parm>". <parm> may be an arbitrary number of tokens
828 ***********************************************************************/
829 
830 #define QUOTE_IT( parm ) #parm
831 
832 /***********************************************************************
833  ELISTIZE( CLASSNAME ) MACRO
834  ============================
835 
836 CLASSNAME is assumed to be the name of a class which has a baseclass of
837 ELIST_LINK.
838 
839 NOTE: Because we don't use virtual functions in the list code, the list code
840 will NOT work correctly for classes derived from this.
841 
842 The macros generate:
843  - An element deletion function: CLASSNAME##_zapper
844  - An E_LIST subclass: CLASSNAME##_LIST
845  - An E_LIST_ITERATOR subclass: CLASSNAME##_IT
846 
847 NOTE: Generated names are DELIBERATELY designed to clash with those for
848 ELIST2IZE but NOT with those for CLISTIZE and CLIST2IZE
849 
850 Two macros are provided: ELISTIZE and ELISTIZEH.
851 The ...IZEH macros just define the class names for use in .h files
852 The ...IZE macros define the code use in .c files
853 ***********************************************************************/
854 
855 /***********************************************************************
856  ELISTIZEH( CLASSNAME ) MACRO
857 
858 ELISTIZEH is a concatenation of 3 fragments ELISTIZEH_A, ELISTIZEH_B and
859 ELISTIZEH_C.
860 ***********************************************************************/
861 
862 #define ELISTIZEH_A(CLASSNAME) \
863  \
864 extern DLLSYM void CLASSNAME##_zapper(ELIST_LINK* link);
865 
866 #define ELISTIZEH_B(CLASSNAME) \
867  \
868 /*********************************************************************** \
869 * CLASS - CLASSNAME##_LIST \
870 * \
871 * List class for class CLASSNAME \
872 * \
873 **********************************************************************/ \
874  \
875 class DLLSYM CLASSNAME##_LIST : public ELIST { \
876  public: \
877  CLASSNAME##_LIST():ELIST() {} \
878  \
879  void clear() { /* delete elements */\
880  ELIST::internal_clear(&CLASSNAME##_zapper); \
881  } \
882  \
883  ~CLASSNAME##_LIST() { \
884  clear(); \
885  } \
886  \
887  /* Become a deep copy of src_list*/ \
888  void deep_copy(const CLASSNAME##_LIST* src_list, \
889  CLASSNAME* (*copier)(const CLASSNAME*)); \
890  \
891 private: \
892  /* Prevent assign and copy construction. */ \
893  CLASSNAME##_LIST(const CLASSNAME##_LIST&) { \
894  DONT_CONSTRUCT_LIST_BY_COPY.error(QUOTE_IT(CLASSNAME##_LIST), ABORT, NULL);\
895  } \
896  void operator=(const CLASSNAME##_LIST&) { \
897  DONT_ASSIGN_LISTS.error(QUOTE_IT(CLASSNAME##_LIST), ABORT, NULL ); \
898  } \
899 
900 #define ELISTIZEH_C( CLASSNAME ) \
901 }; \
902  \
903  \
904  \
905 /*********************************************************************** \
906 * CLASS - CLASSNAME##_IT \
907 * \
908 * Iterator class for class CLASSNAME##_LIST \
909 * \
910 * Note: We don't need to coerce pointers to member functions input \
911 * parameters as these are automatically converted to the type of the base \
912 * type. ("A ptr to a class may be converted to a pointer to a public base \
913 * class of that class") \
914 **********************************************************************/ \
915  \
916 class DLLSYM CLASSNAME##_IT : public ELIST_ITERATOR { \
917  public: \
918  CLASSNAME##_IT():ELIST_ITERATOR(){} \
919  \
920  /* TODO(rays) This constructor should be explicit, but that means changing \
921  hundreds of incorrect initializations of iterators that use = over () */ \
922  CLASSNAME##_IT(CLASSNAME##_LIST* list) : ELIST_ITERATOR(list) {} \
923  \
924  CLASSNAME* data() { \
925  return reinterpret_cast<CLASSNAME*>(ELIST_ITERATOR::data()); \
926  } \
927  \
928  CLASSNAME* data_relative(inT8 offset) { \
929  return reinterpret_cast<CLASSNAME*>(ELIST_ITERATOR::data_relative(offset));\
930  } \
931  \
932  CLASSNAME* forward() { \
933  return reinterpret_cast<CLASSNAME*>(ELIST_ITERATOR::forward()); \
934  } \
935  \
936  CLASSNAME* extract() { \
937  return reinterpret_cast<CLASSNAME*>(ELIST_ITERATOR::extract()); \
938  } \
939  \
940  CLASSNAME* move_to_first() { \
941  return reinterpret_cast<CLASSNAME*>(ELIST_ITERATOR::move_to_first()); \
942  } \
943  \
944  CLASSNAME* move_to_last() { \
945  return reinterpret_cast<CLASSNAME*>(ELIST_ITERATOR::move_to_last()); \
946  } \
947 };
948 
949 #define ELISTIZEH( CLASSNAME ) \
950  \
951 ELISTIZEH_A( CLASSNAME ) \
952  \
953 ELISTIZEH_B( CLASSNAME ) \
954  \
955 ELISTIZEH_C( CLASSNAME )
956 
957 
958 /***********************************************************************
959  ELISTIZE( CLASSNAME ) MACRO
960 ***********************************************************************/
961 
962 #define ELISTIZE(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(ELIST_LINK* link) { \
974  delete reinterpret_cast<CLASSNAME*>(link); \
975 } \
976  \
977 /* Become a deep copy of src_list*/ \
978 void CLASSNAME##_LIST::deep_copy(const CLASSNAME##_LIST* src_list, \
979  CLASSNAME* (*copier)(const CLASSNAME*)) { \
980  \
981  CLASSNAME##_IT from_it(const_cast<CLASSNAME##_LIST*>(src_list)); \
982  CLASSNAME##_IT to_it(this); \
983  \
984  for (from_it.mark_cycle_pt(); !from_it.cycled_list(); from_it.forward()) \
985  to_it.add_after_then_move((*copier)(from_it.data())); \
986 }
987 
988 #endif
int inT32
Definition: host.h:102
ELIST_LINK * move_to_first()
Definition: elst.h:647
void set_to_list(ELIST *list_to_iterate)
Definition: elst.h:297
void add_to_end(ELIST_LINK *new_link)
Definition: elst.h:791
bool cycled_list()
Definition: elst.h:732
SIGNED char inT8
Definition: host.h:98
ELIST_LINK()
Definition: elst.h:92
void sort(int comparator(const void *, const void *))
Definition: elst.cpp:110
#define FALSE
Definition: capi.h:29
bool singleton() const
Definition: elst.h:136
const ERRCODE BAD_PARAMETER
Definition: lsterr.h:39
ELIST_ITERATOR()
Definition: elst.h:208
const ERRCODE NO_LIST
Definition: lsterr.h:32
bool empty() const
Definition: elst.h:132
inT32 length() const
Definition: elst.cpp:91
const ERRCODE STILL_LINKED
Definition: lsterr.h:40
void mark_cycle_pt()
Definition: elst.h:671
void add_list_before(ELIST *list_to_add)
Definition: elst.h:560
void add_after_stay_put(ELIST_LINK *new_link)
Definition: elst.h:379
void add_after_then_move(ELIST_LINK *new_link)
Definition: elst.h:334
ELIST()
Definition: elst.h:124
void add_before_then_move(ELIST_LINK *new_link)
Definition: elst.h:427
void error(const char *caller, TessErrorLogCode action, const char *format,...) const
Definition: errcode.cpp:40
bool empty()
Definition: elst.h:258
struct list_rec * next
Definition: oldlist.h:130
ELIST_LINK * data()
Definition: elst.h:235
inT32 length()
Definition: elst.h:750
ELIST_LINK * extract()
Definition: elst.h:606
const ERRCODE NULL_DATA
Definition: lsterr.h:34
bool current_extracted()
Definition: elst.h:266
void sort(int comparator(const void *, const void *))
Definition: elst.h:768
Definition: errcode.h:30
#define TRUE
Definition: capi.h:28
void add_list_after(ELIST *list_to_add)
Definition: elst.h:512
Definition: elst.h:113
void shallow_copy(ELIST *from_list)
Definition: elst.h:140
#define DLLSYM
Definition: platform.h:25
const ERRCODE NULL_CURRENT
Definition: lsterr.h:35
bool at_first()
Definition: elst.h:692
bool add_sorted(int comparator(const void *, const void *), bool unique, ELIST_LINK *new_link)
Definition: elst.h:174
LIST last(LIST var_list)
Definition: oldlist.cpp:277
ELIST_LINK(const ELIST_LINK &)
Definition: elst.h:97
bool at_last()
Definition: elst.h:712
void assign_to_sublist(ELIST_ITERATOR *start_it, ELIST_ITERATOR *end_it)
Definition: elst.cpp:72
void add_before_stay_put(ELIST_LINK *new_link)
Definition: elst.h:469