Skip to content

Commit

Permalink
dev: Add Strutil::eval_as_bool (AcademySoftwareFoundation#4250)
Browse files Browse the repository at this point in the history
Signed-off-by: Larry Gritz <lg@larrygritz.com>
  • Loading branch information
lgritz committed May 18, 2024
1 parent 6fc6f83 commit 530987c
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 2 deletions.
13 changes: 13 additions & 0 deletions src/include/OpenImageIO/strutil.h
Original file line number Diff line number Diff line change
Expand Up @@ -1155,6 +1155,19 @@ OIIO_UTIL_API size_t
edit_distance(string_view a, string_view b,
EditDistMetric metric = EditDistMetric::Levenshtein);


/// Evaluate a string as a boolean value using the following heuristic:
/// - If the string is a valid numeric value (represents an integer or
/// floating point value), return true if it's non-zero, false if it's
/// zero.
/// - If the string is one of "false", "no", or "off", or if it contains
/// only whitespace, return false.
/// - All other non-empty strings return true.
/// The comparisons are case-insensitive and ignore leading and trailing
/// whitespace.
OIIO_UTIL_API bool
eval_as_bool(string_view value);

} // namespace Strutil


Expand Down
26 changes: 26 additions & 0 deletions src/libutil/strutil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1861,4 +1861,30 @@ Strutil::edit_distance(string_view a, string_view b, EditDistMetric metric)
return levenshtein_distance(a, b);
}



/// Interpret a string as a boolean value using the following heuristic:
/// - If the string is a valid numeric value (represents an integer or
/// floating point value), return true if it's non-zero, false if it's
/// zero.
/// - If the string is one of "false", "no", or "off", or if it contains
/// only whitespace, return false.
/// - All other non-empty strings return true.
/// The comparisons are case-insensitive and ignore leading and trailing
/// whitespace.
bool
Strutil::eval_as_bool(string_view value)
{
Strutil::trim_whitespace(value);
if (Strutil::string_is_int(value)) {
return Strutil::stoi(value) != 0;
} else if (Strutil::string_is_float(value)) {
return Strutil::stof(value) != 0.0f;
} else {
return !(value.empty() || Strutil::iequals(value, "false")
|| Strutil::iequals(value, "no")
|| Strutil::iequals(value, "off"));
}
}

OIIO_NAMESPACE_END
48 changes: 48 additions & 0 deletions src/libutil/strutil_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1673,6 +1673,53 @@ test_base64_encode()



void
test_eval_as_bool()
{
using namespace Strutil;
print("testing eval_as_bool()\n");

// Test cases for integer values
OIIO_CHECK_EQUAL(eval_as_bool("0"), false);
OIIO_CHECK_EQUAL(eval_as_bool("1"), true);
OIIO_CHECK_EQUAL(eval_as_bool("-1"), true);
OIIO_CHECK_EQUAL(eval_as_bool("10"), true);
OIIO_CHECK_EQUAL(eval_as_bool("-10"), true);

// Test cases for floating-point values
OIIO_CHECK_EQUAL(eval_as_bool("0.0"), false);
OIIO_CHECK_EQUAL(eval_as_bool("1.0"), true);
OIIO_CHECK_EQUAL(eval_as_bool("-1.0"), true);
OIIO_CHECK_EQUAL(eval_as_bool("10.5"), true);
OIIO_CHECK_EQUAL(eval_as_bool("-10.5"), true);

// Test cases for string values
OIIO_CHECK_EQUAL(eval_as_bool(""), false);
OIIO_CHECK_EQUAL(eval_as_bool("false"), false);
OIIO_CHECK_EQUAL(eval_as_bool("FALSE"), false);
OIIO_CHECK_EQUAL(eval_as_bool("no"), false);
OIIO_CHECK_EQUAL(eval_as_bool("NO"), false);
OIIO_CHECK_EQUAL(eval_as_bool("off"), false);
OIIO_CHECK_EQUAL(eval_as_bool("OFF"), false);

OIIO_CHECK_EQUAL(eval_as_bool("true"), true);
OIIO_CHECK_EQUAL(eval_as_bool("TRUE"), true);
OIIO_CHECK_EQUAL(eval_as_bool("yes"), true);
OIIO_CHECK_EQUAL(eval_as_bool("YES"), true);
OIIO_CHECK_EQUAL(eval_as_bool("on"), true);
OIIO_CHECK_EQUAL(eval_as_bool("ON"), true);
OIIO_CHECK_EQUAL(eval_as_bool("OpenImageIO"), true);

// Test whitespace, case insensitivity, other tricky cases
OIIO_CHECK_EQUAL(eval_as_bool(" "), false);
OIIO_CHECK_EQUAL(eval_as_bool("\t \n"), false);
OIIO_CHECK_EQUAL(eval_as_bool(" faLsE"), false);
OIIO_CHECK_EQUAL(eval_as_bool("\tOFf"), false);
OIIO_CHECK_EQUAL(eval_as_bool("off OpenImageIO"), true);
}



int
main(int /*argc*/, char* /*argv*/[])
{
Expand Down Expand Up @@ -1708,6 +1755,7 @@ main(int /*argc*/, char* /*argv*/[])
test_datetime();
test_edit_distance();
test_base64_encode();
test_eval_as_bool();

Strutil::debug("debug message\n");

Expand Down
4 changes: 2 additions & 2 deletions src/oiiotool/oiiotool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1121,7 +1121,7 @@ control_if(Oiiotool& ot, cspan<const char*> argv)
if (ot.running()) {
// string_view command = ot.express(argv[0]);
string_view value = ot.express(argv[1]);
cond = eval_as_bool(value);
cond = Strutil::eval_as_bool(value);
// Strutil::print("while: val='{}' cond={}\n", value, cond);
} else {
// If not running in the outer scope, don't even evaluate the
Expand Down Expand Up @@ -1184,7 +1184,7 @@ control_while(Oiiotool& ot, cspan<const char*> argv)
if (ot.running()) {
// string_view command = ot.express(argv[0]);
string_view value = ot.express(argv[1]);
cond = eval_as_bool(value);
cond = Strutil::eval_as_bool(value);
// Strutil::print("while: val='{}' cond={}\n", value, cond);
} else {
// If not running in the outer scope, don't even evaluate the
Expand Down

0 comments on commit 530987c

Please sign in to comment.