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