changeset 498:fbd80bfcf58d

Irccd: import new options, closes #713
author David Demelier <markand@malikania.fr>
date Sat, 30 Sep 2017 10:31:08 +0200
parents d7882b30b01a
children 1c96d1fee4b4
files irccd/main.cpp irccdctl/cli.cpp irccdctl/main.cpp libcommon/irccd/options.cpp libcommon/irccd/options.hpp
diffstat 5 files changed, 154 insertions(+), 141 deletions(-) [+]
line wrap: on
line diff
--- a/irccd/main.cpp	Fri Sep 29 17:04:03 2017 +0200
+++ b/irccd/main.cpp	Sat Sep 30 10:31:08 2017 +0200
@@ -74,7 +74,7 @@
     std::exit(1);
 }
 
-void version(const option::Result& options)
+void version(const option::result& options)
 {
     std::cout << IRCCD_VERSION << std::endl;
 
@@ -126,13 +126,13 @@
     ++ argv;
 }
 
-option::Result parse(int& argc, char**& argv)
+option::result parse(int& argc, char**& argv)
 {
     // Parse command line options.
-    option::Result result;
+    option::result result;
 
     try {
-        option::Options options{
+        option::options options{
             { "-c",             true    },
             { "--config",       true    },
             { "-f",             false   },
@@ -164,7 +164,7 @@
     return result;
 }
 
-config open(const option::Result& result)
+config open(const option::result& result)
 {
     auto it = result.find("-c");
 
@@ -230,7 +230,7 @@
     }
 }
 
-void load_foreground(bool foreground, const option::Result& options)
+void load_foreground(bool foreground, const option::result& options)
 {
     try {
 #if defined(HAVE_DAEMON)
@@ -245,7 +245,7 @@
     }
 }
 
-void load(const config& config, const option::Result& options)
+void load(const config& config, const option::result& options)
 {
     /*
      * Order matters, please be careful when changing this.
@@ -289,7 +289,7 @@
 {
     init(argc, argv);
 
-    option::Result options = parse(argc, argv);
+    option::result options = parse(argc, argv);
 
     instance = std::make_unique<irccd::irccd>();
     instance->commands().add(std::make_unique<plugin_config_command>());
--- a/irccdctl/cli.cpp	Fri Sep 29 17:04:03 2017 +0200
+++ b/irccdctl/cli.cpp	Sat Sep 30 10:31:08 2017 +0200
@@ -352,9 +352,9 @@
 
 namespace {
 
-option::Result parse(std::vector<std::string> &args)
+option::result parse(std::vector<std::string> &args)
 {
-    option::Options options{
+    option::options options{
         { "-c",             true    },
         { "--command",      true    },
         { "-n",             true    },
@@ -396,8 +396,8 @@
 {
     std::vector<std::string> copy(args);
 
-    option::Result result = parse(copy);
-    option::Result::const_iterator it;
+    option::result result = parse(copy);
+    option::result::const_iterator it;
 
     if (copy.size() < 2)
         throw std::invalid_argument("server-connect requires at least 2 arguments");
@@ -869,7 +869,7 @@
 
 void RuleAddCli::exec(Irccdctl &irccdctl, const std::vector<std::string> &args)
 {
-    static const option::Options options{
+    static const option::options options{
         { "-c",             true },
         { "--add-channel",  true },
         { "-e",             true },
@@ -952,7 +952,7 @@
 
 void RuleEditCli::exec(Irccdctl &irccdctl, const std::vector<std::string> &args)
 {
-    static const option::Options options{
+    static const option::options options{
         { "-a",                 true },
         { "--action",           true },
         { "-c",                 true },
--- a/irccdctl/main.cpp	Fri Sep 29 17:04:03 2017 +0200
+++ b/irccdctl/main.cpp	Sat Sep 30 10:31:08 2017 +0200
@@ -298,9 +298,9 @@
  * -h host or ip
  * -p port
  */
-void parseConnectIp(const option::Result &options)
+void parseConnectIp(const option::result &options)
 {
-    option::Result::const_iterator it;
+    option::result::const_iterator it;
 
     // Host (-h or --host).
     std::string host;
@@ -341,10 +341,10 @@
  *
  * -P file
  */
-void parseConnectLocal(const option::Result &options)
+void parseConnectLocal(const option::result &options)
 {
 #if !defined(IRCCD_SYSTEM_WINDOWS)
-    option::Result::const_iterator it;
+    option::result::const_iterator it;
 
     if ((it = options.find("-P")) == options.end() && (it = options.find("--path")) == options.end())
         throw std::invalid_argument("missing path parameter (-P or --path)");
@@ -364,7 +364,7 @@
  *
  * Generic parsing of command line option for connection.
  */
-void parseConnect(const option::Result &options)
+void parseConnect(const option::result &options)
 {
     assert(options.count("-t") > 0 || options.count("--type") > 0);
 
@@ -380,10 +380,10 @@
     throw std::invalid_argument("invalid type given: " + it->second);
 }
 
-option::Result parse(int &argc, char **&argv)
+option::result parse(int &argc, char **&argv)
 {
     // 1. Parse command line options.
-    option::Options def{
+    option::options def{
         { "-c",         true    },
         { "--config",   true    },
         { "-h",         true    },
@@ -399,7 +399,7 @@
         { "--verbose",  false   }
     };
 
-    option::Result result;
+    option::result result;
 
     try {
         result = option::read(argc, argv, def);
--- a/libcommon/irccd/options.cpp	Fri Sep 29 17:04:03 2017 +0200
+++ b/libcommon/irccd/options.cpp	Sat Sep 30 10:31:08 2017 +0200
@@ -1,7 +1,7 @@
 /*
  * options.cpp -- parse Unix command line options
  *
- * Copyright (c) 2015 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2015-2017 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
@@ -26,41 +26,40 @@
 
 namespace {
 
-using Iterator = std::vector<std::string>::iterator;
-using Args = std::vector<std::string>;
+using iterator = std::vector<std::string>::iterator;
+using args = std::vector<std::string>;
 
-inline bool isOption(const std::string &arg) noexcept
+inline bool is_option(const std::string& arg) noexcept
 {
     return arg.size() >= 2 && arg[0] == '-';
 }
 
-inline bool isLongOption(const std::string &arg) noexcept
+inline bool is_long_option(const std::string& arg) noexcept
 {
-    assert(isOption(arg));
+    assert(is_option(arg));
 
     return arg.size() >= 3 && arg[1] == '-';
 }
 
-inline bool isShortSimple(const std::string &arg) noexcept
+inline bool is_short_simple(const std::string& arg) noexcept
 {
-    assert(isOption(arg));
-    assert(!isLongOption(arg));
+    assert(is_option(arg) && !is_long_option(arg));
 
     return arg.size() == 2;
 }
 
-void parseLongOption(Result &result, Args &args, Iterator &it, Iterator &end, const Options &definition)
+void parse_long_option(result& result, args& args, iterator& it, iterator& end, const options& definition)
 {
     auto arg = *it++;
     auto opt = definition.find(arg);
 
     if (opt == definition.end())
-        throw InvalidOption{arg};
+        throw invalid_option(arg);
 
     // Need argument?
     if (opt->second) {
-        if (it == end || isOption(*it))
-            throw MissingValue{arg};
+        if (it == end || is_option(*it))
+            throw missing_value(arg);
 
         result.insert(std::make_pair(arg, *it++));
         it = args.erase(args.begin(), it);
@@ -72,97 +71,106 @@
     }
 }
 
-void parseShortOption(Result &result, Args &args, Iterator &it, Iterator &end, const Options &definition)
+void parse_short_option_simple(result& result, args& args, iterator& it, iterator &end, const options& definition)
 {
-    if (isShortSimple(*it)) {
-        /*
-         * Here two cases:
-         *
-         * -v (no option)
-         * -c value
-         */
-        auto arg = *it++;
-        auto opt = definition.find(arg);
+    /*
+     * Here two cases:
+     *
+     * -v (no option)
+     * -c value
+     */
+    auto arg = *it++;
+    auto opt = definition.find(arg);
 
-        if (opt == definition.end())
-            throw InvalidOption{arg};
-
-        // Need argument?
-        if (opt->second) {
-            if (it == end || isOption(*it))
-                throw MissingValue{arg};
+    if (opt == definition.end())
+        throw invalid_option(arg);
 
-            result.insert(std::make_pair(arg, *it++));
-            it = args.erase(args.begin(), it);
-            end = args.end();
-        } else {
-            result.insert(std::make_pair(arg, ""));
-            it = args.erase(args.begin());
-            end = args.end();
-        }
+    // Need argument?
+    if (opt->second) {
+        if (it == end || is_option(*it))
+            throw missing_value(arg);
+
+        result.insert(std::make_pair(arg, *it++));
+        it = args.erase(args.begin(), it);
+        end = args.end();
     } else {
-        /*
-         * Here multiple scenarios:
-         *
-         * 1. -abc (-a -b -c if all are simple boolean arguments)
-         * 2. -vc foo.conf (-v -c foo.conf if -c is argument dependant)
-         * 3. -vcfoo.conf (-v -c foo.conf also)
-         */
-        auto value = it->substr(1);
-        auto len = value.length();
-        int toremove = 1;
-
-        for (decltype(len) i = 0; i < len; ++i) {
-            auto arg = std::string{'-'} + value[i];
-            auto opt = definition.find(arg);
-
-            if (opt == definition.end())
-                throw InvalidOption{arg};
-
-            if (opt->second) {
-                if (i == (len - 1)) {
-                    // End of string, get the next argument (see 2.).
-                    if (++it == end || isOption(*it))
-                        throw MissingValue{arg};
-
-                    result.insert(std::make_pair(arg, *it));
-                    toremove += 1;
-                } else {
-                    result.insert(std::make_pair(arg, value.substr(i + 1)));
-                    i = len;
-                }
-            } else
-                result.insert(std::make_pair(arg, ""));
-        }
-
-        it = args.erase(args.begin(), args.begin() + toremove);
+        result.insert(std::make_pair(arg, ""));
+        it = args.erase(args.begin());
         end = args.end();
     }
 }
 
+void parse_short_option_compressed(result& result, args& args, iterator& it, iterator &end, const options& definition)
+{
+    /*
+     * Here multiple scenarios:
+     *
+     * 1. -abc (-a -b -c if all are simple boolean arguments)
+     * 2. -vc foo.conf (-v -c foo.conf if -c is argument dependant)
+     * 3. -vcfoo.conf (-v -c foo.conf also)
+     */
+    auto value = it->substr(1);
+    auto len = value.length();
+    int toremove = 1;
+
+    for (std::size_t i = 0; i < len; ++i) {
+        auto arg = std::string{'-'} + value[i];
+        auto opt = definition.find(arg);
+
+        if (opt == definition.end())
+            throw invalid_option(arg);
+
+        if (opt->second) {
+            if (i == (len - 1)) {
+                // End of string, get the next argument (see 2.).
+                if (++it == end || is_option(*it))
+                    throw missing_value(arg);
+
+                result.insert(std::make_pair(arg, *it));
+                toremove += 1;
+            } else {
+                result.insert(std::make_pair(arg, value.substr(i + 1)));
+                i = len;
+            }
+        } else
+            result.insert(std::make_pair(arg, ""));
+    }
+
+    it = args.erase(args.begin(), args.begin() + toremove);
+    end = args.end();
+}
+
+void parse_short_option(result& result, args& args, iterator& it, iterator &end, const options& definition)
+{
+    if (is_short_simple(*it))
+        parse_short_option_simple(result, args, it, end, definition);
+    else
+        parse_short_option_compressed(result, args, it, end, definition);
+}
+
 } // !namespace
 
-Result read(std::vector<std::string> &args, const Options &definition)
+result read(std::vector<std::string>& args, const options& definition)
 {
-    Result result;
+    result result;
 
     auto it = args.begin();
     auto end = args.end();
 
     while (it != end) {
-        if (!isOption(*it))
+        if (!is_option(*it))
             break;
 
-        if (isLongOption(*it))
-            parseLongOption(result, args, it, end, definition);
+        if (is_long_option(*it))
+            parse_long_option(result, args, it, end, definition);
         else
-            parseShortOption(result, args, it, end, definition);
+            parse_short_option(result, args, it, end, definition);
     }
 
     return result;
 }
 
-Result read(int &argc, char **&argv, const Options &definition)
+result read(int& argc, char**& argv, const options& definition)
 {
     std::vector<std::string> args;
 
--- a/libcommon/irccd/options.hpp	Fri Sep 29 17:04:03 2017 +0200
+++ b/libcommon/irccd/options.hpp	Sat Sep 30 10:31:08 2017 +0200
@@ -1,7 +1,7 @@
 /*
- * options.h -- parse Unix command line options
+ * options.hpp -- parse Unix command line options
  *
- * Copyright (c) 2015 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2015-2017 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
@@ -30,8 +30,6 @@
 #include <utility>
 #include <vector>
 
-#include "sysconfig.hpp"
-
 namespace irccd {
 
 /**
@@ -42,25 +40,31 @@
 /**
  * \brief This exception is thrown when an invalid option has been found.
  */
-class InvalidOption : public std::exception {
+class invalid_option : public std::exception {
 private:
-    std::string message;
+    std::string message_;
+    std::string name_;
 
 public:
     /**
-     * The invalid option given.
-     */
-    std::string argument;
-
-    /**
      * Construct the exception.
      *
      * \param arg the argument missing
      */
-    inline InvalidOption(std::string arg)
-        : argument(std::move(arg))
+    inline invalid_option(std::string name)
+        : name_(std::move(name))
     {
-        message = std::string("invalid option: ") + argument;
+        message_ = std::string("invalid option: ") + name_;
+    }
+
+    /**
+     * Get the option name.
+     *
+     * \return the name
+     */
+    inline const std::string& name() const noexcept
+    {
+        return name_;
     }
 
     /**
@@ -68,40 +72,41 @@
      *
      * \return the error message
      */
-    const char *what() const noexcept override
+    const char* what() const noexcept override
     {
-        return message.c_str();
+        return message_.c_str();
     }
 };
 
 /**
- * \brief This exception is thrown when an option requires a value and no value has been given.
+ * \brief This exception is thrown when an option requires a value and no value
+ * has been given.
  */
-class MissingValue : public std::exception {
+class missing_value : public std::exception {
 private:
-    std::string m_message;
-    std::string m_option;
+    std::string message_;
+    std::string name_;
 
 public:
     /**
      * Construct the exception.
      *
-     * \param option the option that requires a value
+     * \param name the option that requires a value
      */
-    inline MissingValue(std::string option)
-        : m_option(std::move(option))
+    inline missing_value(std::string name)
+        : name_(std::move(name))
     {
-        m_message = std::string("missing argument for: ") + m_option;
+        message_ = std::string("missing argument for: ") + name_;
     }
 
     /**
-     * Get the options that requires a value.
+     * Get the option name.
      *
-     * \return the option name
+     * \return the name
      */
-    inline const std::string &option() const noexcept
+    inline const std::string& name() const noexcept
     {
-        return m_option;
+        return name_;
     }
 
     /**
@@ -109,21 +114,21 @@
      *
      * \return the error message
      */
-    const char *what() const noexcept override
+    const char* what() const noexcept override
     {
-        return m_message.c_str();
+        return message_.c_str();
     }
 };
 
 /**
  * Packed multimap of options.
  */
-using Result = std::multimap<std::string, std::string>;
+using result = std::multimap<std::string, std::string>;
 
 /**
  * Define the allowed options.
  */
-using Options = std::map<std::string, bool>;
+using options = std::map<std::string, bool>;
 
 /**
  * Extract the command line options and return a result.
@@ -131,10 +136,10 @@
  * \param args the arguments
  * \param definition
  * \warning the arguments vector is modified in place to remove parsed options
- * \throw MissingValue
- * \throw InvalidOption
+ * \throw missing_value
+ * \throw invalid_option
  */
-IRCCD_EXPORT Result read(std::vector<std::string> &args, const Options &definition);
+result read(std::vector<std::string>& args, const options& definition);
 
 /**
  * Overloaded function for usage with main() arguments.
@@ -144,13 +149,13 @@
  * \param definition
  * \note don't forget to remove the first argv[0] argument
  * \warning the argc and argv are modified in place to remove parsed options
- * \throw MissingValue
- * \throw InvalidOption
+ * \throw missing_value
+ * \throw invalid_option
  */
-IRCCD_EXPORT Result read(int &argc, char **&argv, const Options &definition);
+result read(int& argc, char**& argv, const options& definition);
 
 } // !option
 
 } // !irccd
 
-#endif // !IRCCD_OPTIONS_HPP
+#endif // !OPTIONS_HPP