Add OpenCV source code
[platform/upstream/opencv.git] / modules / core / src / cmdparser.cpp
1 #include "precomp.hpp"
2
3 #include <iostream>
4 #include <iomanip>
5
6 using namespace std;
7 using namespace cv;
8
9 namespace {
10 void helpParser()
11 {
12     printf("\nThe CommandLineParser class is designed for command line arguments parsing\n"
13            "Keys map: \n"
14            "Before you start to work with CommandLineParser you have to create a map for keys.\n"
15            "    It will look like this\n"
16            "    const char* keys =\n"
17            "    {\n"
18            "        {    s|  string|  123asd |string parameter}\n"
19            "        {    d|  digit |  100    |digit parameter }\n"
20            "        {    c|noCamera|false    |without camera  }\n"
21            "        {    1|        |some text|help            }\n"
22            "        {    2|        |333      |another help    }\n"
23            "    };\n"
24            "Usage syntax: \n"
25            "    \"{\" - start of parameter string.\n"
26            "    \"}\" - end of parameter string\n"
27            "    \"|\" - separator between short name, full name, default value and help\n"
28            "Supported syntax: \n"
29            "    --key1=arg1  <If a key with '--' must has an argument\n"
30            "                  you have to assign it through '=' sign.> \n"
31            "<If the key with '--' doesn't have any argument, it means that it is a bool key>\n"
32            "    -key2=arg2   <If a key with '-' must has an argument \n"
33            "                  you have to assign it through '=' sign.> \n"
34            "If the key with '-' doesn't have any argument, it means that it is a bool key\n"
35            "    key3                 <This key can't has any parameter> \n"
36            "Usage: \n"
37            "      Imagine that the input parameters are next:\n"
38            "                -s=string_value --digit=250 --noCamera lena.jpg 10000\n"
39            "    CommandLineParser parser(argc, argv, keys) - create a parser object\n"
40            "    parser.get<string>(\"s\" or \"string\") will return you first parameter value\n"
41            "    parser.get<string>(\"s\", false or \"string\", false) will return you first parameter value\n"
42            "                                                                without spaces in end and begin\n"
43            "    parser.get<int>(\"d\" or \"digit\") will return you second parameter value.\n"
44            "                    It also works with 'unsigned int', 'double', and 'float' types>\n"
45            "    parser.get<bool>(\"c\" or \"noCamera\") will return you true .\n"
46            "                                If you enter this key in commandline>\n"
47            "                                It return you false otherwise.\n"
48            "    parser.get<string>(\"1\") will return you the first argument without parameter (lena.jpg) \n"
49            "    parser.get<int>(\"2\") will return you the second argument without parameter (10000)\n"
50            "                          It also works with 'unsigned int', 'double', and 'float' types \n"
51            );
52 }
53
54 vector<string> split_string(const string& str, const string& delimiters)
55 {
56     vector<string> res;
57
58     string split_str = str;
59     size_t pos_delim = split_str.find(delimiters);
60
61     while ( pos_delim != string::npos)
62     {
63         if (pos_delim == 0)
64         {
65             res.push_back("");
66             split_str.erase(0, 1);
67         }
68         else
69         {
70             res.push_back(split_str.substr(0, pos_delim));
71             split_str.erase(0, pos_delim + 1);
72         }
73
74         pos_delim = split_str.find(delimiters);
75     }
76
77     res.push_back(split_str);
78
79     return res;
80 }
81
82 string del_space(string name)
83 {
84     while ((name.find_first_of(' ') == 0)  && (name.length() > 0))
85         name.erase(0, 1);
86
87     while ((name.find_last_of(' ') == (name.length() - 1)) && (name.length() > 0))
88         name.erase(name.end() - 1, name.end());
89
90     return name;
91 }
92
93 }//namespace
94
95 static bool keyIsNumber(const std::string & option, size_t start)
96 {
97     bool isNumber = true;
98     size_t end = option.find_first_of('=', start);
99     end = option.npos == end ? option.length() : end;
100
101     for ( ; start < end; ++start)
102         if (!isdigit(option[start]))
103         {
104             isNumber = false;
105             break;
106         }
107
108     return isNumber;
109 }
110
111 CommandLineParser::CommandLineParser(int argc, const char* const argv[], const char* keys)
112 {
113     std::string keys_buffer;
114     std::string values_buffer;
115     std::string buffer;
116     std::string curName;
117     std::vector<string> keysVector;
118     std::vector<string> paramVector;
119     std::map<std::string, std::vector<std::string> >::iterator it;
120     size_t flagPosition;
121     int currentIndex = 1;
122     //bool isFound = false;
123     bool withNoKey = false;
124     bool hasValueThroughEq = false;
125
126     keys_buffer = keys;
127     while (!keys_buffer.empty())
128     {
129
130         flagPosition = keys_buffer.find_first_of('}');
131         flagPosition++;
132         buffer = keys_buffer.substr(0, flagPosition);
133         keys_buffer.erase(0, flagPosition);
134
135         flagPosition = buffer.find('{');
136         if (flagPosition != buffer.npos)
137             buffer.erase(flagPosition, (flagPosition + 1));
138
139         flagPosition = buffer.find('}');
140         if (flagPosition != buffer.npos)
141             buffer.erase(flagPosition);
142
143         paramVector = split_string(buffer, "|");
144         while (paramVector.size() < 4) paramVector.push_back("");
145
146         buffer = paramVector[0];
147         buffer += '|' + paramVector[1];
148
149         //if (buffer == "") CV_ERROR(CV_StsBadArg, "In CommandLineParser need set short and full name");
150
151         paramVector.erase(paramVector.begin(), paramVector.begin() + 2);
152         data[buffer] = paramVector;
153     }
154
155     buffer.clear();
156     keys_buffer.clear();
157     paramVector.clear();
158     for (int i = 1; i < argc; i++)
159     {
160         if (!argv[i])
161             break;
162         curName = argv[i];
163
164         size_t nondash = curName.find_first_not_of("-");
165         if (nondash == 0 || nondash == curName.npos || keyIsNumber(curName, nondash))
166             withNoKey = true;
167         else
168             curName.erase(0, nondash);
169
170         if (curName.find('=') != curName.npos)
171         {
172             hasValueThroughEq = true;
173             buffer = curName;
174             curName.erase(curName.find('='));
175             buffer.erase(0, (buffer.find('=') + 1));
176         }
177
178         values_buffer = del_space(values_buffer);
179
180         for(it = data.begin(); it != data.end(); it++)
181         {
182             keys_buffer = it->first;
183             keysVector = split_string(keys_buffer, "|");
184
185             for (size_t j = 0; j < keysVector.size(); j++) keysVector[j] = del_space(keysVector[j]);
186
187             values_buffer = it->second[0];
188             if (((curName == keysVector[0]) || (curName == keysVector[1])) && hasValueThroughEq)
189             {
190                 it->second[0] = buffer;
191                 //isFound = true;
192                 break;
193             }
194
195             if (!hasValueThroughEq && ((curName == keysVector[0]) || (curName == keysVector[1]))
196                 && (
197                     values_buffer.find("false") != values_buffer.npos ||
198                     values_buffer == ""
199                 ))
200             {
201                 it->second[0] = "true";
202                 //isFound = true;
203                 break;
204             }
205
206             if (!hasValueThroughEq && (values_buffer.find("false") == values_buffer.npos) &&
207                 ((curName == keysVector[0]) || (curName == keysVector[1])))
208             {
209                 it->second[0] = argv[++i];
210                 //isFound = true;
211                 break;
212             }
213
214
215             if (withNoKey)
216             {
217                 std::string noKeyStr = it->first;
218                 if(atoi(noKeyStr.c_str()) == currentIndex)
219                 {
220                     it->second[0] = curName;
221                     currentIndex++;
222                     //isFound = true;
223                     break;
224                 }
225             }
226         }
227
228         withNoKey = false;
229         hasValueThroughEq = false;
230         //isFound = false;
231     }
232 }
233
234 bool CommandLineParser::has(const std::string& keys)
235 {
236     std::map<std::string, std::vector<std::string> >::iterator it;
237     std::vector<string> keysVector;
238
239     for(it = data.begin(); it != data.end(); it++)
240     {
241         keysVector = split_string(it->first, "|");
242         for (size_t i = 0; i < keysVector.size(); i++) keysVector[i] = del_space(keysVector[i]);
243
244         if (keysVector.size() == 1) keysVector.push_back("");
245
246         if ((del_space(keys).compare(keysVector[0]) == 0) ||
247             (del_space(keys).compare(keysVector[1]) == 0))
248             return true;
249     }
250
251     return false;
252 }
253
254 std::string CommandLineParser::getString(const std::string& keys)
255 {
256     std::map<std::string, std::vector<std::string> >::iterator it;
257     std::vector<string> valueVector;
258
259     for(it = data.begin(); it != data.end(); it++)
260     {
261         valueVector = split_string(it->first, "|");
262         for (size_t i = 0; i < valueVector.size(); i++) valueVector[i] = del_space(valueVector[i]);
263
264         if (valueVector.size() == 1) valueVector.push_back("");
265
266         if ((del_space(keys).compare(valueVector[0]) == 0) ||
267             (del_space(keys).compare(valueVector[1]) == 0))
268             return it->second[0];
269     }
270     return string();
271 }
272
273 template<typename _Tp>
274  _Tp CommandLineParser::fromStringNumber(const std::string& str)//the default conversion function for numbers
275 {
276     return getData<_Tp>(str);
277 }
278
279  void CommandLineParser::printParams()
280  {
281     int col_p = 30;
282     int col_d = 50;
283
284     std::map<std::string, std::vector<std::string> >::iterator it;
285     std::vector<string> keysVector;
286     std::string buf;
287     for(it = data.begin(); it != data.end(); it++)
288     {
289         keysVector = split_string(it->first, "|");
290         for (size_t i = 0; i < keysVector.size(); i++) keysVector[i] = del_space(keysVector[i]);
291
292         cout << "  ";
293         buf = "";
294         if (keysVector[0] != "")
295         {
296             buf = "-" + keysVector[0];
297             if (keysVector[1] != "") buf += ", --" + keysVector[1];
298         }
299         else if (keysVector[1] != "") buf += "--" + keysVector[1];
300         if (del_space(it->second[0]) != "") buf += "=[" + del_space(it->second[0]) + "]";
301
302         cout << setw(col_p-2) << left << buf;
303
304         if ((int)buf.length() > col_p-2)
305         {
306             cout << endl << "  ";
307             cout << setw(col_p-2) << left << " ";
308         }
309
310         buf = "";
311         if (del_space(it->second[1]) != "") buf += del_space(it->second[1]);
312
313         for(;;)
314         {
315             bool tr = ((int)buf.length() > col_d-2) ? true: false;
316             std::string::size_type pos = 0;
317
318             if (tr)
319             {
320                 pos = buf.find_first_of(' ');
321                 for(;;)
322                 {
323                     if (buf.find_first_of(' ', pos + 1 ) < (std::string::size_type)(col_d-2) &&
324                         buf.find_first_of(' ', pos + 1 ) != std::string::npos)
325                         pos = buf.find_first_of(' ', pos + 1);
326                     else
327                         break;
328                 }
329                 pos++;
330                 cout << setw(col_d-2) << left << buf.substr(0, pos) << endl;
331             }
332             else
333             {
334                 cout << setw(col_d-2) << left << buf<< endl;
335                 break;
336             }
337
338             buf.erase(0, pos);
339             cout << "  ";
340             cout << setw(col_p-2) << left << " ";
341         }
342     }
343  }
344
345 template<>
346 bool CommandLineParser::get<bool>(const std::string& name, bool space_delete)
347 {
348     std::string str_buf = getString(name);
349
350     if (space_delete && str_buf != "")
351     {
352         str_buf = del_space(str_buf);
353     }
354
355     if (str_buf == "true")
356         return true;
357
358     return false;
359 }
360 template<>
361 std::string CommandLineParser::analyzeValue<std::string>(const std::string& str, bool space_delete)
362 {
363     if (space_delete)
364     {
365         return del_space(str);
366     }
367     return str;
368 }
369
370 template<>
371 int CommandLineParser::analyzeValue<int>(const std::string& str, bool /*space_delete*/)
372 {
373     return fromStringNumber<int>(str);
374 }
375
376 template<>
377 unsigned int CommandLineParser::analyzeValue<unsigned int>(const std::string& str, bool /*space_delete*/)
378 {
379     return fromStringNumber<unsigned int>(str);
380 }
381
382 template<>
383 uint64 CommandLineParser::analyzeValue<uint64>(const std::string& str, bool /*space_delete*/)
384 {
385     return fromStringNumber<uint64>(str);
386 }
387
388 template<>
389 float CommandLineParser::analyzeValue<float>(const std::string& str, bool /*space_delete*/)
390 {
391     return fromStringNumber<float>(str);
392 }
393
394 template<>
395 double CommandLineParser::analyzeValue<double>(const std::string& str, bool /*space_delete*/)
396 {
397     return fromStringNumber<double>(str);
398 }