Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of gr-peach-opencv-project-sd-card by
command_line_parser.cpp
00001 #include "precomp.hpp" 00002 #include <sstream> 00003 00004 namespace cv 00005 { 00006 00007 namespace { 00008 static const char* noneValue = "<none>"; 00009 00010 static String cat_string(const String& str) 00011 { 00012 int left = 0, right = (int)str.length(); 00013 while( left <= right && str[left] == ' ' ) 00014 left++; 00015 while( right > left && str[right-1] == ' ' ) 00016 right--; 00017 return left >= right ? String("") : str.substr(left, right-left); 00018 } 00019 } 00020 00021 struct CommandLineParserParams 00022 { 00023 public: 00024 String help_message; 00025 String def_value; 00026 std::vector<String> keys; 00027 int number; 00028 }; 00029 00030 00031 struct CommandLineParser::Impl 00032 { 00033 bool error; 00034 String error_message; 00035 String about_message; 00036 00037 String path_to_app; 00038 String app_name; 00039 00040 std::vector<CommandLineParserParams> data; 00041 00042 std::vector<String> split_range_string(const String& str, char fs, char ss) const; 00043 std::vector<String> split_string(const String& str, char symbol = ' ', bool create_empty_item = false) const; 00044 00045 void apply_params(const String& key, const String& value); 00046 void apply_params(int i, String value); 00047 00048 void sort_params(); 00049 int refcount; 00050 }; 00051 00052 00053 static const char* get_type_name(int type) 00054 { 00055 if( type == Param::INT ) 00056 return "int"; 00057 if( type == Param::BOOLEAN ) 00058 return "bool"; 00059 if( type == Param::UNSIGNED_INT ) 00060 return "unsigned"; 00061 if( type == Param::UINT64 ) 00062 return "unsigned long long"; 00063 if( type == Param::FLOAT ) 00064 return "float"; 00065 if( type == Param::REAL ) 00066 return "double"; 00067 if( type == Param::STRING ) 00068 return "string"; 00069 return "unknown"; 00070 } 00071 00072 static void from_str(const String& str, int type, void* dst) 00073 { 00074 std::stringstream ss(str.c_str()); 00075 if( type == Param::INT ) 00076 ss >> *(int*)dst; 00077 else if( type == Param::BOOLEAN ) 00078 { 00079 std::string temp; 00080 ss >> temp; 00081 *(bool*) dst = temp == "true"; 00082 } 00083 else if( type == Param::UNSIGNED_INT ) 00084 ss >> *(unsigned*)dst; 00085 else if( type == Param::UINT64 ) 00086 ss >> *(uint64*)dst; 00087 else if( type == Param::FLOAT ) 00088 ss >> *(float*)dst; 00089 else if( type == Param::REAL ) 00090 ss >> *(double*)dst; 00091 else if( type == Param::STRING ) 00092 *(String*)dst = str; 00093 else 00094 CV_Error(Error::StsBadArg, "unknown/unsupported parameter type"); 00095 00096 if (ss.fail()) 00097 { 00098 CV_Error_(Error::StsBadArg, ("can not convert: [%s] to [%s]", str.c_str(), get_type_name(type))); 00099 } 00100 } 00101 00102 void CommandLineParser::getByName(const String& name, bool space_delete, int type, void* dst) const 00103 { 00104 //try 00105 // { 00106 for (size_t i = 0; i < impl->data.size(); i++) 00107 { 00108 for (size_t j = 0; j < impl->data[i].keys.size(); j++) 00109 { 00110 if (name == impl->data[i].keys[j]) 00111 { 00112 String v = impl->data[i].def_value; 00113 if (space_delete) 00114 v = cat_string(v); 00115 00116 // the key was neither specified nor has it a default value 00117 if((v.empty() && type != Param::STRING) || v == noneValue) { 00118 impl->error = true; 00119 impl->error_message = impl->error_message + "Missing parameter: '" + name + "'\n"; 00120 return; 00121 } 00122 00123 from_str(v, type, dst); 00124 return; 00125 } 00126 } 00127 } 00128 //} 00129 // catch (Exception& e) 00130 // { 00131 // impl->error = true; 00132 // impl->error_message = impl->error_message + "Parameter '"+ name + "': " + e.err + "\n"; 00133 // return; 00134 // } 00135 00136 CV_Error_(Error::StsBadArg, ("undeclared key '%s' requested", name.c_str())); 00137 } 00138 00139 00140 void CommandLineParser::getByIndex(int index, bool space_delete, int type, void* dst) const 00141 { 00142 //try 00143 // { 00144 for (size_t i = 0; i < impl->data.size(); i++) 00145 { 00146 if (impl->data[i].number == index) 00147 { 00148 String v = impl->data[i].def_value; 00149 if (space_delete == true) v = cat_string(v); 00150 00151 // the key was neither specified nor has it a default value 00152 if((v.empty() && type != Param::STRING) || v == noneValue) { 00153 impl->error = true; 00154 impl->error_message = impl->error_message + format("Missing parameter #%d\n", index); 00155 return; 00156 } 00157 from_str(v, type, dst); 00158 return; 00159 } 00160 } 00161 //} 00162 // catch(Exception& e) 00163 // { 00164 // impl->error = true; 00165 // impl->error_message = impl->error_message + format("Parameter #%d: ", index) + e.err + "\n"; 00166 // return; 00167 // } 00168 00169 CV_Error_(Error::StsBadArg, ("undeclared position %d requested", index)); 00170 } 00171 00172 static bool cmp_params(const CommandLineParserParams & p1, const CommandLineParserParams & p2) 00173 { 00174 if (p1.number < p2.number) 00175 return true; 00176 00177 if (p1.number > p2.number) 00178 return false; 00179 00180 return p1.keys[0].compare(p2.keys[0]) < 0; 00181 } 00182 00183 CommandLineParser::CommandLineParser(int argc, const char* const argv[], const String& keys) 00184 { 00185 impl = new Impl; 00186 impl->refcount = 1; 00187 00188 // path to application 00189 size_t pos_s = String(argv[0]).find_last_of("/\\"); 00190 if (pos_s == String::npos) 00191 { 00192 impl->path_to_app = ""; 00193 impl->app_name = String(argv[0]); 00194 } 00195 else 00196 { 00197 impl->path_to_app = String(argv[0]).substr(0, pos_s); 00198 impl->app_name = String(argv[0]).substr(pos_s + 1, String(argv[0]).length() - pos_s); 00199 } 00200 00201 impl->error = false; 00202 impl->error_message = ""; 00203 00204 // parse keys 00205 std::vector<String> k = impl->split_range_string(keys, '{', '}'); 00206 00207 int jj = 0; 00208 for (size_t i = 0; i < k.size(); i++) 00209 { 00210 std::vector<String> l = impl->split_string(k[i], '|', true); 00211 CommandLineParserParams p; 00212 p.keys = impl->split_string(l[0]); 00213 p.def_value = l[1]; 00214 p.help_message = cat_string(l[2]); 00215 p.number = -1; 00216 if (p.keys.size() <= 0) 00217 { 00218 impl->error = true; 00219 impl->error_message = "Field KEYS could not be empty\n"; 00220 } 00221 else 00222 { 00223 if (p.keys[0][0] == '@') 00224 { 00225 p.number = jj; 00226 jj++; 00227 } 00228 00229 impl->data.push_back(p); 00230 } 00231 } 00232 00233 // parse argv 00234 jj = 0; 00235 for (int i = 1; i < argc; i++) 00236 { 00237 String s(argv[i]); 00238 bool hasSingleDash = s.length() > 1 && s[0] == '-'; 00239 00240 if (hasSingleDash) 00241 { 00242 bool hasDoubleDash = s.length() > 2 && s[1] == '-'; 00243 String key = s.substr(hasDoubleDash ? 2 : 1); 00244 String value = "true"; 00245 size_t equalsPos = key.find('='); 00246 00247 if(equalsPos != String::npos) { 00248 value = key.substr(equalsPos + 1); 00249 key = key.substr(0, equalsPos); 00250 } 00251 impl->apply_params(key, value); 00252 } 00253 else 00254 { 00255 impl->apply_params(jj, s); 00256 jj++; 00257 } 00258 } 00259 00260 impl->sort_params(); 00261 } 00262 00263 CommandLineParser::~CommandLineParser() 00264 { 00265 if (CV_XADD(&impl->refcount, -1) == 1) 00266 delete impl; 00267 } 00268 00269 CommandLineParser::CommandLineParser(const CommandLineParser& parser) 00270 { 00271 impl = parser.impl; 00272 CV_XADD(&impl->refcount, 1); 00273 } 00274 00275 CommandLineParser& CommandLineParser::operator = (const CommandLineParser& parser) 00276 { 00277 if( this != &parser ) 00278 { 00279 if(CV_XADD(&impl->refcount, -1) == 1) 00280 delete impl; 00281 impl = parser.impl; 00282 CV_XADD(&impl->refcount, 1); 00283 } 00284 return *this; 00285 } 00286 00287 void CommandLineParser::about(const String& message) 00288 { 00289 impl->about_message = message; 00290 } 00291 00292 void CommandLineParser::Impl::apply_params(const String& key, const String& value) 00293 { 00294 for (size_t i = 0; i < data.size(); i++) 00295 { 00296 for (size_t k = 0; k < data[i].keys.size(); k++) 00297 { 00298 if (key.compare(data[i].keys[k]) == 0) 00299 { 00300 data[i].def_value = value; 00301 break; 00302 } 00303 } 00304 } 00305 } 00306 00307 void CommandLineParser::Impl::apply_params(int i, String value) 00308 { 00309 for (size_t j = 0; j < data.size(); j++) 00310 { 00311 if (data[j].number == i) 00312 { 00313 data[j].def_value = value; 00314 break; 00315 } 00316 } 00317 } 00318 00319 void CommandLineParser::Impl::sort_params() 00320 { 00321 for (size_t i = 0; i < data.size(); i++) 00322 { 00323 std::sort(data[i].keys.begin(), data[i].keys.end()); 00324 } 00325 00326 std::sort (data.begin(), data.end(), cmp_params); 00327 } 00328 00329 String CommandLineParser::getPathToApplication() const 00330 { 00331 return impl->path_to_app; 00332 } 00333 00334 bool CommandLineParser::has(const String& name) const 00335 { 00336 for (size_t i = 0; i < impl->data.size(); i++) 00337 { 00338 for (size_t j = 0; j < impl->data[i].keys.size(); j++) 00339 { 00340 if (name == impl->data[i].keys[j]) 00341 { 00342 const String v = cat_string(impl->data[i].def_value); 00343 return !v.empty() && v != noneValue; 00344 } 00345 } 00346 } 00347 00348 CV_Error_(Error::StsBadArg, ("undeclared key '%s' requested", name.c_str())); 00349 return false; 00350 } 00351 00352 bool CommandLineParser::check() const 00353 { 00354 return impl->error == false; 00355 } 00356 00357 void CommandLineParser::printErrors() const 00358 { 00359 if (impl->error) 00360 { 00361 printf("\nERRORS:\n%s\n", impl->error_message.c_str()); 00362 fflush(stdout); 00363 } 00364 } 00365 00366 void CommandLineParser::printMessage() const 00367 { 00368 if (impl->about_message != "") 00369 printf("%s\n", impl->about_message.c_str()); 00370 00371 printf("Usage: %s [params] ", impl->app_name.c_str()); 00372 00373 for (size_t i = 0; i < impl->data.size(); i++) 00374 { 00375 if (impl->data[i].number > -1) 00376 { 00377 String name = impl->data[i].keys[0].substr(1, impl->data[i].keys[0].length() - 1); 00378 printf("%s ", name.c_str()); 00379 } 00380 } 00381 00382 printf("\n\n"); 00383 00384 for (size_t i = 0; i < impl->data.size(); i++) 00385 { 00386 if (impl->data[i].number == -1) 00387 { 00388 printf("\t"); 00389 for (size_t j = 0; j < impl->data[i].keys.size(); j++) 00390 { 00391 String k = impl->data[i].keys[j]; 00392 if (k.length() > 1) 00393 { 00394 printf("--"); 00395 } 00396 else 00397 { 00398 printf("-"); 00399 } 00400 printf("%s", k.c_str()); 00401 00402 if (j != impl->data[i].keys.size() - 1) 00403 { 00404 printf(", "); 00405 } 00406 } 00407 String dv = cat_string(impl->data[i].def_value); 00408 if (dv.compare("") != 0) 00409 { 00410 printf(" (value:%s)", dv.c_str()); 00411 } 00412 printf("\n\t\t%s\n", impl->data[i].help_message.c_str()); 00413 } 00414 } 00415 printf("\n"); 00416 00417 for (size_t i = 0; i < impl->data.size(); i++) 00418 { 00419 if (impl->data[i].number != -1) 00420 { 00421 printf("\t"); 00422 String k = impl->data[i].keys[0]; 00423 k = k.substr(1, k.length() - 1); 00424 00425 printf("%s", k.c_str()); 00426 00427 String dv = cat_string(impl->data[i].def_value); 00428 if (dv.compare("") != 0) 00429 { 00430 printf(" (value:%s)", dv.c_str()); 00431 } 00432 printf("\n\t\t%s\n", impl->data[i].help_message.c_str()); 00433 } 00434 } 00435 } 00436 00437 std::vector<String> CommandLineParser::Impl::split_range_string(const String& _str, char fs, char ss) const 00438 { 00439 String str = _str; 00440 std::vector<String> vec; 00441 String word = ""; 00442 bool begin = false; 00443 00444 while (!str.empty()) 00445 { 00446 if (str[0] == fs) 00447 { 00448 if (begin == true) 00449 { 00450 cv::Exception(CV_StsParseError, 00451 String("error in split_range_string(") 00452 + str 00453 + String(", ") 00454 + String(1, fs) 00455 + String(", ") 00456 + String(1, ss) 00457 + String(")"), 00458 "", __FILE__, __LINE__ 00459 ); 00460 return {}; 00461 } 00462 begin = true; 00463 word = ""; 00464 str = str.substr(1, str.length() - 1); 00465 } 00466 00467 if (str[0] == ss) 00468 { 00469 if (begin == false) 00470 { 00471 cv::Exception(CV_StsParseError, 00472 String("error in split_range_string(") 00473 + str 00474 + String(", ") 00475 + String(1, fs) 00476 + String(", ") 00477 + String(1, ss) 00478 + String(")"), 00479 "", __FILE__, __LINE__ 00480 ); 00481 return {}; 00482 } 00483 begin = false; 00484 vec.push_back(word); 00485 } 00486 00487 if (begin == true) 00488 { 00489 word = word + str[0]; 00490 } 00491 str = str.substr(1, str.length() - 1); 00492 } 00493 00494 if (begin == true) 00495 { 00496 cv::Exception(CV_StsParseError, 00497 String("error in split_range_string(") 00498 + str 00499 + String(", ") 00500 + String(1, fs) 00501 + String(", ") 00502 + String(1, ss) 00503 + String(")"), 00504 "", __FILE__, __LINE__ 00505 ); 00506 return {}; 00507 } 00508 00509 return vec; 00510 } 00511 00512 std::vector<String> CommandLineParser::Impl::split_string(const String& _str, char symbol, bool create_empty_item) const 00513 { 00514 String str = _str; 00515 std::vector<String> vec; 00516 String word = ""; 00517 00518 while (!str.empty()) 00519 { 00520 if (str[0] == symbol) 00521 { 00522 if (!word.empty() || create_empty_item) 00523 { 00524 vec.push_back(word); 00525 word = ""; 00526 } 00527 } 00528 else 00529 { 00530 word = word + str[0]; 00531 } 00532 str = str.substr(1, str.length() - 1); 00533 } 00534 00535 if (word != "" || create_empty_item) 00536 { 00537 vec.push_back(word); 00538 } 00539 00540 return vec; 00541 } 00542 00543 } 00544
Generated on Tue Jul 12 2022 14:46:26 by
