Mercurial > code
view C++/OptionParser.h @ 232:420b1710355f
Luae: disable optionals, it is not currently ready
author | David Demelier <markand@malikania.fr> |
---|---|
date | Sun, 22 Jun 2014 16:23:15 +0200 |
parents | 96ff112d05cf |
children | ff2db0ed78f1 |
line wrap: on
line source
/* * OptionParser.h -- safe getopt(3) replacement * * Copyright (c) 2013, 2014 David Demelier <markand@malikania.fr> * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef _OPTION_PARSER_H_ #define _OPTION_PARSER_H_ /** * @file OptionParser.h * @brief Command line option replacement for getopt(3) * * This alternative to getopt is thread safe, reentrant and stateless. It does * not use any global and is customizable. */ #include <string> #include <vector> #include <map> #include <unordered_set> /** * @class Option * @brief Option description * * This class describe an option with its optional flags. Name can be arbitrary * and must specify by hand - or --. */ class Option final { public: enum class Type { Switch, Argument }; /** * @brief Optional flags */ enum { Multiple = 0, //!< can appear multiple times Single //!< must appear exactly once }; private: std::string m_name; std::string m_help; int m_flags; Type m_type; public: /** * Build an option. * * @param name the name * @param help the help message * @param flags the flags */ Option(const std::string &name, const std::string &help, Type type = Type::Switch, int flags = 0); /** * Get the option name. * * @return the name */ const std::string &name() const; /** * Get the help. * * @return the help */ const std::string &help() const; /** * Get the option type. * * @return the type */ Type type() const; /** * Get the flags. * * @return the flags */ int flags() const; }; /** * @class OptionValue * @brief Describe the result of an option * * This class is instanciated when an option has been declared and successfully parsed. * * One should use the operator bool for boolean options and operator std::string (or value()) * for options with arguments. */ class OptionValue final { private: friend class OptionParser; std::string m_name; std::string m_value; bool m_enabled = false; private: /** * Construct an option value. This is constructor is used * with Option::Switch. * * @param name the option name */ OptionValue(const std::string &name); /** * Construct a value with a parameter. * * @param name the name * @param value the value */ OptionValue(const std::string &name, const std::string &value); public: /** * Get the option name. * * @return the name */ const std::string &name() const; /** * Get the value. * * @return the value */ const std::string &value() const; /** * Check if the option is enabled (only with Option::Switch) * * @return true if enabled */ operator bool() const; /** * Convert the value to string. * * @return the value */ operator std::string() const; }; /** * @class OptionResult * @brief Result of a command line parse */ class OptionResult final { private: friend class OptionParser; using Values = std::vector<OptionValue>; Values m_values; int m_total = 0; public: /** * Default constructor. */ OptionResult() = default; /** * Move constructor. * * @param other the other */ OptionResult(OptionResult &&other) = default; /** * Returns an iterator to the beginning of values. * * @return the iterator */ auto begin() -> decltype(m_values.begin()); /** * Returns a const iterator to the beginning of values. * * @return the iterator */ auto begin() const -> decltype(m_values.begin()); /** * Returns a const iterator to the beginning of values. * * @return the iterator */ auto cbegin() const -> decltype(m_values.cbegin()); /** * Returns an iterator to the end of values. * * @return the iterator */ auto end() -> decltype(m_values.end()); /** * Returns a const iterator to the end of values. * * @return the iterator */ auto end() const -> decltype(m_values.end()); /** * Returns a const iterator to the end of values. * * @return the iterator */ auto cend() const -> decltype(m_values.cend()); /** * Count the number of parsed options. * * @return the number */ int count() const; /** * Get the total number of tokens parsed from the argv vector. * * @return the total number */ int total() const; /** * Move assignment operator. * * @param other the other * @return the result */ OptionResult &operator=(OptionResult &&other) = default; }; /** * @class OptionParser * @brief Parse command line options */ class OptionParser { private: using Placed = std::unordered_set<std::string>; public: using Options = std::map<std::string, Option>; enum { BreakNonOption = (1 << 0), //!< break on first non option Strict = (1 << 1), //!< abort on first error Silent = (1 << 2) //!< do not / call any log handler }; private: Placed m_placed; //!< already placed options protected: Options m_options; //!< list of options descriptions int m_maxlength = 0; //!< max option length public: /** * Default destructor. */ virtual ~OptionParser() = default; /** * Move an option. * * @param option the option */ void add(Option &&option); /** * Add an option. * * @param option the option */ void add(const Option &option); /** * Parse options. * * @param argc the number of args * @param argv the arguments * @param flags the optional flags */ OptionResult parse(int argc, char **argv, int flags = 0); /** * Show the usage. Called on error only if silent and if is strict is set, because * it will continue parsing and may show usage multiple times. */ virtual void usage(); /** * On error log. * * @param option the option * @param error the error */ virtual void log(const std::string &option, const std::string &error); }; #endif // !_OPTION_PARSER_H_