00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include "command_args.h"
00034
00035 #include <cstdlib>
00036 #include <cstring>
00037 #include <fstream>
00038 #include <algorithm>
00039 #include "os_specific.h"
00040 using namespace std;
00041
00042 namespace g2o {
00043
00044 enum CommandArgumentType
00045 {
00046 CAT_DOUBLE, CAT_FLOAT, CAT_INT, CAT_STRING, CAT_BOOL
00047 };
00048
00049 CommandArgs::CommandArgs()
00050 {
00051 }
00052
00053 CommandArgs::~CommandArgs()
00054 {
00055 }
00056
00057 bool CommandArgs::parseArgs(int argc, char** argv, bool exitOnError)
00058 {
00059 _progName = argv[0];
00060 int i;
00061 for (i = 1; i < argc; i++) {
00062 string name = argv[i];
00063
00064 if (name[0] != '-') {
00065
00066
00067
00068
00069
00070 break;
00071 }
00072
00073 if (name == "--") {
00074 ++i;
00075 break;
00076 }
00077
00078 string::size_type dashPos = name.find_first_not_of('-');
00079 if (dashPos != string::npos)
00080 name = name.substr(dashPos);
00081
00082 if (name == "help" || name == "h") {
00083 printHelp(cout);
00084 exit(0);
00085 }
00086 else {
00087
00088 std::vector<CommandArgument>::iterator it = _args.begin();
00089 for ( ; it != _args.end(); ++it) {
00090 if (it->name == name) {
00091 if (it->type == CAT_BOOL) {
00092 if (!it->parsed) {
00093 bool* data = static_cast<bool*>(it->data);
00094 *data = !(*data);
00095 }
00096 it->parsed = true;
00097 } else {
00098 if(i >= argc-1) {
00099 fprintf(stderr, "Argument %s needs value.\n", name.c_str());
00100 printHelp(cerr);
00101 if (exitOnError)
00102 exit(1);
00103 return false;
00104 }
00105 i++;
00106 str2arg(argv[i], *it);
00107 it->parsed = true;
00108 }
00109 break;
00110 }
00111 }
00112 if (it == _args.end()) {
00113 fprintf(stderr, "Error: Unknown Option '%s' (use -help to get list of options).\n", name.c_str());
00114 if (exitOnError)
00115 exit(1);
00116 return false;
00117 }
00118
00119 }
00120
00121 }
00122
00123 if ((int)_leftOvers.size() > argc - i) {
00124 cerr << "Error: program requires parameters" << endl;
00125 printHelp(cerr);
00126 if (exitOnError)
00127 exit(1);
00128 return false;
00129 }
00130 for (size_t j = 0; (i < argc && j < _leftOvers.size()); i++, j++) {
00131 string* s = static_cast<string*>(_leftOvers[j].data);
00132 *s = argv[i];
00133 }
00134
00135
00136 for (size_t j = 0; (i < argc && j < _leftOversOptional.size()); i++, j++) {
00137 string* s = static_cast<string*>(_leftOversOptional[j].data);
00138 *s = argv[i];
00139 }
00140
00141 return true;
00142 }
00143
00144 void CommandArgs::param(const std::string& name, bool& p, bool defValue, const std::string& desc)
00145 {
00146 CommandArgument ca;
00147 ca.name = name;
00148 ca.description = desc;
00149 ca.type = CAT_BOOL;
00150 ca.data = static_cast<void*>(&p);
00151 ca.parsed = false;
00152 p = defValue;
00153 _args.push_back(ca);
00154 }
00155
00156 void CommandArgs::param(const std::string& name, int& p, int defValue, const std::string& desc)
00157 {
00158 CommandArgument ca;
00159 ca.name = name;
00160 ca.description = desc;
00161 ca.type = CAT_INT;
00162 ca.data = static_cast<void*>(&p);
00163 ca.parsed = false;
00164 p = defValue;
00165 _args.push_back(ca);
00166 }
00167
00168 void CommandArgs::param(const std::string& name, float& p, float defValue, const std::string& desc)
00169 {
00170 CommandArgument ca;
00171 ca.name = name;
00172 ca.description = desc;
00173 ca.type = CAT_FLOAT;
00174 ca.data = static_cast<void*>(&p);
00175 ca.parsed = false;
00176 p = defValue;
00177 _args.push_back(ca);
00178 }
00179
00180 void CommandArgs::param(const std::string& name, double& p, double defValue, const std::string& desc)
00181 {
00182 CommandArgument ca;
00183 ca.name = name;
00184 ca.description = desc;
00185 ca.type = CAT_DOUBLE;
00186 ca.data = static_cast<void*>(&p);
00187 ca.parsed = false;
00188 p = defValue;
00189 _args.push_back(ca);
00190 }
00191
00192 void CommandArgs::printHelp(std::ostream& os)
00193 {
00194 if (_banner.size())
00195 os << _banner << endl;
00196 os << "Usage: " << _progName << (_args.size()>0?" [options] ":" ");
00197 if (_leftOvers.size() > 0) {
00198 for (size_t i = 0; i < _leftOvers.size(); ++i) {
00199 if (i > 0)
00200 os << " ";
00201 os << _leftOvers[i].name;
00202 }
00203 }
00204 if (_leftOversOptional.size() > 0) {
00205 if (_leftOvers.size() > 0)
00206 os << " ";
00207 for (size_t i = 0; i < _leftOversOptional.size(); ++i) {
00208 if (i > 0)
00209 os << " ";
00210 os << "[" << _leftOversOptional[i].name << "]";
00211 }
00212 }
00213 os << endl << endl;
00214 os << "General options:" << endl;
00215 os << "-------------------------------------------" << endl;
00216 os << "-help / -h Displays this help." << endl << endl;
00217 if (_args.size() > 0) {
00218 os << "Program Options:" << endl;
00219 os << "-------------------------------------------" << endl;
00220
00221 vector<pair<string, string> > tableStrings;
00222 tableStrings.reserve(_args.size());
00223 size_t maxArgLen = 0;
00224 for (size_t i = 0; i < _args.size(); ++i) {
00225 if (_args[i].type != CAT_BOOL)
00226 tableStrings.push_back(make_pair(_args[i].name + " " + type2str(_args[i].type), _args[i].description));
00227 else
00228 tableStrings.push_back(make_pair(_args[i].name, _args[i].description));
00229 maxArgLen = max(maxArgLen, tableStrings.back().first.size());
00230 }
00231 sort(tableStrings.begin(), tableStrings.end(), CmpPairFirst<string,string>());
00232 maxArgLen += 3;
00233 for (size_t i = 0; i < tableStrings.size(); ++i) {
00234 os << "-" << tableStrings[i].first;
00235 for (size_t l = tableStrings[i].first.size(); l < maxArgLen; ++l)
00236 os << " ";
00237 os << tableStrings[i].second << endl;
00238 }
00239
00240 }
00241 }
00242
00243 void CommandArgs::param(const std::string& name, std::string& p, const std::string& defValue, const std::string& desc)
00244 {
00245 CommandArgument ca;
00246 ca.name = name;
00247 ca.description = desc;
00248 ca.type = CAT_STRING;
00249 ca.data = static_cast<void*>(&p);
00250 ca.parsed = false;
00251 p = defValue;
00252 _args.push_back(ca);
00253 }
00254
00255 void CommandArgs::setBanner(const std::string& banner)
00256 {
00257 _banner = banner;
00258 }
00259
00260 void CommandArgs::paramLeftOver(const std::string& name, std::string& p, const std::string& defValue, const std::string& desc, bool optional)
00261 {
00262 CommandArgument ca;
00263 ca.name = name;
00264 ca.description = desc;
00265 ca.type = CAT_STRING;
00266 ca.data = static_cast<void*>(&p);
00267 ca.parsed = false;
00268 ca.optional = optional;
00269 p = defValue;
00270 if (optional)
00271 _leftOversOptional.push_back(ca);
00272 else
00273 _leftOvers.push_back(ca);
00274 }
00275
00276 const char* CommandArgs::type2str(int t) const
00277 {
00278 switch (t) {
00279 case CAT_DOUBLE:
00280 return "<double>";
00281 case CAT_FLOAT:
00282 return "<float>";
00283 case CAT_INT:
00284 return "<int>";
00285 case CAT_STRING:
00286 return "<string>";
00287 case CAT_BOOL:
00288 return "<bool>";
00289 }
00290 return "";
00291 }
00292
00293 void CommandArgs::str2arg(const std::string& input, CommandArgument& ca) const
00294 {
00295 switch (ca.type) {
00296 case CAT_FLOAT:
00297 {
00298 float aux;
00299 bool convertStatus = convertString(input, aux);
00300 if (convertStatus) {
00301 float* data = static_cast<float*>(ca.data);
00302 *data = aux;
00303 }
00304 }
00305 break;
00306 case CAT_DOUBLE:
00307 {
00308 double aux;
00309 bool convertStatus = convertString(input, aux);
00310 if (convertStatus) {
00311 double* data = static_cast<double*>(ca.data);
00312 *data = aux;
00313 }
00314 }
00315 break;
00316 case CAT_INT:
00317 {
00318 int aux;
00319 bool convertStatus = convertString(input, aux);
00320 if (convertStatus) {
00321 int* data = static_cast<int*>(ca.data);
00322 *data = aux;
00323 }
00324 }
00325 break;
00326 case CAT_BOOL:
00327 {
00328 bool aux;
00329 bool convertStatus = convertString(input, aux);
00330 if (convertStatus) {
00331 bool* data = static_cast<bool*>(ca.data);
00332 *data = aux;
00333 }
00334 }
00335 break;
00336 case CAT_STRING:
00337 {
00338 string* data = static_cast<string*>(ca.data);
00339 *data = input;
00340 }
00341 break;
00342 }
00343 }
00344
00345 std::string CommandArgs::arg2str(const CommandArgument& ca) const
00346 {
00347 switch (ca.type) {
00348 case CAT_FLOAT:
00349 {
00350 float* data = static_cast<float*>(ca.data);
00351 stringstream auxStream;
00352 auxStream << *data;
00353 return auxStream.str();
00354 }
00355 break;
00356 case CAT_DOUBLE:
00357 {
00358 double* data = static_cast<double*>(ca.data);
00359 stringstream auxStream;
00360 auxStream << *data;
00361 return auxStream.str();
00362 }
00363 break;
00364 case CAT_INT:
00365 {
00366 int* data = static_cast<int*>(ca.data);
00367 stringstream auxStream;
00368 auxStream << *data;
00369 return auxStream.str();
00370 }
00371 break;
00372 case CAT_BOOL:
00373 {
00374 bool* data = static_cast<bool*>(ca.data);
00375 stringstream auxStream;
00376 auxStream << *data;
00377 return auxStream.str();
00378 }
00379 break;
00380 case CAT_STRING:
00381 {
00382 string* data = static_cast<string*>(ca.data);
00383 return *data;
00384 }
00385 break;
00386 }
00387 return "";
00388 }
00389
00390 std::string CommandArgs::trim(const std::string& s) const
00391 {
00392 if(s.length() == 0)
00393 return s;
00394 string::size_type b = s.find_first_not_of(" \t\n");
00395 string::size_type e = s.find_last_not_of(" \t\n");
00396 if(b == string::npos)
00397 return "";
00398 return std::string(s, b, e - b + 1);
00399 }
00400
00401 }