source: trunk/yat/utility/OptionArg.h @ 1741

Last change on this file since 1741 was 1741, checked in by Peter, 13 years ago

fixes #481

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 4.4 KB
Line 
1#ifndef _theplu_yat_utility_option_arg_
2#define _theplu_yat_utility_option_arg_
3
4// $Id: OptionArg.h 1741 2009-01-22 22:36:42Z peter $
5
6/*
7  Copyright (C) 2007 Jari Häkkinen, Peter Johansson
8  Copyright (C) 2008, 2009 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
48   */
49  template<typename T>
50  class OptionArg : public Option
51  {
52  public:
53    /**
54       \brief Constructor
55       
56       \param cmd Commandline Option is associated with
57       \param name string such as "help" for --help, "h" for -h or
58       "h,help" for having both short and long option name
59       \param desc string used in help display
60       \param required If true option must be found in commandline or
61       exception is thrown in validation
62    */
63    OptionArg(CommandLine& cmd, std::string name, std::string desc,
64              bool required=false)
65      : Option(cmd, name, desc), required_(required) {}
66
67    /**
68       \param arg string to be used in help output such as `=TARGET'
69       in `--target=TARGET'. See print3().
70
71       \since New in yat 0.5.
72     */
73    void print_arg(std::string arg) { print_arg_ = arg; }
74
75    /**
76       \return value
77    */
78    T value(void) const 
79    { 
80      if (!cmd().parsed()) {
81        std::string s("OptionArg::value called before Commandline was parsed");
82        throw std::logic_error(s);
83      }
84      return value_; 
85    }
86
87    /**
88       \brief set value
89
90       \since new in yat 0.5
91    */
92    void value(T v) { value_ = v; }
93
94  protected:
95    /**
96       \return true if Option is required, i.e., if Option is not
97       found during parsing an exception will be thrown.
98     */
99    inline bool required(void) const { return required_; }
100
101  private:
102    std::string print_arg_;
103    bool required_;
104    T value_;
105
106    void do_parse(std::vector<std::string>::iterator& first, 
107                  const std::vector<std::string>::iterator& last) 
108    {
109      if ( first->size()>2 && (*first)[0]=='-' && (*first)[1]!='-'){
110        std::stringstream ss;
111        ss << "option requires an argument -- " << short_name() << "\n"
112           << cmd().try_help();
113        throw cmd_error(ss.str());
114      }
115      if (first+1==last ) {
116        if (first->size()>2){
117          std::stringstream ss;
118          ss << "option `--" << long_name() << "' requires an argument\n"
119             << cmd().try_help();
120          throw cmd_error(ss.str());
121        }
122        else {
123          std::stringstream ss;
124          ss << "option requires an argument -- " << short_name() << "\n"
125             << cmd().try_help();
126          throw cmd_error(ss.str());
127        }
128      }       
129       
130      if ( *(first+1)->begin() == '"' && *((first+1)->end()-1) == '"')
131        *(first+1) = (first+1)->substr(1, (first+1)->size()-2); 
132      assign(value_, *(++first));
133    }
134
135    void assign(std::string& lhs, std::string rhs )
136    { 
137      lhs = rhs;
138    }
139   
140    template<class T1>
141    void assign(T1& lhs, std::string rhs )
142    { 
143      try {
144        lhs = convert<T1>(rhs);
145      }
146      catch (std::runtime_error& e) {
147        std::stringstream sstr(rhs);
148        sstr << ": invalid argument";
149        throw cmd_error(sstr.str());
150      }
151    }
152
153    /**
154     */
155    void do_validate(void) const 
156    {
157      if (required_ && !present()) {
158        std::stringstream ss;
159        ss << "mandatory option `";
160        if (long_name().size())
161          ss << long_name();
162        else
163          ss << short_name();
164        ss << "' not given\n";
165        ss << cmd().try_help();
166        throw cmd_error(ss.str());
167      }
168      do_validate2();
169    }
170
171
172    virtual void do_validate2(void) const {}
173
174    virtual std::string print3(void) const 
175    { 
176      return print_arg_; 
177    }
178
179  };
180
181}}} // of namespace utility, yat, and theplu
182
183#endif
Note: See TracBrowser for help on using the repository browser.