Changeset 1313 in 3DVCSoftware for trunk/source/Lib/TAppCommon/program_options_lite.cpp
- Timestamp:
- 13 Aug 2015, 17:38:13 (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/source/Lib/TAppCommon/program_options_lite.cpp
r1179 r1313 2 2 * License, included below. This software may be subject to other third party 3 3 * and contributor rights, including patent rights, and no such rights are 4 * granted under this license. 4 * granted under this license. 5 5 * 6 * Copyright (c) 2010-2015, ITU/ISO/IEC6 * Copyright (c) 2010-2015, ITU/ISO/IEC 7 7 * All rights reserved. 8 8 * … … 40 40 #include <algorithm> 41 41 #include "program_options_lite.h" 42 #include "../TLibCommon/ TypeDef.h"42 #include "../TLibCommon/CommonDef.h" 43 43 using namespace std; 44 44 … … 50 50 namespace program_options_lite 51 51 { 52 52 ErrorReporter default_error_reporter; 53 54 ostream& ErrorReporter::error(const string& where) 55 { 56 is_errored = 1; 57 cerr << where << " error: "; 58 return cerr; 59 } 60 61 ostream& ErrorReporter::warn(const string& where) 62 { 63 cerr << where << " warning: "; 64 return cerr; 65 } 66 53 67 Options::~Options() 54 68 { … … 58 72 } 59 73 } 60 74 61 75 void Options::addOption(OptionBase *opt) 62 76 { … … 64 78 names->opt = opt; 65 79 string& opt_string = opt->opt_string; 66 80 67 81 size_t opt_start = 0; 68 82 for (size_t opt_end = 0; opt_end != string::npos;) … … 96 110 return OptionSpecific(*this); 97 111 } 98 99 static void setOptions(Options::NamesPtrList& opt_list, const string& value )112 113 static void setOptions(Options::NamesPtrList& opt_list, const string& value, ErrorReporter& error_reporter) 100 114 { 101 115 /* multiple options may be registered for the same name: … … 103 117 for (Options::NamesPtrList::iterator it = opt_list.begin(); it != opt_list.end(); ++it) 104 118 { 105 (*it)->opt->parse(value );119 (*it)->opt->parse(value, error_reporter); 106 120 } 107 121 } 108 122 109 123 static const char spaces[41] = " "; 110 124 111 125 /* format help text for a single option: 112 126 * using the formatting: "-x, --long", … … 138 152 } 139 153 } 140 154 141 155 /* format the help text */ 142 156 void doHelp(ostream& out, Options& opts, unsigned columns) … … 147 161 for(Options::NamesPtrList::iterator it = opts.opt_list.begin(); it != opts.opt_list.end(); it++) 148 162 { 149 #if H_MV163 #if NH_MV 150 164 if ( (*it)->opt->opt_duplicate ) continue; 151 165 #endif … … 157 171 unsigned opt_width = min(max_width+2, 28u + pad_short) + 2; 158 172 unsigned desc_width = columns - opt_width; 159 173 160 174 /* second pass: write out formatted option and help text. 161 175 * - align start of help text to start at opt_width … … 165 179 for(Options::NamesPtrList::iterator it = opts.opt_list.begin(); it != opts.opt_list.end(); it++) 166 180 { 167 #if H_MV181 #if NH_MV 168 182 if ( (*it)->opt->opt_duplicate ) continue; 169 183 #endif … … 215 229 split_pos = opt_desc.find_last_not_of(' ', split_pos) + 1; 216 230 } 217 231 218 232 /* bad split if no suitable space to split at. fall back to width */ 219 233 bool bad_split = split_pos == string::npos || split_pos <= cur_pos; … … 223 237 } 224 238 line << opt_desc.substr(cur_pos, split_pos - cur_pos); 225 239 226 240 /* eat up any space for the start of the next line */ 227 241 if (!bad_split) … … 230 244 } 231 245 cur_pos = newline_pos = split_pos; 232 246 233 247 if (cur_pos >= opt_desc.size()) 234 248 { … … 241 255 } 242 256 } 243 244 bool storePair(Options& opts, bool allow_long, bool allow_short, const string& name, const string& value) 257 258 struct OptionWriter 259 { 260 OptionWriter(Options& rOpts, ErrorReporter& err) 261 : opts(rOpts), error_reporter(err) 262 {} 263 virtual ~OptionWriter() {} 264 265 virtual const string where() = 0; 266 267 bool storePair(bool allow_long, bool allow_short, const string& name, const string& value); 268 bool storePair(const string& name, const string& value) 269 { 270 return storePair(true, true, name, value); 271 } 272 273 Options& opts; 274 ErrorReporter& error_reporter; 275 }; 276 277 bool OptionWriter::storePair(bool allow_long, bool allow_short, const string& name, const string& value) 245 278 { 246 279 bool found = false; … … 254 287 } 255 288 } 256 289 257 290 /* check for the short list */ 258 291 if (allow_short && !(found && allow_long)) … … 267 300 if (!found) 268 301 { 269 /* not found */270 cerr << "Unknown option: `" << name << "' (value:`" << value << "')" << endl;302 error_reporter.error(where()) 303 << "Unknown option `" << name << "' (value:`" << value << "')\n"; 271 304 return false; 272 305 } 273 306 274 setOptions((*opt_it).second, value );307 setOptions((*opt_it).second, value, error_reporter); 275 308 return true; 276 309 } 277 278 bool storePair(Options& opts, const string& name, const string& value) 279 { 280 return storePair(opts, true, true, name, value); 281 } 282 310 311 struct ArgvParser : public OptionWriter 312 { 313 ArgvParser(Options& rOpts, ErrorReporter& rError_reporter) 314 : OptionWriter(rOpts, rError_reporter) 315 {} 316 317 const string where() { return "command line"; } 318 319 unsigned parseGNU(unsigned argc, const char* argv[]); 320 unsigned parseSHORT(unsigned argc, const char* argv[]); 321 }; 322 283 323 /** 284 324 * returns number of extra arguments consumed 285 325 */ 286 unsigned parseGNU(Options& opts,unsigned argc, const char* argv[])326 unsigned ArgvParser::parseGNU(unsigned argc, const char* argv[]) 287 327 { 288 328 /* gnu style long options can take the forms: … … 294 334 size_t arg_opt_sep = arg.find_first_of('='); 295 335 string option = arg.substr(arg_opt_start, arg_opt_sep - arg_opt_start); 296 336 297 337 unsigned extra_argc_consumed = 0; 298 338 if (arg_opt_sep == string::npos) … … 305 345 * booleans */ 306 346 if (argc == 1) 347 { 307 348 return 0; /* run out of argv for argument */ 349 } 308 350 extra_argc_consumed = 1; 309 351 #endif 310 if(!storePair( opts,true, false, option, "1"))352 if(!storePair(true, false, option, "1")) 311 353 { 312 354 return 0; … … 317 359 /* argument occurs after option_sep */ 318 360 string val = arg.substr(arg_opt_sep + 1); 319 storePair( opts,true, false, option, val);361 storePair(true, false, option, val); 320 362 } 321 363 … … 323 365 } 324 366 325 unsigned parseSHORT(Options& opts,unsigned argc, const char* argv[])367 unsigned ArgvParser::parseSHORT(unsigned argc, const char* argv[]) 326 368 { 327 369 /* short options can take the forms: … … 338 380 if (argc == 1) 339 381 { 340 cerr << "Not processing option without argument `" << option << "'" << endl; 382 error_reporter.error(where()) 383 << "Not processing option `" << option << "' without argument\n"; 341 384 return 0; /* run out of argv for argument */ 342 385 } 343 storePair( opts,false, true, option, string(argv[1]));386 storePair(false, true, option, string(argv[1])); 344 387 345 388 return 1; 346 389 } 347 390 348 391 list<const char*> 349 scanArgv(Options& opts, unsigned argc, const char* argv[]) 350 { 392 scanArgv(Options& opts, unsigned argc, const char* argv[], ErrorReporter& error_reporter) 393 { 394 ArgvParser avp(opts, error_reporter); 395 351 396 /* a list for anything that didn't get handled as an option */ 352 397 list<const char*> non_option_arguments; … … 370 415 { 371 416 /* handle short (single dash) options */ 372 #if 0 373 i += parsePOSIX(opts, argc - i, &argv[i]); 374 #else 375 i += parseSHORT(opts, argc - i, &argv[i]); 376 #endif 417 i += avp.parseSHORT(argc - i, &argv[i]); 377 418 continue; 378 419 } … … 382 423 /* a lone double dash ends option processing */ 383 424 while (++i < argc) 425 { 384 426 non_option_arguments.push_back(argv[i]); 427 } 385 428 break; 386 429 } 387 430 388 431 /* handle long (double dash) options */ 389 i += parseGNU(opts,argc - i, &argv[i]);432 i += avp.parseGNU(argc - i, &argv[i]); 390 433 } 391 434 392 435 return non_option_arguments; 393 436 } 394 395 void scanLine(Options& opts, string& line) 437 438 struct CfgStreamParser : public OptionWriter 439 { 440 CfgStreamParser(const string& rName, Options& rOpts, ErrorReporter& rError_reporter) 441 : OptionWriter(rOpts, rError_reporter) 442 , name(rName) 443 , linenum(0) 444 {} 445 446 const string name; 447 int linenum; 448 const string where() 449 { 450 ostringstream os; 451 os << name << ":" << linenum; 452 return os.str(); 453 } 454 455 void scanLine(string& line); 456 void scanStream(istream& in); 457 }; 458 459 void CfgStreamParser::scanLine(string& line) 396 460 { 397 461 /* strip any leading whitespace */ … … 416 480 { 417 481 /* error: badly formatted line */ 482 error_reporter.warn(where()) << "line formatting error\n"; 418 483 return; 419 484 } … … 421 486 { 422 487 /* error: badly formatted line */ 488 error_reporter.warn(where()) << "line formatting error\n"; 423 489 return; 424 490 } … … 429 495 { 430 496 /* error: badly formatted line */ 497 #if !NH_MV 498 error_reporter.warn(where()) << "line formatting error\n"; 499 #else 500 // HTM also allows empty parameters. 501 #endif 431 502 return; 432 503 } … … 447 518 * any trailing whitespace will be removed shortly */ 448 519 value_end = line.find_first_not_of(" \t\n\r", value_end); 449 } 450 while (value_end != string::npos); 520 } while (value_end != string::npos); 451 521 /* strip any trailing space from value*/ 452 522 value_end = line.find_last_not_of(" \t\n\r", value_end); … … 460 530 { 461 531 /* error: no value */ 532 #if !NH_MV 533 error_reporter.warn(where()) << "no value found\n"; 534 #else 535 // This is ok for HTM. 536 #endif 462 537 return; 463 538 } 464 539 465 540 /* store the value in option */ 466 storePair( opts,true, false, option, value);467 } 468 469 void scanFile(Options& opts,istream& in)541 storePair(true, false, option, value); 542 } 543 544 void CfgStreamParser::scanStream(istream& in) 470 545 { 471 546 do 472 547 { 548 linenum++; 473 549 string line; 474 550 getline(in, line); 475 scanLine(opts, line); 476 } 477 while(!!in); 551 scanLine(line); 552 } while(!!in); 478 553 } 479 554 … … 488 563 } 489 564 490 void parseConfigFile(Options& opts, const string& filename )565 void parseConfigFile(Options& opts, const string& filename, ErrorReporter& error_reporter) 491 566 { 492 567 ifstream cfgstream(filename.c_str(), ifstream::in); 493 568 if (!cfgstream) 494 569 { 495 cerr << "Failed to open config file: `" << filename << "'" << endl; 496 exit(EXIT_FAILURE); 497 } 498 scanFile(opts, cfgstream); 499 } 500 501 }; 502 }; 570 error_reporter.error(filename) << "Failed to open config file\n"; 571 return; 572 } 573 CfgStreamParser csp(filename, opts, error_reporter); 574 csp.scanStream(cfgstream); 575 } 576 577 } 578 } 503 579 504 580 //! \}
Note: See TracChangeset for help on using the changeset viewer.