source: trunk/yat/OptionArg.h @ 1336

Last change on this file since 1336 was 1336, checked in by Peter Johansson, 12 years ago

latest yat

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