BASIS  version 1.2.3 (revision 2104)
MultiArg.h
Go to the documentation of this file.
00001 /**
00002  * @file  basis/MultiArg.h
00003  * @brief Extends TCLAP's MultiArg implementation.
00004  *
00005  * Instead of always only consuming one argument after the argument name or
00006  * flag, this MultiArg implementation consumes N arguments, where the number
00007  * of arguments N is set to a fixed number at construction time.
00008  *
00009  * Copyright (c) 2011 University of Pennsylvania. All rights reserved.<br />
00010  * See https://www.cbica.upenn.edu/sbia/software/license.html or COPYING file.
00011  *
00012  * Contact: SBIA Group <sbia-software at uphs.upenn.edu>
00013  */
00014 
00015 #pragma once
00016 #ifndef _SBIA_BASIS_MULTIARG_H
00017 #define _SBIA_BASIS_MULTIARG_H
00018 
00019 
00020 #include <sbia/tclap/MultiArg.h>
00021 
00022 
00023 namespace sbia
00024 {
00025 
00026 namespace basis
00027 {
00028 
00029 
00030 /**
00031  * @brief An argument that allows multiple values of type T to be specified.
00032  *
00033  * Very similar to a TCLAP::ValueArg, except a vector of values will be returned
00034  * instead of just one. Unlike TCLAP::MultiArg, this argument will each time
00035  * its option keyword or flag is encountered process N > 0 argument values,
00036  * where the number N is specified at construction time. Moreover, this argument
00037  * can be given several times. Hence, the returned vector of values has length
00038  * N * M, where M is the number of times the argument was given on the
00039  * command-line.
00040  *
00041  * Copyright (c) 2011 University of Pennsylvania. All rights reserved.<br />
00042  * See https://www.cbica.upenn.edu/sbia/software/license.html or COPYING file.
00043  *
00044  * @ingroup CxxCmdLine
00045  */
00046 template <class T>
00047 class MultiArg : public TCLAP::MultiArg<T>
00048 {
00049     // -----------------------------------------------------------------------
00050     // construction / destruction
00051 public:
00052 
00053     /**
00054      * @brief Constructor.
00055      *
00056      * @param [in] flag       The one character flag that identifies this
00057      *                        argument on the command line.
00058      * @param [in] name       A one word name for the argument.  Can be
00059      *                        used as a long flag on the command line.
00060      * @param [in] desc       A description of what the argument is for or does.
00061      * @param [in] req        Whether the argument is required on the command-line.
00062      * @param [in] typeDesc   A short, human readable description of the
00063      *                        type that this object expects.  This is used in
00064      *                        the generation of the USAGE statement. The goal
00065      *                        is to be helpful to the end user of the program.
00066      * @param [in] n          Number of values per argument occurrence.
00067      * @param [in] once       Accept argument only once.
00068      * @param [in] v          An optional visitor. You probably should not
00069      *                        use this unless you have a very good reason.
00070      */
00071     MultiArg(const std::string& flag,
00072              const std::string& name,
00073              const std::string& desc,
00074              bool               req,
00075              const std::string& typeDesc,
00076              unsigned int       n    = 1,
00077              bool               once = false,
00078              TCLAP::Visitor*    v    = NULL);
00079 
00080     /**
00081      * @brief Constructor.
00082      *
00083      * @param [in] flag       The one character flag that identifies this
00084      *                        argument on the command line.
00085      * @param [in] name       A one word name for the argument.  Can be
00086      *                        used as a long flag on the command line.
00087      * @param [in] desc       A description of what the argument is for or does.
00088      * @param [in] req        Whether the argument is required on the command-line.
00089      * @param [in] typeDesc   A short, human readable description of the
00090      *                        type that this object expects.  This is used in
00091      *                        the generation of the USAGE statement. The goal
00092      *                        is to be helpful to the end user of the program.
00093      * @param [in] parser     A CmdLine parser object to add this Arg to
00094      * @param [in] n          Number of values per argument occurrence.
00095      * @param [in] once       Accept argument only once.
00096      * @param [in] v          An optional visitor. You probably should not
00097      *                        use this unless you have a very good reason.
00098      */
00099     MultiArg(const std::string&       flag, 
00100              const std::string&       name,
00101              const std::string&       desc,
00102              bool                     req,
00103              const std::string&       typeDesc,
00104              TCLAP::CmdLineInterface& parser,
00105              unsigned int             n    = 1,
00106              bool                     once = false,
00107              TCLAP::Visitor*          v    = NULL);
00108 
00109     /**
00110      * @brief Constructor.
00111      *
00112      * @param [in] flag       The one character flag that identifies this
00113      *                        argument on the command line.
00114      * @param [in] name       A one word name for the argument.  Can be
00115      *                        used as a long flag on the command line.
00116      * @param [in] desc       A description of what the argument is for or does.
00117      * @param [in] req        Whether the argument is required on the command-line.
00118      * @param [in] constraint A pointer to a Constraint object used
00119      *                        to constrain this Arg.
00120      * @param [in] n          Number of values per argument occurrence.
00121      * @param [in] once       Accept argument only once.
00122      * @param [in] v          An optional visitor. You probably should not
00123      *                        use this unless you have a very good reason.
00124      */
00125     MultiArg(const std::string&    flag,
00126              const std::string&    name,
00127              const std::string&    desc,
00128              bool                  req,
00129              TCLAP::Constraint<T>* constraint,
00130              unsigned int          n    = 1,
00131              bool                  once = false,
00132              TCLAP::Visitor*       v    = NULL);
00133 
00134     /**
00135      * @brief Constructor.
00136      *
00137      * @param [in] flag       The one character flag that identifies this
00138      *                        argument on the command line.
00139      * @param [in] name       A one word name for the argument.  Can be
00140      *                        used as a long flag on the command line.
00141      * @param [in] desc       A description of what the argument is for or does.
00142      * @param [in] req        Whether the argument is required on the command-line.
00143      * @param [in] constraint A pointer to a Constraint object used
00144      *                        to constrain this Arg.
00145      * @param [in] parser     A CmdLine parser object to add this Arg to.
00146      * @param [in] n          Number of values per argument occurrence.
00147      * @param [in] once       Accept argument only once.
00148      * @param [in] v          An optional visitor. You probably should not
00149      *                        use this unless you have a very good reason.
00150      */
00151     MultiArg(const std::string&       flag, 
00152              const std::string&       name,
00153              const std::string&       desc,
00154              bool                     req,
00155              TCLAP::Constraint<T>*    constraint,
00156              TCLAP::CmdLineInterface& parser,
00157              unsigned int             n    = 1,
00158              bool                     once = false,
00159              TCLAP::Visitor*          v    = NULL);
00160  
00161     // -----------------------------------------------------------------------
00162     // parsing
00163 public:
00164 
00165     /**
00166      * @brief Handles the processing of the argument.
00167      *
00168      * This re-implements the TCLAP::MultiArg version of this method to set
00169      * the _value of the argument appropriately. It knows the difference
00170      * between labeled and unlabeled.
00171      *
00172      * @param [in, out] i    Pointer to the current argument in the list.
00173      * @param [in, out] args Mutable list of strings. Passed from main().
00174      */
00175     virtual bool processArg(int* i, std::vector<std::string>& args); 
00176 
00177     /**
00178      * @brief Whether the argument is required or not.
00179      *
00180      * Once we've matched the first value, then the arg is no longer required,
00181      * except if the argument is only accepted once with multiple values.
00182      */
00183     virtual bool isRequired() const;
00184 
00185     // -----------------------------------------------------------------------
00186     // unsupported
00187 private:
00188 
00189     MultiArg<T>(const MultiArg<T>&);            ///< Not implemented.
00190     MultiArg<T>& operator=(const MultiArg<T>&); ///< Not implemented.
00191 
00192     // -----------------------------------------------------------------------
00193     // member variables
00194 protected:
00195 
00196     unsigned int _numberOfArguments; ///< Number of values to process each time.
00197 
00198 }; // class MultiArg
00199 
00200 
00201 // ===========================================================================
00202 // template definitions
00203 // ===========================================================================
00204 
00205 // ---------------------------------------------------------------------------
00206 template <class T>
00207 MultiArg<T>::MultiArg(const std::string& flag, 
00208                       const std::string& name,
00209                       const std::string& desc,
00210                       bool req,
00211                       const std::string& typeDesc,
00212                       unsigned int n,
00213                       bool once,
00214                       TCLAP::Visitor* v)
00215 :
00216    TCLAP::MultiArg<T>(flag, name, desc, req, typeDesc, v),
00217    _numberOfArguments(n)
00218 {
00219     if (once) TCLAP::MultiArg<T>::_acceptsMultipleValues = false;
00220 }
00221 
00222 // ---------------------------------------------------------------------------
00223 template <class T>
00224 MultiArg<T>::MultiArg(const std::string& flag, 
00225                       const std::string& name,
00226                       const std::string& desc,
00227                       bool req,
00228                       const std::string& typeDesc,
00229                       TCLAP::CmdLineInterface& parser,
00230                       unsigned int n,
00231                       bool once,
00232                       TCLAP::Visitor* v)
00233 :
00234     TCLAP::MultiArg<T>(flag, name, desc, req, typeDesc, parser, v),
00235     _numberOfArguments(n)
00236 { 
00237     if (once) TCLAP::MultiArg<T>::_acceptsMultipleValues = false;
00238 }
00239 
00240 // ---------------------------------------------------------------------------
00241 template <class T>
00242 MultiArg<T>::MultiArg(const std::string& flag, 
00243                       const std::string& name,
00244                       const std::string& desc,
00245                       bool req,
00246                       TCLAP::Constraint<T>* constraint,
00247                       unsigned int n,
00248                       bool once,
00249                       TCLAP::Visitor* v)
00250 :
00251     TCLAP::MultiArg<T>(flag, name, desc, req, constraint, v),
00252     _numberOfArguments(n)
00253 { 
00254     if (once) TCLAP::MultiArg<T>::_acceptsMultipleValues = false;
00255 }
00256 
00257 // ---------------------------------------------------------------------------
00258 template <class T>
00259 MultiArg<T>::MultiArg(const std::string& flag, 
00260                       const std::string& name,
00261                       const std::string& desc,
00262                       bool req,
00263                       TCLAP::Constraint<T>* constraint,
00264                       TCLAP::CmdLineInterface& parser,
00265                       unsigned int n,
00266                       bool once,
00267                       TCLAP::Visitor* v)
00268 :
00269     TCLAP::MultiArg<T>(flag, name, desc, req, constraint, parser, v),
00270     _numberOfArguments(n)
00271 { 
00272     if (once) TCLAP::MultiArg<T>::_acceptsMultipleValues = false;
00273 }
00274 
00275 // ---------------------------------------------------------------------------
00276 template <class T>
00277 bool MultiArg<T>::processArg(int *i, std::vector<std::string>& args) 
00278 {
00279     if (TCLAP::MultiArg<T>::_ignoreable && TCLAP::Arg::ignoreRest()) {
00280         return false;
00281     }
00282     if (TCLAP::MultiArg<T>::_hasBlanks( args[*i] )) return false;
00283     // separate flag and value if delimiter is not ' '
00284     std::string flag = args[*i];
00285     std::string value = "";
00286     TCLAP::MultiArg<T>::trimFlag(flag, value);
00287     if (!TCLAP::MultiArg<T>::argMatches(flag)) return false;
00288     // check if delimiter was found
00289     if (TCLAP::Arg::delimiter() != ' ' && value == "") {
00290         throw TCLAP::ArgParseException( 
00291                 "Couldn't find delimiter for this argument!",
00292                 TCLAP::MultiArg<T>::toString());
00293     }
00294     // always take the first one, regardless of number of arguments
00295     if (value == "")
00296     {
00297         if (TCLAP::MultiArg<T>::_alreadySet &&
00298                 !TCLAP::MultiArg<T>::_acceptsMultipleValues) {
00299             throw TCLAP::CmdLineParseException("Argument already set!",
00300                                                TCLAP::MultiArg<T>::toString());
00301         }
00302         (*i)++;
00303         if (static_cast<unsigned int>(*i) < args.size()) {
00304             TCLAP::MultiArg<T>::_extractValue(args[*i]);
00305         } else {
00306             throw TCLAP::ArgParseException(
00307                     "Missing a value for this argument!",
00308                     TCLAP::MultiArg<T>::toString());
00309         }
00310     } else {
00311         TCLAP::MultiArg<T>::_extractValue(value);
00312     }
00313     // continue extracting values until number of arguments processed
00314     for (unsigned int n = 1; n < _numberOfArguments; n++) {
00315         (*i)++;
00316         if (static_cast<unsigned int>(*i) < args.size()) {
00317             TCLAP::MultiArg<T>::_extractValue(args[*i]);
00318         } else {
00319             throw TCLAP::ArgParseException(
00320                     "Too few values for this argument!",
00321                     TCLAP::MultiArg<T>::toString());
00322         }
00323     }
00324     TCLAP::MultiArg<T>::_alreadySet = true;
00325     TCLAP::MultiArg<T>::_allowMore  = false;
00326     TCLAP::MultiArg<T>::_checkWithVisitor();
00327     return true;
00328 }
00329 
00330 template <class T>
00331 bool MultiArg<T>::isRequired() const
00332 {
00333     if (TCLAP::MultiArg<T>::_required) {
00334         if (TCLAP::MultiArg<T>::_acceptsMultipleValues
00335                 && TCLAP::MultiArg<T>::_values.size() > 1) {
00336             return false;
00337         } else {
00338             return true;
00339         }
00340     } else {
00341         return false;
00342     }
00343 }
00344 
00345 
00346 } // namespace basis
00347 
00348 } // namespace sbia
00349 
00350 
00351 #endif // _SBIA_BASIS_MULTIARG_H