ParamUtils::ReportParamsUsageStatistics() work extracted from master; rough first draft, as in: not compile-tested, not backported to using PrintFontsTable() instead of fmt::format et al.

This commit is contained in:
Ger Hobbelt 2023-02-25 11:57:22 +01:00
parent 9d71da7854
commit c38b33b9fe
5 changed files with 437 additions and 98 deletions

View File

@ -161,6 +161,17 @@ public:
*/
void PrintVariables(FILE *fp) const;
/*
* Report parameters' usage statistics, i.e. report which params have been
* set, modified and read/checked until now during this run-time's lifetime.
*
* Use this method for run-time 'discovery' about which tesseract parameters
* are actually *used* during your particular usage of the library, ergo
* answering the question:
* "Which of all those parameters are actually *relevant* to my use case today?"
*/
void ReportParamsUsageStatistics() const;
/**
* Get value of named variable as a string, if it exists.
*/

View File

@ -292,8 +292,8 @@ bool TessBaseAPI::SetDebugVariable(const char *name, const char *value) {
}
bool TessBaseAPI::GetIntVariable(const char *name, int *value) const {
auto *p = ParamUtils::FindParam<IntParam>(name, GlobalParams()->int_params,
tesseract_->params()->int_params);
auto *p = ParamUtils::FindParam<IntParam>(name, GlobalParams()->int_params(),
tesseract_->params()->int_params());
if (p == nullptr) {
return false;
}
@ -302,8 +302,8 @@ bool TessBaseAPI::GetIntVariable(const char *name, int *value) const {
}
bool TessBaseAPI::GetBoolVariable(const char *name, bool *value) const {
auto *p = ParamUtils::FindParam<BoolParam>(name, GlobalParams()->bool_params,
tesseract_->params()->bool_params);
auto *p = ParamUtils::FindParam<BoolParam>(name, GlobalParams()->bool_params(),
tesseract_->params()->bool_params());
if (p == nullptr) {
return false;
}
@ -312,14 +312,14 @@ bool TessBaseAPI::GetBoolVariable(const char *name, bool *value) const {
}
const char *TessBaseAPI::GetStringVariable(const char *name) const {
auto *p = ParamUtils::FindParam<StringParam>(name, GlobalParams()->string_params,
tesseract_->params()->string_params);
auto *p = ParamUtils::FindParam<StringParam>(name, GlobalParams()->string_params(),
tesseract_->params()->string_params());
return (p != nullptr) ? p->c_str() : nullptr;
}
bool TessBaseAPI::GetDoubleVariable(const char *name, double *value) const {
auto *p = ParamUtils::FindParam<DoubleParam>(name, GlobalParams()->double_params,
tesseract_->params()->double_params);
auto *p = ParamUtils::FindParam<DoubleParam>(name, GlobalParams()->double_params(),
tesseract_->params()->double_params());
if (p == nullptr) {
return false;
}
@ -357,6 +357,19 @@ void TessBaseAPI::PrintVariables(FILE *fp) const {
ParamUtils::PrintParams(fp, tesseract_->params());
}
// Report parameters' usage statistics, i.e. report which params have been
// set, modified and read/checked until now during this run-time's lifetime.
//
// Use this method for run-time 'discovery' about which tesseract parameters
// are actually *used* during your particular usage of the library, ergo
// answering the question:
// "Which of all those parameters are actually *relevant* to my use case today?"
void TessBaseAPI::ReportParamsUsageStatistics() const {
tesseract::ParamsVectors *vec = tesseract_->params();
ParamUtils::ReportParamsUsageStatistics(vec);
}
/**
* The datapath must be the name of the data directory or
* some other file in which the data directory resides (for instance argv[0].)

View File

@ -212,16 +212,16 @@ SVMenuNode *ParamsEditor::BuildListOfAllLeaves(tesseract::Tesseract *tess) {
int num_iterations = (tess->params() == nullptr) ? 1 : 2;
for (int v = 0; v < num_iterations; ++v) {
tesseract::ParamsVectors *vec = (v == 0) ? GlobalParams() : tess->params();
for (auto &param : vec->int_params) {
for (auto &param : vec->int_params()) {
vc_it.add_after_then_move(new ParamContent(param));
}
for (auto &param : vec->bool_params) {
for (auto &param : vec->bool_params()) {
vc_it.add_after_then_move(new ParamContent(param));
}
for (auto &param : vec->string_params) {
for (auto &param : vec->string_params()) {
vc_it.add_after_then_move(new ParamContent(param));
}
for (auto &param : vec->double_params) {
for (auto &param : vec->double_params()) {
vc_it.add_after_then_move(new ParamContent(param));
}
}

View File

@ -18,11 +18,14 @@
#include "params.h"
#include "helpers.h" // for chomp_string
#include "helpers.h" // for chomp_string, mupdf imports, etc.: see also the header collision comment in there (MSVC-specific).
#include "host.h" // tesseract/export.h, windows.h for MAX_PATH
#include "serialis.h" // for TFile
#include "tprintf.h"
#include <fmt/core.h>
#include <fmt/format.h>
#include <climits> // for INT_MIN, INT_MAX
#include <cmath> // for NAN, std::isnan
#include <cstdio>
@ -31,10 +34,12 @@
#include <locale> // for std::locale::classic
#include <sstream> // for std::stringstream
namespace tesseract {
TESS_API
tesseract::ParamsVectors *GlobalParams() {
static tesseract::ParamsVectors global_params = tesseract::ParamsVectors();
static tesseract::ParamsVectors global_params; // static auto-inits at startup
return &global_params;
}
@ -42,7 +47,7 @@ bool ParamUtils::ReadParamsFile(const char *file, SetParamConstraint constraint,
ParamsVectors *member_params) {
TFile fp;
if (!fp.Open(file, nullptr)) {
tprintf("read_params_file: Can't open %s\n", file);
tprintf("ERROR: read_params_file: Can't open file {}\n", file);
return true;
}
return ReadParamsFromFp(constraint, &fp, member_params);
@ -71,18 +76,157 @@ bool ParamUtils::ReadParamsFromFp(SetParamConstraint constraint, TFile *fp,
if (!foundit) {
anyerr = true; // had an error
tprintf("Warning: Parameter not found: %s\n", line);
tprintf("WARNING: Parameter not found: {}\n", line);
}
}
}
return anyerr;
}
void ParamUtils::ReportParamsUsageStatistics(const ParamsVectors *member_params)
{
std::string report_path = vars_report_file;
FILE* f = nullptr;
if (report_path == "stdout" || report_path == "-" || report_path == "1")
f = stdout;
else if (report_path == "stdeerr" || report_path == "+" || report_path == "2")
f = stderr;
else if (!report_path.empty())
{
#if defined(HAVE_MUPDF)
fz_context* ctx = fz_get_global_context();
fz_mkdir_for_file(ctx, report_path.c_str());
f = fz_fopen_utf8(ctx, report_path.c_str(), "w");
#else
f = fopen(report_path.c_str(), "w");
#endif
if (!f)
{
tprintf("ERROR: Cannot produce paramater usage report file: {}\n", report_path);
}
}
if (!f)
return;
fprintf(f, "\n\nTesseract Parameter Usage Statistics: which params have been relevant?\n"
"----------------------------------------------------------------------\n\n");
// first collect all parameter names:
typedef enum {
INT_PARAM = 0,
BOOL_PARAM,
DOUBLE_PARAM,
STRING_PARAM,
} param_type_t;
typedef struct param_info {
const char* name;
bool global;
param_type_t type;
const Param* ref;
} param_info_t;
std::vector<param_info_t> param_names;
if (member_params != nullptr) {
for (auto p : member_params->int_params_c()) {
param_names.push_back({ p->name_str(), false, INT_PARAM, p });
}
for (auto p : member_params->bool_params_c()) {
param_names.push_back({ p->name_str(), false, BOOL_PARAM, p });
}
for (auto p : member_params->string_params_c()) {
param_names.push_back({ p->name_str(), false, STRING_PARAM, p });
}
for (auto p : member_params->double_params_c()) {
param_names.push_back({ p->name_str(), false, DOUBLE_PARAM, p });
}
}
const ParamsVectors* globals = GlobalParams();
for (auto p : globals->int_params_c()) {
param_names.push_back({ p->name_str(), true, INT_PARAM, p });
}
for (auto p : globals->bool_params_c()) {
param_names.push_back({ p->name_str(), true, BOOL_PARAM, p });
}
for (auto p : globals->string_params_c()) {
param_names.push_back({ p->name_str(), true, STRING_PARAM, p });
}
for (auto p : globals->double_params_c()) {
param_names.push_back({ p->name_str(), true, DOUBLE_PARAM, p });
}
sort(param_names.begin(), param_names.end(), [](param_info_t& a, param_info_t& b)
{
int rv = strcmp(b.name, a.name);
if (rv == 0)
{
rv = (int) b.global - (int) a.global;
}
#if !defined(NDEBUG)
if (rv == 0)
{
fprintf(stderr, "Apparently you have double-defined Tesseract Variable: '%s'! Fix that in the source code!\n", a.name);
ASSEERT0(!"Apparently you have double-defined a Tesseract Variable.");
}
#endif
return rv >= 0;
});
static const char* type_map[] = { "[Integer]", "[Boolean]", "[Float]", "[String]" };
static const char* categories[] = { "(Global)", "(Local)" };
static const char* write_access[] = { ".", "w", "W" };
static const char* read_access[] = { ".", "r", "R" };
auto acc = [](int access) {
if (access > 2)
access = 2;
return access;
};
for (auto item : param_names) {
const Param* p = item.ref;
auto stats = p->access_counts();
if (stats.reading > 0)
{
fmt::print(f, "* {:.<60} {:8} {}{} {:9} = {}\n", p->name_str(), categories[item.global], write_access[acc(stats.writing)], read_access[acc(stats.reading)], type_map[item.type], p->formatted_value_str());
}
}
if (report_all_variables)
{
fprintf(f, "\n\nUnused parameters:\n\n");
for (auto item : param_names) {
const Param* p = item.ref;
auto stats = p->access_counts();
if (stats.reading <= 0)
{
fmt::print(f, "* {:.<60} {:8} {}{} {:9} = {}\n", p->name_str(), categories[item.global], write_access[acc(stats.writing)], read_access[acc(stats.reading)], type_map[item.type], p->formatted_value_str());
}
}
}
if (f != stdout)
{
fclose(f);
}
else
{
fflush(stdout);
}
}
bool ParamUtils::SetParam(const char *name, const char *value, SetParamConstraint constraint,
ParamsVectors *member_params) {
// Look for the parameter among string parameters.
auto *sp =
FindParam<StringParam>(name, GlobalParams()->string_params, member_params->string_params);
FindParam<StringParam>(name, GlobalParams()->string_params(), member_params->string_params());
if (sp != nullptr && sp->constraint_ok(constraint)) {
sp->set_value(value);
}
@ -91,7 +235,7 @@ bool ParamUtils::SetParam(const char *name, const char *value, SetParamConstrain
}
// Look for the parameter among int parameters.
auto *ip = FindParam<IntParam>(name, GlobalParams()->int_params, member_params->int_params);
auto *ip = FindParam<IntParam>(name, GlobalParams()->int_params(), member_params->int_params());
if (ip && ip->constraint_ok(constraint)) {
int intval = INT_MIN;
std::stringstream stream(value);
@ -103,7 +247,7 @@ bool ParamUtils::SetParam(const char *name, const char *value, SetParamConstrain
}
// Look for the parameter among bool parameters.
auto *bp = FindParam<BoolParam>(name, GlobalParams()->bool_params, member_params->bool_params);
auto *bp = FindParam<BoolParam>(name, GlobalParams()->bool_params(), member_params->bool_params());
if (bp != nullptr && bp->constraint_ok(constraint)) {
if (*value == 'T' || *value == 't' || *value == 'Y' || *value == 'y' || *value == '1') {
bp->set_value(true);
@ -114,7 +258,7 @@ bool ParamUtils::SetParam(const char *name, const char *value, SetParamConstrain
// Look for the parameter among double parameters.
auto *dp =
FindParam<DoubleParam>(name, GlobalParams()->double_params, member_params->double_params);
FindParam<DoubleParam>(name, GlobalParams()->double_params(), member_params->double_params());
if (dp != nullptr && dp->constraint_ok(constraint)) {
double doubleval = NAN;
std::stringstream stream(value);
@ -131,26 +275,26 @@ bool ParamUtils::GetParamAsString(const char *name, const ParamsVectors *member_
std::string *value) {
// Look for the parameter among string parameters.
auto *sp =
FindParam<StringParam>(name, GlobalParams()->string_params, member_params->string_params);
FindParam<StringParam>(name, GlobalParams()->string_params_c(), member_params->string_params_c());
if (sp) {
*value = sp->c_str();
return true;
}
// Look for the parameter among int parameters.
auto *ip = FindParam<IntParam>(name, GlobalParams()->int_params, member_params->int_params);
auto *ip = FindParam<IntParam>(name, GlobalParams()->int_params_c(), member_params->int_params_c());
if (ip) {
*value = std::to_string(int32_t(*ip));
return true;
}
// Look for the parameter among bool parameters.
auto *bp = FindParam<BoolParam>(name, GlobalParams()->bool_params, member_params->bool_params);
auto *bp = FindParam<BoolParam>(name, GlobalParams()->bool_params_c(), member_params->bool_params_c());
if (bp != nullptr) {
*value = bool(*bp) ? "1" : "0";
return true;
}
// Look for the parameter among double parameters.
auto *dp =
FindParam<DoubleParam>(name, GlobalParams()->double_params, member_params->double_params);
FindParam<DoubleParam>(name, GlobalParams()->double_params_c(), member_params->double_params_c());
if (dp != nullptr) {
std::ostringstream stream;
stream.imbue(std::locale::classic());
@ -163,27 +307,55 @@ bool ParamUtils::GetParamAsString(const char *name, const ParamsVectors *member_
void ParamUtils::PrintParams(FILE *fp, const ParamsVectors *member_params) {
int num_iterations = (member_params == nullptr) ? 1 : 2;
// When printing to stdout info text is included.
// Info text is omitted when printing to a file (would result in an invalid config file).
if (!fp)
fp = stdout;
bool print_info = (fp == stdout || fp == stderr);
std::ostringstream stream;
stream.imbue(std::locale::classic());
for (int v = 0; v < num_iterations; ++v) {
const ParamsVectors *vec = (v == 0) ? GlobalParams() : member_params;
for (auto int_param : vec->int_params) {
for (auto int_param : vec->int_params_c()) {
if (print_info) {
stream << int_param->name_str() << '\t' << (int32_t)(*int_param) << '\t'
<< int_param->info_str() << '\n';
} else {
stream << int_param->name_str() << '\t' << (int32_t)(*int_param) << '\n';
}
for (auto bool_param : vec->bool_params) {
}
for (auto bool_param : vec->bool_params_c()) {
if (print_info) {
stream << bool_param->name_str() << '\t' << bool(*bool_param) << '\t'
<< bool_param->info_str() << '\n';
} else {
stream << bool_param->name_str() << '\t' << bool(*bool_param) << '\n';
}
for (auto string_param : vec->string_params) {
}
for (auto string_param : vec->string_params_c()) {
if (print_info) {
stream << string_param->name_str() << '\t' << string_param->c_str() << '\t'
<< string_param->info_str() << '\n';
} else {
stream << string_param->name_str() << '\t' << string_param->c_str() << '\n';
}
for (auto double_param : vec->double_params) {
}
for (auto double_param : vec->double_params_c()) {
if (print_info) {
stream << double_param->name_str() << '\t' << (double)(*double_param) << '\t'
<< double_param->info_str() << '\n';
} else {
stream << double_param->name_str() << '\t' << (double)(*double_param) << '\n';
}
}
}
#ifdef HAVE_MUPDF
if (print_info)
{
tprintf("{}", stream.str().c_str());
return;
}
#endif
fprintf(fp, "%s", stream.str().c_str());
}
@ -192,16 +364,16 @@ void ParamUtils::ResetToDefaults(ParamsVectors *member_params) {
int num_iterations = (member_params == nullptr) ? 1 : 2;
for (int v = 0; v < num_iterations; ++v) {
ParamsVectors *vec = (v == 0) ? GlobalParams() : member_params;
for (auto &param : vec->int_params) {
for (auto &param : vec->int_params()) {
param->ResetToDefault();
}
for (auto &param : vec->bool_params) {
for (auto &param : vec->bool_params()) {
param->ResetToDefault();
}
for (auto &param : vec->string_params) {
for (auto &param : vec->string_params()) {
param->ResetToDefault();
}
for (auto &param : vec->double_params) {
for (auto &param : vec->double_params()) {
param->ResetToDefault();
}
}

View File

@ -3,6 +3,8 @@
* Description: Class definitions of the *_VAR classes for tunable constants.
* Author: Ray Smith
*
* UTF8 detect helper statement: «bloody MSVC»
*
* (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.
@ -43,11 +45,43 @@ enum SetParamConstraint {
SET_PARAM_CONSTRAINT_NON_INIT_ONLY,
};
struct ParamsVectors {
std::vector<IntParam *> int_params;
std::vector<BoolParam *> bool_params;
std::vector<StringParam *> string_params;
std::vector<DoubleParam *> double_params;
class ParamsVectors {
std::vector<IntParam *> _int_params;
std::vector<BoolParam *> _bool_params;
std::vector<StringParam *> _string_params;
std::vector<DoubleParam *> _double_params;
public:
ParamsVectors() {
}
~ParamsVectors() {
}
std::vector<IntParam *> &int_params() {
return _int_params;
}
std::vector<BoolParam *> &bool_params() {
return _bool_params;
}
std::vector<StringParam *> &string_params() {
return _string_params;
}
std::vector<DoubleParam *> &double_params() {
return _double_params;
}
const std::vector<IntParam *> &int_params_c() const {
return _int_params;
}
const std::vector<BoolParam *> &bool_params_c() const {
return _bool_params;
}
const std::vector<StringParam *> &string_params_c() const {
return _string_params;
}
const std::vector<DoubleParam *> &double_params_c() const {
return _double_params;
}
};
// Utility functions for working with Tesseract parameters.
@ -69,6 +103,25 @@ public:
static bool SetParam(const char *name, const char *value, SetParamConstraint constraint,
ParamsVectors *member_params);
// accept both - and _ in key names, e.g. user-specified 'debug-all' would match 'debug_all'
// in the database.
static inline bool CompareKeys(const char *db_key, const char *user_key)
{
// if (0 == strcmp(db_key, user_key))
// return true;
for (; *db_key && *user_key; db_key++, user_key++)
{
if (*db_key != *user_key)
{
if (*db_key == '_' && *user_key == '-')
continue;
return false;
}
}
return true;
}
// Returns the pointer to the parameter with the given name (of the
// appropriate type) if it was found in the vector obtained from
// GlobalParams() or in the given member_params.
@ -76,12 +129,12 @@ public:
static T *FindParam(const char *name, const std::vector<T *> &global_vec,
const std::vector<T *> &member_vec) {
for (auto *param : global_vec) {
if (strcmp(param->name_str(), name) == 0) {
if (CompareKeys(param->name_str(), name)) {
return param;
}
}
for (auto *param : member_vec) {
if (strcmp(param->name_str(), name) == 0) {
if (CompareKeys(param->name_str(), name)) {
return param;
}
}
@ -105,6 +158,15 @@ public:
// Print parameters to the given file.
static void PrintParams(FILE *fp, const ParamsVectors *member_params);
// Report parameters' usage statistics, i.e. report which params have been
// set, modified and read/checked until now during this run-time's lifetime.
//
// Use this method for run-time 'discovery' about which tesseract parameters
// are actually *used* during your particular usage of the library, ergo
// answering the question:
// "Which of all those parameters are actually *relevant* to my use case today?"
static void ReportParamsUsageStatistics(const ParamsVectors *member_params);
// Resets all parameters back to default values;
static void ResetToDefaults(ParamsVectors *member_params);
};
@ -133,16 +195,29 @@ public:
(constraint == SET_PARAM_CONSTRAINT_NON_INIT_ONLY && !this->is_init()));
}
typedef struct access_counts {
int reading;
int writing;
} access_counts_t;
access_counts_t access_counts() const {
return access_counts_;
}
virtual std::string formatted_value_str() const = 0;
protected:
Param(const char *name, const char *comment, bool init)
: name_(name), info_(comment), init_(init) {
debug_ = (strstr(name, "debug") != nullptr) || (strstr(name, "display"));
access_counts_ = {0,0};
}
const char *name_; // name of this parameter
const char *info_; // for menus
bool init_; // needs to be set before init
bool debug_;
mutable access_counts_t access_counts_;
};
class IntParam : public Param {
@ -151,40 +226,51 @@ public:
: Param(name, comment, init) {
value_ = value;
default_ = value;
params_vec_ = &(vec->int_params);
vec->int_params.push_back(this);
access_counts_.writing++;
params_vec_ = vec;
vec->int_params().push_back(this);
}
~IntParam() {
ParamUtils::RemoveParam<IntParam>(this, params_vec_);
ParamUtils::RemoveParam<IntParam>(this, &params_vec_->int_params());
}
operator int32_t() const {
access_counts_.reading++;
return value_;
}
void operator=(int32_t value) {
access_counts_.writing++;
value_ = value;
}
void set_value(int32_t value) {
access_counts_.writing++;
value_ = value;
}
void ResetToDefault() {
access_counts_.writing++;
value_ = default_;
}
void ResetFrom(const ParamsVectors *vec) {
for (auto *param : vec->int_params) {
for (auto *param : vec->int_params_c()) {
if (strcmp(param->name_str(), name_) == 0) {
// printf("overriding param %s=%d by =%d\n", name_, value_,
// param);
// tprintf("overriding param {}={} by ={}\n", name_, value_,
// *param);
access_counts_.writing++;
value_ = *param;
break;
}
}
}
virtual std::string formatted_value_str() const override {
return std::to_string(value_);
}
private:
int32_t value_;
int32_t default_;
// Pointer to the vector that contains this param (not owned by this class).
std::vector<IntParam *> *params_vec_;
// Pointer to the vector that contains this param (not owned by this class). Used by the destructor.
ParamsVectors *params_vec_;
};
class BoolParam : public Param {
@ -193,40 +279,51 @@ public:
: Param(name, comment, init) {
value_ = value;
default_ = value;
params_vec_ = &(vec->bool_params);
vec->bool_params.push_back(this);
access_counts_.writing++;
params_vec_ = vec;
vec->bool_params().push_back(this);
}
~BoolParam() {
ParamUtils::RemoveParam<BoolParam>(this, params_vec_);
ParamUtils::RemoveParam<BoolParam>(this, &params_vec_->bool_params());
}
operator bool() const {
access_counts_.reading++;
return value_;
}
void operator=(bool value) {
access_counts_.writing++;
value_ = value;
}
void set_value(bool value) {
access_counts_.writing++;
value_ = value;
}
void ResetToDefault() {
access_counts_.writing++;
value_ = default_;
}
void ResetFrom(const ParamsVectors *vec) {
for (auto *param : vec->bool_params) {
for (auto *param : vec->bool_params_c()) {
if (strcmp(param->name_str(), name_) == 0) {
// printf("overriding param %s=%s by =%s\n", name_, value_ ? "true" :
// tprintf("overriding param {}={} by ={}\n", name_, value_ ? "true" :
// "false", *param ? "true" : "false");
access_counts_.writing++;
value_ = *param;
break;
}
}
}
virtual std::string formatted_value_str() const override {
return std::to_string(value_);
}
private:
bool value_;
bool default_;
// Pointer to the vector that contains this param (not owned by this class).
std::vector<BoolParam *> *params_vec_;
ParamsVectors *params_vec_;
};
class StringParam : public Param {
@ -236,52 +333,74 @@ public:
: Param(name, comment, init) {
value_ = value;
default_ = value;
params_vec_ = &(vec->string_params);
vec->string_params.push_back(this);
access_counts_.writing++;
params_vec_ = vec;
vec->string_params().push_back(this);
}
~StringParam() {
ParamUtils::RemoveParam<StringParam>(this, params_vec_);
ParamUtils::RemoveParam<StringParam>(this, &params_vec_->string_params());
}
operator std::string &() {
access_counts_.reading++;
return value_;
}
const char *c_str() const {
access_counts_.reading++;
return value_.c_str();
}
bool contains(char c) const {
access_counts_.reading++;
return value_.find(c) != std::string::npos;
}
bool empty() const {
access_counts_.reading++;
return value_.empty();
}
bool operator==(const std::string &other) const {
access_counts_.reading++;
return value_ == other;
}
void operator=(const std::string &value) {
access_counts_.writing++;
value_ = value;
}
void set_value(const std::string &value) {
access_counts_.writing++;
value_ = value;
}
const std::string &value() {
access_counts_.reading++;
return value_;
}
void ResetToDefault() {
access_counts_.writing++;
value_ = default_;
}
void ResetFrom(const ParamsVectors *vec) {
for (auto *param : vec->string_params) {
for (auto *param : vec->string_params_c()) {
if (strcmp(param->name_str(), name_) == 0) {
// printf("overriding param %s=%s by =%s\n", name_, value_,
// tprintf("overriding param {}={} by ={}\n", name_, value_,
// param->c_str());
access_counts_.writing++;
value_ = *param;
break;
}
}
}
virtual std::string formatted_value_str() const override {
std::string rv = (const char *)u8"«";
rv += value_;
rv += (const char *)u8"»";
return rv;
}
private:
std::string value_;
std::string default_;
// Pointer to the vector that contains this param (not owned by this class).
std::vector<StringParam *> *params_vec_;
ParamsVectors *params_vec_;
};
class DoubleParam : public Param {
@ -290,40 +409,57 @@ public:
: Param(name, comment, init) {
value_ = value;
default_ = value;
params_vec_ = &(vec->double_params);
vec->double_params.push_back(this);
access_counts_.writing++;
params_vec_ = vec;
vec->double_params().push_back(this);
}
~DoubleParam() {
ParamUtils::RemoveParam<DoubleParam>(this, params_vec_);
ParamUtils::RemoveParam<DoubleParam>(this, &params_vec_->double_params());
}
operator double() const {
access_counts_.reading++;
return value_;
}
void operator=(double value) {
access_counts_.writing++;
value_ = value;
}
void set_value(double value) {
access_counts_.writing++;
value_ = value;
}
void ResetToDefault() {
access_counts_.writing++;
value_ = default_;
}
void ResetFrom(const ParamsVectors *vec) {
for (auto *param : vec->double_params) {
for (auto *param : vec->double_params_c()) {
if (strcmp(param->name_str(), name_) == 0) {
// printf("overriding param %s=%f by =%f\n", name_, value_,
// tprintf("overriding param {}={} by ={}\n", name_, value_,
// *param);
access_counts_.writing++;
value_ = *param;
break;
}
}
}
virtual std::string formatted_value_str() const override {
#if 0
return std::to_string(value_); // always outputs %.6f format style values
#else
char sbuf[40];
snprintf(sbuf, sizeof(sbuf), "%1.f", value_);
return sbuf;
#endif
}
private:
double value_;
double default_;
// Pointer to the vector that contains this param (not owned by this class).
std::vector<DoubleParam *> *params_vec_;
ParamsVectors *params_vec_;
};
// Global parameter lists.
@ -338,6 +474,7 @@ private:
TESS_API
ParamsVectors *GlobalParams();
/*************************************************************************
* Note on defining parameters.
*
@ -382,6 +519,12 @@ ParamsVectors *GlobalParams();
#define double_INIT_MEMBER(name, val, comment, vec) name(val, #name, comment, true, vec)
// ------------------------------------
extern BOOL_VAR_H(debug_all);
extern STRING_VAR_H(vars_report_file);
extern BOOL_VAR_H(report_all_variables);
} // namespace tesseract
#endif