mirror of
https://github.com/tesseract-ocr/tesseract.git
synced 2024-11-23 18:49:08 +08:00
Convert ELIST into template.
This commit is contained in:
parent
ffb33795a8
commit
4991295a39
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -27,7 +27,7 @@ namespace tesseract {
|
||||
|
||||
class ParagraphModel;
|
||||
|
||||
struct PARA : public ELIST_LINK {
|
||||
struct PARA : public ELIST<PARA>::LINK {
|
||||
public:
|
||||
PARA()
|
||||
: model(nullptr)
|
||||
|
@ -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;
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
@ -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=
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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) {}
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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_) {}
|
||||
|
@ -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,
|
||||
|
@ -169,7 +169,7 @@ private:
|
||||
};
|
||||
|
||||
/* ccmain/tstruct.cpp *********************************************************/
|
||||
class FRAGMENT : public ELIST_LINK {
|
||||
class FRAGMENT : public ELIST<FRAGMENT>::LINK {
|
||||
public:
|
||||
FRAGMENT() { // constructor
|
||||
}
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user