#ifndef _theplu_yat_utility_option_arg_ #define _theplu_yat_utility_option_arg_ // $Id: OptionArg.h 2384 2010-12-22 14:03:36Z peter $ /* Copyright (C) 2007, 2008 Jari Häkkinen, Peter Johansson Copyright (C) 2009, 2010 Peter Johansson This file is part of the yat library, http://dev.thep.lu.se/yat The yat library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. The yat library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with yat. If not, see . */ #include "Option.h" #include "CommandLine.h" #include "Exception.h" #include "utility.h" #include #include #include namespace theplu { namespace yat { namespace utility { class CommandLine; /** \brief Option with argument If the option is present, argument is set during parsing. Supported formats are both gnu-style "--support-gnu=value", POSIX-like "--support-posix value", as well as shorter "-s value". The argument of an parameter is retrived by the value() function. The type \c T should be either a string or a type supported by function convert(). */ template class OptionArg : public Option { public: /** \brief Constructor \param cmd Commandline Option is associated with \param name string such as "help" for --help, "h" for -h or "h,help" for having both short and long option name \param desc string used in help display \param required If true option must be found in commandline or exception is thrown in validation */ OptionArg(CommandLine& cmd, std::string name, std::string desc, bool required=false) : Option(cmd, name, desc), required_(required) {} /** \param arg string to be used in help output such as `=TARGET' in `--target=TARGET'. See print3(). \since New in yat 0.5. */ void print_arg(std::string arg) { print_arg_ = arg; } /** \return value */ T value(void) const { if (!cmd().parsed()) { std::string s("OptionArg::value called before Commandline was parsed"); throw std::logic_error(s); } return value_; } /** \brief set value \since new in yat 0.5 */ void value(T v) { value_ = v; } protected: /** \return true if Option is required, i.e., if Option is not found during parsing an exception will be thrown. */ inline bool required(void) const { return required_; } private: std::string print_arg_; bool required_; T value_; void do_parse(std::vector::iterator& first, const std::vector::iterator& last) { if ( first->size()>2 && (*first)[0]=='-' && (*first)[1]!='-'){ std::stringstream ss; ss << "option requires an argument -- " << short_name() << "\n" << cmd().try_help(); throw cmd_error(ss.str()); } if (first+1==last ) { if (first->size()>2){ std::stringstream ss; ss << "option `--" << long_name() << "' requires an argument\n" << cmd().try_help(); throw cmd_error(ss.str()); } else { std::stringstream ss; ss << "option requires an argument -- " << short_name() << "\n" << cmd().try_help(); throw cmd_error(ss.str()); } } if ( *(first+1)->begin() == '"' && *((first+1)->end()-1) == '"') *(first+1) = (first+1)->substr(1, (first+1)->size()-2); assign(value_, *(++first)); } void assign(std::string& lhs, const std::string& rhs ) { lhs = rhs; } template void assign(T1& lhs, const std::string& rhs ) { try { lhs = convert(rhs); } catch (runtime_error& e) { std::stringstream sstr(rhs); sstr << "invalid argument"; sstr << "`" << rhs << "' for `"; if (!long_name().empty()) sstr << "--" << long_name(); else sstr << "-" << short_name(); sstr << "'"; throw cmd_error(sstr.str()); } } /** */ void do_validate(void) const { if (required_ && !present()) { std::stringstream ss; ss << "mandatory option `"; if (long_name().size()) ss << long_name(); else ss << short_name(); ss << "' not given\n"; ss << cmd().try_help(); throw cmd_error(ss.str()); } do_validate2(); } virtual void do_validate2(void) const {} virtual std::string print3(void) const { return print_arg_; } }; }}} // of namespace utility, yat, and theplu #endif