yat/utility/OptionArg.h

Code
Comments
Other
Rev Date Author Line
965 11 Oct 07 peter 1 #ifndef _theplu_yat_utility_option_arg_
965 11 Oct 07 peter 2 #define _theplu_yat_utility_option_arg_
965 11 Oct 07 peter 3
965 11 Oct 07 peter 4 // $Id$
965 11 Oct 07 peter 5
965 11 Oct 07 peter 6 /*
4359 23 Aug 23 peter 7   Copyright (C) 2007 Peter Johansson
4359 23 Aug 23 peter 8   Copyright (C) 2008 Jari Häkkinen, Peter Johansson
3114 10 Nov 13 peter 9   Copyright (C) 2009, 2010, 2013 Peter Johansson
965 11 Oct 07 peter 10
1437 25 Aug 08 peter 11   This file is part of the yat library, http://dev.thep.lu.se/yat
965 11 Oct 07 peter 12
965 11 Oct 07 peter 13   The yat library is free software; you can redistribute it and/or
965 11 Oct 07 peter 14   modify it under the terms of the GNU General Public License as
1486 09 Sep 08 jari 15   published by the Free Software Foundation; either version 3 of the
965 11 Oct 07 peter 16   License, or (at your option) any later version.
965 11 Oct 07 peter 17
965 11 Oct 07 peter 18   The yat library is distributed in the hope that it will be useful,
965 11 Oct 07 peter 19   but WITHOUT ANY WARRANTY; without even the implied warranty of
965 11 Oct 07 peter 20   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
965 11 Oct 07 peter 21   General Public License for more details.
965 11 Oct 07 peter 22
965 11 Oct 07 peter 23   You should have received a copy of the GNU General Public License
1487 10 Sep 08 jari 24   along with yat. If not, see <http://www.gnu.org/licenses/>.
965 11 Oct 07 peter 25 */
965 11 Oct 07 peter 26
965 11 Oct 07 peter 27 #include "Option.h"
980 22 Oct 07 peter 28 #include "CommandLine.h"
1178 27 Feb 08 peter 29 #include "Exception.h"
1630 17 Nov 08 peter 30 #include "utility.h"
965 11 Oct 07 peter 31
1741 22 Jan 09 peter 32 #include <stdexcept>
965 11 Oct 07 peter 33 #include <string>
975 17 Oct 07 peter 34 #include <sstream>
965 11 Oct 07 peter 35
965 11 Oct 07 peter 36 namespace theplu {
965 11 Oct 07 peter 37 namespace yat {
965 11 Oct 07 peter 38 namespace utility {
965 11 Oct 07 peter 39
965 11 Oct 07 peter 40   class CommandLine;
965 11 Oct 07 peter 41   /**
965 11 Oct 07 peter 42      \brief Option with argument
965 11 Oct 07 peter 43
965 11 Oct 07 peter 44      If the option is present, argument is set during
965 11 Oct 07 peter 45      parsing. Supported formats are both gnu-style
965 11 Oct 07 peter 46      "--support-gnu=value", POSIX-like "--support-posix value", as
965 11 Oct 07 peter 47      well as shorter "-s value". The argument of an parameter is
2046 02 Sep 09 peter 48      retrived by the value() function. The type \c T should be either
2046 02 Sep 09 peter 49      a string or a type supported by function convert().
965 11 Oct 07 peter 50    */
965 11 Oct 07 peter 51   template<typename T>
965 11 Oct 07 peter 52   class OptionArg : public Option
965 11 Oct 07 peter 53   {
965 11 Oct 07 peter 54   public:
965 11 Oct 07 peter 55     /**
2964 22 Jan 13 peter 56        \brief Constructor
2964 22 Jan 13 peter 57
2964 22 Jan 13 peter 58        \param cmd Commandline Option is associated with
1630 17 Nov 08 peter 59        \param name string such as "help" for --help, "h" for -h or
1630 17 Nov 08 peter 60        "h,help" for having both short and long option name
1630 17 Nov 08 peter 61        \param desc string used in help display
1630 17 Nov 08 peter 62        \param required If true option must be found in commandline or
1630 17 Nov 08 peter 63        exception is thrown in validation
965 11 Oct 07 peter 64     */
980 22 Oct 07 peter 65     OptionArg(CommandLine& cmd, std::string name,  std::string desc,
1632 19 Nov 08 peter 66               bool required=false)
1632 19 Nov 08 peter 67       : Option(cmd, name, desc), required_(required) {}
965 11 Oct 07 peter 68
965 11 Oct 07 peter 69     /**
2964 22 Jan 13 peter 70        \param arg string to be used in help output such as '=TARGET'
2964 22 Jan 13 peter 71        in '--target=TARGET'. See print3().
1632 19 Nov 08 peter 72
1632 19 Nov 08 peter 73        \since New in yat 0.5.
1632 19 Nov 08 peter 74      */
1632 19 Nov 08 peter 75     void print_arg(std::string arg) { print_arg_ = arg; }
1632 19 Nov 08 peter 76
1632 19 Nov 08 peter 77     /**
965 11 Oct 07 peter 78        \return value
965 11 Oct 07 peter 79     */
2964 22 Jan 13 peter 80     T value(void) const
2964 22 Jan 13 peter 81     {
1741 22 Jan 09 peter 82       if (!cmd().parsed()) {
1741 22 Jan 09 peter 83         std::string s("OptionArg::value called before Commandline was parsed");
1741 22 Jan 09 peter 84         throw std::logic_error(s);
1741 22 Jan 09 peter 85       }
2964 22 Jan 13 peter 86       return value_;
1741 22 Jan 09 peter 87     }
965 11 Oct 07 peter 88
1601 27 Oct 08 peter 89     /**
1601 27 Oct 08 peter 90        \brief set value
1601 27 Oct 08 peter 91
1601 27 Oct 08 peter 92        \since new in yat 0.5
1601 27 Oct 08 peter 93     */
1602 27 Oct 08 peter 94     void value(T v) { value_ = v; }
1601 27 Oct 08 peter 95
980 22 Oct 07 peter 96   protected:
1125 22 Feb 08 peter 97     /**
1125 22 Feb 08 peter 98        \return true if Option is required, i.e., if Option is not
1125 22 Feb 08 peter 99        found during parsing an exception will be thrown.
1125 22 Feb 08 peter 100      */
980 22 Oct 07 peter 101     inline bool required(void) const { return required_; }
980 22 Oct 07 peter 102
965 11 Oct 07 peter 103   private:
1629 17 Nov 08 peter 104     std::string print_arg_;
980 22 Oct 07 peter 105     bool required_;
965 11 Oct 07 peter 106     T value_;
965 11 Oct 07 peter 107
2964 22 Jan 13 peter 108     void do_parse(std::vector<std::string>::iterator& first,
2964 22 Jan 13 peter 109                   const std::vector<std::string>::iterator& last)
965 11 Oct 07 peter 110     {
965 11 Oct 07 peter 111       if ( first->size()>2 && (*first)[0]=='-' && (*first)[1]!='-'){
980 22 Oct 07 peter 112         std::stringstream ss;
980 22 Oct 07 peter 113         ss << "option requires an argument -- " << short_name() << "\n"
980 22 Oct 07 peter 114            << cmd().try_help();
1178 27 Feb 08 peter 115         throw cmd_error(ss.str());
965 11 Oct 07 peter 116       }
965 11 Oct 07 peter 117       if (first+1==last ) {
965 11 Oct 07 peter 118         if (first->size()>2){
965 11 Oct 07 peter 119           std::stringstream ss;
2964 22 Jan 13 peter 120           ss << "option '--" << long_name() << "' requires an argument\n"
980 22 Oct 07 peter 121              << cmd().try_help();
1178 27 Feb 08 peter 122           throw cmd_error(ss.str());
965 11 Oct 07 peter 123         }
965 11 Oct 07 peter 124         else {
980 22 Oct 07 peter 125           std::stringstream ss;
980 22 Oct 07 peter 126           ss << "option requires an argument -- " << short_name() << "\n"
980 22 Oct 07 peter 127              << cmd().try_help();
1178 27 Feb 08 peter 128           throw cmd_error(ss.str());
965 11 Oct 07 peter 129         }
2964 22 Jan 13 peter 130       }
2964 22 Jan 13 peter 131
965 11 Oct 07 peter 132       if ( *(first+1)->begin() == '"' && *((first+1)->end()-1) == '"')
2964 22 Jan 13 peter 133         *(first+1) = (first+1)->substr(1, (first+1)->size()-2);
965 11 Oct 07 peter 134       assign(value_, *(++first));
965 11 Oct 07 peter 135     }
965 11 Oct 07 peter 136
2173 27 Jan 10 peter 137     void assign(std::string& lhs, const std::string& rhs )
2964 22 Jan 13 peter 138     {
965 11 Oct 07 peter 139       lhs = rhs;
965 11 Oct 07 peter 140     }
2964 22 Jan 13 peter 141
965 11 Oct 07 peter 142     template<class T1>
2173 27 Jan 10 peter 143     void assign(T1& lhs, const std::string& rhs )
2964 22 Jan 13 peter 144     {
1630 17 Nov 08 peter 145       try {
1630 17 Nov 08 peter 146         lhs = convert<T1>(rhs);
1630 17 Nov 08 peter 147       }
2210 05 Mar 10 peter 148       catch (runtime_error& e) {
965 11 Oct 07 peter 149         std::stringstream sstr(rhs);
2352 27 Nov 10 peter 150         sstr << "invalid argument";
2964 22 Jan 13 peter 151         sstr << "'" << rhs << "' for '";
2352 27 Nov 10 peter 152         if (!long_name().empty())
2352 27 Nov 10 peter 153           sstr << "--" << long_name();
2352 27 Nov 10 peter 154         else
2352 27 Nov 10 peter 155           sstr << "-" << short_name();
2352 27 Nov 10 peter 156         sstr << "'";
1178 27 Feb 08 peter 157         throw cmd_error(sstr.str());
965 11 Oct 07 peter 158       }
965 11 Oct 07 peter 159     }
965 11 Oct 07 peter 160
965 11 Oct 07 peter 161     /**
965 11 Oct 07 peter 162      */
2964 22 Jan 13 peter 163     void do_validate(void) const
980 22 Oct 07 peter 164     {
980 22 Oct 07 peter 165       if (required_ && !present()) {
980 22 Oct 07 peter 166         std::stringstream ss;
2964 22 Jan 13 peter 167         ss << "mandatory option '";
980 22 Oct 07 peter 168         if (long_name().size())
980 22 Oct 07 peter 169           ss << long_name();
980 22 Oct 07 peter 170         else
980 22 Oct 07 peter 171           ss << short_name();
980 22 Oct 07 peter 172         ss << "' not given\n";
980 22 Oct 07 peter 173         ss << cmd().try_help();
1178 27 Feb 08 peter 174         throw cmd_error(ss.str());
980 22 Oct 07 peter 175       }
980 22 Oct 07 peter 176       do_validate2();
980 22 Oct 07 peter 177     }
965 11 Oct 07 peter 178
980 22 Oct 07 peter 179
980 22 Oct 07 peter 180     virtual void do_validate2(void) const {}
1629 17 Nov 08 peter 181
2964 22 Jan 13 peter 182     virtual std::string print3(void) const
2964 22 Jan 13 peter 183     {
2964 22 Jan 13 peter 184       return print_arg_;
1629 17 Nov 08 peter 185     }
1629 17 Nov 08 peter 186
965 11 Oct 07 peter 187   };
965 11 Oct 07 peter 188
965 11 Oct 07 peter 189 }}} // of namespace utility, yat, and theplu
965 11 Oct 07 peter 190
965 11 Oct 07 peter 191 #endif