diff --git a/DEPENDENCIES b/DEPENDENCIES index 92d46402..a38d5e52 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -1,6 +1,6 @@ vendorpull https://github.com/sourcemeta/vendorpull dea311b5bfb53b6926a4140267959ae334d3ecf4 noa https://github.com/sourcemeta/noa caad2e1ceedf9fd1a18686a6a6d1e2b9757ead75 -jsontoolkit https://github.com/sourcemeta/jsontoolkit aae184d87d6c4efe600cfb3c85163eda61f207c4 +jsontoolkit https://github.com/sourcemeta/jsontoolkit c8c1f6bb8530b0fe0aa83bdfccb8ccb8db5e54ea googletest https://github.com/google/googletest a7f443b80b105f940225332ed3c31f2790092f47 googlebenchmark https://github.com/google/benchmark 378fe693a1ef51500db21b11ff05a8018c5f0e55 jsonschema-test-suite https://github.com/json-schema-org/JSON-Schema-Test-Suite c2badb1298a8698f86dadf1aea7b44b3a894e5ac diff --git a/src/evaluator/dispatch.inc.h b/src/evaluator/dispatch.inc.h index 2998c062..e8fe8128 100644 --- a/src/evaluator/dispatch.inc.h +++ b/src/evaluator/dispatch.inc.h @@ -33,7 +33,7 @@ switch (static_cast(instruction.index())) { assert(assertion.value.size() > 1); // Otherwise there is no way the instance can satisfy it anyway - if (assertion.value.size() <= target.size()) { + if (assertion.value.size() <= target.object_size()) { result = true; for (const auto &property : assertion.value) { if (!target.defines(property)) { @@ -125,8 +125,9 @@ switch (static_cast(instruction.index())) { assert(!maximum.has_value() || maximum.value() >= minimum); // Require early breaking assert(!std::get<2>(assertion.value)); - result = target.type() == JSON::Type::String && target.size() >= minimum && - (!maximum.has_value() || target.size() <= maximum.value()); + result = target.type() == JSON::Type::String && + target.string_size() >= minimum && + (!maximum.has_value() || target.string_size() <= maximum.value()); EVALUATE_END(assertion, AssertionTypeStringBounded); } @@ -138,8 +139,9 @@ switch (static_cast(instruction.index())) { assert(!maximum.has_value() || maximum.value() >= minimum); // Require early breaking assert(!std::get<2>(assertion.value)); - result = target.type() == JSON::Type::Array && target.size() >= minimum && - (!maximum.has_value() || target.size() <= maximum.value()); + result = target.type() == JSON::Type::Array && + target.array_size() >= minimum && + (!maximum.has_value() || target.array_size() <= maximum.value()); EVALUATE_END(assertion, AssertionTypeArrayBounded); } @@ -151,8 +153,9 @@ switch (static_cast(instruction.index())) { assert(!maximum.has_value() || maximum.value() >= minimum); // Require early breaking assert(!std::get<2>(assertion.value)); - result = target.type() == JSON::Type::Object && target.size() >= minimum && - (!maximum.has_value() || target.size() <= maximum.value()); + result = target.type() == JSON::Type::Object && + target.object_size() >= minimum && + (!maximum.has_value() || target.object_size() <= maximum.value()); EVALUATE_END(assertion, AssertionTypeObjectBounded); } @@ -176,25 +179,25 @@ switch (static_cast(instruction.index())) { case IS_INSTRUCTION(AssertionArraySizeLess): { EVALUATE_BEGIN(assertion, AssertionArraySizeLess, target.is_array()); - result = (target.size() < assertion.value); + result = (target.array_size() < assertion.value); EVALUATE_END(assertion, AssertionArraySizeLess); } case IS_INSTRUCTION(AssertionArraySizeGreater): { EVALUATE_BEGIN(assertion, AssertionArraySizeGreater, target.is_array()); - result = (target.size() > assertion.value); + result = (target.array_size() > assertion.value); EVALUATE_END(assertion, AssertionArraySizeGreater); } case IS_INSTRUCTION(AssertionObjectSizeLess): { EVALUATE_BEGIN(assertion, AssertionObjectSizeLess, target.is_object()); - result = (target.size() < assertion.value); + result = (target.object_size() < assertion.value); EVALUATE_END(assertion, AssertionObjectSizeLess); } case IS_INSTRUCTION(AssertionObjectSizeGreater): { EVALUATE_BEGIN(assertion, AssertionObjectSizeGreater, target.is_object()); - result = (target.size() > assertion.value); + result = (target.object_size() > assertion.value); EVALUATE_END(assertion, AssertionObjectSizeGreater); } @@ -370,7 +373,7 @@ switch (static_cast(instruction.index())) { assert(!assertion.children.empty()); result = target.empty(); const auto prefixes{assertion.children.size() - 1}; - const auto array_size{target.size()}; + const auto array_size{target.array_size()}; if (!result) [[likely]] { const auto pointer{array_size == prefixes ? prefixes @@ -395,7 +398,7 @@ switch (static_cast(instruction.index())) { assert(!assertion.children.empty()); result = target.empty(); const auto prefixes{assertion.children.size() - 1}; - const auto array_size{target.size()}; + const auto array_size{target.array_size()}; if (!result) [[likely]] { const auto pointer{array_size == prefixes ? prefixes @@ -481,7 +484,7 @@ switch (static_cast(instruction.index())) { case IS_INSTRUCTION(LogicalWhenArraySizeGreater): { EVALUATE_BEGIN(logical, LogicalWhenArraySizeGreater, - target.is_array() && target.size() > logical.value); + target.is_array() && target.array_size() > logical.value); result = true; for (const auto &child : logical.children) { if (!EVALUATE_RECURSE(child, target)) { @@ -1096,7 +1099,7 @@ switch (static_cast(instruction.index())) { // Otherwise if the number of properties in the instance // is larger than the whitelist, then it already violated // the whitelist? - if (target.size() <= loop.value.size()) { + if (target.object_size() <= loop.value.size()) { result = true; for (const auto &entry : target.as_object()) { if (!loop.value.contains(entry.first)) { @@ -1247,7 +1250,7 @@ switch (static_cast(instruction.index())) { } } #else - for (std::size_t index = 0; index < target.size(); index++) { + for (std::size_t index = 0; index < target.array_size(); index++) { if (track) { context.instance_location.push_back(index); } @@ -1273,10 +1276,10 @@ switch (static_cast(instruction.index())) { case IS_INSTRUCTION(LoopItemsFrom): { EVALUATE_BEGIN(loop, LoopItemsFrom, - target.is_array() && loop.value < target.size()); + target.is_array() && loop.value < target.array_size()); assert(!loop.children.empty()); result = true; - for (std::size_t index = loop.value; index < target.size(); index++) { + for (std::size_t index = loop.value; index < target.array_size(); index++) { if (track) { context.instance_location.push_back(index); } @@ -1304,7 +1307,7 @@ switch (static_cast(instruction.index())) { assert(!loop.children.empty()); result = true; - for (std::size_t index = 0; index < target.size(); index++) { + for (std::size_t index = 0; index < target.array_size(); index++) { if (context.is_evaluated(index)) { continue; } @@ -1383,7 +1386,7 @@ switch (static_cast(instruction.index())) { result = minimum == 0 && target.empty(); auto match_count{std::numeric_limits::min()}; - for (std::size_t index = 0; index < target.size(); index++) { + for (std::size_t index = 0; index < target.array_size(); index++) { if (track) { context.instance_location.push_back(index); } diff --git a/vendor/jsontoolkit/src/json/include/sourcemeta/jsontoolkit/json_value.h b/vendor/jsontoolkit/src/json/include/sourcemeta/jsontoolkit/json_value.h index 6092f51d..fdde0370 100644 --- a/vendor/jsontoolkit/src/json/include/sourcemeta/jsontoolkit/json_value.h +++ b/vendor/jsontoolkit/src/json/include/sourcemeta/jsontoolkit/json_value.h @@ -799,6 +799,47 @@ class SOURCEMETA_JSONTOOLKIT_JSON_EXPORT JSON { /// ``` [[nodiscard]] auto size() const -> std::size_t; + /// If the input JSON instance is a string, return its logical length. + /// + /// For example: + /// + /// ```cpp + /// #include + /// #include + /// + /// const sourcemeta::jsontoolkit::JSON my_string{"foo"}; + /// assert(my_string.string_size() == 3); + /// ``` + [[nodiscard]] auto string_size() const -> std::size_t; + + /// If the input JSON instance is an array, return its number of elements. + /// + /// For example: + /// + /// ```cpp + /// #include + /// #include + /// + /// const sourcemeta::jsontoolkit::JSON my_array = + /// sourcemeta::jsontoolkit::parse("[ 1, 2 ]"); + /// assert(my_array.array_size() == 2); + /// ``` + [[nodiscard]] auto array_size() const -> std::size_t; + + /// If the input JSON instance is an object, return its number of pairs. + /// + /// For example: + /// + /// ```cpp + /// #include + /// #include + /// + /// const sourcemeta::jsontoolkit::JSON my_object = + /// sourcemeta::jsontoolkit::parse("{ \"foo\": 1 }"); + /// assert(my_object.object_size() == 1); + /// ``` + [[nodiscard]] auto object_size() const -> std::size_t; + /// If the input JSON instance is string, input JSON instance is a string, /// return its number of bytes. For example: /// diff --git a/vendor/jsontoolkit/src/json/json_value.cc b/vendor/jsontoolkit/src/json/json_value.cc index 69828ee4..45b554d6 100644 --- a/vendor/jsontoolkit/src/json/json_value.cc +++ b/vendor/jsontoolkit/src/json/json_value.cc @@ -355,15 +355,29 @@ auto JSON::operator-=(const JSON &substractive) -> JSON & { [[nodiscard]] auto JSON::size() const -> std::size_t { if (this->is_object()) { - return std::get(this->data).data.size(); + return this->object_size(); } else if (this->is_array()) { - return std::get(this->data).data.size(); + return this->array_size(); } else { - assert(this->is_string()); - return JSON::size(std::get(this->data)); + return this->string_size(); } } +[[nodiscard]] auto JSON::string_size() const -> std::size_t { + assert(this->is_string()); + return JSON::size(std::get(this->data)); +} + +[[nodiscard]] auto JSON::array_size() const -> std::size_t { + assert(this->is_array()); + return std::get(this->data).data.size(); +} + +[[nodiscard]] auto JSON::object_size() const -> std::size_t { + assert(this->is_object()); + return std::get(this->data).data.size(); +} + [[nodiscard]] auto JSON::byte_size() const -> std::size_t { assert(this->is_string()); return std::get(this->data).size();