From 0bbb0da5222db2e9c666b508c936508086bd0449 Mon Sep 17 00:00:00 2001 From: res0nance Date: Wed, 24 Aug 2022 01:02:28 +0800 Subject: [PATCH 01/25] ci: run on main branch and update nlohmann-json version --- .github/workflows/github-actions.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/github-actions.yml b/.github/workflows/github-actions.yml index 5a7d96d..42a9927 100644 --- a/.github/workflows/github-actions.yml +++ b/.github/workflows/github-actions.yml @@ -6,6 +6,7 @@ on: - develop - master - release/* + - main pull_request: jobs: @@ -21,7 +22,7 @@ jobs: with: repository: nlohmann/json path: nlohmann-json - ref: release/3.10.2 + ref: v3.11.2 - name: Build and install nlohmann json run: | cd nlohmann-json From d2210f65dad4672b3fbaa618437a0943a240392c Mon Sep 17 00:00:00 2001 From: res0nance Date: Wed, 24 Aug 2022 01:17:44 +0800 Subject: [PATCH 02/25] chore: use to_string() to avoid warning --- src/json-validator.cpp | 2 +- src/nlohmann/json-schema.hpp | 4 ++-- test/binary-validation.cpp | 2 +- test/uri.cpp | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/json-validator.cpp b/src/json-validator.cpp index 3ffd087..c7c5f75 100644 --- a/src/json-validator.cpp +++ b/src/json-validator.cpp @@ -179,7 +179,7 @@ public: auto fragment = new_uri.pointer(); // is there a reference looking for this unknown-keyword, which is thus no longer a unknown keyword but a schema - auto unresolved = file.unresolved.find(fragment); + auto unresolved = file.unresolved.find(fragment.to_string()); if (unresolved != file.unresolved.end()) schema::make(value, this, {}, {{new_uri}}); else { // no, nothing ref'd it, keep for later diff --git a/src/nlohmann/json-schema.hpp b/src/nlohmann/json-schema.hpp index ebe7cef..07befd3 100644 --- a/src/nlohmann/json-schema.hpp +++ b/src/nlohmann/json-schema.hpp @@ -61,7 +61,7 @@ protected: std::tuple as_tuple() const { - return std::make_tuple(urn_, scheme_, authority_, path_, identifier_ != "" ? identifier_ : pointer_); + return std::make_tuple(urn_, scheme_, authority_, path_, identifier_ != "" ? identifier_ : pointer_.to_string()); } public: @@ -80,7 +80,7 @@ public: std::string fragment() const { if (identifier_ == "") - return pointer_; + return pointer_.to_string(); else return identifier_; } diff --git a/test/binary-validation.cpp b/test/binary-validation.cpp index 01392cf..4a9c7ea 100644 --- a/test/binary-validation.cpp +++ b/test/binary-validation.cpp @@ -163,7 +163,7 @@ int main() val.set_root_schema(array_of_types_without_binary); val.validate({{"something", binary}}, err); EXPECT_EQ(err.failed_pointers.size(), 1); - EXPECT_EQ(err.failed_pointers[0], "/something"); + EXPECT_EQ(err.failed_pointers[0].to_string(), "/something"); err.reset(); // check that without content callback you get exception with schema with contentEncoding or contentMeditType diff --git a/test/uri.cpp b/test/uri.cpp index 9083cd3..38c81ee 100644 --- a/test/uri.cpp +++ b/test/uri.cpp @@ -75,11 +75,11 @@ static void pointer_plain_name(json_uri start, a = a.derive("#foo/looks_like_json/poiner/but/isnt"); EXPECT_EQ(a, full + " # foo/looks_like_json/poiner/but/isnt"); EXPECT_EQ(a.identifier(), "foo/looks_like_json/poiner/but/isnt"); - EXPECT_EQ(a.pointer(), ""); + EXPECT_EQ(a.pointer().to_string(), ""); a = a.derive("#/looks_like_json/poiner/and/it/is"); EXPECT_EQ(a, full + " # /looks_like_json/poiner/and/it/is"); - EXPECT_EQ(a.pointer(), "/looks_like_json/poiner/and/it/is"); + EXPECT_EQ(a.pointer().to_string(), "/looks_like_json/poiner/and/it/is"); EXPECT_EQ(a.identifier(), ""); } From 87252bb5ce4d80d519acdeb25a90ccb914d8bd0a Mon Sep 17 00:00:00 2001 From: res0nance Date: Thu, 25 Aug 2022 00:08:41 +0800 Subject: [PATCH 03/25] ci: add CI for the minimum supported version --- .github/workflows/github-actions.yml | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/.github/workflows/github-actions.yml b/.github/workflows/github-actions.yml index 42a9927..c5cf5b2 100644 --- a/.github/workflows/github-actions.yml +++ b/.github/workflows/github-actions.yml @@ -37,3 +37,30 @@ jobs: run: cmake --build build --target all -j$(nproc) - name: test run: cd build && ctest + build_and_test_min_version: + runs-on: ubuntu-latest + container: ghcr.io/nlohmann/json-ci:v1.0.0 + steps: + - run: echo "🎉 The job was automatically triggered by a ${{ github.event_name }} event." + - run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by GitHub." + - run: echo "🔎 Branch name is ${{ github.ref }} and repository is ${{ github.repository }}." + - name: Clone nlohmann json + uses: actions/checkout@master + with: + repository: nlohmann/json + path: nlohmann-json + ref: v3.8.0 + - name: Build and install nlohmann json + run: | + cd nlohmann-json + cmake -S . -B build + cmake --build build --target install -j$(nproc) + cd .. + - name: Clone json-schema-validator + uses: actions/checkout@v2 + - name: cmake + run: cmake -S . -B build + - name: build + run: cmake --build build --target all -j$(nproc) + - name: test + run: cd build && ctest From 793b85ce12b2e19ae14193514bc2ff4bd961e879 Mon Sep 17 00:00:00 2001 From: res0nance Date: Fri, 26 Aug 2022 20:28:42 +0800 Subject: [PATCH 04/25] chore: use to_string() for json_pointers --- src/json-patch.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/json-patch.cpp b/src/json-patch.cpp index d0cd2e4..3203543 100644 --- a/src/json-patch.cpp +++ b/src/json-patch.cpp @@ -85,19 +85,19 @@ json_patch::json_patch(const json &patch) json_patch &json_patch::add(const json::json_pointer &ptr, json value) { - j_.push_back(json{{"op", "add"}, {"path", ptr}, {"value", std::move(value)}}); + j_.push_back(json{{"op", "add"}, {"path", ptr.to_string()}, {"value", std::move(value)}}); return *this; } json_patch &json_patch::replace(const json::json_pointer &ptr, json value) { - j_.push_back(json{{"op", "replace"}, {"path", ptr}, {"value", std::move(value)}}); + j_.push_back(json{{"op", "replace"}, {"path", ptr.to_string()}, {"value", std::move(value)}}); return *this; } json_patch &json_patch::remove(const json::json_pointer &ptr) { - j_.push_back(json{{"op", "remove"}, {"path", ptr}}); + j_.push_back(json{{"op", "remove"}, {"path", ptr.to_string()}}); return *this; } From c7325ae9329e811c7275add8b0c4c732b690f181 Mon Sep 17 00:00:00 2001 From: res0nance Date: Fri, 26 Aug 2022 19:20:08 +0800 Subject: [PATCH 05/25] ci: update build container to v2.4.0 --- .github/workflows/github-actions.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/github-actions.yml b/.github/workflows/github-actions.yml index c5cf5b2..07e4ca6 100644 --- a/.github/workflows/github-actions.yml +++ b/.github/workflows/github-actions.yml @@ -12,7 +12,7 @@ on: jobs: build_and_test: runs-on: ubuntu-latest - container: ghcr.io/nlohmann/json-ci:v1.0.0 + container: ghcr.io/nlohmann/json-ci:v2.4.0 steps: - run: echo "🎉 The job was automatically triggered by a ${{ github.event_name }} event." - run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by GitHub." @@ -39,7 +39,7 @@ jobs: run: cd build && ctest build_and_test_min_version: runs-on: ubuntu-latest - container: ghcr.io/nlohmann/json-ci:v1.0.0 + container: ghcr.io/nlohmann/json-ci:v2.4.0 steps: - run: echo "🎉 The job was automatically triggered by a ${{ github.event_name }} event." - run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by GitHub." From 5ec1961439b59c76e5cfec650e5641104dd409a4 Mon Sep 17 00:00:00 2001 From: res0nance Date: Fri, 26 Aug 2022 20:19:38 +0800 Subject: [PATCH 06/25] cmake: add option to disable installing targets --- CMakeLists.txt | 71 +++++++++++++++++++++++++++----------------------- 1 file changed, 38 insertions(+), 33 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e6aff61..6ca2542 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,6 +2,7 @@ cmake_minimum_required(VERSION 3.2) option(JSON_VALIDATOR_BUILD_TESTS "Build tests" ON) option(JSON_VALIDATOR_BUILD_EXAMPLES "Build examples" ON) +option(JSON_VALIDATOR_INSTALL "Install target" ON) option(JSON_VALIDATOR_HUNTER "Enable Hunter package manager support" OFF) if(JSON_VALIDATOR_HUNTER) @@ -95,14 +96,16 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") endif() endif() -install(TARGETS nlohmann_json_schema_validator - EXPORT ${PROJECT_NAME}Targets - LIBRARY DESTINATION lib - ARCHIVE DESTINATION lib - RUNTIME DESTINATION bin) +if(JSON_VALIDATOR_INSTALL) + install(TARGETS nlohmann_json_schema_validator + EXPORT ${PROJECT_NAME}Targets + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib + RUNTIME DESTINATION bin) -install(FILES src/nlohmann/json-schema.hpp - DESTINATION include/nlohmann) + install(FILES src/nlohmann/json-schema.hpp + DESTINATION include/nlohmann) +endif() if (JSON_VALIDATOR_BUILD_EXAMPLES) # simple nlohmann_json_schema_validator-executable @@ -127,32 +130,34 @@ endif() # Set Up the Project Targets and Config Files for CMake -# Set the install path to the cmake config files (Relative, so install works correctly under Hunter as well) -set(INSTALL_CMAKE_DIR "lib/cmake/${PROJECT_NAME}") -set(INSTALL_CMAKEDIR_ROOT share/cmake) +if(JSON_VALIDATOR_INSTALL) + # Set the install path to the cmake config files (Relative, so install works correctly under Hunter as well) + set(INSTALL_CMAKE_DIR "lib/cmake/${PROJECT_NAME}") + set(INSTALL_CMAKEDIR_ROOT share/cmake) -# Install Targets -install(EXPORT ${PROJECT_NAME}Targets - FILE ${PROJECT_NAME}Targets.cmake - DESTINATION "${INSTALL_CMAKE_DIR}") + # Install Targets + install(EXPORT ${PROJECT_NAME}Targets + FILE ${PROJECT_NAME}Targets.cmake + DESTINATION "${INSTALL_CMAKE_DIR}") -include(CMakePackageConfigHelpers) -write_basic_package_version_file( - ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake - VERSION ${PROJECT_VERSION} - COMPATIBILITY SameMajorVersion - ) - -configure_package_config_file( - ${PROJECT_SOURCE_DIR}/${PROJECT_NAME}Config.cmake.in - ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake - INSTALL_DESTINATION ${INSTALL_CMAKEDIR_ROOT}/${PROJECT_NAME} - ) - -install( - FILES - ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake + include(CMakePackageConfigHelpers) + write_basic_package_version_file( ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake - DESTINATION - ${INSTALL_CMAKE_DIR} - ) + VERSION ${PROJECT_VERSION} + COMPATIBILITY SameMajorVersion + ) + + configure_package_config_file( + ${PROJECT_SOURCE_DIR}/${PROJECT_NAME}Config.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake + INSTALL_DESTINATION ${INSTALL_CMAKEDIR_ROOT}/${PROJECT_NAME} + ) + + install( + FILES + ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake + ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake + DESTINATION + ${INSTALL_CMAKE_DIR} + ) +endif() \ No newline at end of file From e1e48ddbe08c0fdad66600bd47fb815b5a8465a6 Mon Sep 17 00:00:00 2001 From: Chris Wright Date: Tue, 5 Jul 2022 17:47:23 +0100 Subject: [PATCH 07/25] Replace dynamic_cast with member functions (#210) --- src/json-validator.cpp | 49 +++++++++++++++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 10 deletions(-) diff --git a/src/json-validator.cpp b/src/json-validator.cpp index c7c5f75..34076c2 100644 --- a/src/json-validator.cpp +++ b/src/json-validator.cpp @@ -40,6 +40,16 @@ protected: root_schema *root_; json default_value_ = nullptr; +protected: + virtual std::shared_ptr make_for_default_( + std::shared_ptr<::schema> & /* sch */, + root_schema * /* root */, + std::vector & /* uris */, + nlohmann::json & /* default_value */) const + { + return nullptr; + }; + public: virtual ~schema() = default; @@ -92,6 +102,21 @@ class schema_ref : public schema return default_value_; } +protected: + virtual std::shared_ptr make_for_default_( + std::shared_ptr<::schema> &sch, + root_schema *root, + std::vector &uris, + nlohmann::json &default_value) const override + { + // create a new reference schema using the original reference (which will be resolved later) + // to store this overloaded default value #209 + auto result = std::make_shared(uris[0].to_string(), root); + result->set_target(sch, true); + result->set_default_value(default_value); + return result; + }; + public: schema_ref(const std::string &id, root_schema *root) : schema(root), id_(id) {} @@ -509,6 +534,18 @@ class type_schema : public schema } } +protected: + virtual std::shared_ptr make_for_default_( + std::shared_ptr<::schema> & /* sch */, + root_schema * /* root */, + std::vector & /* uris */, + nlohmann::json &default_value) const override + { + auto result = std::make_shared(*this); + result->set_default_value(default_value); + return result; + }; + public: type_schema(json &sch, root_schema *root, @@ -1289,16 +1326,8 @@ std::shared_ptr schema::make(json &schema, attr = schema.find("default"); if (attr != schema.end()) { // copy the referenced schema depending on the underlying type and modify the default value - if (dynamic_cast(sch.get())) { - // create a new reference schema use the original reference (which will be resolved later) - // to store this overloaed default value #209 - auto overloaded_ref_sch = std::make_shared(uris[0].to_string(), root); - overloaded_ref_sch->set_target(sch, true); - overloaded_ref_sch->set_default_value(attr.value()); - sch = overloaded_ref_sch; - } else if (auto *type_sch = dynamic_cast(sch.get())) { - sch = std::make_shared(*type_sch); - sch->set_default_value(attr.value()); + if (auto new_sch = sch->make_for_default_(sch, root, uris, attr.value())) { + sch = new_sch; } schema.erase(attr); } From 1c126b6f3db0c3a4a1d02d61d82f738db3b8afdd Mon Sep 17 00:00:00 2001 From: Erwin Nindl Date: Fri, 2 Sep 2022 13:13:58 +0200 Subject: [PATCH 08/25] Updates conanfile.py --- conanfile.py | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/conanfile.py b/conanfile.py index d886875..6bec115 100644 --- a/conanfile.py +++ b/conanfile.py @@ -15,7 +15,6 @@ def get_version(): except: return None - class JsonSchemaValidatorConan(ConanFile): name = 'JsonSchemaValidator' version = get_version() @@ -24,34 +23,49 @@ class JsonSchemaValidatorConan(ConanFile): settings = 'os', 'compiler', 'build_type', 'arch' options = { 'shared': [True, False], - 'fPIC': [True, False] + 'fPIC': [True, False], + 'build_examples': [True, False], + 'build_tests': [True, False] } default_options = { 'shared': False, - 'fPIC': True + 'fPIC': True, + 'build_examples': True, + 'build_tests': False } - generators = "cmake" + generators = "CMakeDeps" exports_sources = [ 'CMakeLists.txt', 'nlohmann_json_schema_validatorConfig.cmake.in', 'src/*', 'app/*', + 'test/*', ] - requires = ( - 'nlohmann_json/3.7.3' + 'nlohmann_json/3.11.2' ) + _cmake = None + + def _configure_cmake(self): + if self._cmake: + return self._cmake + self._cmake = CMake(self) + self._cmake.definitions['JSON_VALIDATOR_BUILD_EXAMPLES'] = self.options.build_examples + self._cmake.definitions['JSON_VALIDATOR_BUILD_TESTS'] = self.options.build_tests + self._cmake.configure() + return self._cmake + + def layout(self): + build_type = str(self.settings.build_type).lower() + self.folders.build = "build-{}".format(build_type) def build(self): - cmake = CMake(self) - cmake.definitions['nlohmann_json_DIR'] = os.path.join(self.deps_cpp_info['nlohmann_json'].rootpath, 'include') - cmake.definitions['JSON_VALIDATOR_BUILD_EXAMPLES'] = True - cmake.definitions['JSON_VALIDATOR_BUILD_TESTS'] = False + cmake = self._configure_cmake() cmake.configure() cmake.build() def package(self): - cmake = CMake(self) + cmake = self._configure_cmake() cmake.install() def package_info(self): From 0efd3ae507d2e72716df341d80bba0b4195e0f16 Mon Sep 17 00:00:00 2001 From: Erwin Nindl Date: Fri, 2 Sep 2022 22:55:56 +0200 Subject: [PATCH 09/25] Build conan package with Github actions --- .github/workflows/github-actions.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/.github/workflows/github-actions.yml b/.github/workflows/github-actions.yml index 07e4ca6..d5d5c42 100644 --- a/.github/workflows/github-actions.yml +++ b/.github/workflows/github-actions.yml @@ -64,3 +64,20 @@ jobs: run: cmake --build build --target all -j$(nproc) - name: test run: cd build && ctest + build_conan: + runs-on: ubuntu-latest + container: ghcr.io/nlohmann/json-ci:v2.4.0 + steps: + - run: echo "🎉 The job was automatically triggered by a ${{ github.event_name }} event." + - run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by GitHub." + - run: echo "🔎 Branch name is ${{ github.ref }} and repository is ${{ github.repository }}." + - name: Clone json-schema-validator + uses: actions/checkout@v3 + - uses: actions/setup-python@v4 + with: + python-version: '3.10' + - run: python -m pip install --upgrade conan + - run: conan config init + - run: conan profile update settings.compiler.libcxx=libstdc++11 default + - name: conan create package + run: conan create . From 1b27d5cf016457b7290361d83ba683c5a47e9b2d Mon Sep 17 00:00:00 2001 From: Francesco Biscani Date: Tue, 21 Jun 2022 11:13:25 +0200 Subject: [PATCH 10/25] Increase the verbosity of the error message produced when there are undefined references. --- src/json-validator.cpp | 31 ++++++++++++++++++++++++++----- test/issue-98.cpp | 3 ++- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/src/json-validator.cpp b/src/json-validator.cpp index 34076c2..7f34553 100644 --- a/src/json-validator.cpp +++ b/src/json-validator.cpp @@ -14,6 +14,7 @@ #include #include #include +#include using nlohmann::json; using nlohmann::json_patch; @@ -308,11 +309,31 @@ public: break; } while (1); - for (const auto &file : files_) - if (file.second.unresolved.size() != 0) + for (const auto &file : files_) { + if (file.second.unresolved.size() != 0) { + // Build a representation of the undefined + // references as a list of comma-separated strings. + auto n_urefs = file.second.unresolved.size(); + std::string urefs = "["; + + decltype(n_urefs) counter = 0; + for (const auto &p : file.second.unresolved) { + urefs += p.first; + + if (counter != n_urefs - 1u) { + urefs += ", "; + } + + ++counter; + } + + urefs += "]"; + throw std::invalid_argument("after all files have been parsed, '" + (file.first == "" ? "" : file.first) + - "' has still undefined references."); + "' has still the following undefined references: " + urefs); + } + } } void validate(const json::json_pointer &ptr, @@ -929,8 +950,8 @@ class boolean : public schema { if (!true_) { // false schema // empty array - //switch (instance.type()) { - //case json::value_t::array: + // switch (instance.type()) { + // case json::value_t::array: // if (instance.size() != 0) // valid false-schema // e.error(ptr, instance, "false-schema required empty array"); // return; diff --git a/test/issue-98.cpp b/test/issue-98.cpp index 088b324..63a824c 100644 --- a/test/issue-98.cpp +++ b/test/issue-98.cpp @@ -8,7 +8,8 @@ int main(void) try { validator.set_root_schema(nlBase); // this line will log the caught exception } catch (const std::exception &e) { - if (std::string("after all files have been parsed, '' has still undefined references.") == e.what()) + + if (std::string("after all files have been parsed, '' has still the following undefined references: [/unknown/keywords]") == e.what()) return EXIT_SUCCESS; } return EXIT_FAILURE; From 5b3200f83979519a41ffd6a43e6ae1f2a8dff3df Mon Sep 17 00:00:00 2001 From: Sam V Date: Tue, 6 Sep 2022 20:02:45 +0200 Subject: [PATCH 11/25] Use find_dependency in PackageConfig file pboettch/json-schema-validator#207 --- nlohmann_json_schema_validatorConfig.cmake.in | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/nlohmann_json_schema_validatorConfig.cmake.in b/nlohmann_json_schema_validatorConfig.cmake.in index c47fb16..88960cc 100644 --- a/nlohmann_json_schema_validatorConfig.cmake.in +++ b/nlohmann_json_schema_validatorConfig.cmake.in @@ -1,6 +1,7 @@ @PACKAGE_INIT@ -find_package(nlohmann_json 3.8.0 REQUIRED) +include(CMakeFindDependencyMacro) +find_dependency(nlohmann_json) include("${CMAKE_CURRENT_LIST_DIR}/nlohmann_json_schema_validatorTargets.cmake") check_required_components( From 1063c9adbafc25f5a14bae15c3babdb039de86c6 Mon Sep 17 00:00:00 2001 From: Sam V Date: Tue, 20 Sep 2022 18:06:05 +0200 Subject: [PATCH 12/25] Make JSON_VALIDATOR_BUILD_EXAMPLES and JSON_VALIDATOR_BUILD_TESTS overridable by user Resolves pboettch/json-schema-validator#195 --- CMakeLists.txt | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6ca2542..d0f0ec4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,5 @@ cmake_minimum_required(VERSION 3.2) -option(JSON_VALIDATOR_BUILD_TESTS "Build tests" ON) -option(JSON_VALIDATOR_BUILD_EXAMPLES "Build examples" ON) option(JSON_VALIDATOR_INSTALL "Install target" ON) option(JSON_VALIDATOR_HUNTER "Enable Hunter package manager support" OFF) @@ -48,16 +46,11 @@ set_target_properties(nlohmann_json_schema_validator # disable tests and examples if project is not super project if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) # I am top-level project. - set(JSON_VALIDATOR_IS_TOP_LEVEL TRUE) + set(JSON_VALIDATOR_IS_TOP_LEVEL ON) endif() -if(JSON_VALIDATOR_IS_TOP_LEVEL) - set(JSON_VALIDATOR_BUILD_TESTS ON) - set(JSON_VALIDATOR_BUILD_EXAMPLES ON) -else() - set(JSON_VALIDATOR_BUILD_TESTS OFF) - set(JSON_VALIDATOR_BUILD_EXAMPLES OFF) -endif() +option(JSON_VALIDATOR_BUILD_TESTS "Build tests" ${JSON_VALIDATOR_IS_TOP_LEVEL}) +option(JSON_VALIDATOR_BUILD_EXAMPLES "Build examples" ${JSON_VALIDATOR_IS_TOP_LEVEL}) if(NOT TARGET nlohmann_json::nlohmann_json) find_package(nlohmann_json REQUIRED) From e39c1aef5bf10c6dfd3eb144677401fd39b5465a Mon Sep 17 00:00:00 2001 From: sebasfalcone Date: Wed, 21 Sep 2022 17:07:47 -0300 Subject: [PATCH 13/25] CL: - Added tests for URI format - Added URI format validationCL: --- src/string-format-check.cpp | 118 ++++++++++++++++++++++++++++-- test/string-format-check-test.cpp | 16 ++++ 2 files changed, 129 insertions(+), 5 deletions(-) diff --git a/src/string-format-check.cpp b/src/string-format-check.cpp index 98954d9..1a623fc 100644 --- a/src/string-format-check.cpp +++ b/src/string-format-check.cpp @@ -84,10 +84,10 @@ void rfc3339_time_check(const std::string &value) } /** - * @todo Could be made more exact by querying a leap second database and choosing the - * correct maximum in {58,59,60}. This current solution might match some invalid dates - * but it won't lead to false negatives. This only works if we know the full date, however - */ + * @todo Could be made more exact by querying a leap second database and choosing the + * correct maximum in {58,59,60}. This current solution might match some invalid dates + * but it won't lead to false negatives. This only works if we know the full date, however + */ auto day_minutes = hour * 60 + minute - (offsetHour * 60 + offsetMinute); if (day_minutes < 0) @@ -126,7 +126,7 @@ void rfc3339_time_check(const std::string &value) * @endverbatim * NOTE: Per [ABNF] and ISO8601, the "T" and "Z" characters in this * syntax may alternatively be lower case "t" or "z" respectively. -*/ + */ void rfc3339_date_time_check(const std::string &value) { const static std::regex dateTimeRegex{R"(^([0-9]{4}\-[0-9]{2}\-[0-9]{2})[Tt]([0-9]{2}\:[0-9]{2}\:[0-9]{2}(?:\.[0-9]+)?(?:[Zz]|(?:\+|\-)[0-9]{2}\:[0-9]{2}))$)"}; @@ -265,6 +265,112 @@ const std::string dotAtom{"(?:" + atext + R"(+(?:\.)" + atext + "+)*)"}; const std::string stackoverflowMagicPart{R"((?:[[:alnum:]](?:[[:alnum:]-]*[[:alnum:]])?\.)+)" R"([[:alnum:]](?:[[:alnum:]-]*[[:alnum:]])?)"}; const std::string email{"(?:" + dotAtom + "|" + quotedString + ")@(?:" + stackoverflowMagicPart + "|" + domainLiteral + ")"}; + +/** + * @see + * + * @verbatim + * URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ] + * + * hier-part = "//" authority path-abempty + * / path-absolute + * / path-rootless + * / path-empty + * + * URI-reference = URI / relative-ref + * + * absolute-URI = scheme ":" hier-part [ "?" query ] + * + * relative-ref = relative-part [ "?" query ] [ "#" fragment ] + * + * relative-part = "//" authority path-abempty + * / path-absolute + * / path-noscheme + * / path-empty + * + * scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) + * + * authority = [ userinfo "@" ] host [ ":" port ] + * userinfo = *( unreserved / pct-encoded / sub-delims / ":" ) + * host = IP-literal / IPv4address / reg-name + * port = *DIGIT + * + * IP-literal = "[" ( IPv6address / IPvFuture ) "]" + * + * IPvFuture = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" ) + * + * IPv6address = 6( h16 ":" ) ls32 + * / "::" 5( h16 ":" ) ls32 + * / [ h16 ] "::" 4( h16 ":" ) ls32 + * / [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32 + * / [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32 + * / [ *3( h16 ":" ) h16 ] "::" h16 ":" ls32 + * / [ *4( h16 ":" ) h16 ] "::" ls32 + * / [ *5( h16 ":" ) h16 ] "::" h16 + * / [ *6( h16 ":" ) h16 ] "::" + * + * h16 = 1*4HEXDIG + * ls32 = ( h16 ":" h16 ) / IPv4address + * IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet + * dec-octet = DIGIT ; 0-9 + * / %x31-39 DIGIT ; 10-99 + * / "1" 2DIGIT ; 100-199 + * / "2" %x30-34 DIGIT ; 200-249 + * / "25" %x30-35 ; 250-255 + * + * reg-name = *( unreserved / pct-encoded / sub-delims ) + * + * path = path-abempty ; begins with "/" or is empty + * / path-absolute ; begins with "/" but not "//" + * / path-noscheme ; begins with a non-colon segment + * / path-rootless ; begins with a segment + * / path-empty ; zero characters + * + * path-abempty = *( "/" segment ) + * path-absolute = "/" [ segment-nz *( "/" segment ) ] + * path-noscheme = segment-nz-nc *( "/" segment ) + * path-rootless = segment-nz *( "/" segment ) + * path-empty = 0 + * + * segment = *pchar + * segment-nz = 1*pchar + * segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" ) + * ; non-zero-length segment without any colon ":" + * + * pchar = unreserved / pct-encoded / sub-delims / ":" / "@" + * + * query = *( pchar / "/" / "?" ) + * + * fragment = *( pchar / "/" / "?" ) + * + * pct-encoded = "%" HEXDIG HEXDIG + * + * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" + * reserved = gen-delims / sub-delims + * gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@" + * sub-delims = "!" / "$" / "&" / "'" / "(" / ")" + * / "*" / "+" / "," / ";" / "=" + * + * @endverbatim + * @see adapted from: https://github.com/jhermsmeier/uri.regex/blob/master/uri.regex + * + */ +const std::string scheme{R"(([A-Za-z][A-Za-z0-9+\-.]*):)"}; +const std::string hierPart{R"((?:(\/\/)(?:((?:[A-Za-z0-9\-._~!$&'()*+,;=:]|%[0-9A-Fa-f]{2})*)@)?((?:\[(?:(?:(?:(?:[0-9A-Fa-f]{1,4}:){6}|::(?:[0-9A-Fa-f]{1,4}:){5}|(?:[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){4}|(?:(?:[0-9A-Fa-f]{1,4}:){0,1}[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){3}|(?:(?:[0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){2}|(?:(?:[0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})?::[0-9A-Fa-f]{1,4}:|(?:(?:[0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})?::)(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))|(?:(?:[0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})?::[0-9A-Fa-f]{1,4}|(?:(?:[0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})?::)|[Vv][0-9A-Fa-f]+\.[A-Za-z0-9\-._~!$&'()*+,;=:]+)\]|(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)|(?:[A-Za-z0-9\-._~!$&'()*+,;=]|%[0-9A-Fa-f]{2})*))(?::([0-9]*))?((?:\/(?:[A-Za-z0-9\-._~!$&'()*+,;=:@]|%[0-9A-Fa-f]{2})*)*)|\/((?:(?:[A-Za-z0-9\-._~!$&'()*+,;=:@]|%[0-9A-Fa-f]{2})+(?:\/(?:[A-Za-z0-9\-._~!$&'()*+,;=:@]|%[0-9A-Fa-f]{2})*)*)?)|((?:[A-Za-z0-9\-._~!$&'()*+,;=:@]|%[0-9A-Fa-f]{2})+(?:\/(?:[A-Za-z0-9\-._~!$&'()*+,;=:@]|%[0-9A-Fa-f]{2})*)*)|))"}; +const std::string query{R"((?:\?((?:[A-Za-z0-9\-._~!$&'()*+,;=:@\/?]|%[0-9A-Fa-f]{2})*))?)"}; +const std::string fragment{ + R"((?:\#((?:[A-Za-z0-9\-._~!$&'()*+,;=:@\/?]|%[0-9A-Fa-f]{2})*))?)"}; + +void rfc3986_uri_check(const std::string &value) +{ + const std::string uriFormat{scheme + hierPart + query + fragment}; + static const std::regex uriRegex{uriFormat}; + + if (!std::regex_match(value, uriRegex)) { + throw std::invalid_argument(value + " is not a URI string according to RFC 3986."); + } +} + } // namespace namespace nlohmann @@ -286,6 +392,8 @@ void default_string_format_check(const std::string &format, const std::string &v rfc3339_date_check(value); } else if (format == "time") { rfc3339_time_check(value); + } else if (format == "uri") { + rfc3986_uri_check(value); } else if (format == "email") { static const std::regex emailRegex{email}; if (!std::regex_match(value, emailRegex)) { diff --git a/test/string-format-check-test.cpp b/test/string-format-check-test.cpp index 2a5fb88..4a207b1 100644 --- a/test/string-format-check-test.cpp +++ b/test/string-format-check-test.cpp @@ -82,5 +82,21 @@ int main() numberOfErrors += testStringFormat("ipv4", ipv4Checks); + const std::vector> uriChecks{ + {"http://www.google.com/search?q=regular%20expression", true}, + {"http://www.google.com/", true}, + {"http://www.google.com/search?q=regular%20expression", true}, + {"www.google.com", false}, + {"http://www.google.comj", true}, + {"ldap://[2001:db8::7]/c=GB?objectClass?one", true}, + {"mailto:John.Doe@example.com", true}, + {"news:comp.infosystems.www.servers.unix", true}, + {"https://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top", true}, + {"tel:+1-816-555-1212", true}, + {"telnet://192.0.2.16:80/", true}, + {"urn:oasis:names:specification:docbook:dtd:xml:4.1.2", true}}; + + numberOfErrors += testStringFormat("uri", uriChecks); + return numberOfErrors; } From e1e6581b0548a9b99c54256463a9182a9d4d159c Mon Sep 17 00:00:00 2001 From: sebasfalcone Date: Thu, 22 Sep 2022 11:34:15 -0300 Subject: [PATCH 14/25] CL: encapsulation --- src/string-format-check.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/string-format-check.cpp b/src/string-format-check.cpp index 1a623fc..65825a7 100644 --- a/src/string-format-check.cpp +++ b/src/string-format-check.cpp @@ -355,16 +355,16 @@ const std::string email{"(?:" + dotAtom + "|" + quotedString + ")@(?:" + stackov * @see adapted from: https://github.com/jhermsmeier/uri.regex/blob/master/uri.regex * */ -const std::string scheme{R"(([A-Za-z][A-Za-z0-9+\-.]*):)"}; -const std::string hierPart{R"((?:(\/\/)(?:((?:[A-Za-z0-9\-._~!$&'()*+,;=:]|%[0-9A-Fa-f]{2})*)@)?((?:\[(?:(?:(?:(?:[0-9A-Fa-f]{1,4}:){6}|::(?:[0-9A-Fa-f]{1,4}:){5}|(?:[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){4}|(?:(?:[0-9A-Fa-f]{1,4}:){0,1}[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){3}|(?:(?:[0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){2}|(?:(?:[0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})?::[0-9A-Fa-f]{1,4}:|(?:(?:[0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})?::)(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))|(?:(?:[0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})?::[0-9A-Fa-f]{1,4}|(?:(?:[0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})?::)|[Vv][0-9A-Fa-f]+\.[A-Za-z0-9\-._~!$&'()*+,;=:]+)\]|(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)|(?:[A-Za-z0-9\-._~!$&'()*+,;=]|%[0-9A-Fa-f]{2})*))(?::([0-9]*))?((?:\/(?:[A-Za-z0-9\-._~!$&'()*+,;=:@]|%[0-9A-Fa-f]{2})*)*)|\/((?:(?:[A-Za-z0-9\-._~!$&'()*+,;=:@]|%[0-9A-Fa-f]{2})+(?:\/(?:[A-Za-z0-9\-._~!$&'()*+,;=:@]|%[0-9A-Fa-f]{2})*)*)?)|((?:[A-Za-z0-9\-._~!$&'()*+,;=:@]|%[0-9A-Fa-f]{2})+(?:\/(?:[A-Za-z0-9\-._~!$&'()*+,;=:@]|%[0-9A-Fa-f]{2})*)*)|))"}; -const std::string query{R"((?:\?((?:[A-Za-z0-9\-._~!$&'()*+,;=:@\/?]|%[0-9A-Fa-f]{2})*))?)"}; -const std::string fragment{ - R"((?:\#((?:[A-Za-z0-9\-._~!$&'()*+,;=:@\/?]|%[0-9A-Fa-f]{2})*))?)"}; - void rfc3986_uri_check(const std::string &value) { - const std::string uriFormat{scheme + hierPart + query + fragment}; - static const std::regex uriRegex{uriFormat}; + const static std::string scheme{R"(([A-Za-z][A-Za-z0-9+\-.]*):)"}; + const static std::string hierPart{R"((?:(\/\/)(?:((?:[A-Za-z0-9\-._~!$&'()*+,;=:]|%[0-9A-Fa-f]{2})*)@)?((?:\[(?:(?:(?:(?:[0-9A-Fa-f]{1,4}:){6}|::(?:[0-9A-Fa-f]{1,4}:){5}|(?:[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){4}|(?:(?:[0-9A-Fa-f]{1,4}:){0,1}[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){3}|(?:(?:[0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){2}|(?:(?:[0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})?::[0-9A-Fa-f]{1,4}:|(?:(?:[0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})?::)(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))|(?:(?:[0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})?::[0-9A-Fa-f]{1,4}|(?:(?:[0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})?::)|[Vv][0-9A-Fa-f]+\.[A-Za-z0-9\-._~!$&'()*+,;=:]+)\]|(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)|(?:[A-Za-z0-9\-._~!$&'()*+,;=]|%[0-9A-Fa-f]{2})*))(?::([0-9]*))?((?:\/(?:[A-Za-z0-9\-._~!$&'()*+,;=:@]|%[0-9A-Fa-f]{2})*)*)|\/((?:(?:[A-Za-z0-9\-._~!$&'()*+,;=:@]|%[0-9A-Fa-f]{2})+(?:\/(?:[A-Za-z0-9\-._~!$&'()*+,;=:@]|%[0-9A-Fa-f]{2})*)*)?)|((?:[A-Za-z0-9\-._~!$&'()*+,;=:@]|%[0-9A-Fa-f]{2})+(?:\/(?:[A-Za-z0-9\-._~!$&'()*+,;=:@]|%[0-9A-Fa-f]{2})*)*)|))"}; + const static std::string query{R"((?:\?((?:[A-Za-z0-9\-._~!$&'()*+,;=:@\/?]|%[0-9A-Fa-f]{2})*))?)"}; + const static std::string fragment{ + R"((?:\#((?:[A-Za-z0-9\-._~!$&'()*+,;=:@\/?]|%[0-9A-Fa-f]{2})*))?)"}; + const static std::string uriFormat{scheme + hierPart + query + fragment}; + + const static std::regex uriRegex{uriFormat}; if (!std::regex_match(value, uriRegex)) { throw std::invalid_argument(value + " is not a URI string according to RFC 3986."); From f24f8f420397fa6bf0d39a1cca6a2d15a6b34caf Mon Sep 17 00:00:00 2001 From: sebasfalcone Date: Thu, 22 Sep 2022 13:35:45 -0300 Subject: [PATCH 15/25] CL: removed uri from WILL_FAIL list --- test/JSON-Schema-Test-Suite/CMakeLists.txt | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/test/JSON-Schema-Test-Suite/CMakeLists.txt b/test/JSON-Schema-Test-Suite/CMakeLists.txt index 237254e..b26f189 100644 --- a/test/JSON-Schema-Test-Suite/CMakeLists.txt +++ b/test/JSON-Schema-Test-Suite/CMakeLists.txt @@ -5,9 +5,9 @@ set(DRAFT "draft7") # find schema-test-suite find_path(JSON_SCHEMA_TEST_SUITE_PATH NAMES - tests/${DRAFT}) + tests/${DRAFT}) -if (NOT JSON_SCHEMA_TEST_SUITE_PATH) +if(NOT JSON_SCHEMA_TEST_SUITE_PATH) message(STATUS "Set JSON_SCHEMA_TEST_SUITE_PATH to a path in which JSON-Schema-Test-Suite is located (github.com/json-schema-org/JSON-Schema-Test-Suite). Using internal test-suite which might be out of date.") set(JSON_SCHEMA_TEST_SUITE_PATH ${CMAKE_CURRENT_SOURCE_DIR}) endif() @@ -18,7 +18,7 @@ if(JSON_SCHEMA_TEST_SUITE_PATH) target_link_libraries(json-schema-test nlohmann_json_schema_validator) target_compile_definitions(json-schema-test PRIVATE - JSON_SCHEMA_TEST_SUITE_PATH="${JSON_SCHEMA_TEST_SUITE_PATH}") + JSON_SCHEMA_TEST_SUITE_PATH="${JSON_SCHEMA_TEST_SUITE_PATH}") option(JSON_SCHEMA_ENABLE_OPTIONAL_TESTS "Enable optional tests of the JSONSchema Test Suite" ON) @@ -28,23 +28,23 @@ if(JSON_SCHEMA_TEST_SUITE_PATH) foreach(TEST_FILE ${TEST_FILES}) get_filename_component(TEST_NAME ${TEST_FILE} NAME_WE) add_test(NAME "${JSON_SCHEMA_TEST_PREFIX}::${TEST_NAME}" - COMMAND ${PIPE_IN_TEST_SCRIPT} $ ${TEST_FILE}) + COMMAND ${PIPE_IN_TEST_SCRIPT} $ ${TEST_FILE}) endforeach() - if (JSON_SCHEMA_ENABLE_OPTIONAL_TESTS) + if(JSON_SCHEMA_ENABLE_OPTIONAL_TESTS) file(GLOB OPT_TEST_FILES ${JSON_SCHEMA_TEST_SUITE_PATH}/tests/${DRAFT}/optional/*.json) file(GLOB FORMAT_TEST_FILES ${JSON_SCHEMA_TEST_SUITE_PATH}/tests/${DRAFT}/optional/format/*.json) foreach(TEST_FILE ${OPT_TEST_FILES}) get_filename_component(TEST_NAME ${TEST_FILE} NAME_WE) add_test(NAME "${JSON_SCHEMA_TEST_PREFIX}::Optional::${TEST_NAME}" - COMMAND ${PIPE_IN_TEST_SCRIPT} $ ${TEST_FILE}) + COMMAND ${PIPE_IN_TEST_SCRIPT} $ ${TEST_FILE}) endforeach() foreach(TEST_FILE ${FORMAT_TEST_FILES}) get_filename_component(TEST_NAME ${TEST_FILE} NAME_WE) add_test(NAME "${JSON_SCHEMA_TEST_PREFIX}::Optional::Format::${TEST_NAME}" - COMMAND ${PIPE_IN_TEST_SCRIPT} $ ${TEST_FILE}) + COMMAND ${PIPE_IN_TEST_SCRIPT} $ ${TEST_FILE}) endforeach() # some optional tests will fail @@ -62,11 +62,10 @@ if(JSON_SCHEMA_TEST_SUITE_PATH) JSON-Suite::Optional::Format::relative-json-pointer JSON-Suite::Optional::Format::uri-reference JSON-Suite::Optional::Format::uri-template - JSON-Suite::Optional::Format::uri JSON-Suite::Optional::unicode PROPERTIES - WILL_FAIL ON) + WILL_FAIL ON) endif() else() endif() From 2a2d2d25d1d6f0711b6aa59876f3e91b2d63321d Mon Sep 17 00:00:00 2001 From: sebasfalcone Date: Thu, 22 Sep 2022 14:52:47 -0300 Subject: [PATCH 16/25] CL: Splited regex string to improve readability --- src/string-format-check.cpp | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/src/string-format-check.cpp b/src/string-format-check.cpp index 65825a7..cd908f0 100644 --- a/src/string-format-check.cpp +++ b/src/string-format-check.cpp @@ -358,7 +358,37 @@ const std::string email{"(?:" + dotAtom + "|" + quotedString + ")@(?:" + stackov void rfc3986_uri_check(const std::string &value) { const static std::string scheme{R"(([A-Za-z][A-Za-z0-9+\-.]*):)"}; - const static std::string hierPart{R"((?:(\/\/)(?:((?:[A-Za-z0-9\-._~!$&'()*+,;=:]|%[0-9A-Fa-f]{2})*)@)?((?:\[(?:(?:(?:(?:[0-9A-Fa-f]{1,4}:){6}|::(?:[0-9A-Fa-f]{1,4}:){5}|(?:[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){4}|(?:(?:[0-9A-Fa-f]{1,4}:){0,1}[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){3}|(?:(?:[0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){2}|(?:(?:[0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})?::[0-9A-Fa-f]{1,4}:|(?:(?:[0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})?::)(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))|(?:(?:[0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})?::[0-9A-Fa-f]{1,4}|(?:(?:[0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})?::)|[Vv][0-9A-Fa-f]+\.[A-Za-z0-9\-._~!$&'()*+,;=:]+)\]|(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)|(?:[A-Za-z0-9\-._~!$&'()*+,;=]|%[0-9A-Fa-f]{2})*))(?::([0-9]*))?((?:\/(?:[A-Za-z0-9\-._~!$&'()*+,;=:@]|%[0-9A-Fa-f]{2})*)*)|\/((?:(?:[A-Za-z0-9\-._~!$&'()*+,;=:@]|%[0-9A-Fa-f]{2})+(?:\/(?:[A-Za-z0-9\-._~!$&'()*+,;=:@]|%[0-9A-Fa-f]{2})*)*)?)|((?:[A-Za-z0-9\-._~!$&'()*+,;=:@]|%[0-9A-Fa-f]{2})+(?:\/(?:[A-Za-z0-9\-._~!$&'()*+,;=:@]|%[0-9A-Fa-f]{2})*)*)|))"}; + const static std::string hierPart{ + R"((?:(\/\/)(?:((?:[A-Za-z0-9\-._~!$&'()*+,;=:]|)" + R"(%[0-9A-Fa-f]{2})*)@)?((?:\[(?:(?:(?:(?:[0-9A-Fa-f]{1,4}:){6}|)" + R"(::(?:[0-9A-Fa-f]{1,4}:){5}|)" + R"((?:[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){4}|)" + R"((?:(?:[0-9A-Fa-f]{1,4}:){0,1}[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){3}|)" + R"((?:(?:[0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){2}|)" + R"((?:(?:[0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})?::[0-9A-Fa-f]{1,4}:|)" + R"((?:(?:[0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})?::)(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|)" + R"((?:(?:25[0-5]|2[0-4][0-9]|)" + R"([01]?[0-9][0-9]?)\.){3}(?:25[0-5]|)" + R"(2[0-4][0-9]|)" + R"([01]?[0-9][0-9]?))|)" + R"((?:(?:[0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})?::[0-9A-Fa-f]{1,4}|)" + R"((?:(?:[0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})?::)|)" + R"([Vv][0-9A-Fa-f]+\.[A-Za-z0-9\-._~!$&'()*+,;=:]+)\]|)" + R"((?:(?:25[0-5]|)" + R"(2[0-4][0-9]|)" + R"([01]?[0-9][0-9]?)\.){3}(?:25[0-5]|)" + R"(2[0-4][0-9]|)" + R"([01]?[0-9][0-9]?)|)" + R"((?:[A-Za-z0-9\-._~!$&'()*+,;=]|)" + R"(%[0-9A-Fa-f]{2})*))(?::([0-9]*))?((?:\/(?:[A-Za-z0-9\-._~!$&'()*+,;=:@]|)" + R"(%[0-9A-Fa-f]{2})*)*)|)" + R"(\/((?:(?:[A-Za-z0-9\-._~!$&'()*+,;=:@]|)" + R"(%[0-9A-Fa-f]{2})+(?:\/(?:[A-Za-z0-9\-._~!$&'()*+,;=:@]|)" + R"(%[0-9A-Fa-f]{2})*)*)?)|)" + R"(((?:[A-Za-z0-9\-._~!$&'()*+,;=:@]|)" + R"(%[0-9A-Fa-f]{2})+(?:\/(?:[A-Za-z0-9\-._~!$&'()*+,;=:@]|)" + R"(%[0-9A-Fa-f]{2})*)*)|))"}; + const static std::string query{R"((?:\?((?:[A-Za-z0-9\-._~!$&'()*+,;=:@\/?]|%[0-9A-Fa-f]{2})*))?)"}; const static std::string fragment{ R"((?:\#((?:[A-Za-z0-9\-._~!$&'()*+,;=:@\/?]|%[0-9A-Fa-f]{2})*))?)"}; From 56bb4a4af43ee12b81fcf079acd19fda725e732f Mon Sep 17 00:00:00 2001 From: sebasfalcone Date: Fri, 23 Sep 2022 10:16:06 -0300 Subject: [PATCH 17/25] CL: Restored CMakeLists to original state --- test/JSON-Schema-Test-Suite/CMakeLists.txt | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test/JSON-Schema-Test-Suite/CMakeLists.txt b/test/JSON-Schema-Test-Suite/CMakeLists.txt index b26f189..1a240c6 100644 --- a/test/JSON-Schema-Test-Suite/CMakeLists.txt +++ b/test/JSON-Schema-Test-Suite/CMakeLists.txt @@ -5,9 +5,9 @@ set(DRAFT "draft7") # find schema-test-suite find_path(JSON_SCHEMA_TEST_SUITE_PATH NAMES - tests/${DRAFT}) + tests/${DRAFT}) -if(NOT JSON_SCHEMA_TEST_SUITE_PATH) +if (NOT JSON_SCHEMA_TEST_SUITE_PATH) message(STATUS "Set JSON_SCHEMA_TEST_SUITE_PATH to a path in which JSON-Schema-Test-Suite is located (github.com/json-schema-org/JSON-Schema-Test-Suite). Using internal test-suite which might be out of date.") set(JSON_SCHEMA_TEST_SUITE_PATH ${CMAKE_CURRENT_SOURCE_DIR}) endif() @@ -18,7 +18,7 @@ if(JSON_SCHEMA_TEST_SUITE_PATH) target_link_libraries(json-schema-test nlohmann_json_schema_validator) target_compile_definitions(json-schema-test PRIVATE - JSON_SCHEMA_TEST_SUITE_PATH="${JSON_SCHEMA_TEST_SUITE_PATH}") + JSON_SCHEMA_TEST_SUITE_PATH="${JSON_SCHEMA_TEST_SUITE_PATH}") option(JSON_SCHEMA_ENABLE_OPTIONAL_TESTS "Enable optional tests of the JSONSchema Test Suite" ON) @@ -28,23 +28,23 @@ if(JSON_SCHEMA_TEST_SUITE_PATH) foreach(TEST_FILE ${TEST_FILES}) get_filename_component(TEST_NAME ${TEST_FILE} NAME_WE) add_test(NAME "${JSON_SCHEMA_TEST_PREFIX}::${TEST_NAME}" - COMMAND ${PIPE_IN_TEST_SCRIPT} $ ${TEST_FILE}) + COMMAND ${PIPE_IN_TEST_SCRIPT} $ ${TEST_FILE}) endforeach() - if(JSON_SCHEMA_ENABLE_OPTIONAL_TESTS) + if (JSON_SCHEMA_ENABLE_OPTIONAL_TESTS) file(GLOB OPT_TEST_FILES ${JSON_SCHEMA_TEST_SUITE_PATH}/tests/${DRAFT}/optional/*.json) file(GLOB FORMAT_TEST_FILES ${JSON_SCHEMA_TEST_SUITE_PATH}/tests/${DRAFT}/optional/format/*.json) foreach(TEST_FILE ${OPT_TEST_FILES}) get_filename_component(TEST_NAME ${TEST_FILE} NAME_WE) add_test(NAME "${JSON_SCHEMA_TEST_PREFIX}::Optional::${TEST_NAME}" - COMMAND ${PIPE_IN_TEST_SCRIPT} $ ${TEST_FILE}) + COMMAND ${PIPE_IN_TEST_SCRIPT} $ ${TEST_FILE}) endforeach() foreach(TEST_FILE ${FORMAT_TEST_FILES}) get_filename_component(TEST_NAME ${TEST_FILE} NAME_WE) add_test(NAME "${JSON_SCHEMA_TEST_PREFIX}::Optional::Format::${TEST_NAME}" - COMMAND ${PIPE_IN_TEST_SCRIPT} $ ${TEST_FILE}) + COMMAND ${PIPE_IN_TEST_SCRIPT} $ ${TEST_FILE}) endforeach() # some optional tests will fail @@ -65,7 +65,7 @@ if(JSON_SCHEMA_TEST_SUITE_PATH) JSON-Suite::Optional::unicode PROPERTIES - WILL_FAIL ON) + WILL_FAIL ON) endif() else() endif() From fd622c040b507dd2e161b74a45c3ecd999a5b8b1 Mon Sep 17 00:00:00 2001 From: Gene Hightower Date: Fri, 21 Oct 2022 10:39:12 -0700 Subject: [PATCH 18/25] Use Ragel generated RFC-5321/RFC-6531 parsrr Mailbox address parser from --- CMakeLists.txt | 3 +- src/smtp-address-validator.cpp | 830 +++++++++++++++++++++ src/smtp-address-validator.hpp | 34 + src/string-format-check.cpp | 108 +-- test/JSON-Schema-Test-Suite/CMakeLists.txt | 1 - 5 files changed, 886 insertions(+), 90 deletions(-) create mode 100644 src/smtp-address-validator.cpp create mode 100644 src/smtp-address-validator.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index d0f0ec4..9379b1b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,6 +23,7 @@ endif() # the library add_library(nlohmann_json_schema_validator + src/smtp-address-validator.cpp src/json-schema-draft7.json.cpp src/json-uri.cpp src/json-validator.cpp @@ -153,4 +154,4 @@ if(JSON_VALIDATOR_INSTALL) DESTINATION ${INSTALL_CMAKE_DIR} ) -endif() \ No newline at end of file +endif() diff --git a/src/smtp-address-validator.cpp b/src/smtp-address-validator.cpp new file mode 100644 index 0000000..a63ead0 --- /dev/null +++ b/src/smtp-address-validator.cpp @@ -0,0 +1,830 @@ +/* + +Snarfed from + +: + +Copyright (c) 2021 Gene Hightower + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +*/ + +#line 1 "smtp-address-validator.rl" +#include "smtp-address-validator.hpp" + +#line 110 "smtp-address-validator.rl" + +#line 7 "smtp-address-validator.cpp" +static const signed char _address_actions[] = { + 0, 1, 0, 1, 1, 0}; + +static const short _address_key_offsets[] = { + 0, 0, 24, 26, 50, 52, 54, 56, + 58, 60, 62, 86, 103, 105, 107, 109, + 111, 113, 115, 117, 134, 150, 161, 168, + 176, 180, 181, 190, 195, 196, 201, 202, + 207, 210, 213, 219, 222, 225, 228, 234, + 237, 240, 243, 249, 252, 261, 270, 282, + 293, 302, 311, 320, 328, 345, 353, 360, + 367, 368, 375, 382, 389, 396, 397, 404, + 411, 418, 425, 426, 433, 440, 447, 454, + 455, 462, 469, 476, 483, 484, 491, 498, + 505, 512, 513, 523, 531, 538, 545, 546, + 552, 559, 566, 573, 581, 589, 597, 608, + 618, 626, 634, 641, 649, 657, 665, 667, + 673, 681, 689, 697, 699, 705, 713, 721, + 729, 731, 737, 745, 753, 761, 763, 769, + 777, 785, 793, 795, 802, 812, 821, 829, + 837, 839, 848, 857, 865, 873, 875, 884, + 893, 901, 909, 911, 920, 929, 937, 945, + 947, 956, 965, 974, 983, 992, 1004, 1015, + 1024, 1033, 1042, 1051, 1060, 1072, 1083, 1092, + 1101, 1109, 1118, 1127, 1136, 1148, 1159, 1168, + 1177, 1185, 1194, 1203, 1212, 1224, 1235, 1244, + 1253, 1261, 1270, 1279, 1288, 1300, 1311, 1320, + 1329, 1337, 1339, 1353, 1355, 1357, 1359, 1361, + 1363, 1365, 1367, 1368, 1370, 1388, 0 +}; + +static const char _address_trans_keys[] = { + -32, -19, -16, -12, 34, 45, 61, 63, + -62, -33, -31, -17, -15, -13, 33, 39, + 42, 43, 47, 57, 65, 90, 94, 126, + -128, -65, -32, -19, -16, -12, 33, 46, + 61, 64, -62, -33, -31, -17, -15, -13, + 35, 39, 42, 43, 45, 57, 63, 90, + 94, 126, -96, -65, -128, -65, -128, -97, + -112, -65, -128, -65, -128, -113, -32, -19, + -16, -12, 33, 45, 61, 63, -62, -33, + -31, -17, -15, -13, 35, 39, 42, 43, + 47, 57, 65, 90, 94, 126, -32, -19, + -16, -12, 91, -62, -33, -31, -17, -15, + -13, 48, 57, 65, 90, 97, 122, -128, + -65, -96, -65, -128, -65, -128, -97, -112, + -65, -128, -65, -128, -113, -32, -19, -16, + -12, 45, -62, -33, -31, -17, -15, -13, + 48, 57, 65, 90, 97, 122, -32, -19, + -16, -12, -62, -33, -31, -17, -15, -13, + 48, 57, 65, 90, 97, 122, 45, 48, + 49, 50, 73, 51, 57, 65, 90, 97, + 122, 45, 48, 57, 65, 90, 97, 122, + 45, 58, 48, 57, 65, 90, 97, 122, + 33, 90, 94, 126, 93, 45, 46, 58, + 48, 57, 65, 90, 97, 122, 48, 49, + 50, 51, 57, 46, 48, 49, 50, 51, + 57, 46, 48, 49, 50, 51, 57, 93, + 48, 57, 93, 48, 57, 53, 93, 48, + 52, 54, 57, 93, 48, 53, 46, 48, + 57, 46, 48, 57, 46, 53, 48, 52, + 54, 57, 46, 48, 53, 46, 48, 57, + 46, 48, 57, 46, 53, 48, 52, 54, + 57, 46, 48, 53, 45, 46, 58, 48, + 57, 65, 90, 97, 122, 45, 46, 58, + 48, 57, 65, 90, 97, 122, 45, 46, + 53, 58, 48, 52, 54, 57, 65, 90, + 97, 122, 45, 46, 58, 48, 53, 54, + 57, 65, 90, 97, 122, 45, 58, 80, + 48, 57, 65, 90, 97, 122, 45, 58, + 118, 48, 57, 65, 90, 97, 122, 45, + 54, 58, 48, 57, 65, 90, 97, 122, + 45, 58, 48, 57, 65, 90, 97, 122, + 58, 33, 47, 48, 57, 59, 64, 65, + 70, 71, 90, 94, 96, 97, 102, 103, + 126, 58, 93, 48, 57, 65, 70, 97, + 102, 58, 48, 57, 65, 70, 97, 102, + 58, 48, 57, 65, 70, 97, 102, 58, + 58, 48, 57, 65, 70, 97, 102, 58, + 48, 57, 65, 70, 97, 102, 58, 48, + 57, 65, 70, 97, 102, 58, 48, 57, + 65, 70, 97, 102, 58, 58, 48, 57, + 65, 70, 97, 102, 58, 48, 57, 65, + 70, 97, 102, 58, 48, 57, 65, 70, + 97, 102, 58, 48, 57, 65, 70, 97, + 102, 58, 58, 48, 57, 65, 70, 97, + 102, 58, 48, 57, 65, 70, 97, 102, + 58, 48, 57, 65, 70, 97, 102, 58, + 48, 57, 65, 70, 97, 102, 58, 58, + 48, 57, 65, 70, 97, 102, 58, 48, + 57, 65, 70, 97, 102, 58, 48, 57, + 65, 70, 97, 102, 58, 48, 57, 65, + 70, 97, 102, 58, 58, 48, 57, 65, + 70, 97, 102, 58, 48, 57, 65, 70, + 97, 102, 58, 48, 57, 65, 70, 97, + 102, 58, 48, 57, 65, 70, 97, 102, + 58, 48, 49, 50, 58, 51, 57, 65, + 70, 97, 102, 46, 58, 48, 57, 65, + 70, 97, 102, 58, 48, 57, 65, 70, + 97, 102, 58, 48, 57, 65, 70, 97, + 102, 58, 48, 57, 65, 70, 97, 102, + 93, 48, 57, 65, 70, 97, 102, 93, + 48, 57, 65, 70, 97, 102, 93, 48, + 57, 65, 70, 97, 102, 46, 58, 48, + 57, 65, 70, 97, 102, 46, 58, 48, + 57, 65, 70, 97, 102, 46, 58, 48, + 57, 65, 70, 97, 102, 46, 53, 58, + 48, 52, 54, 57, 65, 70, 97, 102, + 46, 58, 48, 53, 54, 57, 65, 70, + 97, 102, 46, 58, 48, 57, 65, 70, + 97, 102, 46, 58, 48, 57, 65, 70, + 97, 102, 93, 48, 57, 65, 70, 97, + 102, 58, 93, 48, 57, 65, 70, 97, + 102, 58, 93, 48, 57, 65, 70, 97, + 102, 58, 93, 48, 57, 65, 70, 97, + 102, 58, 93, 48, 57, 65, 70, 97, + 102, 58, 93, 48, 57, 65, 70, 97, + 102, 58, 93, 48, 57, 65, 70, 97, + 102, 58, 93, 48, 57, 65, 70, 97, + 102, 58, 93, 48, 57, 65, 70, 97, + 102, 58, 93, 48, 57, 65, 70, 97, + 102, 58, 93, 48, 57, 65, 70, 97, + 102, 58, 93, 48, 57, 65, 70, 97, + 102, 58, 93, 48, 57, 65, 70, 97, + 102, 58, 93, 48, 57, 65, 70, 97, + 102, 58, 93, 48, 57, 65, 70, 97, + 102, 58, 93, 48, 57, 65, 70, 97, + 102, 58, 93, 48, 57, 65, 70, 97, + 102, 58, 93, 48, 57, 65, 70, 97, + 102, 58, 93, 48, 57, 65, 70, 97, + 102, 58, 93, 48, 57, 65, 70, 97, + 102, 58, 93, 58, 48, 57, 65, 70, + 97, 102, 48, 49, 50, 93, 51, 57, + 65, 70, 97, 102, 46, 58, 93, 48, + 57, 65, 70, 97, 102, 58, 93, 48, + 57, 65, 70, 97, 102, 58, 93, 48, + 57, 65, 70, 97, 102, 58, 93, 48, + 49, 50, 51, 57, 65, 70, 97, 102, + 46, 58, 93, 48, 57, 65, 70, 97, + 102, 58, 93, 48, 57, 65, 70, 97, + 102, 58, 93, 48, 57, 65, 70, 97, + 102, 58, 93, 48, 49, 50, 51, 57, + 65, 70, 97, 102, 46, 58, 93, 48, + 57, 65, 70, 97, 102, 58, 93, 48, + 57, 65, 70, 97, 102, 58, 93, 48, + 57, 65, 70, 97, 102, 58, 93, 48, + 49, 50, 51, 57, 65, 70, 97, 102, + 46, 58, 93, 48, 57, 65, 70, 97, + 102, 58, 93, 48, 57, 65, 70, 97, + 102, 58, 93, 48, 57, 65, 70, 97, + 102, 58, 93, 48, 49, 50, 51, 57, + 65, 70, 97, 102, 46, 58, 93, 48, + 57, 65, 70, 97, 102, 46, 58, 93, + 48, 57, 65, 70, 97, 102, 46, 58, + 93, 48, 57, 65, 70, 97, 102, 46, + 58, 93, 48, 57, 65, 70, 97, 102, + 46, 53, 58, 93, 48, 52, 54, 57, + 65, 70, 97, 102, 46, 58, 93, 48, + 53, 54, 57, 65, 70, 97, 102, 46, + 58, 93, 48, 57, 65, 70, 97, 102, + 46, 58, 93, 48, 57, 65, 70, 97, + 102, 46, 58, 93, 48, 57, 65, 70, + 97, 102, 46, 58, 93, 48, 57, 65, + 70, 97, 102, 46, 58, 93, 48, 57, + 65, 70, 97, 102, 46, 53, 58, 93, + 48, 52, 54, 57, 65, 70, 97, 102, + 46, 58, 93, 48, 53, 54, 57, 65, + 70, 97, 102, 46, 58, 93, 48, 57, + 65, 70, 97, 102, 46, 58, 93, 48, + 57, 65, 70, 97, 102, 58, 93, 48, + 57, 65, 70, 97, 102, 46, 58, 93, + 48, 57, 65, 70, 97, 102, 46, 58, + 93, 48, 57, 65, 70, 97, 102, 46, + 58, 93, 48, 57, 65, 70, 97, 102, + 46, 53, 58, 93, 48, 52, 54, 57, + 65, 70, 97, 102, 46, 58, 93, 48, + 53, 54, 57, 65, 70, 97, 102, 46, + 58, 93, 48, 57, 65, 70, 97, 102, + 46, 58, 93, 48, 57, 65, 70, 97, + 102, 58, 93, 48, 57, 65, 70, 97, + 102, 46, 58, 93, 48, 57, 65, 70, + 97, 102, 46, 58, 93, 48, 57, 65, + 70, 97, 102, 46, 58, 93, 48, 57, + 65, 70, 97, 102, 46, 53, 58, 93, + 48, 52, 54, 57, 65, 70, 97, 102, + 46, 58, 93, 48, 53, 54, 57, 65, + 70, 97, 102, 46, 58, 93, 48, 57, + 65, 70, 97, 102, 46, 58, 93, 48, + 57, 65, 70, 97, 102, 58, 93, 48, + 57, 65, 70, 97, 102, 46, 58, 93, + 48, 57, 65, 70, 97, 102, 46, 58, + 93, 48, 57, 65, 70, 97, 102, 46, + 58, 93, 48, 57, 65, 70, 97, 102, + 46, 53, 58, 93, 48, 52, 54, 57, + 65, 70, 97, 102, 46, 58, 93, 48, + 53, 54, 57, 65, 70, 97, 102, 46, + 58, 93, 48, 57, 65, 70, 97, 102, + 46, 58, 93, 48, 57, 65, 70, 97, + 102, 58, 93, 48, 57, 65, 70, 97, + 102, 58, 93, -32, -19, -16, -12, 34, + 92, -62, -33, -31, -17, -15, -13, 32, + 126, -128, -65, -96, -65, -128, -65, -128, + -97, -112, -65, -128, -65, -128, -113, 64, + 32, 126, -32, -19, -16, -12, 45, 46, + -62, -33, -31, -17, -15, -13, 48, 57, + 65, 90, 97, 122, 0 +}; + +static const signed char _address_single_lengths[] = { + 0, 8, 0, 8, 0, 0, 0, 0, + 0, 0, 8, 5, 0, 0, 0, 0, + 0, 0, 0, 5, 4, 5, 1, 2, + 0, 1, 3, 3, 1, 3, 1, 3, + 1, 1, 2, 1, 1, 1, 2, 1, + 1, 1, 2, 1, 3, 3, 4, 3, + 3, 3, 3, 2, 1, 2, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 4, 2, 1, 1, 1, 0, + 1, 1, 1, 2, 2, 2, 3, 2, + 2, 2, 1, 2, 2, 2, 2, 0, + 2, 2, 2, 2, 0, 2, 2, 2, + 2, 0, 2, 2, 2, 2, 0, 2, + 2, 2, 2, 1, 4, 3, 2, 2, + 2, 3, 3, 2, 2, 2, 3, 3, + 2, 2, 2, 3, 3, 2, 2, 2, + 3, 3, 3, 3, 3, 4, 3, 3, + 3, 3, 3, 3, 4, 3, 3, 3, + 2, 3, 3, 3, 4, 3, 3, 3, + 2, 3, 3, 3, 4, 3, 3, 3, + 2, 3, 3, 3, 4, 3, 3, 3, + 2, 2, 6, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 6, 0, 0 +}; + +static const signed char _address_range_lengths[] = { + 0, 8, 1, 8, 1, 1, 1, 1, + 1, 1, 8, 6, 1, 1, 1, 1, + 1, 1, 1, 6, 6, 3, 3, 3, + 2, 0, 3, 1, 0, 1, 0, 1, + 1, 1, 2, 1, 1, 1, 2, 1, + 1, 1, 2, 1, 3, 3, 4, 4, + 3, 3, 3, 3, 8, 3, 3, 3, + 0, 3, 3, 3, 3, 0, 3, 3, + 3, 3, 0, 3, 3, 3, 3, 0, + 3, 3, 3, 3, 0, 3, 3, 3, + 3, 0, 3, 3, 3, 3, 0, 3, + 3, 3, 3, 3, 3, 3, 4, 4, + 3, 3, 3, 3, 3, 3, 0, 3, + 3, 3, 3, 0, 3, 3, 3, 3, + 0, 3, 3, 3, 3, 0, 3, 3, + 3, 3, 0, 3, 3, 3, 3, 3, + 0, 3, 3, 3, 3, 0, 3, 3, + 3, 3, 0, 3, 3, 3, 3, 0, + 3, 3, 3, 3, 3, 4, 4, 3, + 3, 3, 3, 3, 4, 4, 3, 3, + 3, 3, 3, 3, 4, 4, 3, 3, + 3, 3, 3, 3, 4, 4, 3, 3, + 3, 3, 3, 3, 4, 4, 3, 3, + 3, 0, 4, 1, 1, 1, 1, 1, + 1, 1, 0, 1, 6, 0, 0 +}; + +static const short _address_index_offsets[] = { + 0, 0, 17, 19, 36, 38, 40, 42, + 44, 46, 48, 65, 77, 79, 81, 83, + 85, 87, 89, 91, 103, 114, 123, 128, + 134, 137, 139, 146, 151, 153, 158, 160, + 165, 168, 171, 176, 179, 182, 185, 190, + 193, 196, 199, 204, 207, 214, 221, 230, + 238, 245, 252, 259, 265, 275, 281, 286, + 291, 293, 298, 303, 308, 313, 315, 320, + 325, 330, 335, 337, 342, 347, 352, 357, + 359, 364, 369, 374, 379, 381, 386, 391, + 396, 401, 403, 411, 417, 422, 427, 429, + 433, 438, 443, 448, 454, 460, 466, 474, + 481, 487, 493, 498, 504, 510, 516, 519, + 523, 529, 535, 541, 544, 548, 554, 560, + 566, 569, 573, 579, 585, 591, 594, 598, + 604, 610, 616, 619, 624, 632, 639, 645, + 651, 654, 661, 668, 674, 680, 683, 690, + 697, 703, 709, 712, 719, 726, 732, 738, + 741, 748, 755, 762, 769, 776, 785, 793, + 800, 807, 814, 821, 828, 837, 845, 852, + 859, 865, 872, 879, 886, 895, 903, 910, + 917, 923, 930, 937, 944, 953, 961, 968, + 975, 981, 988, 995, 1002, 1011, 1019, 1026, + 1033, 1039, 1042, 1053, 1055, 1057, 1059, 1061, + 1063, 1065, 1067, 1069, 1071, 1084, 0 +}; + +static const short _address_cond_targs[] = { + 4, 6, 7, 9, 186, 3, 3, 3, + 2, 5, 8, 3, 3, 3, 3, 3, + 0, 3, 0, 4, 6, 7, 9, 3, + 10, 3, 11, 2, 5, 8, 3, 3, + 3, 3, 3, 0, 2, 0, 2, 0, + 2, 0, 5, 0, 5, 0, 5, 0, + 4, 6, 7, 9, 3, 3, 3, 3, + 2, 5, 8, 3, 3, 3, 3, 3, + 0, 13, 15, 16, 18, 21, 12, 14, + 17, 196, 196, 196, 0, 196, 0, 12, + 0, 12, 0, 12, 0, 14, 0, 14, + 0, 14, 0, 13, 15, 16, 18, 19, + 12, 14, 17, 196, 196, 196, 0, 13, + 15, 16, 18, 12, 14, 17, 196, 196, + 196, 0, 22, 26, 44, 46, 48, 45, + 23, 23, 0, 22, 23, 23, 23, 0, + 22, 24, 23, 23, 23, 0, 25, 25, + 0, 197, 0, 22, 27, 24, 23, 23, + 23, 0, 28, 40, 42, 41, 0, 29, + 0, 30, 36, 38, 37, 0, 31, 0, + 25, 32, 34, 33, 0, 197, 33, 0, + 197, 25, 0, 35, 197, 33, 25, 0, + 197, 25, 0, 31, 37, 0, 31, 30, + 0, 31, 39, 37, 30, 0, 31, 30, + 0, 29, 41, 0, 29, 28, 0, 29, + 43, 41, 28, 0, 29, 28, 0, 22, + 27, 24, 45, 23, 23, 0, 22, 27, + 24, 26, 23, 23, 0, 22, 27, 47, + 24, 45, 26, 23, 23, 0, 22, 27, + 24, 26, 23, 23, 23, 0, 22, 24, + 49, 23, 23, 23, 0, 22, 24, 50, + 23, 23, 23, 0, 22, 51, 24, 23, + 23, 23, 0, 22, 52, 23, 23, 23, + 0, 185, 25, 53, 25, 53, 25, 25, + 53, 25, 0, 57, 197, 54, 54, 54, + 0, 57, 55, 55, 55, 0, 57, 56, + 56, 56, 0, 57, 0, 124, 58, 58, + 58, 0, 62, 59, 59, 59, 0, 62, + 60, 60, 60, 0, 62, 61, 61, 61, + 0, 62, 0, 124, 63, 63, 63, 0, + 67, 64, 64, 64, 0, 67, 65, 65, + 65, 0, 67, 66, 66, 66, 0, 67, + 0, 124, 68, 68, 68, 0, 72, 69, + 69, 69, 0, 72, 70, 70, 70, 0, + 72, 71, 71, 71, 0, 72, 0, 124, + 73, 73, 73, 0, 77, 74, 74, 74, + 0, 77, 75, 75, 75, 0, 77, 76, + 76, 76, 0, 77, 0, 98, 78, 78, + 78, 0, 82, 79, 79, 79, 0, 82, + 80, 80, 80, 0, 82, 81, 81, 81, + 0, 82, 0, 83, 91, 94, 98, 97, + 123, 123, 0, 27, 87, 84, 84, 84, + 0, 87, 85, 85, 85, 0, 87, 86, + 86, 86, 0, 87, 0, 88, 88, 88, + 0, 197, 89, 89, 89, 0, 197, 90, + 90, 90, 0, 197, 25, 25, 25, 0, + 27, 87, 92, 84, 84, 0, 27, 87, + 93, 85, 85, 0, 27, 87, 86, 86, + 86, 0, 27, 95, 87, 92, 96, 84, + 84, 0, 27, 87, 93, 85, 85, 85, + 0, 27, 87, 85, 85, 85, 0, 27, + 87, 96, 84, 84, 0, 197, 99, 99, + 99, 0, 103, 197, 100, 100, 100, 0, + 103, 197, 101, 101, 101, 0, 103, 197, + 102, 102, 102, 0, 103, 197, 0, 104, + 104, 104, 0, 108, 197, 105, 105, 105, + 0, 108, 197, 106, 106, 106, 0, 108, + 197, 107, 107, 107, 0, 108, 197, 0, + 109, 109, 109, 0, 113, 197, 110, 110, + 110, 0, 113, 197, 111, 111, 111, 0, + 113, 197, 112, 112, 112, 0, 113, 197, + 0, 114, 114, 114, 0, 118, 197, 115, + 115, 115, 0, 118, 197, 116, 116, 116, + 0, 118, 197, 117, 117, 117, 0, 118, + 197, 0, 119, 119, 119, 0, 87, 197, + 120, 120, 120, 0, 87, 197, 121, 121, + 121, 0, 87, 197, 122, 122, 122, 0, + 87, 197, 0, 87, 84, 84, 84, 0, + 125, 177, 180, 197, 183, 184, 184, 0, + 27, 129, 197, 126, 126, 126, 0, 129, + 197, 127, 127, 127, 0, 129, 197, 128, + 128, 128, 0, 129, 197, 0, 130, 169, + 172, 175, 176, 176, 0, 27, 134, 197, + 131, 131, 131, 0, 134, 197, 132, 132, + 132, 0, 134, 197, 133, 133, 133, 0, + 134, 197, 0, 135, 161, 164, 167, 168, + 168, 0, 27, 139, 197, 136, 136, 136, + 0, 139, 197, 137, 137, 137, 0, 139, + 197, 138, 138, 138, 0, 139, 197, 0, + 140, 153, 156, 159, 160, 160, 0, 27, + 144, 197, 141, 141, 141, 0, 144, 197, + 142, 142, 142, 0, 144, 197, 143, 143, + 143, 0, 144, 197, 0, 145, 146, 149, + 152, 119, 119, 0, 27, 87, 197, 120, + 120, 120, 0, 27, 87, 197, 147, 120, + 120, 0, 27, 87, 197, 148, 121, 121, + 0, 27, 87, 197, 122, 122, 122, 0, + 27, 150, 87, 197, 147, 151, 120, 120, + 0, 27, 87, 197, 148, 121, 121, 121, + 0, 27, 87, 197, 121, 121, 121, 0, + 27, 87, 197, 151, 120, 120, 0, 27, + 144, 197, 154, 141, 141, 0, 27, 144, + 197, 155, 142, 142, 0, 27, 144, 197, + 143, 143, 143, 0, 27, 157, 144, 197, + 154, 158, 141, 141, 0, 27, 144, 197, + 155, 142, 142, 142, 0, 27, 144, 197, + 142, 142, 142, 0, 27, 144, 197, 158, + 141, 141, 0, 144, 197, 141, 141, 141, + 0, 27, 139, 197, 162, 136, 136, 0, + 27, 139, 197, 163, 137, 137, 0, 27, + 139, 197, 138, 138, 138, 0, 27, 165, + 139, 197, 162, 166, 136, 136, 0, 27, + 139, 197, 163, 137, 137, 137, 0, 27, + 139, 197, 137, 137, 137, 0, 27, 139, + 197, 166, 136, 136, 0, 139, 197, 136, + 136, 136, 0, 27, 134, 197, 170, 131, + 131, 0, 27, 134, 197, 171, 132, 132, + 0, 27, 134, 197, 133, 133, 133, 0, + 27, 173, 134, 197, 170, 174, 131, 131, + 0, 27, 134, 197, 171, 132, 132, 132, + 0, 27, 134, 197, 132, 132, 132, 0, + 27, 134, 197, 174, 131, 131, 0, 134, + 197, 131, 131, 131, 0, 27, 129, 197, + 178, 126, 126, 0, 27, 129, 197, 179, + 127, 127, 0, 27, 129, 197, 128, 128, + 128, 0, 27, 181, 129, 197, 178, 182, + 126, 126, 0, 27, 129, 197, 179, 127, + 127, 127, 0, 27, 129, 197, 127, 127, + 127, 0, 27, 129, 197, 182, 126, 126, + 0, 129, 197, 126, 126, 126, 0, 124, + 197, 0, 188, 190, 191, 193, 194, 195, + 187, 189, 192, 186, 0, 186, 0, 187, + 0, 187, 0, 187, 0, 189, 0, 189, + 0, 189, 0, 11, 0, 186, 0, 13, + 15, 16, 18, 19, 20, 12, 14, 17, + 196, 196, 196, 0, 0, 0, 1, 2, + 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 41, 42, + 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 66, + 67, 68, 69, 70, 71, 72, 73, 74, + 75, 76, 77, 78, 79, 80, 81, 82, + 83, 84, 85, 86, 87, 88, 89, 90, + 91, 92, 93, 94, 95, 96, 97, 98, + 99, 100, 101, 102, 103, 104, 105, 106, + 107, 108, 109, 110, 111, 112, 113, 114, + 115, 116, 117, 118, 119, 120, 121, 122, + 123, 124, 125, 126, 127, 128, 129, 130, + 131, 132, 133, 134, 135, 136, 137, 138, + 139, 140, 141, 142, 143, 144, 145, 146, + 147, 148, 149, 150, 151, 152, 153, 154, + 155, 156, 157, 158, 159, 160, 161, 162, + 163, 164, 165, 166, 167, 168, 169, 170, + 171, 172, 173, 174, 175, 176, 177, 178, + 179, 180, 181, 182, 183, 184, 185, 186, + 187, 188, 189, 190, 191, 192, 193, 194, + 195, 196, 197, 0 +}; + +static const signed char _address_cond_actions[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 3, 0, 3, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 3, 0, 3, 0, 3, + 0, 3, 0, 3, 0, 3, 0, 3, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 3, 1, 3, 0, + 3, 0, 3, 0, 3, 0, 3, 0, + 3, 0, 3, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 3, 0, + 0, 0, 0, 0, 0, 0, 1, 1, + 1, 3, 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, 0, 3, + 0, 0, 0, 0, 0, 3, 0, 0, + 3, 1, 3, 0, 0, 0, 0, 0, + 0, 3, 0, 0, 0, 0, 3, 0, + 3, 0, 0, 0, 0, 3, 0, 3, + 0, 0, 0, 0, 3, 1, 0, 3, + 1, 0, 3, 0, 1, 0, 0, 3, + 1, 0, 3, 0, 0, 3, 0, 0, + 3, 0, 0, 0, 0, 3, 0, 0, + 3, 0, 0, 3, 0, 0, 3, 0, + 0, 0, 0, 3, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 3, 0, 0, + 0, 0, 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 3, 0, 0, + 0, 0, 0, 0, 0, 3, 0, 0, + 0, 0, 0, 0, 3, 0, 0, 0, + 0, 0, 0, 3, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 1, 0, 0, 0, + 3, 0, 0, 0, 0, 3, 0, 0, + 0, 0, 3, 0, 3, 0, 0, 0, + 0, 3, 0, 0, 0, 0, 3, 0, + 0, 0, 0, 3, 0, 0, 0, 0, + 3, 0, 3, 0, 0, 0, 0, 3, + 0, 0, 0, 0, 3, 0, 0, 0, + 0, 3, 0, 0, 0, 0, 3, 0, + 3, 0, 0, 0, 0, 3, 0, 0, + 0, 0, 3, 0, 0, 0, 0, 3, + 0, 0, 0, 0, 3, 0, 3, 0, + 0, 0, 0, 3, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 3, 0, 0, + 0, 0, 3, 0, 3, 0, 0, 0, + 0, 3, 0, 0, 0, 0, 3, 0, + 0, 0, 0, 3, 0, 0, 0, 0, + 3, 0, 3, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 3, 0, 0, + 0, 0, 3, 0, 3, 0, 0, 0, + 3, 1, 0, 0, 0, 3, 1, 0, + 0, 0, 3, 1, 0, 0, 0, 3, + 0, 0, 0, 0, 0, 3, 0, 0, + 0, 0, 0, 3, 0, 0, 0, 0, + 0, 3, 0, 0, 0, 0, 0, 0, + 0, 3, 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 3, 1, 0, 0, + 0, 3, 0, 1, 0, 0, 0, 3, + 0, 1, 0, 0, 0, 3, 0, 1, + 0, 0, 0, 3, 0, 1, 3, 0, + 0, 0, 3, 0, 1, 0, 0, 0, + 3, 0, 1, 0, 0, 0, 3, 0, + 1, 0, 0, 0, 3, 0, 1, 3, + 0, 0, 0, 3, 0, 1, 0, 0, + 0, 3, 0, 1, 0, 0, 0, 3, + 0, 1, 0, 0, 0, 3, 0, 1, + 3, 0, 0, 0, 3, 0, 1, 0, + 0, 0, 3, 0, 1, 0, 0, 0, + 3, 0, 1, 0, 0, 0, 3, 0, + 1, 3, 0, 0, 0, 3, 0, 1, + 0, 0, 0, 3, 0, 1, 0, 0, + 0, 3, 0, 1, 0, 0, 0, 3, + 0, 1, 3, 0, 0, 0, 0, 3, + 0, 0, 0, 1, 0, 0, 0, 3, + 0, 0, 1, 0, 0, 0, 3, 0, + 1, 0, 0, 0, 3, 0, 1, 0, + 0, 0, 3, 0, 1, 3, 0, 0, + 0, 0, 0, 0, 3, 0, 0, 1, + 0, 0, 0, 3, 0, 1, 0, 0, + 0, 3, 0, 1, 0, 0, 0, 3, + 0, 1, 3, 0, 0, 0, 0, 0, + 0, 3, 0, 0, 1, 0, 0, 0, + 3, 0, 1, 0, 0, 0, 3, 0, + 1, 0, 0, 0, 3, 0, 1, 3, + 0, 0, 0, 0, 0, 0, 3, 0, + 0, 1, 0, 0, 0, 3, 0, 1, + 0, 0, 0, 3, 0, 1, 0, 0, + 0, 3, 0, 1, 3, 0, 0, 0, + 0, 0, 0, 3, 0, 0, 1, 0, + 0, 0, 3, 0, 0, 1, 0, 0, + 0, 3, 0, 0, 1, 0, 0, 0, + 3, 0, 0, 1, 0, 0, 0, 3, + 0, 0, 0, 1, 0, 0, 0, 0, + 3, 0, 0, 1, 0, 0, 0, 0, + 3, 0, 0, 1, 0, 0, 0, 3, + 0, 0, 1, 0, 0, 0, 3, 0, + 0, 1, 0, 0, 0, 3, 0, 0, + 1, 0, 0, 0, 3, 0, 0, 1, + 0, 0, 0, 3, 0, 0, 0, 1, + 0, 0, 0, 0, 3, 0, 0, 1, + 0, 0, 0, 0, 3, 0, 0, 1, + 0, 0, 0, 3, 0, 0, 1, 0, + 0, 0, 3, 0, 1, 0, 0, 0, + 3, 0, 0, 1, 0, 0, 0, 3, + 0, 0, 1, 0, 0, 0, 3, 0, + 0, 1, 0, 0, 0, 3, 0, 0, + 0, 1, 0, 0, 0, 0, 3, 0, + 0, 1, 0, 0, 0, 0, 3, 0, + 0, 1, 0, 0, 0, 3, 0, 0, + 1, 0, 0, 0, 3, 0, 1, 0, + 0, 0, 3, 0, 0, 1, 0, 0, + 0, 3, 0, 0, 1, 0, 0, 0, + 3, 0, 0, 1, 0, 0, 0, 3, + 0, 0, 0, 1, 0, 0, 0, 0, + 3, 0, 0, 1, 0, 0, 0, 0, + 3, 0, 0, 1, 0, 0, 0, 3, + 0, 0, 1, 0, 0, 0, 3, 0, + 1, 0, 0, 0, 3, 0, 0, 1, + 0, 0, 0, 3, 0, 0, 1, 0, + 0, 0, 3, 0, 0, 1, 0, 0, + 0, 3, 0, 0, 0, 1, 0, 0, + 0, 0, 3, 0, 0, 1, 0, 0, + 0, 0, 3, 0, 0, 1, 0, 0, + 0, 3, 0, 0, 1, 0, 0, 0, + 3, 0, 1, 0, 0, 0, 3, 0, + 1, 3, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 3, 0, + 3, 0, 3, 0, 3, 0, 3, 0, + 3, 0, 3, 0, 3, 0, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 3, 3, 0, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 0, 0, 0 +}; + +static const short _address_eof_trans[] = { + 1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, + 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, + 1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, + 1110, 1111, 1112, 1113, 1114, 1115, 1116, 1117, + 1118, 1119, 1120, 1121, 1122, 1123, 1124, 1125, + 1126, 1127, 1128, 1129, 1130, 1131, 1132, 1133, + 1134, 1135, 1136, 1137, 1138, 1139, 1140, 1141, + 1142, 1143, 1144, 1145, 1146, 1147, 1148, 1149, + 1150, 1151, 1152, 1153, 1154, 1155, 1156, 1157, + 1158, 1159, 1160, 1161, 1162, 1163, 1164, 1165, + 1166, 1167, 1168, 1169, 1170, 1171, 1172, 1173, + 1174, 1175, 1176, 1177, 1178, 1179, 1180, 1181, + 1182, 1183, 1184, 1185, 1186, 1187, 1188, 1189, + 1190, 1191, 1192, 1193, 1194, 1195, 1196, 1197, + 1198, 1199, 1200, 1201, 1202, 1203, 1204, 1205, + 1206, 1207, 1208, 1209, 1210, 1211, 1212, 1213, + 1214, 1215, 1216, 1217, 1218, 1219, 1220, 1221, + 1222, 1223, 1224, 1225, 1226, 1227, 1228, 1229, + 1230, 1231, 1232, 1233, 1234, 1235, 1236, 1237, + 1238, 1239, 1240, 1241, 1242, 1243, 1244, 1245, + 1246, 1247, 1248, 1249, 1250, 1251, 1252, 1253, + 1254, 1255, 1256, 1257, 1258, 1259, 1260, 1261, + 1262, 1263, 1264, 1265, 1266, 1267, 1268, 1269, + 1270, 1271, 1272, 1273, 1274, 1275, 1276, 1277, + 1278, 1279, 1280, 1281, 1282, 1283, 0 +}; + +static const int address_start = 1; +static const int address_first_final = 196; +static const int address_error = 0; + +static const int address_en_main = 1; + + +#line 112 "smtp-address-validator.rl" + + +bool is_address(const char* p, const char* pe) +{ + int cs = 0; + + const char* eof = pe; + + bool result = false; + + +#line 675 "smtp-address-validator.cpp" + { + cs = (int)address_start; + } + +#line 124 "smtp-address-validator.rl" + + +#line 680 "smtp-address-validator.cpp" + { + int _klen; + unsigned int _trans = 0; + const char * _keys; + const signed char * _acts; + unsigned int _nacts; + _resume: {} + if ( p == pe && p != eof ) + goto _out; + if ( p == eof ) { + if ( _address_eof_trans[cs] > 0 ) { + _trans = (unsigned int)_address_eof_trans[cs] - 1; + } + } + else { + _keys = ( _address_trans_keys + (_address_key_offsets[cs])); + _trans = (unsigned int)_address_index_offsets[cs]; + + _klen = (int)_address_single_lengths[cs]; + if ( _klen > 0 ) { + const char *_lower = _keys; + const char *_upper = _keys + _klen - 1; + const char *_mid; + while ( 1 ) { + if ( _upper < _lower ) { + _keys += _klen; + _trans += (unsigned int)_klen; + break; + } + + _mid = _lower + ((_upper-_lower) >> 1); + if ( ( (*( p))) < (*( _mid)) ) + _upper = _mid - 1; + else if ( ( (*( p))) > (*( _mid)) ) + _lower = _mid + 1; + else { + _trans += (unsigned int)(_mid - _keys); + goto _match; + } + } + } + + _klen = (int)_address_range_lengths[cs]; + if ( _klen > 0 ) { + const char *_lower = _keys; + const char *_upper = _keys + (_klen<<1) - 2; + const char *_mid; + while ( 1 ) { + if ( _upper < _lower ) { + _trans += (unsigned int)_klen; + break; + } + + _mid = _lower + (((_upper-_lower) >> 1) & ~1); + if ( ( (*( p))) < (*( _mid)) ) + _upper = _mid - 2; + else if ( ( (*( p))) > (*( _mid + 1)) ) + _lower = _mid + 2; + else { + _trans += (unsigned int)((_mid - _keys)>>1); + break; + } + } + } + + _match: {} + } + cs = (int)_address_cond_targs[_trans]; + + if ( _address_cond_actions[_trans] != 0 ) { + + _acts = ( _address_actions + (_address_cond_actions[_trans])); + _nacts = (unsigned int)(*( _acts)); + _acts += 1; + while ( _nacts > 0 ) { + switch ( (*( _acts)) ) + { + case 0: { + { +#line 108 "smtp-address-validator.rl" + result = true; } + +#line 762 "smtp-address-validator.cpp" + + break; + } + case 1: { + { +#line 108 "smtp-address-validator.rl" + result = false; } + +#line 770 "smtp-address-validator.cpp" + + break; + } + } + _nacts -= 1; + _acts += 1; + } + + } + + if ( p == eof ) { + if ( cs >= 196 ) + goto _out; + } + else { + if ( cs != 0 ) { + p += 1; + goto _resume; + } + } + _out: {} + } + +#line 125 "smtp-address-validator.rl" + + + return result; +} diff --git a/src/smtp-address-validator.hpp b/src/smtp-address-validator.hpp new file mode 100644 index 0000000..5552c3e --- /dev/null +++ b/src/smtp-address-validator.hpp @@ -0,0 +1,34 @@ +#ifndef SMTP_ADDRESS_PARSER_HPP_INCLUDED +#define SMTP_ADDRESS_PARSER_HPP_INCLUDED + +/* + +Snarfed from + +: + +Copyright (c) 2021 Gene Hightower + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +*/ + +bool is_address(const char* p, const char* pe); + +#endif // SMTP_ADDRESS_PARSER_HPP_INCLUDED diff --git a/src/string-format-check.cpp b/src/string-format-check.cpp index cd908f0..ce69396 100644 --- a/src/string-format-check.cpp +++ b/src/string-format-check.cpp @@ -1,5 +1,7 @@ #include +#include + #include #include #include @@ -180,91 +182,15 @@ const std::string uuid{R"([0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a- // from http://stackoverflow.com/questions/106179/regular-expression-to-match-dns-hostname-or-ip-address const std::string hostname{R"(^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])(\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9]))*$)"}; -/** - * @see https://tools.ietf.org/html/rfc5322#section-4.1 - * - * @verbatim - * atom = [CFWS] 1*atext [CFWS] - * word = atom / quoted-string - * phrase = 1*word / obs-phrase - * obs-FWS = 1*WSP *(CRLF 1*WSP) - * FWS = ([*WSP CRLF] 1*WSP) / obs-FWS - * ; Folding white space - * ctext = %d33-39 / ; Printable US-ASCII - * %d42-91 / ; characters not including - * %d93-126 / ; "(", ")", or "\" - * obs-ctext - * ccontent = ctext / quoted-pair / comment - * comment = "(" *([FWS] ccontent) [FWS] ")" - * CFWS = (1*([FWS] comment) [FWS]) / FWS - * obs-local-part = word *("." word) - * obs-domain = atom *("." atom) - * obs-dtext = obs-NO-WS-CTL / quoted-pair - * quoted-pair = ("\" (VCHAR / WSP)) / obs-qp - * obs-NO-WS-CTL = %d1-8 / ; US-ASCII control - * %d11 / ; characters that do not - * %d12 / ; include the carriage - * %d14-31 / ; return, line feed, and - * %d127 ; white space characters - * obs-ctext = obs-NO-WS-CTL - * obs-qtext = obs-NO-WS-CTL - * obs-utext = %d0 / obs-NO-WS-CTL / VCHAR - * obs-qp = "\" (%d0 / obs-NO-WS-CTL / LF / CR) - * obs-body = *((*LF *CR *((%d0 / text) *LF *CR)) / CRLF) - * obs-unstruct = *((*LF *CR *(obs-utext *LF *CR)) / FWS) - * obs-phrase = word *(word / "." / CFWS) - * obs-phrase-list = [phrase / CFWS] *("," [phrase / CFWS]) - * qtext = %d33 / ; Printable US-ASCII - * %d35-91 / ; characters not including - * %d93-126 / ; "\" or the quote character - * obs-qtext - * qcontent = qtext / quoted-pair - * quoted-string = [CFWS] - * DQUOTE *([FWS] qcontent) [FWS] DQUOTE - * [CFWS] - * atext = ALPHA / DIGIT / ; Printable US-ASCII - * "!" / "#" / ; characters not including - * "$" / "%" / ; specials. Used for atoms. - * "&" / "'" / - * "*" / "+" / - * "-" / "/" / - * "=" / "?" / - * "^" / "_" / - * "`" / "{" / - * "|" / "}" / - * "~" - * dot-atom-text = 1*atext *("." 1*atext) - * dot-atom = [CFWS] dot-atom-text [CFWS] - * addr-spec = local-part "@" domain - * local-part = dot-atom / quoted-string / obs-local-part - * domain = dot-atom / domain-literal / obs-domain - * domain-literal = [CFWS] "[" *([FWS] dtext) [FWS] "]" [CFWS] - * dtext = %d33-90 / ; Printable US-ASCII - * %d94-126 / ; characters not including - * obs-dtext ; "[", "]", or "\" - * @endverbatim - * @todo Currently don't have a working tool for this larger ABNF to generate a regex. - * Other options: - * - https://github.com/ldthomas/apg-6.3 - * - https://github.com/akr/abnf - * - * The problematic thing are the allowed whitespaces (even newlines) in the email. - * Ignoring those and starting with - * @see https://stackoverflow.com/questions/13992403/regex-validation-of-email-addresses-according-to-rfc5321-rfc5322 - * and trying to divide up the complicated regex into understandable ABNF definitions from rfc5322 yields: - */ -const std::string obsnowsctl{R"([\x01-\x08\x0b\x0c\x0e-\x1f\x7f])"}; -const std::string obsqp{R"(\\[\x01-\x09\x0b\x0c\x0e-\x7f])"}; -const std::string qtext{R"((?:[\x21\x23-\x5b\x5d-\x7e]|)" + obsnowsctl + ")"}; -const std::string dtext{R"([\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f])"}; -const std::string quotedString{R"("(?:)" + qtext + "|" + obsqp + R"()*")"}; -const std::string atext{R"([A-Za-z0-9!#$%&'*+/=?^_`{|}~-])"}; -const std::string domainLiteral{R"(\[(?:(?:)" + decOctet + R"()\.){3}(?:)" + decOctet + R"(|[A-Za-z0-9-]*[A-Za-z0-9]:(?:)" + dtext + "|" + obsqp + R"()+)\])"}; - -const std::string dotAtom{"(?:" + atext + R"(+(?:\.)" + atext + "+)*)"}; -const std::string stackoverflowMagicPart{R"((?:[[:alnum:]](?:[[:alnum:]-]*[[:alnum:]])?\.)+)" - R"([[:alnum:]](?:[[:alnum:]-]*[[:alnum:]])?)"}; -const std::string email{"(?:" + dotAtom + "|" + quotedString + ")@(?:" + stackoverflowMagicPart + "|" + domainLiteral + ")"}; +bool is_ascii(std::string const& value) +{ + for (auto ch : value) { + if (ch & 0x80) { + return false; + } + } + return true; +} /** * @see @@ -425,9 +351,15 @@ void default_string_format_check(const std::string &format, const std::string &v } else if (format == "uri") { rfc3986_uri_check(value); } else if (format == "email") { - static const std::regex emailRegex{email}; - if (!std::regex_match(value, emailRegex)) { - throw std::invalid_argument(value + " is not a valid email according to RFC 5322."); + if (!is_ascii(value)) { + throw std::invalid_argument(value + " contains non-ASCII values, not RFC 5321 compliant."); + } + if (!is_address(&*value.begin(), &*value.end())) { + throw std::invalid_argument(value + " is not a valid email according to RFC 5321."); + } + } else if (format == "idn-email") { + if (!is_address(&*value.begin(), &*value.end())) { + throw std::invalid_argument(value + " is not a valid idn-email according to RFC 6531."); } } else if (format == "hostname") { static const std::regex hostRegex{hostname}; diff --git a/test/JSON-Schema-Test-Suite/CMakeLists.txt b/test/JSON-Schema-Test-Suite/CMakeLists.txt index 1a240c6..3d93b55 100644 --- a/test/JSON-Schema-Test-Suite/CMakeLists.txt +++ b/test/JSON-Schema-Test-Suite/CMakeLists.txt @@ -54,7 +54,6 @@ if(JSON_SCHEMA_TEST_SUITE_PATH) JSON-Suite::Optional::float-overflow JSON-Suite::Optional::ecmascript-regex - JSON-Suite::Optional::Format::idn-email JSON-Suite::Optional::Format::idn-hostname JSON-Suite::Optional::Format::iri-reference JSON-Suite::Optional::Format::iri From 96a42559387e5cb3f30ef755d7bef22f2e2ce8f3 Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Sat, 26 Nov 2022 17:56:17 +0100 Subject: [PATCH 19/25] bump to 2.2.0 (some minor changes/addtions to API) --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9379b1b..afe6627 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,7 +15,7 @@ endif() project(nlohmann_json_schema_validator LANGUAGES CXX) -set(PROJECT_VERSION 2.1.1) +set(PROJECT_VERSION 2.2.0) if(JSON_VALIDATOR_HUNTER) hunter_add_package(nlohmann_json) From 6b17782d6a5d1dee5d2c4fc5d25ffb1123913431 Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Sat, 26 Nov 2022 18:05:52 +0100 Subject: [PATCH 20/25] update to SOVERSION to 2 (as it should have been done 3 years ago) fix #186 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index afe6627..f636734 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,7 +42,7 @@ target_compile_features(nlohmann_json_schema_validator set_target_properties(nlohmann_json_schema_validator PROPERTIES VERSION ${PROJECT_VERSION} - SOVERSION 1) + SOVERSION 2) # disable tests and examples if project is not super project if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) From f156a7fc7b95ef64a598f74cb829a89c3449c157 Mon Sep 17 00:00:00 2001 From: Christophe Blaess Date: Mon, 28 Nov 2022 07:17:57 +0100 Subject: [PATCH 21/25] Remove obsolete sentence in `README.md`. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b9dd8d9..1e930bf 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ This is a C++ library for validating JSON documents based on a [draft-7 of JSON Schema Validation](http://json-schema.org/schema). First a disclaimer: *It is work in progress and -contributions or hints or discussions are welcome.* Even though a 2.0.0 release is imminent. +contributions or hints or discussions are welcome.* Niels Lohmann et al develop a great JSON parser for C++ called [JSON for Modern C++](https://github.com/nlohmann/json). This validator is based on this From dfcb0152e952932f7c263b346411c5dfabbd57e1 Mon Sep 17 00:00:00 2001 From: Gareth Sylvester-Bradley <31761158+garethsb@users.noreply.github.com> Date: Mon, 28 Nov 2022 09:49:56 +0000 Subject: [PATCH 22/25] Local include for smtp-address-validator.hpp --- src/string-format-check.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/string-format-check.cpp b/src/string-format-check.cpp index ce69396..bd8952f 100644 --- a/src/string-format-check.cpp +++ b/src/string-format-check.cpp @@ -1,6 +1,6 @@ #include -#include +#include "smtp-address-validator.hpp" #include #include From 491ac44026e08f31790f5cacffa62e168bb35e32 Mon Sep 17 00:00:00 2001 From: Robert Joslyn Date: Wed, 30 Nov 2022 13:07:29 -0800 Subject: [PATCH 23/25] Fix assumed signed char The code assumes that char is signed, but whether char is signed or unsigned is implementation defined. On some architectures like PowerPC, GCC treats char as unsigned resulting in compile errors: smtp-address-validator.cpp:213:1: error: narrowing conversion of '-32' from 'int' to 'char' [-Wnarrowing] Fix this by specifying signed char. --- src/smtp-address-validator.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/smtp-address-validator.cpp b/src/smtp-address-validator.cpp index a63ead0..3903b51 100644 --- a/src/smtp-address-validator.cpp +++ b/src/smtp-address-validator.cpp @@ -63,7 +63,7 @@ static const short _address_key_offsets[] = { 1363, 1365, 1367, 1368, 1370, 1388, 0 }; -static const char _address_trans_keys[] = { +static const signed char _address_trans_keys[] = { -32, -19, -16, -12, 34, 45, 61, 63, -62, -33, -31, -17, -15, -13, 33, 39, 42, 43, 47, 57, 65, 90, 94, 126, @@ -711,7 +711,7 @@ bool is_address(const char* p, const char* pe) { int _klen; unsigned int _trans = 0; - const char * _keys; + const signed char * _keys; const signed char * _acts; unsigned int _nacts; _resume: {} @@ -728,9 +728,9 @@ bool is_address(const char* p, const char* pe) _klen = (int)_address_single_lengths[cs]; if ( _klen > 0 ) { - const char *_lower = _keys; - const char *_upper = _keys + _klen - 1; - const char *_mid; + const signed char *_lower = _keys; + const signed char *_upper = _keys + _klen - 1; + const signed char *_mid; while ( 1 ) { if ( _upper < _lower ) { _keys += _klen; @@ -752,9 +752,9 @@ bool is_address(const char* p, const char* pe) _klen = (int)_address_range_lengths[cs]; if ( _klen > 0 ) { - const char *_lower = _keys; - const char *_upper = _keys + (_klen<<1) - 2; - const char *_mid; + const signed char *_lower = _keys; + const signed char *_upper = _keys + (_klen<<1) - 2; + const signed char *_mid; while ( 1 ) { if ( _upper < _lower ) { _trans += (unsigned int)_klen; From 59c9d6200bf3cd54b4fc717ec1660c91eddb4d1a Mon Sep 17 00:00:00 2001 From: Sven Fink Date: Fri, 13 Jan 2023 09:15:42 +0100 Subject: [PATCH 24/25] For root value, use empty pointer --- src/json-validator.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/json-validator.cpp b/src/json-validator.cpp index 7f34553..3c73d98 100644 --- a/src/json-validator.cpp +++ b/src/json-validator.cpp @@ -553,6 +553,9 @@ class type_schema : public schema else_->validate(ptr, instance, patch, e); } } + if (instance.is_null()) { + patch.add(nlohmann::json::json_pointer{}, default_value_); + } } protected: @@ -1134,6 +1137,11 @@ public: propertyNames_ = schema::make(attr.value(), root, {"propertyNames"}, uris); sch.erase(attr); } + + attr = sch.find("default"); + if (attr != sch.end()) { + set_default_value(*attr); + } } }; From cae6fad80001510077a7f40e68477a31ec443add Mon Sep 17 00:00:00 2001 From: Sven Fink Date: Fri, 13 Jan 2023 09:16:17 +0100 Subject: [PATCH 25/25] Add test for issue 243 --- test/CMakeLists.txt | 4 +++ test/issue-243-root-default-values.cpp | 48 ++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 test/issue-243-root-default-values.cpp diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index fd1c309..9fa9c5b 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -73,3 +73,7 @@ add_test(NAME issue-149-entry-selection COMMAND issue-149-entry-selection) add_executable(issue-189-default-values issue-189-default-values.cpp) target_link_libraries(issue-189-default-values nlohmann_json_schema_validator) add_test(NAME issue-189-default-values COMMAND issue-189-default-values) + +add_executable(issue-243-root-default-values issue-243-root-default-values.cpp) +target_link_libraries(issue-243-root-default-values nlohmann_json_schema_validator) +add_test(NAME issue-243-root-default-values COMMAND issue-243-root-default-values) diff --git a/test/issue-243-root-default-values.cpp b/test/issue-243-root-default-values.cpp new file mode 100644 index 0000000..34f0582 --- /dev/null +++ b/test/issue-243-root-default-values.cpp @@ -0,0 +1,48 @@ +#include +#include + +using nlohmann::json; +using nlohmann::json_uri; +using nlohmann::json_schema::json_validator; + +static const json root_default = R"( +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "properties": { + "width": { + "type": "integer" + } + }, + "default": { + "width": 42 + } +})"_json; + +int main(void) +{ + json_validator validator{}; + + validator.set_root_schema(root_default); + + { + json nul_json; + if (!nul_json.is_null()) { + return 1; + } + + const auto default_patch = validator.validate(nul_json); + + if (default_patch.is_null()) { + std::cerr << "Patch is null but should contain operation to add defaults to root" << std::endl; + return 1; + } + + const auto actual = nul_json.patch(default_patch); + const auto expected = R"({"width": 42})"_json; + if (actual != expected) { + std::cerr << "Patch of defaults is wrong for root schema: '" << actual.dump() << "' instead of expected '" << expected.dump() << "'" << std::endl; + } + } + + return 0; +}