Convert ELIST into template.

This commit is contained in:
Egor Pugin 2024-11-22 17:54:40 +03:00
parent ffb33795a8
commit 4991295a39
31 changed files with 1031 additions and 1162 deletions

View File

@ -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<ParamContent>::LINK {
public:
// Compare two VC objects by their name.
static int Compare(const void *v1, const void *v2);

View File

@ -138,7 +138,7 @@ class ColPartition;
class BLOBNBOX;
ELISTIZEH(BLOBNBOX)
class BLOBNBOX : public ELIST_LINK {
class BLOBNBOX : public ELIST<BLOBNBOX>::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<TO_BLOCK>::LINK {
public:
TO_BLOCK() : pitch_decision(PITCH_DUNNO) {
clear();

View File

@ -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<C_OUTLINE>::LINK {
public:
C_OUTLINE() {
stepcount = 0;

View File

@ -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<BLOCK>::LINK::operator=(source);
pdblk = source.pdblk;
proportional = source.proportional;
kerning = source.kerning;

View File

@ -29,7 +29,7 @@ class BLOCK; // forward decl
ELISTIZEH(BLOCK)
class TESS_API BLOCK : public ELIST_LINK
class TESS_API BLOCK : public ELIST<BLOCK>::LINK
// page block
{
friend class BLOCK_RECT_IT; // block iterator

View File

@ -27,7 +27,7 @@ namespace tesseract {
class ParagraphModel;
struct PARA : public ELIST_LINK {
struct PARA : public ELIST<PARA>::LINK {
public:
PARA()
: model(nullptr)

View File

@ -223,7 +223,7 @@ void ROW::plot( // draw it
**********************************************************************/
ROW &ROW::operator=(const ROW &source) {
this->ELIST_LINK::operator=(source);
this->ELIST<ROW>::LINK::operator=(source);
kerning = source.kerning;
spacing = source.spacing;
xheight = source.xheight;

View File

@ -36,7 +36,7 @@ class TO_ROW;
struct PARA;
class ROW : public ELIST_LINK {
class ROW : public ELIST<ROW>::LINK {
friend void tweak_row_baseline(ROW *, double, double);
public:

View File

@ -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<WERD_RES>::LINK::operator=(source);
Clear();
if (source.combination) {
word = new WERD;

View File

@ -115,7 +115,7 @@ public:
* BLOCK_RES - Block results
*************************************************************************/
class BLOCK_RES : public ELIST_LINK {
class BLOCK_RES : public ELIST<BLOCK_RES>::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<ROW_RES>::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<WERD_RES>::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<WERD_RES>::LINK(source) {
// combination is used in function Clear which is called from operator=.
combination = false;
*this = source; // see operator=

View File

@ -160,7 +160,7 @@ protected:
TDimension ycoord; ///< y value
};
class ICOORDELT : public ELIST_LINK,
class ICOORDELT : public ELIST<ICOORDELT>::LINK,
public ICOORD
// embedded coord list
{

View File

@ -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<BLOB_CHOICE>::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<BLOB_CHOICE>::LINK::operator=(other);
unichar_id_ = other.unichar_id();
rating_ = other.rating();
certainty_ = other.certainty();

View File

@ -53,7 +53,7 @@ enum BlobChoiceClassifier {
BCC_FAKE, // From some other process.
};
class BLOB_CHOICE : public ELIST_LINK {
class BLOB_CHOICE : public ELIST<BLOB_CHOICE>::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<WERD_CHOICE>::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<WERD_CHOICE>::LINK(word), unicharset_(word.unicharset_) {
this->init(word.length());
this->operator=(word);
}

View File

@ -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<C_BLOB>::LINK {
public:
C_BLOB() = default;
explicit C_BLOB(C_OUTLINE_LIST *outline_list);

View File

@ -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<AmbigSpec>::LINK {
public:
AmbigSpec();
~AmbigSpec() = default;

View File

@ -34,7 +34,7 @@ namespace tesseract {
**********************************************************************/
template <typename CLASSNAME>
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

View File

@ -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 <cstdlib>
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<ELIST_LINK *> 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<void *>(this),
static_cast<void *>(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

File diff suppressed because it is too large Load Diff

View File

@ -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<TrainingSample>::LINK {
public:
TrainingSample()
: class_id_(INVALID_UNICHAR_ID)

View File

@ -44,7 +44,7 @@ CLASS REGION_OCC
****************************************************************************/
class REGION_OCC : public ELIST_LINK {
class REGION_OCC : public ELIST<REGION_OCC>::LINK {
public:
float min_x; // Lowest x in region
float max_x; // Highest x in region

View File

@ -35,7 +35,7 @@ using PartSetVector = std::vector<ColPartitionSet *>;
// 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<ColPartitionSet>::LINK {
public:
ColPartitionSet() = default;
explicit ColPartitionSet(ColPartition_LIST *partitions);

View File

@ -24,7 +24,7 @@
namespace tesseract {
class C_OUTLINE_FRAG : public ELIST_LINK {
class C_OUTLINE_FRAG : public ELIST<C_OUTLINE_FRAG>::LINK {
public:
C_OUTLINE_FRAG() { // empty constructor
steps = nullptr;

View File

@ -31,7 +31,7 @@ namespace tesseract {
class FPSEGPT_LIST;
class FPSEGPT : public ELIST_LINK {
class FPSEGPT : public ELIST<FPSEGPT>::LINK {
public:
FPSEGPT() = default;
FPSEGPT( // constructor

View File

@ -23,7 +23,7 @@
namespace tesseract {
class SORTED_FLOAT : public ELIST_LINK {
class SORTED_FLOAT : public ELIST<SORTED_FLOAT>::LINK {
friend class SORTED_FLOATS;
public:

View File

@ -2099,7 +2099,7 @@ void TableFinder::MakeTableBlocks(ColPartitionGrid *grid,
//////// ColSegment code
////////
ColSegment::ColSegment()
: ELIST_LINK(),
: ELIST<ColSegment>::LINK(),
num_table_cells_(0),
num_text_cells_(0),
type_(COL_UNKNOWN) {}

View File

@ -36,7 +36,7 @@ class ColSegment;
ELISTIZEH(ColSegment)
CLISTIZEH(ColSegment)
class ColSegment : public ELIST_LINK {
class ColSegment : public ELIST<ColSegment>::LINK {
public:
ColSegment();
~ColSegment() = default;

View File

@ -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<TabConstraint>::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

View File

@ -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<WorkingPartSet>::LINK {
public:
explicit WorkingPartSet(ColPartition *column)
: column_(column), latest_part_(nullptr), part_it_(&part_set_) {}

View File

@ -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<ViterbiStateEntry>::LINK {
ViterbiStateEntry(ViterbiStateEntry *pe, BLOB_CHOICE *b, float c, float ol,
const LMConsistencyInfo &ci, const AssociateStats &as,
LanguageModelFlagsType tcf, LanguageModelDawgInfo *d, LanguageModelNgramInfo *n,

View File

@ -169,7 +169,7 @@ private:
};
/* ccmain/tstruct.cpp *********************************************************/
class FRAGMENT : public ELIST_LINK {
class FRAGMENT : public ELIST<FRAGMENT>::LINK {
public:
FRAGMENT() { // constructor
}

View File

@ -31,7 +31,7 @@ public:
unsigned value;
};
class Elst : public ELIST_LINK {
class Elst : public ELIST<Elst>::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<Elst>::ITERATOR(&list);
for (unsigned i = 0; i < ListSize; i++) {
auto *elst = new Elst(i);
it.add_to_end(elst);