gravatar
alpar (Alpar Juttner)
alpar@cs.elte.hu
Some cleanup in ArgParser API (ticket #116)
0 2 0
default
2 files changed with 45 insertions and 41 deletions:
↑ Collapse diff ↑
Ignore white space 48 line context
... ...
@@ -218,216 +218,217 @@
218 218
    LEMON_ASSERT(s==_opts.end(), "Option already used: '"+syn+"'");
219 219
    ParData p;
220 220
    p.help=opt;
221 221
    p.mandatory=false;
222 222
    p.syn=true;
223 223
    _opts[syn]=p;
224 224
    o->second.has_syn=true;
225 225
    return *this;
226 226
  }
227 227

	
228 228
  ArgParser &ArgParser::mandatoryGroup(const std::string &group)
229 229
  {
230 230
    GroupData &g=_groups[group];
231 231
    g.mandatory=true;
232 232
    return *this;
233 233
  }
234 234

	
235 235
  ArgParser &ArgParser::other(const std::string &name,
236 236
                              const std::string &help)
237 237
  {
238 238
    _others_help.push_back(OtherArg(name,help));
239 239
    return *this;
240 240
  }
241 241

	
242
  void ArgParser::show(std::ostream &os,Opts::iterator i)
242
  void ArgParser::show(std::ostream &os,Opts::const_iterator i) const
243 243
  {
244 244
    os << "-" << i->first;
245 245
    if(i->second.has_syn)
246
      for(Opts::iterator j=_opts.begin();j!=_opts.end();++j)
246
      for(Opts::const_iterator j=_opts.begin();j!=_opts.end();++j)
247 247
        if(j->second.syn&&j->second.help==i->first)
248 248
          os << "|-" << j->first;
249 249
    switch(i->second.type) {
250 250
    case STRING:
251 251
      os << " str";
252 252
      break;
253 253
    case INTEGER:
254 254
      os << " int";
255 255
      break;
256 256
    case DOUBLE:
257 257
      os << " num";
258 258
      break;
259 259
    default:
260 260
      break;
261 261
    }
262 262
  }
263 263

	
264
  void ArgParser::show(std::ostream &os,Groups::iterator i)
264
  void ArgParser::show(std::ostream &os,Groups::const_iterator i) const
265 265
  {
266
    GroupData::Opts::iterator o=i->second.opts.begin();
266
    GroupData::Opts::const_iterator o=i->second.opts.begin();
267 267
    while(o!=i->second.opts.end()) {
268 268
      show(os,_opts.find(*o));
269 269
      ++o;
270 270
      if(o!=i->second.opts.end()) os<<'|';
271 271
    }
272 272
  }
273 273

	
274
  void ArgParser::showHelp(Opts::iterator i)
274
  void ArgParser::showHelp(Opts::const_iterator i) const
275 275
  {
276 276
    if(i->second.help.size()==0||i->second.syn) return;
277 277
    std::cerr << "  ";
278 278
    show(std::cerr,i);
279 279
    std::cerr << std::endl;
280 280
    std::cerr << "     " << i->second.help << std::endl;
281 281
  }
282
  void ArgParser::showHelp(std::vector<ArgParser::OtherArg>::iterator i)
282
  void ArgParser::showHelp(std::vector<ArgParser::OtherArg>::const_iterator i)
283
    const
283 284
  {
284 285
    if(i->help.size()==0) return;
285 286
    std::cerr << "  " << i->name << std::endl
286 287
              << "     " << i->help << std::endl;
287 288
  }
288 289

	
289
  void ArgParser::shortHelp()
290
  void ArgParser::shortHelp() const
