tesseract  3.04.01
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
clst.cpp
Go to the documentation of this file.
1 /**********************************************************************
2  * File: clst.c (Formerly clist.c)
3  * Description: CONS cell list handling code which is not in the include file.
4  * Author: Phil Cheatle
5  * Created: Mon Jan 28 08:33:13 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 #include <stdlib.h>
21 #include "clst.h"
22 
23 /***********************************************************************
24  * MEMBER FUNCTIONS OF CLASS: CLIST
25  * ================================
26  **********************************************************************/
27 
28 /***********************************************************************
29  * CLIST::internal_deep_clear
30  *
31  * Used by the "deep_clear" member function of derived list
32  * classes to destroy all the elements on the list.
33  * The calling function passes a "zapper" function which can be called to
34  * delete each data element of the list, regardless of its class. This
35  * technique permits a generic clear function to destroy elements of
36  * different derived types correctly, without requiring virtual functions and
37  * the consequential memory overhead.
38  **********************************************************************/
39 
40 void
41 CLIST::internal_deep_clear ( //destroy all links
42 void (*zapper) (void *)) { //ptr to zapper functn
43  CLIST_LINK *ptr;
44  CLIST_LINK *next;
45 
46  if (!empty ()) {
47  ptr = last->next; //set to first
48  last->next = NULL; //break circle
49  last = NULL; //set list empty
50  while (ptr) {
51  next = ptr->next;
52  zapper (ptr->data);
53  delete(ptr);
54  ptr = next;
55  }
56  }
57 }
58 
59 
60 /***********************************************************************
61  * CLIST::shallow_clear
62  *
63  * Used by the destructor and the "shallow_clear" member function of derived
64  * list classes to destroy the list.
65  * The data elements are NOT destroyed.
66  *
67  **********************************************************************/
68 
69 void CLIST::shallow_clear() { //destroy all links
70  CLIST_LINK *ptr;
71  CLIST_LINK *next;
72 
73  if (!empty ()) {
74  ptr = last->next; //set to first
75  last->next = NULL; //break circle
76  last = NULL; //set list empty
77  while (ptr) {
78  next = ptr->next;
79  delete(ptr);
80  ptr = next;
81  }
82  }
83 }
84 
85 /***********************************************************************
86  * CLIST::assign_to_sublist
87  *
88  * The list is set to a sublist of another list. "This" list must be empty
89  * before this function is invoked. The two iterators passed must refer to
90  * the same list, different from "this" one. The sublist removed is the
91  * inclusive list from start_it's current position to end_it's current
92  * position. If this range passes over the end of the source list then the
93  * source list has its end set to the previous element of start_it. The
94  * extracted sublist is unaffected by the end point of the source list, its
95  * end point is always the end_it position.
96  **********************************************************************/
97 
98 void CLIST::assign_to_sublist( //to this list
99  CLIST_ITERATOR *start_it, //from list start
100  CLIST_ITERATOR *end_it) { //from list end
101  const ERRCODE LIST_NOT_EMPTY =
102  "Destination list must be empty before extracting a sublist";
103 
104  if (!empty ())
105  LIST_NOT_EMPTY.error ("CLIST.assign_to_sublist", ABORT, NULL);
106 
107  last = start_it->extract_sublist (end_it);
108 }
109 
110 
111 /***********************************************************************
112  * CLIST::length
113  *
114  * Return count of elements on list
115  **********************************************************************/
116 
117 inT32 CLIST::length() const { //count elements
118  CLIST_ITERATOR it(const_cast<CLIST*>(this));
119  inT32 count = 0;
120 
121  for (it.mark_cycle_pt(); !it.cycled_list(); it.forward())
122  count++;
123  return count;
124 }
125 
126 
127 /***********************************************************************
128  * CLIST::sort
129  *
130  * Sort elements on list
131  **********************************************************************/
132 
133 void
134 CLIST::sort ( //sort elements
135 int comparator ( //comparison routine
136 const void *, const void *)) {
137  CLIST_ITERATOR it(this);
138  inT32 count;
139  void **base; //ptr array to sort
140  void **current;
141  inT32 i;
142 
143  /* Allocate an array of pointers, one per list element */
144  count = length ();
145  base = (void **) malloc (count * sizeof (void *));
146 
147  /* Extract all elements, putting the pointers in the array */
148  current = base;
149  for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ()) {
150  *current = it.extract ();
151  current++;
152  }
153 
154  /* Sort the pointer array */
155  qsort ((char *) base, count, sizeof (*base), comparator);
156 
157  /* Rebuild the list from the sorted pointers */
158  current = base;
159  for (i = 0; i < count; i++) {
160  it.add_to_end (*current);
161  current++;
162  }
163  free(base);
164 }
165 
166 // Assuming list has been sorted already, insert new_data to
167 // keep the list sorted according to the same comparison function.
168 // Comparison function is the same as used by sort, i.e. uses double
169 // indirection. Time is O(1) to add to beginning or end.
170 // Time is linear to add pre-sorted items to an empty list.
171 // If unique, then don't add duplicate entries.
172 // Returns true if the element was added to the list.
173 bool CLIST::add_sorted(int comparator(const void*, const void*),
174  bool unique, void* new_data) {
175  // Check for adding at the end.
176  if (last == NULL || comparator(&last->data, &new_data) < 0) {
177  CLIST_LINK* new_element = new CLIST_LINK;
178  new_element->data = new_data;
179  if (last == NULL) {
180  new_element->next = new_element;
181  } else {
182  new_element->next = last->next;
183  last->next = new_element;
184  }
185  last = new_element;
186  return true;
187  } else if (!unique || last->data != new_data) {
188  // Need to use an iterator.
189  CLIST_ITERATOR it(this);
190  for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
191  void* data = it.data();
192  if (data == new_data && unique)
193  return false;
194  if (comparator(&data, &new_data) > 0)
195  break;
196  }
197  if (it.cycled_list())
198  it.add_to_end(new_data);
199  else
200  it.add_before_then_move(new_data);
201  return true;
202  }
203  return false;
204 }
205 
206 // Assuming that the minuend and subtrahend are already sorted with
207 // the same comparison function, shallow clears this and then copies
208 // the set difference minuend - subtrahend to this, being the elements
209 // of minuend that do not compare equal to anything in subtrahend.
210 // If unique is true, any duplicates in minuend are also eliminated.
211 void CLIST::set_subtract(int comparator(const void*, const void*),
212  bool unique,
213  CLIST* minuend, CLIST* subtrahend) {
214  shallow_clear();
215  CLIST_ITERATOR m_it(minuend);
216  CLIST_ITERATOR s_it(subtrahend);
217  // Since both lists are sorted, finding the subtras that are not
218  // minus is a case of a parallel iteration.
219  for (m_it.mark_cycle_pt(); !m_it.cycled_list(); m_it.forward()) {
220  void* minu = m_it.data();
221  void* subtra = NULL;
222  if (!s_it.empty()) {
223  subtra = s_it.data();
224  while (!s_it.at_last() &&
225  comparator(&subtra, &minu) < 0) {
226  s_it.forward();
227  subtra = s_it.data();
228  }
229  }
230  if (subtra == NULL || comparator(&subtra, &minu) != 0)
231  add_sorted(comparator, unique, minu);
232  }
233 }
234 
235 
236 /***********************************************************************
237  * MEMBER FUNCTIONS OF CLASS: CLIST_ITERATOR
238  * =========================================
239  **********************************************************************/
240 
241 /***********************************************************************
242  * CLIST_ITERATOR::forward
243  *
244  * Move the iterator to the next element of the list.
245  * REMEMBER: ALL LISTS ARE CIRCULAR.
246  **********************************************************************/
247 
249  #ifndef NDEBUG
250  if (!list)
251  NO_LIST.error ("CLIST_ITERATOR::forward", ABORT, NULL);
252  #endif
253  if (list->empty ())
254  return NULL;
255 
256  if (current) { //not removed so
257  //set previous
258  prev = current;
259  started_cycling = TRUE;
260  // In case next is deleted by another iterator, get next from current.
261  current = current->next;
262  } else {
263  if (ex_current_was_cycle_pt)
264  cycle_pt = next;
265  current = next;
266  }
267  next = current->next;
268 
269  #ifndef NDEBUG
270  if (!current)
271  NULL_DATA.error ("CLIST_ITERATOR::forward", ABORT, NULL);
272  if (!next)
273  NULL_NEXT.error ("CLIST_ITERATOR::forward", ABORT,
274  "This is: %p Current is: %p", this, current);
275  #endif
276  return current->data;
277 }
278 
279 
280 /***********************************************************************
281  * CLIST_ITERATOR::data_relative
282  *
283  * Return the data pointer to the element "offset" elements from current.
284  * "offset" must not be less than -1.
285  * (This function can't be INLINEd because it contains a loop)
286  **********************************************************************/
287 
288 void *CLIST_ITERATOR::data_relative( //get data + or - ...
289  inT8 offset) { //offset from current
290  CLIST_LINK *ptr;
291 
292  #ifndef NDEBUG
293  if (!list)
294  NO_LIST.error ("CLIST_ITERATOR::data_relative", ABORT, NULL);
295  if (list->empty ())
296  EMPTY_LIST.error ("CLIST_ITERATOR::data_relative", ABORT, NULL);
297  if (offset < -1)
298  BAD_PARAMETER.error ("CLIST_ITERATOR::data_relative", ABORT,
299  "offset < -l");
300  #endif
301 
302  if (offset == -1)
303  ptr = prev;
304  else
305  for (ptr = current ? current : prev; offset-- > 0; ptr = ptr->next);
306 
307  #ifndef NDEBUG
308  if (!ptr)
309  NULL_DATA.error ("CLIST_ITERATOR::data_relative", ABORT, NULL);
310  #endif
311 
312  return ptr->data;
313 }
314 
315 
316 /***********************************************************************
317  * CLIST_ITERATOR::move_to_last()
318  *
319  * Move current so that it is set to the end of the list.
320  * Return data just in case anyone wants it.
321  * (This function can't be INLINEd because it contains a loop)
322  **********************************************************************/
323 
325  #ifndef NDEBUG
326  if (!list)
327  NO_LIST.error ("CLIST_ITERATOR::move_to_last", ABORT, NULL);
328  #endif
329 
330  while (current != list->last)
331  forward();
332 
333  if (current == NULL)
334  return NULL;
335  else
336  return current->data;
337 }
338 
339 
340 /***********************************************************************
341  * CLIST_ITERATOR::exchange()
342  *
343  * Given another iterator, whose current element is a different element on
344  * the same list list OR an element of another list, exchange the two current
345  * elements. On return, each iterator points to the element which was the
346  * other iterators current on entry.
347  * (This function hasn't been in-lined because its a bit big!)
348  **********************************************************************/
349 
350 void CLIST_ITERATOR::exchange( //positions of 2 links
351  CLIST_ITERATOR *other_it) { //other iterator
352  const ERRCODE DONT_EXCHANGE_DELETED =
353  "Can't exchange deleted elements of lists";
354 
355  CLIST_LINK *old_current;
356 
357  #ifndef NDEBUG
358  if (!list)
359  NO_LIST.error ("CLIST_ITERATOR::exchange", ABORT, NULL);
360  if (!other_it)
361  BAD_PARAMETER.error ("CLIST_ITERATOR::exchange", ABORT, "other_it NULL");
362  if (!(other_it->list))
363  NO_LIST.error ("CLIST_ITERATOR::exchange", ABORT, "other_it");
364  #endif
365 
366  /* Do nothing if either list is empty or if both iterators reference the same
367  link */
368 
369  if ((list->empty ()) ||
370  (other_it->list->empty ()) || (current == other_it->current))
371  return;
372 
373  /* Error if either current element is deleted */
374 
375  if (!current || !other_it->current)
376  DONT_EXCHANGE_DELETED.error ("CLIST_ITERATOR.exchange", ABORT, NULL);
377 
378  /* Now handle the 4 cases: doubleton list; non-doubleton adjacent elements
379  (other before this); non-doubleton adjacent elements (this before other);
380  non-adjacent elements. */
381 
382  //adjacent links
383  if ((next == other_it->current) ||
384  (other_it->next == current)) {
385  //doubleton list
386  if ((next == other_it->current) &&
387  (other_it->next == current)) {
388  prev = next = current;
389  other_it->prev = other_it->next = other_it->current;
390  }
391  else { //non-doubleton with
392  //adjacent links
393  //other before this
394  if (other_it->next == current) {
395  other_it->prev->next = current;
396  other_it->current->next = next;
397  current->next = other_it->current;
398  other_it->next = other_it->current;
399  prev = current;
400  }
401  else { //this before other
402  prev->next = other_it->current;
403  current->next = other_it->next;
404  other_it->current->next = current;
405  next = current;
406  other_it->prev = other_it->current;
407  }
408  }
409  }
410  else { //no overlap
411  prev->next = other_it->current;
412  current->next = other_it->next;
413  other_it->prev->next = current;
414  other_it->current->next = next;
415  }
416 
417  /* update end of list pointer when necessary (remember that the 2 iterators
418  may iterate over different lists!) */
419 
420  if (list->last == current)
421  list->last = other_it->current;
422  if (other_it->list->last == other_it->current)
423  other_it->list->last = current;
424 
425  if (current == cycle_pt)
426  cycle_pt = other_it->cycle_pt;
427  if (other_it->current == other_it->cycle_pt)
428  other_it->cycle_pt = cycle_pt;
429 
430  /* The actual exchange - in all cases*/
431 
432  old_current = current;
433  current = other_it->current;
434  other_it->current = old_current;
435 }
436 
437 
438 /***********************************************************************
439  * CLIST_ITERATOR::extract_sublist()
440  *
441  * This is a private member, used only by CLIST::assign_to_sublist.
442  * Given another iterator for the same list, extract the links from THIS to
443  * OTHER inclusive, link them into a new circular list, and return a
444  * pointer to the last element.
445  * (Can't inline this function because it contains a loop)
446  **********************************************************************/
447 
448 CLIST_LINK *CLIST_ITERATOR::extract_sublist( //from this current
449  CLIST_ITERATOR *other_it) { //to other current
450  CLIST_ITERATOR temp_it = *this;
451  CLIST_LINK *end_of_new_list;
452 
453  const ERRCODE BAD_SUBLIST = "Can't find sublist end point in original list";
454  #ifndef NDEBUG
455  const ERRCODE BAD_EXTRACTION_PTS =
456  "Can't extract sublist from points on different lists";
457  const ERRCODE DONT_EXTRACT_DELETED =
458  "Can't extract a sublist marked by deleted points";
459 
460  if (!other_it)
461  BAD_PARAMETER.error ("CLIST_ITERATOR::extract_sublist", ABORT,
462  "other_it NULL");
463  if (!list)
464  NO_LIST.error ("CLIST_ITERATOR::extract_sublist", ABORT, NULL);
465  if (list != other_it->list)
466  BAD_EXTRACTION_PTS.error ("CLIST_ITERATOR.extract_sublist", ABORT, NULL);
467  if (list->empty ())
468  EMPTY_LIST.error ("CLIST_ITERATOR::extract_sublist", ABORT, NULL);
469 
470  if (!current || !other_it->current)
471  DONT_EXTRACT_DELETED.error ("CLIST_ITERATOR.extract_sublist", ABORT,
472  NULL);
473  #endif
474 
475  ex_current_was_last = other_it->ex_current_was_last = FALSE;
476  ex_current_was_cycle_pt = FALSE;
477  other_it->ex_current_was_cycle_pt = FALSE;
478 
479  temp_it.mark_cycle_pt ();
480  do { //walk sublist
481  if (temp_it.cycled_list ()) //can't find end pt
482  BAD_SUBLIST.error ("CLIST_ITERATOR.extract_sublist", ABORT, NULL);
483 
484  if (temp_it.at_last ()) {
485  list->last = prev;
486  ex_current_was_last = other_it->ex_current_was_last = TRUE;
487  }
488 
489  if (temp_it.current == cycle_pt)
490  ex_current_was_cycle_pt = TRUE;
491 
492  if (temp_it.current == other_it->cycle_pt)
493  other_it->ex_current_was_cycle_pt = TRUE;
494 
495  temp_it.forward ();
496  }
497  while (temp_it.prev != other_it->current);
498 
499  //circularise sublist
500  other_it->current->next = current;
501  end_of_new_list = other_it->current;
502 
503  //sublist = whole list
504  if (prev == other_it->current) {
505  list->last = NULL;
506  prev = current = next = NULL;
507  other_it->prev = other_it->current = other_it->next = NULL;
508  }
509  else {
510  prev->next = other_it->next;
511  current = other_it->current = NULL;
512  next = other_it->next;
513  other_it->prev = prev;
514  }
515  return end_of_new_list;
516 }
const ERRCODE EMPTY_LIST
Definition: lsterr.h:38
int inT32
Definition: host.h:102
void * extract()
Definition: clst.h:576
BOOL8 empty()
Definition: clst.h:216
void mark_cycle_pt()
Definition: clst.h:641
const ERRCODE NULL_NEXT
Definition: lsterr.h:36
void exchange(CLIST_ITERATOR *other_it)
Definition: clst.cpp:350
SIGNED char inT8
Definition: host.h:98
BOOL8 cycled_list()
Definition: clst.h:702
Definition: clst.h:70
void * move_to_last()
Definition: clst.cpp:324
void assign_to_sublist(CLIST_ITERATOR *start_it, CLIST_ITERATOR *end_it)
Definition: clst.cpp:98
#define FALSE
Definition: capi.h:29
int count(LIST var_list)
Definition: oldlist.cpp:108
void shallow_clear()
Definition: clst.cpp:69
const ERRCODE BAD_PARAMETER
Definition: lsterr.h:39
const ERRCODE NO_LIST
Definition: lsterr.h:32
BOOL8 at_last()
Definition: clst.h:682
void * forward()
Definition: clst.cpp:248
void set_subtract(int comparator(const void *, const void *), bool unique, CLIST *minuend, CLIST *subtrahend)
Definition: clst.cpp:211
void * data_relative(inT8 offset)
Definition: clst.cpp:288
inT32 length() const
Definition: clst.cpp:117
void error(const char *caller, TessErrorLogCode action, const char *format,...) const
Definition: errcode.cpp:40
bool empty() const
Definition: clst.h:95
const ERRCODE NULL_DATA
Definition: lsterr.h:34
Definition: errcode.h:30
#define TRUE
Definition: capi.h:28
void sort(int comparator(const void *, const void *))
Definition: clst.cpp:134
void add_before_then_move(void *new_data)
Definition: clst.h:391
void add_to_end(void *new_data)
Definition: clst.h:761
void internal_deep_clear(void(*zapper)(void *))
Definition: clst.cpp:41
bool add_sorted(int comparator(const void *, const void *), bool unique, void *new_data)
Definition: clst.cpp:173
void * data()
Definition: clst.h:193