]> Creatis software - cpPlugins.git/blob - lib/tclap/CmdLine.h
...
[cpPlugins.git] / lib / tclap / CmdLine.h
1 // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-
2
3 /******************************************************************************
4  *
5  *  file:  CmdLine.h
6  *
7  *  Copyright (c) 2003, Michael E. Smoot .
8  *  Copyright (c) 2004, Michael E. Smoot, Daniel Aarno.
9  *  All rights reserved.
10  *
11  *  See the file COPYING in the top directory of this distribution for
12  *  more information.
13  *
14  *  THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
15  *  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17  *  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19  *  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20  *  DEALINGS IN THE SOFTWARE.
21  *
22  *****************************************************************************/
23
24 #ifndef TCLAP_CMDLINE_H
25 #define TCLAP_CMDLINE_H
26
27 #include <tclap/SwitchArg.h>
28 #include <tclap/MultiSwitchArg.h>
29 #include <tclap/UnlabeledValueArg.h>
30 #include <tclap/UnlabeledMultiArg.h>
31
32 #include <tclap/XorHandler.h>
33 #include <tclap/HelpVisitor.h>
34 #include <tclap/VersionVisitor.h>
35 #include <tclap/IgnoreRestVisitor.h>
36
37 #include <tclap/CmdLineOutput.h>
38 #include <tclap/StdOutput.h>
39
40 #include <tclap/Constraint.h>
41 #include <tclap/ValuesConstraint.h>
42
43 #include <string>
44 #include <vector>
45 #include <list>
46 #include <iostream>
47 #include <iomanip>
48 #include <algorithm>
49 #include <stdlib.h> // Needed for exit(), which isn't defined in some envs.
50
51 namespace TCLAP {
52
53 template<typename T> void DelPtr(T ptr)
54 {
55         delete ptr;
56 }
57
58 template<typename C> void ClearContainer(C &c)
59 {
60         typedef typename C::value_type value_type;
61         std::for_each(c.begin(), c.end(), DelPtr<value_type>);
62         c.clear();
63 }
64
65
66 /**
67  * The base class that manages the command line definition and passes
68  * along the parsing to the appropriate Arg classes.
69  */
70 class CmdLine : public CmdLineInterface
71 {
72         protected:
73
74                 /**
75                  * The list of arguments that will be tested against the
76                  * command line.
77                  */
78                 std::list<Arg*> _argList;
79
80                 /**
81                  * The name of the program.  Set to argv[0].
82                  */
83                 std::string _progName;
84
85                 /**
86                  * A message used to describe the program.  Used in the usage output.
87                  */
88                 std::string _message;
89
90                 /**
91                  * The version to be displayed with the --version switch.
92                  */
93                 std::string _version;
94
95                 /**
96                  * The number of arguments that are required to be present on
97                  * the command line. This is set dynamically, based on the
98                  * Args added to the CmdLine object.
99                  */
100                 int _numRequired;
101
102                 /**
103                  * The character that is used to separate the argument flag/name
104                  * from the value.  Defaults to ' ' (space).
105                  */
106                 char _delimiter;
107
108                 /**
109                  * The handler that manages xoring lists of args.
110                  */
111                 XorHandler _xorHandler;
112
113                 /**
114                  * A list of Args to be explicitly deleted when the destructor
115                  * is called.  At the moment, this only includes the three default
116                  * Args.
117                  */
118                 std::list<Arg*> _argDeleteOnExitList;
119
120                 /**
121                  * A list of Visitors to be explicitly deleted when the destructor
122                  * is called.  At the moment, these are the Visitors created for the
123                  * default Args.
124                  */
125                 std::list<Visitor*> _visitorDeleteOnExitList;
126
127                 /**
128                  * Object that handles all output for the CmdLine.
129                  */
130                 CmdLineOutput* _output;
131
132                 /**
133                  * Should CmdLine handle parsing exceptions internally?
134                  */
135                 bool _handleExceptions;
136
137                 /**
138                  * Throws an exception listing the missing args.
139                  */
140                 void missingArgsException();
141
142                 /**
143                  * Checks whether a name/flag string matches entirely matches
144                  * the Arg::blankChar.  Used when multiple switches are combined
145                  * into a single argument.
146                  * \param s - The message to be used in the usage.
147                  */
148                 bool _emptyCombined(const std::string& s);
149
150                 /**
151                  * Perform a delete ptr; operation on ptr when this object is deleted.
152                  */
153                 void deleteOnExit(Arg* ptr);
154
155                 /**
156                  * Perform a delete ptr; operation on ptr when this object is deleted.
157                  */
158                 void deleteOnExit(Visitor* ptr);
159
160 private:
161
162                 /**
163                  * Prevent accidental copying.
164                  */
165                 CmdLine(const CmdLine& rhs);
166                 CmdLine& operator=(const CmdLine& rhs);
167
168                 /**
169                  * Encapsulates the code common to the constructors
170                  * (which is all of it).
171                  */
172                 void _constructor();
173
174
175                 /**
176                  * Is set to true when a user sets the output object. We use this so
177                  * that we don't delete objects that are created outside of this lib.
178                  */
179                 bool _userSetOutput;
180
181                 /**
182                  * Whether or not to automatically create help and version switches.
183                  */
184                 bool _helpAndVersion;
185
186                 /**
187                  * Whether or not to ignore unmatched args.
188                  */
189                 bool _ignoreUnmatched;
190
191         public:
192
193                 /**
194                  * Command line constructor. Defines how the arguments will be
195                  * parsed.
196                  * \param message - The message to be used in the usage
197                  * output.
198                  * \param delimiter - The character that is used to separate
199                  * the argument flag/name from the value.  Defaults to ' ' (space).
200                  * \param version - The version number to be used in the
201                  * --version switch.
202                  * \param helpAndVersion - Whether or not to create the Help and
203                  * Version switches. Defaults to true.
204                  */
205                 CmdLine(const std::string& message,
206                                 const char delimiter = ' ',
207                                 const std::string& version = "none",
208                                 bool helpAndVersion = true);
209
210                 /**
211                  * Deletes any resources allocated by a CmdLine object.
212                  */
213                 virtual ~CmdLine();
214
215                 /**
216                  * Adds an argument to the list of arguments to be parsed.
217                  * \param a - Argument to be added.
218                  */
219                 void add( Arg& a );
220
221                 /**
222                  * An alternative add.  Functionally identical.
223                  * \param a - Argument to be added.
224                  */
225                 void add( Arg* a );
226
227                 /**
228                  * Add two Args that will be xor'd.  If this method is used, add does
229                  * not need to be called.
230                  * \param a - Argument to be added and xor'd.
231                  * \param b - Argument to be added and xor'd.
232                  */
233                 void xorAdd( Arg& a, Arg& b );
234
235                 /**
236                  * Add a list of Args that will be xor'd.  If this method is used,
237                  * add does not need to be called.
238                  * \param xors - List of Args to be added and xor'd.
239                  */
240                 void xorAdd( const std::vector<Arg*>& xors );
241
242                 /**
243                  * Parses the command line.
244                  * \param argc - Number of arguments.
245                  * \param argv - Array of arguments.
246                  */
247                 void parse(int argc, const char * const * argv);
248
249                 /**
250                  * Parses the command line.
251                  * \param args - A vector of strings representing the args.
252                  * args[0] is still the program name.
253                  */
254                 void parse(std::vector<std::string>& args);
255
256                 /**
257                  *
258                  */
259                 CmdLineOutput* getOutput();
260
261                 /**
262                  *
263                  */
264                 void setOutput(CmdLineOutput* co);
265
266                 /**
267                  *
268                  */
269                 std::string& getVersion();
270
271                 /**
272                  *
273                  */
274                 std::string& getProgramName();
275
276                 /**
277                  *
278                  */
279                 std::list<Arg*>& getArgList();
280
281                 /**
282                  *
283                  */
284                 XorHandler& getXorHandler();
285
286                 /**
287                  *
288                  */
289                 char getDelimiter();
290
291                 /**
292                  *
293                  */
294                 std::string& getMessage();
295
296                 /**
297                  *
298                  */
299                 bool hasHelpAndVersion();
300
301                 /**
302                  * Disables or enables CmdLine's internal parsing exception handling.
303                  *
304                  * @param state Should CmdLine handle parsing exceptions internally?
305                  */
306                 void setExceptionHandling(const bool state);
307
308                 /**
309                  * Returns the current state of the internal exception handling.
310                  *
311                  * @retval true Parsing exceptions are handled internally.
312                  * @retval false Parsing exceptions are propagated to the caller.
313                  */
314                 bool getExceptionHandling() const;
315
316                 /**
317                  * Allows the CmdLine object to be reused.
318                  */
319                 void reset();
320
321                 /**
322                  * Allows unmatched args to be ignored. By default false.
323                  * 
324                  * @param ignore If true the cmdline will ignore any unmatched args
325                  * and if false it will behave as normal.
326                  */
327                 void ignoreUnmatched(const bool ignore);
328 };
329
330
331 ///////////////////////////////////////////////////////////////////////////////
332 //Begin CmdLine.cpp
333 ///////////////////////////////////////////////////////////////////////////////
334
335 inline CmdLine::CmdLine(const std::string& m,
336                         char delim,
337                         const std::string& v,
338                         bool help )
339     :
340   _argList(std::list<Arg*>()),
341   _progName("not_set_yet"),
342   _message(m),
343   _version(v),
344   _numRequired(0),
345   _delimiter(delim),
346   _xorHandler(XorHandler()),
347   _argDeleteOnExitList(std::list<Arg*>()),
348   _visitorDeleteOnExitList(std::list<Visitor*>()),
349   _output(0),
350   _handleExceptions(true),
351   _userSetOutput(false),
352   _helpAndVersion(help),
353   _ignoreUnmatched(false)
354 {
355         _constructor();
356 }
357
358 inline CmdLine::~CmdLine()
359 {
360         ClearContainer(_argDeleteOnExitList);
361         ClearContainer(_visitorDeleteOnExitList);
362
363         if ( !_userSetOutput ) {
364                 delete _output;
365                 _output = 0;
366         }
367 }
368
369 inline void CmdLine::_constructor()
370 {
371         _output = new StdOutput;
372
373         Arg::setDelimiter( _delimiter );
374
375         Visitor* v;
376
377         if ( _helpAndVersion )
378         {
379                 v = new HelpVisitor( this, &_output );
380                 SwitchArg* help = new SwitchArg("h","help",
381                                       "Displays usage information and exits.",
382                                       false, v);
383                 add( help );
384                 deleteOnExit(help);
385                 deleteOnExit(v);
386
387                 v = new VersionVisitor( this, &_output );
388                 SwitchArg* vers = new SwitchArg("","version",
389                                       "Displays version information and exits.",
390                                       false, v);
391                 add( vers );
392                 deleteOnExit(vers);
393                 deleteOnExit(v);
394         }
395
396         v = new IgnoreRestVisitor();
397         SwitchArg* ignore  = new SwitchArg(Arg::flagStartString(),
398                   Arg::ignoreNameString(),
399                   "Ignores the rest of the labeled arguments following this flag.",
400                   false, v);
401         add( ignore );
402         deleteOnExit(ignore);
403         deleteOnExit(v);
404 }
405
406 inline void CmdLine::xorAdd( const std::vector<Arg*>& ors )
407 {
408         _xorHandler.add( ors );
409
410         for (ArgVectorIterator it = ors.begin(); it != ors.end(); it++)
411         {
412                 (*it)->forceRequired();
413                 (*it)->setRequireLabel( "OR required" );
414                 add( *it );
415         }
416 }
417
418 inline void CmdLine::xorAdd( Arg& a, Arg& b )
419 {
420         std::vector<Arg*> ors;
421         ors.push_back( &a );
422         ors.push_back( &b );
423         xorAdd( ors );
424 }
425
426 inline void CmdLine::add( Arg& a )
427 {
428         add( &a );
429 }
430
431 inline void CmdLine::add( Arg* a )
432 {
433         for( ArgListIterator it = _argList.begin(); it != _argList.end(); it++ )
434                 if ( *a == *(*it) )
435                         throw( SpecificationException(
436                                 "Argument with same flag/name already exists!",
437                                 a->longID() ) );
438
439         a->addToList( _argList );
440
441         if ( a->isRequired() )
442                 _numRequired++;
443 }
444
445
446 inline void CmdLine::parse(int argc, const char * const * argv)
447 {
448                 // this step is necessary so that we have easy access to
449                 // mutable strings.
450                 std::vector<std::string> args;
451                 for (int i = 0; i < argc; i++)
452                         args.push_back(argv[i]);
453
454                 parse(args);
455 }
456
457 inline void CmdLine::parse(std::vector<std::string>& args)
458 {
459         bool shouldExit = false;
460         int estat = 0;
461
462         try {
463                 _progName = args.front();
464                 args.erase(args.begin());
465
466                 int requiredCount = 0;
467
468                 for (int i = 0; static_cast<unsigned int>(i) < args.size(); i++) 
469                 {
470                         bool matched = false;
471                         for (ArgListIterator it = _argList.begin();
472                              it != _argList.end(); it++) {
473                                 if ( (*it)->processArg( &i, args ) )
474                                 {
475                                         requiredCount += _xorHandler.check( *it );
476                                         matched = true;
477                                         break;
478                                 }
479                         }
480
481                         // checks to see if the argument is an empty combined
482                         // switch and if so, then we've actually matched it
483                         if ( !matched && _emptyCombined( args[i] ) )
484                                 matched = true;
485
486                         if ( !matched && !Arg::ignoreRest() && !_ignoreUnmatched)
487                                 throw(CmdLineParseException("Couldn't find match "
488                                                             "for argument",
489                                                             args[i]));
490                 }
491
492                 if ( requiredCount < _numRequired )
493                         missingArgsException();
494
495                 if ( requiredCount > _numRequired )
496                         throw(CmdLineParseException("Too many arguments!"));
497
498         } catch ( ArgException& e ) {
499                 // If we're not handling the exceptions, rethrow.
500                 if ( !_handleExceptions) {
501                         throw;
502                 }
503
504                 try {
505                         _output->failure(*this,e);
506                 } catch ( ExitException &ee ) {
507                         estat = ee.getExitStatus();
508                         shouldExit = true;
509                 }
510         } catch (ExitException &ee) {
511                 // If we're not handling the exceptions, rethrow.
512                 if ( !_handleExceptions) {
513                         throw;
514                 }
515
516                 estat = ee.getExitStatus();
517                 shouldExit = true;
518         }
519
520         if (shouldExit)
521                 exit(estat);
522 }
523
524 inline bool CmdLine::_emptyCombined(const std::string& s)
525 {
526         if ( s.length() > 0 && s[0] != Arg::flagStartChar() )
527                 return false;
528
529         for ( int i = 1; static_cast<unsigned int>(i) < s.length(); i++ )
530                 if ( s[i] != Arg::blankChar() )
531                         return false;
532
533         return true;
534 }
535
536 inline void CmdLine::missingArgsException()
537 {
538                 int count = 0;
539
540                 std::string missingArgList;
541                 for (ArgListIterator it = _argList.begin(); it != _argList.end(); it++)
542                 {
543                         if ( (*it)->isRequired() && !(*it)->isSet() )
544                         {
545                                 missingArgList += (*it)->getName();
546                                 missingArgList += ", ";
547                                 count++;
548                         }
549                 }
550                 missingArgList = missingArgList.substr(0,missingArgList.length()-2);
551
552                 std::string msg;
553                 if ( count > 1 )
554                         msg = "Required arguments missing: ";
555                 else
556                         msg = "Required argument missing: ";
557
558                 msg += missingArgList;
559
560                 throw(CmdLineParseException(msg));
561 }
562
563 inline void CmdLine::deleteOnExit(Arg* ptr)
564 {
565         _argDeleteOnExitList.push_back(ptr);
566 }
567
568 inline void CmdLine::deleteOnExit(Visitor* ptr)
569 {
570         _visitorDeleteOnExitList.push_back(ptr);
571 }
572
573 inline CmdLineOutput* CmdLine::getOutput()
574 {
575         return _output;
576 }
577
578 inline void CmdLine::setOutput(CmdLineOutput* co)
579 {
580         if ( !_userSetOutput )
581                 delete _output;
582         _userSetOutput = true;
583         _output = co;
584 }
585
586 inline std::string& CmdLine::getVersion()
587 {
588         return _version;
589 }
590
591 inline std::string& CmdLine::getProgramName()
592 {
593         return _progName;
594 }
595
596 inline std::list<Arg*>& CmdLine::getArgList()
597 {
598         return _argList;
599 }
600
601 inline XorHandler& CmdLine::getXorHandler()
602 {
603         return _xorHandler;
604 }
605
606 inline char CmdLine::getDelimiter()
607 {
608         return _delimiter;
609 }
610
611 inline std::string& CmdLine::getMessage()
612 {
613         return _message;
614 }
615
616 inline bool CmdLine::hasHelpAndVersion()
617 {
618         return _helpAndVersion;
619 }
620
621 inline void CmdLine::setExceptionHandling(const bool state)
622 {
623         _handleExceptions = state;
624 }
625
626 inline bool CmdLine::getExceptionHandling() const
627 {
628         return _handleExceptions;
629 }
630
631 inline void CmdLine::reset()
632 {
633         for( ArgListIterator it = _argList.begin(); it != _argList.end(); it++ )
634                 (*it)->reset();
635         
636         _progName.clear();
637 }
638
639 inline void CmdLine::ignoreUnmatched(const bool ignore)
640 {
641         _ignoreUnmatched = ignore;
642 }
643
644 ///////////////////////////////////////////////////////////////////////////////
645 //End CmdLine.cpp
646 ///////////////////////////////////////////////////////////////////////////////
647
648
649
650 } //namespace TCLAP
651 #endif