#include #include #include #include #include #include namespace cxxopts { using boost::any; class Value { public: virtual void parse(const std::string& text) const = 0; virtual bool has_arg() const = 0; }; namespace values { template void parse_value(const std::string& text, T& value) { std::istringstream is(text); is >> value; } template bool value_has_arg(bool*) { return false; } template bool value_has_arg(T*) { return true; } template class default_value : public Value { public: default_value() : m_result(std::make_shared()) , m_store(m_result.get()) { } default_value(T* t) : m_store(t) { } void parse(const std::string& text) const { parse_value(text, *m_store); } bool has_arg() const { return value_has_arg(m_store); } const T& get() const { if (m_store == nullptr) { return *m_result; } else { return *m_store; } } private: std::shared_ptr m_result; T* m_store; }; } template std::shared_ptr value() { return std::make_shared>(); } extern std::basic_regex option_matcher; extern std::basic_regex option_specifier; class MessageException ; class OptionException : public std::exception { public: OptionException(const std::string& message) : m_message(message) { } virtual const char* what() const noexcept { return m_message.c_str(); } private: std::string m_message; }; class OptionSpecException : public OptionException { public: OptionSpecException(const std::string& message) : OptionException(message) { } }; class OptionParseException : public OptionException { public: OptionParseException(const std::string& message) : OptionException(message) { } }; class option_exists_error : public OptionSpecException { public: option_exists_error(const std::string& option) : OptionSpecException(u8"Option ‘" + option + u8"’ already exists") { } }; class invalid_option_format_error : public OptionSpecException { public: invalid_option_format_error(const std::string& format) : OptionSpecException(u8"Invalid option format ‘" + format + u8"’") { } }; class option_not_exists_exception : public OptionParseException { public: option_not_exists_exception(const std::string& option) : OptionParseException(u8"Option ‘" + option + u8"’ does not exist") { } }; class missing_argument_exception : public OptionParseException { public: missing_argument_exception(const std::string& option) : OptionParseException(u8"Option ‘" + option + u8"’ is missing an argument") { } }; class option_requires_argument_exception : public OptionParseException { public: option_requires_argument_exception(const std::string& option) : OptionParseException(u8"Option ‘" + option + u8"’ requires an argument") { } }; class option_not_has_argument_exception : public OptionParseException { public: option_not_has_argument_exception ( const std::string& option, const std::string& arg ) : OptionParseException( u8"Option ‘" + option + u8"’ does not take an argument, but argument‘" + arg + "’ given") { } }; class option_not_present_exception : public OptionParseException { public: option_not_present_exception(const std::string& option) : OptionParseException(u8"Option ‘" + option + u8"’ not present") { } }; class OptionAdder; class OptionDetails { public: OptionDetails ( const std::string& description, std::shared_ptr value ) : m_desc(description) , m_value(value) , m_count(0) { } const std::string& description() const { return m_desc; } bool has_arg() const { return m_value->has_arg(); } void parse(const std::string& text) { m_value->parse(text); ++m_count; } int count() const { return m_count; } template const T& as() const { return dynamic_cast&>(*m_value).get(); } private: std::string m_desc; std::shared_ptr m_value; int m_count; }; class Options { public: void parse(int& argc, char**& argv); OptionAdder add_options(); int count(const std::string& o) const { auto iter = m_options.find(o); if (iter == m_options.end()) { return 0; } return iter->second->count(); } const OptionDetails& operator[](const std::string& option) const { auto iter = m_options.find(option); if (iter == m_options.end()) { throw option_not_present_exception(option); } return *iter->second; } private: friend class OptionAdder; void parse_option ( std::shared_ptr value, const std::string& name, const std::string& arg = "" ); void checked_parse_arg ( int argc, char* argv[], int argPos, std::shared_ptr value, const std::string& name ); std::map> m_options; }; class OptionAdder { public: OptionAdder(Options& options) : m_options(options) { } OptionAdder& operator() ( const std::string& opts, const std::string& desc, std::shared_ptr value = ::cxxopts::value() ); private: Options& m_options; }; }