1 /**********************************************************************
2  * File:        params.cpp
3  * Description: Initialization and setting of Tesseract parameters.
4  * Author:      Ray Smith
5  *
6  * (C) Copyright 1991, Hewlett-Packard Ltd.
7  ** Licensed under the Apache License, Version 2.0 (the "License");
8  ** you may not use this file except in compliance with the License.
9  ** You may obtain a copy of the License at
10  ** http://www.apache.org/licenses/LICENSE-2.0
11  ** Unless required by applicable law or agreed to in writing, software
12  ** distributed under the License is distributed on an "AS IS" BASIS,
13  ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  ** See the License for the specific language governing permissions and
15  ** limitations under the License.
16  *
17  **********************************************************************/
18 
19 #include "params.h"
20 
21 #include "helpers.h"  // for chomp_string
22 #include "host.h"     // tesseract/export.h, windows.h for MAX_PATH
23 #include "serialis.h" // for TFile
24 #include "tprintf.h"
25 
26 #include <climits> // for INT_MIN, INT_MAX
27 #include <cmath>   // for NAN, std::isnan
28 #include <cstdio>
29 #include <cstdlib>
30 #include <cstring>
31 #include <locale>  // for std::locale::classic
32 #include <sstream> // for std::stringstream
33 
34 namespace tesseract {
35 
GlobalParams()36 tesseract::ParamsVectors *GlobalParams() {
37   static tesseract::ParamsVectors global_params = tesseract::ParamsVectors();
38   return &global_params;
39 }
40 
ReadParamsFile(const char * file,SetParamConstraint constraint,ParamsVectors * member_params)41 bool ParamUtils::ReadParamsFile(const char *file, SetParamConstraint constraint,
42                                 ParamsVectors *member_params) {
43   TFile fp;
44   if (!fp.Open(file, nullptr)) {
45     tprintf("read_params_file: Can't open %s\n", file);
46     return true;
47   }
48   return ReadParamsFromFp(constraint, &fp, member_params);
49 }
50 
ReadParamsFromFp(SetParamConstraint constraint,TFile * fp,ParamsVectors * member_params)51 bool ParamUtils::ReadParamsFromFp(SetParamConstraint constraint, TFile *fp,
52                                   ParamsVectors *member_params) {
53   char line[MAX_PATH]; // input line
54   bool anyerr = false; // true if any error
55   bool foundit;        // found parameter
56   char *valptr;        // value field
57 
58   while (fp->FGets(line, MAX_PATH) != nullptr) {
59     if (line[0] != '\r' && line[0] != '\n' && line[0] != '#') {
60       chomp_string(line); // remove newline
61       for (valptr = line; *valptr && *valptr != ' ' && *valptr != '\t'; valptr++) {
62         ;
63       }
64       if (*valptr) {    // found blank
65         *valptr = '\0'; // make name a string
66         do {
67           valptr++; // find end of blanks
68         } while (*valptr == ' ' || *valptr == '\t');
69       }
70       foundit = SetParam(line, valptr, constraint, member_params);
71 
72       if (!foundit) {
73         anyerr = true; // had an error
74         tprintf("Warning: Parameter not found: %s\n", line);
75       }
76     }
77   }
78   return anyerr;
79 }
80 
SetParam(const char * name,const char * value,SetParamConstraint constraint,ParamsVectors * member_params)81 bool ParamUtils::SetParam(const char *name, const char *value, SetParamConstraint constraint,
82                           ParamsVectors *member_params) {
83   // Look for the parameter among string parameters.
84   auto *sp =
85       FindParam<StringParam>(name, GlobalParams()->string_params, member_params->string_params);
86   if (sp != nullptr && sp->constraint_ok(constraint)) {
87     sp->set_value(value);
88   }
89   if (*value == '\0') {
90     return (sp != nullptr);
91   }
92 
93   // Look for the parameter among int parameters.
94   auto *ip = FindParam<IntParam>(name, GlobalParams()->int_params, member_params->int_params);
95   if (ip && ip->constraint_ok(constraint)) {
96     int intval = INT_MIN;
97     std::stringstream stream(value);
98     stream.imbue(std::locale::classic());
99     stream >> intval;
100     if (intval != INT_MIN) {
101       ip->set_value(intval);
102     }
103   }
104 
105   // Look for the parameter among bool parameters.
106   auto *bp = FindParam<BoolParam>(name, GlobalParams()->bool_params, member_params->bool_params);
107   if (bp != nullptr && bp->constraint_ok(constraint)) {
108     if (*value == 'T' || *value == 't' || *value == 'Y' || *value == 'y' || *value == '1') {
109       bp->set_value(true);
110     } else if (*value == 'F' || *value == 'f' || *value == 'N' || *value == 'n' || *value == '0') {
111       bp->set_value(false);
112     }
113   }
114 
115   // Look for the parameter among double parameters.
116   auto *dp =
117       FindParam<DoubleParam>(name, GlobalParams()->double_params, member_params->double_params);
118   if (dp != nullptr && dp->constraint_ok(constraint)) {
119     double doubleval = NAN;
120     std::stringstream stream(value);
121     stream.imbue(std::locale::classic());
122     stream >> doubleval;
123     if (!std::isnan(doubleval)) {
124       dp->set_value(doubleval);
125     }
126   }
127   return (sp || ip || bp || dp);
128 }
129 
GetParamAsString(const char * name,const ParamsVectors * member_params,std::string * value)130 bool ParamUtils::GetParamAsString(const char *name, const ParamsVectors *member_params,
131                                   std::string *value) {
132   // Look for the parameter among string parameters.
133   auto *sp =
134       FindParam<StringParam>(name, GlobalParams()->string_params, member_params->string_params);
135   if (sp) {
136     *value = sp->c_str();
137     return true;
138   }
139   // Look for the parameter among int parameters.
140   auto *ip = FindParam<IntParam>(name, GlobalParams()->int_params, member_params->int_params);
141   if (ip) {
142     *value = std::to_string(int32_t(*ip));
143     return true;
144   }
145   // Look for the parameter among bool parameters.
146   auto *bp = FindParam<BoolParam>(name, GlobalParams()->bool_params, member_params->bool_params);
147   if (bp != nullptr) {
148     *value = bool(*bp) ? "1" : "0";
149     return true;
150   }
151   // Look for the parameter among double parameters.
152   auto *dp =
153       FindParam<DoubleParam>(name, GlobalParams()->double_params, member_params->double_params);
154   if (dp != nullptr) {
155     std::ostringstream stream;
156     stream.imbue(std::locale::classic());
157     stream << double(*dp);
158     *value = stream.str();
159     return true;
160   }
161   return false;
162 }
163 
PrintParams(FILE * fp,const ParamsVectors * member_params)164 void ParamUtils::PrintParams(FILE *fp, const ParamsVectors *member_params) {
165   int num_iterations = (member_params == nullptr) ? 1 : 2;
166   std::ostringstream stream;
167   stream.imbue(std::locale::classic());
168   for (int v = 0; v < num_iterations; ++v) {
169     const ParamsVectors *vec = (v == 0) ? GlobalParams() : member_params;
170     for (auto int_param : vec->int_params) {
171       stream << int_param->name_str() << '\t' << (int32_t)(*int_param) << '\t'
172              << int_param->info_str() << '\n';
173     }
174     for (auto bool_param : vec->bool_params) {
175       stream << bool_param->name_str() << '\t' << bool(*bool_param) << '\t'
176              << bool_param->info_str() << '\n';
177     }
178     for (auto string_param : vec->string_params) {
179       stream << string_param->name_str() << '\t' << string_param->c_str() << '\t'
180              << string_param->info_str() << '\n';
181     }
182     for (auto double_param : vec->double_params) {
183       stream << double_param->name_str() << '\t' << (double)(*double_param) << '\t'
184              << double_param->info_str() << '\n';
185     }
186   }
187   fprintf(fp, "%s", stream.str().c_str());
188 }
189 
190 // Resets all parameters back to default values;
ResetToDefaults(ParamsVectors * member_params)191 void ParamUtils::ResetToDefaults(ParamsVectors *member_params) {
192   int num_iterations = (member_params == nullptr) ? 1 : 2;
193   for (int v = 0; v < num_iterations; ++v) {
194     ParamsVectors *vec = (v == 0) ? GlobalParams() : member_params;
195     for (auto &param : vec->int_params) {
196       param->ResetToDefault();
197     }
198     for (auto &param : vec->bool_params) {
199       param->ResetToDefault();
200     }
201     for (auto &param : vec->string_params) {
202       param->ResetToDefault();
203     }
204     for (auto &param : vec->double_params) {
205       param->ResetToDefault();
206     }
207   }
208 }
209 
210 } // namespace tesseract
211