diff options
Diffstat (limited to 'nihil.ucl')
| -rw-r--r-- | nihil.ucl/boolean.ccm | 3 | ||||
| -rw-r--r-- | nihil.ucl/integer.ccm | 7 | ||||
| -rw-r--r-- | nihil.ucl/real.ccm | 8 | ||||
| -rw-r--r-- | nihil.ucl/string.ccm | 44 | ||||
| -rw-r--r-- | nihil.ucl/tests/array.cc | 28 | ||||
| -rw-r--r-- | nihil.ucl/tests/boolean.cc | 27 | ||||
| -rw-r--r-- | nihil.ucl/tests/integer.cc | 28 | ||||
| -rw-r--r-- | nihil.ucl/tests/real.cc | 28 | ||||
| -rw-r--r-- | nihil.ucl/tests/string.cc | 96 |
9 files changed, 227 insertions, 42 deletions
diff --git a/nihil.ucl/boolean.ccm b/nihil.ucl/boolean.ccm index e9c161b..8510152 100644 --- a/nihil.ucl/boolean.ccm +++ b/nihil.ucl/boolean.ccm @@ -37,6 +37,9 @@ export struct boolean final : object { throw type_mismatch(ucl_type, type()); } + // Create a new default-initialised boolean. + boolean() : boolean(false) {} + // Create a new boolean from a value. explicit boolean(value_type value) : object(noref, ::ucl_object_frombool(value)) diff --git a/nihil.ucl/integer.ccm b/nihil.ucl/integer.ccm index 18f0049..b58c04d 100644 --- a/nihil.ucl/integer.ccm +++ b/nihil.ucl/integer.ccm @@ -37,8 +37,13 @@ export struct integer final : object { throw type_mismatch(ucl_type, type()); } + // Create a new default-initialised integer. + integer() + : integer(0) + {} + // Create a new integer from a value. - integer(value_type value) + explicit integer(value_type value) : object(noref, ::ucl_object_fromint(value)) { if (_object == nullptr) diff --git a/nihil.ucl/real.ccm b/nihil.ucl/real.ccm index d968667..51607f2 100644 --- a/nihil.ucl/real.ccm +++ b/nihil.ucl/real.ccm @@ -36,14 +36,20 @@ export struct real final : object { throw type_mismatch(ucl_type, type()); } + // Create a default-initialised real. + real() + : real(0) + {} + // Create a new real from a value. - real(value_type value) + explicit real(value_type value) : object(noref, ::ucl_object_fromdouble(value)) { if (_object == nullptr) throw error("failed to create UCL object"); } + // Return the value of this real. auto value(this real const &self) -> value_type { auto v = value_type{}; diff --git a/nihil.ucl/string.ccm b/nihil.ucl/string.ccm index ffad847..64f88dc 100644 --- a/nihil.ucl/string.ccm +++ b/nihil.ucl/string.ccm @@ -36,8 +36,13 @@ export struct string final : object { throw type_mismatch(ucl_type, type()); } + // Create a new empty string. + string() + : string(std::string_view("")) + {} + // Create a new UCL string from a string. - string(std::string_view value) + explicit string(std::string_view value) : object(nihil::ucl::ref, ::ucl_object_fromstring_common( value.data(), value.size(), @@ -75,6 +80,7 @@ export struct string final : object { if (::ucl_object_tolstring_safe(uobj, &dptr, &dlen)) return {dptr, dlen}; + // This should never fail. std::abort(); } }; @@ -95,16 +101,42 @@ export auto operator<=> (string const &a, string const &b) return a.value() <=> b.value(); } -export auto operator== (string const &a, string::value_type b) - -> bool +/* + * For convenience, allow comparison with C++ strings without having to + * construct a temporary UCL object. + */ + +export auto operator==(string const &lhs, std::string_view rhs) -> bool +{ + return lhs.value() == rhs; +} + +export auto operator<=>(string const &lhs, std::string_view rhs) + -> std::strong_ordering +{ + return lhs.value() <=> rhs; +} + +export auto operator==(string const &lhs, std::string const &rhs) -> bool +{ + return lhs == std::string_view(rhs); +} + +export auto operator<=>(string const &lhs, std::string const &rhs) + -> std::strong_ordering +{ + return lhs <=> std::string_view(rhs); +} + +export auto operator==(string const &lhs, char const *rhs) -> bool { - return a.value() == b; + return lhs == std::string_view(rhs); } -export auto operator<=> (string const &a, string::value_type b) +export auto operator<=>(string const &lhs, char const *rhs) -> std::strong_ordering { - return a.value() <=> b; + return lhs <=> std::string_view(rhs); } } // namespace nihil::ucl diff --git a/nihil.ucl/tests/array.cc b/nihil.ucl/tests/array.cc index a4f26b6..ce86058 100644 --- a/nihil.ucl/tests/array.cc +++ b/nihil.ucl/tests/array.cc @@ -31,9 +31,9 @@ TEST_CASE("ucl: array: push_back", "[ucl]") arr.push_back(integer(666)); REQUIRE(arr.size() == 3); - REQUIRE(arr[0].value() == 1); - REQUIRE(arr[1].value() == 42); - REQUIRE(arr[2].value() == 666); + REQUIRE(arr[0] == 1); + REQUIRE(arr[1] == 42); + REQUIRE(arr[2] == 666); REQUIRE_THROWS_AS(arr[3], std::out_of_range); @@ -46,22 +46,22 @@ TEST_CASE("ucl: array: compare", "[ucl]") using namespace nihil::ucl; auto arr = array<integer>(); - arr.push_back(1); - arr.push_back(42); - arr.push_back(666); + arr.push_back(integer(1)); + arr.push_back(integer(42)); + arr.push_back(integer(666)); auto arr2 = array<integer>(); REQUIRE(arr != arr2); - arr2.push_back(1); - arr2.push_back(42); - arr2.push_back(666); + arr2.push_back(integer(1)); + arr2.push_back(integer(42)); + arr2.push_back(integer(666)); REQUIRE(arr == arr2); auto arr3 = array<integer>(); - arr3.push_back(1); - arr3.push_back(1); - arr3.push_back(1); + arr3.push_back(integer(1)); + arr3.push_back(integer(1)); + arr3.push_back(integer(1)); REQUIRE(arr != arr3); } @@ -69,7 +69,7 @@ TEST_CASE("ucl: array: iterator", "[ucl]") { using namespace nihil::ucl; - auto arr = array<integer>{1, 42, 666}; + auto arr = array<integer>{integer(1), integer(42), integer(666)}; auto it = arr.begin(); REQUIRE(*it == 1); @@ -129,7 +129,7 @@ TEST_CASE("ucl: array is a sized_range", "[ucl]") { using namespace nihil::ucl; - auto arr = array<integer>{1, 42, 666}; + auto arr = array<integer>{integer(1), integer(42), integer(666)}; static_assert(std::ranges::sized_range<decltype(arr)>); auto size = std::ranges::size(arr); diff --git a/nihil.ucl/tests/boolean.cc b/nihil.ucl/tests/boolean.cc index c023498..b0b3b58 100644 --- a/nihil.ucl/tests/boolean.cc +++ b/nihil.ucl/tests/boolean.cc @@ -10,19 +10,36 @@ import nihil.ucl; TEST_CASE("ucl: boolean: construct", "[ucl]") { - auto obj = nihil::ucl::boolean(true); - REQUIRE(object_cast<nihil::ucl::boolean>(obj).value() == true); + auto b = nihil::ucl::boolean(true); + REQUIRE(b == true); } -TEST_CASE("ucl: boolean: compare", "[ucl]") +TEST_CASE("ucl: boolean: default construct", "[ucl]") +{ + auto b = nihil::ucl::boolean(); + REQUIRE(b == false); +} + +TEST_CASE("ucl: boolean: operator==", "[ucl]") { auto b = nihil::ucl::boolean(true); - REQUIRE(b == nihil::ucl::boolean(true)); REQUIRE(b == true); + REQUIRE(b == nihil::ucl::boolean(true)); - REQUIRE(b != nihil::ucl::boolean(false)); REQUIRE(b != false); + REQUIRE(b != nihil::ucl::boolean(false)); +} + +TEST_CASE("ucl: boolean: operator<=>", "[ucl]") +{ + auto b = nihil::ucl::boolean(false); + + REQUIRE(b < true); + REQUIRE(b < nihil::ucl::boolean(true)); + + REQUIRE(b >= false); + REQUIRE(b >= nihil::ucl::boolean(false)); } TEST_CASE("ucl: boolean: parse", "[ucl]") diff --git a/nihil.ucl/tests/integer.cc b/nihil.ucl/tests/integer.cc index da119e6..c7db851 100644 --- a/nihil.ucl/tests/integer.cc +++ b/nihil.ucl/tests/integer.cc @@ -10,20 +10,36 @@ import nihil.ucl; TEST_CASE("ucl: integer: construct", "[ucl]") { - auto obj = nihil::ucl::integer(42); - REQUIRE(object_cast<nihil::ucl::integer>(obj).value() == 42); + auto i = nihil::ucl::integer(42); + REQUIRE(i == 42); } -TEST_CASE("ucl: integer: compare", "[ucl]") +TEST_CASE("ucl: integer: default construct", "[ucl]") +{ + auto i = nihil::ucl::integer(); + REQUIRE(i == 0); +} + +TEST_CASE("ucl: integer: operator==", "[ucl]") { auto i = nihil::ucl::integer(42); + REQUIRE(i == 42); REQUIRE(i == nihil::ucl::integer(42)); + + REQUIRE(i != 1); REQUIRE(i != nihil::ucl::integer(1)); - REQUIRE((i == 42) == true); +} + +TEST_CASE("ucl: integer: operator<=>", "[ucl]") +{ + auto i = nihil::ucl::integer(42); + + REQUIRE(i < 43); + REQUIRE(i < nihil::ucl::integer(43)); - REQUIRE(i > nihil::ucl::integer(40)); - REQUIRE(i > 40); + REQUIRE(i > 1); + REQUIRE(i > nihil::ucl::integer(1)); } TEST_CASE("ucl: parse: integer", "[ucl]") diff --git a/nihil.ucl/tests/real.cc b/nihil.ucl/tests/real.cc index 275684a..d97e767 100644 --- a/nihil.ucl/tests/real.cc +++ b/nihil.ucl/tests/real.cc @@ -16,16 +16,32 @@ TEST_CASE("ucl: real: construct", "[ucl]") Catch::Matchers::WithinRel(42.1)); } -TEST_CASE("ucl: real: compare", "[ucl]") +TEST_CASE("ucl: real: default construct", "[ucl]") { - auto i = nihil::ucl::real(42); + auto i = nihil::ucl::real(); + REQUIRE(i == 0); +} + +TEST_CASE("ucl: real: operator==", "[ucl]") +{ + auto i = nihil::ucl::real(42.5); + + REQUIRE(i == 42.5); + REQUIRE(i == nihil::ucl::real(42.5)); - REQUIRE(i == nihil::ucl::real(42)); + REQUIRE(i != 1); REQUIRE(i != nihil::ucl::real(1)); - REQUIRE((i == 42) == true); +} + +TEST_CASE("ucl: real: operator<=>", "[ucl]") +{ + auto i = nihil::ucl::real(42.5); + + REQUIRE(i < 43); + REQUIRE(i < nihil::ucl::real(43)); - REQUIRE(i > nihil::ucl::real(40)); - REQUIRE(i > 40); + REQUIRE(i > 1); + REQUIRE(i > nihil::ucl::real(1)); } TEST_CASE("ucl: real: parse", "[ucl]") diff --git a/nihil.ucl/tests/string.cc b/nihil.ucl/tests/string.cc index 4385dbb..b702b51 100644 --- a/nihil.ucl/tests/string.cc +++ b/nihil.ucl/tests/string.cc @@ -2,16 +2,106 @@ * This source code is released into the public domain. */ +#include <list> #include <string> +#include <vector> #include <catch2/catch_test_macros.hpp> +#include <ucl.h> import nihil.ucl; -TEST_CASE("ucl: string: construct", "[ucl]") +TEST_CASE("ucl: string: invariants", "[ucl]") { - auto obj = nihil::ucl::string("testing"); - REQUIRE(object_cast<nihil::ucl::string>(obj).value() == "testing"); + using namespace nihil::ucl; + + static_assert(std::same_as<std::string_view, string::value_type>); + REQUIRE(string::ucl_type == object_type::string); + REQUIRE(static_cast<::ucl_type>(string::ucl_type) == UCL_STRING); +} + +TEST_CASE("ucl: string: default construct", "[ucl]") +{ + auto str = nihil::ucl::string(); + REQUIRE(str == ""); +} + +TEST_CASE("ucl: string: construct from string literal", "[ucl]") +{ + auto str = nihil::ucl::string("testing"); + REQUIRE(str == "testing"); +} + +TEST_CASE("ucl: string: construct from std::string", "[ucl]") +{ + auto str = nihil::ucl::string(std::string("testing")); + REQUIRE(str == "testing"); +} + +TEST_CASE("ucl: string: construct from std::string_view", "[ucl]") +{ + auto str = nihil::ucl::string(std::string_view("testing")); + REQUIRE(str == "testing"); +} + +TEST_CASE("ucl: string: construct from contiguous range", "[ucl]") +{ + auto s = std::vector{'t', 'e', 's', 't', 'i', 'n', 'g'}; + auto str = nihil::ucl::string(std::from_range, s); + REQUIRE(str == "testing"); +} + +TEST_CASE("ucl: string: construct from non-contiguous range", "[ucl]") +{ + auto s = std::list{'t', 'e', 's', 't', 'i', 'n', 'g'}; + auto str = nihil::ucl::string(std::from_range, s); + REQUIRE(str == "testing"); +} + +TEST_CASE("ucl: string: construct from contiguous iterator", "[ucl]") +{ + auto s = std::vector{'t', 'e', 's', 't', 'i', 'n', 'g'}; + auto str = nihil::ucl::string(std::ranges::begin(s), + std::ranges::end(s)); + REQUIRE(str == "testing"); +} + +TEST_CASE("ucl: string: construct from non-contiguous iterator", "[ucl]") +{ + auto s = std::list{'t', 'e', 's', 't', 'i', 'n', 'g'}; + auto str = nihil::ucl::string(std::ranges::begin(s), + std::ranges::end(s)); + REQUIRE(str == "testing"); +} + +TEST_CASE("ucl: string: operator==", "[ucl]") +{ + auto str = nihil::ucl::string("testing"); + + REQUIRE(str == nihil::ucl::string("testing")); + REQUIRE(str == std::string_view("testing")); + REQUIRE(str == std::string("testing")); + REQUIRE(str == "testing"); + + REQUIRE(str != nihil::ucl::string("test")); + REQUIRE(str != std::string_view("test")); + REQUIRE(str != std::string("test")); + REQUIRE(str != "test"); +} + +TEST_CASE("ucl: string: operator<=>", "[ucl]") +{ + auto str = nihil::ucl::string("testing"); + + REQUIRE(str < nihil::ucl::string("zzz")); + REQUIRE(str < std::string_view("zzz")); + REQUIRE(str < std::string("zzz")); + REQUIRE(str < "zzz"); + + REQUIRE(str > nihil::ucl::string("aaa")); + REQUIRE(str > std::string_view("aaa")); + REQUIRE(str > std::string("aaa")); + REQUIRE(str > "aaa"); } TEST_CASE("ucl: string: parse", "[ucl]") |
