Commit 03435adc for tesseract
commit 03435adca0634806661e09e8ceb2a03a1a43970f
Author: Egor Pugin <egor.pugin@gmail.com>
Date: Wed Apr 7 00:04:30 2021 +0300
[elist] Rework macro into template and small macro. Move common iterator template into 'list_iterator.h'.
diff --git a/src/ccmain/paramsd.cpp b/src/ccmain/paramsd.cpp
index 8d5cd20d..38d0d5cb 100644
--- a/src/ccmain/paramsd.cpp
+++ b/src/ccmain/paramsd.cpp
@@ -54,8 +54,6 @@ static std::map<int, ParamContent *> vcMap;
static int nrParams = 0;
static int writeCommands[2];
-ELISTIZE(ParamContent)
-
// Constructors for the various ParamTypes.
ParamContent::ParamContent(tesseract::StringParam *it) {
my_id_ = nrParams;
diff --git a/src/ccstruct/blobbox.cpp b/src/ccstruct/blobbox.cpp
index d66b7bea..83bb7253 100644
--- a/src/ccstruct/blobbox.cpp
+++ b/src/ccstruct/blobbox.cpp
@@ -39,9 +39,7 @@
namespace tesseract {
-ELISTIZE(BLOBNBOX)
ELIST2IZE(TO_ROW)
-ELISTIZE(TO_BLOCK)
// Up to 30 degrees is allowed for rotations of diacritic blobs.
const double kCosSmallAngle = 0.866;
diff --git a/src/ccstruct/blobbox.h b/src/ccstruct/blobbox.h
index b5ba7557..56a288fe 100644
--- a/src/ccstruct/blobbox.h
+++ b/src/ccstruct/blobbox.h
@@ -677,7 +677,7 @@ private:
};
ELIST2IZEH(TO_ROW)
-class 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.cpp b/src/ccstruct/coutln.cpp
index e9d26ffe..1a5eb5c0 100644
--- a/src/ccstruct/coutln.cpp
+++ b/src/ccstruct/coutln.cpp
@@ -42,7 +42,6 @@
namespace tesseract {
-ELISTIZE(C_OUTLINE)
ICOORD C_OUTLINE::step_coords[4] = {ICOORD(-1, 0), ICOORD(0, -1), ICOORD(1, 0), ICOORD(0, 1)};
/**
diff --git a/src/ccstruct/ocrblock.cpp b/src/ccstruct/ocrblock.cpp
index f03b8c77..8a7fa6fa 100644
--- a/src/ccstruct/ocrblock.cpp
+++ b/src/ccstruct/ocrblock.cpp
@@ -26,7 +26,6 @@
namespace tesseract {
-ELISTIZE(BLOCK)
/**
* BLOCK::BLOCK
*
diff --git a/src/ccstruct/ocrpara.cpp b/src/ccstruct/ocrpara.cpp
index 40f757b4..dda72db1 100644
--- a/src/ccstruct/ocrpara.cpp
+++ b/src/ccstruct/ocrpara.cpp
@@ -24,8 +24,6 @@
namespace tesseract {
-ELISTIZE(PARA)
-
using tesseract::JUSTIFICATION_CENTER;
using tesseract::JUSTIFICATION_LEFT;
using tesseract::JUSTIFICATION_RIGHT;
diff --git a/src/ccstruct/ocrrow.cpp b/src/ccstruct/ocrrow.cpp
index 80c7d170..f02f0749 100644
--- a/src/ccstruct/ocrrow.cpp
+++ b/src/ccstruct/ocrrow.cpp
@@ -26,7 +26,6 @@
namespace tesseract {
-ELISTIZE(ROW)
/**********************************************************************
* ROW::ROW
*
diff --git a/src/ccstruct/pageres.cpp b/src/ccstruct/pageres.cpp
index 88c9a3c4..534088fc 100644
--- a/src/ccstruct/pageres.cpp
+++ b/src/ccstruct/pageres.cpp
@@ -45,10 +45,6 @@ struct Pix;
namespace tesseract {
-ELISTIZE(BLOCK_RES)
-ELISTIZE(ROW_RES)
-ELISTIZE(WERD_RES)
-
// Gain factor for computing thresholds that determine the ambiguity of a
// word.
static const double kStopperAmbiguityThresholdGain = 8.0;
diff --git a/src/ccstruct/points.cpp b/src/ccstruct/points.cpp
index 03654c4c..1e0375e7 100644
--- a/src/ccstruct/points.cpp
+++ b/src/ccstruct/points.cpp
@@ -29,7 +29,6 @@
namespace tesseract {
-ELISTIZE(ICOORDELT) // turn to list
bool FCOORD::normalise() { // Convert to unit vec
float len = length();
diff --git a/src/ccstruct/ratngs.cpp b/src/ccstruct/ratngs.cpp
index 4b4997c9..5801cd9b 100644
--- a/src/ccstruct/ratngs.cpp
+++ b/src/ccstruct/ratngs.cpp
@@ -33,9 +33,6 @@
namespace tesseract {
-ELISTIZE(BLOB_CHOICE)
-ELISTIZE(WERD_CHOICE)
-
const float WERD_CHOICE::kBadRating = 100000.0;
// Min offset in baseline-normalized coords to make a character a subscript.
const int kMinSubscriptOffset = 20;
diff --git a/src/ccstruct/stepblob.cpp b/src/ccstruct/stepblob.cpp
index 13051337..513619d7 100644
--- a/src/ccstruct/stepblob.cpp
+++ b/src/ccstruct/stepblob.cpp
@@ -35,7 +35,6 @@ class DENORM;
// Max perimeter to width ratio for a baseline position above box bottom.
const double kMaxPerimeterWidthRatio = 8.0;
-ELISTIZE(C_BLOB)
/**********************************************************************
* position_outline
*
diff --git a/src/ccutil/ambigs.cpp b/src/ccutil/ambigs.cpp
index c118822d..a4dcd242 100644
--- a/src/ccutil/ambigs.cpp
+++ b/src/ccutil/ambigs.cpp
@@ -47,8 +47,6 @@ AmbigSpec::AmbigSpec() {
wrong_ngram_size = 0;
}
-ELISTIZE(AmbigSpec)
-
// Initializes the ambigs by adding a nullptr pointer to each table.
void UnicharAmbigs::InitUnicharAmbigs(const UNICHARSET &unicharset, bool use_ambigs_for_adaption) {
for (int i = 0; i < unicharset.size(); ++i) {
diff --git a/src/ccutil/clst.h b/src/ccutil/clst.h
index 2d057447..b216f878 100644
--- a/src/ccutil/clst.h
+++ b/src/ccutil/clst.h
@@ -19,6 +19,7 @@
#ifndef CLST_H
#define CLST_H
+#include "list_iterator.h"
#include "lsterr.h"
#include "serialis.h"
@@ -703,38 +704,15 @@ public:
}
};
-template <typename CLASSNAME>
-class X_C_IT : public CLIST_ITERATOR {
-public:
- X_C_IT() = default;
-protected:
- template <typename U>
- X_C_IT(U *list) : CLIST_ITERATOR(list) {}
-
-public:
- CLASSNAME *data() {
- return static_cast<CLASSNAME *>(CLIST_ITERATOR::data());
- }
- CLASSNAME *data_relative(int8_t offset) {
- return static_cast<CLASSNAME *>(CLIST_ITERATOR::data_relative(offset));
- }
- CLASSNAME *forward() {
- return static_cast<CLASSNAME *>(CLIST_ITERATOR::forward());
- }
- CLASSNAME *extract() {
- return static_cast<CLASSNAME *>(CLIST_ITERATOR::extract());
- }
-};
-
-#define CLISTIZEH(CLASSNAME) \
- class CLASSNAME##_CLIST : public X_CLIST<CLASSNAME> { \
- public: \
- using X_CLIST<CLASSNAME>::X_CLIST; \
- }; \
- class CLASSNAME##_C_IT : public X_C_IT<CLASSNAME> { \
- public: \
- using X_C_IT<CLASSNAME>::X_C_IT; \
- CLASSNAME##_C_IT(CLASSNAME##_CLIST *list) : X_C_IT(list) {} \
+#define CLISTIZEH(CLASSNAME) \
+ class CLASSNAME##_CLIST : public X_CLIST<CLASSNAME> { \
+ public: \
+ using X_CLIST<CLASSNAME>::X_CLIST; \
+ }; \
+ class CLASSNAME##_C_IT : public X_ITER<CLIST_ITERATOR, CLASSNAME> { \
+ public: \
+ using X_ITER<CLIST_ITERATOR, CLASSNAME>::X_ITER; \
+ CLASSNAME##_C_IT(CLASSNAME##_CLIST *list) : X_ITER(list) {} \
};
} // namespace tesseract
diff --git a/src/ccutil/elst.h b/src/ccutil/elst.h
index ba6f3787..6f4bf28b 100644
--- a/src/ccutil/elst.h
+++ b/src/ccutil/elst.h
@@ -19,6 +19,7 @@
#ifndef ELST_H
#define ELST_H
+#include "list_iterator.h"
#include "lsterr.h"
#include "serialis.h"
@@ -804,142 +805,45 @@ inline void ELIST_ITERATOR::add_to_end( // element to add
}
}
-/***********************************************************************
- ******************** MACROS **************************************
- ***********************************************************************/
-
-/***********************************************************************
- ELISTIZE(CLASSNAME) MACRO
- ============================
-
-CLASSNAME is assumed to be the name of a class which has a baseclass of
-ELIST_LINK.
+template <typename CLASSNAME>
+class X_LIST : public ELIST {
+public:
+ X_LIST() = default;
+ X_LIST(const X_LIST &) = delete;
+ X_LIST &operator=(const X_LIST &) = delete;
+ ~X_LIST() {
+ clear();
+ }
-NOTE: Because we don't use virtual functions in the list code, the list code
-will NOT work correctly for classes derived from this.
+ /* delete elements */
+ void clear() {
+ ELIST::internal_clear([](ELIST_LINK *link) {delete reinterpret_cast<CLASSNAME *>(link);});
+ }
-The macros generate:
- - An element deletion function: CLASSNAME##_zapper
- - An E_LIST subclass: CLASSNAME##_LIST
- - An E_LIST_ITERATOR subclass: CLASSNAME##_IT
+ /* Become a deep copy of src_list */
+ template <typename U>
+ void deep_copy(const U *src_list, CLASSNAME *(*copier)(const CLASSNAME *)) {
+ static_assert(std::is_base_of_v<X_LIST, U>);
-NOTE: Generated names are DELIBERATELY designed to clash with those for
-ELIST2IZE but NOT with those for CLISTIZE.
+ X_ITER<ELIST_ITERATOR, CLASSNAME> from_it(const_cast<U *>(src_list));
+ X_ITER<ELIST_ITERATOR, CLASSNAME> to_it(this);
-Two macros are provided: ELISTIZE and ELISTIZEH.
-The ...IZEH macros just define the class names for use in .h files
-The ...IZE macros define the code use in .c files
-***********************************************************************/
+ for (from_it.mark_cycle_pt(); !from_it.cycled_list(); from_it.forward())
+ to_it.add_after_then_move((*copier)(from_it.data()));
+ }
+};
-/***********************************************************************
- ELISTIZEH(CLASSNAME) MACRO
-
-ELISTIZEH is a concatenation of 3 fragments ELISTIZEH_A, ELISTIZEH_B and
-ELISTIZEH_C.
-***********************************************************************/
-
-#define ELISTIZEH_A(CLASSNAME) TESS_API extern void CLASSNAME##_zapper(ELIST_LINK *link);
-
-#define ELISTIZEH_B(CLASSNAME) \
- \
- /*********************************************************************** \
- * CLASS - CLASSNAME##_LIST \
- * \
- * List class for class CLASSNAME \
- * \
- **********************************************************************/ \
- \
- class CLASSNAME##_LIST : public ELIST { \
- public: \
- CLASSNAME##_LIST() : ELIST() {} \
- \
- void clear() { /* delete elements */ \
- ELIST::internal_clear(&CLASSNAME##_zapper); \
- } \
- \
- ~CLASSNAME##_LIST() { \
- clear(); \
- } \
- \
- /* Become a deep copy of src_list*/ \
- void deep_copy(const CLASSNAME##_LIST *src_list, CLASSNAME *(*copier)(const CLASSNAME *)); \
- \
- /* Prevent assign and copy construction. */ \
- CLASSNAME##_LIST(const CLASSNAME##_LIST &) = delete; \
- void operator=(const CLASSNAME##_LIST &) = delete; \
-
-#define ELISTIZEH_C(CLASSNAME) \
- } \
- ; \
- \
- /*********************************************************************** \
- * CLASS - CLASSNAME##_IT \
- * \
- * Iterator class for class CLASSNAME##_LIST \
- * \
- * Note: We don't need to coerce pointers to member functions input \
- * parameters as these are automatically converted to the type of the base \
- * type. ("A ptr to a class may be converted to a pointer to a public base \
- * class of that class") \
- **********************************************************************/ \
- \
- class CLASSNAME##_IT : public ELIST_ITERATOR { \
- public: \
- CLASSNAME##_IT() : ELIST_ITERATOR() {} \
- \
- /* TODO(rays) This constructor should be explicit, but that means changing \
- hundreds of incorrect initializations of iterators that use = over () \
- */ \
- CLASSNAME##_IT(CLASSNAME##_LIST *list) : ELIST_ITERATOR(list) {} \
- \
- CLASSNAME *data() { \
- return reinterpret_cast<CLASSNAME *>(ELIST_ITERATOR::data()); \
- } \
- CLASSNAME *data_relative(int8_t offset) { \
- return reinterpret_cast<CLASSNAME *>(ELIST_ITERATOR::data_relative(offset)); \
- } \
- CLASSNAME *forward() { \
- return reinterpret_cast<CLASSNAME *>(ELIST_ITERATOR::forward()); \
- } \
- CLASSNAME *extract() { \
- return reinterpret_cast<CLASSNAME *>(ELIST_ITERATOR::extract()); \
- } \
+#define ELISTIZEH(CLASSNAME) \
+ class CLASSNAME##_LIST : public X_LIST<CLASSNAME> { \
+ public: \
+ using X_LIST<CLASSNAME>::X_LIST; \
+ }; \
+ class CLASSNAME##_IT : public X_ITER<ELIST_ITERATOR, CLASSNAME> { \
+ public: \
+ using X_ITER<ELIST_ITERATOR, CLASSNAME>::X_ITER; \
+ CLASSNAME##_IT(CLASSNAME##_LIST *list) : X_ITER(list) {} \
};
-#define ELISTIZEH(CLASSNAME) \
- ELISTIZEH_A(CLASSNAME) \
- ELISTIZEH_B(CLASSNAME) \
- ELISTIZEH_C(CLASSNAME)
-
-/***********************************************************************
- ELISTIZE(CLASSNAME) MACRO
-***********************************************************************/
-
-#define ELISTIZE(CLASSNAME) \
- \
- /*********************************************************************** \
- * CLASSNAME##_zapper \
- * \
- * A function which can delete a CLASSNAME element. This is passed to the \
- * generic clear list member function so that when a list is cleared the \
- * elements on the list are properly destroyed from the base class, even \
- * though we don't use a virtual destructor function. \
- **********************************************************************/ \
- \
- void CLASSNAME##_zapper(ELIST_LINK *link) { \
- delete reinterpret_cast<CLASSNAME *>(link); \
- } \
- \
- /* Become a deep copy of src_list*/ \
- void CLASSNAME##_LIST::deep_copy(const CLASSNAME##_LIST *src_list, \
- CLASSNAME *(*copier)(const CLASSNAME *)) { \
- CLASSNAME##_IT from_it(const_cast<CLASSNAME##_LIST *>(src_list)); \
- CLASSNAME##_IT 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())); \
- }
-
} // namespace tesseract
#endif
diff --git a/src/ccutil/list_iterator.h b/src/ccutil/list_iterator.h
new file mode 100644
index 00000000..c419ed20
--- /dev/null
+++ b/src/ccutil/list_iterator.h
@@ -0,0 +1,44 @@
+/**********************************************************************
+ ** 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.
+ *
+ **********************************************************************/
+
+#ifndef LIST_ITERATOR_H
+#define LIST_ITERATOR_H
+
+#include <stdint.h>
+
+namespace tesseract {
+
+template <typename CONTAINER, typename CLASSNAME>
+class X_ITER : public CONTAINER {
+public:
+ X_ITER() = default;
+ template <typename U>
+ X_ITER(U *list) : CONTAINER(list) {}
+
+ CLASSNAME *data() {
+ return static_cast<CLASSNAME *>(CONTAINER::data());
+ }
+ CLASSNAME *data_relative(int8_t offset) {
+ return static_cast<CLASSNAME *>(CONTAINER::data_relative(offset));
+ }
+ CLASSNAME *forward() {
+ return static_cast<CLASSNAME *>(CONTAINER::forward());
+ }
+ CLASSNAME *extract() {
+ return static_cast<CLASSNAME *>(CONTAINER::extract());
+ }
+};
+
+} // namespace tesseract
+
+#endif
diff --git a/src/classify/trainingsample.cpp b/src/classify/trainingsample.cpp
index d4307a2e..ccbb84aa 100644
--- a/src/classify/trainingsample.cpp
+++ b/src/classify/trainingsample.cpp
@@ -32,8 +32,6 @@
namespace tesseract {
-ELISTIZE(TrainingSample)
-
// Center of randomizing operations.
const int kRandomizingCenter = 128;
diff --git a/src/textord/colpartitionset.cpp b/src/textord/colpartitionset.cpp
index 4a89c989..1252c2ae 100644
--- a/src/textord/colpartitionset.cpp
+++ b/src/textord/colpartitionset.cpp
@@ -30,8 +30,6 @@ namespace tesseract {
// Minimum width of a column to be interesting as a multiple of resolution.
const double kMinColumnWidth = 2.0 / 3;
-ELISTIZE(ColPartitionSet)
-
ColPartitionSet::ColPartitionSet(ColPartition_LIST *partitions) {
ColPartition_IT it(&parts_);
it.add_list_after(partitions);
diff --git a/src/textord/fpchop.cpp b/src/textord/fpchop.cpp
index 3e0adbd7..faee5f02 100644
--- a/src/textord/fpchop.cpp
+++ b/src/textord/fpchop.cpp
@@ -34,8 +34,6 @@ namespace tesseract {
INT_VAR(textord_fp_chop_error, 2, "Max allowed bending of chop cells");
double_VAR(textord_fp_chop_snap, 0.5, "Max distance of chop pt from vertex");
-ELISTIZE(C_OUTLINE_FRAG)
-
static WERD *add_repeated_word(WERD_IT *rep_it, int16_t &rep_left, int16_t &prev_chop_coord,
uint8_t &blanks, float pitch, WERD_IT *word_it);
diff --git a/src/textord/pitsync1.cpp b/src/textord/pitsync1.cpp
index 8f2ecadc..415d29ca 100644
--- a/src/textord/pitsync1.cpp
+++ b/src/textord/pitsync1.cpp
@@ -23,8 +23,6 @@
namespace tesseract {
-ELISTIZE(FPSEGPT)
-
INT_VAR(pitsync_linear_version, 6, "Use new fast algorithm");
double_VAR(pitsync_joined_edge, 0.75, "Dist inside big blob for chopping");
double_VAR(pitsync_offset_freecut_fraction, 0.25, "Fraction of cut for free cuts");
diff --git a/src/textord/sortflts.cpp b/src/textord/sortflts.cpp
index 0ea74839..edf9c34c 100644
--- a/src/textord/sortflts.cpp
+++ b/src/textord/sortflts.cpp
@@ -20,7 +20,6 @@
namespace tesseract {
-ELISTIZE(SORTED_FLOAT)
/**
* @name SORTED_FLOATS::add
*
diff --git a/src/textord/tablefind.cpp b/src/textord/tablefind.cpp
index ea4cd7f5..2b4fb9d0 100644
--- a/src/textord/tablefind.cpp
+++ b/src/textord/tablefind.cpp
@@ -150,8 +150,6 @@ static BOOL_VAR(textord_tablefind_show_stats, false,
static BOOL_VAR(textord_tablefind_recognize_tables, false,
"Enables the table recognizer for table layout and filtering.");
-ELISTIZE(ColSegment)
-
// Templated helper function used to create destructor callbacks for the
// BBGrid::ClearGridData() method.
template <typename T>
diff --git a/src/textord/tabvector.cpp b/src/textord/tabvector.cpp
index c5a9b43a..bc9ff596 100644
--- a/src/textord/tabvector.cpp
+++ b/src/textord/tabvector.cpp
@@ -59,8 +59,6 @@ double_VAR(textord_tabvector_vertical_gap_fraction, 0.5,
double_VAR(textord_tabvector_vertical_box_ratio, 0.5,
"Fraction of box matches required to declare a line vertical");
-ELISTIZE(TabConstraint)
-
// Create a constraint for the top or bottom of this TabVector.
void TabConstraint::CreateConstraint(TabVector *vector, bool is_top) {
auto *constraint = new TabConstraint(vector, is_top);
diff --git a/src/textord/workingpartset.cpp b/src/textord/workingpartset.cpp
index 53398694..45c4abac 100644
--- a/src/textord/workingpartset.cpp
+++ b/src/textord/workingpartset.cpp
@@ -23,8 +23,6 @@
namespace tesseract {
-ELISTIZE(WorkingPartSet)
-
// Add the partition to this WorkingPartSet. Unrelated partitions are
// stored in the order in which they are received, but if the partition
// has a SingletonPartner, make sure that it stays with its partner.
diff --git a/src/wordrec/lm_state.cpp b/src/wordrec/lm_state.cpp
index fcae0ac8..0376fd95 100644
--- a/src/wordrec/lm_state.cpp
+++ b/src/wordrec/lm_state.cpp
@@ -21,8 +21,6 @@
namespace tesseract {
-ELISTIZE(ViterbiStateEntry)
-
void ViterbiStateEntry::Print(const char *msg) const {
tprintf("%s ViterbiStateEntry", msg);
if (updated) {
diff --git a/unittest/list_test.cc b/unittest/list_test.cc
index 5310214a..04d8c343 100644
--- a/unittest/list_test.cc
+++ b/unittest/list_test.cc
@@ -45,7 +45,6 @@ public:
CLISTIZEH(Clst)
ELISTIZEH(Elst)
-ELISTIZE(Elst)
ELIST2IZEH(Elst2)
ELIST2IZE(Elst2)