diff --git a/src/ccmain/paramsd.h b/src/ccmain/paramsd.h index 5e2a57e4..e1a87b93 100644 --- a/src/ccmain/paramsd.h +++ b/src/ccmain/paramsd.h @@ -44,7 +44,7 @@ enum ParamType { VT_INTEGER, VT_BOOLEAN, VT_STRING, VT_DOUBLE }; // comparisond or getting its value. It is used in the context of the // ParamsEditor as a bridge from the internal tesseract parameters to the // ones displayed by the ScrollView server. -class ParamContent : public ELIST_LINK { +class ParamContent : public ELIST::LINK { public: // Compare two VC objects by their name. static int Compare(const void *v1, const void *v2); diff --git a/src/ccstruct/blobbox.h b/src/ccstruct/blobbox.h index 03e73ec9..5d8c1edc 100644 --- a/src/ccstruct/blobbox.h +++ b/src/ccstruct/blobbox.h @@ -138,7 +138,7 @@ class ColPartition; class BLOBNBOX; ELISTIZEH(BLOBNBOX) -class BLOBNBOX : public ELIST_LINK { +class BLOBNBOX : public ELIST::LINK { public: BLOBNBOX() { ReInit(); @@ -695,7 +695,7 @@ private: }; ELIST2IZEH(TO_ROW) -class TESS_API TO_BLOCK : public ELIST_LINK { +class TESS_API TO_BLOCK : public ELIST::LINK { public: TO_BLOCK() : pitch_decision(PITCH_DUNNO) { clear(); diff --git a/src/ccstruct/coutln.h b/src/ccstruct/coutln.h index 3aa25519..fd08fd6d 100644 --- a/src/ccstruct/coutln.h +++ b/src/ccstruct/coutln.h @@ -72,7 +72,7 @@ struct EdgeOffset { class C_OUTLINE; // forward declaration ELISTIZEH(C_OUTLINE) -class C_OUTLINE : public ELIST_LINK { +class C_OUTLINE : public ELIST::LINK { public: C_OUTLINE() { stepcount = 0; diff --git a/src/ccstruct/ocrblock.cpp b/src/ccstruct/ocrblock.cpp index 1b222f6e..9127a859 100644 --- a/src/ccstruct/ocrblock.cpp +++ b/src/ccstruct/ocrblock.cpp @@ -222,7 +222,7 @@ void BLOCK::print( // print list of sides BLOCK &BLOCK::operator=( // assignment const BLOCK &source // from this ) { - this->ELIST_LINK::operator=(source); + this->ELIST::LINK::operator=(source); pdblk = source.pdblk; proportional = source.proportional; kerning = source.kerning; diff --git a/src/ccstruct/ocrblock.h b/src/ccstruct/ocrblock.h index 88753b4b..38a830d7 100644 --- a/src/ccstruct/ocrblock.h +++ b/src/ccstruct/ocrblock.h @@ -29,7 +29,7 @@ class BLOCK; // forward decl ELISTIZEH(BLOCK) -class TESS_API BLOCK : public ELIST_LINK +class TESS_API BLOCK : public ELIST::LINK // page block { friend class BLOCK_RECT_IT; // block iterator diff --git a/src/ccstruct/ocrpara.h b/src/ccstruct/ocrpara.h index e0bb6ab2..473ba6c6 100644 --- a/src/ccstruct/ocrpara.h +++ b/src/ccstruct/ocrpara.h @@ -27,7 +27,7 @@ namespace tesseract { class ParagraphModel; -struct PARA : public ELIST_LINK { +struct PARA : public ELIST::LINK { public: PARA() : model(nullptr) diff --git a/src/ccstruct/ocrrow.cpp b/src/ccstruct/ocrrow.cpp index 5e6eba40..a2c284eb 100644 --- a/src/ccstruct/ocrrow.cpp +++ b/src/ccstruct/ocrrow.cpp @@ -223,7 +223,7 @@ void ROW::plot( // draw it **********************************************************************/ ROW &ROW::operator=(const ROW &source) { - this->ELIST_LINK::operator=(source); + this->ELIST::LINK::operator=(source); kerning = source.kerning; spacing = source.spacing; xheight = source.xheight; diff --git a/src/ccstruct/ocrrow.h b/src/ccstruct/ocrrow.h index 4955cd28..637cb0c5 100644 --- a/src/ccstruct/ocrrow.h +++ b/src/ccstruct/ocrrow.h @@ -36,7 +36,7 @@ class TO_ROW; struct PARA; -class ROW : public ELIST_LINK { +class ROW : public ELIST::LINK { friend void tweak_row_baseline(ROW *, double, double); public: diff --git a/src/ccstruct/pageres.cpp b/src/ccstruct/pageres.cpp index 65ea748f..1bc5e163 100644 --- a/src/ccstruct/pageres.cpp +++ b/src/ccstruct/pageres.cpp @@ -184,7 +184,7 @@ ROW_RES::ROW_RES(bool merge_similar_words, ROW *the_row) { } WERD_RES &WERD_RES::operator=(const WERD_RES &source) { - this->ELIST_LINK::operator=(source); + this->ELIST::LINK::operator=(source); Clear(); if (source.combination) { word = new WERD; diff --git a/src/ccstruct/pageres.h b/src/ccstruct/pageres.h index 48e70b73..c7176f7a 100644 --- a/src/ccstruct/pageres.h +++ b/src/ccstruct/pageres.h @@ -115,7 +115,7 @@ public: * BLOCK_RES - Block results *************************************************************************/ -class BLOCK_RES : public ELIST_LINK { +class BLOCK_RES : public ELIST::LINK { public: BLOCK *block; // real block int32_t char_count; // chars in block @@ -139,7 +139,7 @@ public: * ROW_RES - Row results *************************************************************************/ -class ROW_RES : public ELIST_LINK { +class ROW_RES : public ELIST::LINK { public: ROW *row; // real row int32_t char_count; // chars in block @@ -161,7 +161,7 @@ enum CRUNCH_MODE { CR_NONE, CR_KEEP_SPACE, CR_LOOSE_SPACE, CR_DELETE }; // WERD_RES is a collection of publicly accessible members that gathers // information about a word result. -class TESS_API WERD_RES : public ELIST_LINK { +class TESS_API WERD_RES : public ELIST::LINK { public: // Which word is which? // There are 3 coordinate spaces in use here: a possibly rotated pixel space, @@ -345,7 +345,7 @@ public: } // Deep copies everything except the ratings MATRIX. // To get that use deep_copy below. - WERD_RES(const WERD_RES &source) : ELIST_LINK(source) { + WERD_RES(const WERD_RES &source) : ELIST::LINK(source) { // combination is used in function Clear which is called from operator=. combination = false; *this = source; // see operator= diff --git a/src/ccstruct/points.h b/src/ccstruct/points.h index 59793592..f3adfbf6 100644 --- a/src/ccstruct/points.h +++ b/src/ccstruct/points.h @@ -160,7 +160,7 @@ protected: TDimension ycoord; ///< y value }; -class ICOORDELT : public ELIST_LINK, +class ICOORDELT : public ELIST::LINK, public ICOORD // embedded coord list { diff --git a/src/ccstruct/ratngs.cpp b/src/ccstruct/ratngs.cpp index 0b3cda09..878b439e 100644 --- a/src/ccstruct/ratngs.cpp +++ b/src/ccstruct/ratngs.cpp @@ -110,7 +110,7 @@ BLOB_CHOICE::BLOB_CHOICE(UNICHAR_ID src_unichar_id, // character id * * Constructor to build a BLOB_CHOICE from another BLOB_CHOICE. */ -BLOB_CHOICE::BLOB_CHOICE(const BLOB_CHOICE &other) : ELIST_LINK(other) { +BLOB_CHOICE::BLOB_CHOICE(const BLOB_CHOICE &other) : ELIST::LINK(other) { unichar_id_ = other.unichar_id(); rating_ = other.rating(); certainty_ = other.certainty(); @@ -129,7 +129,7 @@ BLOB_CHOICE::BLOB_CHOICE(const BLOB_CHOICE &other) : ELIST_LINK(other) { // Copy assignment operator. BLOB_CHOICE &BLOB_CHOICE::operator=(const BLOB_CHOICE &other) { - ELIST_LINK::operator=(other); + ELIST::LINK::operator=(other); unichar_id_ = other.unichar_id(); rating_ = other.rating(); certainty_ = other.certainty(); diff --git a/src/ccstruct/ratngs.h b/src/ccstruct/ratngs.h index 2107e903..e9371c9c 100644 --- a/src/ccstruct/ratngs.h +++ b/src/ccstruct/ratngs.h @@ -53,7 +53,7 @@ enum BlobChoiceClassifier { BCC_FAKE, // From some other process. }; -class BLOB_CHOICE : public ELIST_LINK { +class BLOB_CHOICE : public ELIST::LINK { public: BLOB_CHOICE() { unichar_id_ = UNICHAR_SPACE; @@ -255,7 +255,7 @@ enum ScriptPos { SP_NORMAL, SP_SUBSCRIPT, SP_SUPERSCRIPT, SP_DROPCAP }; const char *ScriptPosToString(ScriptPos script_pos); -class TESS_API WERD_CHOICE : public ELIST_LINK { +class TESS_API WERD_CHOICE : public ELIST::LINK { public: static const float kBadRating; static const char *permuter_name(uint8_t permuter); @@ -272,7 +272,7 @@ public: this->init(src_string, src_lengths, src_rating, src_certainty, src_permuter); } WERD_CHOICE(const char *src_string, const UNICHARSET &unicharset); - WERD_CHOICE(const WERD_CHOICE &word) : ELIST_LINK(word), unicharset_(word.unicharset_) { + WERD_CHOICE(const WERD_CHOICE &word) : ELIST::LINK(word), unicharset_(word.unicharset_) { this->init(word.length()); this->operator=(word); } diff --git a/src/ccstruct/stepblob.h b/src/ccstruct/stepblob.h index 31d26710..c7dbd252 100644 --- a/src/ccstruct/stepblob.h +++ b/src/ccstruct/stepblob.h @@ -36,8 +36,7 @@ class C_BLOB; class DENORM; ELISTIZEH(C_BLOB) - -class TESS_API C_BLOB : public ELIST_LINK { +class TESS_API C_BLOB : public ELIST::LINK { public: C_BLOB() = default; explicit C_BLOB(C_OUTLINE_LIST *outline_list); diff --git a/src/ccutil/ambigs.h b/src/ccutil/ambigs.h index fee1c067..2881d365 100644 --- a/src/ccutil/ambigs.h +++ b/src/ccutil/ambigs.h @@ -109,7 +109,7 @@ public: // AMBIG_SPEC_LIST stores a list of dangerous ambigs that // start with the same unichar (e.g. r->t rn->m rr1->m). -class AmbigSpec : public ELIST_LINK { +class AmbigSpec : public ELIST::LINK { public: AmbigSpec(); ~AmbigSpec() = default; diff --git a/src/ccutil/clst.h b/src/ccutil/clst.h index 7fab2b1b..7aa00907 100644 --- a/src/ccutil/clst.h +++ b/src/ccutil/clst.h @@ -34,7 +34,7 @@ namespace tesseract { **********************************************************************/ template -class TESS_API CLIST { +class CLIST { friend class LINK; //friend class ITERATOR; @@ -64,7 +64,7 @@ public: * Generic iterator class for singly linked lists with embedded *links **********************************************************************/ - class TESS_API ITERATOR { + class ITERATOR { CLIST *list; // List being iterated LINK *prev; // prev element LINK *current; // current element diff --git a/src/ccutil/elst.cpp b/src/ccutil/elst.cpp deleted file mode 100644 index 2cac5fd1..00000000 --- a/src/ccutil/elst.cpp +++ /dev/null @@ -1,440 +0,0 @@ -/********************************************************************** - * File: elst.cpp (Formerly elist.c) - * Description: Embedded list handling code which is not in the include file. - * Author: Phil Cheatle - * - * (C) Copyright 1991, Hewlett-Packard Ltd. - ** Licensed under the Apache License, Version 2.0 (the "License"); - ** you may not use this file except in compliance with the License. - ** You may obtain a copy of the License at - ** http://www.apache.org/licenses/LICENSE-2.0 - ** Unless required by applicable law or agreed to in writing, software - ** distributed under the License is distributed on an "AS IS" BASIS, - ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - ** See the License for the specific language governing permissions and - ** limitations under the License. - * - **********************************************************************/ - -#include "elst.h" -#include - -namespace tesseract { - -/*********************************************************************** - * ELIST::internal_clear - * - * Used by the destructor and the "clear" member function of derived list - * classes to destroy all the elements on the list. - * The calling function passes a "zapper" function which can be called to - * delete each element of the list, regardless of its derived type. This - * technique permits a generic clear function to destroy elements of - * different derived types correctly, without requiring virtual functions and - * the consequential memory overhead. - **********************************************************************/ - -void ELIST::internal_clear( // destroy all links - void (*zapper)(void *)) { - // ptr to zapper functn - ELIST_LINK *ptr; - ELIST_LINK *next; - - if (!empty()) { - ptr = last->next; // set to first - last->next = nullptr; // break circle - last = nullptr; // set list empty - while (ptr) { - next = ptr->next; - zapper(ptr); - ptr = next; - } - } -} - -/*********************************************************************** - * ELIST::assign_to_sublist - * - * The list is set to a sublist of another list. "This" list must be empty - * before this function is invoked. The two iterators passed must refer to - * the same list, different from "this" one. The sublist removed is the - * inclusive list from start_it's current position to end_it's current - * position. If this range passes over the end of the source list then the - * source list has its end set to the previous element of start_it. The - * extracted sublist is unaffected by the end point of the source list, its - * end point is always the end_it position. - **********************************************************************/ - -void ELIST::assign_to_sublist( // to this list - ELIST_ITERATOR *start_it, // from list start - ELIST_ITERATOR *end_it) { // from list end - constexpr ERRCODE LIST_NOT_EMPTY("Destination list must be empty before extracting a sublist"); - - if (!empty()) { - LIST_NOT_EMPTY.error("ELIST.assign_to_sublist", ABORT); - } - - last = start_it->extract_sublist(end_it); -} - -/*********************************************************************** - * ELIST::sort - * - * Sort elements on list - * NB If you don't like the const declarations in the comparator, coerce yours: - * ( int (*)(const void *, const void *) - **********************************************************************/ - -void ELIST::sort( // sort elements - int comparator( // comparison routine - const void *, const void *)) { - // Allocate an array of pointers, one per list element. - auto count = length(); - - if (count > 0) { - // ptr array to sort - std::vector base; - base.reserve(count); - - ELIST_ITERATOR it(this); - - // Extract all elements, putting the pointers in the array. - for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) { - base.push_back(it.extract()); - } - - // Sort the pointer array. - qsort(&base[0], count, sizeof(base[0]), comparator); - - // Rebuild the list from the sorted pointers. - for (auto current : base) { - it.add_to_end(current); - } - } -} - -// Assuming list has been sorted already, insert new_link to -// keep the list sorted according to the same comparison function. -// Comparison function is the same as used by sort, i.e. uses double -// indirection. Time is O(1) to add to beginning or end. -// Time is linear to add pre-sorted items to an empty list. -// If unique is set to true and comparator() returns 0 (an entry with the -// same information as the one contained in new_link is already in the -// list) - new_link is not added to the list and the function returns the -// pointer to the identical entry that already exists in the list -// (otherwise the function returns new_link). -ELIST_LINK *ELIST::add_sorted_and_find(int comparator(const void *, const void *), bool unique, - ELIST_LINK *new_link) { - // Check for adding at the end. - if (last == nullptr || comparator(&last, &new_link) < 0) { - if (last == nullptr) { - new_link->next = new_link; - } else { - new_link->next = last->next; - last->next = new_link; - } - last = new_link; - } else { - // Need to use an iterator. - ELIST_ITERATOR it(this); - for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) { - ELIST_LINK *link = it.data(); - int compare = comparator(&link, &new_link); - if (compare > 0) { - break; - } else if (unique && compare == 0) { - return link; - } - } - if (it.cycled_list()) { - it.add_to_end(new_link); - } else { - it.add_before_then_move(new_link); - } - } - return new_link; -} - -/*********************************************************************** - * MEMBER FUNCTIONS OF CLASS: ELIST_ITERATOR - * ========================================= - **********************************************************************/ - -/*********************************************************************** - * ELIST_ITERATOR::forward - * - * Move the iterator to the next element of the list. - * REMEMBER: ALL LISTS ARE CIRCULAR. - **********************************************************************/ - -ELIST_LINK *ELIST_ITERATOR::forward() { -#ifndef NDEBUG - if (!list) - NO_LIST.error("ELIST_ITERATOR::forward", ABORT); -#endif - if (list->empty()) { - return nullptr; - } - - if (current) { // not removed so - // set previous - prev = current; - started_cycling = true; - // In case next is deleted by another iterator, get next from current. - current = current->next; - } else { - if (ex_current_was_cycle_pt) { - cycle_pt = next; - } - current = next; - } -#ifndef NDEBUG - if (!current) - NULL_DATA.error("ELIST_ITERATOR::forward", ABORT); -#endif - next = current->next; - -#ifndef NDEBUG - if (!next) { - NULL_NEXT.error("ELIST_ITERATOR::forward", ABORT, - "This is: %p Current is: %p", - static_cast(this), - static_cast(current)); - } -#endif - return current; -} - -/*********************************************************************** - * ELIST_ITERATOR::data_relative - * - * Return the data pointer to the element "offset" elements from current. - * "offset" must not be less than -1. - * (This function can't be INLINEd because it contains a loop) - **********************************************************************/ - -ELIST_LINK *ELIST_ITERATOR::data_relative( // get data + or - ... - int8_t offset) { // offset from current - ELIST_LINK *ptr; - -#ifndef NDEBUG - if (!list) - NO_LIST.error("ELIST_ITERATOR::data_relative", ABORT); - if (list->empty()) - EMPTY_LIST.error("ELIST_ITERATOR::data_relative", ABORT); - if (offset < -1) - BAD_PARAMETER.error("ELIST_ITERATOR::data_relative", ABORT, "offset < -l"); -#endif - - if (offset == -1) { - ptr = prev; - } else { - for (ptr = current ? current : prev; offset-- > 0; ptr = ptr->next) { - ; - } - } - -#ifndef NDEBUG - if (!ptr) - NULL_DATA.error("ELIST_ITERATOR::data_relative", ABORT); -#endif - - return ptr; -} - -/*********************************************************************** - * ELIST_ITERATOR::move_to_last() - * - * Move current so that it is set to the end of the list. - * Return data just in case anyone wants it. - * (This function can't be INLINEd because it contains a loop) - **********************************************************************/ - -ELIST_LINK *ELIST_ITERATOR::move_to_last() { -#ifndef NDEBUG - if (!list) - NO_LIST.error("ELIST_ITERATOR::move_to_last", ABORT); -#endif - - while (current != list->last) { - forward(); - } - - return current; -} - -/*********************************************************************** - * ELIST_ITERATOR::exchange() - * - * Given another iterator, whose current element is a different element on - * the same list list OR an element of another list, exchange the two current - * elements. On return, each iterator points to the element which was the - * other iterators current on entry. - * (This function hasn't been in-lined because its a bit big!) - **********************************************************************/ - -void ELIST_ITERATOR::exchange( // positions of 2 links - ELIST_ITERATOR *other_it) { // other iterator - constexpr ERRCODE DONT_EXCHANGE_DELETED("Can't exchange deleted elements of lists"); - - ELIST_LINK *old_current; - -#ifndef NDEBUG - if (!list) - NO_LIST.error("ELIST_ITERATOR::exchange", ABORT); - if (!other_it) - BAD_PARAMETER.error("ELIST_ITERATOR::exchange", ABORT, "other_it nullptr"); - if (!(other_it->list)) - NO_LIST.error("ELIST_ITERATOR::exchange", ABORT, "other_it"); -#endif - - /* Do nothing if either list is empty or if both iterators reference the same -link */ - - if ((list->empty()) || (other_it->list->empty()) || (current == other_it->current)) { - return; - } - - /* Error if either current element is deleted */ - - if (!current || !other_it->current) { - DONT_EXCHANGE_DELETED.error("ELIST_ITERATOR.exchange", ABORT); - } - - /* Now handle the 4 cases: doubleton list; non-doubleton adjacent elements -(other before this); non-doubleton adjacent elements (this before other); -non-adjacent elements. */ - - // adjacent links - if ((next == other_it->current) || (other_it->next == current)) { - // doubleton list - if ((next == other_it->current) && (other_it->next == current)) { - prev = next = current; - other_it->prev = other_it->next = other_it->current; - } else { // non-doubleton with - // adjacent links - // other before this - if (other_it->next == current) { - other_it->prev->next = current; - other_it->current->next = next; - current->next = other_it->current; - other_it->next = other_it->current; - prev = current; - } else { // this before other - prev->next = other_it->current; - current->next = other_it->next; - other_it->current->next = current; - next = current; - other_it->prev = other_it->current; - } - } - } else { // no overlap - prev->next = other_it->current; - current->next = other_it->next; - other_it->prev->next = current; - other_it->current->next = next; - } - - /* update end of list pointer when necessary (remember that the 2 iterators - may iterate over different lists!) */ - - if (list->last == current) { - list->last = other_it->current; - } - if (other_it->list->last == other_it->current) { - other_it->list->last = current; - } - - if (current == cycle_pt) { - cycle_pt = other_it->cycle_pt; - } - if (other_it->current == other_it->cycle_pt) { - other_it->cycle_pt = cycle_pt; - } - - /* The actual exchange - in all cases*/ - - old_current = current; - current = other_it->current; - other_it->current = old_current; -} - -/*********************************************************************** - * ELIST_ITERATOR::extract_sublist() - * - * This is a private member, used only by ELIST::assign_to_sublist. - * Given another iterator for the same list, extract the links from THIS to - * OTHER inclusive, link them into a new circular list, and return a - * pointer to the last element. - * (Can't inline this function because it contains a loop) - **********************************************************************/ - -ELIST_LINK *ELIST_ITERATOR::extract_sublist( // from this current - ELIST_ITERATOR *other_it) { // to other current -#ifndef NDEBUG - constexpr ERRCODE BAD_EXTRACTION_PTS("Can't extract sublist from points on different lists"); - constexpr ERRCODE DONT_EXTRACT_DELETED("Can't extract a sublist marked by deleted points"); -#endif - constexpr ERRCODE BAD_SUBLIST("Can't find sublist end point in original list"); - - ELIST_ITERATOR temp_it = *this; - ELIST_LINK *end_of_new_list; - -#ifndef NDEBUG - if (!other_it) - BAD_PARAMETER.error("ELIST_ITERATOR::extract_sublist", ABORT, "other_it nullptr"); - if (!list) - NO_LIST.error("ELIST_ITERATOR::extract_sublist", ABORT); - if (list != other_it->list) - BAD_EXTRACTION_PTS.error("ELIST_ITERATOR.extract_sublist", ABORT); - if (list->empty()) - EMPTY_LIST.error("ELIST_ITERATOR::extract_sublist", ABORT); - - if (!current || !other_it->current) - DONT_EXTRACT_DELETED.error("ELIST_ITERATOR.extract_sublist", ABORT); -#endif - - ex_current_was_last = other_it->ex_current_was_last = false; - ex_current_was_cycle_pt = false; - other_it->ex_current_was_cycle_pt = false; - - temp_it.mark_cycle_pt(); - do { // walk sublist - if (temp_it.cycled_list()) { // can't find end pt - BAD_SUBLIST.error("ELIST_ITERATOR.extract_sublist", ABORT); - } - - if (temp_it.at_last()) { - list->last = prev; - ex_current_was_last = other_it->ex_current_was_last = true; - } - - if (temp_it.current == cycle_pt) { - ex_current_was_cycle_pt = true; - } - - if (temp_it.current == other_it->cycle_pt) { - other_it->ex_current_was_cycle_pt = true; - } - - temp_it.forward(); - } while (temp_it.prev != other_it->current); - - // circularise sublist - other_it->current->next = current; - end_of_new_list = other_it->current; - - // sublist = whole list - if (prev == other_it->current) { - list->last = nullptr; - prev = current = next = nullptr; - other_it->prev = other_it->current = other_it->next = nullptr; - } else { - prev->next = other_it->next; - current = other_it->current = nullptr; - next = other_it->next; - other_it->prev = prev; - } - return end_of_new_list; -} - -} // namespace tesseract diff --git a/src/ccutil/elst.h b/src/ccutil/elst.h index 040ce2a4..b264b647 100644 --- a/src/ccutil/elst.h +++ b/src/ccutil/elst.h @@ -27,8 +27,6 @@ namespace tesseract { -class ELIST_ITERATOR; - /********************************************************************** This module implements list classes and iterators. The following list types and iterators are provided: @@ -68,58 +66,913 @@ list class - though macros can generate these. It also prevents heterogeneous lists. **********************************************************************/ -/********************************************************************** - * CLASS - ELIST_LINK - * - * Generic link class for singly linked lists with - *embedded links - * - * Note: No destructor - elements are assumed to be destroyed EITHER after - * they have been extracted from a list OR by the ELIST destructor which - * walks the list. - **********************************************************************/ - -class ELIST_LINK { - friend class ELIST_ITERATOR; - friend class ELIST; - - ELIST_LINK *next; - -public: - ELIST_LINK() { - next = nullptr; - } - // constructor - - // The special copy constructor is used by lots of classes. - ELIST_LINK(const ELIST_LINK &) { - next = nullptr; - } - - // The special assignment operator is used by lots of classes. - void operator=(const ELIST_LINK &) { - next = nullptr; - } -}; - /********************************************************************** * CLASS - ELIST * * Generic list class for singly linked lists with embedded links **********************************************************************/ -class TESS_API ELIST { - friend class ELIST_ITERATOR; +template +class ELIST { +public: - ELIST_LINK *last = nullptr; // End of list + /********************************************************************** + * CLASS - ELIST_LINK + * + * Generic link class for singly linked lists with + *embedded links + * + * Note: No destructor - elements are assumed to be destroyed EITHER after + * they have been extracted from a list OR by the ELIST destructor which + * walks the list. + **********************************************************************/ + + class LINK { + friend class ITERATOR; + friend class ELIST; + + CLASSNAME *next; + + public: + LINK() { + next = nullptr; + } + // constructor + + // The special copy constructor is used by lots of classes. + LINK(const LINK &) { + next = nullptr; + } + + // The special assignment operator is used by lots of classes. + void operator=(const LINK &) { + next = nullptr; + } + }; + + + /*********************************************************************** + * CLASS - ELIST_ITERATOR + * + * Generic iterator class for singly linked lists with + *embedded links + **********************************************************************/ + + class ITERATOR { + friend void ELIST::assign_to_sublist(ITERATOR *, ITERATOR *); + + ELIST *list; // List being iterated + CLASSNAME *prev; // prev element + CLASSNAME *current; // current element + CLASSNAME *next; // next element + CLASSNAME *cycle_pt; // point we are cycling the list to. + bool ex_current_was_last; // current extracted was end of list + bool ex_current_was_cycle_pt; // current extracted was cycle point + bool started_cycling; // Have we moved off the start? + /*********************************************************************** + * ITERATOR::extract_sublist() + * + * This is a private member, used only by ELIST::assign_to_sublist. + * Given another iterator for the same list, extract the links from THIS to + * OTHER inclusive, link them into a new circular list, and return a + * pointer to the last element. + * (Can't inline this function because it contains a loop) + **********************************************************************/ + CLASSNAME *extract_sublist( // from this current... + ITERATOR *other_it) { // to other current +#ifndef NDEBUG + constexpr ERRCODE BAD_EXTRACTION_PTS("Can't extract sublist from points on different lists"); + constexpr ERRCODE DONT_EXTRACT_DELETED("Can't extract a sublist marked by deleted points"); +#endif + constexpr ERRCODE BAD_SUBLIST("Can't find sublist end point in original list"); + + ITERATOR temp_it = *this; + CLASSNAME *end_of_new_list; + +#ifndef NDEBUG + if (!other_it) + BAD_PARAMETER.error("ELIST_ITERATOR::extract_sublist", ABORT, "other_it nullptr"); + if (!list) + NO_LIST.error("ELIST_ITERATOR::extract_sublist", ABORT); + if (list != other_it->list) + BAD_EXTRACTION_PTS.error("ELIST_ITERATOR.extract_sublist", ABORT); + if (list->empty()) + EMPTY_LIST.error("ELIST_ITERATOR::extract_sublist", ABORT); + + if (!current || !other_it->current) + DONT_EXTRACT_DELETED.error("ELIST_ITERATOR.extract_sublist", ABORT); +#endif + + ex_current_was_last = other_it->ex_current_was_last = false; + ex_current_was_cycle_pt = false; + other_it->ex_current_was_cycle_pt = false; + + temp_it.mark_cycle_pt(); + do { // walk sublist + if (temp_it.cycled_list()) { // can't find end pt + BAD_SUBLIST.error("ITERATOR.extract_sublist", ABORT); + } + + if (temp_it.at_last()) { + list->last = prev; + ex_current_was_last = other_it->ex_current_was_last = true; + } + + if (temp_it.current == cycle_pt) { + ex_current_was_cycle_pt = true; + } + + if (temp_it.current == other_it->cycle_pt) { + other_it->ex_current_was_cycle_pt = true; + } + + temp_it.forward(); + } while (temp_it.prev != other_it->current); + + // circularise sublist + other_it->current->next = current; + end_of_new_list = other_it->current; + + // sublist = whole list + if (prev == other_it->current) { + list->last = nullptr; + prev = current = next = nullptr; + other_it->prev = other_it->current = other_it->next = nullptr; + } else { + prev->next = other_it->next; + current = other_it->current = nullptr; + next = other_it->next; + other_it->prev = prev; + } + return end_of_new_list; + } // to other current + + public: + ITERATOR() { // constructor + list = nullptr; + } // unassigned list + /*********************************************************************** + * ELIST_ITERATOR::ELIST_ITERATOR + * + * CONSTRUCTOR - set iterator to specified list; + **********************************************************************/ + ITERATOR(ELIST *list_to_iterate) { + set_to_list(list_to_iterate); + } + /*********************************************************************** + * ELIST_ITERATOR::set_to_list + * + * (Re-)initialise the iterator to point to the start of the list_to_iterate + * over. + **********************************************************************/ + void set_to_list( // change list + ELIST *list_to_iterate) { +#ifndef NDEBUG + if (!list_to_iterate) { + BAD_PARAMETER.error("ELIST_ITERATOR::set_to_list", ABORT, "list_to_iterate is nullptr"); + } +#endif + + list = list_to_iterate; + prev = list->last; + current = list->First(); + next = current ? current->next : nullptr; + cycle_pt = nullptr; // await explicit set + started_cycling = false; + ex_current_was_last = false; + ex_current_was_cycle_pt = false; + } + /*********************************************************************** + * ELIST_ITERATOR::add_after_then_move + * + * Add a new element to the list after the current element and move the + * iterator to the new element. + **********************************************************************/ + void add_after_then_move( // add after current & + CLASSNAME *new_element) { +#ifndef NDEBUG + if (!list) { + NO_LIST.error("ELIST_ITERATOR::add_after_then_move", ABORT); + } + if (!new_element) { + BAD_PARAMETER.error("ELIST_ITERATOR::add_after_then_move", ABORT, "new_element is nullptr"); + } + if (new_element->next) { + STILL_LINKED.error("ELIST_ITERATOR::add_after_then_move", ABORT); + } +#endif + + if (list->empty()) { + new_element->next = new_element; + list->last = new_element; + prev = next = new_element; + } else { + new_element->next = next; + + if (current) { // not extracted + current->next = new_element; + prev = current; + if (current == list->last) { + list->last = new_element; + } + } else { // current extracted + prev->next = new_element; + if (ex_current_was_last) { + list->last = new_element; + } + if (ex_current_was_cycle_pt) { + cycle_pt = new_element; + } + } + } + current = new_element; + } // move to new + /*********************************************************************** + * ELIST_ITERATOR::add_after_stay_put + * + * Add a new element to the list after the current element but do not move + * the iterator to the new element. + **********************************************************************/ + void add_after_stay_put( // add after current & + CLASSNAME *new_element) { +#ifndef NDEBUG + if (!list) { + NO_LIST.error("ELIST_ITERATOR::add_after_stay_put", ABORT); + } + if (!new_element) { + BAD_PARAMETER.error("ELIST_ITERATOR::add_after_stay_put", ABORT, "new_element is nullptr"); + } + if (new_element->next) { + STILL_LINKED.error("ELIST_ITERATOR::add_after_stay_put", ABORT); + } +#endif + + if (list->empty()) { + new_element->next = new_element; + list->last = new_element; + prev = next = new_element; + ex_current_was_last = false; + current = nullptr; + } else { + new_element->next = next; + + if (current) { // not extracted + current->next = new_element; + if (prev == current) { + prev = new_element; + } + if (current == list->last) { + list->last = new_element; + } + } else { // current extracted + prev->next = new_element; + if (ex_current_was_last) { + list->last = new_element; + ex_current_was_last = false; + } + } + next = new_element; + } + } // stay at current + /*********************************************************************** + * ELIST_ITERATOR::add_before_then_move + * + * Add a new element to the list before the current element and move the + * iterator to the new element. + **********************************************************************/ + void add_before_then_move( // add before current & + CLASSNAME *new_element) { +#ifndef NDEBUG + if (!list) { + NO_LIST.error("ELIST_ITERATOR::add_before_then_move", ABORT); + } + if (!new_element) { + BAD_PARAMETER.error("ELIST_ITERATOR::add_before_then_move", ABORT, "new_element is nullptr"); + } + if (new_element->next) { + STILL_LINKED.error("ELIST_ITERATOR::add_before_then_move", ABORT); + } +#endif + + if (list->empty()) { + new_element->next = new_element; + list->last = new_element; + prev = next = new_element; + } else { + prev->next = new_element; + if (current) { // not extracted + new_element->next = current; + next = current; + } else { // current extracted + new_element->next = next; + if (ex_current_was_last) { + list->last = new_element; + } + if (ex_current_was_cycle_pt) { + cycle_pt = new_element; + } + } + } + current = new_element; + } // move to new + /*********************************************************************** + * ELIST_ITERATOR::add_before_stay_put + * + * Add a new element to the list before the current element but don't move the + * iterator to the new element. + **********************************************************************/ + void add_before_stay_put( // add before current & + CLASSNAME *new_element) { +#ifndef NDEBUG + if (!list) { + NO_LIST.error("ELIST_ITERATOR::add_before_stay_put", ABORT); + } + if (!new_element) { + BAD_PARAMETER.error("ELIST_ITERATOR::add_before_stay_put", ABORT, "new_element is nullptr"); + } + if (new_element->next) { + STILL_LINKED.error("ELIST_ITERATOR::add_before_stay_put", ABORT); + } +#endif + + if (list->empty()) { + new_element->next = new_element; + list->last = new_element; + prev = next = new_element; + ex_current_was_last = true; + current = nullptr; + } else { + prev->next = new_element; + if (current) { // not extracted + new_element->next = current; + if (next == current) { + next = new_element; + } + } else { // current extracted + new_element->next = next; + if (ex_current_was_last) { + list->last = new_element; + } + } + prev = new_element; + } + } // stay at current + /*********************************************************************** + * ELIST_ITERATOR::add_list_after + * + * Insert another list to this list after the current element but don't move + *the + * iterator. + **********************************************************************/ + void add_list_after( // add a list & + ELIST *list_to_add) { +#ifndef NDEBUG + if (!list) { + NO_LIST.error("ELIST_ITERATOR::add_list_after", ABORT); + } + if (!list_to_add) { + BAD_PARAMETER.error("ELIST_ITERATOR::add_list_after", ABORT, "list_to_add is nullptr"); + } +#endif + + if (!list_to_add->empty()) { + if (list->empty()) { + list->last = list_to_add->last; + prev = list->last; + next = list->First(); + ex_current_was_last = true; + current = nullptr; + } else { + if (current) { // not extracted + current->next = list_to_add->First(); + if (current == list->last) { + list->last = list_to_add->last; + } + list_to_add->last->next = next; + next = current->next; + } else { // current extracted + prev->next = list_to_add->First(); + if (ex_current_was_last) { + list->last = list_to_add->last; + ex_current_was_last = false; + } + list_to_add->last->next = next; + next = prev->next; + } + } + list_to_add->last = nullptr; + } + } // stay at current + /*********************************************************************** + * ELIST_ITERATOR::add_list_before + * + * Insert another list to this list before the current element. Move the + * iterator to the start of the inserted elements + * iterator. + **********************************************************************/ + void add_list_before( // add a list & + ELIST *list_to_add) { +#ifndef NDEBUG + if (!list) { + NO_LIST.error("ELIST_ITERATOR::add_list_before", ABORT); + } + if (!list_to_add) { + BAD_PARAMETER.error("ELIST_ITERATOR::add_list_before", ABORT, "list_to_add is nullptr"); + } +#endif + + if (!list_to_add->empty()) { + if (list->empty()) { + list->last = list_to_add->last; + prev = list->last; + current = list->First(); + next = current->next; + ex_current_was_last = false; + } else { + prev->next = list_to_add->First(); + if (current) { // not extracted + list_to_add->last->next = current; + } else { // current extracted + list_to_add->last->next = next; + if (ex_current_was_last) { + list->last = list_to_add->last; + } + if (ex_current_was_cycle_pt) { + cycle_pt = prev->next; + } + } + current = prev->next; + next = current->next; + } + list_to_add->last = nullptr; + } + } // move to it 1st item + + CLASSNAME *data() { // get current data +#ifndef NDEBUG + if (!list) { + NO_LIST.error("ELIST_ITERATOR::data", ABORT); + } + if (!current) { + NULL_DATA.error("ELIST_ITERATOR::data", ABORT); + } +#endif + return current; + } + /*********************************************************************** + * ELIST_ITERATOR::data_relative + * + * Return the data pointer to the element "offset" elements from current. + * "offset" must not be less than -1. + * (This function can't be INLINEd because it contains a loop) + **********************************************************************/ + CLASSNAME *data_relative( // get data + or - ... + int8_t offset) { // offset from current + CLASSNAME *ptr; + +#ifndef NDEBUG + if (!list) + NO_LIST.error("ELIST_ITERATOR::data_relative", ABORT); + if (list->empty()) + EMPTY_LIST.error("ELIST_ITERATOR::data_relative", ABORT); + if (offset < -1) + BAD_PARAMETER.error("ELIST_ITERATOR::data_relative", ABORT, "offset < -l"); +#endif + + if (offset == -1) { + ptr = prev; + } else { + for (ptr = current ? current : prev; offset-- > 0; ptr = ptr->next) { + ; + } + } + +#ifndef NDEBUG + if (!ptr) + NULL_DATA.error("ELIST_ITERATOR::data_relative", ABORT); +#endif + + return ptr; + } // offset from current + /*********************************************************************** + * ELIST_ITERATOR::forward + * + * Move the iterator to the next element of the list. + * REMEMBER: ALL LISTS ARE CIRCULAR. + **********************************************************************/ + CLASSNAME *forward() { +#ifndef NDEBUG + if (!list) + NO_LIST.error("ELIST_ITERATOR::forward", ABORT); +#endif + if (list->empty()) { + return nullptr; + } + + if (current) { // not removed so + // set previous + prev = current; + started_cycling = true; + // In case next is deleted by another iterator, get next from current. + current = current->next; + } else { + if (ex_current_was_cycle_pt) { + cycle_pt = next; + } + current = next; + } +#ifndef NDEBUG + if (!current) + NULL_DATA.error("ELIST_ITERATOR::forward", ABORT); +#endif + next = current->next; + +#ifndef NDEBUG + if (!next) { + NULL_NEXT.error("ELIST_ITERATOR::forward", ABORT, + "This is: %p Current is: %p", + static_cast(this), + static_cast(current)); + } +#endif + return current; + } // move to next element + + /*********************************************************************** + * ELIST_ITERATOR::extract + * + * Do extraction by removing current from the list, returning it to the + * caller, but NOT updating the iterator. (So that any calling loop can do + * this.) The iterator's current points to nullptr. If the extracted element + * is to be deleted, this is the callers responsibility. + **********************************************************************/ + CLASSNAME *extract() { + CLASSNAME *extracted_link; + +#ifndef NDEBUG + if (!list) { + NO_LIST.error("ELIST_ITERATOR::extract", ABORT); + } + if (!current) { // list empty or + // element extracted + NULL_CURRENT.error("ELIST_ITERATOR::extract", ABORT); + } +#endif + + if (list->singleton()) { + // Special case where we do need to change the iterator. + prev = next = list->last = nullptr; + } else { + prev->next = next; // remove from list + + ex_current_was_last = (current == list->last); + if (ex_current_was_last) { + list->last = prev; + } + } + // Always set ex_current_was_cycle_pt so an add/forward will work in a loop. + ex_current_was_cycle_pt = (current == cycle_pt); + extracted_link = current; + extracted_link->next = nullptr; // for safety + current = nullptr; + return extracted_link; + } // remove from list + /*********************************************************************** + * ELIST_ITERATOR::move_to_first() + * + * Move current so that it is set to the start of the list. + * Return data just in case anyone wants it. + **********************************************************************/ + CLASSNAME *move_to_first() { +#ifndef NDEBUG + if (!list) { + NO_LIST.error("ELIST_ITERATOR::move_to_first", ABORT); + } +#endif + + current = list->First(); + prev = list->last; + next = current ? current->next : nullptr; + return current; + } // go to start of list + /*********************************************************************** + * ELIST_ITERATOR::move_to_last() + * + * Move current so that it is set to the end of the list. + * Return data just in case anyone wants it. + * (This function can't be INLINEd because it contains a loop) + **********************************************************************/ + CLASSNAME *move_to_last() { +#ifndef NDEBUG + if (!list) + NO_LIST.error("ELIST_ITERATOR::move_to_last", ABORT); +#endif + + while (current != list->last) { + forward(); + } + + return current; + } // go to end of list + /*********************************************************************** + * ELIST_ITERATOR::mark_cycle_pt() + * + * Remember the current location so that we can tell whether we've returned + * to this point later. + * + * If the current point is deleted either now, or in the future, the cycle + * point will be set to the next item which is set to current. This could be + * by a forward, add_after_then_move or add_after_then_move. + **********************************************************************/ + void mark_cycle_pt() { +#ifndef NDEBUG + if (!list) { + NO_LIST.error("ELIST_ITERATOR::mark_cycle_pt", ABORT); + } +#endif + + if (current) { + cycle_pt = current; + } else { + ex_current_was_cycle_pt = true; + } + started_cycling = false; + } // remember current + + bool empty() const { // is list empty? +#ifndef NDEBUG + if (!list) { + NO_LIST.error("ELIST_ITERATOR::empty", ABORT); + } +#endif + return list->empty(); + } + + bool current_extracted() const { // current extracted? + return !current; + } + /*********************************************************************** + * ELIST_ITERATOR::at_first() + * + * Are we at the start of the list? + * + **********************************************************************/ + bool at_first() const { +#ifndef NDEBUG + if (!list) { + NO_LIST.error("ELIST_ITERATOR::at_first", ABORT); + } +#endif + + // we're at a deleted + return ((list->empty()) || (current == list->First()) || + ((current == nullptr) && (prev == list->last) && // NON-last pt between + !ex_current_was_last)); // first and last + } // Current is first? + /*********************************************************************** + * ELIST_ITERATOR::at_last() + * + * Are we at the end of the list? + * + **********************************************************************/ + bool at_last() const { +#ifndef NDEBUG + if (!list) { + NO_LIST.error("ELIST_ITERATOR::at_last", ABORT); + } +#endif + + // we're at a deleted + return ((list->empty()) || (current == list->last) || + ((current == nullptr) && (prev == list->last) && // last point between + ex_current_was_last)); // first and last + } // Current is last? + /*********************************************************************** + * ELIST_ITERATOR::cycled_list() + * + * Have we returned to the cycle_pt since it was set? + * + **********************************************************************/ + bool cycled_list() const { +#ifndef NDEBUG + if (!list) { + NO_LIST.error("ELIST_ITERATOR::cycled_list", ABORT); + } +#endif + + return ((list->empty()) || ((current == cycle_pt) && started_cycling)); + } // Completed a cycle? + /*********************************************************************** + * ELIST_ITERATOR::add_to_end + * + * Add a new element to the end of the list without moving the iterator. + * This is provided because a single linked list cannot move to the last as + * the iterator couldn't set its prev pointer. Adding to the end is + * essential for implementing + queues. + **********************************************************************/ + void add_to_end( // add at end & + CLASSNAME *new_element) { +#ifndef NDEBUG + if (!list) { + NO_LIST.error("ELIST_ITERATOR::add_to_end", ABORT); + } + if (!new_element) { + BAD_PARAMETER.error("ELIST_ITERATOR::add_to_end", ABORT, "new_element is nullptr"); + } + if (new_element->next) { + STILL_LINKED.error("ELIST_ITERATOR::add_to_end", ABORT); + } +#endif + + if (this->at_last()) { + this->add_after_stay_put(new_element); + } else { + if (this->at_first()) { + this->add_before_stay_put(new_element); + list->last = new_element; + } else { // Iteratr is elsewhere + new_element->next = list->last->next; + list->last->next = new_element; + list->last = new_element; + } + } + } // don't move + /*********************************************************************** + * ELIST_ITERATOR::exchange() + * + * Given another iterator, whose current element is a different element on + * the same list list OR an element of another list, exchange the two current + * elements. On return, each iterator points to the element which was the + * other iterators current on entry. + * (This function hasn't been in-lined because its a bit big!) + **********************************************************************/ + void exchange( // positions of 2 links + ITERATOR *other_it) { // other iterator + constexpr ERRCODE DONT_EXCHANGE_DELETED("Can't exchange deleted elements of lists"); + + CLASSNAME *old_current; + +#ifndef NDEBUG + if (!list) + NO_LIST.error("ELIST_ITERATOR::exchange", ABORT); + if (!other_it) + BAD_PARAMETER.error("ELIST_ITERATOR::exchange", ABORT, "other_it nullptr"); + if (!(other_it->list)) + NO_LIST.error("ELIST_ITERATOR::exchange", ABORT, "other_it"); +#endif + + /* Do nothing if either list is empty or if both iterators reference the same + link */ + + if ((list->empty()) || (other_it->list->empty()) || (current == other_it->current)) { + return; + } + + /* Error if either current element is deleted */ + + if (!current || !other_it->current) { + DONT_EXCHANGE_DELETED.error("ELIST_ITERATOR.exchange", ABORT); + } + + /* Now handle the 4 cases: doubleton list; non-doubleton adjacent elements + (other before this); non-doubleton adjacent elements (this before other); + non-adjacent elements. */ + + // adjacent links + if ((next == other_it->current) || (other_it->next == current)) { + // doubleton list + if ((next == other_it->current) && (other_it->next == current)) { + prev = next = current; + other_it->prev = other_it->next = other_it->current; + } else { // non-doubleton with + // adjacent links + // other before this + if (other_it->next == current) { + other_it->prev->next = current; + other_it->current->next = next; + current->next = other_it->current; + other_it->next = other_it->current; + prev = current; + } else { // this before other + prev->next = other_it->current; + current->next = other_it->next; + other_it->current->next = current; + next = current; + other_it->prev = other_it->current; + } + } + } else { // no overlap + prev->next = other_it->current; + current->next = other_it->next; + other_it->prev->next = current; + other_it->current->next = next; + } + + /* update end of list pointer when necessary (remember that the 2 iterators + may iterate over different lists!) */ + + if (list->last == current) { + list->last = other_it->current; + } + if (other_it->list->last == other_it->current) { + other_it->list->last = current; + } + + if (current == cycle_pt) { + cycle_pt = other_it->cycle_pt; + } + if (other_it->current == other_it->cycle_pt) { + other_it->cycle_pt = cycle_pt; + } + + /* The actual exchange - in all cases*/ + + old_current = current; + current = other_it->current; + other_it->current = old_current; + } // other iterator + + //# elements in list + int32_t length() const { + return list->length(); + } + /*********************************************************************** + * ELIST_ITERATOR::sort() + * + * Sort the elements of the list, then reposition at the start. + * + **********************************************************************/ + void sort( // sort elements + int comparator( // comparison routine + const void *, const void *)) { +#ifndef NDEBUG + if (!list) { + NO_LIST.error("ELIST_ITERATOR::sort", ABORT); + } +#endif + + list->sort(comparator); + move_to_first(); + } + }; + + +private: + CLASSNAME *last = nullptr; // End of list //(Points to head) - ELIST_LINK *First() { // return first + CLASSNAME *First() { // return first return last ? last->next : nullptr; } public: - // destroy all links - void internal_clear(void (*zapper)(void *)); + ~ELIST() { + clear(); + } + + /* delete elements */ + void clear() { + internal_clear(); + } + + /* Become a deep copy of src_list */ + template + void deep_copy(const U *src_list, CLASSNAME *(*copier)(const CLASSNAME *)) { + ITERATOR from_it(const_cast(src_list)); + ITERATOR to_it(this); + + for (from_it.mark_cycle_pt(); !from_it.cycled_list(); from_it.forward()) + to_it.add_after_then_move((*copier)(from_it.data())); + } + + /*********************************************************************** + * ELIST::internal_clear + * + * Used by the destructor and the "clear" member function of derived list + * classes to destroy all the elements on the list. + * The calling function passes a "zapper" function which can be called to + * delete each element of the list, regardless of its derived type. This + * technique permits a generic clear function to destroy elements of + * different derived types correctly, without requiring virtual functions and + * the consequential memory overhead. + **********************************************************************/ + + // destroy all links + void internal_clear() { + CLASSNAME *ptr; + CLASSNAME *next; + + if (!empty()) { + ptr = last->next; // set to first + last->next = nullptr; // break circle + last = nullptr; // set list empty + while (ptr) { + next = ptr->next; + delete ptr; + ptr = next; + } + } + } bool empty() const { return !last; @@ -130,19 +983,35 @@ public: } void shallow_copy( // dangerous!! - ELIST *from_list) { // beware destructors!! + ELIST *from_list) { // beware destructors!! last = from_list->last; } - // ptr to copier functn - void internal_deep_copy(ELIST_LINK *(*copier)(ELIST_LINK *), - const ELIST *list); // list being copied - + /*********************************************************************** + * ELIST::assign_to_sublist + * + * The list is set to a sublist of another list. "This" list must be empty + * before this function is invoked. The two iterators passed must refer to + * the same list, different from "this" one. The sublist removed is the + * inclusive list from start_it's current position to end_it's current + * position. If this range passes over the end of the source list then the + * source list has its end set to the previous element of start_it. The + * extracted sublist is unaffected by the end point of the source list, its + * end point is always the end_it position. + **********************************************************************/ void assign_to_sublist( // to this list - ELIST_ITERATOR *start_it, // from list start - ELIST_ITERATOR *end_it); // from list end + ITERATOR *start_it, // from list start + ITERATOR *end_it) { // from list end + constexpr ERRCODE LIST_NOT_EMPTY("Destination list must be empty before extracting a sublist"); - // # elements in list + if (!empty()) { + LIST_NOT_EMPTY.error("ELIST.assign_to_sublist", ABORT); + } + + last = start_it->extract_sublist(end_it); + } // from list end + + // # elements in list int32_t length() const { int32_t count = 0; if (last != nullptr) { @@ -154,9 +1023,40 @@ public: return count; } + /*********************************************************************** + * ELIST::sort + * + * Sort elements on list + * NB If you don't like the const declarations in the comparator, coerce yours: + * ( int (*)(const void *, const void *) + **********************************************************************/ void sort( // sort elements - int comparator( // comparison routine - const void *, const void *)); + int comparator( // comparison routine + const void *, const void *)) { + // Allocate an array of pointers, one per list element. + auto count = length(); + + if (count > 0) { + // ptr array to sort + std::vector base; + base.reserve(count); + + ITERATOR it(this); + + // Extract all elements, putting the pointers in the array. + for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) { + base.push_back(it.extract()); + } + + // Sort the pointer array. + qsort(&base[0], count, sizeof(base[0]), comparator); + + // Rebuild the list from the sorted pointers. + for (auto current : base) { + it.add_to_end(current); + } + } + } // Assuming list has been sorted already, insert new_link to // keep the list sorted according to the same comparison function. @@ -168,644 +1068,54 @@ public: // list) - new_link is not added to the list and the function returns the // pointer to the identical entry that already exists in the list // (otherwise the function returns new_link). - ELIST_LINK *add_sorted_and_find(int comparator(const void *, const void *), bool unique, - ELIST_LINK *new_link); + CLASSNAME *add_sorted_and_find(int comparator(const void *, const void *), bool unique, + CLASSNAME *new_link) { + // Check for adding at the end. + if (last == nullptr || comparator(&last, &new_link) < 0) { + if (last == nullptr) { + new_link->next = new_link; + } else { + new_link->next = last->next; + last->next = new_link; + } + last = new_link; + } else { + // Need to use an iterator. + ITERATOR it(this); + for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) { + auto *link = it.data(); + int compare = comparator(&link, &new_link); + if (compare > 0) { + break; + } else if (unique && compare == 0) { + return link; + } + } + if (it.cycled_list()) { + it.add_to_end(new_link); + } else { + it.add_before_then_move(new_link); + } + } + return new_link; + } // Same as above, but returns true if the new entry was inserted, false // if the identical entry already existed in the list. - bool add_sorted(int comparator(const void *, const void *), bool unique, ELIST_LINK *new_link) { + bool add_sorted(int comparator(const void *, const void *), bool unique, CLASSNAME *new_link) { return (add_sorted_and_find(comparator, unique, new_link) == new_link); } }; -/*********************************************************************** - * CLASS - ELIST_ITERATOR - * - * Generic iterator class for singly linked lists with - *embedded links - **********************************************************************/ - -class TESS_API ELIST_ITERATOR { - friend void ELIST::assign_to_sublist(ELIST_ITERATOR *, ELIST_ITERATOR *); - - ELIST *list; // List being iterated - ELIST_LINK *prev; // prev element - ELIST_LINK *current; // current element - ELIST_LINK *next; // next element - ELIST_LINK *cycle_pt; // point we are cycling the list to. - bool ex_current_was_last; // current extracted was end of list - bool ex_current_was_cycle_pt; // current extracted was cycle point - bool started_cycling; // Have we moved off the start? - - ELIST_LINK *extract_sublist( // from this current... - ELIST_ITERATOR *other_it); // to other current - -public: - ELIST_ITERATOR() { // constructor - list = nullptr; - } // unassigned list - - explicit ELIST_ITERATOR(ELIST *list_to_iterate); - - void set_to_list( // change list - ELIST *list_to_iterate); - - void add_after_then_move( // add after current & - ELIST_LINK *new_link); // move to new - - void add_after_stay_put( // add after current & - ELIST_LINK *new_link); // stay at current - - void add_before_then_move( // add before current & - ELIST_LINK *new_link); // move to new - - void add_before_stay_put( // add before current & - ELIST_LINK *new_link); // stay at current - - void add_list_after( // add a list & - ELIST *list_to_add); // stay at current - - void add_list_before( // add a list & - ELIST *list_to_add); // move to it 1st item - - ELIST_LINK *data() { // get current data -#ifndef NDEBUG - if (!list) { - NO_LIST.error("ELIST_ITERATOR::data", ABORT); - } - if (!current) { - NULL_DATA.error("ELIST_ITERATOR::data", ABORT); - } -#endif - return current; - } - - ELIST_LINK *data_relative( // get data + or - ... - int8_t offset); // offset from current - - ELIST_LINK *forward(); // move to next element - - ELIST_LINK *extract(); // remove from list - - ELIST_LINK *move_to_first(); // go to start of list - - ELIST_LINK *move_to_last(); // go to end of list - - void mark_cycle_pt(); // remember current - - bool empty() const { // is list empty? -#ifndef NDEBUG - if (!list) { - NO_LIST.error("ELIST_ITERATOR::empty", ABORT); - } -#endif - return list->empty(); - } - - bool current_extracted() const { // current extracted? - return !current; - } - - bool at_first() const; // Current is first? - - bool at_last() const; // Current is last? - - bool cycled_list() const; // Completed a cycle? - - void add_to_end( // add at end & - ELIST_LINK *new_link); // don't move - - void exchange( // positions of 2 links - ELIST_ITERATOR *other_it); // other iterator - - //# elements in list - int32_t length() const { - return list->length(); - } - - void sort( // sort elements - int comparator( // comparison routine - const void *, const void *)); -}; - -/*********************************************************************** - * ELIST_ITERATOR::set_to_list - * - * (Re-)initialise the iterator to point to the start of the list_to_iterate - * over. - **********************************************************************/ - -inline void ELIST_ITERATOR::set_to_list( // change list - ELIST *list_to_iterate) { -#ifndef NDEBUG - if (!list_to_iterate) { - BAD_PARAMETER.error("ELIST_ITERATOR::set_to_list", ABORT, "list_to_iterate is nullptr"); - } -#endif - - list = list_to_iterate; - prev = list->last; - current = list->First(); - next = current ? current->next : nullptr; - cycle_pt = nullptr; // await explicit set - started_cycling = false; - ex_current_was_last = false; - ex_current_was_cycle_pt = false; -} - -/*********************************************************************** - * ELIST_ITERATOR::ELIST_ITERATOR - * - * CONSTRUCTOR - set iterator to specified list; - **********************************************************************/ - -inline ELIST_ITERATOR::ELIST_ITERATOR(ELIST *list_to_iterate) { - set_to_list(list_to_iterate); -} - -/*********************************************************************** - * ELIST_ITERATOR::add_after_then_move - * - * Add a new element to the list after the current element and move the - * iterator to the new element. - **********************************************************************/ - -inline void ELIST_ITERATOR::add_after_then_move( // element to add - ELIST_LINK *new_element) { -#ifndef NDEBUG - if (!list) { - NO_LIST.error("ELIST_ITERATOR::add_after_then_move", ABORT); - } - if (!new_element) { - BAD_PARAMETER.error("ELIST_ITERATOR::add_after_then_move", ABORT, "new_element is nullptr"); - } - if (new_element->next) { - STILL_LINKED.error("ELIST_ITERATOR::add_after_then_move", ABORT); - } -#endif - - if (list->empty()) { - new_element->next = new_element; - list->last = new_element; - prev = next = new_element; - } else { - new_element->next = next; - - if (current) { // not extracted - current->next = new_element; - prev = current; - if (current == list->last) { - list->last = new_element; - } - } else { // current extracted - prev->next = new_element; - if (ex_current_was_last) { - list->last = new_element; - } - if (ex_current_was_cycle_pt) { - cycle_pt = new_element; - } - } - } - current = new_element; -} - -/*********************************************************************** - * ELIST_ITERATOR::add_after_stay_put - * - * Add a new element to the list after the current element but do not move - * the iterator to the new element. - **********************************************************************/ - -inline void ELIST_ITERATOR::add_after_stay_put( // element to add - ELIST_LINK *new_element) { -#ifndef NDEBUG - if (!list) { - NO_LIST.error("ELIST_ITERATOR::add_after_stay_put", ABORT); - } - if (!new_element) { - BAD_PARAMETER.error("ELIST_ITERATOR::add_after_stay_put", ABORT, "new_element is nullptr"); - } - if (new_element->next) { - STILL_LINKED.error("ELIST_ITERATOR::add_after_stay_put", ABORT); - } -#endif - - if (list->empty()) { - new_element->next = new_element; - list->last = new_element; - prev = next = new_element; - ex_current_was_last = false; - current = nullptr; - } else { - new_element->next = next; - - if (current) { // not extracted - current->next = new_element; - if (prev == current) { - prev = new_element; - } - if (current == list->last) { - list->last = new_element; - } - } else { // current extracted - prev->next = new_element; - if (ex_current_was_last) { - list->last = new_element; - ex_current_was_last = false; - } - } - next = new_element; - } -} - -/*********************************************************************** - * ELIST_ITERATOR::add_before_then_move - * - * Add a new element to the list before the current element and move the - * iterator to the new element. - **********************************************************************/ - -inline void ELIST_ITERATOR::add_before_then_move( // element to add - ELIST_LINK *new_element) { -#ifndef NDEBUG - if (!list) { - NO_LIST.error("ELIST_ITERATOR::add_before_then_move", ABORT); - } - if (!new_element) { - BAD_PARAMETER.error("ELIST_ITERATOR::add_before_then_move", ABORT, "new_element is nullptr"); - } - if (new_element->next) { - STILL_LINKED.error("ELIST_ITERATOR::add_before_then_move", ABORT); - } -#endif - - if (list->empty()) { - new_element->next = new_element; - list->last = new_element; - prev = next = new_element; - } else { - prev->next = new_element; - if (current) { // not extracted - new_element->next = current; - next = current; - } else { // current extracted - new_element->next = next; - if (ex_current_was_last) { - list->last = new_element; - } - if (ex_current_was_cycle_pt) { - cycle_pt = new_element; - } - } - } - current = new_element; -} - -/*********************************************************************** - * ELIST_ITERATOR::add_before_stay_put - * - * Add a new element to the list before the current element but don't move the - * iterator to the new element. - **********************************************************************/ - -inline void ELIST_ITERATOR::add_before_stay_put( // element to add - ELIST_LINK *new_element) { -#ifndef NDEBUG - if (!list) { - NO_LIST.error("ELIST_ITERATOR::add_before_stay_put", ABORT); - } - if (!new_element) { - BAD_PARAMETER.error("ELIST_ITERATOR::add_before_stay_put", ABORT, "new_element is nullptr"); - } - if (new_element->next) { - STILL_LINKED.error("ELIST_ITERATOR::add_before_stay_put", ABORT); - } -#endif - - if (list->empty()) { - new_element->next = new_element; - list->last = new_element; - prev = next = new_element; - ex_current_was_last = true; - current = nullptr; - } else { - prev->next = new_element; - if (current) { // not extracted - new_element->next = current; - if (next == current) { - next = new_element; - } - } else { // current extracted - new_element->next = next; - if (ex_current_was_last) { - list->last = new_element; - } - } - prev = new_element; - } -} - -/*********************************************************************** - * ELIST_ITERATOR::add_list_after - * - * Insert another list to this list after the current element but don't move - *the - * iterator. - **********************************************************************/ - -inline void ELIST_ITERATOR::add_list_after(ELIST *list_to_add) { -#ifndef NDEBUG - if (!list) { - NO_LIST.error("ELIST_ITERATOR::add_list_after", ABORT); - } - if (!list_to_add) { - BAD_PARAMETER.error("ELIST_ITERATOR::add_list_after", ABORT, "list_to_add is nullptr"); - } -#endif - - if (!list_to_add->empty()) { - if (list->empty()) { - list->last = list_to_add->last; - prev = list->last; - next = list->First(); - ex_current_was_last = true; - current = nullptr; - } else { - if (current) { // not extracted - current->next = list_to_add->First(); - if (current == list->last) { - list->last = list_to_add->last; - } - list_to_add->last->next = next; - next = current->next; - } else { // current extracted - prev->next = list_to_add->First(); - if (ex_current_was_last) { - list->last = list_to_add->last; - ex_current_was_last = false; - } - list_to_add->last->next = next; - next = prev->next; - } - } - list_to_add->last = nullptr; - } -} - -/*********************************************************************** - * ELIST_ITERATOR::add_list_before - * - * Insert another list to this list before the current element. Move the - * iterator to the start of the inserted elements - * iterator. - **********************************************************************/ - -inline void ELIST_ITERATOR::add_list_before(ELIST *list_to_add) { -#ifndef NDEBUG - if (!list) { - NO_LIST.error("ELIST_ITERATOR::add_list_before", ABORT); - } - if (!list_to_add) { - BAD_PARAMETER.error("ELIST_ITERATOR::add_list_before", ABORT, "list_to_add is nullptr"); - } -#endif - - if (!list_to_add->empty()) { - if (list->empty()) { - list->last = list_to_add->last; - prev = list->last; - current = list->First(); - next = current->next; - ex_current_was_last = false; - } else { - prev->next = list_to_add->First(); - if (current) { // not extracted - list_to_add->last->next = current; - } else { // current extracted - list_to_add->last->next = next; - if (ex_current_was_last) { - list->last = list_to_add->last; - } - if (ex_current_was_cycle_pt) { - cycle_pt = prev->next; - } - } - current = prev->next; - next = current->next; - } - list_to_add->last = nullptr; - } -} - -/*********************************************************************** - * ELIST_ITERATOR::extract - * - * Do extraction by removing current from the list, returning it to the - * caller, but NOT updating the iterator. (So that any calling loop can do - * this.) The iterator's current points to nullptr. If the extracted element - * is to be deleted, this is the callers responsibility. - **********************************************************************/ - -inline ELIST_LINK *ELIST_ITERATOR::extract() { - ELIST_LINK *extracted_link; - -#ifndef NDEBUG - if (!list) { - NO_LIST.error("ELIST_ITERATOR::extract", ABORT); - } - if (!current) { // list empty or - // element extracted - NULL_CURRENT.error("ELIST_ITERATOR::extract", ABORT); - } -#endif - - if (list->singleton()) { - // Special case where we do need to change the iterator. - prev = next = list->last = nullptr; - } else { - prev->next = next; // remove from list - - ex_current_was_last = (current == list->last); - if (ex_current_was_last) { - list->last = prev; - } - } - // Always set ex_current_was_cycle_pt so an add/forward will work in a loop. - ex_current_was_cycle_pt = (current == cycle_pt); - extracted_link = current; - extracted_link->next = nullptr; // for safety - current = nullptr; - return extracted_link; -} - -/*********************************************************************** - * ELIST_ITERATOR::move_to_first() - * - * Move current so that it is set to the start of the list. - * Return data just in case anyone wants it. - **********************************************************************/ - -inline ELIST_LINK *ELIST_ITERATOR::move_to_first() { -#ifndef NDEBUG - if (!list) { - NO_LIST.error("ELIST_ITERATOR::move_to_first", ABORT); - } -#endif - - current = list->First(); - prev = list->last; - next = current ? current->next : nullptr; - return current; -} - -/*********************************************************************** - * ELIST_ITERATOR::mark_cycle_pt() - * - * Remember the current location so that we can tell whether we've returned - * to this point later. - * - * If the current point is deleted either now, or in the future, the cycle - * point will be set to the next item which is set to current. This could be - * by a forward, add_after_then_move or add_after_then_move. - **********************************************************************/ - -inline void ELIST_ITERATOR::mark_cycle_pt() { -#ifndef NDEBUG - if (!list) { - NO_LIST.error("ELIST_ITERATOR::mark_cycle_pt", ABORT); - } -#endif - - if (current) { - cycle_pt = current; - } else { - ex_current_was_cycle_pt = true; - } - started_cycling = false; -} - -/*********************************************************************** - * ELIST_ITERATOR::at_first() - * - * Are we at the start of the list? - * - **********************************************************************/ - -inline bool ELIST_ITERATOR::at_first() const { -#ifndef NDEBUG - if (!list) { - NO_LIST.error("ELIST_ITERATOR::at_first", ABORT); - } -#endif - - // we're at a deleted - return ((list->empty()) || (current == list->First()) || - ((current == nullptr) && (prev == list->last) && // NON-last pt between - !ex_current_was_last)); // first and last -} - -/*********************************************************************** - * ELIST_ITERATOR::at_last() - * - * Are we at the end of the list? - * - **********************************************************************/ - -inline bool ELIST_ITERATOR::at_last() const { -#ifndef NDEBUG - if (!list) { - NO_LIST.error("ELIST_ITERATOR::at_last", ABORT); - } -#endif - - // we're at a deleted - return ((list->empty()) || (current == list->last) || - ((current == nullptr) && (prev == list->last) && // last point between - ex_current_was_last)); // first and last -} - -/*********************************************************************** - * ELIST_ITERATOR::cycled_list() - * - * Have we returned to the cycle_pt since it was set? - * - **********************************************************************/ - -inline bool ELIST_ITERATOR::cycled_list() const { -#ifndef NDEBUG - if (!list) { - NO_LIST.error("ELIST_ITERATOR::cycled_list", ABORT); - } -#endif - - return ((list->empty()) || ((current == cycle_pt) && started_cycling)); -} - -/*********************************************************************** - * ELIST_ITERATOR::sort() - * - * Sort the elements of the list, then reposition at the start. - * - **********************************************************************/ - -inline void ELIST_ITERATOR::sort( // sort elements - int comparator( // comparison routine - const void *, const void *)) { -#ifndef NDEBUG - if (!list) { - NO_LIST.error("ELIST_ITERATOR::sort", ABORT); - } -#endif - - list->sort(comparator); - move_to_first(); -} - -/*********************************************************************** - * ELIST_ITERATOR::add_to_end - * - * Add a new element to the end of the list without moving the iterator. - * This is provided because a single linked list cannot move to the last as - * the iterator couldn't set its prev pointer. Adding to the end is - * essential for implementing - queues. -**********************************************************************/ - -inline void ELIST_ITERATOR::add_to_end( // element to add - ELIST_LINK *new_element) { -#ifndef NDEBUG - if (!list) { - NO_LIST.error("ELIST_ITERATOR::add_to_end", ABORT); - } - if (!new_element) { - BAD_PARAMETER.error("ELIST_ITERATOR::add_to_end", ABORT, "new_element is nullptr"); - } - if (new_element->next) { - STILL_LINKED.error("ELIST_ITERATOR::add_to_end", ABORT); - } -#endif - - if (this->at_last()) { - this->add_after_stay_put(new_element); - } else { - if (this->at_first()) { - this->add_before_stay_put(new_element); - list->last = new_element; - } else { // Iteratr is elsewhere - new_element->next = list->last->next; - list->last->next = new_element; - list->last = new_element; - } - } -} - -#define ELISTIZEH(CLASSNAME) \ - class CLASSNAME##_LIST : public X_LIST { \ - using X_LIST::X_LIST; \ - }; \ - class CLASSNAME##_IT : public X_ITER { \ - using X_ITER::X_ITER; \ +// add TESS_API? +// move templated lists to public include dirs? +#define ELISTIZEH(CLASSNAME) \ + struct CLASSNAME##_LIST : ELIST { \ + using ELIST::ELIST; \ + }; \ + struct CLASSNAME##_IT : ELIST::ITERATOR { \ + using base = ELIST::ITERATOR; \ + using base::base; \ }; } // namespace tesseract diff --git a/src/classify/trainingsample.h b/src/classify/trainingsample.h index 5e4a943a..211ab669 100644 --- a/src/classify/trainingsample.h +++ b/src/classify/trainingsample.h @@ -51,7 +51,7 @@ static const int kSampleScaleSize = 3; static const int kSampleRandomSize = kSampleYShiftSize * kSampleScaleSize - 2; // ASSERT_IS_PRIME(kSampleRandomSize) !! -class TESS_API TrainingSample : public ELIST_LINK { +class TESS_API TrainingSample : public ELIST::LINK { public: TrainingSample() : class_id_(INVALID_UNICHAR_ID) diff --git a/src/textord/blkocc.h b/src/textord/blkocc.h index 449cddbb..e8d5a1bb 100644 --- a/src/textord/blkocc.h +++ b/src/textord/blkocc.h @@ -44,7 +44,7 @@ CLASS REGION_OCC ****************************************************************************/ -class REGION_OCC : public ELIST_LINK { +class REGION_OCC : public ELIST::LINK { public: float min_x; // Lowest x in region float max_x; // Highest x in region diff --git a/src/textord/colpartitionset.h b/src/textord/colpartitionset.h index 60a78297..53b04177 100644 --- a/src/textord/colpartitionset.h +++ b/src/textord/colpartitionset.h @@ -35,7 +35,7 @@ using PartSetVector = std::vector; // Its main use is in holding a candidate partitioning of the width of the // image into columns, where each member ColPartition is a single column. // ColPartitionSets are used in building the column layout of a page. -class ColPartitionSet : public ELIST_LINK { +class ColPartitionSet : public ELIST::LINK { public: ColPartitionSet() = default; explicit ColPartitionSet(ColPartition_LIST *partitions); diff --git a/src/textord/fpchop.h b/src/textord/fpchop.h index 13f4c10a..2e8ec39f 100644 --- a/src/textord/fpchop.h +++ b/src/textord/fpchop.h @@ -24,7 +24,7 @@ namespace tesseract { -class C_OUTLINE_FRAG : public ELIST_LINK { +class C_OUTLINE_FRAG : public ELIST::LINK { public: C_OUTLINE_FRAG() { // empty constructor steps = nullptr; diff --git a/src/textord/pitsync1.h b/src/textord/pitsync1.h index 5df7ec48..d81512d6 100644 --- a/src/textord/pitsync1.h +++ b/src/textord/pitsync1.h @@ -31,7 +31,7 @@ namespace tesseract { class FPSEGPT_LIST; -class FPSEGPT : public ELIST_LINK { +class FPSEGPT : public ELIST::LINK { public: FPSEGPT() = default; FPSEGPT( // constructor diff --git a/src/textord/sortflts.h b/src/textord/sortflts.h index 278d8f90..8c1755b1 100644 --- a/src/textord/sortflts.h +++ b/src/textord/sortflts.h @@ -23,7 +23,7 @@ namespace tesseract { -class SORTED_FLOAT : public ELIST_LINK { +class SORTED_FLOAT : public ELIST::LINK { friend class SORTED_FLOATS; public: diff --git a/src/textord/tablefind.cpp b/src/textord/tablefind.cpp index 537bec9c..46ce4fa4 100644 --- a/src/textord/tablefind.cpp +++ b/src/textord/tablefind.cpp @@ -2099,7 +2099,7 @@ void TableFinder::MakeTableBlocks(ColPartitionGrid *grid, //////// ColSegment code //////// ColSegment::ColSegment() - : ELIST_LINK(), + : ELIST::LINK(), num_table_cells_(0), num_text_cells_(0), type_(COL_UNKNOWN) {} diff --git a/src/textord/tablefind.h b/src/textord/tablefind.h index 2554afdb..378b71a2 100644 --- a/src/textord/tablefind.h +++ b/src/textord/tablefind.h @@ -36,7 +36,7 @@ class ColSegment; ELISTIZEH(ColSegment) CLISTIZEH(ColSegment) -class ColSegment : public ELIST_LINK { +class ColSegment : public ELIST::LINK { public: ColSegment(); ~ColSegment() = default; diff --git a/src/textord/tabvector.h b/src/textord/tabvector.h index 2c48d721..f23fd602 100644 --- a/src/textord/tabvector.h +++ b/src/textord/tabvector.h @@ -64,7 +64,7 @@ ELISTIZEH(TabConstraint) // on a list of constraints. The list itself is cooperatively owned // by the TabVectors of the constraints on the list and managed // by implicit reference counting via the elements of the list. -class TabConstraint : public ELIST_LINK { +class TabConstraint : public ELIST::LINK { public: // This empty constructor is here only so that the class can be ELISTIZED. // TODO(rays) change deep_copy in elst.h line 955 to take a callback copier diff --git a/src/textord/workingpartset.h b/src/textord/workingpartset.h index f0292696..ee092dec 100644 --- a/src/textord/workingpartset.h +++ b/src/textord/workingpartset.h @@ -29,7 +29,7 @@ namespace tesseract { // WorkingPartSet holds a working set of ColPartitions during transformation // from the grid-based storage to regions in logical reading order, and is // therefore only used during construction of the regions. -class WorkingPartSet : public ELIST_LINK { +class WorkingPartSet : public ELIST::LINK { public: explicit WorkingPartSet(ColPartition *column) : column_(column), latest_part_(nullptr), part_it_(&part_set_) {} diff --git a/src/wordrec/lm_state.h b/src/wordrec/lm_state.h index 14f343e4..0176a253 100644 --- a/src/wordrec/lm_state.h +++ b/src/wordrec/lm_state.h @@ -89,7 +89,7 @@ struct LanguageModelNgramInfo { /// Struct for storing the information about a path in the segmentation graph /// explored by Viterbi search. -struct ViterbiStateEntry : public ELIST_LINK { +struct ViterbiStateEntry : public ELIST::LINK { ViterbiStateEntry(ViterbiStateEntry *pe, BLOB_CHOICE *b, float c, float ol, const LMConsistencyInfo &ci, const AssociateStats &as, LanguageModelFlagsType tcf, LanguageModelDawgInfo *d, LanguageModelNgramInfo *n, diff --git a/src/wordrec/wordrec.h b/src/wordrec/wordrec.h index 20bdbcf9..f57d6fe9 100644 --- a/src/wordrec/wordrec.h +++ b/src/wordrec/wordrec.h @@ -169,7 +169,7 @@ private: }; /* ccmain/tstruct.cpp *********************************************************/ -class FRAGMENT : public ELIST_LINK { +class FRAGMENT : public ELIST::LINK { public: FRAGMENT() { // constructor } diff --git a/unittest/list_test.cc b/unittest/list_test.cc index cfdae00e..0ba8c3af 100644 --- a/unittest/list_test.cc +++ b/unittest/list_test.cc @@ -31,7 +31,7 @@ public: unsigned value; }; -class Elst : public ELIST_LINK { +class Elst : public ELIST::LINK { public: Elst(unsigned n) : value(n) {} unsigned value; @@ -82,7 +82,7 @@ TEST_F(ListTest, TestELIST) { Elst_LIST list; EXPECT_TRUE(list.empty()); EXPECT_EQ(list.length(), 0); - auto it = ELIST_ITERATOR(&list); + auto it = ELIST::ITERATOR(&list); for (unsigned i = 0; i < ListSize; i++) { auto *elst = new Elst(i); it.add_to_end(elst);