diff --git a/src/ccstruct/fontinfo.cpp b/src/ccstruct/fontinfo.cpp index 9395ebfb8a..65d4d032e1 100644 --- a/src/ccstruct/fontinfo.cpp +++ b/src/ccstruct/fontinfo.cpp @@ -221,7 +221,8 @@ bool write_spacing_info(FILE *f, const FontInfo &fi) { bool write_set(FILE *f, const FontSet &fs) { int size = fs.size(); - return tesseract::Serialize(f, &size) && tesseract::Serialize(f, &fs[0], size); + return tesseract::Serialize(f, &size) && + (size > 0 ? tesseract::Serialize(f, &fs[0], size) : true); } } // namespace tesseract. diff --git a/src/ccutil/helpers.h b/src/ccutil/helpers.h index c445297d29..f252f6a9d5 100644 --- a/src/ccutil/helpers.h +++ b/src/ccutil/helpers.h @@ -31,6 +31,8 @@ #include #include +#include "serialis.h" + namespace tesseract { template @@ -242,6 +244,19 @@ bool Serialize(FILE *fp, const std::vector &data) { return false; } } + } else if constexpr (std::is_pointer::value) { + // Serialize pointers. + for (auto &item : data) { + uint8_t non_null = (item != nullptr); + if (!Serialize(fp, &non_null)) { + return false; + } + if (non_null) { + if (!item->Serialize(fp)) { + return false; + } + } + } } else if (size > 0) { if (fwrite(&data[0], sizeof(T), size, fp) != size) { return false; diff --git a/src/ccutil/unicity_table.h b/src/ccutil/unicity_table.h index 8e2ccde855..4108995080 100644 --- a/src/ccutil/unicity_table.h +++ b/src/ccutil/unicity_table.h @@ -62,6 +62,13 @@ class UnicityTable { return table_.at(id); } + T &operator[](size_t id) { + return table_[id]; + } + const T &operator[](size_t id) const { + return table_[id]; + } + /// Return the id of the T object. /// This method NEEDS a compare_callback to be passed to /// set_compare_callback. @@ -73,8 +80,7 @@ class UnicityTable { int push_back(T object) { auto idx = get_index(object); if (idx == -1) { - table_.push_back(object); - idx = size(); + idx = table_.push_back(object); } return idx; } diff --git a/src/classify/cluster.cpp b/src/classify/cluster.cpp index 046c79f14e..fd88978023 100644 --- a/src/classify/cluster.cpp +++ b/src/classify/cluster.cpp @@ -1716,7 +1716,7 @@ static void CreateClusterTree(CLUSTERER *Clusterer) { context.candidates = new TEMPCLUSTER[Clusterer->NumberOfSamples]; context.next = 0; context.heap = new ClusterHeap(Clusterer->NumberOfSamples); - KDWalk(context.tree, reinterpret_cast(MakePotentialClusters), &context); + KDWalk(context.tree, MakePotentialClusters, &context); // form potential clusters into actual clusters - always do "best" first while (context.heap->Pop(&HeapEntry)) { @@ -2523,7 +2523,6 @@ static PROTOTYPE *NewMixedProto(int16_t N, CLUSTER *Cluster, STATISTICS *Statist */ static PROTOTYPE *NewSimpleProto(int16_t N, CLUSTER *Cluster) { auto Proto = new PROTOTYPE; - ASSERT_HOST(N == sizeof(Cluster->Mean)); Proto->Mean = Cluster->Mean; Proto->Distrib.clear(); Proto->Significant = true; @@ -2775,8 +2774,8 @@ static double ComputeChiSquared(uint16_t DegreesOfFreedom, double Alpha) for the specified number of degrees of freedom. Search the list for the desired chi-squared. */ CHISTRUCT SearchKey(0.0, Alpha); - auto OldChiSquared = reinterpret_cast( - search(ChiWith[DegreesOfFreedom], &SearchKey, AlphaMatch)->first_node()); + auto *found = search(ChiWith[DegreesOfFreedom], &SearchKey, AlphaMatch); + auto OldChiSquared = reinterpret_cast(found ? found->first_node() : nullptr); if (OldChiSquared == nullptr) { OldChiSquared = new CHISTRUCT(DegreesOfFreedom, Alpha); diff --git a/src/classify/intproto.cpp b/src/classify/intproto.cpp index 0638e59907..854026bcc9 100644 --- a/src/classify/intproto.cpp +++ b/src/classify/intproto.cpp @@ -505,9 +505,11 @@ INT_TEMPLATES_STRUCT *Classify::CreateIntTemplates(CLASSES FloatProtos, } assert(UnusedClassIdIn(IntTemplates, ClassId)); IClass = new INT_CLASS_STRUCT(FClass->NumProtos, FClass->NumConfigs); - FontSet fs{FClass->font_set.size()}; - for (unsigned i = 0; i < fs.size(); ++i) { - fs[i] = FClass->font_set.at(i); + unsigned fs_size = FClass->font_set.size(); + FontSet fs; + fs.reserve(fs_size); + for (unsigned i = 0; i < fs_size; ++i) { + fs.push_back(FClass->font_set[i]); } IClass->font_set_id = this->fontset_table_.push_back(fs); AddIntClass(IntTemplates, ClassId, IClass); @@ -917,13 +919,13 @@ void ClearFeatureSpaceWindow(NORM_METHOD norm_method, ScrollView *window) { void Classify::WriteIntTemplates(FILE *File, INT_TEMPLATES_STRUCT *Templates, const UNICHARSET &target_unicharset) { INT_CLASS_STRUCT *Class; - auto unicharset_size = target_unicharset.size(); + uint32_t unicharset_size = target_unicharset.size(); int version_id = -5; // When negated by the reader -1 becomes +1 etc. if (Templates->NumClasses != unicharset_size) { tprintf( "Warning: executing WriteIntTemplates() with %d classes in" - " Templates, while target_unicharset size is %zu\n", + " Templates, while target_unicharset size is %" PRIu32 "\n", Templates->NumClasses, unicharset_size); } diff --git a/src/classify/kdtree.cpp b/src/classify/kdtree.cpp index df706d77c5..d5fe1509af 100644 --- a/src/classify/kdtree.cpp +++ b/src/classify/kdtree.cpp @@ -212,7 +212,7 @@ KDTREE *MakeKDTree(int16_t KeySize, const PARAM_DESC KeyDesc[]) { * @param Key ptr to key by which data can be retrieved * @param Data ptr to data to be stored in the tree */ -void KDStore(KDTREE *Tree, float *Key, void *Data) { +void KDStore(KDTREE *Tree, float *Key, CLUSTER *Data) { auto PtrToNode = &(Tree->Root.Left); auto Node = *PtrToNode; auto Level = NextLevel(Tree, -1); @@ -310,7 +310,7 @@ void KDNearestNeighborSearch(KDTREE *Tree, float Query[], int QuerySize, float M /*---------------------------------------------------------------------------*/ /** Walk a given Tree with action. */ -void KDWalk(KDTREE *Tree, void_proc action, void *context) { +void KDWalk(KDTREE *Tree, kdwalk_proc action, ClusteringContext *context) { if (Tree->Root.Left != nullptr) { Walk(Tree, action, context, Tree->Root.Left, NextLevel(Tree, -1)); } @@ -463,7 +463,7 @@ bool KDTreeSearch::BoxIntersectsSearch(float *lower, float *upper) { * @param sub_tree ptr to root of subtree to be walked * @param level current level in the tree for this node */ -void Walk(KDTREE *tree, void_proc action, void *context, KDNODE *sub_tree, int32_t level) { +void Walk(KDTREE *tree, kdwalk_proc action, ClusteringContext *context, KDNODE *sub_tree, int32_t level) { (*action)(context, sub_tree->Data, level); if (sub_tree->Left != nullptr) { Walk(tree, action, context, sub_tree->Left, NextLevel(tree, level)); diff --git a/src/classify/kdtree.h b/src/classify/kdtree.h index a05740ae3d..5a54f9b1e2 100644 --- a/src/classify/kdtree.h +++ b/src/classify/kdtree.h @@ -22,8 +22,6 @@ namespace tesseract { -using void_proc = void (*)(...); - /** NOTE: All circular parameters of all keys must be in the range @@ -34,8 +32,12 @@ MakeKDTree. All KD routines assume that this is true and will not operate correctly if circular parameters outside the specified range are used. */ +struct ClusteringContext; +struct CLUSTER; struct KDTREE; +using kdwalk_proc = void (*)(ClusteringContext *context, CLUSTER *Cluster, int32_t Level); + struct KDNODE { /// This routine allocates memory for a new K-D tree node /// and places the specified Key and Data into it. The @@ -46,14 +48,14 @@ struct KDNODE { /// @param Data ptr to data to be stored in new node /// @param Index index of Key to branch on KDNODE() = default; - KDNODE(KDTREE *tree, float key[], void *data, int Index); + KDNODE(KDTREE *tree, float key[], CLUSTER *data, int Index); ~KDNODE() { delete Left; delete Right; } float *Key; /**< search key */ - void *Data; /**< data that corresponds to key */ + CLUSTER *Data; /**< data that corresponds to key */ float BranchPoint; /**< needed to make deletes work efficiently */ float LeftBranch; /**< used to optimize search pruning */ float RightBranch; /**< used to optimize search pruning */ @@ -80,7 +82,7 @@ struct KDTREE { std::vector KeyDesc; // description of each dimension }; -inline KDNODE::KDNODE(KDTREE *tree, float key[], void *data, int Index) { +inline KDNODE::KDNODE(KDTREE *tree, float key[], CLUSTER *data, int Index) { Key = key; Data = data; BranchPoint = Key[Index]; @@ -100,14 +102,14 @@ inline KDNODE::KDNODE(KDTREE *tree, float key[], void *data, int Index) { -----------------------------------------------------------------------------*/ KDTREE *MakeKDTree(int16_t KeySize, const PARAM_DESC KeyDesc[]); -void KDStore(KDTREE *Tree, float *Key, void *Data); +void KDStore(KDTREE *Tree, float *Key, CLUSTER *Data); void KDDelete(KDTREE *Tree, float Key[], void *Data); void KDNearestNeighborSearch(KDTREE *Tree, float Query[], int QuerySize, float MaxDistance, int *NumberOfResults, void **NBuffer, float DBuffer[]); -void KDWalk(KDTREE *Tree, void_proc Action, void *context); +void KDWalk(KDTREE *Tree, kdwalk_proc Action, ClusteringContext *context); /*----------------------------------------------------------------------------- Private Function Prototypes @@ -120,7 +122,7 @@ float ComputeDistance(int k, PARAM_DESC *dim, float p1[], float p2[]); int QueryInSearch(KDTREE *tree); -void Walk(KDTREE *tree, void_proc action, void *context, KDNODE *SubTree, int32_t Level); +void Walk(KDTREE *tree, kdwalk_proc action, ClusteringContext *context, KDNODE *SubTree, int32_t Level); void InsertNodes(KDTREE *tree, KDNODE *nodes); diff --git a/src/training/common/commontraining.cpp b/src/training/common/commontraining.cpp index 473cb70b4c..60f3bd64f6 100644 --- a/src/training/common/commontraining.cpp +++ b/src/training/common/commontraining.cpp @@ -376,6 +376,7 @@ void ReadTrainingSamples(const FEATURE_DEFS_STRUCT &feature_definitions, const c if (feature_type != i) { delete char_desc->FeatureSets[i]; } + char_desc->FeatureSets[i] = nullptr; } delete char_desc; }