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