commit 472ece92ec426b2fa2efafff642e222bdca91da5 Author: Alexander Zhirov Date: Tue Aug 30 19:12:29 2022 +0300 тестовая версия парсера аргументов diff --git a/README.md b/README.md new file mode 100644 index 0000000..46012d9 --- /dev/null +++ b/README.md @@ -0,0 +1,23 @@ +# Парсер аргументов + +```cpp +int main(int argc, char *argv[]) +{ + Config cfg(error, false); + cfg.addKey('h', "hello", Config::NO); + cfg.addKey('m', "my", Config::OPTIONAL); + cfg.addKey('w', "world", Config::REQUIRED); + cfg.readArguments(argc, argv); + + if (cfg.checkKey('h')) + std::cout << "h установлен" << std::endl; + + if (cfg.checkKey('m')) + std::cout << "m установлен " << cfg.getValue('z') << std::endl; + + if (cfg.checkKey('w')) + std::cout << "w установлен" << std::endl; + + return 0; +} +``` \ No newline at end of file diff --git a/argpars.cpp b/argpars.cpp new file mode 100644 index 0000000..03957ef --- /dev/null +++ b/argpars.cpp @@ -0,0 +1,116 @@ +/* + * argpars.cpp + * + * Created on: 30 авг. 2022 г. + * Author: alexander + */ + +#include + +ArgPars::ArgPars(cPtr callback, bool silencemode) : + longOptions(nullptr), sizeLongOption(0), shortOptions(nullptr), sizeShortOption(0), _callback(callback) +{ + if (silencemode) + { + shortOptions = new char[++sizeShortOption]; + shortOptions[0] = ':'; + } +} + +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)) + { + cfg[next_option].first = true; + if (optarg) + cfg[next_option].second.push_back(std::string(optarg)); + } + if (next_option == '?' && _callback) + _callback(); + } +} + +void ArgPars::addKey(const char shortKey, const std::string &longKey, hasArg argument) +{ + addShortOption(shortKey, argument); + addLongOption(shortKey, longKey, argument); +} + +void ArgPars::addNullKey() +{ + 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; +} + +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 new file mode 100644 index 0000000..949d956 --- /dev/null +++ b/argpars.hpp @@ -0,0 +1,42 @@ +/* + * argpars.hpp + * + * Created on: 30 авг. 2022 г. + * Author: alexander + */ + +#pragma once + +#include +#include +#include +#include +#include + +class ArgPars +{ +private: + typedef void (*cPtr)(); +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(); +};