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