1
0
mirror of https://github.com/rwengine/openrw.git synced 2024-10-06 09:07:19 +02:00

Merge pull request #692 from madebr/rwconfig_fixes

RWconfig fixes
This commit is contained in:
Daniel Evans 2019-01-18 22:31:21 +00:00 committed by GitHub
commit 01d2445b86
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 91 additions and 25 deletions

View File

@ -39,17 +39,9 @@ po::options_description build_options() {
} \
} while (0);
#define RWCONFIGARG(_RW_TYPE, _RW_NAME, _RW_DEFAULT, _RW_CONFPATH, _RW_CATEGORY, _RW_ARGMASK, _RW_ARGMETA, _RW_HELP) \
do { \
if constexpr (std::is_same_v<bool, _RW_TYPE>) { \
descriptions[RWArgumentParser::Category::_RW_CATEGORY].add_options()( \
_RW_ARGMASK, _RW_HELP); \
} else { \
descriptions[RWArgumentParser::Category::_RW_CATEGORY].add_options()( \
_RW_ARGMASK, po::value<_RW_TYPE>()->value_name(_RW_ARGMETA), _RW_HELP); \
} \
} while (0);
RWARG(_RW_TYPE, _RW_NAME, _RW_CATEGORY, _RW_ARGMASK, _RW_ARGMETA, _RW_HELP)
#define RWARG_OPT(_RW_TYPE, _RW_NAME, _RW_CATEGORY, _RW_ARGMASK, _RW_ARGMETA, _RW_HELP) \
RWCONFIGARG(_RW_TYPE, _RW_NAME, std::nullopt, nullptr, _RW_CATEGORY, _RW_ARGMASK, _RW_ARGMETA, _RW_HELP)
RWARG(_RW_TYPE, _RW_NAME, _RW_CATEGORY, _RW_ARGMASK, _RW_ARGMETA, _RW_HELP)
#include "RWConfig.inc"
@ -89,39 +81,62 @@ constexpr std::string_view arg_mask_to_key(std::string_view v) {
return v.substr(maxstart, maxsize);
}
template <typename T>
std::optional<T> vm_get_opt_argmask(const po::variables_map& vm, const std::string_view& argmask) {
const std::string key{arg_mask_to_key(argmask)};
auto it = vm.find(key);
if (it != vm.end()) {
return it->second.as<T>();
}
return std::nullopt;
}
template <>
std::optional<bool> vm_get_opt_argmask<bool>(const po::variables_map& vm, const std::string_view& argmask) {
const std::string key{arg_mask_to_key(argmask)};
auto it = vm.find(key);
if (it != vm.end()) {
return true;
}
return std::nullopt;
}
bool vm_get_argmask(const po::variables_map& vm, const std::string_view& argmask) {
auto val = vm_get_opt_argmask<bool>(vm, argmask);
return val.has_value() && *val;
}
}
std::optional<RWArgConfigLayer> RWArgumentParser::parseArguments(int argc, const char* argv[]) const {
po::variables_map vm;
try {
if (argc != 0) {
po::store(po::command_line_parser(argc, argv).options(_desc).positional(po::positional_options_description{}).run(), vm);
po::command_line_parser parser(argc, argv);
parser.options(_desc);
parser.positional(po::positional_options_description{});
parser.style(po::command_line_style::unix_style & (~po::command_line_style::allow_guessing));
po::store(parser.run(), vm);
}
po::notify(vm);
} catch (po::error &ex) {
} catch (po::error& ex) {
std::cerr << "Error parsing arguments: " << ex.what() << std::endl;
return std::nullopt;
} catch (boost::exception& ex) {
std::cerr << "A boost::exception object was thrown (bug in Boost.Program_options?).\n";
std::cerr << "unknown error\n";
return std::nullopt;
}
RWArgConfigLayer layer;
#define RWARG(_RW_TYPE, _RW_NAME, _RW_CATEGORY, _RW_ARGMASK, _RW_ARGMETA, _RW_HELP) \
do { \
const std::string key{arg_mask_to_key(_RW_ARGMASK)}; \
layer._RW_NAME = vm.count(key) != 0u; \
layer._RW_NAME = vm_get_argmask(vm, _RW_ARGMASK); \
} while (0);
#define RWCONFIGARG(_RW_TYPE, _RW_NAME, _RW_DEFAULT, _RW_CONFPATH, _RW_CATEGORY, _RW_ARGMASK, _RW_ARGMETA, _RW_HELP) \
do { \
const std::string key{arg_mask_to_key(_RW_ARGMASK)}; \
if (vm.count(key)) { \
layer._RW_NAME = vm[key].as<_RW_TYPE>(); \
} \
} while (0);
RWARG_OPT(_RW_TYPE, _RW_NAME, _RW_CATEGORY, _RW_ARGMASK, _RW_ARGMETA, _RW_HELP)
#define RWARG_OPT(_RW_TYPE, _RW_NAME, _RW_CATEGORY, _RW_ARGMASK, _RW_ARGMETA, _RW_HELP) \
do { \
const std::string key{arg_mask_to_key(_RW_ARGMASK)}; \
if (vm.count(key)) { \
layer._RW_NAME = vm[key].as<_RW_TYPE>(); \
} \
layer._RW_NAME = vm_get_opt_argmask<_RW_TYPE>(vm, _RW_ARGMASK); \
} while (0);
#include "RWConfig.inc"
@ -131,7 +146,7 @@ std::optional<RWArgConfigLayer> RWArgumentParser::parseArguments(int argc, const
#undef RWARG
if (layer.noconfig && layer.configPath.has_value()) {
std::cerr << "Cannot set config path and ask noconfig at the sametime.\n";
std::cerr << "Cannot set config path and noconfig at the same time.\n";
return std::nullopt;
}

View File

@ -638,6 +638,20 @@ BOOST_AUTO_TEST_CASE(test_argParser_int) {
BOOST_CHECK_EQUAL(*optLayer->width, width);
}
BOOST_AUTO_TEST_CASE(test_argParser_incomplete_optional) {
RWArgumentParser argParser;
const char *args[] = {"", "--hel"};
auto optLayer = argParser.parseArguments(2, args);
BOOST_CHECK(!optLayer.has_value());
}
BOOST_AUTO_TEST_CASE(test_argParser_case_sensitive) {
RWArgumentParser argParser;
const char *args[] = {"", "--HELP"};
auto optLayer = argParser.parseArguments(2, args);
BOOST_CHECK(!optLayer.has_value());
}
BOOST_AUTO_TEST_CASE(test_argParser_int_invalid) {
RWArgumentParser argParser;
@ -648,6 +662,43 @@ BOOST_AUTO_TEST_CASE(test_argParser_int_invalid) {
BOOST_CHECK(!optLayer.has_value());
}
BOOST_AUTO_TEST_CASE(test_argParser_bool_newgame) {
RWArgumentParser argParser;
{
const char *args[] = {""};
auto optLayer = argParser.parseArguments(1, args);
BOOST_REQUIRE(optLayer.has_value());
BOOST_CHECK(!optLayer->newGame);
}
{
const char *args[] = {"", "-n"};
auto optLayer = argParser.parseArguments(2, args);
BOOST_REQUIRE(optLayer.has_value());
BOOST_CHECK(optLayer->newGame);
}
}
BOOST_AUTO_TEST_CASE(test_argParser_bool_invert_y) {
RWArgumentParser argParser;
{
const char *args[] = {""};
auto optLayer = argParser.parseArguments(1, args);
BOOST_REQUIRE(optLayer.has_value());
BOOST_CHECK(!optLayer->invertY.has_value());
}
{
const char *args[] = {"", "--invert_y"};
auto optLayer = argParser.parseArguments(2, args);
BOOST_REQUIRE(optLayer.has_value());
BOOST_REQUIRE(optLayer->invertY.has_value());
BOOST_CHECK(*optLayer->invertY);
}
}
BOOST_AUTO_TEST_CASE(test_rwconfig_initial) {
RWConfig config;
auto missingKeys = config.missingKeys();