diff --git a/modules/core/doc/command_line_parser.rst b/modules/core/doc/command_line_parser.rst index 5f0e512c8..c54e65b80 100644 --- a/modules/core/doc/command_line_parser.rst +++ b/modules/core/doc/command_line_parser.rst @@ -58,15 +58,15 @@ The sample below demonstrates how to use CommandLineParser: } int N = parser.get("N"); - double fps = parser.getparser("fps"); + double fps = parser.get("fps"); std::string path = parser.get("path"); - use_time_stamp = parserer.has("timestamp"); + use_time_stamp = parser.has("timestamp"); - std::string img1 = parser.get(1); - std::string img2 = parser.get(2); + std::string img1 = parser.get(0); + std::string img2 = parser.get(1); - int repeat = parser.get(3); + int repeat = parser.get(2); if (!parser.check()) { diff --git a/modules/core/include/opencv2/core/core.hpp b/modules/core/include/opencv2/core/core.hpp index 2496c805c..44941aff4 100644 --- a/modules/core/include/opencv2/core/core.hpp +++ b/modules/core/include/opencv2/core/core.hpp @@ -221,7 +221,7 @@ CV_EXPORTS void setNumThreads(int nthreads); CV_EXPORTS int getNumThreads(); CV_EXPORTS int getThreadNum(); -CV_EXPORTS_W const std::string& getBuildInformation(); +CV_EXPORTS_W const string& getBuildInformation(); //! Returns the number of ticks. @@ -4434,7 +4434,7 @@ protected: struct CV_EXPORTS Param { - enum { INT=0, BOOLEAN=1, REAL=2, STRING=3, MAT=4, MAT_VECTOR=5, ALGORITHM=6 }; + enum { INT=0, BOOLEAN=1, REAL=2, STRING=3, MAT=4, MAT_VECTOR=5, ALGORITHM=6, FLOAT=7, UNSIGNED_INT=8, UINT64=9 }; Param(); Param(int _type, bool _readonly, int _offset, @@ -4505,142 +4505,73 @@ template<> struct ParamType enum { type = Param::ALGORITHM }; }; -// The CommandLineParser class is designed for command line arguments parsing - -class CV_EXPORTS CommandLineParserParams +template<> struct ParamType { - public: - std::string help_message; - std::string def_value; - std::vector keys; - int number; + typedef float const_param_type; + typedef float member_type; + + enum { type = Param::FLOAT }; +}; + +template<> struct ParamType +{ + typedef unsigned const_param_type; + typedef unsigned member_type; + + enum { type = Param::UNSIGNED_INT }; }; -template -std::string get_type_name() { return "UNKNOW"; } - -bool cmp_params(const CommandLineParserParams & p1, const CommandLineParserParams & p2); - -template -T from_str(const std::string & str) +template<> struct ParamType { - T value; - std::stringstream ss(str); - ss >> value; + typedef uint64 const_param_type; + typedef uint64 member_type; + + enum { type = Param::UINT64 }; +}; - if (ss.fail()) - { - std::string err_msg = - std::string("can not convert: [") - + str - + std::string("] to [") - + get_type_name() - + std::string("]"); - CV_Error(CV_StsBadArg, err_msg); - } - - return value; -} - -template<> std::string from_str(const std::string & str); - -template -std::string to_str(T value) -{ - std::ostringstream os; - os << value; - return os.str(); -} +// The CommandLineParser class is designed for command line arguments parsing class CV_EXPORTS CommandLineParser { - public: - CommandLineParser(int argc, const char * const argv[], const std::string keys); +public: + CommandLineParser(int argc, const char* const argv[], const string& keys); + CommandLineParser(const CommandLineParser& parser); + CommandLineParser& operator = (const CommandLineParser& parser); - std::string getPathToApplication(); + string getPathToApplication() const; - template - T get(const std::string& name, bool space_delete = true) - { - try - { - for (size_t i = 0; i < data.size(); i++) - { - for (size_t j = 0; j < data[i].keys.size(); j++) - { - if (name.compare(data[i].keys[j]) == 0) - { - std::string v = data[i].def_value; - if (space_delete == true) v = cat_string(v); - return from_str(v); - } - } - } - error = true; - error_message += "Unknown parametes " + name + "\n"; - } - catch (std::exception& e) - { - error = true; - error_message += "Exception: " + std::string(e.what()) + "\n"; - } - return T(); - } + template + T get(const string& name, bool space_delete = true) const + { + T val = T(); + getByName(name, space_delete, ParamType::type, (void*)&val); + return val; + } - template - T get(int index, bool space_delete = true) - { - try - { - for (size_t i = 0; i < data.size(); i++) - { - if (data[i].number == index - 1) - { - std::string v = data[i].def_value; - if (space_delete == true) v = cat_string(v); - return from_str(v); - } - } - error = true; - error_message += "Unknown parametes #" + to_str(index) + "\n"; - } - catch(std::exception & e) - { - error = true; - error_message += "Exception: " + std::string(e.what()) + "\n"; - } - return T(); - } - - bool has(const std::string& name); - - bool check(); - - void about(std::string message); - - void printMessage(); - void printErrors(); - - protected: - bool error; - std::string error_message; - std::string about_message; - - std::string path_to_app; - std::string app_name; - - std::vector data; - - std::vector split_range_string(std::string str, char fs, char ss); - std::vector split_string(std::string str, char symbol = ' ', bool create_empty_item = false); - std::string cat_string(std::string str); - - void apply_params(std::string key, std::string value); - void apply_params(int i, std::string value); - - void sort_params(); + template + T get(int index, bool space_delete = true) const + { + T val = T(); + getByIndex(index, space_delete, ParamType::type, (void*)&val); + return val; + } + + bool has(const string& name) const; + + bool check() const; + + void about(const string& message); + + void printMessage() const; + void printErrors() const; +protected: + void getByName(const string& name, bool space_delete, int type, void* dst) const; + void getByIndex(int index, bool space_delete, int type, void* dst) const; + + struct Impl; + Impl* impl; }; /////////////////////////////// Parallel Primitives ////////////////////////////////// diff --git a/modules/core/src/command_line_parser.cpp b/modules/core/src/command_line_parser.cpp index dc137e729..8cfeaf3ca 100644 --- a/modules/core/src/command_line_parser.cpp +++ b/modules/core/src/command_line_parser.cpp @@ -5,402 +5,501 @@ namespace cv { - bool cmp_params(const CommandLineParserParams & p1, const CommandLineParserParams & p2) + +struct CommandLineParserParams +{ +public: + string help_message; + string def_value; + vector keys; + int number; +}; + + +struct CommandLineParser::Impl +{ + bool error; + string error_message; + string about_message; + + string path_to_app; + string app_name; + + vector data; + + vector split_range_string(const string& str, char fs, char ss) const; + vector split_string(const string& str, char symbol = ' ', bool create_empty_item = false) const; + string cat_string(const string& str) const; + + void apply_params(const string& key, const string& value); + void apply_params(int i, string value); + + void sort_params(); + int refcount; +}; + + +static string get_type_name(int type) +{ + if( type == Param::INT ) + return "int"; + if( type == Param::UNSIGNED_INT ) + return "unsigned"; + if( type == Param::UINT64 ) + return "unsigned long long"; + if( type == Param::FLOAT ) + return "float"; + if( type == Param::REAL ) + return "double"; + if( type == Param::STRING ) + return "string"; + return "unknown"; +} + +static void from_str(const string& str, int type, void* dst) +{ + std::stringstream ss(str); + if( type == Param::INT ) + ss >> *(int*)dst; + else if( type == Param::UNSIGNED_INT ) + ss >> *(unsigned*)dst; + else if( type == Param::UINT64 ) + ss >> *(uint64*)dst; + else if( type == Param::FLOAT ) + ss >> *(float*)dst; + else if( type == Param::REAL ) + ss >> *(double*)dst; + else if( type == Param::STRING ) + ss >> *(string*)dst; + + if (ss.fail()) { - if (p1.number > p2.number) + string err_msg = "can not convert: [" + str + + + "] to [" + get_type_name(type) + "]"; + + CV_Error(CV_StsBadArg, err_msg); + } +} + +void CommandLineParser::getByName(const string& name, bool space_delete, int type, void* dst) const +{ + try + { + for (size_t i = 0; i < impl->data.size(); i++) + { + for (size_t j = 0; j < impl->data[i].keys.size(); j++) + { + if (name.compare(impl->data[i].keys[j]) == 0) + { + string v = impl->data[i].def_value; + if (space_delete) + v = impl->cat_string(v); + from_str(v, type, dst); + return; + } + } + } + impl->error = true; + impl->error_message += "Unknown parametes " + name + "\n"; + } + catch (std::exception& e) + { + impl->error = true; + impl->error_message += "Exception: " + string(e.what()) + "\n"; + } +} + + +void CommandLineParser::getByIndex(int index, bool space_delete, int type, void* dst) const +{ + try + { + for (size_t i = 0; i < impl->data.size(); i++) + { + if (impl->data[i].number == index) + { + string v = impl->data[i].def_value; + if (space_delete == true) v = impl->cat_string(v); + from_str(v, type, dst); + return; + } + } + impl->error = true; + impl->error_message += "Unknown parametes #" + format("%d", index) + "\n"; + } + catch(std::exception & e) + { + impl->error = true; + impl->error_message += "Exception: " + string(e.what()) + "\n"; + } +} + +static bool cmp_params(const CommandLineParserParams & p1, const CommandLineParserParams & p2) +{ + if (p1.number > p2.number) + return false; + + if (p1.number == -1 && p2.number == -1) + { + if (p1.keys[0].compare(p2.keys[0]) > 0) + { return false; - - if (p1.number == -1 && p2.number == -1) - { - if (p1.keys[0].compare(p2.keys[0]) > 0) - { - return false; - } - } - - return true; - } - - CommandLineParser::CommandLineParser(int argc, const char * const argv[], const std::string keys) - { - // path to application - size_t pos_s = std::string(argv[0]).find_last_of("/\\"); - if (pos_s == std::string::npos) - { - path_to_app = ""; - app_name = std::string(argv[0]); - } - else - { - path_to_app = std::string(argv[0]).substr(0, pos_s); - app_name = std::string(argv[0]).substr(pos_s + 1, std::string(argv[0]).length() - pos_s); - } - - error = false; - error_message = ""; - - // parse keys - std::vector k = split_range_string(keys, '{', '}'); - - int jj = 0; - for (size_t i = 0; i < k.size(); i++) - { - std::vector l = split_string(k[i], '|', true); - CommandLineParserParams p; - p.keys = split_string(l[0]); - p.def_value = l[1]; - p.help_message = cat_string(l[2]); - p.number = -1; - if (p.keys[0][0] == '@') - { - p.number = jj; - jj++; - } - - data.push_back(p); - } - - // parse argv - jj = 0; - for (int i = 1; i < argc; i++) - { - std::string s = std::string(argv[i]); - - if (s.find('=') != std::string::npos && s.find('=') < s.length()) - { - std::vector k_v = split_string(s, '=', true); - for (int h = 0; h < 2; h++) - { - if (k_v[0][0] == '-') - k_v[0] = k_v[0].substr(1, k_v[0].length() -1); - } - apply_params(k_v[0], k_v[1]); - } - else if (s.length() > 1 && s[0] == '-') - { - for (int h = 0; h < 2; h++) - { - if (s[0] == '-') - s = s.substr(1, s.length() - 1); - } - apply_params(s, "true"); - } - else if (s[0] != '-') - { - apply_params(jj, s); - jj++; - } - } - - sort_params(); - } - - void CommandLineParser::about(std::string message) - { - about_message = message; - } - - void CommandLineParser::apply_params(std::string key, std::string value) - { - for (size_t i = 0; i < data.size(); i++) - { - for (size_t k = 0; k < data[i].keys.size(); k++) - { - if (key.compare(data[i].keys[k]) == 0) - { - data[i].def_value = value; - break; - } - } } } - void CommandLineParser::apply_params(int i, std::string value) + return true; +} + +CommandLineParser::CommandLineParser(int argc, const char* const argv[], const string& keys) +{ + impl = new Impl; + impl->refcount = 1; + + // path to application + size_t pos_s = string(argv[0]).find_last_of("/\\"); + if (pos_s == string::npos) { - for (size_t j = 0; j < data.size(); j++) + impl->path_to_app = ""; + impl->app_name = string(argv[0]); + } + else + { + impl->path_to_app = string(argv[0]).substr(0, pos_s); + impl->app_name = string(argv[0]).substr(pos_s + 1, string(argv[0]).length() - pos_s); + } + + impl->error = false; + impl->error_message = ""; + + // parse keys + vector k = impl->split_range_string(keys, '{', '}'); + + int jj = 0; + for (size_t i = 0; i < k.size(); i++) + { + vector l = impl->split_string(k[i], '|', true); + CommandLineParserParams p; + p.keys = impl->split_string(l[0]); + p.def_value = l[1]; + p.help_message = impl->cat_string(l[2]); + p.number = -1; + if (p.keys[0][0] == '@') { - if (data[j].number == i) + p.number = jj; + jj++; + } + + impl->data.push_back(p); + } + + // parse argv + jj = 0; + for (int i = 1; i < argc; i++) + { + string s = string(argv[i]); + + if (s.find('=') != string::npos && s.find('=') < s.length()) + { + vector k_v = impl->split_string(s, '=', true); + for (int h = 0; h < 2; h++) { - data[j].def_value = value; + if (k_v[0][0] == '-') + k_v[0] = k_v[0].substr(1, k_v[0].length() -1); + } + impl->apply_params(k_v[0], k_v[1]); + } + else if (s.length() > 1 && s[0] == '-') + { + for (int h = 0; h < 2; h++) + { + if (s[0] == '-') + s = s.substr(1, s.length() - 1); + } + impl->apply_params(s, "true"); + } + else if (s[0] != '-') + { + impl->apply_params(jj, s); + jj++; + } + } + + impl->sort_params(); +} + + +CommandLineParser::CommandLineParser(const CommandLineParser& parser) +{ + impl = parser.impl; + CV_XADD(&impl->refcount, 1); +} + +CommandLineParser& CommandLineParser::operator = (const CommandLineParser& parser) +{ + if( this != &parser ) + { + if(CV_XADD(&impl->refcount, -1) == 1) + delete impl; + impl = parser.impl; + CV_XADD(&impl->refcount, 1); + } + return *this; +} + +void CommandLineParser::about(const string& message) +{ + impl->about_message = message; +} + +void CommandLineParser::Impl::apply_params(const string& key, const string& value) +{ + for (size_t i = 0; i < data.size(); i++) + { + for (size_t k = 0; k < data[i].keys.size(); k++) + { + if (key.compare(data[i].keys[k]) == 0) + { + data[i].def_value = value; break; } } } +} - void CommandLineParser::sort_params() +void CommandLineParser::Impl::apply_params(int i, string value) +{ + for (size_t j = 0; j < data.size(); j++) { - for (size_t i = 0; i < data.size(); i++) + if (data[j].number == i) { - sort(data[i].keys.begin(), data[i].keys.end()); + data[j].def_value = value; + break; } + } +} - sort (data.begin(), data.end(), cmp_params); +void CommandLineParser::Impl::sort_params() +{ + for (size_t i = 0; i < data.size(); i++) + { + sort(data[i].keys.begin(), data[i].keys.end()); } - std::string CommandLineParser::cat_string(std::string str) + sort (data.begin(), data.end(), cmp_params); +} + +string CommandLineParser::Impl::cat_string(const string& str) const +{ + int left = 0, right = (int)str.length(); + while( left <= right && str[left] == ' ' ) + left++; + while( right > left && str[right-1] == ' ' ) + right--; + return left >= right ? string("") : str.substr(left, right-left); +} + +string CommandLineParser::getPathToApplication() const +{ + return impl->path_to_app; +} + +bool CommandLineParser::has(const string& name) const +{ + for (size_t i = 0; i < impl->data.size(); i++) { - while (!str.empty() && str[0] == ' ') + for (size_t j = 0; j < impl->data[i].keys.size(); j++) { - str = str.substr(1, str.length() - 1); - } - - while (!str.empty() && str[str.length() - 1] == ' ') - { - str = str.substr(0, str.length() - 1); - } - - return str; - } - - std::string CommandLineParser::getPathToApplication() - { - return path_to_app; - } - - bool CommandLineParser::has(const std::string& name) - { - for (size_t i = 0; i < data.size(); i++) - { - for (size_t j = 0; j < data[i].keys.size(); j++) + if (name.compare(impl->data[i].keys[j]) == 0 && string("true").compare(impl->data[i].def_value) == 0) { - if (name.compare(data[i].keys[j]) == 0 && std::string("true").compare(data[i].def_value) == 0) - { - return true; - } + return true; } } - return false; } + return false; +} - bool CommandLineParser::check() +bool CommandLineParser::check() const +{ + return impl->error == false; +} + +void CommandLineParser::printErrors() const +{ + if (impl->error) { - return error == false; + std::cout << std::endl << "ERRORS:" << std::endl << impl->error_message << std::endl; } +} - void CommandLineParser::printErrors() +void CommandLineParser::printMessage() const +{ + if (impl->about_message != "") + std::cout << impl->about_message << std::endl; + + std::cout << "Usage: " << impl->app_name << " [params] "; + + for (size_t i = 0; i < impl->data.size(); i++) { - if (error) + if (impl->data[i].number > -1) { - std::cout << std::endl << "ERRORS:" << std::endl << error_message << std::endl; + string name = impl->data[i].keys[0].substr(1, impl->data[i].keys[0].length() - 1); + std::cout << name << " "; } } - void CommandLineParser::printMessage() + std::cout << std::endl << std::endl; + + for (size_t i = 0; i < impl->data.size(); i++) { - if (about_message != "") - std::cout << about_message << std::endl; - - std::cout << "Usage: " << app_name << " [params] "; - - for (size_t i = 0; i < data.size(); i++) + if (impl->data[i].number == -1) { - if (data[i].number > -1) + std::cout << "\t"; + for (size_t j = 0; j < impl->data[i].keys.size(); j++) { - std::string name = data[i].keys[0].substr(1, data[i].keys[0].length() - 1); - std::cout << name << " "; - } - } - - std::cout << std::endl << std::endl; - - for (size_t i = 0; i < data.size(); i++) - { - if (data[i].number == -1) - { - std::cout << "\t"; - for (size_t j = 0; j < data[i].keys.size(); j++) + string k = impl->data[i].keys[j]; + if (k.length() > 1) { - std::string k = data[i].keys[j]; - if (k.length() > 1) - { - std::cout << "--"; - } - else - { - std::cout << "-"; - } - std::cout << k; - - if (j != data[i].keys.size() - 1) - { - std::cout << ", "; - } + std::cout << "--"; } - std::string dv = cat_string(data[i].def_value); - if (dv.compare("") != 0) + else { - std::cout << " (value:" << dv << ")"; + std::cout << "-"; } - std::cout << std::endl << "\t\t" << data[i].help_message << std::endl; - } - } - std::cout << std::endl; - - for (size_t i = 0; i < data.size(); i++) - { - if (data[i].number != -1) - { - std::cout << "\t"; - std::string k = data[i].keys[0]; - k = k.substr(1, k.length() - 1); - std::cout << k; - std::string dv = cat_string(data[i].def_value); - if (dv.compare("") != 0) + if (j != impl->data[i].keys.size() - 1) { - std::cout << " (value:" << dv << ")"; + std::cout << ", "; } - std::cout << std::endl << "\t\t" << data[i].help_message << std::endl; } + string dv = impl->cat_string(impl->data[i].def_value); + if (dv.compare("") != 0) + { + std::cout << " (value:" << dv << ")"; + } + std::cout << std::endl << "\t\t" << impl->data[i].help_message << std::endl; } } + std::cout << std::endl; - std::vector CommandLineParser::split_range_string(std::string str, char fs, char ss) + for (size_t i = 0; i < impl->data.size(); i++) { - std::vector vec; - std::string word = ""; - bool begin = false; - - while (!str.empty()) + if (impl->data[i].number != -1) { - if (str[0] == fs) - { - if (begin == true) - { - CV_Error(CV_StsParseError, - std::string("error in split_range_string(") - + str - + std::string(", ") - + std::string(1, fs) - + std::string(", ") - + std::string(1, ss) - + std::string(")") - ); - } - begin = true; - word = ""; - str = str.substr(1, str.length() - 1); - } + std::cout << "\t"; + string k = impl->data[i].keys[0]; + k = k.substr(1, k.length() - 1); - if (str[0] == ss) - { - if (begin == false) - { - CV_Error(CV_StsParseError, - std::string("error in split_range_string(") - + str - + std::string(", ") - + std::string(1, fs) - + std::string(", ") - + std::string(1, ss) - + std::string(")") - ); - } - begin = false; - vec.push_back(word); - } + std::cout << k; + string dv = impl->cat_string(impl->data[i].def_value); + if (dv.compare("") != 0) + { + std::cout << " (value:" << dv << ")"; + } + std::cout << std::endl << "\t\t" << impl->data[i].help_message << std::endl; + } + } +} + +vector CommandLineParser::Impl::split_range_string(const string& _str, char fs, char ss) const +{ + string str = _str; + vector vec; + string word = ""; + bool begin = false; + + while (!str.empty()) + { + if (str[0] == fs) + { if (begin == true) { - word += str[0]; + CV_Error(CV_StsParseError, + string("error in split_range_string(") + + str + + string(", ") + + string(1, fs) + + string(", ") + + string(1, ss) + + string(")") + ); } + begin = true; + word = ""; str = str.substr(1, str.length() - 1); } + if (str[0] == ss) + { + if (begin == false) + { + CV_Error(CV_StsParseError, + string("error in split_range_string(") + + str + + string(", ") + + string(1, fs) + + string(", ") + + string(1, ss) + + string(")") + ); + } + begin = false; + vec.push_back(word); + } + if (begin == true) { - CV_Error(CV_StsParseError, - std::string("error in split_range_string(") - + str - + std::string(", ") - + std::string(1, fs) - + std::string(", ") - + std::string(1, ss) - + std::string(")") - ); + word += str[0]; } - - return vec; + str = str.substr(1, str.length() - 1); } - std::vector CommandLineParser::split_string(std::string str, char symbol, bool create_empty_item) + if (begin == true) { - std::vector vec; - std::string word = ""; - - while (!str.empty()) - { - if (str[0] == symbol) - { - if (!word.empty() || create_empty_item) - { - vec.push_back(word); - word = ""; - } - } - else - { - word += str[0]; - } - str = str.substr(1, str.length() - 1); - } - - if (word != "" || create_empty_item) - { - vec.push_back(word); - } - - return vec; + CV_Error(CV_StsParseError, + string("error in split_range_string(") + + str + + string(", ") + + string(1, fs) + + string(", ") + + string(1, ss) + + string(")") + ); } - #undef clp_get - #define clp_get(T) template<> T CommandLineParser::get(const std::string& name, bool space_delete); + return vec; +} - clp_get(int) - clp_get(unsigned int) - clp_get(long) - clp_get(unsigned long) - clp_get(long long) - clp_get(unsigned long long) - clp_get(size_t) - clp_get(float) - clp_get(double) - clp_get(uint64) - clp_get(int64) - clp_get(std::string) +vector CommandLineParser::Impl::split_string(const string& _str, char symbol, bool create_empty_item) const +{ + string str = _str; + vector vec; + string word = ""; - #undef clp_from_str - #define clp_from_str(T) template<> T from_str(const std::string & str); - - clp_from_str(int) - clp_from_str(unsigned int) - clp_from_str(long) - clp_from_str(unsigned long) - clp_from_str(long long) - clp_from_str(unsigned long long) - clp_from_str(size_t) - clp_from_str(uint64) - clp_from_str(int64) - clp_from_str(float) - clp_from_str(double) - - template<> - std::string from_str(const std::string & str) + while (!str.empty()) { - return str; + if (str[0] == symbol) + { + if (!word.empty() || create_empty_item) + { + vec.push_back(word); + word = ""; + } + } + else + { + word += str[0]; + } + str = str.substr(1, str.length() - 1); } - #undef clp_type_name - #define clp_type_name(type, name) template<> std::string get_type_name() { return std::string(name);} + if (word != "" || create_empty_item) + { + vec.push_back(word); + } - clp_type_name(int, "int") - clp_type_name(unsigned int, "unsigned int") - clp_type_name(long, "long") - clp_type_name(long long, "long long") - clp_type_name(unsigned long long, "unsigned long long") - clp_type_name(size_t, "size_t") - clp_type_name(float, "float") - clp_type_name(double, "double") + return vec; +} }