Compare commits

..

No commits in common. "e50baa07245d36ceaabfcd7f49a48d81b38fa8a8" and "1c978ba183b1e3d9debdfd26391f752b8dc0cae7" have entirely different histories.

4 changed files with 114 additions and 202 deletions

17
.vscode/settings.json vendored
View File

@ -1,17 +0,0 @@
{
"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"
}
}

View File

@ -1,48 +1,22 @@
# Парсер аргументов # Парсер аргументов
Обработка аргументов при запуске программы.
Объект типа `Hub` принимает первым аргументом вектор объектов типа `ConfigOption`, где аргументы:
1. Длинное имя аргумента
2. Короткое имя аргемнта
3. Наличие значения у аргумента: `NO` (НЕТ), `REQUIRED` (ОБЯЗАТЕЛЬНО), `OPTIONAL` (НЕОБЯЗАТЕЛЬНО)
4. Указатель на предварительную функцию-обработчик перед получением фактического значения(ий) аргумента
Вторым аргументом устанавливается значение тихого режима (по умолчанию `true`) для отображения системных ошибок при чтении аргументов.
- `readArguments` - чтение аргументов, где 3-ий аргумент функция на обработку ошибочных опций.
- `getOption` - получить объект опции
- `getValues` - получить значение опции. С параметром `true` выполнить предварительную обработку функцией, переданной в качестве аргумента при создании объекта `Hub`
```cpp ```cpp
#include <argpars.hpp>
void message()
{
std::cout << "Неверный аргумент" << std::endl;
exit(1);
}
typedef std::vector<std::string> arguments;
arguments print(const arguments &v)
{
std::cout << v.front() << std::endl;
return v;
}
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
args::Hub hub({ ArgPars cfg(error, false);
{"help", 'h', args::REQUIRED, print}, cfg.addKey('h', "hello", ArgPars::NO);
{"name", 'n', args::OPTIONAL, print} cfg.addKey('m', "my", ArgPars::OPTIONAL);
}, false); cfg.addKey('w', "world", ArgPars::REQUIRED);
cfg.readArguments(argc, argv);
hub.readArguments(argc, argv, message); if (cfg.checkKey('h'))
arguments a = hub.getOption('h').getValues(true); std::cout << "h установлен" << std::endl;
arguments b = hub.getOption('n').getValues(true);
if (cfg.checkKey('m'))
std::cout << "m установлен " << cfg.getValue('z') << std::endl;
if (cfg.checkKey('w'))
std::cout << "w установлен" << std::endl;
return 0; return 0;
} }

View File

@ -7,125 +7,110 @@
#include <argpars.hpp> #include <argpars.hpp>
namespace args ArgPars::ArgPars(cPtr callback, bool silencemode) :
longOptions(nullptr), sizeLongOption(0), shortOptions(nullptr), sizeShortOption(0), _callback(callback)
{ {
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<std::string> 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<std::string> Option::getValues(bool handling)
{
if (handling)
return _handling();
return _values;
}
void Hub::_createArguments(const std::vector<ConfigOption> &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))
{ {
_longOptions[opt.index()].name = opt.value().getLongParameter(); shortOptions = new char[++sizeShortOption];
_longOptions[opt.index()].has_arg = opt.value().getPresenceArgument(); shortOptions[0] = ':';
_longOptions[opt.index()].flag = nullptr;
_longOptions[opt.index()].val = opt.value().getShortParameter();
temp.push_back(opt.value().getShortParameter());
switch (opt.value().getPresenceArgument())
{
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<ConfigOption> &options, bool silence) : void ArgPars::addShortOption(const char shortKey, hasArg argument)
_longOptions(nullptr), _shortOptions(nullptr)
{ {
_createArguments(options, silence); 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;
} }
void Hub::readArguments(int argc, char *argv[], void (*_callback)()) 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; int next_option;
while ((next_option = getopt_long(argc, argv, _shortOptions, _longOptions, nullptr)) != -1) while ((next_option = getopt_long(argc, argv, shortOptions, longOptions, &option_index)) != -1)
{ {
if (_arguments.count(next_option)) if (cfg.count(next_option))
{ {
_arguments[next_option].first = true; cfg[next_option].first = true;
if (optarg) if (optarg)
_arguments[next_option].second.push(std::string(optarg)); cfg[next_option].second.push_back(std::string(optarg));
} }
if (next_option == '?' && _callback) if (next_option == '?' && _callback)
_callback(); _callback();
} }
} }
Option Hub::getOption(char key) const void ArgPars::addKey(const char shortKey, const std::string &longKey, hasArg argument)
{ {
return _arguments.count(key) && _arguments.at(key).first ? _arguments.at(key).second : Option(); addShortOption(shortKey, argument);
addLongOption(shortKey, longKey, argument);
} }
Hub::~Hub() void ArgPars::addNullKey()
{ {
delete[] _shortOptions; 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<std::string> ArgPars::getValues(const char shortKey)
{
if (cfg.count(shortKey) && cfg[shortKey].first)
return cfg[shortKey].second;
return {};
} }

View File

@ -7,66 +7,36 @@
#pragma once #pragma once
#include <iostream>
#include <getopt.h> #include <getopt.h>
#include <vector> #include <vector>
#include <string> #include <string>
#include <cstring> #include <cstring>
#include <map> #include <map>
#include <boost/range/adaptors.hpp> class ArgPars
#include <iostream>
namespace args
{
enum hasArg
{
NO, REQUIRED, OPTIONAL
};
typedef std::vector<std::string> (*_handler)(const std::vector<std::string>&);
class ConfigOption
{ {
private: private:
char *_longParameter; typedef void (*cPtr)();
const char _shortParameter;
const hasArg _ha;
const _handler _h;
public: public:
ConfigOption(const std::string &longParameter, const char shortParameter, const hasArg ha, _handler h = nullptr); enum hasArg {NO, REQUIRED, OPTIONAL};
const char* getLongParameter() const;
const char& getShortParameter() const;
const hasArg& getPresenceArgument() const;
const _handler getHandler() const;
};
class Option 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<std::string> getValues(const char shortKey);
private: private:
_handler _h; struct option *longOptions;
std::vector<std::string> _values; size_t sizeLongOption;
std::vector<std::string> _handling() const; char* shortOptions;
public: size_t sizeShortOption;
Option(const _handler h = nullptr); std::map<char, std::pair<bool, std::vector<std::string>>> cfg;
void push(const std::string &value);
std::vector<std::string> getValues(bool handling = false);
};
class Hub cPtr _callback;
{
private:
struct option *_longOptions;
char *_shortOptions;
std::map<char, std::pair<bool, Option>> _arguments;
void _createArguments(const std::vector<ConfigOption> &options, bool silence);
public:
Hub(const std::vector<ConfigOption> &options, bool silence = true);
void readArguments(int argc, char *argv[], void (*_callback)() = nullptr);
Option getOption(char key) const;
~Hub();
};
} 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();
};