2011-05-21 22:09:03 +08:00
|
|
|
#include "precomp.hpp"
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
using namespace cv;
|
|
|
|
|
2011-06-08 14:45:21 +08:00
|
|
|
void helpParser()
|
|
|
|
{
|
|
|
|
printf("\nThe CommandLineParser class is designed for command line arguments parsing\n"
|
|
|
|
"Supported syntax: \n"
|
|
|
|
" --key1=arg1 or --key3 <The keys with '--' can have argument.\n"
|
|
|
|
"If it has argument, you should assign it through '=' sign> \n"
|
|
|
|
" -key2=arg2 or -key2 <The keys witn '-' can have argument \n"
|
|
|
|
"If it has argument, you should assign it through '=' sign> \n"
|
|
|
|
" key3 <This key can't has any parameter> \n"
|
|
|
|
"Usage: \n"
|
|
|
|
" Imagine that the input parameters are next:\n"
|
|
|
|
" -k=10 --key --db=-10.11 -key1 argument --inputFile=lena.jpg\n"
|
|
|
|
"parser.get<int>(\"k\")<If you need to take 'k' value.\n"
|
|
|
|
" It also works with 'unsigned int', 'double', 'float' and 'string' types>\n"
|
|
|
|
"parser.get<double>(\"db\", 99.99)<If you need to take 'db' value.\n"
|
|
|
|
" If its value is empty, you will get default value 99.99>\n"
|
|
|
|
" It also works with 'int', 'unsigned int', 'float' and 'string' types\n"
|
|
|
|
"parser.get<string>(\"0\")<If you need to take 'key'. It's the first parameter without value\n"
|
|
|
|
" and it has index 0>\n"
|
|
|
|
"parser.get<stirng>(\"1\")<If you need to take 'key1'. It's the second parameter without value\n"
|
|
|
|
" and it has index 1>\n"
|
|
|
|
"parser.get<stirng>(\"2\")<If you need to take 'argument'. It's the third parameter without value\n"
|
|
|
|
" and it has index 2>\n\n"
|
|
|
|
);
|
|
|
|
}
|
2011-05-21 22:09:03 +08:00
|
|
|
|
|
|
|
vector<string> split_string(const string& str, const string& delimiters)
|
|
|
|
{
|
|
|
|
vector<string> res;
|
|
|
|
string::size_type lastPos = str.find_first_not_of(delimiters, 0);
|
|
|
|
string::size_type pos = str.find_first_of(delimiters, lastPos);
|
|
|
|
while (string::npos != pos || string::npos != lastPos)
|
|
|
|
{
|
|
|
|
res.push_back(str.substr(lastPos, pos - lastPos));
|
|
|
|
lastPos = str.find_first_not_of(delimiters, pos);
|
|
|
|
pos = str.find_first_of(delimiters, lastPos);
|
|
|
|
}
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2011-06-07 18:30:40 +08:00
|
|
|
CommandLineParser::CommandLineParser(int argc, const char* argv[])
|
2011-05-21 22:09:03 +08:00
|
|
|
{
|
2011-06-07 18:30:40 +08:00
|
|
|
std::string cur_name;
|
|
|
|
std::string buffer;
|
|
|
|
std::stringstream str_buff(std::stringstream::in | std::stringstream::out);
|
|
|
|
std::map<std::string, std::string >::iterator it;
|
2011-05-21 22:09:03 +08:00
|
|
|
int find_symbol;
|
2011-06-07 18:30:40 +08:00
|
|
|
int index = 0;
|
2011-05-21 22:09:03 +08:00
|
|
|
|
|
|
|
|
2011-06-07 18:30:40 +08:00
|
|
|
for(int i = 1; i < argc; i++)
|
2011-05-21 22:09:03 +08:00
|
|
|
{
|
2011-05-28 14:55:41 +08:00
|
|
|
|
2011-06-07 18:30:40 +08:00
|
|
|
if(!argv[i])
|
|
|
|
break;
|
|
|
|
cur_name = argv[i];
|
|
|
|
if((cur_name.find('-') == 0) && ((int)cur_name.find('=') != -1) &&
|
|
|
|
(cur_name.find('=') != (cur_name.length() - 1)))
|
|
|
|
{
|
|
|
|
while (cur_name.find('-') == 0)
|
|
|
|
cur_name.erase(0,1);
|
|
|
|
|
|
|
|
buffer = cur_name;
|
|
|
|
find_symbol = (int)cur_name.find('=');
|
|
|
|
cur_name.erase(find_symbol);
|
|
|
|
buffer.erase(0, find_symbol + 1);
|
|
|
|
if (data.find(cur_name) != data.end())
|
2011-05-21 22:09:03 +08:00
|
|
|
{
|
2011-06-08 14:45:21 +08:00
|
|
|
printf("CommandLineParser constructor found dublicating parameters for name=%s\n"
|
|
|
|
, cur_name.c_str());
|
|
|
|
printf("Constructor will not continue its work since this moment.\n"
|
|
|
|
"Please enter parameters without dublicates\n");
|
|
|
|
helpParser();
|
|
|
|
data.clear();
|
|
|
|
break;
|
2011-06-07 18:30:40 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
data[cur_name] = buffer;
|
|
|
|
}
|
|
|
|
else if (cur_name.find('=') == 0)
|
|
|
|
{
|
2011-06-08 14:45:21 +08:00
|
|
|
printf("The next key is wrong: key= %s\n", cur_name.c_str());
|
|
|
|
printf("Constructor will not continue its work since this moment.\n"
|
|
|
|
"Please enter parameters without any mistakes\n");
|
|
|
|
helpParser();
|
|
|
|
data.clear();
|
|
|
|
break;
|
2011-06-07 18:30:40 +08:00
|
|
|
}
|
|
|
|
else if(((int)cur_name.find('-') == -1) && ((int)cur_name.find('=') != -1))
|
|
|
|
{
|
2011-06-08 14:45:21 +08:00
|
|
|
printf("The next key must be defined with '--' or '-' increment: key= %s\n", cur_name.c_str());
|
|
|
|
printf("Constructor will not continue its work since this moment.\n"
|
|
|
|
"Please enter parameters without any mistakes\n");
|
|
|
|
helpParser();
|
|
|
|
data.clear();
|
|
|
|
break;
|
2011-06-07 18:30:40 +08:00
|
|
|
}
|
|
|
|
else if (cur_name.find('=') == (cur_name.length() - 1))
|
|
|
|
{
|
2011-06-08 14:45:21 +08:00
|
|
|
printf("The next key must have argument after '=': key= %s\n", cur_name.c_str());
|
|
|
|
printf("Constructor will not continue its work since this moment.\n"
|
|
|
|
"Please enter parameters without any mistakes\n");
|
|
|
|
helpParser();
|
|
|
|
data.clear();
|
|
|
|
break;
|
2011-06-07 18:30:40 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-06-08 14:45:21 +08:00
|
|
|
str_buff << index;
|
|
|
|
while (cur_name.find('-') == 0)
|
|
|
|
cur_name.erase(0,1);
|
|
|
|
|
|
|
|
for(it = data.begin(); it != data.end(); it++)
|
|
|
|
{
|
|
|
|
if (it->second == cur_name)
|
2011-05-28 14:55:41 +08:00
|
|
|
{
|
2011-06-08 14:45:21 +08:00
|
|
|
printf("CommandLineParser constructor found dublicating parameters for name=%s\n"
|
|
|
|
, cur_name.c_str());
|
|
|
|
printf("Constructor will not continue its work since this moment.\n"
|
|
|
|
"Please enter parameters without dublicates\n");
|
|
|
|
helpParser();
|
|
|
|
data.clear();
|
|
|
|
break;
|
2011-05-28 14:55:41 +08:00
|
|
|
}
|
2011-06-08 14:45:21 +08:00
|
|
|
}
|
|
|
|
data[str_buff.str()] = cur_name;
|
|
|
|
str_buff.seekp(0);
|
2011-06-07 18:30:40 +08:00
|
|
|
index++;
|
|
|
|
}
|
2011-05-21 22:09:03 +08:00
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CommandLineParser::has(const std::string& keys) const
|
|
|
|
{
|
|
|
|
vector<string> names=split_string(keys, " |");
|
2011-05-28 14:55:41 +08:00
|
|
|
for(size_t j=0; j < names.size(); j++) {
|
2011-05-21 22:09:03 +08:00
|
|
|
if (data.find(names[j])!=data.end())
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-05-28 14:55:41 +08:00
|
|
|
std::string CommandLineParser::getString(const std::string& keys) const
|
2011-05-21 22:09:03 +08:00
|
|
|
{
|
|
|
|
vector<string> names=split_string(keys, " |");
|
|
|
|
|
|
|
|
int found_index=-1;
|
2011-05-28 14:55:41 +08:00
|
|
|
for(size_t j=0; j < names.size(); j++) {
|
2011-05-21 22:09:03 +08:00
|
|
|
const string& cur_name=names[j];
|
|
|
|
bool is_cur_found=has(cur_name);
|
|
|
|
|
2011-05-28 14:55:41 +08:00
|
|
|
if (is_cur_found && (found_index >= 0)) {
|
|
|
|
string str_exception="dublicating parameters for "
|
|
|
|
"name='" + names[found_index] + "' and name='"+cur_name+"'";
|
2011-05-21 22:09:03 +08:00
|
|
|
CV_Error(CV_StsParseError, str_exception);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (is_cur_found)
|
|
|
|
found_index=j;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (found_index<0)
|
2011-05-28 14:55:41 +08:00
|
|
|
return string();
|
2011-06-07 18:30:40 +08:00
|
|
|
return data.find(names[found_index])->second;
|
2011-05-21 22:09:03 +08:00
|
|
|
}
|
|
|
|
|
2011-05-31 03:20:57 +08:00
|
|
|
template<typename _Tp>
|
|
|
|
_Tp CommandLineParser::fromStringNumber(const std::string& str) //the default conversion function for numbers
|
|
|
|
{
|
|
|
|
if (str.empty())
|
|
|
|
CV_Error(CV_StsParseError, "Empty string cannot be converted to a number");
|
|
|
|
|
|
|
|
const char* c_str=str.c_str();
|
|
|
|
if((!isdigit(c_str[0]))
|
|
|
|
&&
|
|
|
|
(
|
|
|
|
(c_str[0]!='-') || (strlen(c_str) <= 1) || ( !isdigit(c_str[1]) )
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
{
|
|
|
|
CV_Error(CV_StsParseError, "The string '"+ str +"' cannot be converted to a number");
|
|
|
|
}
|
|
|
|
|
|
|
|
return getData<_Tp>(str);
|
|
|
|
}
|
2011-05-28 14:55:41 +08:00
|
|
|
|
2011-05-30 20:36:07 +08:00
|
|
|
template<typename _Tp>
|
|
|
|
static _Tp getData(const std::string& str)
|
|
|
|
{
|
|
|
|
_Tp res;
|
|
|
|
std::stringstream s1(str);
|
|
|
|
s1 >> res;
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename _Tp>
|
|
|
|
static _Tp fromStringNumber(const std::string& str)//the default conversion function for numbers
|
|
|
|
{
|
|
|
|
|
|
|
|
if (str.empty())
|
|
|
|
CV_Error(CV_StsParseError, "Empty string cannot be converted to a number");
|
|
|
|
|
|
|
|
const char* c_str=str.c_str();
|
|
|
|
if( !isdigit(c_str[0]) &&
|
|
|
|
(c_str[0] != '-' || strlen(c_str) <= 1 || !isdigit(c_str[1]) ))
|
|
|
|
CV_Error(CV_StsParseError, "The string '"+ str +"' cannot be converted to a number");
|
|
|
|
|
|
|
|
return getData<_Tp>(str);
|
|
|
|
}
|
|
|
|
|
2011-05-21 22:09:03 +08:00
|
|
|
template<>
|
2011-05-30 20:36:07 +08:00
|
|
|
std::string CommandLineParser::analyzeValue<std::string>(const std::string& str)
|
2011-05-21 22:09:03 +08:00
|
|
|
{
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<>
|
2011-05-30 20:36:07 +08:00
|
|
|
int CommandLineParser::analyzeValue<int>(const std::string& str)
|
2011-05-21 22:09:03 +08:00
|
|
|
{
|
|
|
|
return fromStringNumber<int>(str);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<>
|
2011-05-30 20:36:07 +08:00
|
|
|
unsigned int CommandLineParser::analyzeValue<unsigned int>(const std::string& str)
|
2011-05-21 22:09:03 +08:00
|
|
|
{
|
|
|
|
return fromStringNumber<unsigned int>(str);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<>
|
2011-05-30 20:36:07 +08:00
|
|
|
float CommandLineParser::analyzeValue<float>(const std::string& str)
|
2011-05-21 22:09:03 +08:00
|
|
|
{
|
2011-05-28 14:55:41 +08:00
|
|
|
return fromStringNumber<float>(str);
|
2011-05-21 22:09:03 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
template<>
|
2011-05-30 20:36:07 +08:00
|
|
|
double CommandLineParser::analyzeValue<double>(const std::string& str)
|
2011-05-21 22:09:03 +08:00
|
|
|
{
|
2011-05-28 14:55:41 +08:00
|
|
|
return fromStringNumber<double>(str);
|
2011-05-21 22:09:03 +08:00
|
|
|
}
|
|
|
|
|