Renesas GR-PEACH OpenCV Development / gr-peach-opencv-project-sd-card_update

Fork of gr-peach-opencv-project-sd-card by the do

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers command_line_parser.cpp Source File

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