tesseract 4.1.1
Loading...
Searching...
No Matches
commandlineflags.cpp
Go to the documentation of this file.
1// Licensed under the Apache License, Version 2.0 (the "License");
2// you may not use this file except in compliance with the License.
3// You may obtain a copy of the License at
4// http://www.apache.org/licenses/LICENSE-2.0
5// Unless required by applicable law or agreed to in writing, software
6// distributed under the License is distributed on an "AS IS" BASIS,
7// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
8// See the License for the specific language governing permissions and
9// limitations under the License.
10
11#include <cmath> // for std::isnan, NAN
12#include <locale> // for std::locale::classic
13#include <sstream> // for std::stringstream
14#include "baseapi.h" // TessBaseAPI::Version
15#include "commandlineflags.h"
16#include "errcode.h"
17#include "tprintf.h" // for tprintf
18
19#ifndef GOOGLE_TESSERACT
20
21namespace tesseract {
22static bool IntFlagExists(const char* flag_name, int32_t* value) {
23 STRING full_flag_name("FLAGS_");
24 full_flag_name += flag_name;
26 IntParam *p = ParamUtils::FindParam<IntParam>(
27 full_flag_name.string(), GlobalParams()->int_params, empty);
28 if (p == nullptr) return false;
29 *value = (int32_t)(*p);
30 return true;
31}
32
33static bool DoubleFlagExists(const char* flag_name, double* value) {
34 STRING full_flag_name("FLAGS_");
35 full_flag_name += flag_name;
37 DoubleParam *p = ParamUtils::FindParam<DoubleParam>(
38 full_flag_name.string(), GlobalParams()->double_params, empty);
39 if (p == nullptr) return false;
40 *value = static_cast<double>(*p);
41 return true;
42}
43
44static bool BoolFlagExists(const char* flag_name, bool* value) {
45 STRING full_flag_name("FLAGS_");
46 full_flag_name += flag_name;
48 BoolParam *p = ParamUtils::FindParam<BoolParam>(
49 full_flag_name.string(), GlobalParams()->bool_params, empty);
50 if (p == nullptr) return false;
51 *value = bool(*p);
52 return true;
53}
54
55static bool StringFlagExists(const char* flag_name, const char** value) {
56 STRING full_flag_name("FLAGS_");
57 full_flag_name += flag_name;
59 StringParam *p = ParamUtils::FindParam<StringParam>(
60 full_flag_name.string(), GlobalParams()->string_params, empty);
61 *value = (p != nullptr) ? p->string() : nullptr;
62 return p != nullptr;
63}
64
65static void SetIntFlagValue(const char* flag_name, const int32_t new_val) {
66 STRING full_flag_name("FLAGS_");
67 full_flag_name += flag_name;
69 IntParam *p = ParamUtils::FindParam<IntParam>(
70 full_flag_name.string(), GlobalParams()->int_params, empty);
71 ASSERT_HOST(p != nullptr);
72 p->set_value(new_val);
73}
74
75static void SetDoubleFlagValue(const char* flag_name, const double new_val) {
76 STRING full_flag_name("FLAGS_");
77 full_flag_name += flag_name;
79 DoubleParam *p = ParamUtils::FindParam<DoubleParam>(
80 full_flag_name.string(), GlobalParams()->double_params, empty);
81 ASSERT_HOST(p != nullptr);
82 p->set_value(new_val);
83}
84
85static void SetBoolFlagValue(const char* flag_name, const bool new_val) {
86 STRING full_flag_name("FLAGS_");
87 full_flag_name += flag_name;
89 BoolParam *p = ParamUtils::FindParam<BoolParam>(
90 full_flag_name.string(), GlobalParams()->bool_params, empty);
91 ASSERT_HOST(p != nullptr);
92 p->set_value(new_val);
93}
94
95static void SetStringFlagValue(const char* flag_name, const char* new_val) {
96 STRING full_flag_name("FLAGS_");
97 full_flag_name += flag_name;
99 StringParam *p = ParamUtils::FindParam<StringParam>(
100 full_flag_name.string(), GlobalParams()->string_params, empty);
101 ASSERT_HOST(p != nullptr);
102 p->set_value(STRING(new_val));
103}
104
105static bool SafeAtoi(const char* str, int* val) {
106 char* endptr = nullptr;
107 *val = strtol(str, &endptr, 10);
108 return endptr != nullptr && *endptr == '\0';
109}
110
111static bool SafeAtod(const char* str, double* val) {
112 double d = NAN;
113 std::stringstream stream(str);
114 // Use "C" locale for reading double value.
115 stream.imbue(std::locale::classic());
116 stream >> d;
117 *val = 0;
118 bool success = !std::isnan(d);
119 if (success) {
120 *val = d;
121 }
122 return success;
123}
124
125static void PrintCommandLineFlags() {
126 const char* kFlagNamePrefix = "FLAGS_";
127 const int kFlagNamePrefixLen = strlen(kFlagNamePrefix);
128 for (int i = 0; i < GlobalParams()->int_params.size(); ++i) {
129 if (!strncmp(GlobalParams()->int_params[i]->name_str(),
130 kFlagNamePrefix, kFlagNamePrefixLen)) {
131 printf(" --%s %s (type:int default:%d)\n",
132 GlobalParams()->int_params[i]->name_str() + kFlagNamePrefixLen,
133 GlobalParams()->int_params[i]->info_str(),
134 int32_t(*(GlobalParams()->int_params[i])));
135 }
136 }
137 for (int i = 0; i < GlobalParams()->double_params.size(); ++i) {
138 if (!strncmp(GlobalParams()->double_params[i]->name_str(),
139 kFlagNamePrefix, kFlagNamePrefixLen)) {
140 printf(" --%s %s (type:double default:%g)\n",
141 GlobalParams()->double_params[i]->name_str() + kFlagNamePrefixLen,
142 GlobalParams()->double_params[i]->info_str(),
143 static_cast<double>(*(GlobalParams()->double_params[i])));
144 }
145 }
146 for (int i = 0; i < GlobalParams()->bool_params.size(); ++i) {
147 if (!strncmp(GlobalParams()->bool_params[i]->name_str(),
148 kFlagNamePrefix, kFlagNamePrefixLen)) {
149 printf(" --%s %s (type:bool default:%s)\n",
150 GlobalParams()->bool_params[i]->name_str() + kFlagNamePrefixLen,
151 GlobalParams()->bool_params[i]->info_str(),
152 bool(*(GlobalParams()->bool_params[i])) ? "true" : "false");
153 }
154 }
155 for (int i = 0; i < GlobalParams()->string_params.size(); ++i) {
156 if (!strncmp(GlobalParams()->string_params[i]->name_str(),
157 kFlagNamePrefix, kFlagNamePrefixLen)) {
158 printf(" --%s %s (type:string default:%s)\n",
159 GlobalParams()->string_params[i]->name_str() + kFlagNamePrefixLen,
160 GlobalParams()->string_params[i]->info_str(),
161 GlobalParams()->string_params[i]->string());
162 }
163 }
164}
165
166void ParseCommandLineFlags(const char* usage,
167 int* argc, char*** argv,
168 const bool remove_flags) {
169 if (*argc == 1) {
170 printf("USAGE: %s\n", usage);
171 PrintCommandLineFlags();
172 exit(0);
173 }
174
175 if (*argc > 1 && (!strcmp((*argv)[1], "-v") || !strcmp((*argv)[1], "--version"))) {
176 printf("%s\n", TessBaseAPI::Version());
177 exit(0);
178 }
179
180 int i;
181 for (i = 1; i < *argc; ++i) {
182 const char* current_arg = (*argv)[i];
183 // If argument does not start with a hyphen then break.
184 if (current_arg[0] != '-') {
185 break;
186 }
187 // Position current_arg after startings hyphens. We treat a sequence of
188 // one or two consecutive hyphens identically.
189 ++current_arg;
190 if (current_arg[0] == '-') {
191 ++current_arg;
192 }
193 // If this is asking for usage, print the help message and abort.
194 if (!strcmp(current_arg, "help")) {
195 printf("Usage:\n %s [OPTION ...]\n\n", usage);
196 PrintCommandLineFlags();
197 exit(0);
198 }
199 // Find the starting position of the value if it was specified in this
200 // string.
201 const char* equals_position = strchr(current_arg, '=');
202 const char* rhs = nullptr;
203 if (equals_position != nullptr) {
204 rhs = equals_position + 1;
205 }
206 // Extract the flag name.
207 STRING lhs;
208 if (equals_position == nullptr) {
209 lhs = current_arg;
210 } else {
211 lhs.assign(current_arg, equals_position - current_arg);
212 }
213 if (!lhs.length()) {
214 tprintf("ERROR: Bad argument: %s\n", (*argv)[i]);
215 exit(1);
216 }
217
218 // Find the flag name in the list of global flags.
219 // int32_t flag
220 int32_t int_val;
221 if (IntFlagExists(lhs.string(), &int_val)) {
222 if (rhs != nullptr) {
223 if (!strlen(rhs)) {
224 // Bad input of the format --int_flag=
225 tprintf("ERROR: Bad argument: %s\n", (*argv)[i]);
226 exit(1);
227 }
228 if (!SafeAtoi(rhs, &int_val)) {
229 tprintf("ERROR: Could not parse int from %s in flag %s\n",
230 rhs, (*argv)[i]);
231 exit(1);
232 }
233 } else {
234 // We need to parse the next argument
235 if (i + 1 >= *argc) {
236 tprintf("ERROR: Could not find value argument for flag %s\n",
237 lhs.string());
238 exit(1);
239 } else {
240 ++i;
241 if (!SafeAtoi((*argv)[i], &int_val)) {
242 tprintf("ERROR: Could not parse int32_t from %s\n", (*argv)[i]);
243 exit(1);
244 }
245 }
246 }
247 SetIntFlagValue(lhs.string(), int_val);
248 continue;
249 }
250
251 // double flag
252 double double_val;
253 if (DoubleFlagExists(lhs.string(), &double_val)) {
254 if (rhs != nullptr) {
255 if (!strlen(rhs)) {
256 // Bad input of the format --double_flag=
257 tprintf("ERROR: Bad argument: %s\n", (*argv)[i]);
258 exit(1);
259 }
260 if (!SafeAtod(rhs, &double_val)) {
261 tprintf("ERROR: Could not parse double from %s in flag %s\n",
262 rhs, (*argv)[i]);
263 exit(1);
264 }
265 } else {
266 // We need to parse the next argument
267 if (i + 1 >= *argc) {
268 tprintf("ERROR: Could not find value argument for flag %s\n",
269 lhs.string());
270 exit(1);
271 } else {
272 ++i;
273 if (!SafeAtod((*argv)[i], &double_val)) {
274 tprintf("ERROR: Could not parse double from %s\n", (*argv)[i]);
275 exit(1);
276 }
277 }
278 }
279 SetDoubleFlagValue(lhs.string(), double_val);
280 continue;
281 }
282
283 // Bool flag. Allow input forms --flag (equivalent to --flag=true),
284 // --flag=false, --flag=true, --flag=0 and --flag=1
285 bool bool_val;
286 if (BoolFlagExists(lhs.string(), &bool_val)) {
287 if (rhs == nullptr) {
288 // --flag form
289 bool_val = true;
290 } else {
291 if (!strlen(rhs)) {
292 // Bad input of the format --bool_flag=
293 tprintf("ERROR: Bad argument: %s\n", (*argv)[i]);
294 exit(1);
295 }
296 if (!strcmp(rhs, "false") || !strcmp(rhs, "0")) {
297 bool_val = false;
298 } else if (!strcmp(rhs, "true") || !strcmp(rhs, "1")) {
299 bool_val = true;
300 } else {
301 tprintf("ERROR: Could not parse bool from flag %s\n", (*argv)[i]);
302 exit(1);
303 }
304 }
305 SetBoolFlagValue(lhs.string(), bool_val);
306 continue;
307 }
308
309 // string flag
310 const char* string_val;
311 if (StringFlagExists(lhs.string(), &string_val)) {
312 if (rhs != nullptr) {
313 string_val = rhs;
314 } else {
315 // Pick the next argument
316 if (i + 1 >= *argc) {
317 tprintf("ERROR: Could not find string value for flag %s\n",
318 lhs.string());
319 exit(1);
320 } else {
321 string_val = (*argv)[++i];
322 }
323 }
324 SetStringFlagValue(lhs.string(), string_val);
325 continue;
326 }
327
328 // Flag was not found. Exit with an error message.
329 tprintf("ERROR: Non-existent flag %s\n", (*argv)[i]);
330 exit(1);
331 } // for each argv
332 if (remove_flags) {
333 (*argv)[i - 1] = (*argv)[0];
334 (*argv) += (i - 1);
335 (*argc) -= (i - 1);
336 }
337}
338} // namespace tesseract
339
340#else
341
342#include "base/init_google.h"
343
344namespace tesseract {
345void ParseCommandLineFlags(const char* usage,
346 int* argc, char*** argv,
347 const bool remove_flags) {
348 InitGoogle(usage, argc, argv, remove_flags);
349}
350} // namespace tesseract
351
352#endif
#define ASSERT_HOST(x)
Definition: errcode.h:88
tesseract::ParamsVectors * GlobalParams()
Definition: params.cpp:32
DLLSYM void tprintf(const char *format,...)
Definition: tprintf.cpp:35
void ParseCommandLineFlags(const char *usage, int *argc, char ***argv, const bool remove_flags)
GenericVector< IntParam * > int_params
Definition: params.h:43
GenericVector< DoubleParam * > double_params
Definition: params.h:46
GenericVector< BoolParam * > bool_params
Definition: params.h:44
GenericVector< StringParam * > string_params
Definition: params.h:45
Definition: strngs.h:45
int32_t length() const
Definition: strngs.cpp:189
void assign(const char *cstr, int len)
Definition: strngs.cpp:420
const char * string() const
Definition: strngs.cpp:194