tesseract  5.0.0-alpha-619-ge9db
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 <tesseract/baseapi.h> // TessBaseAPI::Version
15 #include "commandlineflags.h"
16 #include "errcode.h"
17 #include "tprintf.h" // for tprintf
18 
19 #ifndef GOOGLE_TESSERACT
20 
21 namespace tesseract {
22 static 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.c_str(), GlobalParams()->int_params, empty);
28  if (p == nullptr) return false;
29  *value = (int32_t)(*p);
30  return true;
31 }
32 
33 static 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.c_str(), GlobalParams()->double_params, empty);
39  if (p == nullptr) return false;
40  *value = static_cast<double>(*p);
41  return true;
42 }
43 
44 static 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.c_str(), GlobalParams()->bool_params, empty);
50  if (p == nullptr) return false;
51  *value = bool(*p);
52  return true;
53 }
54 
55 static 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.c_str(), GlobalParams()->string_params, empty);
61  *value = (p != nullptr) ? p->c_str() : nullptr;
62  return p != nullptr;
63 }
64 
65 static 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.c_str(), GlobalParams()->int_params, empty);
71  ASSERT_HOST(p != nullptr);
72  p->set_value(new_val);
73 }
74 
75 static 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.c_str(), GlobalParams()->double_params, empty);
81  ASSERT_HOST(p != nullptr);
82  p->set_value(new_val);
83 }
84 
85 static 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.c_str(), GlobalParams()->bool_params, empty);
91  ASSERT_HOST(p != nullptr);
92  p->set_value(new_val);
93 }
94 
95 static 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.c_str(), GlobalParams()->string_params, empty);
101  ASSERT_HOST(p != nullptr);
102  p->set_value(STRING(new_val));
103 }
104 
105 static 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 
111 static 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 
125 static 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]->c_str());
162  }
163  }
164 }
165 
166 void 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.c_str(), &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.c_str());
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.c_str(), int_val);
248  continue;
249  }
250 
251  // double flag
252  double double_val;
253  if (DoubleFlagExists(lhs.c_str(), &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.c_str());
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.c_str(), 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.c_str(), &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.c_str(), bool_val);
306  continue;
307  }
308 
309  // string flag
310  const char* string_val;
311  if (StringFlagExists(lhs.c_str(), &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.c_str());
319  exit(1);
320  } else {
321  string_val = (*argv)[++i];
322  }
323  }
324  SetStringFlagValue(lhs.c_str(), 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 
344 namespace tesseract {
345 void 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
ASSERT_HOST
#define ASSERT_HOST(x)
Definition: errcode.h:87
STRING
Definition: strngs.h:45
tesseract::ParamsVectors::int_params
GenericVector< IntParam * > int_params
Definition: params.h:57
tesseract::ParseCommandLineFlags
void ParseCommandLineFlags(const char *usage, int *argc, char ***argv, const bool remove_flags)
Definition: commandlineflags.cpp:166
tesseract::ParamsVectors::double_params
GenericVector< DoubleParam * > double_params
Definition: params.h:60
tesseract::ParamsVectors::string_params
GenericVector< StringParam * > string_params
Definition: params.h:59
baseapi.h
STRING::c_str
const char * c_str() const
Definition: strngs.cpp:192
GlobalParams
tesseract::ParamsVectors * GlobalParams()
Definition: params.cpp:32
tesseract::TessBaseAPI::Version
static const char * Version()
Definition: baseapi.cpp:233
tesseract
Definition: baseapi.h:65
tprintf.h
GenericVector
Definition: baseapi.h:40
STRING::length
int32_t length() const
Definition: strngs.cpp:187
STRING::assign
void assign(const char *cstr, int len)
Definition: strngs.cpp:413
tprintf
DLLSYM void tprintf(const char *format,...)
Definition: tprintf.cpp:34
errcode.h
commandlineflags.h
tesseract::ParamsVectors::bool_params
GenericVector< BoolParam * > bool_params
Definition: params.h:58