changeset 598:ce684e9e2151

Options: use Boost.ProgramOptions instead
author David Demelier <markand@malikania.fr>
date Fri, 02 Dec 2016 22:20:10 +0100
parents 2a0b3a7363f2
children 9016afda8527
files CMakeLists.txt modules/options/CMakeLists.txt modules/options/options.cpp modules/options/options.hpp modules/options/test/main.cpp
diffstat 5 files changed, 0 insertions(+), 678 deletions(-) [+]
line wrap: on
line diff
--- a/CMakeLists.txt	Fri Dec 02 22:19:22 2016 +0100
+++ b/CMakeLists.txt	Fri Dec 02 22:20:10 2016 +0100
@@ -52,7 +52,6 @@
 add_subdirectory(modules/elapsed-timer)
 add_subdirectory(modules/js)
 add_subdirectory(modules/net)
-add_subdirectory(modules/options)
 add_subdirectory(modules/signals)
 add_subdirectory(modules/timer)
 add_subdirectory(modules/unicode)
--- a/modules/options/CMakeLists.txt	Fri Dec 02 22:19:22 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +0,0 @@
-#
-# CMakeLists.txt -- options module
-#
-# Copyright (c) 2013-2015 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.
-#
-
-project(options)
-
-code_define_module(
-    NAME options
-    SOURCES
-        ${options_SOURCE_DIR}/options.cpp
-        ${options_SOURCE_DIR}/options.hpp
-)
--- a/modules/options/options.cpp	Fri Dec 02 22:19:22 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,179 +0,0 @@
-/*
- * options.cpp -- parse Unix command line options
- *
- * Copyright (c) 2015 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.
- */
-
-#include <cassert>
-
-#include "options.hpp"
-
-namespace option {
-
-namespace {
-
-using Iterator = std::vector<std::string>::iterator;
-using Args = std::vector<std::string>;
-
-inline bool isOption(const std::string &arg) noexcept
-{
-    return arg.size() >= 2 && arg[0] == '-';
-}
-
-inline bool isLongOption(const std::string &arg) noexcept
-{
-    assert(isOption(arg));
-
-    return arg.size() >= 3 && arg[1] == '-';
-}
-
-inline bool isShortSimple(const std::string &arg) noexcept
-{
-    assert(isOption(arg));
-    assert(!isLongOption(arg));
-
-    return arg.size() == 2;
-}
-
-void parseLongOption(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};
-
-    // Need argument?
-    if (opt->second) {
-        if (it == end || isOption(*it))
-            throw MissingValue{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();
-    }
-}
-
-void parseShortOption(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);
-
-        if (opt == definition.end())
-            throw InvalidOption{arg};
-
-        // Need argument?
-        if (opt->second) {
-            if (it == end || isOption(*it))
-                throw MissingValue{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();
-        }
-    } 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);
-        end = args.end();
-    }
-}
-
-} // !namespace
-
-Result read(std::vector<std::string> &args, const Options &definition)
-{
-    Result result;
-
-    auto it = args.begin();
-    auto end = args.end();
-
-    while (it != end) {
-        if (!isOption(*it))
-            break;
-
-        if (isLongOption(*it))
-            parseLongOption(result, args, it, end, definition);
-        else
-            parseShortOption(result, args, it, end, definition);
-    }
-
-    return result;
-}
-
-Result read(int &argc, char **&argv, const Options &definition)
-{
-    std::vector<std::string> args;
-
-    for (int i = 0; i < argc; ++i)
-        args.push_back(argv[i]);
-
-    auto before = args.size();
-    auto result = read(args, definition);
-
-    argc -= before - args.size();
-    argv += before - args.size();
-
-    return result;
-}
-
-} // !option
--- a/modules/options/options.hpp	Fri Dec 02 22:19:22 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,185 +0,0 @@
-/*
- * options.hpp -- parse Unix command line options
- *
- * Copyright (c) 2015 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 OPTIONS_HPP
-#define OPTIONS_HPP
-
-/**
- * \file options.hpp
- * \brief Basic Unix options parser.
- */
-
-/**
- * \page options Options parser.
- *
- * ## Export macros
- *
- * You must define `OPTIONS_DLL` globally and `OPTIONS_BUILDING_DLL` when
- * compiling the library if you want a DLL, alternatively you can provide your
- * own `OPTIONS_EXPORT` macro instead.
- */
-
-/**
- * \cond OPTIONS_HIDDEN_SYMBOLS
- */
-
-#if !defined(OPTIONS_EXPORT)
-#   if defined(OPTIONS_DLL)
-#       if defined(_WIN32)
-#           if defined(OPTIONS_BUILDING_DLL)
-#               define OPTIONS_EXPORT __declspec(dllexport)
-#           else
-#               define OPTIONS_EXPORT __declspec(dllimport)
-#           endif
-#       else
-#           define OPTIONS_EXPORT
-#       endif
-#   else
-#       define OPTIONS_EXPORT
-#   endif
-#endif
-
-/**
- * \endcond
- */
-
-#include <exception>
-#include <map>
-#include <string>
-#include <utility>
-#include <vector>
-
-/**
- * Namespace for options parsing.
- */
-namespace option {
-
-/**
- * \brief This exception is thrown when an invalid option has been found.
- */
-class InvalidOption : public std::exception {
-private:
-    std::string message;
-
-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))
-    {
-        message = std::string("invalid option: ") + argument;
-    }
-
-    /**
-     * Get the error message.
-     *
-     * \return the error message
-     */
-    const char *what() const noexcept override
-    {
-        return message.c_str();
-    }
-};
-
-/**
- * \brief This exception is thrown when an option requires a value and no value
- * has been given.
- */
-class MissingValue : public std::exception {
-private:
-    std::string m_message;
-    std::string m_option;
-
-public:
-    /**
-     * Construct the exception.
-     *
-     * \param option the option that requires a value
-     */
-    inline MissingValue(std::string option)
-        : m_option(std::move(option))
-    {
-        m_message = std::string("missing argument for: ") + m_option;
-    }
-
-    /**
-     * Get the options that requires a value.
-     *
-     * \return the option name
-     */
-    inline const std::string &option() const noexcept
-    {
-        return m_option;
-    }
-
-    /**
-     * Get the error message.
-     *
-     * \return the error message
-     */
-    const char *what() const noexcept override
-    {
-        return m_message.c_str();
-    }
-};
-
-/**
- * Packed multimap of options.
- */
-using Result = std::multimap<std::string, std::string>;
-
-/**
- * Define the allowed options.
- */
-using Options = std::map<std::string, bool>;
-
-/**
- * Extract the command line options and return a result.
- *
- * \param args the arguments
- * \param definition
- * \warning the arguments vector is modified in place to remove parsed options
- * \throw MissingValue
- * \throw InvalidOption
- */
-OPTIONS_EXPORT Result read(std::vector<std::string> &args, const Options &definition);
-
-/**
- * Overloaded function for usage with main() arguments.
- *
- * \param argc the number of arguments
- * \param argv the argument vector
- * \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
- */
-OPTIONS_EXPORT Result read(int &argc, char **&argv, const Options &definition);
-
-} // !option
-
-#endif // !OPTIONS_HPP
--- a/modules/options/test/main.cpp	Fri Dec 02 22:19:22 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,287 +0,0 @@
-/*
- * main.cpp -- main test file for OptionParser
- *
- * Copyright (c) 2013-2015 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.
- */
-
-#include <gtest/gtest.h>
-
-#include <options.hpp>
-
-/*
- * Short options.
- * ------------------------------------------------------------------
- */
-
-TEST(Short, simpleNoArg)
-{
-    std::vector<std::string> args{"-a", "-b"};
-
-    option::Options options{
-        { "-a", false },
-        { "-b", false }
-    };
-
-    option::Result pack = option::read(args, options);
-
-    ASSERT_EQ(2U, pack.size());
-    ASSERT_EQ(0U, args.size());
-
-    ASSERT_TRUE(pack.count("-a") != 0);
-    ASSERT_TRUE(pack.count("-b") != 0);
-}
-
-TEST(Short, simpleArg)
-{
-    std::vector<std::string> args{"-v", "-cfoo.conf"};
-
-    option::Options options{
-        { "-v", false },
-        { "-c", true  }
-    };
-
-    option::Result pack = option::read(args, options);
-
-    ASSERT_EQ(2U, pack.size());
-    ASSERT_EQ(0U, args.size());
-
-    ASSERT_TRUE(pack.count("-v") != 0);
-    ASSERT_EQ("foo.conf", pack.find("-c")->second);
-}
-
-TEST(Short, spacedArg)
-{
-    std::vector<std::string> args{"-v", "-c", "foo.conf"};
-
-    option::Options options{
-        { "-v", false },
-        { "-c", true  }
-    };
-
-    option::Result pack = option::read(args, options);
-
-    ASSERT_EQ(2U, pack.size());
-    ASSERT_EQ(0U, args.size());
-
-    ASSERT_TRUE(pack.count("-v") != 0);
-    ASSERT_EQ("foo.conf", pack.find("-c")->second);
-}
-
-TEST(Short, compacted)
-{
-    std::vector<std::string> args{"-abc"};
-
-    option::Options options{
-        { "-a", false },
-        { "-b", false },
-        { "-c", false },
-    };
-
-    option::Result pack = option::read(args, options);
-
-    ASSERT_EQ(3U, pack.size());
-    ASSERT_EQ(0U, args.size());
-
-    ASSERT_TRUE(pack.count("-a") != 0);
-    ASSERT_TRUE(pack.count("-b") != 0);
-    ASSERT_TRUE(pack.count("-c") != 0);
-}
-
-TEST(Short, compactedArg)
-{
-    std::vector<std::string> args{"-vdcfoo.conf"};
-
-    option::Options options{
-        { "-v", false },
-        { "-d", false },
-        { "-c", true },
-    };
-
-    option::Result pack = option::read(args, options);
-
-    ASSERT_EQ(3U, pack.size());
-    ASSERT_EQ(0U, args.size());
-
-    ASSERT_TRUE(pack.count("-v") != 0);
-    ASSERT_TRUE(pack.count("-d") != 0);
-    ASSERT_EQ("foo.conf", pack.find("-c")->second);
-}
-
-/*
- * Long options.
- * ------------------------------------------------------------------
- */
-
-TEST(Long, simple)
-{
-    std::vector<std::string> args{"--fullscreen"};
-
-    option::Options options{
-        { "--verbose",      false },
-        { "--fullscreen",   false }
-    };
-
-    option::Result pack = option::read(args, options);
-
-    ASSERT_EQ(1U, pack.size());
-    ASSERT_EQ(0U, args.size());
-
-    ASSERT_TRUE(pack.count("--fullscreen") != 0);
-}
-
-TEST(Long, simpleArg)
-{
-    std::vector<std::string> args{"--config", "config.conf", "--level", "2"};
-
-    option::Options options{
-        { "--config",   true },
-        { "--level",    true }
-    };
-
-    option::Result pack = option::read(args, options);
-
-    ASSERT_EQ(2U, pack.size());
-    ASSERT_EQ(0U, args.size());
-
-    ASSERT_EQ("config.conf", pack.find("--config")->second);
-    ASSERT_EQ("2", pack.find("--level")->second);
-}
-
-/*
- * Errors.
- * ------------------------------------------------------------------
- */
-
-TEST(Errors, stop)
-{
-    std::vector<std::string> args{"-v", "install", "-y", "irccd"};
-    std::vector<std::string> expected{"install", "-y", "irccd"};
-
-    option::Options options{
-        { "-v", false }
-    };
-
-    option::Result pack = option::read(args, options);
-
-    ASSERT_EQ(1U, pack.size());
-    ASSERT_EQ(3U, args.size());
-
-    ASSERT_TRUE(pack.count("-v") != 0);
-    ASSERT_EQ(expected, args);
-}
-
-TEST(Errors, missingShortArg)
-{
-    std::vector<std::string> args{"-c"};
-
-    option::Options options{
-        { "-c", true }
-    };
-
-    try {
-        option::Result pack = option::read(args, options);
-
-        FAIL() << "exception expected";
-    } catch (const option::MissingValue &) {
-    }
-}
-
-TEST(Errors, missingShortArg2)
-{
-    std::vector<std::string> args{"-vc"};
-
-    option::Options options{
-        { "-v", false },
-        { "-c", true }
-    };
-
-    try {
-        option::Result pack = option::read(args, options);
-
-        FAIL() << "exception expected";
-    } catch (const option::MissingValue &) {
-    }
-}
-
-TEST(Errors, missingLongArg)
-{
-    std::vector<std::string> args{"--config"};
-
-    option::Options options{
-        { "--config", true }
-    };
-
-    try {
-        option::Result pack = option::read(args, options);
-
-        FAIL() << "exception expected";
-    } catch (const option::MissingValue &) {
-    }
-}
-
-TEST(Errors, invalidOption)
-{
-    std::vector<std::string> args{"-x"};
-
-    option::Options options{
-        { "-v", true }
-    };
-
-    try {
-        option::Result pack = option::read(args, options);
-
-        FAIL() << "exception expected";
-    } catch (const option::InvalidOption &) {
-    }
-}
-
-TEST(Errors, invalidOption2)
-{
-    std::vector<std::string> args{"--destroy"};
-
-    option::Options options{
-        { "--verbose", true }
-    };
-
-    try {
-        option::Result pack = option::read(args, options);
-
-        FAIL() << "exception expected";
-    } catch (const option::InvalidOption &) {
-    }
-}
-
-TEST(Errors, invalidOption3)
-{
-    std::vector<std::string> args{"-vx"};
-
-    option::Options options{
-        { "-x", true }
-    };
-
-    try {
-        option::Result pack = option::read(args, options);
-
-        FAIL() << "exception expected";
-    } catch (const option::InvalidOption &) {
-    }
-}
-
-int main(int argc, char **argv)
-{
-    testing::InitGoogleTest(&argc, argv);
-
-    return RUN_ALL_TESTS();
-}