2011-05-21 22:09:03 +08:00
|
|
|
#include "precomp.hpp"
|
2011-08-05 00:09:04 +08:00
|
|
|
#include "iostream"
|
2011-05-21 22:09:03 +08:00
|
|
|
|
|
|
|
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"
|
2011-08-05 00:09:04 +08:00
|
|
|
"Keys map: \n"
|
|
|
|
"Before you start to work with CommandLineParser you have to create a map for keys.\n"
|
|
|
|
" It will look like this\n"
|
|
|
|
" const char* keys =\n"
|
|
|
|
" {\n"
|
|
|
|
" { s| string| 123asd |string parameter}\n"
|
|
|
|
" { d| digit | 100 |digit parameter }\n"
|
|
|
|
" { c|noCamera|false |without camera }\n"
|
|
|
|
" { 1| |some text|help }\n"
|
|
|
|
" { 2| |333 |another help }\n"
|
|
|
|
" };\n"
|
|
|
|
"Usage syntax: \n"
|
|
|
|
" \"{\" - start of parameter string.\n"
|
|
|
|
" \"}\" - end of parameter string\n"
|
|
|
|
" \"|\" - separator between short name, full name, default value and help\n"
|
2011-06-08 14:45:21 +08:00
|
|
|
"Supported syntax: \n"
|
2011-08-05 00:09:04 +08:00
|
|
|
" --key1=arg1 <If a key with '--' must has an argument\n"
|
|
|
|
" you have to assign it through '=' sign.> \n"
|
|
|
|
"<If the key with '--' doesn't have any argument, it means that it is a bool key>\n"
|
|
|
|
" -key2=arg2 <If a key with '-' must has an argument \n"
|
|
|
|
" you have to assign it through '=' sign.> \n"
|
|
|
|
"If the key with '-' doesn't have any argument, it means that it is a bool key\n"
|
2011-06-08 14:45:21 +08:00
|
|
|
" key3 <This key can't has any parameter> \n"
|
|
|
|
"Usage: \n"
|
|
|
|
" Imagine that the input parameters are next:\n"
|
2011-08-05 00:09:04 +08:00
|
|
|
" -s=string_value --digit=250 --noCamera lena.jpg 10000\n"
|
|
|
|
" CommandLineParser parser(argc, argv, keys) - create a parser object\n"
|
|
|
|
" parser.get<string>(\"s\" or \"string\") will return you first parameter value\n"
|
|
|
|
" parser.get<string>(\"s\", false or \"string\", false) will return you first parameter value\n"
|
|
|
|
" without spaces in end and begin\n"
|
|
|
|
" parser.get<int>(\"d\" or \"digit\") will return you second parameter value.\n"
|
|
|
|
" It also works with 'unsigned int', 'double', and 'float' types>\n"
|
|
|
|
" parser.get<bool>(\"c\" or \"noCamera\") will return you true .\n"
|
|
|
|
" If you enter this key in commandline>\n"
|
|
|
|
" It return you false otherwise.\n"
|
|
|
|
" parser.get<string>(\"1\") will return you the first argument without parameter (lena.jpg) \n"
|
|
|
|
" parser.get<int>(\"2\") will return you the second argument without parameter (10000)\n"
|
|
|
|
" It also works with 'unsigned int', 'double', and 'float' types \n"
|
2011-06-08 14:45:21 +08:00
|
|
|
);
|
|
|
|
}
|
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)
|
|
|
|
{
|
2011-08-05 00:09:04 +08:00
|
|
|
|
2011-05-21 22:09:03 +08:00
|
|
|
res.push_back(str.substr(lastPos, pos - lastPos));
|
|
|
|
lastPos = str.find_first_not_of(delimiters, pos);
|
2011-08-05 00:09:04 +08:00
|
|
|
if (str[pos + 1] == '|' && str[pos] == '|')
|
|
|
|
{
|
|
|
|
res.push_back("");
|
|
|
|
if(str[pos + 2] == '|')
|
|
|
|
res.push_back("");
|
|
|
|
}
|
|
|
|
if (str[pos + 1] == '\0')
|
|
|
|
res.push_back("");
|
2011-05-21 22:09:03 +08:00
|
|
|
pos = str.find_first_of(delimiters, lastPos);
|
|
|
|
}
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2011-09-06 23:30:28 +08:00
|
|
|
CommandLineParser::CommandLineParser(int argc, const char* const argv[], const char* keys)
|
2011-05-21 22:09:03 +08:00
|
|
|
{
|
|
|
|
|
2011-08-05 00:09:04 +08:00
|
|
|
std::string keys_buffer;
|
|
|
|
std::string values_buffer;
|
|
|
|
std::string buffer;
|
|
|
|
std::string curName;
|
|
|
|
std::vector<string> keysVector;
|
|
|
|
std::vector<string> paramVector;
|
|
|
|
std::map<std::string, std::vector<std::string> >::iterator it;
|
|
|
|
size_t flagPosition;
|
|
|
|
int currentIndex = 1;
|
|
|
|
bool isFound = false;
|
|
|
|
bool withNoKey = false;
|
|
|
|
bool hasValueThroughEq = false;
|
2011-05-21 22:09:03 +08:00
|
|
|
|
2011-08-05 00:09:04 +08:00
|
|
|
keys_buffer = keys;
|
|
|
|
while (!keys_buffer.empty())
|
2011-05-21 22:09:03 +08:00
|
|
|
{
|
2011-05-28 14:55:41 +08:00
|
|
|
|
2011-08-05 00:09:04 +08:00
|
|
|
flagPosition = keys_buffer.find_first_of('}');
|
|
|
|
flagPosition++;
|
|
|
|
buffer = keys_buffer.substr(0, flagPosition);
|
|
|
|
keys_buffer.erase(0, flagPosition);
|
|
|
|
|
|
|
|
flagPosition = buffer.find('{');
|
|
|
|
if (flagPosition != buffer.npos)
|
|
|
|
buffer.erase(flagPosition, (flagPosition + 1));
|
|
|
|
|
|
|
|
flagPosition = buffer.find('}');
|
|
|
|
if (flagPosition != buffer.npos)
|
|
|
|
buffer.erase(flagPosition);
|
|
|
|
|
|
|
|
paramVector = split_string(buffer, "|");
|
|
|
|
buffer = paramVector[0];
|
|
|
|
if (atoi(buffer.c_str()) == 0)
|
|
|
|
buffer = buffer + '|' + paramVector[1];
|
|
|
|
|
|
|
|
paramVector.erase(paramVector.begin(), paramVector.begin() + 2);
|
|
|
|
data[buffer] = paramVector;
|
|
|
|
}
|
|
|
|
|
|
|
|
buffer.clear();
|
|
|
|
keys_buffer.clear();
|
|
|
|
paramVector.clear();
|
|
|
|
for (int i = 1; i < argc; i++)
|
|
|
|
{
|
|
|
|
if (!argv[i])
|
2011-06-07 18:30:40 +08:00
|
|
|
break;
|
2011-08-05 00:09:04 +08:00
|
|
|
curName = argv[i];
|
|
|
|
if (curName.find('-') == 0 && ((curName[1] < '0') || (curName[1] > '9')))
|
|
|
|
{
|
|
|
|
while (curName.find('-') == 0)
|
|
|
|
curName.erase(curName.begin(), (curName.begin() + 1));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
withNoKey = true;
|
|
|
|
if (curName.find('=') != curName.npos)
|
|
|
|
{
|
|
|
|
hasValueThroughEq = true;
|
|
|
|
buffer = curName;
|
|
|
|
curName.erase(curName.find('='));
|
|
|
|
buffer.erase(0, (buffer.find('=') + 1));
|
|
|
|
}
|
|
|
|
|
|
|
|
for(it = data.begin(); it != data.end(); it++)
|
2011-06-07 18:30:40 +08:00
|
|
|
{
|
2011-08-05 00:09:04 +08:00
|
|
|
keys_buffer = it->first;
|
|
|
|
keysVector = split_string(keys_buffer, "| ");
|
|
|
|
if (keysVector.size() == 1)
|
|
|
|
keysVector.push_back("");
|
|
|
|
values_buffer = it->second[0];
|
|
|
|
if (((curName == keysVector[0]) || (curName == keysVector[1])) && hasValueThroughEq)
|
2011-05-21 22:09:03 +08:00
|
|
|
{
|
2011-08-05 00:09:04 +08:00
|
|
|
it->second[0] = buffer;
|
|
|
|
isFound = true;
|
2011-06-08 14:45:21 +08:00
|
|
|
break;
|
2011-06-07 18:30:40 +08:00
|
|
|
}
|
2011-08-05 00:09:04 +08:00
|
|
|
|
2011-08-05 00:12:55 +08:00
|
|
|
if (!hasValueThroughEq && (values_buffer.find("false") == values_buffer.npos) &&
|
2011-08-05 00:09:04 +08:00
|
|
|
((curName == keysVector[0]) || (curName == keysVector[1])))
|
|
|
|
|
|
|
|
{
|
|
|
|
it->second[0] = argv[++i];
|
|
|
|
isFound = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2011-08-05 00:12:55 +08:00
|
|
|
if (!hasValueThroughEq && (values_buffer.find("false") != values_buffer.npos)
|
2011-08-05 00:09:04 +08:00
|
|
|
&& ((curName == keysVector[0]) || (curName == keysVector[1])))
|
|
|
|
|
|
|
|
{
|
|
|
|
it->second[0] = "true";
|
|
|
|
isFound = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (withNoKey)
|
|
|
|
{
|
|
|
|
std::string noKeyStr = it->first;
|
|
|
|
if(atoi(noKeyStr.c_str()) == currentIndex)
|
2011-06-07 18:30:40 +08:00
|
|
|
{
|
2011-08-05 00:09:04 +08:00
|
|
|
it->second[0] = curName;
|
|
|
|
currentIndex++;
|
|
|
|
isFound = true;
|
2011-06-08 14:45:21 +08:00
|
|
|
break;
|
2011-06-07 18:30:40 +08:00
|
|
|
}
|
2011-08-05 00:09:04 +08:00
|
|
|
}
|
|
|
|
}
|
2011-05-21 22:09:03 +08:00
|
|
|
|
2011-08-05 00:09:04 +08:00
|
|
|
withNoKey = false;
|
|
|
|
hasValueThroughEq = false;
|
|
|
|
if(!isFound)
|
|
|
|
printf("The current parameter is not defined: %s\n", curName.c_str());
|
|
|
|
isFound = false;
|
2011-05-21 22:09:03 +08:00
|
|
|
}
|
2011-08-05 00:09:04 +08:00
|
|
|
|
|
|
|
|
2011-05-21 22:09:03 +08:00
|
|
|
}
|
|
|
|
|
2011-08-05 00:09:04 +08:00
|
|
|
bool CommandLineParser::has(const std::string& keys)
|
2011-05-21 22:09:03 +08:00
|
|
|
{
|
2011-08-05 00:09:04 +08:00
|
|
|
std::map<std::string, std::vector<std::string> >::iterator it;
|
|
|
|
std::vector<string> keysVector;
|
|
|
|
for(it = data.begin(); it != data.end(); it++)
|
|
|
|
{
|
|
|
|
keysVector = split_string(it->first, "| ");
|
|
|
|
if (keysVector.size() == 1)
|
|
|
|
keysVector.push_back("");
|
|
|
|
if ((keys == keysVector[0]) || (keys == keysVector[1]))
|
2011-05-21 22:09:03 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-08-05 00:09:04 +08:00
|
|
|
std::string CommandLineParser::getString(const std::string& keys)
|
2011-05-21 22:09:03 +08:00
|
|
|
{
|
2011-08-05 00:09:04 +08:00
|
|
|
std::map<std::string, std::vector<std::string> >::iterator it;
|
|
|
|
std::vector<string> valueVector;
|
2011-05-21 22:09:03 +08:00
|
|
|
|
2011-08-05 00:09:04 +08:00
|
|
|
for(it = data.begin(); it != data.end(); it++)
|
|
|
|
{
|
|
|
|
valueVector = split_string(it->first, "| ");
|
|
|
|
if (valueVector.size() == 1)
|
|
|
|
valueVector.push_back("");
|
|
|
|
if ((keys == valueVector[0]) || (keys == valueVector[1]))
|
|
|
|
return it->second[0];
|
2011-05-21 22:09:03 +08:00
|
|
|
}
|
2011-08-05 00:09:04 +08:00
|
|
|
return string();
|
2011-05-21 22:09:03 +08:00
|
|
|
}
|
|
|
|
|
2011-05-31 03:20:57 +08:00
|
|
|
template<typename _Tp>
|
2011-08-05 00:09:04 +08:00
|
|
|
_Tp CommandLineParser::fromStringNumber(const std::string& str)//the default conversion function for numbers
|
2011-05-31 03:20:57 +08:00
|
|
|
{
|
|
|
|
const char* c_str=str.c_str();
|
2011-08-05 00:09:04 +08:00
|
|
|
if ((!isdigit(c_str[0]))
|
2011-05-31 03:20:57 +08:00
|
|
|
&&
|
|
|
|
(
|
|
|
|
(c_str[0]!='-') || (strlen(c_str) <= 1) || ( !isdigit(c_str[1]) )
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
{
|
2011-08-05 00:09:04 +08:00
|
|
|
printf("This string cannot be converted to a number. Zero will be returned %s\n ", str.c_str());
|
|
|
|
return _Tp();
|
2011-05-31 03:20:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return getData<_Tp>(str);
|
|
|
|
}
|
2011-05-28 14:55:41 +08:00
|
|
|
|
2011-08-05 00:09:04 +08:00
|
|
|
void CommandLineParser::printParams()
|
|
|
|
{
|
|
|
|
std::map<std::string, std::vector<std::string> >::iterator it;
|
|
|
|
std::vector<string> keysVector;
|
|
|
|
for(it = data.begin(); it != data.end(); it++)
|
|
|
|
{
|
|
|
|
keysVector = split_string(it->first, "| ");
|
|
|
|
if (keysVector.size() == 1)
|
|
|
|
keysVector.push_back("");
|
|
|
|
printf("\t%s [%8s] (%12s - by default) - %s\n", keysVector[0].c_str(),
|
|
|
|
keysVector[1].c_str(), it->second[0].c_str(), it->second[1].c_str());
|
|
|
|
}
|
|
|
|
}
|
2011-05-30 20:36:07 +08:00
|
|
|
|
2011-06-08 18:18:56 +08:00
|
|
|
template<>
|
2011-08-05 00:09:04 +08:00
|
|
|
bool CommandLineParser::get<bool>(const std::string& name, bool space_delete)
|
2011-06-08 18:18:56 +08:00
|
|
|
{
|
2011-08-05 00:09:04 +08:00
|
|
|
std::string str_buf = getString(name);
|
|
|
|
if (space_delete)
|
|
|
|
{
|
|
|
|
while (str_buf.find_first_of(' ') == 0)
|
|
|
|
str_buf.erase(0, 1);
|
|
|
|
while (str_buf.find_last_of(' ') == (str_buf.length() - 1))
|
|
|
|
str_buf.erase(str_buf.end() - 1, str_buf.end());
|
|
|
|
}
|
|
|
|
if (str_buf == "false")
|
2011-06-08 18:18:56 +08:00
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
2011-05-21 22:09:03 +08:00
|
|
|
template<>
|
2011-09-06 23:30:28 +08:00
|
|
|
std::string CommandLineParser::analyzeValue<std::string>(const std::string& str, bool space_delete)
|
2011-05-21 22:09:03 +08:00
|
|
|
{
|
2011-08-05 00:09:04 +08:00
|
|
|
if (space_delete)
|
|
|
|
{
|
|
|
|
std::string str_buf = str;
|
|
|
|
while (str_buf.find_first_of(' ') == 0)
|
|
|
|
str_buf.erase(0, 1);
|
|
|
|
while (str_buf.find_last_of('-') == (str.length() - 1))
|
|
|
|
str_buf.erase(str_buf.end() - 1, str_buf.end());
|
|
|
|
return str_buf;
|
|
|
|
}
|
2011-05-21 22:09:03 +08:00
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<>
|
2011-09-06 23:30:28 +08:00
|
|
|
int CommandLineParser::analyzeValue<int>(const std::string& str, bool /*space_delete*/)
|
2011-05-21 22:09:03 +08:00
|
|
|
{
|
|
|
|
return fromStringNumber<int>(str);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<>
|
2011-09-06 23:30:28 +08:00
|
|
|
unsigned int CommandLineParser::analyzeValue<unsigned int>(const std::string& str, bool /*space_delete*/)
|
2011-05-21 22:09:03 +08:00
|
|
|
{
|
|
|
|
return fromStringNumber<unsigned int>(str);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<>
|
2011-09-06 23:30:28 +08:00
|
|
|
uint64 CommandLineParser::analyzeValue<uint64>(const std::string& str, bool /*space_delete*/)
|
|
|
|
{
|
|
|
|
return fromStringNumber<uint64>(str);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<>
|
|
|
|
float CommandLineParser::analyzeValue<float>(const std::string& str, bool /*space_delete*/)
|
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-09-06 23:30:28 +08:00
|
|
|
double CommandLineParser::analyzeValue<double>(const std::string& str, bool /*space_delete*/)
|
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
|
|
|
}
|