From ba8e55d9c003403beb30d5183c5820c2fdeaa162 Mon Sep 17 00:00:00 2001 From: Alexander Zhirov Date: Wed, 31 Aug 2022 15:20:57 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A7=D1=82=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B0?= =?UTF-8?q?=D1=80=D0=B3=D1=83=D0=BC=D0=B5=D0=BD=D1=82=D0=BE=D0=B2=20=D1=81?= =?UTF-8?q?=20=D0=BF=D1=80=D0=B5=D0=B4=D0=B2=D0=B0=D1=80=D0=B8=D1=82=D0=B5?= =?UTF-8?q?=D0=BB=D1=8C=D0=BD=D0=BE=D0=B9=20=D0=BE=D0=B1=D1=80=D0=B0=D0=B1?= =?UTF-8?q?=D0=BE=D1=82=D0=BA=D0=BE=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/settings.json | 17 ++++ argpars.cpp | 193 +++++++++++++++++++++++------------------- argpars.hpp | 76 ++++++++++++----- 3 files changed, 174 insertions(+), 112 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..9efbaf5 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,17 @@ +{ + "files.associations": { + "functional": "cpp", + "type_traits": "cpp", + "variant": "cpp", + "__hash_table": "cpp", + "deque": "cpp", + "map": "cpp", + "memory": "cpp", + "mutex": "cpp", + "optional": "cpp", + "queue": "cpp", + "thread": "cpp", + "unordered_map": "cpp", + "vector": "cpp" + } +} \ No newline at end of file diff --git a/argpars.cpp b/argpars.cpp index 03957ef..649f686 100644 --- a/argpars.cpp +++ b/argpars.cpp @@ -7,110 +7,125 @@ #include -ArgPars::ArgPars(cPtr callback, bool silencemode) : - longOptions(nullptr), sizeLongOption(0), shortOptions(nullptr), sizeShortOption(0), _callback(callback) +namespace args { - if (silencemode) + +ConfigOption::ConfigOption(const std::string &longParameter, const char shortParameter, const hasArg ha, _handler h) : + _longParameter(nullptr), _shortParameter(shortParameter), _ha(ha), _h(h) +{ + _longParameter = new char[longParameter.length() + 1]; + strcpy(_longParameter, longParameter.c_str()); +} + +const char* ConfigOption::getLongParameter() const +{ + return _longParameter; +} + +const char& ConfigOption::getShortParameter() const +{ + return _shortParameter; +} + +const hasArg& ConfigOption::getPresenceArgument() const +{ + return _ha; +} + +const _handler ConfigOption::getHandler() const +{ + return _h; +} + +std::vector Option::_handling() const +{ + return _h ? _h(_values) : _values; +} + +Option::Option(const _handler h) : + _h(h) +{ +} +void Option::push(const std::string &value) +{ + _values.push_back(value); +} +std::vector Option::getValues(bool handling) +{ + if (handling) + return _handling(); + return _values; +} + +void Hub::_createArguments(const std::vector &options, bool silence) +{ + _longOptions = new struct option[options.size() + 1]; + std::string temp; + if (silence) + temp.push_back(':'); + for (auto const &opt : options | boost::adaptors::indexed(0)) { - shortOptions = new char[++sizeShortOption]; - shortOptions[0] = ':'; - } -} + _longOptions[opt.index()].name = opt.value().getLongParameter(); + _longOptions[opt.index()].has_arg = opt.value().getPresenceArgument(); + _longOptions[opt.index()].flag = nullptr; + _longOptions[opt.index()].val = opt.value().getShortParameter(); -void ArgPars::addShortOption(const char shortKey, hasArg argument) -{ - size_t sizeTemp = sizeShortOption; - if (argument == hasArg::REQUIRED) - ++sizeShortOption; - else if (argument == hasArg::OPTIONAL) - sizeShortOption += 2; - char *temp = new char[++sizeShortOption]; - if (sizeTemp) - strcpy(temp, shortOptions); - temp[sizeTemp++] = shortKey; - if (argument == hasArg::REQUIRED) - temp[sizeTemp] = ':'; - else if (argument == hasArg::OPTIONAL) - strcpy(&temp[sizeTemp], "::"); - delete[] shortOptions; - shortOptions = temp; - cfg[shortKey].first = false; -} - -struct option ArgPars::createNewOption(const char shortKey, const std::string &longKey, hasArg argument) -{ - struct option newOption; - char *name = new char[longKey.length() + 1]; - strcpy(name, longKey.c_str()); - newOption.name = name; - newOption.has_arg = argument; - newOption.flag = nullptr; - newOption.val = shortKey; - return newOption; -} - -void ArgPars::addLongOption(const char shortKey, const std::string &longKey, hasArg argument) -{ - struct option *temp = new struct option[++sizeLongOption]; - for (size_t i = 0; i < sizeLongOption - 1; ++i) - temp[i] = longOptions[i]; - temp[sizeLongOption - 1] = createNewOption(shortKey, longKey, argument); - delete[] longOptions; - longOptions = temp; -} - -void ArgPars::readArguments(int argc, char *argv[]) -{ - int option_index; - int next_option; - while ((next_option = getopt_long(argc, argv, shortOptions, longOptions, &option_index)) != -1) - { - if (cfg.count(next_option)) + temp.push_back(opt.value().getShortParameter()); + switch (opt.value().getPresenceArgument()) { - cfg[next_option].first = true; + case hasArg::OPTIONAL: + temp.push_back(':'); + case hasArg::REQUIRED: + temp.push_back(':'); + break; + case hasArg::NO: + break; + } + + _arguments[opt.value().getShortParameter()].first = false; + _arguments[opt.value().getShortParameter()].second = + { opt.value().getHandler() }; + } + + _longOptions[options.size()].name = nullptr; + _longOptions[options.size()].has_arg = 0; + _longOptions[options.size()].flag = nullptr; + _longOptions[options.size()].val = 0; + + _shortOptions = new char[temp.size() + 1]; + strcpy(_shortOptions, temp.c_str()); +} + +Hub::Hub(const std::vector &options, bool silence) : + _longOptions(nullptr), _shortOptions(nullptr) +{ + _createArguments(options, silence); +} + +void Hub::readArguments(int argc, char *argv[], void (*_callback)()) +{ + int next_option; + while ((next_option = getopt_long(argc, argv, _shortOptions, _longOptions, nullptr)) != -1) + { + if (_arguments.count(next_option)) + { + _arguments[next_option].first = true; if (optarg) - cfg[next_option].second.push_back(std::string(optarg)); + _arguments[next_option].second.push(std::string(optarg)); } if (next_option == '?' && _callback) _callback(); } } -void ArgPars::addKey(const char shortKey, const std::string &longKey, hasArg argument) +Option Hub::getOption(char key) const { - addShortOption(shortKey, argument); - addLongOption(shortKey, longKey, argument); + return _arguments.count(key) && _arguments.at(key).first ? _arguments.at(key).second : Option(); } -void ArgPars::addNullKey() +Hub::~Hub() { - struct option *temp = new struct option[++sizeLongOption]; - for (size_t i = 0; i < sizeLongOption - 1; ++i) - temp[i] = longOptions[i]; - temp[sizeLongOption - 1] = option - { nullptr, 0, nullptr, 0 }; - delete[] longOptions; - longOptions = temp; + delete[] _shortOptions; } -bool ArgPars::checkKey(const char shortKey) -{ - return cfg.count(shortKey) > 0 && cfg[shortKey].first; -} - -std::string ArgPars::getValue(const char shortKey) -{ - if (cfg.count(shortKey) && cfg[shortKey].first) - { - if (cfg[shortKey].second.size()) - return cfg[shortKey].second.front(); - } - return {}; -} - -std::vector ArgPars::getValues(const char shortKey) -{ - if (cfg.count(shortKey) && cfg[shortKey].first) - return cfg[shortKey].second; - return {}; } diff --git a/argpars.hpp b/argpars.hpp index 949d956..79b5d4a 100644 --- a/argpars.hpp +++ b/argpars.hpp @@ -7,36 +7,66 @@ #pragma once +#include #include + #include #include #include #include -class ArgPars +#include +#include + +namespace args +{ + +enum hasArg +{ + NO, REQUIRED, OPTIONAL +}; + +typedef std::vector (*_handler)(const std::vector&); + +class ConfigOption { private: - typedef void (*cPtr)(); + char *_longParameter; + const char _shortParameter; + const hasArg _ha; + const _handler _h; public: - enum hasArg {NO, REQUIRED, OPTIONAL}; - - ArgPars(cPtr callback = nullptr, bool silencemode = true); - void readArguments(int argc, char *argv[]); - void addKey(const char shortKey, const std::string &longKey, hasArg argument); - bool checkKey(const char shortKey); - std::string getValue(const char shortKey); - std::vector getValues(const char shortKey); -private: - struct option *longOptions; - size_t sizeLongOption; - char* shortOptions; - size_t sizeShortOption; - std::map>> cfg; - - cPtr _callback; - - void addShortOption(const char shortKey, hasArg argument); - struct option createNewOption(const char shortKey, const std::string &longKey, hasArg argument); - void addLongOption(const char shortKey, const std::string &longKey, hasArg argument); - void addNullKey(); + ConfigOption(const std::string &longParameter, const char shortParameter, const hasArg ha, _handler h = nullptr); + const char* getLongParameter() const; + const char& getShortParameter() const; + const hasArg& getPresenceArgument() const; + const _handler getHandler() const; }; + +class Option +{ +private: + _handler _h; + std::vector _values; + std::vector _handling() const; +public: + Option(const _handler h = nullptr); + void push(const std::string &value); + std::vector getValues(bool handling = false); +}; + +class Hub +{ +private: + struct option *_longOptions; + char *_shortOptions; + std::map> _arguments; + void _createArguments(const std::vector &options, bool silence); +public: + Hub(const std::vector &options, bool silence = true); + void readArguments(int argc, char *argv[], void (*_callback)() = nullptr); + Option getOption(char key) const; + ~Hub(); +}; + +}