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