Skip to content

Commit

Permalink
light: restore -bounce flag with no arguments as a shorthand for -bou…
Browse files Browse the repository at this point in the history
…nce 1
  • Loading branch information
ericwa committed Jan 14, 2024
1 parent 10293fa commit 07e050f
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 18 deletions.
49 changes: 33 additions & 16 deletions include/common/settings.hh
Original file line number Diff line number Diff line change
Expand Up @@ -242,14 +242,17 @@ public:
std::string format() const override;
};

class can_omit_argument_tag {};

template<typename T>
class setting_numeric : public setting_value<T>
{
static_assert(!std::is_enum_v<T>, "use setting_enum for enums");

protected:
T _min, _max;

bool _can_omit_argument = false;
T _omitted_argument_value = static_cast<T>(0);
public:
inline setting_numeric(setting_container *dictionary, const nameset &names, T v, T minval, T maxval,
const setting_group *group = nullptr, const char *description = "")
Expand All @@ -270,6 +273,15 @@ public:
{
}

inline setting_numeric(setting_container *dictionary, const nameset &names, T v, T minval, T maxval,
can_omit_argument_tag tag, T omitted_argument_value,
const setting_group *group = nullptr, const char *description = "")
: setting_numeric(dictionary, names, v, minval, maxval, group, description)
{
_can_omit_argument = true;
_omitted_argument_value = omitted_argument_value;
}

void set_value(const T &f, source new_source) override
{
if (f < _min) {
Expand All @@ -286,25 +298,30 @@ public:

bool parse(const std::string &setting_name, parser_base_t &parser, source source) override
{
if (!parser.parse_token()) {
return false;
}

try {
T f;

if constexpr (std::is_floating_point_v<T>) {
f = std::stod(parser.token);
} else {
f = static_cast<T>(std::stoull(parser.token));
if (parser.parse_token(PARSE_PEEK)) {
try {
T f;

if constexpr (std::is_floating_point_v<T>) {
f = std::stod(parser.token);
} else {
f = static_cast<T>(std::stoull(parser.token));
}
// if no exception was thrown then we parsed a float/int here successfully
Q_assert(parser.parse_token());
this->set_value(f, source);
return true;
} catch (std::exception &) {
// fall through...
}
}

this->set_value(f, source);

// either there is nothing to parse, or it failed to parse as a float/int
if (_can_omit_argument) {
this->set_value(_omitted_argument_value, source);
return true;
} catch (std::exception &) {
return false;
}
return false;
}

std::string string_value() const override { return std::to_string(this->_value); }
Expand Down
2 changes: 1 addition & 1 deletion light/light.cc
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ worldspawn_keys::worldspawn_keys()
minlight_dirt{this, "minlight_dirt", false, &worldspawn_group},
phongallowed{this, "phong", true, &worldspawn_group},
phongangle{this, "phong_angle", 0, &worldspawn_group},
bounce{this, "bounce", 0, &worldspawn_group},
bounce{this, "bounce", 0, 0, 100, settings::can_omit_argument_tag(), 1, &worldspawn_group},
bouncestyled{this, "bouncestyled", false, &worldspawn_group},
bouncescale{this, "bouncescale", 1.0, 0.0, 100.0, &worldspawn_group},
bouncecolorscale{this, "bouncecolorscale", 0.0, 0.0, 1.0, &worldspawn_group},
Expand Down
59 changes: 58 additions & 1 deletion tests/test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,64 @@ TEST_SUITE("settings")
REQUIRE_THROWS_AS(settings.parse(p), settings::parse_exception);
}

// test scalars
// test int32 with implicit default
TEST_CASE("int32CanOmitArgumentDefault")
{
settings::setting_container settings;
settings::setting_int32 setting(&settings, "bounce", 0, 0, 100,
settings::can_omit_argument_tag(), 1);
REQUIRE(setting.value() == 0);
}

TEST_CASE("int32CanOmitArgumentSimple")
{
settings::setting_container settings;
settings::setting_int32 setting(&settings, "bounce", 0, 0, 100,
settings::can_omit_argument_tag(), 1);
const char *arguments[] = {"qbsp.exe", "-bounce", "2"};
token_parser_t p{std::size(arguments) - 1, arguments + 1, {}};
settings.parse(p);
REQUIRE(setting.value() == 2);
}

TEST_CASE("int32CanOmitArgumentWithFollingSetting")
{
settings::setting_container settings;
settings::setting_int32 setting(&settings, "bounce", 0, 0, 100,
settings::can_omit_argument_tag(), 1);
settings::setting_scalar scalarSetting(&settings, "scale", 1.0);
const char *arguments[] = {"qbsp.exe", "-bounce", "-scale", "0.25"};
token_parser_t p{std::size(arguments) - 1, arguments + 1, {}};
settings.parse(p);
REQUIRE(setting.value() == 1);
REQUIRE(scalarSetting.value() == 0.25);
}

TEST_CASE("int32CanOmitArgumentEOF")
{
settings::setting_container settings;
settings::setting_int32 setting(&settings, "bounce", 0, 0, 100,
settings::can_omit_argument_tag(), 1);
settings::setting_scalar scalarSetting(&settings, "scale", 1.0);
const char *arguments[] = {"qbsp.exe", "-bounce"};
token_parser_t p{std::size(arguments) - 1, arguments + 1, {}};
settings.parse(p);
REQUIRE(setting.value() == 1);
}

TEST_CASE("int32CanOmitArgumentRemainder")
{
settings::setting_container settings;
settings::setting_int32 setting(&settings, "bounce", 0, 0, 100,
settings::can_omit_argument_tag(), 1);
settings::setting_scalar scalarSetting(&settings, "scale", 1.0);
const char *arguments[] = {"qbsp.exe", "-bounce", "remainder"};
token_parser_t p{std::size(arguments) - 1, arguments + 1, {}};
auto remainder = settings.parse(p);
REQUIRE(remainder == std::vector<std::string>{"remainder"});\
}

// test vec3
TEST_CASE("vec3Simple")
{
settings::setting_container settings;
Expand Down

0 comments on commit 07e050f

Please sign in to comment.