290 291
  {
291 292
    const unsigned int LINE_LEN=77;
292 293
    const std::string indent("    ");
293 294
    std::cerr << "Usage:\n  " << _command_name;
294 295
    int pos=_command_name.size()+2;
295
    for(Groups::iterator g=_groups.begin();g!=_groups.end();++g) {
296
    for(Groups::const_iterator g=_groups.begin();g!=_groups.end();++g) {
296 297
      std::ostringstream cstr;
297 298
      cstr << ' ';
298 299
      if(!g->second.mandatory) cstr << '[';
299 300
      show(cstr,g);
300 301
      if(!g->second.mandatory) cstr << ']';
301 302
      if(pos+cstr.str().size()>LINE_LEN) {
302 303
        std::cerr << std::endl << indent;
303 304
        pos=indent.size();
304 305
      }
305 306
      std::cerr << cstr.str();
306 307
      pos+=cstr.str().size();
307 308
    }
308
    for(Opts::iterator i=_opts.begin();i!=_opts.end();++i)
309
    for(Opts::const_iterator i=_opts.begin();i!=_opts.end();++i)
309 310
      if(!i->second.ingroup&&!i->second.syn) {
310 311
        std::ostringstream cstr;
311 312
        cstr << ' ';
312 313
        if(!i->second.mandatory) cstr << '[';
313 314
        show(cstr,i);
314 315
        if(!i->second.mandatory) cstr << ']';
315 316
        if(pos+cstr.str().size()>LINE_LEN) {
316 317
          std::cerr << std::endl << indent;
317 318
          pos=indent.size();
318 319
        }
319 320
        std::cerr << cstr.str();
320 321
        pos+=cstr.str().size();
321 322
      }
322
    for(std::vector<OtherArg>::iterator i=_others_help.begin();
323
    for(std::vector<OtherArg>::const_iterator i=_others_help.begin();
323 324
        i!=_others_help.end();++i)
324 325
      {
325 326
        std::ostringstream cstr;
326 327
        cstr << ' ' << i->name;
327 328

	
328 329
        if(pos+cstr.str().size()>LINE_LEN) {
329 330
          std::cerr << std::endl << indent;
330 331
          pos=indent.size();
331 332
        }
332 333
        std::cerr << cstr.str();
333 334
        pos+=cstr.str().size();
334 335
      }
335 336
    std::cerr << std::endl;
336 337
  }
337 338

	
338
  void ArgParser::showHelp()
339
  void ArgParser::showHelp() const
339 340
  {
340 341
    shortHelp();
341 342
    std::cerr << "Where:\n";
342
    for(std::vector<OtherArg>::iterator i=_others_help.begin();
343
    for(std::vector<OtherArg>::const_iterator i=_others_help.begin();
343 344
        i!=_others_help.end();++i) showHelp(i);
344
    for(Opts::iterator i=_opts.begin();i!=_opts.end();++i) showHelp(i);
345
    for(Opts::const_iterator i=_opts.begin();i!=_opts.end();++i) showHelp(i);
345 346
    exit(1);
346 347
  }
347 348

	
348 349

	
349
  void ArgParser::unknownOpt(std::string arg)
350
  void ArgParser::unknownOpt(std::string arg) const
350 351
  {
351 352
    std::cerr << "\nUnknown option: " << arg << "\n";
352 353
    std::cerr << "\nType '" << _command_name <<
353 354
      " --help' to obtain a short summary on the usage.\n\n";
354 355
    exit(1);
355 356
  }
356 357

	
357
  void ArgParser::requiresValue(std::string arg, OptType t)
358
  void ArgParser::requiresValue(std::string arg, OptType t) const
358 359
  {
359 360
    std::cerr << "Argument '" << arg << "' requires a";
360 361
    switch(t) {
361 362
    case STRING:
362 363
      std::cerr << " string";
363 364
      break;
364 365
    case INTEGER:
365 366
      std::cerr << "n integer";
366 367
      break;
367 368
    case DOUBLE:
368 369
      std::cerr << " floating point";
369 370
      break;
370 371
    default:
371 372
      break;
372 373
    }
373 374
    std::cerr << " value\n\n";
374 375
    showHelp();
375 376
  }
376 377

	
377 378

	
378
  void ArgParser::checkMandatories()
379
  void ArgParser::checkMandatories() const
379 380
  {
380 381
    bool ok=true;
381
    for(Opts::iterator i=_opts.begin();i!=_opts.end();++i)
382
    for(Opts::const_iterator i=_opts.begin();i!=_opts.end();++i)
382 383
      if(i->second.mandatory&&!i->second.set)
383 384
        {
384 385
          if(ok)
385 386
            std::cerr << _command_name
386 387
                      << ": The following mandatory arguments are missing.\n";
387 388
          ok=false;
388 389
          showHelp(i);
389 390
        }
390
    for(Groups::iterator i=_groups.begin();i!=_groups.end();++i)
391
    for(Groups::const_iterator i=_groups.begin();i!=_groups.end();++i)
391 392
      if(i->second.mandatory||i->second.only_one)
392 393
        {
393 394
          int set=0;
394
          for(GroupData::Opts::iterator o=i->second.opts.begin();
395
          for(GroupData::Opts::const_iterator o=i->second.opts.begin();
395 396
              o!=i->second.opts.end();++o)
396 397
            if(_opts.find(*o)->second.set) ++set;
397 398
          if(i->second.mandatory&&!set) {
398 399
            std::cerr << _command_name <<
399 400
              ": At least one of the following arguments is mandatory.\n";
400 401
            ok=false;
401
            for(GroupData::Opts::iterator o=i->second.opts.begin();
402
            for(GroupData::Opts::const_iterator o=i->second.opts.begin();
402 403
                o!=i->second.opts.end();++o)
403 404
              showHelp(_opts.find(*o));
404 405
          }
405 406
          if(i->second.only_one&&set>1) {
406 407
            std::cerr << _command_name <<
407 408
              ": At most one of the following arguments can be given.\n";
408 409
            ok=false;
409
            for(GroupData::Opts::iterator o=i->second.opts.begin();
410
            for(GroupData::Opts::const_iterator o=i->second.opts.begin();
410 411
                o!=i->second.opts.end();++o)
411 412
              showHelp(_opts.find(*o));
412 413
          }
413 414
        }
414 415
    if(!ok) {
415 416
      std::cerr << "\nType '" << _command_name <<
416 417
        " --help' to obtain a short summary on the usage.\n\n";
417 418
      exit(1);
418 419
    }
419 420
  }
420 421

	
421 422
  ArgParser &ArgParser::parse()
422 423
  {
423 424
    for(int ar=1; ar<_argc; ++ar) {
424 425
      std::string arg(_argv[ar]);
425 426
      if (arg[0] != '-' || arg.size() == 1) {
426 427
        _file_args.push_back(arg);
427 428
      }
428 429
      else {
429 430
        Opts::iterator i = _opts.find(arg.substr(1));
430 431
        if(i==_opts.end()) unknownOpt(arg);
431 432
        else {
432 433
          if(i->second.syn) i=_opts.find(i->second.help);
433 434
          ParData &p(i->second);
Ignore white space 48 line context
... ...
@@ -250,133 +250,136 @@
250 250
    ArgParser &optionGroup(const std::string &group,
251 251
                           const std::string &opt);
252 252

	
253 253
    ///Make the members of a group exclusive
254 254

	
255 255
    ///If you call this function for a group, than at most one of them can be
256 256
    ///given at the same time.
257 257
    ArgParser &onlyOneGroup(const std::string &group);
258 258

	
259 259
    ///Make a group mandatory
260 260

	
261 261
    ///Using this function, at least one of the members of \c group
262 262
    ///must be given.
263 263
    ArgParser &mandatoryGroup(const std::string &group);
264 264

	
265 265
    ///Create synonym to an option
266 266

	
267 267
    ///With this function you can create a synonym \c syn of the
268 268
    ///option \c opt.
269 269
    ArgParser &synonym(const std::string &syn,
270 270
                           const std::string &opt);
271 271

	
272 272
    ///@}
273 273

	
274
    void show(std::ostream &os,Opts::iterator i);
275
    void show(std::ostream &os,Groups::iterator i);
276
    void showHelp(Opts::iterator i);
277
    void showHelp(std::vector<OtherArg>::iterator i);
278
    void shortHelp();
279
    void showHelp();
274
  private:
275
    void show(std::ostream &os,Opts::const_iterator i) const;
276
    void show(std::ostream &os,Groups::const_iterator i) const;
277
    void showHelp(Opts::const_iterator i) const;
278
    void showHelp(std::vector<OtherArg>::const_iterator i) const;
280 279

	
281
    void unknownOpt(std::string arg);
280
    void unknownOpt(std::string arg) const;
282 281

	
283
    void requiresValue(std::string arg, OptType t);
284
    void checkMandatories();
282
    void requiresValue(std::string arg, OptType t) const;
283
    void checkMandatories() const;
284

	
285
    void shortHelp() const;
286
    void showHelp() const;
287
  public:
285 288

	
286 289
    ///Start the parsing process
287 290
    ArgParser &parse();
288 291

	
289 292
    /// Synonym for parse()
290 293
    ArgParser &run()
291 294
    {
292 295
      return parse();
293 296
    }
294 297

	
295 298
    ///Give back the command name (the 0th argument)
296
    const std::string &commandName() { return _command_name; }
299
    const std::string &commandName() const { return _command_name; }
297 300

	
298 301
    ///Check if an opion has been given to the command.
299
    bool given(std::string op)
302
    bool given(std::string op) const
300 303
    {
301
      Opts::iterator i = _opts.find(op);
304
      Opts::const_iterator i = _opts.find(op);
302 305
      return i!=_opts.end()?i->second.set:false;
303 306
    }
304 307

	
305 308

	
306 309
    ///Magic type for operator[]
307 310

	
308 311
    ///This is the type of the return value of ArgParser::operator[]().
309 312
    ///It automatically converts to \c int, \c double, \c bool or
310 313
    ///\c std::string if the type of the option matches, otherwise it
311 314
    ///throws an exception (i.e. it performs runtime type checking).
312 315
    class RefType
313 316
    {
314
      ArgParser &_parser;
317
      const ArgParser &_parser;
315 318
      std::string _name;
316 319
    public:
317 320
      ///\e
318
      RefType(ArgParser &p,const std::string &n) :_parser(p),_name(n) {}
321
      RefType(const ArgParser &p,const std::string &n) :_parser(p),_name(n) {}
319 322
      ///\e
320 323
      operator bool()
321 324
      {
322
        Opts::iterator i = _parser._opts.find(_name);
325
        Opts::const_iterator i = _parser._opts.find(_name);
323 326
        LEMON_ASSERT(i!=_parser._opts.end(),
324 327
                     std::string()+"Unkown option: '"+_name+"'");
325 328
        LEMON_ASSERT(i->second.type==ArgParser::BOOL,
326 329
                     std::string()+"'"+_name+"' is a bool option");
327 330
        return *(i->second.bool_p);
328 331
      }
329 332
      ///\e
330 333
      operator std::string()
331 334
      {
332
        Opts::iterator i = _parser._opts.find(_name);
335
        Opts::const_iterator i = _parser._opts.find(_name);
333 336
        LEMON_ASSERT(i!=_parser._opts.end(),
334 337
                     std::string()+"Unkown option: '"+_name+"'");
335 338
        LEMON_ASSERT(i->second.type==ArgParser::STRING,
336 339
                     std::string()+"'"+_name+"' is a string option");
337 340
        return *(i->second.string_p);
338 341
      }
339 342
      ///\e
340 343
      operator double()
341 344
      {
342
        Opts::iterator i = _parser._opts.find(_name);
345
        Opts::const_iterator i = _parser._opts.find(_name);
343 346
        LEMON_ASSERT(i!=_parser._opts.end(),
344 347
                     std::string()+"Unkown option: '"+_name+"'");
345 348
        LEMON_ASSERT(i->second.type==ArgParser::DOUBLE ||
346 349
                     i->second.type==ArgParser::INTEGER,
347 350
                     std::string()+"'"+_name+"' is a floating point option");
348 351
        return i->second.type==ArgParser::DOUBLE ?
349 352
          *(i->second.double_p) : *(i->second.int_p);
350 353
      }
351 354
      ///\e
352 355
      operator int()
353 356
      {
354
        Opts::iterator i = _parser._opts.find(_name);
357
        Opts::const_iterator i = _parser._opts.find(_name);
355 358
        LEMON_ASSERT(i!=_parser._opts.end(),
356 359
                     std::string()+"Unkown option: '"+_name+"'");
357 360
        LEMON_ASSERT(i->second.type==ArgParser::INTEGER,
358 361
                     std::string()+"'"+_name+"' is an integer option");
359 362
        return *(i->second.int_p);
360 363
      }
361 364

	
362 365
    };
363 366

	
364 367
    ///Give back the value of an option
365 368

	
366 369
    ///Give back the value of an option.
367 370
    ///\sa RefType
368
    RefType operator[](const std::string &n)
371
    RefType operator[](const std::string &n) const
369 372
    {
370 373
      return RefType(*this, n);
371 374
    }
372 375

	
373 376
    ///Give back the non-option type arguments.
374 377

	
375 378
    ///Give back a reference to a vector consisting of the program arguments
376 379
    ///not starting with a '-' character.
377
    std::vector<std::string> &files() { return _file_args; }
380
    const std::vector<std::string> &files() const { return _file_args; }
378 381

	
379 382
  };
380 383
}
381 384

	
382 385
#endif // LEMON_ARG_PARSER
0 comments (0 inline)