BASIS  r3148
ValueArg.h
Go to the documentation of this file.
00001 /**
00002  * @file  basis/ValueArg.h
00003  * @brief Extends TCLAP's ValueArg implementation.
00004  *
00005  * Instead of throwing an exception if an argument is set more than once,
00006  * this argument type optionally allows the value to be overwritten.
00007  *
00008  * Copyright (c) 2012 University of Pennsylvania. All rights reserved.<br />
00009  * See https://www.cbica.upenn.edu/sbia/software/license.html or COPYING file.
00010  *
00011  * Contact: SBIA Group <sbia-software at uphs.upenn.edu>
00012  */ 
00013 
00014 #pragma once
00015 #ifndef _BASIS_VALUEARG_H
00016 #define _BASIS_VALUEARG_H
00017 
00018 
00019 #include "tclap/ValueArg.h"
00020 
00021 
00022 namespace basis {
00023 
00024 
00025 /**
00026  * @brief An argument that allows multiple values of type T to be specified.
00027  *
00028  * Unlike TCLAP::ValueArg, this argument optionally allows the assignement
00029  * of a value more than once, overwriting the previously set argument value.
00030  * This is useful when a visitor set on another option consumed the previously
00031  * set argument already and thus the value can be overwritten before the
00032  * next appearance of this option. See the basistest-driver executable,
00033  * for example, where the tolerances are stored in a structure every time
00034  * a --compare option is encountered and the tolerances can then be overwritten
00035  * for the next --compare statement.
00036  *
00037  * Copyright (c) 2012 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 ValueArg : public TCLAP::ValueArg<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] value          The default value assigned to this argument if it
00059      *                            is not present on the command line.
00060      * @param [in] typeDesc       A short, human readable description of the
00061      *                            type that this object expects.  This is used in
00062      *                            the generation of the USAGE statement. The goal
00063      *                            is to be helpful to the end user of the program.
00064      * @param [in] allowOverwrite Whether value can be overwritten by another
00065      *                            occurrence of the argument on the command-line.
00066      * @param [in] v              An optional visitor. You probably should not
00067      *                            use this unless you have a very good reason.
00068      */
00069     ValueArg(const std::string& flag,
00070              const std::string& name,
00071              const std::string& desc,
00072              bool               req,
00073              T                  value,
00074              const std::string& typeDesc,
00075              bool               allowOverwrite = false,
00076              TCLAP::Visitor*    v              = NULL);
00077              
00078     /**
00079      * @brief Constructor.
00080      *
00081      * @param [in] flag           The one character flag that identifies this
00082      *                            argument on the command line.
00083      * @param [in] name           A one word name for the argument.  Can be
00084      *                            used as a long flag on the command line.
00085      * @param [in] desc           A description of what the argument is for or does.
00086      * @param [in] req            Whether the argument is required on the command-line.
00087      * @param [in] value          The default value assigned to this argument if it
00088      *                            is not present 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] allowOverwrite Whether value can be overwritten by another
00095      *                            occurrence of the argument on the command-line.
00096      * @param [in] v              An optional visitor. You probably should not
00097      *                            use this unless you have a very good reason.
00098      */
00099     ValueArg(const std::string&       flag,
00100              const std::string&       name,
00101              const std::string&       desc,
00102              bool                     req,
00103              T                        value,
00104              const std::string&       typeDesc,
00105              TCLAP::CmdLineInterface& parser,
00106              bool                     allowOverwrite = 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] value          The default value assigned to this argument if it
00119      *                            is not present on the command line.
00120      * @param [in] constraint     A pointer to a Constraint object used
00121      *                            to constrain this Arg.
00122      * @param [in] parser         A CmdLine parser object to add this Arg to.
00123      * @param [in] allowOverwrite Whether value can be overwritten by another
00124      *                            occurrence of the argument on the command-line.
00125      * @param [in] v              An optional visitor. You probably should not
00126      *                            use this unless you have a very good reason.
00127      */
00128     ValueArg(const std::string&       flag,
00129              const std::string&       name,
00130              const std::string&       desc,
00131              bool                     req,
00132              T                        value,
00133              TCLAP::Constraint<T>*    constraint,
00134              TCLAP::CmdLineInterface& parser,
00135              bool                     allowOverwrite = false,
00136              TCLAP::Visitor*          v              = NULL);
00137   
00138     /**
00139      * @brief Constructor.
00140      *
00141      * @param [in] flag           The one character flag that identifies this
00142      *                            argument on the command line.
00143      * @param [in] name           A one word name for the argument.  Can be
00144      *                            used as a long flag on the command line.
00145      * @param [in] desc           A description of what the argument is for or does.
00146      * @param [in] req            Whether the argument is required on the command-line.
00147      * @param [in] value          The default value assigned to this argument if it
00148      *                            is not present on the command line.
00149      * @param [in] constraint     A pointer to a Constraint object used
00150      *                            to constrain this Arg.
00151      * @param [in] allowOverwrite Whether value can be overwritten by another
00152      *                            occurrence of the argument on the command-line.
00153      * @param [in] v              An optional visitor. You probably should not
00154      *                            use this unless you have a very good reason.
00155      */
00156     ValueArg(const std::string&    flag,
00157              const std::string&    name,
00158              const std::string&    desc,
00159              bool                  req,
00160              T                     value,
00161              TCLAP::Constraint<T>* constraint,
00162              bool                  allowOverwrite = false,
00163              TCLAP::Visitor*       v              = NULL);
00164 
00165     // -----------------------------------------------------------------------
00166     // parsing
00167 public:
00168 
00169     /**
00170      * @brief Handles the processing of the argument.
00171      *
00172      * This re-implements the TCLAP::ValueArg version of this method to
00173      * ignore the _alreadySet flag if _allowOverwrite is true.
00174      *
00175      * @param [in, out] i    Pointer to the current argument in the list.
00176      * @param [in, out] args Mutable list of strings. Passed from main().
00177      */
00178     virtual bool processArg(int* i, std::vector<std::string>& args); 
00179 
00180     // -----------------------------------------------------------------------
00181     // unsupported
00182 private:
00183     ValueArg<T>(const ValueArg<T>&);            ///< Not implemented.
00184     ValueArg<T>& operator=(const ValueArg<T>&); ///< Not implemented.
00185 
00186     // -----------------------------------------------------------------------
00187     // member variables
00188 protected:
00189 
00190     bool _allowOverwrite; ///< Whether argument value can be overwritten by
00191                           ///< another occurrence of this argument.
00192 
00193 }; // class ValueArg
00194 
00195 
00196 // ===========================================================================
00197 // template definitions
00198 // ===========================================================================
00199 
00200 // ---------------------------------------------------------------------------
00201 template <class T>
00202 ValueArg<T>::ValueArg(const std::string& flag, 
00203                       const std::string& name, 
00204                       const std::string& desc, 
00205                       bool req, 
00206                       T val,
00207                       const std::string& typeDesc,
00208                       bool allowOverwrite,
00209                       TCLAP::Visitor* v)
00210 :
00211     TCLAP::ValueArg<T>(flag, name, desc, req, val, typeDesc, v),
00212     _allowOverwrite(allowOverwrite)
00213 {
00214 }
00215 
00216 // ---------------------------------------------------------------------------
00217 template <class T>
00218 ValueArg<T>::ValueArg(const std::string& flag, 
00219                       const std::string& name, 
00220                       const std::string& desc, 
00221                       bool req, 
00222                       T val,
00223                       const std::string& typeDesc,
00224                       TCLAP::CmdLineInterface& parser,
00225                       bool allowOverwrite,
00226                       TCLAP::Visitor* v)
00227 :
00228     TCLAP::ValueArg<T>(flag, name, desc, req, val, typeDesc, parser, v),
00229     _allowOverwrite(allowOverwrite)
00230 { 
00231 }
00232 
00233 // ---------------------------------------------------------------------------
00234 template <class T>
00235 ValueArg<T>::ValueArg(const std::string& flag, 
00236                       const std::string& name, 
00237                       const std::string& desc, 
00238                       bool req, 
00239                       T val,
00240                       TCLAP::Constraint<T>* constraint,
00241                       bool allowOverwrite,
00242                       TCLAP::Visitor* v)
00243 :
00244     TCLAP::ValueArg<T>(flag, name, desc, req, val, constraint, v),
00245     _allowOverwrite(allowOverwrite)
00246 {
00247 }
00248 
00249 // ---------------------------------------------------------------------------
00250 template <class T>
00251 ValueArg<T>::ValueArg(const std::string& flag, 
00252                       const std::string& name, 
00253                       const std::string& desc, 
00254                       bool req, 
00255                       T val,
00256                       TCLAP::Constraint<T>* constraint,
00257                       TCLAP::CmdLineInterface& parser,
00258                       bool allowOverwrite,
00259                       TCLAP::Visitor* v)
00260 :
00261     TCLAP::ValueArg<T>(flag, name, desc, req, val, constraint, parser, v),
00262     _allowOverwrite(allowOverwrite)
00263 { 
00264 }
00265 
00266 // ---------------------------------------------------------------------------
00267 template <class T>
00268 bool ValueArg<T>::processArg(int* i, std::vector<std::string>& args)
00269 {
00270     if (TCLAP::ValueArg<T>::_ignoreable && TCLAP::ValueArg<T>::ignoreRest()) return false;
00271     if (TCLAP::ValueArg<T>::_hasBlanks(args[*i])) return false;
00272 
00273     std::string flag = args[*i];
00274 
00275     std::string value = "";
00276     TCLAP::ValueArg<T>::trimFlag(flag, value);
00277 
00278     if (TCLAP::ValueArg<T>::argMatches(flag)) {
00279         if (!_allowOverwrite && TCLAP::ValueArg<T>::_alreadySet) {
00280             if (TCLAP::ValueArg<T>::_xorSet) {
00281                 throw TCLAP::CmdLineParseException("Mutually exclusive argument already set!",
00282                         TCLAP::ValueArg<T>::toString());
00283             } else {
00284                 throw TCLAP::CmdLineParseException("Argument already set!",
00285                         TCLAP::ValueArg<T>::toString());
00286             }
00287         }
00288 
00289         if (TCLAP::Arg::delimiter() != ' ' && value == "") {
00290             throw TCLAP::ArgParseException("Couldn't find delimiter for this argument!",
00291                     TCLAP::ValueArg<T>::toString());
00292         }
00293 
00294         if (value == "") {
00295             (*i)++;
00296             if (static_cast<unsigned int>(*i) < args.size()) {
00297                 TCLAP::ValueArg<T>::_extractValue(args[*i]);
00298             } else {
00299                 throw TCLAP::ArgParseException("Missing a value for this argument!",
00300                         TCLAP::ValueArg<T>::toString());
00301             }
00302         } else {
00303             TCLAP::ValueArg<T>::_extractValue(value);
00304         }
00305 
00306         TCLAP::ValueArg<T>::_alreadySet = true;
00307         TCLAP::ValueArg<T>::_checkWithVisitor();
00308         return true;
00309     } else {
00310         return false;
00311     }
00312 }
00313 
00314 
00315 } // namespace basis
00316 
00317 
00318 #endif // _BASIS_VALUEARG_H