From a15cf65c44d5c224169c32ef5495b68c758134b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Frings-F=C3=BCrst?= Date: Sun, 18 May 2014 16:08:14 +0200 Subject: Imported Upstream version 3.3.0.2 --- libcult/cult/cli/options-parser.hxx | 570 ++++++++++++++++++++++++++++++++++++ 1 file changed, 570 insertions(+) create mode 100644 libcult/cult/cli/options-parser.hxx (limited to 'libcult/cult/cli/options-parser.hxx') diff --git a/libcult/cult/cli/options-parser.hxx b/libcult/cult/cli/options-parser.hxx new file mode 100644 index 0000000..4068fa6 --- /dev/null +++ b/libcult/cult/cli/options-parser.hxx @@ -0,0 +1,570 @@ +// file : cult/cli/options-parser.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_CLI_OPTIONS_PARSER_HXX +#define CULT_CLI_OPTIONS_PARSER_HXX + +#include + +#include +#include + +#include + +#include +#include +#include + +#include + +//@! which types should be NonCopyable + +namespace Cult +{ + namespace CLI + { + struct UnknownMode + { + enum Value + { + skip, + stop, + fail + }; + }; + + template + struct OptionParserBase + { + T + parse (Char const* o, Scanner& s); + }; + + template + struct OptionParser: OptionParserBase + { + OptionParser (Spec const&) + { + } + }; + + template + class OptionParser > > + { + public: + OptionParser (OptionSpec > const&) + : impl_ (OptionSpec ()) + { + } + + T + parse (Char const* k, Scanner& s) + { + return impl_.parse (k, s); + } + + private: + OptionParser > impl_; + }; + + struct OptionParserBooleanBase + { + Boolean + parse (Char const*, Scanner& s); + }; + + template + struct OptionParser >: OptionParserBooleanBase + { + OptionParser (OptionSpec const&) + { + } + }; + + struct OptionParserStringBase + { + String + parse (Char const*, Scanner& s); + }; + + template + struct OptionParser >: OptionParserStringBase + { + OptionParser (OptionSpec const&) + { + } + }; + + // + // + // + + class OptionsParserBase + { + protected: + struct GlueBase + { + // I am using Void* here to (significantly) reduce the length + // on the object file symbols. + // + virtual Void + operator() (Char const*, Scanner&, Void* options) = 0; + }; + + static Trace::Stream tout; + }; + + template + class OptionsParser : OptionsParserBase + { + typedef + Containers::Map > + Map; + + template + struct Glue; + + template + struct Glue > : GlueBase + { + Glue (OptionSpec const& spec) + : parser_ (spec) + { + } + + virtual Void + operator() (Char const* o, Scanner& scan, Void* options) + { + typedef typename Spec::Options Options; + + Options& ops (*reinterpret_cast (options)); + + ops.template value () = parser_.parse (o, scan); + } + + private: + OptionParser > parser_; + }; + + //@@ It's bad that I also have to specialize Glue. Need to redesign + // this. + // + template + struct Glue > > : GlueBase + { + Glue (OptionSpec > const& spec) + : parser_ (spec) + { + } + + virtual Void + operator() (Char const* o, Scanner& scan, Void* options) + { + typedef typename Spec::Options Options; + + Options& ops (*reinterpret_cast (options)); + + ops.template value ().push_back (parser_.parse (o, scan)); + } + + private: + OptionParser > > parser_; + }; + + + // Option-specific specializations of some functions. + // + template + struct S_ + { + // This is a "specialization" for when type is Bits::Null. + // + static Void + add_parser (Spec const&, Map&) + { + } + + static Void + set_default (typename Spec::Options&, Spec const&) + { + } + }; + + template + struct S_ > + { + static Void + add_parser (Spec const& spec, Map& map) + { + if (k[0] != '\0') + { + OptionSpec const& os (spec.template option ()); + map[os.name ()] = new Glue > (os); + } + } + + static Void + set_default (typename Spec::Options& o, Spec const& s) + { + o.template value () = s.template option ().default_value (); + } + }; + + public: + + OptionsParser (Spec const& spec) + : spec_ (spec) + { + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + S_::add_parser (spec_, map_); + } + + + typename Spec::Options + parse (Scanner& scan, + UnknownMode::Value option_mode = UnknownMode::fail, + UnknownMode::Value argument_mode = UnknownMode::stop) + { + typename Spec::Options ops; + + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + S_::set_default (ops, spec_); + + for (Char const* s (scan.peek ()); s != Scanner::eos; s = scan.peek ()) + { + tout << "looking at \"" << s << "\""; + + //@@ Std:: + // + if (strcmp (s, "--") == 0) + { + // We don't want to remove '--' if our option mode is skip. + // + if (option_mode == UnknownMode::skip) + scan.skip (); + else + scan.next (); + + break; + } + + typename Map::ConstIterator it (map_.find (s)); + + if (it != map_.end ()) + { + tout << "found parser for \"" << s << "\""; + + s = scan.next (); + (*(it->second)) (s, scan, &ops); + } + else if (s[0] == '-') + { + // Unknown option. + // + switch (option_mode) + { + case UnknownMode::skip: + { + scan.skip (); + continue; + } + case UnknownMode::stop: + { + break; + } + case UnknownMode::fail: + { + throw UnexpectedOption (s); + } + } + + break; // stop case + } + else + { + // Something else. + // + switch (argument_mode) + { + case UnknownMode::skip: + { + scan.skip (); + continue; + } + case UnknownMode::stop: + { + break; + } + case UnknownMode::fail: + { + throw UnexpectedArgument (s); + } + } + + break; // stop case + } + } + + return ops; + } + + private: + Map map_; + Spec spec_; + }; + + // + // + // + + template + typename Spec::Options + parse (Spec const& s, + Arguments& args, + UnknownMode::Value option_mode = UnknownMode::fail, + UnknownMode::Value argument_mode = UnknownMode::stop) + { + Scanner scan (args, Scanner::Action::erase); + OptionsParser parser (s); + + return parser.parse (scan, option_mode, argument_mode); + } + + template + Options + parse (Arguments& args, + UnknownMode::Value option_mode = UnknownMode::fail, + UnknownMode::Value argument_mode = UnknownMode::stop) + { + OptionsSpec spec; + return parse (spec, args, option_mode, argument_mode); + } + + template + typename Spec::Options + parse (Spec const& s, + Int& argc, + Char** argv, + UnknownMode::Value option_mode = UnknownMode::fail, + UnknownMode::Value argument_mode = UnknownMode::stop) + { + BasicArguments args (argc, argv); + return parse (s, args, option_mode, argument_mode); + } + + template + Options + parse (Int& argc, + Char** argv, + UnknownMode::Value option_mode = UnknownMode::fail, + UnknownMode::Value argument_mode = UnknownMode::stop) + { + OptionsSpec spec; + + return parse (spec, argc, argv, option_mode, argument_mode); + } + } +} + +#include +#include + +#endif // CULT_CLI_OPTIONS_PARSER_HXX -- cgit v1.2.3