[
  {
    "path": ".clang-format",
    "content": "BasedOnStyle: LLVM\n#AlignConsecutiveAssignments: true\n#AlignConsecutiveDeclarations: true\nAllowShortFunctionsOnASingleLine: Inline\nBreakBeforeBraces: Linux\nColumnLimit: 0\nConstructorInitializerAllOnOneLineOrOnePerLine: true\nIndentWidth: 4\nIndentPPDirectives: AfterHash\nObjCBlockIndentWidth: 0\nSpaceAfterCStyleCast: true\nTabWidth: 4\nAccessModifierOffset: -4\nUseTab: ForIndentation\n"
  },
  {
    "path": ".distro/.fmf/version",
    "content": "1\n"
  },
  {
    "path": ".distro/json-schema-validator.spec",
    "content": "Name:           json-schema-validator\nSummary:        JSON schema validator for JSON for Modern C++\nVersion:        0.0.0\nRelease:        %autorelease\nLicense:        MIT\nURL:            https://github.com/pboettch/json-schema-validator\n\nSource:         https://github.com/pboettch/json-schema-validator/archive/refs/tags/v%{version}.tar.gz\n\nBuildRequires:  ninja-build\nBuildRequires:  cmake\nBuildRequires:  gcc-c++\nBuildRequires:  json-devel\n\n%description\nJson schema validator library for C++ projects using nlohmann/json\n\n%package        devel\nSummary:        Development files for JSON schema validator\nRequires:       json-schema-validator%{?_isa} = %{version}-%{release}\nRequires:       json-devel\n\n%description    devel\nJson schema validator development files for C++ projects using nlohmann/json\n\n\n%prep\n%autosetup -n json-schema-validator-%{version}\n\n\n%build\n%cmake \\\n    -DJSON_VALIDATOR_SHARED_LIBS=ON \\\n    -DJSON_VALIDATOR_INSTALL=ON \\\n    -DJSON_VALIDATOR_BUILD_EXAMPLES=OFF \\\n    -DJSON_VALIDATOR_BUILD_TESTS=ON\n\n%cmake_build\n\n\n%install\n%cmake_install\n\n\n%check\n%ctest\n\n\n%files\n%doc README.md\n%license LICENSE\n%{_libdir}/libnlohmann_json_schema_validator.so.*\n\n%files devel\n%{_libdir}/libnlohmann_json_schema_validator.so\n%{_includedir}/nlohmann/json-schema.hpp\n%{_libdir}/cmake/nlohmann_json_schema_validator\n\n\n%changelog\n%autochangelog\n"
  },
  {
    "path": ".distro/plans/import.fmf",
    "content": "summary:\n  Basic importing tests\nprepare+:\n  - name: Include minimum fetching packages\n    how: install\n    package:\n      - git\ndiscover+:\n  how: fmf\n  filter: \"tag: import\"\nexecute:\n    how: tmt\n"
  },
  {
    "path": ".distro/plans/main.fmf.dist-git",
    "content": "discover:\n  how: fmf\n  path: .\n\nadjust+:\n  # Cannot use initiator: fedora-ci reliably yet\n  when: initiator is not defined or initiator != packit\n  discover+:\n    dist-git-source: true\n    dist-git-extract: json-schema-validator-*/\n"
  },
  {
    "path": ".distro/plans/smoke.fmf",
    "content": "summary:\n  Basic smoke tests\ndiscover+:\n  how: fmf\n  filter: \"tag: smoke\"\nexecute:\n    how: tmt\n"
  },
  {
    "path": ".distro/tests/import/FetchContent/CMakeLists.txt",
    "content": "# This is a simple project that tests using cmake to load the installed libraries\ncmake_minimum_required(VERSION 3.14)\n\nproject(test_fetch_content LANGUAGES CXX)\n\n\nFetchContent_Declare(nlohmann_json_schema_validator\n\t\tGIT_REPOSITORY https://github.com/pboettch/json-schema-validator\n\t\tGIT_TAG main\n\t\t)\nFetchContent_MakeAvailable(nlohmann_json_schema_validator)\n\nif (NOT TARGET nlohmann_json_schema_validator::validator)\n\tmessage(FATAL_ERROR \"Missing target nlohmann_json_schema_validator::validator\")\nendif ()\n"
  },
  {
    "path": ".distro/tests/import/find_package/CMakeLists.txt",
    "content": "# This is a simple project that tests using cmake to load the installed libraries\ncmake_minimum_required(VERSION 3.14)\n\nproject(test_find_package LANGUAGES CXX)\n\nset(CMAKE_FIND_DEBUG_MODE ON)\nfind_package(nlohmann_json_schema_validator REQUIRED)\n\nif (NOT TARGET nlohmann_json_schema_validator::validator)\n\tmessage(FATAL_ERROR \"Missing target nlohmann_json_schema_validator::validator\")\nendif ()\n"
  },
  {
    "path": ".distro/tests/import/main.fmf",
    "content": "# Common test variables\ntag:\n  - import\ntier: 0\npath: /tests/import\n\n# Define tests\n/find_package:\n  test: ./test_find_package.sh\n/FetchContent:\n  test: ./test_FetchContent.sh\n"
  },
  {
    "path": ".distro/tests/import/test_FetchContent.sh",
    "content": "#!/bin/bash -eux\n\ntmp_dir=$(mktemp -d)\ncmake -S ./FetchContent -B ${tmp_dir}\n"
  },
  {
    "path": ".distro/tests/import/test_find_package.sh",
    "content": "#!/bin/bash -eux\n\ntmp_dir=$(mktemp -d)\ncmake -S ./find_package -B ${tmp_dir}\n"
  },
  {
    "path": ".distro/tests/smoke.fmf",
    "content": "# Common test variables\ntag:\n  - smoke\ntier: 0\npath: /\n\n# Define tests\n/version:\n  test: echo \"TODO: Write a minimum working example\"\n"
  },
  {
    "path": ".github/workflows/release.yaml",
    "content": "name: release\nrun-name: Release\n\non:\n  push:\n    tags:\n      - \"[0-9]+.[0-9]+.[0-9]+\"\n\njobs:\n  tests:\n    uses: ./.github/workflows/test.yaml\n    secrets: inherit\n\n  publish-release:\n    needs: [tests]\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v4\n      - name: Create GitHub Release\n        uses: softprops/action-gh-release@v2\n        with:\n          name: \"json-schema-validator ${{ github.ref }}\"\n          prerelease: false\n          draft: false\n          generate_release_notes: true\n\n  build_conan:\n    needs: [tests]\n    runs-on: ubuntu-latest\n    container: ghcr.io/nlohmann/json-ci:v2.4.0\n    steps:\n      - run: echo \"🎉 The job was automatically triggered by a ${{ github.event_name }} event.\"\n      - run: echo \"🐧 This job is now running on a ${{ runner.os }} server hosted by GitHub.\"\n      - run: echo \"🔎 Branch name is ${{ github.ref }} and repository is ${{ github.repository }}.\"\n      - name: Clone json-schema-validator\n        uses: actions/checkout@v3\n      - uses: actions/setup-python@v4\n        with:\n          python-version: '3.10'\n      - run: python -m pip install --upgrade conan\n      - run: conan config init\n      - run: conan profile update settings.compiler.libcxx=libstdc++11 default\n      - name: conan create package\n        run: conan create .\n"
  },
  {
    "path": ".github/workflows/test.yaml",
    "content": "name: test\nrun-name: Tests\n\non:\n  push:\n    branches: [ main ]\n  pull_request:\n    branches: [ main ]\n  # Make it able to be used in other workflows\n  workflow_call:\n\ndefaults:\n  run:\n    shell: bash\n\njobs:\n  pre-commit:\n    name: Check pre-commit\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v3\n      - uses: actions/setup-python@v4\n      - uses: pre-commit/action@v3.0.0\n\n  test:\n    name: Run ctests\n    needs: [ pre-commit ]\n    continue-on-error: ${{ matrix.experimental }}\n    strategy:\n      fail-fast: false\n      matrix:\n        toolchain: [ gcc, llvm, intel ]\n        json_version: [ develop, v3.12.0, v3.8.0 ]\n        experimental: [ false ]\n        include:\n          - toolchain: llvm\n            compiler_version: 15\n          - toolchain: gcc\n            compiler_version: latest\n    env:\n      NLOHMANN_JSON_VERSION: ${{ matrix.json_version }}\n    runs-on: ubuntu-latest\n    container: ghcr.io/nlohmann/json-ci:v2.4.0\n    steps:\n      - name: Activate Intel compilers\n        # Not elegant, it will propagate all environment variable.\n        # Intel does not provide a way to output the environment variables to a file\n        # Note: PATH needs to be exported to GITHUB_PATH otherwise it can be overwritten\n        run: |\n          source /opt/intel/oneapi/setvars.sh\n          printenv >> $GITHUB_ENV\n          echo $PATH >> $GITHUB_PATH\n        if: matrix.toolchain == 'intel'\n      - name: Setup gcc toolchain\n        run: |\n          update-alternatives --install /usr/bin/g++ g++ $(which g++-${{ matrix.compiler_version }}) 999\n        if: matrix.compiler_version && matrix.toolchain == 'gcc'\n      - name: Setup llvm toolchain\n        run: |\n          update-alternatives --install /usr/bin/clang++ clang++ $(which clang++-${{ matrix.compiler_version }}) 999\n        if: matrix.compiler_version && matrix.toolchain == 'llvm'\n      - uses: actions/checkout@v3\n        # container version is < 3.25 which does not have workflows\n      - name: Get a working cmake version\n        uses: lukka/get-cmake@v3.25.2\n      - name: Run CMake ${{ matrix.toolchain }}-ci workflow with nlohmann/json version ${{ matrix.json_version }}\n        uses: lukka/run-cmake@v10.5\n        with:\n          workflowPreset: \"${{ matrix.toolchain }}-ci\"\n  coverage:\n    name: Run coverage tests\n    needs: [ test ]\n    runs-on: ubuntu-latest\n    container: ghcr.io/nlohmann/json-ci:v2.4.0\n    if: ${{ github.event_name == 'push' || github.event_name == 'pull_request' }}\n    steps:\n      - uses: actions/checkout@v3\n      - name: Get latest cmake version\n        uses: lukka/get-cmake@latest\n      - name: Get test coverage\n        uses: lukka/run-cmake@v10.5\n        with:\n          workflowPreset: ci-coverage\n      - name: Get lcov data\n        uses: danielealbano/lcov-action@v3\n        with:\n          # Note lcov-action prepends and appends wild-cards *. Account for those\n          # https://github.com/danielealbano/lcov-action/issues/11\n          remove_patterns: /test/,/cmake-build*/\n      - name: Upload coverage to Codecov\n        uses: codecov/codecov-action@v3\n        with:\n          files: coverage.info\n          verbose: true\n"
  },
  {
    "path": ".gitignore",
    "content": "build*/\n*.sw?\ncmake-build-*\nvenv\nenv\ncompile_commands.json\n.vs/*\n"
  },
  {
    "path": ".packit.yaml",
    "content": "files_to_sync:\n  - src: .distro/\n    dest: ./\n    delete: true\n    filters:\n      - \"protect .git*\"\n      - \"protect sources\"\n      - \"protect changelog\"\n      - \"protect gating.yaml\"\n      # Temporary workaround until\n      # https://github.com/packit/packit/pull/2573\n      - \"- json-schema-validator.spec\"\n  - .packit.yaml\n\nupstream_package_name: json-schema-validator\nspecfile_path: .distro/json-schema-validator.spec\ndownstream_package_name: json-schema-validator\nupdate_release: false\n\ntargets: &targets\n  - fedora-all-x86_64\n  # TODO: aarch64 is failing at test\n  # JSON-Suite::Optional::Format::idn-email\n  # - fedora-all-aarch64\n\n_:\n  # Job templates\n  - &build-in-packit\n    job: copr_build\n  - &build-in-lecris\n    <<: *build-in-packit\n    owner: \"@scikit-build\"\n  - &tests\n    job: tests\n    fmf_path: .distro\n    identifier: downstream\n\njobs:\n  # Upstream jobs\n  - <<: *build-in-lecris\n    trigger: release\n    project: release\n#  - <<: *tests\n#    trigger: release\n  - <<: *build-in-lecris\n    trigger: commit\n    branch: main\n    project: nightly\n#  - <<: *tests\n#    trigger: commit\n#    branch: main\n  - <<: *build-in-packit\n    trigger: pull_request\n#  - <<: *tests\n#    trigger: pull_request\n  # Downstream jobs\n  - job: propose_downstream\n    trigger: release\n    dist_git_branches:\n      - fedora-rawhide\n  - job: koji_build\n    trigger: commit\n    dist_git_branches:\n      - fedora-all\n  - job: bodhi_update\n    trigger: commit\n    dist_git_branches:\n      - fedora-branched\n"
  },
  {
    "path": ".pre-commit-config.yaml",
    "content": "repos:\n  - repo: https://github.com/Takishima/cmake-pre-commit-hooks\n    rev: v1.9.6\n    hooks:\n      - id: clang-format\n        args:\n          - '-i'\n      - id: clang-tidy\n        args:\n          # TODO: Remove when upstream issue is fixed\n          # https://gitlab.kitware.com/cmake/cmake/-/issues/24827\n          # https://github.com/Takishima/cmake-pre-commit-hooks/issues/63\n          - '-Bcmake-build-pre-commit'\n          - '--preset'\n          - 'pre-commit'\n        stages: [ manual ]\n  - repo: https://github.com/pre-commit/pre-commit-hooks\n    rev: v6.0.0\n    hooks:\n      - id: trailing-whitespace\n      - id: end-of-file-fixer\n      - id: check-yaml\n  - repo: https://github.com/executablebooks/mdformat\n    rev: 0.7.22\n    hooks:\n      - id: mdformat\n        additional_dependencies:\n          - mdformat-gfm\n          - mdformat-tables\n  - repo: https://github.com/python-jsonschema/check-jsonschema\n    rev: 0.34.0\n    hooks:\n      - id: check-github-workflows\n"
  },
  {
    "path": "CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 3.14)\n# CMake version compatibility\n# TODO: Remove when bumping cmake >= 3.25\nif (POLICY CMP0140)\n    # Enables: return(PROPAGATE)\n    cmake_policy(SET CMP0140 NEW)\nendif ()\n\n#[==============================================================================================[\n#                                    Basic project definition                                   #\n]==============================================================================================]\n\n# TODO: CMake >= 3.19 can use string(JSON VERSION GET \"${METADATA}\" \"version\") to load from JSON\nset(PROJECT_VERSION 2.4.0)\n\n# TODO: Version 3, rename the project and namespace to something more compact\nproject(nlohmann_json_schema_validator\n        VERSION ${PROJECT_VERSION}\n        DESCRIPTION \"Json validator for nlohmann::json library\"\n        HOMEPAGE_URL \"https://github.com/pboettch/json-schema-validator\"\n        LANGUAGES CXX)\n# TODO: Remove when bumping cmake >= 3.21\nif (NOT DEFINED nlohmann_json_schema_validator_IS_TOP_LEVEL)\n    if (CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)\n        set(PROJECT_IS_TOP_LEVEL ON)\n    else ()\n        set(PROJECT_IS_TOP_LEVEL OFF)\n    endif ()\nendif ()\n\n#[==============================================================================================[\n#                                            Options                                            #\n]==============================================================================================]\n\noption(JSON_VALIDATOR_INSTALL \"JsonValidator: Install targets\" ${PROJECT_IS_TOP_LEVEL})\noption(JSON_VALIDATOR_BUILD_TESTS \"JsonValidator: Build tests\" ${PROJECT_IS_TOP_LEVEL})\noption(JSON_VALIDATOR_BUILD_EXAMPLES \"JsonValidator: Build examples\" ${PROJECT_IS_TOP_LEVEL})\noption(JSON_VALIDATOR_SHARED_LIBS \"JsonValidator: Build as shared library\" ${PROJECT_IS_TOP_LEVEL})\noption(JSON_VALIDATOR_TEST_COVERAGE \"JsonValidator: Build with test coverage\" OFF)\nmark_as_advanced(JSON_VALIDATOR_TEST_COVERAGE)\n# Get a default JSON_FETCH_VERSION from environment variables to workaround the CI\nif (DEFINED ENV{NLOHMANN_JSON_VERSION})\n    set(JSON_FETCH_VERSION_DEFAULT $ENV{NLOHMANN_JSON_VERSION})\nelse ()\n    set(JSON_FETCH_VERSION_DEFAULT v3.12.0)\nendif ()\nset(JSON_FETCH_VERSION ${JSON_FETCH_VERSION_DEFAULT} CACHE STRING \"Fetch nlohmann::json version\")\n\n#[==============================================================================================[\n#                                     Project configuration                                     #\n]==============================================================================================]\n\n# Include cmake modules\ninclude(FetchContent)\nif (JSON_VALIDATOR_INSTALL)\n    include(GNUInstallDirs)\n    include(CMakePackageConfigHelpers)\nendif ()\n\n# Default to release build\nif (NOT CMAKE_BUILD_TYPE)\n    set(CMAKE_BUILD_TYPE Release)\nendif ()\n\n# Enable cmake's BUILD_SHARED_LIBS\nset(BUILD_SHARED_LIBS ${nlohmann_json_schema_validator_SHARED_LIBS})\n\nif (JSON_VALIDATOR_TEST_COVERAGE)\n    if (CMAKE_CXX_COMPILER_ID STREQUAL Clang)\n        set(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -fprofile-instr-generate -fcoverage-mapping\")\n    elseif (CMAKE_CXX_COMPILER_ID STREQUAL GNU)\n        set(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} --coverage\")\n    else ()\n        message(WARNING\n                \"JsonValidator: Other toolchain coverage flags unknown.\\n\"\n                \"Using --coverage as default\")\n        set(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} --coverage\")\n    endif ()\nendif ()\n\n#[==============================================================================================[\n#                                       External packages                                       #\n]==============================================================================================]\n\nset(fetch_packages \"\")\nif (NOT TARGET nlohmann_json)\n  # Fetch/Find nlohmann_json\n  # TODO: Remove when bumping cmake >= 3.24\n  if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.24)\n      FetchContent_Declare(nlohmann_json\n              GIT_REPOSITORY https://github.com/nlohmann/json\n              GIT_TAG ${JSON_FETCH_VERSION}\n              FIND_PACKAGE_ARGS\n              )\n      list(APPEND fetch_packages nlohmann_json)\n  else ()\n      # Try to get system installed version\n      find_package(nlohmann_json QUIET)\n      if (NOT nlohmann_json_FOUND)\n          # If failed fetch the desired version\n          FetchContent_Declare(nlohmann_json\n                  GIT_REPOSITORY https://github.com/nlohmann/json\n                  GIT_TAG ${JSON_FETCH_VERSION}\n                  )\n          list(APPEND fetch_packages nlohmann_json)\n      endif ()\n  endif ()\nendif ()\n\n# Handle configure flags\nif (JSON_VALIDATOR_INSTALL)\n    # TODO: This is not ideal, this package should not be installing nlohmann::json\n    # Currently required in order to satisfy cmake exporter\n    set(JSON_Install ON CACHE BOOL \"\")\nendif ()\n\n# Get all dependencies\nFetchContent_MakeAvailable(${fetch_packages})\nif (JSON_VALIDATOR_INSTALL AND NOT nlohmann_json_FOUND AND JSON_Install)\n    # TODO: This is not ideal\n    message(WARNING\n            \"JsonValidator: No nlohmann::json found on the system and nlohmann_json_schema_validator will be installed\\n\"\n            \"This will also install nlohmann::json in its typical installation path\\n\"\n            \"This is not ideal because it might overwrite system installed\")\nendif ()\n\n#[==============================================================================================[\n#                                        Main definition                                        #\n]==============================================================================================]\n\nmessage(STATUS \"JsonValidator: Configured for ${CMAKE_BUILD_TYPE}\")\nif (DEFINED nlohmann_json_VERSION)\n    message(STATUS \"JsonValidator: Using nlohmann/json version: ${nlohmann_json_VERSION}\")\nelse ()\n    message(STATUS \"JsonValidator: nlohmann_json_VERSION is not set. Possible value: ${JSON_FETCH_VERSION}\")\nendif ()\n\n## Main targets\nadd_library(nlohmann_json_schema_validator)\nadd_library(nlohmann_json_schema_validator::validator ALIAS nlohmann_json_schema_validator)\nset_target_properties(nlohmann_json_schema_validator PROPERTIES\n        VERSION ${PROJECT_VERSION}\n        SOVERSION ${PROJECT_VERSION_MAJOR}\n        EXPORT_NAME validator\n        # TODO: Version 3, simplify the library name\n#        OUTPUT_NAME nlohmann_json_validator\n        )\n\n# Main definitions in here\nadd_subdirectory(src)\n\n# Enable examples\n\n# Enable testings\nif (JSON_VALIDATOR_BUILD_TESTS)\n    enable_testing()\n    add_subdirectory(test)\nendif ()\n\nif (JSON_VALIDATOR_BUILD_EXAMPLES)\n    add_subdirectory(example)\nendif ()\n\n\n#[==============================================================================================[\n#                                       Install or Export                                       #\n]==============================================================================================]\n\nif (JSON_VALIDATOR_INSTALL)\n    # Note other install targets found in subdirectories\n    # Here mostly the cmake boilerplate are set\n    write_basic_package_version_file(nlohmann_json_schema_validatorConfigVersion.cmake\n            VERSION ${PROJECT_VERSION}\n            COMPATIBILITY SameMajorVersion\n            )\n    configure_package_config_file(cmake/nlohmann_json_schema_validatorConfig.cmake.in\n            nlohmann_json_schema_validatorConfig.cmake\n            INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/nlohmann_json_schema_validator\n            )\n\n    # Install Targets files\n    export(EXPORT nlohmann_json_schema_validatorTargets\n            NAMESPACE nlohmann_json_schema_validator::\n            FILE nlohmann_json_schema_validatorTargets.cmake\n            )\n    install(EXPORT nlohmann_json_schema_validatorTargets\n            FILE nlohmann_json_schema_validatorTargets.cmake\n            NAMESPACE nlohmann_json_schema_validator::\n            DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/nlohmann_json_schema_validator\n            COMPONENT nlohmann_json_schema_validator_Development\n            )\n    # Install cmake export files\n    install(FILES\n            ${CMAKE_CURRENT_BINARY_DIR}/nlohmann_json_schema_validatorConfig.cmake\n            ${CMAKE_CURRENT_BINARY_DIR}/nlohmann_json_schema_validatorConfigVersion.cmake\n            DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/nlohmann_json_schema_validator\n            COMPONENT nlohmann_json_schema_validator_Development\n            )\nendif ()\n\n# Handle the project being included externally (e.g. FetchContent)\nif (NOT PROJECT_IS_TOP_LEVEL)\n    # Export variables set in nlohmann_json_schema_validatorConfig.cmake\n    # TODO: Remove when bumping cmake >= 3.25\n    if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.25)\n        return(PROPAGATE\n                nlohmann_json_schema_validator_VERSION\n                nlohmann_json_schema_validator_VERSION_MAJOR\n                nlohmann_json_schema_validator_VERSION_MINOR\n                nlohmann_json_schema_validator_VERSION_PATCH\n                nlohmann_json_schema_validator_VERSION_TWEAK\n                )\n    else ()\n        set(nlohmann_json_schema_validator_VERSION ${nlohmann_json_schema_validator_VERSION} PARENT_SCOPE)\n        set(nlohmann_json_schema_validator_VERSION_MAJOR ${nlohmann_json_schema_validator_VERSION_MAJOR} PARENT_SCOPE)\n        set(nlohmann_json_schema_validator_VERSION_MINOR ${nlohmann_json_schema_validator_VERSION_MINOR} PARENT_SCOPE)\n        set(nlohmann_json_schema_validator_VERSION_PATCH ${nlohmann_json_schema_validator_VERSION_PATCH} PARENT_SCOPE)\n        set(nlohmann_json_schema_validator_VERSION_TWEAK ${nlohmann_json_schema_validator_VERSION_TWEAK} PARENT_SCOPE)\n    endif ()\nendif ()\n"
  },
  {
    "path": "CMakePresets.json",
    "content": "{\n  \"version\": 6,\n  \"include\": [\n    \"cmake/CMakePresets-defaults.json\",\n    \"cmake/CMakePresets-CI.json\"\n  ]\n}\n"
  },
  {
    "path": "ChangeLog.md",
    "content": "## Release 2.4.0\n\n- Added CI job to publish GitHub release by @JohanMabille in <https://github.com/pboettch/json-schema-validator/pull/367>\n- Maintenance to Fedora CI infrastructure by @LecrisUT and @JohanMabille in <https://github.com/pboettch/json-schema-validator/pull/363>\n- Reference validation using contains() result rather than exception handling by @BalrogOfHell in <https://github.com/pboettch/json-schema-validator/pull/334>\n- add support for $defs instead of definitions by rpatters1 in <https://github.com/pboettch/json-schema-validator/pull/338>\n- Apply clang-format / fix \"test / Check pre-commit\" failures by @serge-s in <https://github.com/pboettch/json-schema-validator/pull/328>\n- Adding verbose error messages for logical combinations by Csaba Imre Zempleni in <https://github.com/pboettch/json-schema-validator/pull/310>\n- fix: issue-311 by andrejlevkovitch\n- Fix cmake install target on windows by @barts-of in <https://github.com/pboettch/json-schema-validator/pull/315>\n- error-messages: Numeric limit errors should show maximum precision by @pboettch\n- Add Fedora packaging by @LecrisUT in <https://github.com/pboettch/json-schema-validator/pull/264>\n- Improve and fix bugs in Conanfile by Jacob Crabill\n"
  },
  {
    "path": "LICENSE",
    "content": "Modern C++ JSON schema validator is licensed under the MIT License\n<http://opensource.org/licenses/MIT>:\n\nCopyright (c) 2016 Patrick Boettcher\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\nof the Software, and to permit persons to whom the Software is furnished to do\nso, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "[![Build Status](https://travis-ci.org/pboettch/json-schema-validator.svg?branch=master)](https://travis-ci.org/pboettch/json-schema-validator)\n\n# JSON schema validator for JSON for Modern C++\n\n# What is it?\n\nThis is a C++ library for validating JSON documents based on a\n[JSON Schema](http://json-schema.org/) which itself should validate with\n[draft-7 of JSON Schema Validation](http://json-schema.org/schema).\n\nFirst a disclaimer: *It is work in progress and\ncontributions or hints or discussions are welcome.*\n\nNiels Lohmann et al develop a great JSON parser for C++ called [JSON for Modern\nC++](https://github.com/nlohmann/json). This validator is based on this\nlibrary, hence the name.\n\nExternal documentation is missing as well. However the API of the validator\nis rather simple.\n\n# New in version 2\n\nAlthough significant changes have been done for the 2nd version\n(a complete rewrite) the API is compatible with the 1.0.0 release. Except for\nthe namespace which is now `nlohmann::json_schema`.\n\nVersion **2** supports JSON schema draft 7, whereas 1 was supporting draft 4\nonly. Please update your schemas.\n\nThe primary change in 2 is the way a schema is used. While in version 1 the schema was\nkept as a JSON-document and used again and again during validation, in version 2 the schema\nis parsed into compiled C++ objects which are then used during validation. There are surely\nstill optimizations to be done, but validation speed has improved by factor 100\nor more.\n\n# Design goals\n\nThe main goal of this validator is to produce *human-comprehensible* error\nmessages if a JSON-document/instance does not comply to its schema.\n\nBy default this is done with exceptions thrown at the users with a helpful\nmessage telling what's wrong with the document while validating.\n\nStarting with **2.0.0** the user can pass a `json_schema::basic_error_handler`-derived\nobject along with the instance to validate to receive a callback each time\na validation error occurs and decide what to do (throwing, counting, collecting).\n\nAnother goal was to use Niels Lohmann's JSON-library. This is why the validator\nlives in his namespace.\n\n# Thread-safety\n\nInstance validation is thread-safe and the same validator-object can be used by\ndifferent threads:\n\nThe validate method is `const` which indicates the object is not modified when\nbeing called:\n\n```C++\n\tjson json_validator::validate(const json &) const;\n```\n\nValidator-object creation however is not thread-safe. A validator has to be\ncreated in one (main?) thread once.\n\n# Weaknesses\n\nNumerical validation uses nlohmann-json's integer, unsigned and floating point\ntypes, depending on if the schema type is \"integer\" or \"number\". Bignum\n(i.e. arbitrary precision and range) is not supported at this time.\n\n# Building\n\nThis library is based on Niels Lohmann's JSON-library and thus has\na build-dependency to it.\n\nCurrently at least version **3.8.0** of NLohmann's JSON library\nis required.\n\nVarious methods using CMake can be used to build this project.\n\n## Build out-of-source\n\nDo not run cmake inside the source-dir. Rather create a dedicated build-dir:\n\n```Bash\ngit clone https://github.com/pboettch/json-schema-validator.git\ncd json-schema-validator\nmkdir build\ncd build\ncmake [..]\nmake\nmake install # if needed\nctest # run unit, non-regression and test-suite tests\n```\n\n## Building as shared library\n\nBy default a static library is built. Shared libraries can be generated by using\nthe `BUILD_SHARED_LIBS`-cmake variable:\n\nIn your initial call to cmake simply add:\n\n```bash\ncmake [..] -DBUILD_SHARED_LIBS=ON [..]\n```\n\n## nlohmann-json integration\n\nAs nlohmann-json is a dependency, this library tries find it.\n\nThe cmake-configuration first checks if nlohmann-json is available as a cmake-target. This may be the case, because it is used as a submodule in a super-project which already provides and uses nlohmann-json.\nOtherwise, it calls `find_package` for nlohmann-json and requires nlohmann-json to be installed on the system.\n\n### Building with Hunter package manager\n\nTo enable access to nlohmann json library, Hunter can be used. Just run with `JSON_VALIDATOR_HUNTER=ON` option. No further dependencies needed\n\n```bash\ncmake [..] -DJSON_VALIDATOR_HUNTER=ON [..]\n```\n\n### Building as a CMake-subdirectory from within another project\n\nAdding this library as a subdirectory to a parent project is one way of\nbuilding it.\n\nIf the parent project already used `find_package()` to find the CMake-package of nlohmann_json or includes it as a submodule likewise.\n\n### Building directly, finding a CMake-package. (short)\n\nWhen nlohmann-json has been installed, it provides files which allows\nCMake's `find_package()` to be used.\n\nThis library is using this mechanism if `nlohmann_json::nlohmann_json`-target\ndoes not exist.\n\n### Install\n\nSince version 2.1.0 this library can be installed and CMake-package-files will be\ncreated accordingly. If the installation of nlohmann-json and this library\nis done into default unix-system-paths CMake will be able to find this\nlibrary by simply doing:\n\n```CMake\nfind_package(nlohmann_json_schema_validator REQUIRED)\n```\n\nand\n\n```CMake\ntarget_link_libraries(<your-target> [..] nlohmann_json_schema_validator)\n```\n\nto build and link.\n\n## Code\n\nSee also `app/json-schema-validate.cpp`.\n\n```C++\n#include <iostream>\n#include <iomanip>\n\n#include <nlohmann/json-schema.hpp>\n\nusing nlohmann::json;\nusing nlohmann::json_schema::json_validator;\n\n// The schema is defined based upon a string literal\nstatic json person_schema = R\"(\n{\n    \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n    \"title\": \"A person\",\n    \"properties\": {\n        \"name\": {\n            \"description\": \"Name\",\n            \"type\": \"string\"\n        },\n        \"age\": {\n            \"description\": \"Age of the person\",\n            \"type\": \"number\",\n            \"minimum\": 2,\n            \"maximum\": 200\n        }\n    },\n    \"required\": [\n                 \"name\",\n                 \"age\"\n                 ],\n    \"type\": \"object\"\n}\n\n)\"_json;\n\n// The people are defined with brace initialization\nstatic json bad_person = {{\"age\", 42}};\nstatic json good_person = {{\"name\", \"Albert\"}, {\"age\", 42}};\n\nint main()\n{\n    /* json-parse the schema */\n\n    json_validator validator; // create validator\n\n    try {\n        validator.set_root_schema(person_schema); // insert root-schema\n    } catch (const std::exception &e) {\n        std::cerr << \"Validation of schema failed, here is why: \" << e.what() << \"\\n\";\n        return EXIT_FAILURE;\n    }\n\n    /* json-parse the people - API of 1.0.0, default throwing error handler */\n\n    for (auto &person : {bad_person, good_person}) {\n        std::cout << \"About to validate this person:\\n\"\n                  << std::setw(2) << person << std::endl;\n        try {\n            validator.validate(person); // validate the document - uses the default throwing error-handler\n            std::cout << \"Validation succeeded\\n\";\n        } catch (const std::exception &e) {\n            std::cerr << \"Validation failed, here is why: \" << e.what() << \"\\n\";\n        }\n    }\n\n    /* json-parse the people - with custom error handler */\n    class custom_error_handler : public nlohmann::json_schema::basic_error_handler\n    {\n        void error(const nlohmann::json_pointer<nlohmann::basic_json<>> &pointer, const json &instance,\n            const std::string &message) override\n        {\n            nlohmann::json_schema::basic_error_handler::error(pointer, instance, message);\n            std::cerr << \"ERROR: '\" << pointer << \"' - '\" << instance << \"': \" << message << \"\\n\";\n        }\n    };\n\n\n    for (auto &person : {bad_person, good_person}) {\n        std::cout << \"About to validate this person:\\n\"\n                  << std::setw(2) << person << std::endl;\n\n        custom_error_handler err;\n        validator.validate(person, err); // validate the document\n\n        if (err)\n            std::cerr << \"Validation failed\\n\";\n        else\n            std::cout << \"Validation succeeded\\n\";\n    }\n\n    return EXIT_SUCCESS;\n}\n```\n\n# Compliance\n\nThere is an application which can be used for testing the validator with the\n[JSON-Schema-Test-Suite](https://github.com/json-schema-org/JSON-Schema-Test-Suite).\nIn order to simplify the testing, the test-suite is included in the repository.\n\nIf you have cloned this repository providing a path the repository-root via the\ncmake-variable `JSON_SCHEMA_TEST_SUITE_PATH` will enable the test-target(s).\n\nAll required tests are **OK**.\n\n# Format\n\nOptionally JSON-schema-validator can validate predefined or user-defined formats.\nTherefore a format-checker-function can be provided by the user which is called by\nthe validator when a format-check is required (ie. the schema contains a format-field).\n\nThis is how the prototype looks like and how it can be passed to the validation-instance:\n\n```C++\nstatic void my_format_checker(const std::string &format, const std::string &value)\n{\n\tif (format == \"something\") {\n\t\tif (!check_value_for_something(value))\n\t\t\tthrow std::invalid_argument(\"value is not a good something\");\n\t} else\n\t\tthrow std::logic_error(\"Don't know how to validate \" + format);\n}\n\n// when creating the validator\n\njson_validator validator(nullptr, // or loader-callback\n                         my_format_checker); // create validator\n```\n\n## Default Checker\n\nThe library contains a default-checker, which does some checks. It needs to be\nprovided manually to the constructor of the validator:\n\n```C++\njson_validator validator(loader, // or nullptr for no loader\n                         nlohmann::json_schema::default_string_format_check);\n```\n\nSupported formats: `date-time, date, time, email, hostname, ipv4, ipv6, uuid, regex`\n\nMore formats can be added in `src/string-format-check.cpp`. Please contribute implementions for missing json schema draft formats.\n\n## Default value processing\n\nAs a result of the validation, the library returns a json patch including the default values of the specified schema.\n\n```C++\n#include <iostream>\n#include <nlohmann/json-schema.hpp>\n\nusing nlohmann::json;\nusing nlohmann::json_schema::json_validator;\n\nstatic const json rectangle_schema = R\"(\n{\n    \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n    \"title\": \"A rectangle\",\n    \"properties\": {\n        \"width\": {\n            \"$ref\": \"#/definitions/length\",\n            \"default\": 20\n        },\n        \"height\": {\n            \"$ref\": \"#/definitions/length\"\n        }\n    },\n    \"definitions\": {\n        \"length\": {\n            \"type\": \"integer\",\n            \"minimum\": 1,\n            \"default\": 10\n        }\n    }\n})\"_json;\n\nint main()\n{\n\ttry {\n\t\tjson_validator validator{rectangle_schema};\n\t\t/* validate empty json -> will be expanded by the default values defined in the schema */\n\t\tjson rectangle = \"{}\"_json;\n\t\tconst auto default_patch = validator.validate(rectangle);\n\t\trectangle = rectangle.patch(default_patch);\n\t\tstd::cout << rectangle.dump() << std::endl; // {\"height\":10,\"width\":20}\n\t} catch (const std::exception &e) {\n\t\tstd::cerr << \"Validation of schema failed: \" << e.what() << \"\\n\";\n\t\treturn EXIT_FAILURE;\n\t}\n\treturn EXIT_SUCCESS;\n}\n```\n\nThe example above will output the specified default values `{\"height\":10,\"width\":20}` to stdout.\n\n> Note that the default value specified in a `$ref` may be overridden by the current instance location. Also note that this behavior will break draft-7, but it is compliant to newer drafts (e.g. `2019-09` or `2020-12`).\n\n# Contributing\n\nThis project uses [`pre-commit`](https://pre-commit.com/) to enforce style-checks. Please install and run it before\ncreating commits and making pull requests.\n\n```console\n$ pip install pre-commit\n$ pre-commit install\n```\n"
  },
  {
    "path": "cmake/CMakePresets-CI.json",
    "content": "{\n  \"version\": 6,\n  \"include\": [\n    \"CMakePresets-defaults.json\"\n  ],\n  \"configurePresets\": [\n    {\n      \"name\": \"ci-base\",\n      \"hidden\": true,\n      \"generator\": \"Ninja\",\n      \"inherits\": [\n        \"default\"\n      ],\n      \"cacheVariables\": {\n        \"CMAKE_BUILD_TYPE\": {\n          \"type\": \"STRING\",\n          \"value\": \"Debug\"\n        },\n        \"JSON_VALIDATOR_BUILD_TESTS\": {\n          \"type\": \"BOOL\",\n          \"value\": true\n        },\n        \"JSON_VALIDATOR_INSTALL\": {\n          \"type\": \"BOOL\",\n          \"value\": false\n        },\n        \"JSON_BuildTests\": {\n          \"type\": \"BOOL\",\n          \"value\": false\n        }\n      },\n      \"errors\": {\n        \"deprecated\": true\n      }\n    },\n    {\n      \"name\": \"gcc-ci\",\n      \"displayName\": \"Configure preset for GCC toolchain\",\n      \"inherits\": [\n        \"ci-base\"\n      ],\n      \"binaryDir\": \"cmake-build-ci-gcc\",\n      \"cacheVariables\": {\n        \"CMAKE_CXX_COMPILER\": {\n          \"type\": \"FILEPATH\",\n          \"value\": \"g++\"\n        },\n        \"CMAKE_LINKER\": {\n          \"type\": \"FILEPATH\",\n          \"value\": \"ld\"\n        }\n      }\n    },\n    {\n      \"name\": \"intel-ci\",\n      \"displayName\": \"Configure preset for Intel toolchain\",\n      \"inherits\": [\n        \"ci-base\"\n      ],\n      \"binaryDir\": \"cmake-build-ci-intel\",\n      \"cacheVariables\": {\n        \"CMAKE_CXX_COMPILER\": {\n          \"type\": \"FILEPATH\",\n          \"value\": \"icpx\"\n        }\n      }\n    },\n    {\n      \"name\": \"llvm-ci\",\n      \"displayName\": \"Configure preset for LLVM toolchain\",\n      \"inherits\": [\n        \"ci-base\"\n      ],\n      \"binaryDir\": \"cmake-build-ci-llvm\",\n      \"cacheVariables\": {\n        \"CMAKE_CXX_COMPILER\": {\n          \"type\": \"FILEPATH\",\n          \"value\": \"clang++\"\n        },\n        \"CMAKE_LINKER\": {\n          \"type\": \"FILEPATH\",\n          \"value\": \"lld\"\n        }\n      }\n    },\n    {\n      \"name\": \"ci-coverage\",\n      \"displayName\": \"Configure preset for test coverage\",\n      \"inherits\": [\n        \"gcc-ci\"\n      ],\n      \"binaryDir\": \"cmake-build-ci-coverage\",\n      \"errors\": {\n        \"deprecated\": false\n      },\n      \"cacheVariables\": {\n        \"JSON_VALIDATOR_TEST_COVERAGE\": {\n          \"type\": \"BOOL\",\n          \"value\": true\n        }\n      }\n    },\n    {\n      \"name\": \"pre-commit\",\n      \"displayName\": \"Configure preset for pre-commit checks\",\n      \"inherits\": [\n        \"default\"\n      ],\n      \"binaryDir\": \"cmake-build-pre-commit\",\n      \"cacheVariables\": {\n        \"JSON_VALIDATOR_TEST_COVERAGE\": {\n          \"type\": \"BOOL\",\n          \"value\": true\n        },\n        \"JSON_VALIDATOR_INSTALL\": {\n          \"type\": \"BOOL\",\n          \"value\": false\n        }\n      }\n    }\n  ],\n  \"buildPresets\": [\n    {\n      \"name\": \"ci-base\",\n      \"hidden\": true,\n      \"inherits\": [\n        \"default\"\n      ],\n      \"cleanFirst\": true\n    },\n    {\n      \"name\": \"ci-coverage\",\n      \"displayName\": \"Build preset for test coverage\",\n      \"inherits\": [\n        \"ci-base\"\n      ],\n      \"configurePreset\": \"ci-coverage\"\n    },\n    {\n      \"name\": \"gcc-ci\",\n      \"displayName\": \"Build preset for GCC toolchain\",\n      \"inherits\": [\n        \"ci-base\"\n      ],\n      \"configurePreset\": \"gcc-ci\"\n    },\n    {\n      \"name\": \"intel-ci\",\n      \"displayName\": \"Build preset for Intel toolchain\",\n      \"inherits\": [\n        \"ci-base\"\n      ],\n      \"configurePreset\": \"intel-ci\"\n    },\n    {\n      \"name\": \"llvm-ci\",\n      \"displayName\": \"Build preset for LLVM toolchain\",\n      \"inherits\": [\n        \"ci-base\"\n      ],\n      \"configurePreset\": \"llvm-ci\"\n    }\n  ],\n  \"testPresets\": [\n    {\n      \"name\": \"ci-base\",\n      \"hidden\": true,\n      \"inherits\": [\n        \"default\"\n      ],\n      \"output\": {\n        \"outputOnFailure\": true\n      }\n    },\n    {\n      \"name\": \"ci-coverage\",\n      \"inherits\": [\n        \"default\"\n      ],\n      \"configurePreset\": \"ci-coverage\"\n    },\n    {\n      \"name\": \"gcc-ci\",\n      \"displayName\": \"Test preset for GCC toolchain\",\n      \"inherits\": [\n        \"ci-base\"\n      ],\n      \"configurePreset\": \"gcc-ci\"\n    },\n    {\n      \"name\": \"intel-ci\",\n      \"displayName\": \"Test preset for Intel toolchain\",\n      \"inherits\": [\n        \"ci-base\"\n      ],\n      \"configurePreset\": \"intel-ci\"\n    },\n    {\n      \"name\": \"llvm-ci\",\n      \"displayName\": \"Test preset for LLVM toolchain\",\n      \"inherits\": [\n        \"ci-base\"\n      ],\n      \"configurePreset\": \"llvm-ci\"\n    }\n  ],\n  \"workflowPresets\": [\n    {\n      \"name\": \"gcc-ci\",\n      \"displayName\": \"CI test for GCC toolchain\",\n      \"steps\": [\n        {\n          \"type\": \"configure\",\n          \"name\": \"gcc-ci\"\n        },\n        {\n          \"type\": \"build\",\n          \"name\": \"gcc-ci\"\n        },\n        {\n          \"type\": \"test\",\n          \"name\": \"gcc-ci\"\n        }\n      ]\n    },\n    {\n      \"name\": \"intel-ci\",\n      \"displayName\": \"CI test for Intel toolchain\",\n      \"steps\": [\n        {\n          \"type\": \"configure\",\n          \"name\": \"intel-ci\"\n        },\n        {\n          \"type\": \"build\",\n          \"name\": \"intel-ci\"\n        },\n        {\n          \"type\": \"test\",\n          \"name\": \"intel-ci\"\n        }\n      ]\n    },\n    {\n      \"name\": \"llvm-ci\",\n      \"displayName\": \"CI test for LLVM toolchain\",\n      \"steps\": [\n        {\n          \"type\": \"configure\",\n          \"name\": \"llvm-ci\"\n        },\n        {\n          \"type\": \"build\",\n          \"name\": \"llvm-ci\"\n        },\n        {\n          \"type\": \"test\",\n          \"name\": \"llvm-ci\"\n        }\n      ]\n    },\n    {\n      \"name\": \"ci-coverage\",\n      \"displayName\": \"Coverage tests\",\n      \"steps\": [\n        {\n          \"type\": \"configure\",\n          \"name\": \"ci-coverage\"\n        },\n        {\n          \"type\": \"build\",\n          \"name\": \"ci-coverage\"\n        },\n        {\n          \"type\": \"test\",\n          \"name\": \"ci-coverage\"\n        }\n      ]\n    }\n  ]\n}\n"
  },
  {
    "path": "cmake/CMakePresets-defaults.json",
    "content": "{\n  \"version\": 6,\n  \"configurePresets\": [\n    {\n      \"name\": \"default\",\n      \"displayName\": \"Default configuration preset\",\n      \"binaryDir\": \"cmake-build-release\",\n      \"cacheVariables\": {\n        \"CMAKE_BUILD_TYPE\": {\n          \"type\": \"STRING\",\n          \"value\": \"Release\"\n        }\n      }\n    }\n  ],\n  \"buildPresets\": [\n    {\n      \"name\": \"default\",\n      \"displayName\": \"Default build preset\",\n      \"configurePreset\": \"default\"\n    }\n  ],\n  \"testPresets\": [\n    {\n      \"name\": \"default\",\n      \"displayName\": \"Default test preset\",\n      \"configurePreset\": \"default\"\n    }\n  ],\n  \"workflowPresets\": [\n    {\n      \"name\": \"default\",\n      \"displayName\": \"Default workflow\",\n      \"steps\": [\n        {\n          \"type\": \"configure\",\n          \"name\": \"default\"\n        },\n        {\n          \"type\": \"build\",\n          \"name\": \"default\"\n        },\n        {\n          \"type\": \"test\",\n          \"name\": \"default\"\n        }\n      ]\n    }\n  ]\n}\n"
  },
  {
    "path": "cmake/nlohmann_json_schema_validatorConfig.cmake.in",
    "content": "@PACKAGE_INIT@\n\ninclude(CMakeFindDependencyMacro)\nfind_dependency(nlohmann_json)\n\ninclude(\"${CMAKE_CURRENT_LIST_DIR}/nlohmann_json_schema_validatorTargets.cmake\")\ncheck_required_components(\n  \"nlohmann_json_schema_validator\"\n  )\n"
  },
  {
    "path": "conanfile.py",
    "content": "import os\nimport re\n\nfrom conan import ConanFile\nfrom conan.tools.cmake import cmake_layout, CMake, CMakeToolchain\nfrom conans.tools import load\nfrom conans import tools as ctools\n\ndef get_version():\n    try:\n        version = os.getenv('PROJECT_VERSION', None)\n        if version:\n            return version\n\n        content = load('CMakeLists.txt')\n        version = re.search('set\\(PROJECT_VERSION (.*)\\)', content).group(1)\n        return version.strip()\n    except:\n        return None\n\nclass JsonSchemaValidatorConan(ConanFile):\n    name = 'JsonSchemaValidator'\n    version = get_version()\n    url = 'https://github.com/pboettch/json-schema-validator'\n    license = 'MIT'\n\n    settings = 'os', 'compiler', 'build_type', 'arch'\n\n    options = {\n        'shared': [True, False],\n        'fPIC': [True, False],\n        'build_examples': [True, False],\n        'build_tests': [True, False],\n        'test_coverage': [True, False],\n    }\n\n    default_options = {\n        'shared': False,\n        'fPIC': True,\n        'build_examples': True,\n        'build_tests': False,\n        'test_coverage': False,\n    }\n\n    generators = 'CMakeDeps', 'CMakeToolchain', 'VirtualBuildEnv', 'VirtualRunEnv'\n\n    exports_sources = [\n        'CMakeLists.txt',\n        'conanfile.py',\n        'cmake/*',\n        'src/*',\n        'example/*',\n        'test/*',\n    ]\n\n    requires = [\n        'nlohmann_json/3.11.2'\n    ]\n\n    def generate(self):\n        tc = CMakeToolchain(self)\n        tc.variables['JSON_VALIDATOR_BUILD_EXAMPLES'] = self.options.build_examples\n        tc.variables['JSON_VALIDATOR_BUILD_TESTS'] = self.options.build_tests\n        tc.variables['JSON_VALIDATOR_SHARED_LIBS '] = self.options.shared\n        tc.variables['JSON_VALIDATOR_TEST_COVERAGE '] = self.options.test_coverage\n        tc.generate()\n\n    def layout(self):\n        cmake_layout(self)\n\n    def build(self):\n        cmake = CMake(self)\n        cmake.configure()\n        cmake.verbose = True\n        cmake.build()\n\n    def package(self):\n        cmake = CMake(self)\n        cmake.install()\n\n    def package_info(self):\n        includedir = os.path.join(self.package_folder, \"include\")\n        self.cpp_info.includedirs = [includedir]\n\n        libdir = os.path.join(self.package_folder, \"lib\")\n        self.cpp_info.libdirs = [libdir]\n        self.cpp_info.libs += ctools.collect_libs(self, libdir)\n\n        bindir = os.path.join(self.package_folder, \"bin\")\n        self.output.info(\"Appending PATH environment variable: {}\".format(bindir))\n        self.env_info.PATH.append(bindir)\n\n        self.user_info.VERSION = self.version\n"
  },
  {
    "path": "example/CMakeLists.txt",
    "content": "add_executable(readme-json-schema readme.cpp)\ntarget_link_libraries(readme-json-schema nlohmann_json_schema_validator)\n\nadd_executable(format-json-schema format.cpp)\ntarget_link_libraries(format-json-schema nlohmann_json_schema_validator)\n\nif (JSON_VALIDATOR_INSTALL)\n    install(TARGETS readme-json-schema format-json-schema\n            DESTINATION ${CMAKE_INSTALL_BINDIR})\nendif ()\n"
  },
  {
    "path": "example/format.cpp",
    "content": "#include <iostream>\n\n#include <nlohmann/json-schema.hpp>\n\nusing nlohmann::json;\nusing nlohmann::json_schema::json_validator;\n\n// The schema is defined based upon a string literal\nstatic json uri_schema = R\"(\n{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"type\": \"object\",\n  \"properties\": {\n    \"myUri\": {\n      \"type\":\"string\",\n      \"format\": \"uri\"\n    }\n  }\n})\"_json;\n\n// The people are defined with brace initialization\nstatic json good_uri = {{\"myUri\", \"http://hostname.com/\"}};\nstatic json bad_uri = {{\"myUri\", \"http:/hostname.com/\"}};\n\nstatic void uri_format_checker(const std::string &format, const std::string &value)\n{\n\tif (format == \"uri\") {\n\t\tif (value.find(\"://\") == std::string::npos)\n\t\t\tthrow std::invalid_argument(\"URI does not contain :// - invalid\");\n\t} else\n\t\tthrow std::logic_error(\"Don't know how to validate \" + format);\n}\n\nint main()\n{\n\tjson_validator validator(nullptr, uri_format_checker); // create validator\n\n\ttry {\n\t\tvalidator.set_root_schema(uri_schema); // insert root-schema\n\t} catch (const std::exception &e) {\n\t\tstd::cerr << \"Validation of schema failed, here is why: \" << e.what() << \"\\n\";\n\t\treturn EXIT_FAILURE;\n\t}\n\n\tvalidator.validate(good_uri);\n\n\ttry {\n\t\tvalidator.validate(bad_uri);\n\t} catch (const std::exception &e) {\n\t\tstd::cerr << \"Validation expectedly failed, here is why: \" << e.what() << \"\\n\";\n\t}\n\n\treturn EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "example/readme.cpp",
    "content": "#include <iomanip>\n#include <iostream>\n\n#include <nlohmann/json-schema.hpp>\n\nusing nlohmann::json;\nusing nlohmann::json_schema::json_validator;\n\n// The schema is defined based upon a string literal\nstatic json person_schema = R\"(\n{\n    \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n    \"title\": \"A person\",\n    \"properties\": {\n      \"name\": {\n          \"description\": \"Name\",\n          \"type\": \"string\"\n      },\n      \"age\": {\n          \"description\": \"Age of the person\",\n          \"type\": \"number\",\n          \"minimum\": 2,\n          \"maximum\": 200\n      },\n      \"address\":{\n        \"type\": \"object\",\n        \"properties\":{\n          \"street\":{\n            \"type\": \"string\",\n            \"default\": \"Abbey Road\"\n          }\n        }\n      }\n    },\n    \"required\": [\n                 \"name\",\n                 \"age\"\n                 ],\n    \"type\": \"object\"\n}\n\n)\"_json;\n\n// The people are defined with brace initialization\nstatic json bad_person = {{\"age\", 42}};\nstatic json good_person = {{\"name\", \"Albert\"}, {\"age\", 42}, {\"address\", {{\"street\", \"Main Street\"}}}};\nstatic json good_defaulted_person = {{\"name\", \"Knut\"}, {\"age\", 69}, {\"address\", {}}};\n\nint main()\n{\n\t/* json-parse the schema */\n\n\tjson_validator validator; // create validator\n\n\ttry {\n\t\tvalidator.set_root_schema(person_schema); // insert root-schema\n\t} catch (const std::exception &e) {\n\t\tstd::cerr << \"Validation of schema failed, here is why: \" << e.what() << \"\\n\";\n\t\treturn EXIT_FAILURE;\n\t}\n\n\t/* json-parse the people - API of 1.0.0, default throwing error handler */\n\n\tfor (auto &person : {bad_person, good_person, good_defaulted_person}) {\n\t\tstd::cout << \"About to validate this person:\\n\"\n\t\t          << std::setw(2) << person << std::endl;\n\t\ttry {\n\t\t\tauto defaultPatch = validator.validate(person); // validate the document - uses the default throwing error-handler\n\t\t\tstd::cout << \"Validation succeeded\\n\";\n\t\t\tstd::cout << \"Patch with defaults: \" << defaultPatch.dump(2) << std::endl;\n\t\t} catch (const std::exception &e) {\n\t\t\tstd::cerr << \"Validation failed, here is why: \" << e.what() << \"\\n\";\n\t\t}\n\t}\n\n\t/* json-parse the people - with custom error handler */\n\tclass custom_error_handler : public nlohmann::json_schema::basic_error_handler\n\t{\n\t\tvoid error(const nlohmann::json::json_pointer &ptr, const json &instance, const std::string &message) override\n\t\t{\n\t\t\tnlohmann::json_schema::basic_error_handler::error(ptr, instance, message);\n\t\t\tstd::cerr << \"ERROR: '\" << ptr << \"' - '\" << instance << \"': \" << message << \"\\n\";\n\t\t}\n\t};\n\n\tfor (auto &person : {bad_person, good_person}) {\n\t\tstd::cout << \"About to validate this person:\\n\"\n\t\t          << std::setw(2) << person << std::endl;\n\n\t\tcustom_error_handler err;\n\t\tvalidator.validate(person, err); // validate the document\n\n\t\tif (err)\n\t\t\tstd::cerr << \"Validation failed\\n\";\n\t\telse\n\t\t\tstd::cout << \"Validation succeeded\\n\";\n\t}\n\n\treturn EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "schema",
    "content": "{\n    \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n    \"$id\": \"http://json-schema.org/draft-07/schema#\",\n    \"title\": \"Core schema meta-schema\",\n    \"definitions\": {\n        \"schemaArray\": {\n            \"type\": \"array\",\n            \"minItems\": 1,\n            \"items\": { \"$ref\": \"#\" }\n        },\n        \"nonNegativeInteger\": {\n            \"type\": \"integer\",\n            \"minimum\": 0\n        },\n        \"nonNegativeIntegerDefault0\": {\n            \"allOf\": [\n                { \"$ref\": \"#/definitions/nonNegativeInteger\" },\n                { \"default\": 0 }\n            ]\n        },\n        \"simpleTypes\": {\n            \"enum\": [\n                \"array\",\n                \"boolean\",\n                \"integer\",\n                \"null\",\n                \"number\",\n                \"object\",\n                \"string\"\n            ]\n        },\n        \"stringArray\": {\n            \"type\": \"array\",\n            \"items\": { \"type\": \"string\" },\n            \"uniqueItems\": true,\n            \"default\": []\n        }\n    },\n    \"type\": [\"object\", \"boolean\"],\n    \"properties\": {\n        \"$id\": {\n            \"type\": \"string\",\n            \"format\": \"uri-reference\"\n        },\n        \"$schema\": {\n            \"type\": \"string\",\n            \"format\": \"uri\"\n        },\n        \"$ref\": {\n            \"type\": \"string\",\n            \"format\": \"uri-reference\"\n        },\n        \"$comment\": {\n            \"type\": \"string\"\n        },\n        \"title\": {\n            \"type\": \"string\"\n        },\n        \"description\": {\n            \"type\": \"string\"\n        },\n        \"default\": true,\n        \"readOnly\": {\n            \"type\": \"boolean\",\n            \"default\": false\n        },\n        \"examples\": {\n            \"type\": \"array\",\n            \"items\": true\n        },\n        \"multipleOf\": {\n            \"type\": \"number\",\n            \"exclusiveMinimum\": 0\n        },\n        \"maximum\": {\n            \"type\": \"number\"\n        },\n        \"exclusiveMaximum\": {\n            \"type\": \"number\"\n        },\n        \"minimum\": {\n            \"type\": \"number\"\n        },\n        \"exclusiveMinimum\": {\n            \"type\": \"number\"\n        },\n        \"maxLength\": { \"$ref\": \"#/definitions/nonNegativeInteger\" },\n        \"minLength\": { \"$ref\": \"#/definitions/nonNegativeIntegerDefault0\" },\n        \"pattern\": {\n            \"type\": \"string\",\n            \"format\": \"regex\"\n        },\n        \"additionalItems\": { \"$ref\": \"#\" },\n        \"items\": {\n            \"anyOf\": [\n                { \"$ref\": \"#\" },\n                { \"$ref\": \"#/definitions/schemaArray\" }\n            ],\n            \"default\": true\n        },\n        \"maxItems\": { \"$ref\": \"#/definitions/nonNegativeInteger\" },\n        \"minItems\": { \"$ref\": \"#/definitions/nonNegativeIntegerDefault0\" },\n        \"uniqueItems\": {\n            \"type\": \"boolean\",\n            \"default\": false\n        },\n        \"contains\": { \"$ref\": \"#\" },\n        \"maxProperties\": { \"$ref\": \"#/definitions/nonNegativeInteger\" },\n        \"minProperties\": { \"$ref\": \"#/definitions/nonNegativeIntegerDefault0\" },\n        \"required\": { \"$ref\": \"#/definitions/stringArray\" },\n        \"additionalProperties\": { \"$ref\": \"#\" },\n        \"definitions\": {\n            \"type\": \"object\",\n            \"additionalProperties\": { \"$ref\": \"#\" },\n            \"default\": {}\n        },\n        \"properties\": {\n            \"type\": \"object\",\n            \"additionalProperties\": { \"$ref\": \"#\" },\n            \"default\": {}\n        },\n        \"patternProperties\": {\n            \"type\": \"object\",\n            \"additionalProperties\": { \"$ref\": \"#\" },\n            \"propertyNames\": { \"format\": \"regex\" },\n            \"default\": {}\n        },\n        \"dependencies\": {\n            \"type\": \"object\",\n            \"additionalProperties\": {\n                \"anyOf\": [\n                    { \"$ref\": \"#\" },\n                    { \"$ref\": \"#/definitions/stringArray\" }\n                ]\n            }\n        },\n        \"propertyNames\": { \"$ref\": \"#\" },\n        \"const\": true,\n        \"enum\": {\n            \"type\": \"array\",\n            \"items\": true,\n            \"minItems\": 1,\n            \"uniqueItems\": true\n        },\n        \"type\": {\n            \"anyOf\": [\n                { \"$ref\": \"#/definitions/simpleTypes\" },\n                {\n                    \"type\": \"array\",\n                    \"items\": { \"$ref\": \"#/definitions/simpleTypes\" },\n                    \"minItems\": 1,\n                    \"uniqueItems\": true\n                }\n            ]\n        },\n        \"format\": { \"type\": \"string\" },\n        \"contentMediaType\": { \"type\": \"string\" },\n        \"contentEncoding\": { \"type\": \"string\" },\n        \"if\": {\"$ref\": \"#\"},\n        \"then\": {\"$ref\": \"#\"},\n        \"else\": {\"$ref\": \"#\"},\n        \"allOf\": { \"$ref\": \"#/definitions/schemaArray\" },\n        \"anyOf\": { \"$ref\": \"#/definitions/schemaArray\" },\n        \"oneOf\": { \"$ref\": \"#/definitions/schemaArray\" },\n        \"not\": { \"$ref\": \"#\" }\n    },\n    \"default\": true\n}\n"
  },
  {
    "path": "src/CMakeLists.txt",
    "content": "target_sources(nlohmann_json_schema_validator PRIVATE\n        smtp-address-validator.cpp\n        json-schema-draft7.json.cpp\n        json-uri.cpp\n        json-validator.cpp\n        json-patch.cpp\n        string-format-check.cpp\n        )\ntarget_include_directories(nlohmann_json_schema_validator PUBLIC\n        $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>\n        $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>\n        )\n\nset_target_properties(nlohmann_json_schema_validator PROPERTIES\n        PUBLIC_HEADER nlohmann/json-schema.hpp)\n\n# TODO: Why would this need to be if guarded?\nif (JSON_VALIDATOR_SHARED_LIBS)\n    target_compile_definitions(nlohmann_json_schema_validator PRIVATE\n            -DJSON_SCHEMA_VALIDATOR_EXPORTS)\nendif ()\n\n# TODO: Consider setting minimum cxx standard instead\ntarget_compile_features(nlohmann_json_schema_validator PUBLIC\n        cxx_range_for) # for C++11 - flags\n\n# TODO: This should be handled by the CI/presets, not the cmake\nif (\"${CMAKE_CXX_COMPILER_ID}\" STREQUAL \"Clang\" OR\n        \"${CMAKE_CXX_COMPILER_ID}\" STREQUAL \"GNU\")\n    target_compile_options(nlohmann_json_schema_validator\n            PRIVATE\n            -Wall -Wextra -Wshadow)\nendif ()\n\n# TODO: gcc support for <4.9 should be removed\n# regex with boost if gcc < 4.9 - default is std::regex\nif (CMAKE_CXX_COMPILER_ID STREQUAL \"GNU\")\n    if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS \"4.9.0\")\n        find_package(Boost COMPONENTS regex)\n        if (NOT Boost_FOUND)\n            message(STATUS \"GCC less then 4.9 and boost-regex NOT found - no regex used\")\n            target_compile_definitions(nlohmann_json_schema_validator PRIVATE -DJSON_SCHEMA_NO_REGEX)\n        else ()\n            message(STATUS \"GCC less then 4.9 and boost-regex FOUND - using boost::regex\")\n            target_compile_definitions(nlohmann_json_schema_validator PRIVATE -DJSON_SCHEMA_BOOST_REGEX)\n            target_include_directories(nlohmann_json_schema_validator PRIVATE ${Boost_INCLUDE_DIRS})\n            target_link_libraries(nlohmann_json_schema_validator PRIVATE ${Boost_LIBRARIES})\n        endif ()\n    endif ()\nendif ()\n\ntarget_link_libraries(nlohmann_json_schema_validator PUBLIC\n        nlohmann_json::nlohmann_json)\n\nif (JSON_VALIDATOR_INSTALL)\n    # Normal installation target to system. When using scikit-build check python subdirectory\n    install(TARGETS nlohmann_json_schema_validator\n            EXPORT nlohmann_json_schema_validatorTargets\n            LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT nlohmann_json_schema_validator_Runtime\n            NAMELINK_COMPONENT nlohmann_json_schema_validator_Development\n            ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT nlohmann_json_schema_validator_Development\n            PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/nlohmann COMPONENT nlohmann_json_schema_validator_Development\n            RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT nlohmann_json_schema_validator_Runtime)\nendif ()\n"
  },
  {
    "path": "src/json-patch.cpp",
    "content": "#include \"json-patch.hpp\"\n\n#include <nlohmann/json-schema.hpp>\n\nnamespace\n{\n\n// originally from http://jsonpatch.com/, http://json.schemastore.org/json-patch\n// with fixes\nconst nlohmann::json patch_schema = R\"patch({\n    \"title\": \"JSON schema for JSONPatch files\",\n    \"$schema\": \"http://json-schema.org/draft-04/schema#\",\n    \"type\": \"array\",\n\n    \"items\": {\n        \"oneOf\": [\n            {\n                \"additionalProperties\": false,\n                \"required\": [ \"value\", \"op\", \"path\"],\n                \"properties\": {\n                    \"path\" : { \"$ref\": \"#/definitions/path\" },\n                    \"op\": {\n                        \"description\": \"The operation to perform.\",\n                        \"type\": \"string\",\n                        \"enum\": [ \"add\", \"replace\", \"test\" ]\n                    },\n                    \"value\": {\n                        \"description\": \"The value to add, replace or test.\"\n                    }\n                }\n            },\n            {\n                \"additionalProperties\": false,\n                \"required\": [ \"op\", \"path\"],\n                \"properties\": {\n                    \"path\" : { \"$ref\": \"#/definitions/path\" },\n                    \"op\": {\n                        \"description\": \"The operation to perform.\",\n                        \"type\": \"string\",\n                        \"enum\": [ \"remove\" ]\n                    }\n                }\n            },\n            {\n                \"additionalProperties\": false,\n                \"required\": [ \"from\", \"op\", \"path\" ],\n                \"properties\": {\n                    \"path\" : { \"$ref\": \"#/definitions/path\" },\n                    \"op\": {\n                        \"description\": \"The operation to perform.\",\n                        \"type\": \"string\",\n                        \"enum\": [ \"move\", \"copy\" ]\n                    },\n                    \"from\": {\n                        \"$ref\": \"#/definitions/path\",\n                        \"description\": \"A JSON Pointer path pointing to the location to move/copy from.\"\n                    }\n                }\n            }\n        ]\n    },\n    \"definitions\": {\n        \"path\": {\n            \"description\": \"A JSON Pointer path.\",\n            \"type\": \"string\"\n        }\n    }\n})patch\"_json;\n} // namespace\n\nnamespace nlohmann\n{\n\njson_patch::json_patch(json &&patch)\n    : j_(std::move(patch))\n{\n\tvalidateJsonPatch(j_);\n}\n\njson_patch::json_patch(const json &patch)\n    : j_(std::move(patch))\n{\n\tvalidateJsonPatch(j_);\n}\n\njson_patch &json_patch::add(const json::json_pointer &ptr, json value)\n{\n\tj_.push_back(json{{\"op\", \"add\"}, {\"path\", ptr.to_string()}, {\"value\", std::move(value)}});\n\treturn *this;\n}\n\njson_patch &json_patch::replace(const json::json_pointer &ptr, json value)\n{\n\tj_.push_back(json{{\"op\", \"replace\"}, {\"path\", ptr.to_string()}, {\"value\", std::move(value)}});\n\treturn *this;\n}\n\njson_patch &json_patch::remove(const json::json_pointer &ptr)\n{\n\tj_.push_back(json{{\"op\", \"remove\"}, {\"path\", ptr.to_string()}});\n\treturn *this;\n}\n\nvoid json_patch::validateJsonPatch(json const &patch)\n{\n\t// static put here to have it created at the first usage of validateJsonPatch\n\tstatic nlohmann::json_schema::json_validator patch_validator(patch_schema);\n\n\tpatch_validator.validate(patch);\n\n\tfor (auto const &op : patch)\n\t\tjson::json_pointer(op[\"path\"].get<std::string>());\n}\n\n} // namespace nlohmann\n"
  },
  {
    "path": "src/json-patch.hpp",
    "content": "#pragma once\n\n#include <nlohmann/json.hpp>\n#include <string>\n\nnamespace nlohmann\n{\nclass JsonPatchFormatException : public std::exception\n{\npublic:\n\texplicit JsonPatchFormatException(std::string msg)\n\t    : ex_{std::move(msg)} {}\n\n\tinline const char *what() const noexcept override final { return ex_.c_str(); }\n\nprivate:\n\tstd::string ex_;\n};\n\nclass json_patch\n{\npublic:\n\tjson_patch() = default;\n\tjson_patch(json &&patch);\n\tjson_patch(const json &patch);\n\n\tjson_patch &add(const json::json_pointer &, json value);\n\tjson_patch &replace(const json::json_pointer &, json value);\n\tjson_patch &remove(const json::json_pointer &);\n\n\tjson &get_json() { return j_; }\n\tconst json &get_json() const { return j_; }\n\n\toperator json() const { return j_; }\n\nprivate:\n\tjson j_ = nlohmann::json::array();\n\n\tstatic void validateJsonPatch(json const &patch);\n};\n} // namespace nlohmann\n"
  },
  {
    "path": "src/json-schema-draft7.json.cpp",
    "content": "/*\n * JSON schema validator for JSON for modern C++\n *\n * Copyright (c) 2016-2019 Patrick Boettcher <p@yai.se>.\n *\n * SPDX-License-Identifier: MIT\n *\n */\n#include <nlohmann/json.hpp>\n\nnamespace nlohmann\n{\nnamespace json_schema\n{\n\njson draft7_schema_builtin = R\"( {\n    \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n    \"$id\": \"http://json-schema.org/draft-07/schema#\",\n    \"title\": \"Core schema meta-schema\",\n    \"definitions\": {\n        \"schemaArray\": {\n            \"type\": \"array\",\n            \"minItems\": 1,\n            \"items\": { \"$ref\": \"#\" }\n        },\n        \"nonNegativeInteger\": {\n            \"type\": \"integer\",\n            \"minimum\": 0\n        },\n        \"nonNegativeIntegerDefault0\": {\n            \"allOf\": [\n                { \"$ref\": \"#/definitions/nonNegativeInteger\" },\n                { \"default\": 0 }\n            ]\n        },\n        \"simpleTypes\": {\n            \"enum\": [\n                \"array\",\n                \"boolean\",\n                \"integer\",\n                \"null\",\n                \"number\",\n                \"object\",\n                \"string\"\n            ]\n        },\n        \"stringArray\": {\n            \"type\": \"array\",\n            \"items\": { \"type\": \"string\" },\n            \"uniqueItems\": true,\n            \"default\": []\n        }\n    },\n    \"type\": [\"object\", \"boolean\"],\n    \"properties\": {\n        \"$id\": {\n            \"type\": \"string\",\n            \"format\": \"uri-reference\"\n        },\n        \"$schema\": {\n            \"type\": \"string\",\n            \"format\": \"uri\"\n        },\n        \"$ref\": {\n            \"type\": \"string\",\n            \"format\": \"uri-reference\"\n        },\n        \"$comment\": {\n            \"type\": \"string\"\n        },\n        \"title\": {\n            \"type\": \"string\"\n        },\n        \"description\": {\n            \"type\": \"string\"\n        },\n        \"default\": true,\n        \"readOnly\": {\n            \"type\": \"boolean\",\n            \"default\": false\n        },\n        \"examples\": {\n            \"type\": \"array\",\n            \"items\": true\n        },\n        \"multipleOf\": {\n            \"type\": \"number\",\n            \"exclusiveMinimum\": 0\n        },\n        \"maximum\": {\n            \"type\": \"number\"\n        },\n        \"exclusiveMaximum\": {\n            \"type\": \"number\"\n        },\n        \"minimum\": {\n            \"type\": \"number\"\n        },\n        \"exclusiveMinimum\": {\n            \"type\": \"number\"\n        },\n        \"maxLength\": { \"$ref\": \"#/definitions/nonNegativeInteger\" },\n        \"minLength\": { \"$ref\": \"#/definitions/nonNegativeIntegerDefault0\" },\n        \"pattern\": {\n            \"type\": \"string\",\n            \"format\": \"regex\"\n        },\n        \"additionalItems\": { \"$ref\": \"#\" },\n        \"items\": {\n            \"anyOf\": [\n                { \"$ref\": \"#\" },\n                { \"$ref\": \"#/definitions/schemaArray\" }\n            ],\n            \"default\": true\n        },\n        \"maxItems\": { \"$ref\": \"#/definitions/nonNegativeInteger\" },\n        \"minItems\": { \"$ref\": \"#/definitions/nonNegativeIntegerDefault0\" },\n        \"uniqueItems\": {\n            \"type\": \"boolean\",\n            \"default\": false\n        },\n        \"contains\": { \"$ref\": \"#\" },\n        \"maxProperties\": { \"$ref\": \"#/definitions/nonNegativeInteger\" },\n        \"minProperties\": { \"$ref\": \"#/definitions/nonNegativeIntegerDefault0\" },\n        \"required\": { \"$ref\": \"#/definitions/stringArray\" },\n        \"additionalProperties\": { \"$ref\": \"#\" },\n        \"definitions\": {\n            \"type\": \"object\",\n            \"additionalProperties\": { \"$ref\": \"#\" },\n            \"default\": {}\n        },\n        \"properties\": {\n            \"type\": \"object\",\n            \"additionalProperties\": { \"$ref\": \"#\" },\n            \"default\": {}\n        },\n        \"patternProperties\": {\n            \"type\": \"object\",\n            \"additionalProperties\": { \"$ref\": \"#\" },\n            \"propertyNames\": { \"format\": \"regex\" },\n            \"default\": {}\n        },\n        \"dependencies\": {\n            \"type\": \"object\",\n            \"additionalProperties\": {\n                \"anyOf\": [\n                    { \"$ref\": \"#\" },\n                    { \"$ref\": \"#/definitions/stringArray\" }\n                ]\n            }\n        },\n        \"propertyNames\": { \"$ref\": \"#\" },\n        \"const\": true,\n        \"enum\": {\n            \"type\": \"array\",\n            \"items\": true,\n            \"minItems\": 1,\n            \"uniqueItems\": true\n        },\n        \"type\": {\n            \"anyOf\": [\n                { \"$ref\": \"#/definitions/simpleTypes\" },\n                {\n                    \"type\": \"array\",\n                    \"items\": { \"$ref\": \"#/definitions/simpleTypes\" },\n                    \"minItems\": 1,\n                    \"uniqueItems\": true\n                }\n            ]\n        },\n        \"format\": { \"type\": \"string\" },\n        \"contentMediaType\": { \"type\": \"string\" },\n        \"contentEncoding\": { \"type\": \"string\" },\n        \"if\": { \"$ref\": \"#\" },\n        \"then\": { \"$ref\": \"#\" },\n        \"else\": { \"$ref\": \"#\" },\n        \"allOf\": { \"$ref\": \"#/definitions/schemaArray\" },\n        \"anyOf\": { \"$ref\": \"#/definitions/schemaArray\" },\n        \"oneOf\": { \"$ref\": \"#/definitions/schemaArray\" },\n        \"not\": { \"$ref\": \"#\" }\n    },\n    \"default\": true\n} )\"_json;\n}\n} // namespace nlohmann\n"
  },
  {
    "path": "src/json-uri.cpp",
    "content": "/*\n * JSON schema validator for JSON for modern C++\n *\n * Copyright (c) 2016-2019 Patrick Boettcher <p@yai.se>.\n *\n * SPDX-License-Identifier: MIT\n *\n */\n#include <nlohmann/json-schema.hpp>\n\n#include <sstream>\n\nnamespace nlohmann\n{\n\nvoid json_uri::update(const std::string &uri)\n{\n\tstd::string pointer = \"\"; // default pointer is document-root\n\n\t// first split the URI into location and pointer\n\tauto pointer_separator = uri.find('#');\n\tif (pointer_separator != std::string::npos) {    // and extract the pointer-string if found\n\t\tpointer = uri.substr(pointer_separator + 1); // remove #\n\n\t\t// unescape %-values IOW, decode JSON-URI-formatted JSON-pointer\n\t\tstd::size_t pos = pointer.size() - 1;\n\t\tdo {\n\t\t\tpos = pointer.rfind('%', pos);\n\t\t\tif (pos == std::string::npos)\n\t\t\t\tbreak;\n\n\t\t\tif (pos >= pointer.size() - 2) {\n\t\t\t\tpos--;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tstd::string hex = pointer.substr(pos + 1, 2);\n\t\t\tchar ascii = static_cast<char>(std::strtoul(hex.c_str(), nullptr, 16));\n\t\t\tpointer.replace(pos, 3, 1, ascii);\n\n\t\t\tpos--;\n\t\t} while (1);\n\t}\n\n\tauto location = uri.substr(0, pointer_separator);\n\n\tif (location.size()) { // a location part has been found\n\n\t\t// if it is an URN take it as it is\n\t\tif (location.find(\"urn:\") == 0) {\n\t\t\turn_ = location;\n\n\t\t\t// and clear URL members\n\t\t\tscheme_ = \"\";\n\t\t\tauthority_ = \"\";\n\t\t\tpath_ = \"\";\n\n\t\t} else { // it is an URL\n\n\t\t\t// split URL in protocol, hostname and path\n\t\t\tstd::size_t pos = 0;\n\t\t\tauto proto = location.find(\"://\", pos);\n\t\t\tif (proto != std::string::npos) { // extract the protocol\n\n\t\t\t\turn_ = \"\"; // clear URN-member if URL is parsed\n\n\t\t\t\tscheme_ = location.substr(pos, proto - pos);\n\t\t\t\tpos = 3 + proto; // 3 == \"://\"\n\n\t\t\t\tauto authority = location.find(\"/\", pos);\n\t\t\t\tif (authority != std::string::npos) { // and the hostname (no proto without hostname)\n\t\t\t\t\tauthority_ = location.substr(pos, authority - pos);\n\t\t\t\t\tpos = authority;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tauto path = location.substr(pos);\n\n\t\t\t// URNs cannot of have paths\n\t\t\tif (urn_.size() && path.size())\n\t\t\t\tthrow std::invalid_argument(\"Cannot add a path (\" + path + \") to an URN URI (\" + urn_ + \")\");\n\n\t\t\tif (path[0] == '/') // if it starts with a / it is root-path\n\t\t\t\tpath_ = path;\n\t\t\telse if (pos == 0) { // the URL contained only a path and the current path has no / at the end, strip last element until / and append\n\t\t\t\tauto last_slash = path_.rfind('/');\n\t\t\t\tpath_ = path_.substr(0, last_slash) + '/' + path;\n\t\t\t} else // otherwise it is a subfolder\n\t\t\t\tpath_.append(path);\n\t\t}\n\t}\n\n\tpointer_ = \"\"_json_pointer;\n\tidentifier_ = \"\";\n\n\tif (pointer[0] == '/')\n\t\tpointer_ = json::json_pointer(pointer);\n\telse\n\t\tidentifier_ = pointer;\n}\n\nstd::string json_uri::location() const\n{\n\tif (urn_.size())\n\t\treturn urn_;\n\n\tstd::stringstream s;\n\n\tif (scheme_.size() > 0)\n\t\ts << scheme_ << \"://\";\n\n\ts << authority_\n\t  << path_;\n\n\treturn s.str();\n}\n\nstd::string json_uri::to_string() const\n{\n\tstd::stringstream s;\n\n\ts << location() << \" # \";\n\n\tif (identifier_ == \"\")\n\t\ts << pointer_.to_string();\n\telse\n\t\ts << identifier_;\n\n\treturn s.str();\n}\n\nstd::ostream &operator<<(std::ostream &os, const json_uri &u)\n{\n\treturn os << u.to_string();\n}\n\nstd::string json_uri::escape(const std::string &src)\n{\n\tstd::vector<std::pair<std::string, std::string>> chars = {\n\t    {\"~\", \"~0\"},\n\t    {\"/\", \"~1\"}};\n\n\tstd::string l = src;\n\n\tfor (const auto &c : chars) {\n\t\tstd::size_t pos = 0;\n\t\tdo {\n\t\t\tpos = l.find(c.first, pos);\n\t\t\tif (pos == std::string::npos)\n\t\t\t\tbreak;\n\t\t\tl.replace(pos, 1, c.second);\n\t\t\tpos += c.second.size();\n\t\t} while (1);\n\t}\n\n\treturn l;\n}\n\n} // namespace nlohmann\n"
  },
  {
    "path": "src/json-validator.cpp",
    "content": "/*\n * JSON schema validator for JSON for modern C++\n *\n * Copyright (c) 2016-2019 Patrick Boettcher <p@yai.se>.\n *\n * SPDX-License-Identifier: MIT\n *\n */\n#include <nlohmann/json-schema.hpp>\n\n#include \"json-patch.hpp\"\n\n#include <deque>\n#include <memory>\n#include <set>\n#include <sstream>\n#include <string>\n\nusing nlohmann::json;\nusing nlohmann::json_patch;\nusing nlohmann::json_uri;\nusing nlohmann::json_schema::root_schema;\nusing namespace nlohmann::json_schema;\n\n#ifdef JSON_SCHEMA_BOOST_REGEX\n#\tinclude <boost/regex.hpp>\n#\tdefine REGEX_NAMESPACE boost\n#elif defined(JSON_SCHEMA_NO_REGEX)\n#\tdefine NO_STD_REGEX\n#else\n#\tinclude <regex>\n#\tdefine REGEX_NAMESPACE std\n#endif\n\nnamespace\n{\n\nclass schema\n{\nprotected:\n\troot_schema *root_;\n\tjson default_value_ = nullptr;\n\nprotected:\n\tvirtual std::shared_ptr<schema> make_for_default_(\n\t    std::shared_ptr<::schema> & /* sch */,\n\t    root_schema * /* root */,\n\t    std::vector<nlohmann::json_uri> & /* uris */,\n\t    nlohmann::json & /* default_value */) const\n\t{\n\t\treturn nullptr;\n\t};\n\npublic:\n\tvirtual ~schema() = default;\n\n\tschema(root_schema *root)\n\t    : root_(root) {}\n\n\tvirtual void validate(const json::json_pointer &ptr, const json &instance, json_patch &patch, error_handler &e) const = 0;\n\n\tvirtual const json &default_value(const json::json_pointer &, const json &, error_handler &) const\n\t{\n\t\treturn default_value_;\n\t}\n\n\tvoid set_default_value(const json &v) { default_value_ = v; }\n\n\tstatic std::shared_ptr<schema> make(json &schema,\n\t                                    root_schema *root,\n\t                                    const std::vector<std::string> &key,\n\t                                    std::vector<nlohmann::json_uri> uris);\n};\n\nclass schema_ref : public schema\n{\n\tconst std::string id_;\n\tstd::weak_ptr<schema> target_;\n\tstd::shared_ptr<schema> target_strong_; // for references to references keep also the shared_ptr because\n\t                                        // no one else might use it after resolving\n\n\tvoid validate(const json::json_pointer &ptr, const json &instance, json_patch &patch, error_handler &e) const final\n\t{\n\t\tauto target = target_.lock();\n\n\t\tif (target)\n\t\t\ttarget->validate(ptr, instance, patch, e);\n\t\telse\n\t\t\te.error(ptr, instance, \"unresolved or freed schema-reference \" + id_);\n\t}\n\n\tconst json &default_value(const json::json_pointer &ptr, const json &instance, error_handler &e) const override final\n\t{\n\t\tif (!default_value_.is_null())\n\t\t\treturn default_value_;\n\n\t\tauto target = target_.lock();\n\t\tif (target)\n\t\t\treturn target->default_value(ptr, instance, e);\n\n\t\te.error(ptr, instance, \"unresolved or freed schema-reference \" + id_);\n\n\t\treturn default_value_;\n\t}\n\nprotected:\n\tvirtual std::shared_ptr<schema> make_for_default_(\n\t    std::shared_ptr<::schema> &sch,\n\t    root_schema *root,\n\t    std::vector<nlohmann::json_uri> &uris,\n\t    nlohmann::json &default_value) const override\n\t{\n\t\t// create a new reference schema using the original reference (which will be resolved later)\n\t\t// to store this overloaded default value #209\n\t\tauto result = std::make_shared<schema_ref>(uris[0].to_string(), root);\n\t\tresult->set_target(sch, true);\n\t\tresult->set_default_value(default_value);\n\t\treturn result;\n\t};\n\npublic:\n\tschema_ref(const std::string &id, root_schema *root)\n\t    : schema(root), id_(id) {}\n\n\tconst std::string &id() const { return id_; }\n\n\tvoid set_target(const std::shared_ptr<schema> &target, bool strong = false)\n\t{\n\t\ttarget_ = target;\n\t\tif (strong)\n\t\t\ttarget_strong_ = target;\n\t}\n};\n\n} // namespace\n\nnamespace nlohmann\n{\nnamespace json_schema\n{\n\nclass root_schema\n{\n\tschema_loader loader_;\n\tformat_checker format_check_;\n\tcontent_checker content_check_;\n\n\tstd::shared_ptr<schema> root_;\n\n\tstruct schema_file {\n\t\tstd::map<std::string, std::shared_ptr<schema>> schemas;\n\t\tstd::map<std::string, std::shared_ptr<schema_ref>> unresolved; // contains all unresolved references from any other file seen during parsing\n\t\tjson unknown_keywords;\n\t};\n\n\t// location as key\n\tstd::map<std::string, schema_file> files_;\n\n\tschema_file &get_or_create_file(const std::string &loc)\n\t{\n\t\tauto file = files_.lower_bound(loc);\n\t\tif (file != files_.end() && !(files_.key_comp()(loc, file->first)))\n\t\t\treturn file->second;\n\t\telse\n\t\t\treturn files_.insert(file, {loc, {}})->second;\n\t}\n\npublic:\n\troot_schema(schema_loader &&loader,\n\t            format_checker &&format,\n\t            content_checker &&content)\n\n\t    : loader_(std::move(loader)),\n\t      format_check_(std::move(format)),\n\t      content_check_(std::move(content))\n\t{\n\t}\n\n\tformat_checker &format_check() { return format_check_; }\n\tcontent_checker &content_check() { return content_check_; }\n\n\tvoid insert(const json_uri &uri, const std::shared_ptr<schema> &s)\n\t{\n\t\tauto &file = get_or_create_file(uri.location());\n\t\tauto sch = file.schemas.lower_bound(uri.fragment());\n\t\tif (sch != file.schemas.end() && !(file.schemas.key_comp()(uri.fragment(), sch->first))) {\n\t\t\tthrow std::invalid_argument(\"schema with \" + uri.to_string() + \" already inserted\");\n\t\t\treturn;\n\t\t}\n\n\t\tfile.schemas.insert({uri.fragment(), s});\n\n\t\t// was someone referencing this newly inserted schema?\n\t\tauto unresolved = file.unresolved.find(uri.fragment());\n\t\tif (unresolved != file.unresolved.end()) {\n\t\t\tunresolved->second->set_target(s);\n\t\t\tfile.unresolved.erase(unresolved);\n\t\t}\n\t}\n\n\tvoid insert_unknown_keyword(const json_uri &uri, const std::string &key, json &value)\n\t{\n\t\tauto &file = get_or_create_file(uri.location());\n\t\tauto new_uri = uri.append(key);\n\t\tauto fragment = new_uri.pointer();\n\n\t\t// is there a reference looking for this unknown-keyword, which is thus no longer a unknown keyword but a schema\n\t\tauto unresolved = file.unresolved.find(fragment.to_string());\n\t\tif (unresolved != file.unresolved.end())\n\t\t\tschema::make(value, this, {}, {{new_uri}});\n\t\telse { // no, nothing ref'd it, keep for later\n\n\t\t\t// need to create an object for each reference-token in the\n\t\t\t// JSON-Pointer When not existing, a stringified integer reference\n\t\t\t// token (e.g. \"123\") in the middle of the pointer will be\n\t\t\t// interpreted a an array-index and an array will be created.\n\n\t\t\t// json_pointer's reference_tokens is private - get them\n\t\t\tstd::deque<std::string> ref_tokens;\n\t\t\tauto uri_pointer = uri.pointer();\n\t\t\twhile (!uri_pointer.empty()) {\n\t\t\t\tref_tokens.push_front(uri_pointer.back());\n\t\t\t\turi_pointer.pop_back();\n\t\t\t}\n\n\t\t\t// for each token create an object, if not already existing\n\t\t\tauto unk_kw = &file.unknown_keywords;\n\t\t\tfor (auto &rt : ref_tokens) {\n\t\t\t\t// create a json_pointer from rt as rt can be an stringified integer doing find on an array won't work\n\t\t\t\tjson::json_pointer rt_ptr{\"/\" + rt};\n\t\t\t\tif (unk_kw->contains(rt_ptr) == false)\n\t\t\t\t\t(*unk_kw)[rt] = json::object();\n\t\t\t\tunk_kw = &(*unk_kw)[rt_ptr];\n\t\t\t}\n\t\t\t(*unk_kw)[key] = value;\n\t\t}\n\n\t\t// recursively add possible subschemas of unknown keywords\n\t\tif (value.type() == json::value_t::object)\n\t\t\tfor (auto &subsch : value.items())\n\t\t\t\tinsert_unknown_keyword(new_uri, subsch.key(), subsch.value());\n\t}\n\n\tstd::shared_ptr<schema> get_or_create_ref(const json_uri &uri)\n\t{\n\t\tauto &file = get_or_create_file(uri.location());\n\n\t\t// existing schema\n\t\tauto sch = file.schemas.find(uri.fragment());\n\t\tif (sch != file.schemas.end())\n\t\t\treturn sch->second;\n\n\t\t// referencing an unknown keyword, turn it into schema\n\t\t//\n\t\t// an unknown keyword can only be referenced by a json-pointer,\n\t\t// not by a plain name fragment\n\t\tif (!uri.pointer().to_string().empty()) {\n\t\t\tbool contains_pointer = file.unknown_keywords.contains(uri.pointer());\n\t\t\tif (contains_pointer) {\n\t\t\t\tauto &subschema = file.unknown_keywords.at(uri.pointer());\n\t\t\t\tauto s = schema::make(subschema, this, {}, {{uri}});\n\t\t\t\tif (s) { // if schema is valid (non-null)\n\t\t\t\t\tfile.unknown_keywords.erase(uri.fragment());\n\t\t\t\t\treturn s;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// get or create a schema_ref\n\t\tauto r = file.unresolved.lower_bound(uri.fragment());\n\t\tif (r != file.unresolved.end() && !(file.unresolved.key_comp()(uri.fragment(), r->first))) {\n\t\t\treturn r->second; // unresolved, already seen previously - use existing reference\n\t\t} else {\n\t\t\treturn file.unresolved.insert(r,\n\t\t\t                              {uri.fragment(), std::make_shared<schema_ref>(uri.to_string(), this)})\n\t\t\t    ->second; // unresolved, create reference\n\t\t}\n\t}\n\n\tvoid set_root_schema(json sch)\n\t{\n\t\tfiles_.clear();\n\t\troot_ = schema::make(sch, this, {}, {{\"#\"}});\n\n\t\t// load all files which have not yet been loaded\n\t\tdo {\n\t\t\tbool new_schema_loaded = false;\n\n\t\t\t// files_ is modified during parsing, iterators are invalidated\n\t\t\tstd::vector<std::string> locations;\n\t\t\tfor (auto &file : files_)\n\t\t\t\tlocations.push_back(file.first);\n\n\t\t\tfor (auto &loc : locations) {\n\t\t\t\tif (files_[loc].schemas.size() == 0) { // nothing has been loaded for this file\n\t\t\t\t\tif (loader_) {\n\t\t\t\t\t\tjson loaded_schema;\n\n\t\t\t\t\t\tloader_(loc, loaded_schema);\n\n\t\t\t\t\t\tschema::make(loaded_schema, this, {}, {{loc}});\n\t\t\t\t\t\tnew_schema_loaded = true;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthrow std::invalid_argument(\"external schema reference '\" + loc + \"' needs loading, but no loader callback given\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!new_schema_loaded) // if no new schema loaded, no need to try again\n\t\t\t\tbreak;\n\t\t} while (1);\n\n\t\tfor (const auto &file : files_) {\n\t\t\tif (file.second.unresolved.size() != 0) {\n\t\t\t\t// Build a representation of the undefined\n\t\t\t\t// references as a list of comma-separated strings.\n\t\t\t\tauto n_urefs = file.second.unresolved.size();\n\t\t\t\tstd::string urefs = \"[\";\n\n\t\t\t\tdecltype(n_urefs) counter = 0;\n\t\t\t\tfor (const auto &p : file.second.unresolved) {\n\t\t\t\t\turefs += p.first;\n\n\t\t\t\t\tif (counter != n_urefs - 1u) {\n\t\t\t\t\t\turefs += \", \";\n\t\t\t\t\t}\n\n\t\t\t\t\t++counter;\n\t\t\t\t}\n\n\t\t\t\turefs += \"]\";\n\n\t\t\t\tthrow std::invalid_argument(\"after all files have been parsed, '\" +\n\t\t\t\t                            (file.first == \"\" ? \"<root>\" : file.first) +\n\t\t\t\t                            \"' has still the following undefined references: \" + urefs);\n\t\t\t}\n\t\t}\n\t}\n\n\tvoid validate(const json::json_pointer &ptr,\n\t              const json &instance,\n\t              json_patch &patch,\n\t              error_handler &e,\n\t              const json_uri &initial) const\n\t{\n\t\tif (!root_) {\n\t\t\te.error(ptr, \"\", \"no root schema has yet been set for validating an instance\");\n\t\t\treturn;\n\t\t}\n\n\t\tauto file_entry = files_.find(initial.location());\n\t\tif (file_entry == files_.end()) {\n\t\t\te.error(ptr, \"\", \"no file found serving requested root-URI. \" + initial.location());\n\t\t\treturn;\n\t\t}\n\n\t\tauto &file = file_entry->second;\n\t\tauto sch = file.schemas.find(initial.fragment());\n\t\tif (sch == file.schemas.end()) {\n\t\t\te.error(ptr, \"\", \"no schema find for request initial URI: \" + initial.to_string());\n\t\t\treturn;\n\t\t}\n\n\t\tsch->second->validate(ptr, instance, patch, e);\n\t}\n};\n\n} // namespace json_schema\n} // namespace nlohmann\n\nnamespace\n{\n\nclass first_error_handler : public error_handler\n{\npublic:\n\tbool error_{false};\n\tjson::json_pointer ptr_;\n\tjson instance_;\n\tstd::string message_;\n\n\tvoid error(const json::json_pointer &ptr, const json &instance, const std::string &message) override\n\t{\n\t\tif (*this)\n\t\t\treturn;\n\t\terror_ = true;\n\t\tptr_ = ptr;\n\t\tinstance_ = instance;\n\t\tmessage_ = message;\n\t}\n\n\toperator bool() const { return error_; }\n};\n\nclass logical_not : public schema\n{\n\tstd::shared_ptr<schema> subschema_;\n\n\tvoid validate(const json::json_pointer &ptr, const json &instance, json_patch &patch, error_handler &e) const final\n\t{\n\t\tfirst_error_handler esub;\n\t\tsubschema_->validate(ptr, instance, patch, esub);\n\n\t\tif (!esub)\n\t\t\te.error(ptr, instance, \"the subschema has succeeded, but it is required to not validate\");\n\t}\n\n\tconst json &default_value(const json::json_pointer &ptr, const json &instance, error_handler &e) const override\n\t{\n\t\treturn subschema_->default_value(ptr, instance, e);\n\t}\n\npublic:\n\tlogical_not(json &sch,\n\t            root_schema *root,\n\t            const std::vector<nlohmann::json_uri> &uris)\n\t    : schema(root)\n\t{\n\t\tsubschema_ = schema::make(sch, root, {\"not\"}, uris);\n\t}\n};\n\nenum logical_combination_types {\n\tallOf,\n\tanyOf,\n\toneOf\n};\n\nclass logical_combination_error_handler : public error_handler\n{\npublic:\n\tstruct error_entry {\n\t\tjson::json_pointer ptr_;\n\t\tjson instance_;\n\t\tstd::string message_;\n\t};\n\n\tstd::vector<error_entry> error_entry_list_;\n\n\tvoid error(const json::json_pointer &ptr, const json &instance, const std::string &message) override\n\t{\n\t\terror_entry_list_.push_back(error_entry{ptr, instance, message});\n\t}\n\n\tvoid propagate(error_handler &e, const std::string &prefix) const\n\t{\n\t\tfor (const error_entry &entry : error_entry_list_)\n\t\t\te.error(entry.ptr_, entry.instance_, prefix + entry.message_);\n\t}\n\n\toperator bool() const { return !error_entry_list_.empty(); }\n};\n\ntemplate <enum logical_combination_types combine_logic>\nclass logical_combination : public schema\n{\n\tstd::vector<std::shared_ptr<schema>> subschemata_;\n\n\tvoid validate(const json::json_pointer &ptr, const json &instance, json_patch &patch, error_handler &e) const final\n\t{\n\t\tsize_t count = 0;\n\t\tlogical_combination_error_handler error_summary;\n\n\t\tfor (std::size_t index = 0; index < subschemata_.size(); ++index) {\n\t\t\tconst std::shared_ptr<schema> &s = subschemata_[index];\n\t\t\tlogical_combination_error_handler esub;\n\t\t\tauto oldPatchSize = patch.get_json().size();\n\t\t\ts->validate(ptr, instance, patch, esub);\n\t\t\tif (!esub)\n\t\t\t\tcount++;\n\t\t\telse {\n\t\t\t\tpatch.get_json().get_ref<nlohmann::json::array_t &>().resize(oldPatchSize);\n\t\t\t\tesub.propagate(error_summary, \"case#\" + std::to_string(index) + \"] \");\n\t\t\t}\n\n\t\t\tif (is_validate_complete(instance, ptr, e, esub, count, index))\n\t\t\t\treturn;\n\t\t}\n\n\t\tif (count == 0) {\n\t\t\te.error(ptr, instance, \"no subschema has succeeded, but one of them is required to validate. Type: \" + key + \", number of failed subschemas: \" + std::to_string(subschemata_.size()));\n\t\t\terror_summary.propagate(e, \"[combination: \" + key + \" / \");\n\t\t}\n\t}\n\n\t// specialized for each of the logical_combination_types\n\tstatic const std::string key;\n\tstatic bool is_validate_complete(const json &, const json::json_pointer &, error_handler &, const logical_combination_error_handler &, size_t, size_t);\n\npublic:\n\tlogical_combination(json &sch,\n\t                    root_schema *root,\n\t                    const std::vector<nlohmann::json_uri> &uris)\n\t    : schema(root)\n\t{\n\t\tsize_t c = 0;\n\t\tfor (auto &subschema : sch)\n\t\t\tsubschemata_.push_back(schema::make(subschema, root, {key, std::to_string(c++)}, uris));\n\n\t\t// value of allOf, anyOf, and oneOf \"MUST be a non-empty array\"\n\t\t// TODO error/throw? when subschemata_.empty()\n\t}\n};\n\ntemplate <>\nconst std::string logical_combination<allOf>::key = \"allOf\";\ntemplate <>\nconst std::string logical_combination<anyOf>::key = \"anyOf\";\ntemplate <>\nconst std::string logical_combination<oneOf>::key = \"oneOf\";\n\ntemplate <>\nbool logical_combination<allOf>::is_validate_complete(const json &, const json::json_pointer &, error_handler &e, const logical_combination_error_handler &esub, size_t, size_t current_schema_index)\n{\n\tif (esub) {\n\t\te.error(esub.error_entry_list_.front().ptr_, esub.error_entry_list_.front().instance_, \"at least one subschema has failed, but all of them are required to validate - \" + esub.error_entry_list_.front().message_);\n\t\tesub.propagate(e, \"[combination: allOf / case#\" + std::to_string(current_schema_index) + \"] \");\n\t}\n\treturn esub;\n}\n\ntemplate <>\nbool logical_combination<anyOf>::is_validate_complete(const json &, const json::json_pointer &, error_handler &, const logical_combination_error_handler &, size_t count, size_t)\n{\n\treturn count == 1;\n}\n\ntemplate <>\nbool logical_combination<oneOf>::is_validate_complete(const json &instance, const json::json_pointer &ptr, error_handler &e, const logical_combination_error_handler &, size_t count, size_t)\n{\n\tif (count > 1)\n\t\te.error(ptr, instance, \"more than one subschema has succeeded, but exactly one of them is required to validate\");\n\treturn count > 1;\n}\n\nclass type_schema : public schema\n{\n\tstd::vector<std::shared_ptr<schema>> type_;\n\tstd::pair<bool, json> enum_, const_;\n\tstd::vector<std::shared_ptr<schema>> logic_;\n\n\tstatic std::shared_ptr<schema> make(json &schema,\n\t                                    json::value_t type,\n\t                                    root_schema *,\n\t                                    const std::vector<nlohmann::json_uri> &,\n\t                                    std::set<std::string> &);\n\n\tstd::shared_ptr<schema> if_, then_, else_;\n\n\tvoid validate(const json::json_pointer &ptr, const json &instance, json_patch &patch, error_handler &e) const override final\n\t{\n\t\t// depending on the type of instance run the type specific validator - if present\n\t\tauto type = type_[static_cast<uint8_t>(instance.type())];\n\n\t\tif (type)\n\t\t\ttype->validate(ptr, instance, patch, e);\n\t\telse\n\t\t\te.error(ptr, instance, \"unexpected instance type\");\n\n\t\tif (enum_.first) {\n\t\t\tbool seen_in_enum = false;\n\t\t\tfor (auto &v : enum_.second)\n\t\t\t\tif (instance == v) {\n\t\t\t\t\tseen_in_enum = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\tif (!seen_in_enum)\n\t\t\t\te.error(ptr, instance, \"instance not found in required enum\");\n\t\t}\n\n\t\tif (const_.first &&\n\t\t    const_.second != instance)\n\t\t\te.error(ptr, instance, \"instance not const\");\n\n\t\tfor (auto l : logic_)\n\t\t\tl->validate(ptr, instance, patch, e);\n\n\t\tif (if_) {\n\t\t\tfirst_error_handler err;\n\n\t\t\tif_->validate(ptr, instance, patch, err);\n\t\t\tif (!err) {\n\t\t\t\tif (then_)\n\t\t\t\t\tthen_->validate(ptr, instance, patch, e);\n\t\t\t} else {\n\t\t\t\tif (else_)\n\t\t\t\t\telse_->validate(ptr, instance, patch, e);\n\t\t\t}\n\t\t}\n\t\tif (instance.is_null()) {\n\t\t\tpatch.add(nlohmann::json::json_pointer{}, default_value_);\n\t\t}\n\t}\n\nprotected:\n\tvirtual std::shared_ptr<schema> make_for_default_(\n\t    std::shared_ptr<::schema> & /* sch */,\n\t    root_schema * /* root */,\n\t    std::vector<nlohmann::json_uri> & /* uris */,\n\t    nlohmann::json &default_value) const override\n\t{\n\t\tauto result = std::make_shared<type_schema>(*this);\n\t\tresult->set_default_value(default_value);\n\t\treturn result;\n\t};\n\npublic:\n\ttype_schema(json &sch,\n\t            root_schema *root,\n\t            const std::vector<nlohmann::json_uri> &uris)\n\t    : schema(root), type_(static_cast<uint8_t>(json::value_t::discarded) + 1)\n\t{\n\t\t// association between JSON-schema-type and NLohmann-types\n\t\tstatic const std::vector<std::pair<std::string, json::value_t>> schema_types = {\n\t\t    {\"null\", json::value_t::null},\n\t\t    {\"object\", json::value_t::object},\n\t\t    {\"array\", json::value_t::array},\n\t\t    {\"string\", json::value_t::string},\n\t\t    {\"boolean\", json::value_t::boolean},\n\t\t    {\"integer\", json::value_t::number_integer},\n\t\t    {\"number\", json::value_t::number_float},\n\t\t};\n\n\t\tstd::set<std::string> known_keywords;\n\n\t\tauto attr = sch.find(\"type\");\n\t\tif (attr == sch.end()) // no type field means all sub-types possible\n\t\t\tfor (auto &t : schema_types)\n\t\t\t\ttype_[static_cast<uint8_t>(t.second)] = type_schema::make(sch, t.second, root, uris, known_keywords);\n\t\telse {\n\t\t\tswitch (attr.value().type()) { // \"type\": \"type\"\n\n\t\t\tcase json::value_t::string: {\n\t\t\t\tauto schema_type = attr.value().get<std::string>();\n\t\t\t\tfor (auto &t : schema_types)\n\t\t\t\t\tif (t.first == schema_type)\n\t\t\t\t\t\ttype_[static_cast<uint8_t>(t.second)] = type_schema::make(sch, t.second, root, uris, known_keywords);\n\t\t\t} break;\n\n\t\t\tcase json::value_t::array: // \"type\": [\"type1\", \"type2\"]\n\t\t\t\tfor (auto &array_value : attr.value()) {\n\t\t\t\t\tauto schema_type = array_value.get<std::string>();\n\t\t\t\t\tfor (auto &t : schema_types)\n\t\t\t\t\t\tif (t.first == schema_type)\n\t\t\t\t\t\t\ttype_[static_cast<uint8_t>(t.second)] = type_schema::make(sch, t.second, root, uris, known_keywords);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tsch.erase(attr);\n\t\t}\n\n\t\tattr = sch.find(\"default\");\n\t\tif (attr != sch.end()) {\n\t\t\tset_default_value(attr.value());\n\t\t\tsch.erase(attr);\n\t\t}\n\n\t\tfor (auto &key : known_keywords)\n\t\t\tsch.erase(key);\n\n\t\t// with nlohmann::json float instance (but number in schema-definition) can be seen as unsigned or integer -\n\t\t// reuse the number-validator for integer values as well, if they have not been specified explicitly\n\t\tif (type_[static_cast<uint8_t>(json::value_t::number_float)] && !type_[static_cast<uint8_t>(json::value_t::number_integer)])\n\t\t\ttype_[static_cast<uint8_t>(json::value_t::number_integer)] = type_[static_cast<uint8_t>(json::value_t::number_float)];\n\n\t\t// #54: JSON-schema does not differentiate between unsigned and signed integer - nlohmann::json does\n\t\t// we stick with JSON-schema: use the integer-validator if instance-value is unsigned\n\t\ttype_[static_cast<uint8_t>(json::value_t::number_unsigned)] = type_[static_cast<uint8_t>(json::value_t::number_integer)];\n\n\t\t// special for binary types\n\t\tif (type_[static_cast<uint8_t>(json::value_t::string)]) {\n\t\t\ttype_[static_cast<uint8_t>(json::value_t::binary)] = type_[static_cast<uint8_t>(json::value_t::string)];\n\t\t}\n\n\t\tattr = sch.find(\"enum\");\n\t\tif (attr != sch.end()) {\n\t\t\tenum_ = {true, attr.value()};\n\t\t\tsch.erase(attr);\n\t\t}\n\n\t\tattr = sch.find(\"const\");\n\t\tif (attr != sch.end()) {\n\t\t\tconst_ = {true, attr.value()};\n\t\t\tsch.erase(attr);\n\t\t}\n\n\t\tattr = sch.find(\"not\");\n\t\tif (attr != sch.end()) {\n\t\t\tlogic_.push_back(std::make_shared<logical_not>(attr.value(), root, uris));\n\t\t\tsch.erase(attr);\n\t\t}\n\n\t\tattr = sch.find(\"allOf\");\n\t\tif (attr != sch.end()) {\n\t\t\tlogic_.push_back(std::make_shared<logical_combination<allOf>>(attr.value(), root, uris));\n\t\t\tsch.erase(attr);\n\t\t}\n\n\t\tattr = sch.find(\"anyOf\");\n\t\tif (attr != sch.end()) {\n\t\t\tlogic_.push_back(std::make_shared<logical_combination<anyOf>>(attr.value(), root, uris));\n\t\t\tsch.erase(attr);\n\t\t}\n\n\t\tattr = sch.find(\"oneOf\");\n\t\tif (attr != sch.end()) {\n\t\t\tlogic_.push_back(std::make_shared<logical_combination<oneOf>>(attr.value(), root, uris));\n\t\t\tsch.erase(attr);\n\t\t}\n\n\t\tattr = sch.find(\"if\");\n\t\tif (attr != sch.end()) {\n\t\t\tauto attr_then = sch.find(\"then\");\n\t\t\tauto attr_else = sch.find(\"else\");\n\n\t\t\tif (attr_then != sch.end() || attr_else != sch.end()) {\n\t\t\t\tif_ = schema::make(attr.value(), root, {\"if\"}, uris);\n\n\t\t\t\tif (attr_then != sch.end()) {\n\t\t\t\t\tthen_ = schema::make(attr_then.value(), root, {\"then\"}, uris);\n\t\t\t\t\tsch.erase(attr_then);\n\t\t\t\t}\n\n\t\t\t\tif (attr_else != sch.end()) {\n\t\t\t\t\telse_ = schema::make(attr_else.value(), root, {\"else\"}, uris);\n\t\t\t\t\tsch.erase(attr_else);\n\t\t\t\t}\n\t\t\t}\n\t\t\tsch.erase(attr);\n\t\t}\n\t}\n};\n\nclass string : public schema\n{\n\tstd::pair<bool, size_t> maxLength_{false, 0};\n\tstd::pair<bool, size_t> minLength_{false, 0};\n\n#ifndef NO_STD_REGEX\n\tstd::pair<bool, REGEX_NAMESPACE::regex> pattern_{false, REGEX_NAMESPACE::regex()};\n\tstd::string patternString_;\n#endif\n\n\tstd::pair<bool, std::string> format_;\n\tstd::tuple<bool, std::string, std::string> content_{false, \"\", \"\"};\n\n\tstd::size_t utf8_length(const std::string &s) const\n\t{\n\t\tsize_t len = 0;\n\t\tfor (auto c : s)\n\t\t\tif ((c & 0xc0) != 0x80)\n\t\t\t\tlen++;\n\t\treturn len;\n\t}\n\n\tvoid validate(const json::json_pointer &ptr, const json &instance, json_patch &, error_handler &e) const override\n\t{\n\t\tif (minLength_.first) {\n\t\t\tif (utf8_length(instance.get<std::string>()) < minLength_.second) {\n\t\t\t\tstd::ostringstream s;\n\t\t\t\ts << \"instance is too short as per minLength:\" << minLength_.second;\n\t\t\t\te.error(ptr, instance, s.str());\n\t\t\t}\n\t\t}\n\n\t\tif (maxLength_.first) {\n\t\t\tif (utf8_length(instance.get<std::string>()) > maxLength_.second) {\n\t\t\t\tstd::ostringstream s;\n\t\t\t\ts << \"instance is too long as per maxLength: \" << maxLength_.second;\n\t\t\t\te.error(ptr, instance, s.str());\n\t\t\t}\n\t\t}\n\n\t\tif (std::get<0>(content_)) {\n\t\t\tif (root_->content_check() == nullptr)\n\t\t\t\te.error(ptr, instance, std::string(\"a content checker was not provided but a contentEncoding or contentMediaType for this string have been present: '\") + std::get<1>(content_) + \"' '\" + std::get<2>(content_) + \"'\");\n\t\t\telse {\n\t\t\t\ttry {\n\t\t\t\t\troot_->content_check()(std::get<1>(content_), std::get<2>(content_), instance);\n\t\t\t\t} catch (const std::exception &ex) {\n\t\t\t\t\te.error(ptr, instance, std::string(\"content-checking failed: \") + ex.what());\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (instance.type() == json::value_t::binary) {\n\t\t\te.error(ptr, instance, \"expected string, but get binary data\");\n\t\t}\n\n\t\tif (instance.type() != json::value_t::string) {\n\t\t\treturn; // next checks only for strings\n\t\t}\n\n#ifndef NO_STD_REGEX\n\t\tif (pattern_.first &&\n\t\t    !REGEX_NAMESPACE::regex_search(instance.get<std::string>(), pattern_.second))\n\t\t\te.error(ptr, instance, \"instance does not match regex pattern: \" + patternString_);\n#endif\n\n\t\tif (format_.first) {\n\t\t\tif (root_->format_check() == nullptr)\n\t\t\t\te.error(ptr, instance, std::string(\"a format checker was not provided but a format keyword for this string is present: \") + format_.second);\n\t\t\telse {\n\t\t\t\ttry {\n\t\t\t\t\troot_->format_check()(format_.second, instance.get<std::string>());\n\t\t\t\t} catch (const std::exception &ex) {\n\t\t\t\t\te.error(ptr, instance, std::string(\"format-checking failed: \") + ex.what());\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\npublic:\n\tstring(json &sch, root_schema *root)\n\t    : schema(root)\n\t{\n\t\tauto attr = sch.find(\"maxLength\");\n\t\tif (attr != sch.end()) {\n\t\t\tmaxLength_ = {true, attr.value().get<size_t>()};\n\t\t\tsch.erase(attr);\n\t\t}\n\n\t\tattr = sch.find(\"minLength\");\n\t\tif (attr != sch.end()) {\n\t\t\tminLength_ = {true, attr.value().get<size_t>()};\n\t\t\tsch.erase(attr);\n\t\t}\n\n\t\tattr = sch.find(\"contentEncoding\");\n\t\tif (attr != sch.end()) {\n\t\t\tstd::get<0>(content_) = true;\n\t\t\tstd::get<1>(content_) = attr.value().get<std::string>();\n\n\t\t\t// special case for nlohmann::json-binary-types\n\t\t\t//\n\t\t\t// https://github.com/pboettch/json-schema-validator/pull/114\n\t\t\t//\n\t\t\t// We cannot use explicitly in a schema: {\"type\": \"binary\"} or\n\t\t\t// \"type\": [\"binary\", \"number\"] we have to be implicit. For a\n\t\t\t// schema where \"contentEncoding\" is set to \"binary\", an instance\n\t\t\t// of type json::value_t::binary is accepted. If a\n\t\t\t// contentEncoding-callback has to be provided and is called\n\t\t\t// accordingly. For encoding=binary, no other type validations are done\n\n\t\t\tsch.erase(attr);\n\t\t}\n\n\t\tattr = sch.find(\"contentMediaType\");\n\t\tif (attr != sch.end()) {\n\t\t\tstd::get<0>(content_) = true;\n\t\t\tstd::get<2>(content_) = attr.value().get<std::string>();\n\n\t\t\tsch.erase(attr);\n\t\t}\n\n\t\tif (std::get<0>(content_) == true && root_->content_check() == nullptr) {\n\t\t\tthrow std::invalid_argument{\"schema contains contentEncoding/contentMediaType but content checker was not set\"};\n\t\t}\n\n#ifndef NO_STD_REGEX\n\t\tattr = sch.find(\"pattern\");\n\t\tif (attr != sch.end()) {\n\t\t\tpatternString_ = attr.value().get<std::string>();\n\t\t\tpattern_ = {true, REGEX_NAMESPACE::regex(attr.value().get<std::string>(),\n\t\t\t                                         REGEX_NAMESPACE::regex::ECMAScript)};\n\t\t\tsch.erase(attr);\n\t\t}\n#endif\n\n\t\tattr = sch.find(\"format\");\n\t\tif (attr != sch.end()) {\n\t\t\tif (root_->format_check() == nullptr)\n\t\t\t\tthrow std::invalid_argument{\"a format checker was not provided but a format keyword for this string is present: \" + format_.second};\n\n\t\t\tformat_ = {true, attr.value().get<std::string>()};\n\t\t\tsch.erase(attr);\n\t\t}\n\t}\n};\n\ntemplate <typename T>\nclass numeric : public schema\n{\n\tstd::pair<bool, T> maximum_{false, 0};\n\tstd::pair<bool, T> minimum_{false, 0};\n\n\tbool exclusiveMaximum_ = false;\n\tbool exclusiveMinimum_ = false;\n\n\tstd::pair<bool, json::number_float_t> multipleOf_{false, 0};\n\n\t// multipleOf - if the remainder of the division is 0 -> OK\n\tbool violates_multiple_of(T x) const\n\t{\n\t\tdouble res = std::remainder(x, multipleOf_.second);\n\t\tdouble multiple = std::fabs(x / multipleOf_.second);\n\t\tif (multiple > 1) {\n\t\t\tres = res / multiple;\n\t\t}\n\t\tdouble eps = std::nextafter(x, 0) - static_cast<double>(x);\n\n\t\treturn std::fabs(res) > std::fabs(eps);\n\t}\n\n\tvoid validate(const json::json_pointer &ptr, const json &instance, json_patch &, error_handler &e) const override\n\t{\n\t\tT value = instance; // conversion of json to value_type\n\n\t\tstd::ostringstream oss;\n\n\t\tif (multipleOf_.first && value != 0) // zero is multiple of everything\n\t\t\tif (violates_multiple_of(value))\n\t\t\t\toss << \"instance is not a multiple of \" << json(multipleOf_.second);\n\n\t\tif (maximum_.first) {\n\t\t\tif (exclusiveMaximum_ && value >= maximum_.second)\n\t\t\t\toss << \"instance exceeds or equals maximum of \" << json(maximum_.second);\n\t\t\telse if (value > maximum_.second)\n\t\t\t\toss << \"instance exceeds maximum of \" << json(maximum_.second);\n\t\t}\n\n\t\tif (minimum_.first) {\n\t\t\tif (exclusiveMinimum_ && value <= minimum_.second)\n\t\t\t\toss << \"instance is below or equals minimum of \" << json(minimum_.second);\n\t\t\telse if (value < minimum_.second)\n\t\t\t\toss << \"instance is below minimum of \" << json(minimum_.second);\n\t\t}\n\n\t\toss.seekp(0, std::ios::end);\n\t\tauto size = oss.tellp();\n\t\tif (size != 0) {\n\t\t\toss.seekp(0, std::ios::beg);\n\t\t\te.error(ptr, instance, oss.str());\n\t\t}\n\t}\n\npublic:\n\tnumeric(const json &sch, root_schema *root, std::set<std::string> &kw)\n\t    : schema(root)\n\t{\n\t\tauto attr = sch.find(\"maximum\");\n\t\tif (attr != sch.end()) {\n\t\t\tmaximum_ = {true, attr.value().get<T>()};\n\t\t\tkw.insert(\"maximum\");\n\t\t}\n\n\t\tattr = sch.find(\"minimum\");\n\t\tif (attr != sch.end()) {\n\t\t\tminimum_ = {true, attr.value().get<T>()};\n\t\t\tkw.insert(\"minimum\");\n\t\t}\n\n\t\tattr = sch.find(\"exclusiveMaximum\");\n\t\tif (attr != sch.end()) {\n\t\t\texclusiveMaximum_ = true;\n\t\t\tmaximum_ = {true, attr.value().get<T>()};\n\t\t\tkw.insert(\"exclusiveMaximum\");\n\t\t}\n\n\t\tattr = sch.find(\"exclusiveMinimum\");\n\t\tif (attr != sch.end()) {\n\t\t\texclusiveMinimum_ = true;\n\t\t\tminimum_ = {true, attr.value().get<T>()};\n\t\t\tkw.insert(\"exclusiveMinimum\");\n\t\t}\n\n\t\tattr = sch.find(\"multipleOf\");\n\t\tif (attr != sch.end()) {\n\t\t\tmultipleOf_ = {true, attr.value().get<json::number_float_t>()};\n\t\t\tkw.insert(\"multipleOf\");\n\t\t}\n\t}\n};\n\nclass null : public schema\n{\n\tvoid validate(const json::json_pointer &ptr, const json &instance, json_patch &, error_handler &e) const override\n\t{\n\t\tif (!instance.is_null())\n\t\t\te.error(ptr, instance, \"expected to be null\");\n\t}\n\npublic:\n\tnull(json &, root_schema *root)\n\t    : schema(root) {}\n};\n\nclass boolean_type : public schema\n{\n\tvoid validate(const json::json_pointer &, const json &, json_patch &, error_handler &) const override {}\n\npublic:\n\tboolean_type(json &, root_schema *root)\n\t    : schema(root) {}\n};\n\nclass boolean : public schema\n{\n\tbool true_;\n\tvoid validate(const json::json_pointer &ptr, const json &instance, json_patch &, error_handler &e) const override\n\t{\n\t\tif (!true_) { // false schema\n\t\t\t// empty array\n\t\t\t// switch (instance.type()) {\n\t\t\t// case json::value_t::array:\n\t\t\t//\tif (instance.size() != 0) // valid false-schema\n\t\t\t//\t\te.error(ptr, instance, \"false-schema required empty array\");\n\t\t\t//\treturn;\n\t\t\t//}\n\n\t\t\te.error(ptr, instance, \"instance invalid as per false-schema\");\n\t\t}\n\t}\n\npublic:\n\tboolean(json &sch, root_schema *root)\n\t    : schema(root), true_(sch) {}\n};\n\nclass required : public schema\n{\n\tconst std::vector<std::string> required_;\n\n\tvoid validate(const json::json_pointer &ptr, const json &instance, json_patch &, error_handler &e) const override final\n\t{\n\t\tfor (auto &r : required_)\n\t\t\tif (instance.find(r) == instance.end())\n\t\t\t\te.error(ptr, instance, \"required property '\" + r + \"' not found in object as a dependency\");\n\t}\n\npublic:\n\trequired(const std::vector<std::string> &r, root_schema *root)\n\t    : schema(root), required_(r) {}\n};\n\nclass object : public schema\n{\n\tstd::pair<bool, size_t> maxProperties_{false, 0};\n\tstd::pair<bool, size_t> minProperties_{false, 0};\n\tstd::vector<std::string> required_;\n\n\tstd::map<std::string, std::shared_ptr<schema>> properties_;\n#ifndef NO_STD_REGEX\n\tstd::vector<std::pair<REGEX_NAMESPACE::regex, std::shared_ptr<schema>>> patternProperties_;\n#endif\n\tstd::shared_ptr<schema> additionalProperties_;\n\n\tstd::map<std::string, std::shared_ptr<schema>> dependencies_;\n\n\tstd::shared_ptr<schema> propertyNames_;\n\n\tvoid validate(const json::json_pointer &ptr, const json &instance, json_patch &patch, error_handler &e) const override\n\t{\n\t\tif (maxProperties_.first && instance.size() > maxProperties_.second)\n\t\t\te.error(ptr, instance, \"too many properties\");\n\n\t\tif (minProperties_.first && instance.size() < minProperties_.second)\n\t\t\te.error(ptr, instance, \"too few properties\");\n\n\t\tfor (auto &r : required_)\n\t\t\tif (instance.find(r) == instance.end())\n\t\t\t\te.error(ptr, instance, \"required property '\" + r + \"' not found in object\");\n\n\t\t// for each property in instance\n\t\tfor (auto &p : instance.items()) {\n\t\t\tif (propertyNames_)\n\t\t\t\tpropertyNames_->validate(ptr, p.key(), patch, e);\n\n\t\t\tbool a_prop_or_pattern_matched = false;\n\t\t\tauto schema_p = properties_.find(p.key());\n\t\t\t// check if it is in \"properties\"\n\t\t\tif (schema_p != properties_.end()) {\n\t\t\t\ta_prop_or_pattern_matched = true;\n\t\t\t\tschema_p->second->validate(ptr / p.key(), p.value(), patch, e);\n\t\t\t}\n\n#ifndef NO_STD_REGEX\n\t\t\t// check all matching patternProperties\n\t\t\tfor (auto &schema_pp : patternProperties_)\n\t\t\t\tif (REGEX_NAMESPACE::regex_search(p.key(), schema_pp.first)) {\n\t\t\t\t\ta_prop_or_pattern_matched = true;\n\t\t\t\t\tschema_pp.second->validate(ptr / p.key(), p.value(), patch, e);\n\t\t\t\t}\n#endif\n\n\t\t\t// check additionalProperties as a last resort\n\t\t\tif (!a_prop_or_pattern_matched && additionalProperties_) {\n\t\t\t\tfirst_error_handler additional_prop_err;\n\t\t\t\tadditionalProperties_->validate(ptr / p.key(), p.value(), patch, additional_prop_err);\n\t\t\t\tif (additional_prop_err)\n\t\t\t\t\te.error(ptr, instance, \"validation failed for additional property '\" + p.key() + \"': \" + additional_prop_err.message_);\n\t\t\t}\n\t\t}\n\n\t\t// reverse search\n\t\tfor (auto const &prop : properties_) {\n\t\t\tconst auto finding = instance.find(prop.first);\n\t\t\tif (instance.end() == finding) { // if the prop is not in the instance\n\t\t\t\tconst auto &default_value = prop.second->default_value(ptr, instance, e);\n\t\t\t\tif (!default_value.is_null()) { // if default value is available\n\t\t\t\t\tpatch.add((ptr / prop.first), default_value);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor (auto &dep : dependencies_) {\n\t\t\tauto prop = instance.find(dep.first);\n\t\t\tif (prop != instance.end())                                    // if dependency-property is present in instance\n\t\t\t\tdep.second->validate(ptr / dep.first, instance, patch, e); // validate\n\t\t}\n\t}\n\npublic:\n\tobject(json &sch,\n\t       root_schema *root,\n\t       const std::vector<nlohmann::json_uri> &uris)\n\t    : schema(root)\n\t{\n\t\tauto attr = sch.find(\"maxProperties\");\n\t\tif (attr != sch.end()) {\n\t\t\tmaxProperties_ = {true, attr.value().get<size_t>()};\n\t\t\tsch.erase(attr);\n\t\t}\n\n\t\tattr = sch.find(\"minProperties\");\n\t\tif (attr != sch.end()) {\n\t\t\tminProperties_ = {true, attr.value().get<size_t>()};\n\t\t\tsch.erase(attr);\n\t\t}\n\n\t\tattr = sch.find(\"required\");\n\t\tif (attr != sch.end()) {\n\t\t\trequired_ = attr.value().get<std::vector<std::string>>();\n\t\t\tsch.erase(attr);\n\t\t}\n\n\t\tattr = sch.find(\"properties\");\n\t\tif (attr != sch.end()) {\n\t\t\tfor (auto prop : attr.value().items())\n\t\t\t\tproperties_.insert(\n\t\t\t\t    std::make_pair(\n\t\t\t\t        prop.key(),\n\t\t\t\t        schema::make(prop.value(), root, {\"properties\", prop.key()}, uris)));\n\t\t\tsch.erase(attr);\n\t\t}\n\n#ifndef NO_STD_REGEX\n\t\tattr = sch.find(\"patternProperties\");\n\t\tif (attr != sch.end()) {\n\t\t\tfor (auto prop : attr.value().items())\n\t\t\t\tpatternProperties_.push_back(\n\t\t\t\t    std::make_pair(\n\t\t\t\t        REGEX_NAMESPACE::regex(prop.key(), REGEX_NAMESPACE::regex::ECMAScript),\n\t\t\t\t        schema::make(prop.value(), root, {prop.key()}, uris)));\n\t\t\tsch.erase(attr);\n\t\t}\n#endif\n\n\t\tattr = sch.find(\"additionalProperties\");\n\t\tif (attr != sch.end()) {\n\t\t\tadditionalProperties_ = schema::make(attr.value(), root, {\"additionalProperties\"}, uris);\n\t\t\tsch.erase(attr);\n\t\t}\n\n\t\tattr = sch.find(\"dependencies\");\n\t\tif (attr != sch.end()) {\n\t\t\tfor (auto &dep : attr.value().items())\n\t\t\t\tswitch (dep.value().type()) {\n\t\t\t\tcase json::value_t::array:\n\t\t\t\t\tdependencies_.emplace(dep.key(),\n\t\t\t\t\t                      std::make_shared<required>(\n\t\t\t\t\t                          dep.value().get<std::vector<std::string>>(), root));\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tdependencies_.emplace(dep.key(),\n\t\t\t\t\t                      schema::make(dep.value(), root, {\"dependencies\", dep.key()}, uris));\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\tsch.erase(attr);\n\t\t}\n\n\t\tattr = sch.find(\"propertyNames\");\n\t\tif (attr != sch.end()) {\n\t\t\tpropertyNames_ = schema::make(attr.value(), root, {\"propertyNames\"}, uris);\n\t\t\tsch.erase(attr);\n\t\t}\n\n\t\tattr = sch.find(\"default\");\n\t\tif (attr != sch.end()) {\n\t\t\tset_default_value(*attr);\n\t\t}\n\t}\n};\n\nclass array : public schema\n{\n\tstd::pair<bool, size_t> maxItems_{false, 0};\n\tstd::pair<bool, size_t> minItems_{false, 0};\n\tbool uniqueItems_ = false;\n\n\tstd::shared_ptr<schema> items_schema_;\n\n\tstd::vector<std::shared_ptr<schema>> items_;\n\tstd::shared_ptr<schema> additionalItems_;\n\n\tstd::shared_ptr<schema> contains_;\n\n\tvoid validate(const json::json_pointer &ptr, const json &instance, json_patch &patch, error_handler &e) const override\n\t{\n\t\tif (maxItems_.first && instance.size() > maxItems_.second)\n\t\t\te.error(ptr, instance, \"array has too many items\");\n\n\t\tif (minItems_.first && instance.size() < minItems_.second)\n\t\t\te.error(ptr, instance, \"array has too few items\");\n\n\t\tif (uniqueItems_) {\n\t\t\tfor (auto it = instance.cbegin(); it != instance.cend(); ++it) {\n\t\t\t\tauto v = std::find(it + 1, instance.end(), *it);\n\t\t\t\tif (v != instance.end())\n\t\t\t\t\te.error(ptr, instance, \"items have to be unique for this array\");\n\t\t\t}\n\t\t}\n\n\t\tsize_t index = 0;\n\t\tif (items_schema_)\n\t\t\tfor (auto &i : instance) {\n\t\t\t\titems_schema_->validate(ptr / index, i, patch, e);\n\t\t\t\tindex++;\n\t\t\t}\n\t\telse {\n\t\t\tauto item = items_.cbegin();\n\t\t\tfor (auto &i : instance) {\n\t\t\t\tstd::shared_ptr<schema> item_validator;\n\t\t\t\tif (item == items_.cend())\n\t\t\t\t\titem_validator = additionalItems_;\n\t\t\t\telse {\n\t\t\t\t\titem_validator = *item;\n\t\t\t\t\titem++;\n\t\t\t\t}\n\n\t\t\t\tif (!item_validator)\n\t\t\t\t\tbreak;\n\n\t\t\t\titem_validator->validate(ptr / index, i, patch, e);\n\t\t\t}\n\t\t}\n\n\t\tif (contains_) {\n\t\t\tbool contained = false;\n\t\t\tfor (auto &item : instance) {\n\t\t\t\tfirst_error_handler local_e;\n\t\t\t\tcontains_->validate(ptr, item, patch, local_e);\n\t\t\t\tif (!local_e) {\n\t\t\t\t\tcontained = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!contained)\n\t\t\t\te.error(ptr, instance, \"array does not contain required element as per 'contains'\");\n\t\t}\n\t}\n\npublic:\n\tarray(json &sch, root_schema *root, const std::vector<nlohmann::json_uri> &uris)\n\t    : schema(root)\n\t{\n\t\tauto attr = sch.find(\"maxItems\");\n\t\tif (attr != sch.end()) {\n\t\t\tmaxItems_ = {true, attr.value().get<size_t>()};\n\t\t\tsch.erase(attr);\n\t\t}\n\n\t\tattr = sch.find(\"minItems\");\n\t\tif (attr != sch.end()) {\n\t\t\tminItems_ = {true, attr.value().get<size_t>()};\n\t\t\tsch.erase(attr);\n\t\t}\n\n\t\tattr = sch.find(\"uniqueItems\");\n\t\tif (attr != sch.end()) {\n\t\t\tuniqueItems_ = attr.value().get<bool>();\n\t\t\tsch.erase(attr);\n\t\t}\n\n\t\tattr = sch.find(\"items\");\n\t\tif (attr != sch.end()) {\n\n\t\t\tif (attr.value().type() == json::value_t::array) {\n\t\t\t\tsize_t c = 0;\n\t\t\t\tfor (auto &subsch : attr.value())\n\t\t\t\t\titems_.push_back(schema::make(subsch, root, {\"items\", std::to_string(c++)}, uris));\n\n\t\t\t\tauto attr_add = sch.find(\"additionalItems\");\n\t\t\t\tif (attr_add != sch.end()) {\n\t\t\t\t\tadditionalItems_ = schema::make(attr_add.value(), root, {\"additionalItems\"}, uris);\n\t\t\t\t\tsch.erase(attr_add);\n\t\t\t\t}\n\n\t\t\t} else if (attr.value().type() == json::value_t::object ||\n\t\t\t           attr.value().type() == json::value_t::boolean)\n\t\t\t\titems_schema_ = schema::make(attr.value(), root, {\"items\"}, uris);\n\n\t\t\tsch.erase(attr);\n\t\t}\n\n\t\tattr = sch.find(\"contains\");\n\t\tif (attr != sch.end()) {\n\t\t\tcontains_ = schema::make(attr.value(), root, {\"contains\"}, uris);\n\t\t\tsch.erase(attr);\n\t\t}\n\t}\n};\n\nstd::shared_ptr<schema> type_schema::make(json &schema,\n                                          json::value_t type,\n                                          root_schema *root,\n                                          const std::vector<nlohmann::json_uri> &uris,\n                                          std::set<std::string> &kw)\n{\n\tswitch (type) {\n\tcase json::value_t::null:\n\t\treturn std::make_shared<null>(schema, root);\n\n\tcase json::value_t::number_unsigned:\n\tcase json::value_t::number_integer:\n\t\treturn std::make_shared<numeric<json::number_integer_t>>(schema, root, kw);\n\tcase json::value_t::number_float:\n\t\treturn std::make_shared<numeric<json::number_float_t>>(schema, root, kw);\n\tcase json::value_t::string:\n\t\treturn std::make_shared<string>(schema, root);\n\tcase json::value_t::boolean:\n\t\treturn std::make_shared<boolean_type>(schema, root);\n\tcase json::value_t::object:\n\t\treturn std::make_shared<object>(schema, root, uris);\n\tcase json::value_t::array:\n\t\treturn std::make_shared<array>(schema, root, uris);\n\n\tcase json::value_t::discarded: // not a real type - silence please\n\t\tbreak;\n\n\tcase json::value_t::binary:\n\t\tbreak;\n\t}\n\treturn nullptr;\n}\n} // namespace\n\nnamespace\n{\n\nstd::shared_ptr<schema> schema::make(json &schema,\n                                     root_schema *root,\n                                     const std::vector<std::string> &keys,\n                                     std::vector<nlohmann::json_uri> uris)\n{\n\t// remove URIs which contain plain name identifiers, as sub-schemas cannot be referenced\n\tfor (auto uri = uris.begin(); uri != uris.end();)\n\t\tif (uri->identifier() != \"\")\n\t\t\turi = uris.erase(uri);\n\t\telse\n\t\t\turi++;\n\n\t// append to all URIs the keys for this sub-schema\n\tfor (auto &key : keys)\n\t\tfor (auto &uri : uris)\n\t\t\turi = uri.append(key);\n\n\tstd::shared_ptr<::schema> sch;\n\n\t// boolean schema\n\tif (schema.type() == json::value_t::boolean)\n\t\tsch = std::make_shared<boolean>(schema, root);\n\telse if (schema.type() == json::value_t::object) {\n\n\t\tauto attr = schema.find(\"$id\"); // if $id is present, this schema can be referenced by this ID\n\t\t                                // as an additional URI\n\t\tif (attr != schema.end()) {\n\t\t\tif (std::find(uris.begin(),\n\t\t\t              uris.end(),\n\t\t\t              attr.value().get<std::string>()) == uris.end())\n\t\t\t\turis.push_back(uris.back().derive(attr.value().get<std::string>())); // so add it to the list if it is not there already\n\t\t\tschema.erase(attr);\n\t\t}\n\n\t\tauto findDefinitions = [&](const std::string &defs) -> bool {\n\t\t\tattr = schema.find(defs);\n\t\t\tif (attr != schema.end()) {\n\t\t\t\tfor (auto &def : attr.value().items())\n\t\t\t\t\tschema::make(def.value(), root, {defs, def.key()}, uris);\n\t\t\t\tschema.erase(attr);\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\treturn false;\n\t\t};\n\t\tif (!findDefinitions(\"$defs\")) {\n\t\t\tfindDefinitions(\"definitions\");\n\t\t}\n\n\t\tattr = schema.find(\"$ref\");\n\t\tif (attr != schema.end()) { // this schema is a reference\n\t\t\t// the last one on the uri-stack is the last id seen before coming here,\n\t\t\t// so this is the origial URI for this reference, the $ref-value has thus be resolved from it\n\t\t\tauto id = uris.back().derive(attr.value().get<std::string>());\n\t\t\tsch = root->get_or_create_ref(id);\n\n\t\t\tschema.erase(attr);\n\n\t\t\t// special case where we break draft-7 and allow overriding of properties when a $ref is used\n\t\t\tattr = schema.find(\"default\");\n\t\t\tif (attr != schema.end()) {\n\t\t\t\t// copy the referenced schema depending on the underlying type and modify the default value\n\t\t\t\tif (auto new_sch = sch->make_for_default_(sch, root, uris, attr.value())) {\n\t\t\t\t\tsch = new_sch;\n\t\t\t\t}\n\t\t\t\tschema.erase(attr);\n\t\t\t}\n\t\t} else {\n\t\t\tsch = std::make_shared<type_schema>(schema, root, uris);\n\t\t}\n\n\t\tschema.erase(\"$schema\");\n\t\tschema.erase(\"title\");\n\t\tschema.erase(\"description\");\n\t} else {\n\t\tthrow std::invalid_argument(\"invalid JSON-type for a schema for \" + uris[0].to_string() + \", expected: boolean or object\");\n\t}\n\n\tfor (auto &uri : uris) { // for all URIs this schema is referenced by\n\t\troot->insert(uri, sch);\n\n\t\tif (schema.type() == json::value_t::object)\n\t\t\tfor (auto &u : schema.items())\n\t\t\t\troot->insert_unknown_keyword(uri, u.key(), u.value()); // insert unknown keywords for later reference\n\t}\n\treturn sch;\n}\n\nclass throwing_error_handler : public error_handler\n{\n\tvoid error(const json::json_pointer &ptr, const json &instance, const std::string &message) override\n\t{\n\t\tthrow std::invalid_argument(std::string(\"At \") + ptr.to_string() + \" of \" + instance.dump() + \" - \" + message + \"\\n\");\n\t}\n};\n\n} // namespace\n\nnamespace nlohmann\n{\nnamespace json_schema\n{\n\njson_validator::json_validator(schema_loader loader,\n                               format_checker format,\n                               content_checker content)\n    : root_(std::unique_ptr<root_schema>(new root_schema(std::move(loader),\n                                                         std::move(format),\n                                                         std::move(content))))\n{\n}\n\njson_validator::json_validator(const json &schema,\n                               schema_loader loader,\n                               format_checker format,\n                               content_checker content)\n    : json_validator(std::move(loader),\n                     std::move(format),\n                     std::move(content))\n{\n\tset_root_schema(schema);\n}\n\njson_validator::json_validator(json &&schema,\n                               schema_loader loader,\n                               format_checker format,\n                               content_checker content)\n\n    : json_validator(std::move(loader),\n                     std::move(format),\n                     std::move(content))\n{\n\tset_root_schema(std::move(schema));\n}\n\n// move constructor, destructor and move assignment operator can be defaulted here\n// where root_schema is a complete type\njson_validator::json_validator(json_validator &&) = default;\njson_validator::~json_validator() = default;\njson_validator &json_validator::operator=(json_validator &&) = default;\n\nvoid json_validator::set_root_schema(const json &schema)\n{\n\troot_->set_root_schema(schema);\n}\n\nvoid json_validator::set_root_schema(json &&schema)\n{\n\troot_->set_root_schema(std::move(schema));\n}\n\njson json_validator::validate(const json &instance) const\n{\n\tthrowing_error_handler err;\n\treturn validate(instance, err);\n}\n\njson json_validator::validate(const json &instance, error_handler &err, const json_uri &initial_uri) const\n{\n\tjson::json_pointer ptr;\n\tjson_patch patch;\n\troot_->validate(ptr, instance, patch, err, initial_uri);\n\treturn patch;\n}\n\n} // namespace json_schema\n} // namespace nlohmann\n"
  },
  {
    "path": "src/nlohmann/json-schema.hpp",
    "content": "/*\n * JSON schema validator for JSON for modern C++\n *\n * Copyright (c) 2016-2019 Patrick Boettcher <p@yai.se>.\n *\n * SPDX-License-Identifier: MIT\n *\n */\n#ifndef NLOHMANN_JSON_SCHEMA_HPP__\n#define NLOHMANN_JSON_SCHEMA_HPP__\n\n#ifdef _WIN32\n#\tif defined(JSON_SCHEMA_VALIDATOR_EXPORTS)\n#\t\tdefine JSON_SCHEMA_VALIDATOR_API __declspec(dllexport)\n#\telif defined(JSON_SCHEMA_VALIDATOR_IMPORTS)\n#\t\tdefine JSON_SCHEMA_VALIDATOR_API __declspec(dllimport)\n#\telse\n#\t\tdefine JSON_SCHEMA_VALIDATOR_API\n#\tendif\n#else\n#\tdefine JSON_SCHEMA_VALIDATOR_API\n#endif\n\n#include <nlohmann/json.hpp>\n\n#ifdef NLOHMANN_JSON_VERSION_MAJOR\n#\tif (NLOHMANN_JSON_VERSION_MAJOR * 10000 + NLOHMANN_JSON_VERSION_MINOR * 100 + NLOHMANN_JSON_VERSION_PATCH) < 30800\n#\t\terror \"Please use this library with NLohmann's JSON version 3.8.0 or higher\"\n#\tendif\n#else\n#\terror \"expected existing NLOHMANN_JSON_VERSION_MAJOR preproc variable, please update to NLohmann's JSON 3.8.0\"\n#endif\n\n// make yourself a home - welcome to nlohmann's namespace\nnamespace nlohmann\n{\n\n// A class representing a JSON-URI for schemas derived from\n// section 8 of JSON Schema: A Media Type for Describing JSON Documents\n// draft-wright-json-schema-00\n//\n// New URIs can be derived from it using the derive()-method.\n// This is useful for resolving refs or subschema-IDs in json-schemas.\n//\n// This is done implement the requirements described in section 8.2.\n//\nclass JSON_SCHEMA_VALIDATOR_API json_uri\n{\n\tstd::string urn_;\n\n\tstd::string scheme_;\n\tstd::string authority_;\n\tstd::string path_;\n\n\tjson::json_pointer pointer_; // fragment part if JSON-Pointer\n\tstd::string identifier_;     // fragment part if Locatation Independent ID\n\nprotected:\n\t// decodes a JSON uri and replaces all or part of the currently stored values\n\tvoid update(const std::string &uri);\n\n\tstd::tuple<std::string, std::string, std::string, std::string, std::string> as_tuple() const\n\t{\n\t\treturn std::make_tuple(urn_, scheme_, authority_, path_, identifier_ != \"\" ? identifier_ : pointer_.to_string());\n\t}\n\npublic:\n\tjson_uri(const std::string &uri)\n\t{\n\t\tupdate(uri);\n\t}\n\n\tconst std::string &scheme() const { return scheme_; }\n\tconst std::string &authority() const { return authority_; }\n\tconst std::string &path() const { return path_; }\n\n\tconst json::json_pointer &pointer() const { return pointer_; }\n\tconst std::string &identifier() const { return identifier_; }\n\n\tstd::string fragment() const\n\t{\n\t\tif (identifier_ == \"\")\n\t\t\treturn pointer_.to_string();\n\t\telse\n\t\t\treturn identifier_;\n\t}\n\n\tstd::string url() const { return location(); }\n\tstd::string location() const;\n\n\tstatic std::string escape(const std::string &);\n\n\t// create a new json_uri based in this one and the given uri\n\t// resolves relative changes (pathes or pointers) and resets part if proto or hostname changes\n\tjson_uri derive(const std::string &uri) const\n\t{\n\t\tjson_uri u = *this;\n\t\tu.update(uri);\n\t\treturn u;\n\t}\n\n\t// append a pointer-field to the pointer-part of this uri\n\tjson_uri append(const std::string &field) const\n\t{\n\t\tif (identifier_ != \"\")\n\t\t\treturn *this;\n\n\t\tjson_uri u = *this;\n\t\tu.pointer_ /= field;\n\t\treturn u;\n\t}\n\n\tstd::string to_string() const;\n\n\tfriend bool operator<(const json_uri &l, const json_uri &r)\n\t{\n\t\treturn l.as_tuple() < r.as_tuple();\n\t}\n\n\tfriend bool operator==(const json_uri &l, const json_uri &r)\n\t{\n\t\treturn l.as_tuple() == r.as_tuple();\n\t}\n\n\tfriend std::ostream &operator<<(std::ostream &os, const json_uri &u);\n};\n\nnamespace json_schema\n{\n\nextern json draft7_schema_builtin;\n\ntypedef std::function<void(const json_uri & /*id*/, json & /*value*/)> schema_loader;\ntypedef std::function<void(const std::string & /*format*/, const std::string & /*value*/)> format_checker;\ntypedef std::function<void(const std::string & /*contentEncoding*/, const std::string & /*contentMediaType*/, const json & /*instance*/)> content_checker;\n\n// Interface for validation error handlers\nclass JSON_SCHEMA_VALIDATOR_API error_handler\n{\npublic:\n\tvirtual ~error_handler() {}\n\tvirtual void error(const json::json_pointer & /*ptr*/, const json & /*instance*/, const std::string & /*message*/) = 0;\n};\n\nclass JSON_SCHEMA_VALIDATOR_API basic_error_handler : public error_handler\n{\n\tbool error_{false};\n\npublic:\n\tvoid error(const json::json_pointer & /*ptr*/, const json & /*instance*/, const std::string & /*message*/) override\n\t{\n\t\terror_ = true;\n\t}\n\n\tvirtual void reset() { error_ = false; }\n\toperator bool() const { return error_; }\n};\n\n/**\n * Checks validity of JSON schema built-in string format specifiers like 'date-time', 'ipv4', ...\n */\nvoid JSON_SCHEMA_VALIDATOR_API default_string_format_check(const std::string &format, const std::string &value);\n\nclass root_schema;\n\nclass JSON_SCHEMA_VALIDATOR_API json_validator\n{\n\tstd::unique_ptr<root_schema> root_;\n\npublic:\n\tjson_validator(schema_loader = nullptr, format_checker = nullptr, content_checker = nullptr);\n\n\tjson_validator(const json &, schema_loader = nullptr, format_checker = nullptr, content_checker = nullptr);\n\tjson_validator(json &&, schema_loader = nullptr, format_checker = nullptr, content_checker = nullptr);\n\n\tjson_validator(json_validator &&);\n\tjson_validator &operator=(json_validator &&);\n\n\tjson_validator(json_validator const &) = delete;\n\tjson_validator &operator=(json_validator const &) = delete;\n\n\t~json_validator();\n\n\t// insert and set the root-schema\n\tvoid set_root_schema(const json &);\n\tvoid set_root_schema(json &&);\n\n\t// validate a json-document based on the root-schema\n\tjson validate(const json &) const;\n\n\t// validate a json-document based on the root-schema with a custom error-handler\n\tjson validate(const json &, error_handler &, const json_uri &initial_uri = json_uri(\"#\")) const;\n};\n\n} // namespace json_schema\n} // namespace nlohmann\n\n#endif /* NLOHMANN_JSON_SCHEMA_HPP__ */\n"
  },
  {
    "path": "src/smtp-address-validator.cpp",
    "content": "/*\n\nSnarfed from <https://github.com/gene-hightower/smtp-address-validator>\n\n<http://opensource.org/licenses/MIT>:\n\nCopyright (c) 2021 Gene Hightower\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\nof the Software, and to permit persons to whom the Software is furnished to do\nso, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n*/\n\n#include \"smtp-address-validator.hpp\"\n\nstatic const signed char _address_actions[] = {\n    0, 1, 0, 1, 1, 0};\n\nstatic const short _address_key_offsets[] = {\n    0, 0, 24, 26, 50, 52, 54, 56,\n    58, 60, 62, 86, 103, 105, 107, 109,\n    111, 113, 115, 117, 134, 150, 161, 168,\n    176, 180, 181, 190, 195, 196, 201, 202,\n    207, 210, 213, 219, 222, 225, 228, 234,\n    237, 240, 243, 249, 252, 261, 270, 282,\n    293, 302, 311, 320, 328, 345, 353, 360,\n    367, 368, 375, 382, 389, 396, 397, 404,\n    411, 418, 425, 426, 433, 440, 447, 454,\n    455, 462, 469, 476, 483, 484, 491, 498,\n    505, 512, 513, 523, 531, 538, 545, 546,\n    552, 559, 566, 573, 581, 589, 597, 608,\n    618, 626, 634, 641, 649, 657, 665, 667,\n    673, 681, 689, 697, 699, 705, 713, 721,\n    729, 731, 737, 745, 753, 761, 763, 769,\n    777, 785, 793, 795, 802, 812, 821, 829,\n    837, 839, 848, 857, 865, 873, 875, 884,\n    893, 901, 909, 911, 920, 929, 937, 945,\n    947, 956, 965, 974, 983, 992, 1004, 1015,\n    1024, 1033, 1042, 1051, 1060, 1072, 1083, 1092,\n    1101, 1109, 1118, 1127, 1136, 1148, 1159, 1168,\n    1177, 1185, 1194, 1203, 1212, 1224, 1235, 1244,\n    1253, 1261, 1270, 1279, 1288, 1300, 1311, 1320,\n    1329, 1337, 1339, 1353, 1355, 1357, 1359, 1361,\n    1363, 1365, 1367, 1368, 1370, 1388, 0};\n\nstatic const signed char _address_trans_keys[] = {\n    -32, -19, -16, -12, 34, 45, 61, 63,\n    -62, -33, -31, -17, -15, -13, 33, 39,\n    42, 43, 47, 57, 65, 90, 94, 126,\n    -128, -65, -32, -19, -16, -12, 33, 46,\n    61, 64, -62, -33, -31, -17, -15, -13,\n    35, 39, 42, 43, 45, 57, 63, 90,\n    94, 126, -96, -65, -128, -65, -128, -97,\n    -112, -65, -128, -65, -128, -113, -32, -19,\n    -16, -12, 33, 45, 61, 63, -62, -33,\n    -31, -17, -15, -13, 35, 39, 42, 43,\n    47, 57, 65, 90, 94, 126, -32, -19,\n    -16, -12, 91, -62, -33, -31, -17, -15,\n    -13, 48, 57, 65, 90, 97, 122, -128,\n    -65, -96, -65, -128, -65, -128, -97, -112,\n    -65, -128, -65, -128, -113, -32, -19, -16,\n    -12, 45, -62, -33, -31, -17, -15, -13,\n    48, 57, 65, 90, 97, 122, -32, -19,\n    -16, -12, -62, -33, -31, -17, -15, -13,\n    48, 57, 65, 90, 97, 122, 45, 48,\n    49, 50, 73, 51, 57, 65, 90, 97,\n    122, 45, 48, 57, 65, 90, 97, 122,\n    45, 58, 48, 57, 65, 90, 97, 122,\n    33, 90, 94, 126, 93, 45, 46, 58,\n    48, 57, 65, 90, 97, 122, 48, 49,\n    50, 51, 57, 46, 48, 49, 50, 51,\n    57, 46, 48, 49, 50, 51, 57, 93,\n    48, 57, 93, 48, 57, 53, 93, 48,\n    52, 54, 57, 93, 48, 53, 46, 48,\n    57, 46, 48, 57, 46, 53, 48, 52,\n    54, 57, 46, 48, 53, 46, 48, 57,\n    46, 48, 57, 46, 53, 48, 52, 54,\n    57, 46, 48, 53, 45, 46, 58, 48,\n    57, 65, 90, 97, 122, 45, 46, 58,\n    48, 57, 65, 90, 97, 122, 45, 46,\n    53, 58, 48, 52, 54, 57, 65, 90,\n    97, 122, 45, 46, 58, 48, 53, 54,\n    57, 65, 90, 97, 122, 45, 58, 80,\n    48, 57, 65, 90, 97, 122, 45, 58,\n    118, 48, 57, 65, 90, 97, 122, 45,\n    54, 58, 48, 57, 65, 90, 97, 122,\n    45, 58, 48, 57, 65, 90, 97, 122,\n    58, 33, 47, 48, 57, 59, 64, 65,\n    70, 71, 90, 94, 96, 97, 102, 103,\n    126, 58, 93, 48, 57, 65, 70, 97,\n    102, 58, 48, 57, 65, 70, 97, 102,\n    58, 48, 57, 65, 70, 97, 102, 58,\n    58, 48, 57, 65, 70, 97, 102, 58,\n    48, 57, 65, 70, 97, 102, 58, 48,\n    57, 65, 70, 97, 102, 58, 48, 57,\n    65, 70, 97, 102, 58, 58, 48, 57,\n    65, 70, 97, 102, 58, 48, 57, 65,\n    70, 97, 102, 58, 48, 57, 65, 70,\n    97, 102, 58, 48, 57, 65, 70, 97,\n    102, 58, 58, 48, 57, 65, 70, 97,\n    102, 58, 48, 57, 65, 70, 97, 102,\n    58, 48, 57, 65, 70, 97, 102, 58,\n    48, 57, 65, 70, 97, 102, 58, 58,\n    48, 57, 65, 70, 97, 102, 58, 48,\n    57, 65, 70, 97, 102, 58, 48, 57,\n    65, 70, 97, 102, 58, 48, 57, 65,\n    70, 97, 102, 58, 58, 48, 57, 65,\n    70, 97, 102, 58, 48, 57, 65, 70,\n    97, 102, 58, 48, 57, 65, 70, 97,\n    102, 58, 48, 57, 65, 70, 97, 102,\n    58, 48, 49, 50, 58, 51, 57, 65,\n    70, 97, 102, 46, 58, 48, 57, 65,\n    70, 97, 102, 58, 48, 57, 65, 70,\n    97, 102, 58, 48, 57, 65, 70, 97,\n    102, 58, 48, 57, 65, 70, 97, 102,\n    93, 48, 57, 65, 70, 97, 102, 93,\n    48, 57, 65, 70, 97, 102, 93, 48,\n    57, 65, 70, 97, 102, 46, 58, 48,\n    57, 65, 70, 97, 102, 46, 58, 48,\n    57, 65, 70, 97, 102, 46, 58, 48,\n    57, 65, 70, 97, 102, 46, 53, 58,\n    48, 52, 54, 57, 65, 70, 97, 102,\n    46, 58, 48, 53, 54, 57, 65, 70,\n    97, 102, 46, 58, 48, 57, 65, 70,\n    97, 102, 46, 58, 48, 57, 65, 70,\n    97, 102, 93, 48, 57, 65, 70, 97,\n    102, 58, 93, 48, 57, 65, 70, 97,\n    102, 58, 93, 48, 57, 65, 70, 97,\n    102, 58, 93, 48, 57, 65, 70, 97,\n    102, 58, 93, 48, 57, 65, 70, 97,\n    102, 58, 93, 48, 57, 65, 70, 97,\n    102, 58, 93, 48, 57, 65, 70, 97,\n    102, 58, 93, 48, 57, 65, 70, 97,\n    102, 58, 93, 48, 57, 65, 70, 97,\n    102, 58, 93, 48, 57, 65, 70, 97,\n    102, 58, 93, 48, 57, 65, 70, 97,\n    102, 58, 93, 48, 57, 65, 70, 97,\n    102, 58, 93, 48, 57, 65, 70, 97,\n    102, 58, 93, 48, 57, 65, 70, 97,\n    102, 58, 93, 48, 57, 65, 70, 97,\n    102, 58, 93, 48, 57, 65, 70, 97,\n    102, 58, 93, 48, 57, 65, 70, 97,\n    102, 58, 93, 48, 57, 65, 70, 97,\n    102, 58, 93, 48, 57, 65, 70, 97,\n    102, 58, 93, 48, 57, 65, 70, 97,\n    102, 58, 93, 58, 48, 57, 65, 70,\n    97, 102, 48, 49, 50, 93, 51, 57,\n    65, 70, 97, 102, 46, 58, 93, 48,\n    57, 65, 70, 97, 102, 58, 93, 48,\n    57, 65, 70, 97, 102, 58, 93, 48,\n    57, 65, 70, 97, 102, 58, 93, 48,\n    49, 50, 51, 57, 65, 70, 97, 102,\n    46, 58, 93, 48, 57, 65, 70, 97,\n    102, 58, 93, 48, 57, 65, 70, 97,\n    102, 58, 93, 48, 57, 65, 70, 97,\n    102, 58, 93, 48, 49, 50, 51, 57,\n    65, 70, 97, 102, 46, 58, 93, 48,\n    57, 65, 70, 97, 102, 58, 93, 48,\n    57, 65, 70, 97, 102, 58, 93, 48,\n    57, 65, 70, 97, 102, 58, 93, 48,\n    49, 50, 51, 57, 65, 70, 97, 102,\n    46, 58, 93, 48, 57, 65, 70, 97,\n    102, 58, 93, 48, 57, 65, 70, 97,\n    102, 58, 93, 48, 57, 65, 70, 97,\n    102, 58, 93, 48, 49, 50, 51, 57,\n    65, 70, 97, 102, 46, 58, 93, 48,\n    57, 65, 70, 97, 102, 46, 58, 93,\n    48, 57, 65, 70, 97, 102, 46, 58,\n    93, 48, 57, 65, 70, 97, 102, 46,\n    58, 93, 48, 57, 65, 70, 97, 102,\n    46, 53, 58, 93, 48, 52, 54, 57,\n    65, 70, 97, 102, 46, 58, 93, 48,\n    53, 54, 57, 65, 70, 97, 102, 46,\n    58, 93, 48, 57, 65, 70, 97, 102,\n    46, 58, 93, 48, 57, 65, 70, 97,\n    102, 46, 58, 93, 48, 57, 65, 70,\n    97, 102, 46, 58, 93, 48, 57, 65,\n    70, 97, 102, 46, 58, 93, 48, 57,\n    65, 70, 97, 102, 46, 53, 58, 93,\n    48, 52, 54, 57, 65, 70, 97, 102,\n    46, 58, 93, 48, 53, 54, 57, 65,\n    70, 97, 102, 46, 58, 93, 48, 57,\n    65, 70, 97, 102, 46, 58, 93, 48,\n    57, 65, 70, 97, 102, 58, 93, 48,\n    57, 65, 70, 97, 102, 46, 58, 93,\n    48, 57, 65, 70, 97, 102, 46, 58,\n    93, 48, 57, 65, 70, 97, 102, 46,\n    58, 93, 48, 57, 65, 70, 97, 102,\n    46, 53, 58, 93, 48, 52, 54, 57,\n    65, 70, 97, 102, 46, 58, 93, 48,\n    53, 54, 57, 65, 70, 97, 102, 46,\n    58, 93, 48, 57, 65, 70, 97, 102,\n    46, 58, 93, 48, 57, 65, 70, 97,\n    102, 58, 93, 48, 57, 65, 70, 97,\n    102, 46, 58, 93, 48, 57, 65, 70,\n    97, 102, 46, 58, 93, 48, 57, 65,\n    70, 97, 102, 46, 58, 93, 48, 57,\n    65, 70, 97, 102, 46, 53, 58, 93,\n    48, 52, 54, 57, 65, 70, 97, 102,\n    46, 58, 93, 48, 53, 54, 57, 65,\n    70, 97, 102, 46, 58, 93, 48, 57,\n    65, 70, 97, 102, 46, 58, 93, 48,\n    57, 65, 70, 97, 102, 58, 93, 48,\n    57, 65, 70, 97, 102, 46, 58, 93,\n    48, 57, 65, 70, 97, 102, 46, 58,\n    93, 48, 57, 65, 70, 97, 102, 46,\n    58, 93, 48, 57, 65, 70, 97, 102,\n    46, 53, 58, 93, 48, 52, 54, 57,\n    65, 70, 97, 102, 46, 58, 93, 48,\n    53, 54, 57, 65, 70, 97, 102, 46,\n    58, 93, 48, 57, 65, 70, 97, 102,\n    46, 58, 93, 48, 57, 65, 70, 97,\n    102, 58, 93, 48, 57, 65, 70, 97,\n    102, 58, 93, -32, -19, -16, -12, 34,\n    92, -62, -33, -31, -17, -15, -13, 32,\n    126, -128, -65, -96, -65, -128, -65, -128,\n    -97, -112, -65, -128, -65, -128, -113, 64,\n    32, 126, -32, -19, -16, -12, 45, 46,\n    -62, -33, -31, -17, -15, -13, 48, 57,\n    65, 90, 97, 122, 0};\n\nstatic const signed char _address_single_lengths[] = {\n    0, 8, 0, 8, 0, 0, 0, 0,\n    0, 0, 8, 5, 0, 0, 0, 0,\n    0, 0, 0, 5, 4, 5, 1, 2,\n    0, 1, 3, 3, 1, 3, 1, 3,\n    1, 1, 2, 1, 1, 1, 2, 1,\n    1, 1, 2, 1, 3, 3, 4, 3,\n    3, 3, 3, 2, 1, 2, 1, 1,\n    1, 1, 1, 1, 1, 1, 1, 1,\n    1, 1, 1, 1, 1, 1, 1, 1,\n    1, 1, 1, 1, 1, 1, 1, 1,\n    1, 1, 4, 2, 1, 1, 1, 0,\n    1, 1, 1, 2, 2, 2, 3, 2,\n    2, 2, 1, 2, 2, 2, 2, 0,\n    2, 2, 2, 2, 0, 2, 2, 2,\n    2, 0, 2, 2, 2, 2, 0, 2,\n    2, 2, 2, 1, 4, 3, 2, 2,\n    2, 3, 3, 2, 2, 2, 3, 3,\n    2, 2, 2, 3, 3, 2, 2, 2,\n    3, 3, 3, 3, 3, 4, 3, 3,\n    3, 3, 3, 3, 4, 3, 3, 3,\n    2, 3, 3, 3, 4, 3, 3, 3,\n    2, 3, 3, 3, 4, 3, 3, 3,\n    2, 3, 3, 3, 4, 3, 3, 3,\n    2, 2, 6, 0, 0, 0, 0, 0,\n    0, 0, 1, 0, 6, 0, 0};\n\nstatic const signed char _address_range_lengths[] = {\n    0, 8, 1, 8, 1, 1, 1, 1,\n    1, 1, 8, 6, 1, 1, 1, 1,\n    1, 1, 1, 6, 6, 3, 3, 3,\n    2, 0, 3, 1, 0, 1, 0, 1,\n    1, 1, 2, 1, 1, 1, 2, 1,\n    1, 1, 2, 1, 3, 3, 4, 4,\n    3, 3, 3, 3, 8, 3, 3, 3,\n    0, 3, 3, 3, 3, 0, 3, 3,\n    3, 3, 0, 3, 3, 3, 3, 0,\n    3, 3, 3, 3, 0, 3, 3, 3,\n    3, 0, 3, 3, 3, 3, 0, 3,\n    3, 3, 3, 3, 3, 3, 4, 4,\n    3, 3, 3, 3, 3, 3, 0, 3,\n    3, 3, 3, 0, 3, 3, 3, 3,\n    0, 3, 3, 3, 3, 0, 3, 3,\n    3, 3, 0, 3, 3, 3, 3, 3,\n    0, 3, 3, 3, 3, 0, 3, 3,\n    3, 3, 0, 3, 3, 3, 3, 0,\n    3, 3, 3, 3, 3, 4, 4, 3,\n    3, 3, 3, 3, 4, 4, 3, 3,\n    3, 3, 3, 3, 4, 4, 3, 3,\n    3, 3, 3, 3, 4, 4, 3, 3,\n    3, 3, 3, 3, 4, 4, 3, 3,\n    3, 0, 4, 1, 1, 1, 1, 1,\n    1, 1, 0, 1, 6, 0, 0};\n\nstatic const short _address_index_offsets[] = {\n    0, 0, 17, 19, 36, 38, 40, 42,\n    44, 46, 48, 65, 77, 79, 81, 83,\n    85, 87, 89, 91, 103, 114, 123, 128,\n    134, 137, 139, 146, 151, 153, 158, 160,\n    165, 168, 171, 176, 179, 182, 185, 190,\n    193, 196, 199, 204, 207, 214, 221, 230,\n    238, 245, 252, 259, 265, 275, 281, 286,\n    291, 293, 298, 303, 308, 313, 315, 320,\n    325, 330, 335, 337, 342, 347, 352, 357,\n    359, 364, 369, 374, 379, 381, 386, 391,\n    396, 401, 403, 411, 417, 422, 427, 429,\n    433, 438, 443, 448, 454, 460, 466, 474,\n    481, 487, 493, 498, 504, 510, 516, 519,\n    523, 529, 535, 541, 544, 548, 554, 560,\n    566, 569, 573, 579, 585, 591, 594, 598,\n    604, 610, 616, 619, 624, 632, 639, 645,\n    651, 654, 661, 668, 674, 680, 683, 690,\n    697, 703, 709, 712, 719, 726, 732, 738,\n    741, 748, 755, 762, 769, 776, 785, 793,\n    800, 807, 814, 821, 828, 837, 845, 852,\n    859, 865, 872, 879, 886, 895, 903, 910,\n    917, 923, 930, 937, 944, 953, 961, 968,\n    975, 981, 988, 995, 1002, 1011, 1019, 1026,\n    1033, 1039, 1042, 1053, 1055, 1057, 1059, 1061,\n    1063, 1065, 1067, 1069, 1071, 1084, 0};\n\nstatic const short _address_cond_targs[] = {\n    4, 6, 7, 9, 186, 3, 3, 3,\n    2, 5, 8, 3, 3, 3, 3, 3,\n    0, 3, 0, 4, 6, 7, 9, 3,\n    10, 3, 11, 2, 5, 8, 3, 3,\n    3, 3, 3, 0, 2, 0, 2, 0,\n    2, 0, 5, 0, 5, 0, 5, 0,\n    4, 6, 7, 9, 3, 3, 3, 3,\n    2, 5, 8, 3, 3, 3, 3, 3,\n    0, 13, 15, 16, 18, 21, 12, 14,\n    17, 196, 196, 196, 0, 196, 0, 12,\n    0, 12, 0, 12, 0, 14, 0, 14,\n    0, 14, 0, 13, 15, 16, 18, 19,\n    12, 14, 17, 196, 196, 196, 0, 13,\n    15, 16, 18, 12, 14, 17, 196, 196,\n    196, 0, 22, 26, 44, 46, 48, 45,\n    23, 23, 0, 22, 23, 23, 23, 0,\n    22, 24, 23, 23, 23, 0, 25, 25,\n    0, 197, 0, 22, 27, 24, 23, 23,\n    23, 0, 28, 40, 42, 41, 0, 29,\n    0, 30, 36, 38, 37, 0, 31, 0,\n    25, 32, 34, 33, 0, 197, 33, 0,\n    197, 25, 0, 35, 197, 33, 25, 0,\n    197, 25, 0, 31, 37, 0, 31, 30,\n    0, 31, 39, 37, 30, 0, 31, 30,\n    0, 29, 41, 0, 29, 28, 0, 29,\n    43, 41, 28, 0, 29, 28, 0, 22,\n    27, 24, 45, 23, 23, 0, 22, 27,\n    24, 26, 23, 23, 0, 22, 27, 47,\n    24, 45, 26, 23, 23, 0, 22, 27,\n    24, 26, 23, 23, 23, 0, 22, 24,\n    49, 23, 23, 23, 0, 22, 24, 50,\n    23, 23, 23, 0, 22, 51, 24, 23,\n    23, 23, 0, 22, 52, 23, 23, 23,\n    0, 185, 25, 53, 25, 53, 25, 25,\n    53, 25, 0, 57, 197, 54, 54, 54,\n    0, 57, 55, 55, 55, 0, 57, 56,\n    56, 56, 0, 57, 0, 124, 58, 58,\n    58, 0, 62, 59, 59, 59, 0, 62,\n    60, 60, 60, 0, 62, 61, 61, 61,\n    0, 62, 0, 124, 63, 63, 63, 0,\n    67, 64, 64, 64, 0, 67, 65, 65,\n    65, 0, 67, 66, 66, 66, 0, 67,\n    0, 124, 68, 68, 68, 0, 72, 69,\n    69, 69, 0, 72, 70, 70, 70, 0,\n    72, 71, 71, 71, 0, 72, 0, 124,\n    73, 73, 73, 0, 77, 74, 74, 74,\n    0, 77, 75, 75, 75, 0, 77, 76,\n    76, 76, 0, 77, 0, 98, 78, 78,\n    78, 0, 82, 79, 79, 79, 0, 82,\n    80, 80, 80, 0, 82, 81, 81, 81,\n    0, 82, 0, 83, 91, 94, 98, 97,\n    123, 123, 0, 27, 87, 84, 84, 84,\n    0, 87, 85, 85, 85, 0, 87, 86,\n    86, 86, 0, 87, 0, 88, 88, 88,\n    0, 197, 89, 89, 89, 0, 197, 90,\n    90, 90, 0, 197, 25, 25, 25, 0,\n    27, 87, 92, 84, 84, 0, 27, 87,\n    93, 85, 85, 0, 27, 87, 86, 86,\n    86, 0, 27, 95, 87, 92, 96, 84,\n    84, 0, 27, 87, 93, 85, 85, 85,\n    0, 27, 87, 85, 85, 85, 0, 27,\n    87, 96, 84, 84, 0, 197, 99, 99,\n    99, 0, 103, 197, 100, 100, 100, 0,\n    103, 197, 101, 101, 101, 0, 103, 197,\n    102, 102, 102, 0, 103, 197, 0, 104,\n    104, 104, 0, 108, 197, 105, 105, 105,\n    0, 108, 197, 106, 106, 106, 0, 108,\n    197, 107, 107, 107, 0, 108, 197, 0,\n    109, 109, 109, 0, 113, 197, 110, 110,\n    110, 0, 113, 197, 111, 111, 111, 0,\n    113, 197, 112, 112, 112, 0, 113, 197,\n    0, 114, 114, 114, 0, 118, 197, 115,\n    115, 115, 0, 118, 197, 116, 116, 116,\n    0, 118, 197, 117, 117, 117, 0, 118,\n    197, 0, 119, 119, 119, 0, 87, 197,\n    120, 120, 120, 0, 87, 197, 121, 121,\n    121, 0, 87, 197, 122, 122, 122, 0,\n    87, 197, 0, 87, 84, 84, 84, 0,\n    125, 177, 180, 197, 183, 184, 184, 0,\n    27, 129, 197, 126, 126, 126, 0, 129,\n    197, 127, 127, 127, 0, 129, 197, 128,\n    128, 128, 0, 129, 197, 0, 130, 169,\n    172, 175, 176, 176, 0, 27, 134, 197,\n    131, 131, 131, 0, 134, 197, 132, 132,\n    132, 0, 134, 197, 133, 133, 133, 0,\n    134, 197, 0, 135, 161, 164, 167, 168,\n    168, 0, 27, 139, 197, 136, 136, 136,\n    0, 139, 197, 137, 137, 137, 0, 139,\n    197, 138, 138, 138, 0, 139, 197, 0,\n    140, 153, 156, 159, 160, 160, 0, 27,\n    144, 197, 141, 141, 141, 0, 144, 197,\n    142, 142, 142, 0, 144, 197, 143, 143,\n    143, 0, 144, 197, 0, 145, 146, 149,\n    152, 119, 119, 0, 27, 87, 197, 120,\n    120, 120, 0, 27, 87, 197, 147, 120,\n    120, 0, 27, 87, 197, 148, 121, 121,\n    0, 27, 87, 197, 122, 122, 122, 0,\n    27, 150, 87, 197, 147, 151, 120, 120,\n    0, 27, 87, 197, 148, 121, 121, 121,\n    0, 27, 87, 197, 121, 121, 121, 0,\n    27, 87, 197, 151, 120, 120, 0, 27,\n    144, 197, 154, 141, 141, 0, 27, 144,\n    197, 155, 142, 142, 0, 27, 144, 197,\n    143, 143, 143, 0, 27, 157, 144, 197,\n    154, 158, 141, 141, 0, 27, 144, 197,\n    155, 142, 142, 142, 0, 27, 144, 197,\n    142, 142, 142, 0, 27, 144, 197, 158,\n    141, 141, 0, 144, 197, 141, 141, 141,\n    0, 27, 139, 197, 162, 136, 136, 0,\n    27, 139, 197, 163, 137, 137, 0, 27,\n    139, 197, 138, 138, 138, 0, 27, 165,\n    139, 197, 162, 166, 136, 136, 0, 27,\n    139, 197, 163, 137, 137, 137, 0, 27,\n    139, 197, 137, 137, 137, 0, 27, 139,\n    197, 166, 136, 136, 0, 139, 197, 136,\n    136, 136, 0, 27, 134, 197, 170, 131,\n    131, 0, 27, 134, 197, 171, 132, 132,\n    0, 27, 134, 197, 133, 133, 133, 0,\n    27, 173, 134, 197, 170, 174, 131, 131,\n    0, 27, 134, 197, 171, 132, 132, 132,\n    0, 27, 134, 197, 132, 132, 132, 0,\n    27, 134, 197, 174, 131, 131, 0, 134,\n    197, 131, 131, 131, 0, 27, 129, 197,\n    178, 126, 126, 0, 27, 129, 197, 179,\n    127, 127, 0, 27, 129, 197, 128, 128,\n    128, 0, 27, 181, 129, 197, 178, 182,\n    126, 126, 0, 27, 129, 197, 179, 127,\n    127, 127, 0, 27, 129, 197, 127, 127,\n    127, 0, 27, 129, 197, 182, 126, 126,\n    0, 129, 197, 126, 126, 126, 0, 124,\n    197, 0, 188, 190, 191, 193, 194, 195,\n    187, 189, 192, 186, 0, 186, 0, 187,\n    0, 187, 0, 187, 0, 189, 0, 189,\n    0, 189, 0, 11, 0, 186, 0, 13,\n    15, 16, 18, 19, 20, 12, 14, 17,\n    196, 196, 196, 0, 0, 0, 1, 2,\n    3, 4, 5, 6, 7, 8, 9, 10,\n    11, 12, 13, 14, 15, 16, 17, 18,\n    19, 20, 21, 22, 23, 24, 25, 26,\n    27, 28, 29, 30, 31, 32, 33, 34,\n    35, 36, 37, 38, 39, 40, 41, 42,\n    43, 44, 45, 46, 47, 48, 49, 50,\n    51, 52, 53, 54, 55, 56, 57, 58,\n    59, 60, 61, 62, 63, 64, 65, 66,\n    67, 68, 69, 70, 71, 72, 73, 74,\n    75, 76, 77, 78, 79, 80, 81, 82,\n    83, 84, 85, 86, 87, 88, 89, 90,\n    91, 92, 93, 94, 95, 96, 97, 98,\n    99, 100, 101, 102, 103, 104, 105, 106,\n    107, 108, 109, 110, 111, 112, 113, 114,\n    115, 116, 117, 118, 119, 120, 121, 122,\n    123, 124, 125, 126, 127, 128, 129, 130,\n    131, 132, 133, 134, 135, 136, 137, 138,\n    139, 140, 141, 142, 143, 144, 145, 146,\n    147, 148, 149, 150, 151, 152, 153, 154,\n    155, 156, 157, 158, 159, 160, 161, 162,\n    163, 164, 165, 166, 167, 168, 169, 170,\n    171, 172, 173, 174, 175, 176, 177, 178,\n    179, 180, 181, 182, 183, 184, 185, 186,\n    187, 188, 189, 190, 191, 192, 193, 194,\n    195, 196, 197, 0};\n\nstatic const signed char _address_cond_actions[] = {\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    3, 0, 3, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 3, 0, 3, 0, 3,\n    0, 3, 0, 3, 0, 3, 0, 3,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    3, 0, 0, 0, 0, 0, 0, 0,\n    0, 1, 1, 1, 3, 1, 3, 0,\n    3, 0, 3, 0, 3, 0, 3, 0,\n    3, 0, 3, 0, 0, 0, 0, 0,\n    0, 0, 0, 1, 1, 1, 3, 0,\n    0, 0, 0, 0, 0, 0, 1, 1,\n    1, 3, 0, 0, 0, 0, 0, 0,\n    0, 0, 3, 0, 0, 0, 0, 3,\n    0, 0, 0, 0, 0, 3, 0, 0,\n    3, 1, 3, 0, 0, 0, 0, 0,\n    0, 3, 0, 0, 0, 0, 3, 0,\n    3, 0, 0, 0, 0, 3, 0, 3,\n    0, 0, 0, 0, 3, 1, 0, 3,\n    1, 0, 3, 0, 1, 0, 0, 3,\n    1, 0, 3, 0, 0, 3, 0, 0,\n    3, 0, 0, 0, 0, 3, 0, 0,\n    3, 0, 0, 3, 0, 0, 3, 0,\n    0, 0, 0, 3, 0, 0, 3, 0,\n    0, 0, 0, 0, 0, 3, 0, 0,\n    0, 0, 0, 0, 3, 0, 0, 0,\n    0, 0, 0, 0, 0, 3, 0, 0,\n    0, 0, 0, 0, 0, 3, 0, 0,\n    0, 0, 0, 0, 3, 0, 0, 0,\n    0, 0, 0, 3, 0, 0, 0, 0,\n    0, 0, 3, 0, 0, 0, 0, 0,\n    3, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 3, 0, 1, 0, 0, 0,\n    3, 0, 0, 0, 0, 3, 0, 0,\n    0, 0, 3, 0, 3, 0, 0, 0,\n    0, 3, 0, 0, 0, 0, 3, 0,\n    0, 0, 0, 3, 0, 0, 0, 0,\n    3, 0, 3, 0, 0, 0, 0, 3,\n    0, 0, 0, 0, 3, 0, 0, 0,\n    0, 3, 0, 0, 0, 0, 3, 0,\n    3, 0, 0, 0, 0, 3, 0, 0,\n    0, 0, 3, 0, 0, 0, 0, 3,\n    0, 0, 0, 0, 3, 0, 3, 0,\n    0, 0, 0, 3, 0, 0, 0, 0,\n    3, 0, 0, 0, 0, 3, 0, 0,\n    0, 0, 3, 0, 3, 0, 0, 0,\n    0, 3, 0, 0, 0, 0, 3, 0,\n    0, 0, 0, 3, 0, 0, 0, 0,\n    3, 0, 3, 0, 0, 0, 0, 0,\n    0, 0, 3, 0, 0, 0, 0, 0,\n    3, 0, 0, 0, 0, 3, 0, 0,\n    0, 0, 3, 0, 3, 0, 0, 0,\n    3, 1, 0, 0, 0, 3, 1, 0,\n    0, 0, 3, 1, 0, 0, 0, 3,\n    0, 0, 0, 0, 0, 3, 0, 0,\n    0, 0, 0, 3, 0, 0, 0, 0,\n    0, 3, 0, 0, 0, 0, 0, 0,\n    0, 3, 0, 0, 0, 0, 0, 0,\n    3, 0, 0, 0, 0, 0, 3, 0,\n    0, 0, 0, 0, 3, 1, 0, 0,\n    0, 3, 0, 1, 0, 0, 0, 3,\n    0, 1, 0, 0, 0, 3, 0, 1,\n    0, 0, 0, 3, 0, 1, 3, 0,\n    0, 0, 3, 0, 1, 0, 0, 0,\n    3, 0, 1, 0, 0, 0, 3, 0,\n    1, 0, 0, 0, 3, 0, 1, 3,\n    0, 0, 0, 3, 0, 1, 0, 0,\n    0, 3, 0, 1, 0, 0, 0, 3,\n    0, 1, 0, 0, 0, 3, 0, 1,\n    3, 0, 0, 0, 3, 0, 1, 0,\n    0, 0, 3, 0, 1, 0, 0, 0,\n    3, 0, 1, 0, 0, 0, 3, 0,\n    1, 3, 0, 0, 0, 3, 0, 1,\n    0, 0, 0, 3, 0, 1, 0, 0,\n    0, 3, 0, 1, 0, 0, 0, 3,\n    0, 1, 3, 0, 0, 0, 0, 3,\n    0, 0, 0, 1, 0, 0, 0, 3,\n    0, 0, 1, 0, 0, 0, 3, 0,\n    1, 0, 0, 0, 3, 0, 1, 0,\n    0, 0, 3, 0, 1, 3, 0, 0,\n    0, 0, 0, 0, 3, 0, 0, 1,\n    0, 0, 0, 3, 0, 1, 0, 0,\n    0, 3, 0, 1, 0, 0, 0, 3,\n    0, 1, 3, 0, 0, 0, 0, 0,\n    0, 3, 0, 0, 1, 0, 0, 0,\n    3, 0, 1, 0, 0, 0, 3, 0,\n    1, 0, 0, 0, 3, 0, 1, 3,\n    0, 0, 0, 0, 0, 0, 3, 0,\n    0, 1, 0, 0, 0, 3, 0, 1,\n    0, 0, 0, 3, 0, 1, 0, 0,\n    0, 3, 0, 1, 3, 0, 0, 0,\n    0, 0, 0, 3, 0, 0, 1, 0,\n    0, 0, 3, 0, 0, 1, 0, 0,\n    0, 3, 0, 0, 1, 0, 0, 0,\n    3, 0, 0, 1, 0, 0, 0, 3,\n    0, 0, 0, 1, 0, 0, 0, 0,\n    3, 0, 0, 1, 0, 0, 0, 0,\n    3, 0, 0, 1, 0, 0, 0, 3,\n    0, 0, 1, 0, 0, 0, 3, 0,\n    0, 1, 0, 0, 0, 3, 0, 0,\n    1, 0, 0, 0, 3, 0, 0, 1,\n    0, 0, 0, 3, 0, 0, 0, 1,\n    0, 0, 0, 0, 3, 0, 0, 1,\n    0, 0, 0, 0, 3, 0, 0, 1,\n    0, 0, 0, 3, 0, 0, 1, 0,\n    0, 0, 3, 0, 1, 0, 0, 0,\n    3, 0, 0, 1, 0, 0, 0, 3,\n    0, 0, 1, 0, 0, 0, 3, 0,\n    0, 1, 0, 0, 0, 3, 0, 0,\n    0, 1, 0, 0, 0, 0, 3, 0,\n    0, 1, 0, 0, 0, 0, 3, 0,\n    0, 1, 0, 0, 0, 3, 0, 0,\n    1, 0, 0, 0, 3, 0, 1, 0,\n    0, 0, 3, 0, 0, 1, 0, 0,\n    0, 3, 0, 0, 1, 0, 0, 0,\n    3, 0, 0, 1, 0, 0, 0, 3,\n    0, 0, 0, 1, 0, 0, 0, 0,\n    3, 0, 0, 1, 0, 0, 0, 0,\n    3, 0, 0, 1, 0, 0, 0, 3,\n    0, 0, 1, 0, 0, 0, 3, 0,\n    1, 0, 0, 0, 3, 0, 0, 1,\n    0, 0, 0, 3, 0, 0, 1, 0,\n    0, 0, 3, 0, 0, 1, 0, 0,\n    0, 3, 0, 0, 0, 1, 0, 0,\n    0, 0, 3, 0, 0, 1, 0, 0,\n    0, 0, 3, 0, 0, 1, 0, 0,\n    0, 3, 0, 0, 1, 0, 0, 0,\n    3, 0, 1, 0, 0, 0, 3, 0,\n    1, 3, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 3, 0, 3, 0,\n    3, 0, 3, 0, 3, 0, 3, 0,\n    3, 0, 3, 0, 3, 0, 3, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    1, 1, 1, 3, 3, 0, 3, 3,\n    3, 3, 3, 3, 3, 3, 3, 3,\n    3, 3, 3, 3, 3, 3, 3, 3,\n    3, 3, 3, 3, 3, 3, 3, 3,\n    3, 3, 3, 3, 3, 3, 3, 3,\n    3, 3, 3, 3, 3, 3, 3, 3,\n    3, 3, 3, 3, 3, 3, 3, 3,\n    3, 3, 3, 3, 3, 3, 3, 3,\n    3, 3, 3, 3, 3, 3, 3, 3,\n    3, 3, 3, 3, 3, 3, 3, 3,\n    3, 3, 3, 3, 3, 3, 3, 3,\n    3, 3, 3, 3, 3, 3, 3, 3,\n    3, 3, 3, 3, 3, 3, 3, 3,\n    3, 3, 3, 3, 3, 3, 3, 3,\n    3, 3, 3, 3, 3, 3, 3, 3,\n    3, 3, 3, 3, 3, 3, 3, 3,\n    3, 3, 3, 3, 3, 3, 3, 3,\n    3, 3, 3, 3, 3, 3, 3, 3,\n    3, 3, 3, 3, 3, 3, 3, 3,\n    3, 3, 3, 3, 3, 3, 3, 3,\n    3, 3, 3, 3, 3, 3, 3, 3,\n    3, 3, 3, 3, 3, 3, 3, 3,\n    3, 3, 3, 3, 3, 3, 3, 3,\n    3, 3, 3, 3, 3, 3, 3, 3,\n    3, 3, 3, 3, 3, 3, 3, 3,\n    3, 0, 0, 0};\n\nstatic const short _address_eof_trans[] = {\n    1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093,\n    1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101,\n    1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109,\n    1110, 1111, 1112, 1113, 1114, 1115, 1116, 1117,\n    1118, 1119, 1120, 1121, 1122, 1123, 1124, 1125,\n    1126, 1127, 1128, 1129, 1130, 1131, 1132, 1133,\n    1134, 1135, 1136, 1137, 1138, 1139, 1140, 1141,\n    1142, 1143, 1144, 1145, 1146, 1147, 1148, 1149,\n    1150, 1151, 1152, 1153, 1154, 1155, 1156, 1157,\n    1158, 1159, 1160, 1161, 1162, 1163, 1164, 1165,\n    1166, 1167, 1168, 1169, 1170, 1171, 1172, 1173,\n    1174, 1175, 1176, 1177, 1178, 1179, 1180, 1181,\n    1182, 1183, 1184, 1185, 1186, 1187, 1188, 1189,\n    1190, 1191, 1192, 1193, 1194, 1195, 1196, 1197,\n    1198, 1199, 1200, 1201, 1202, 1203, 1204, 1205,\n    1206, 1207, 1208, 1209, 1210, 1211, 1212, 1213,\n    1214, 1215, 1216, 1217, 1218, 1219, 1220, 1221,\n    1222, 1223, 1224, 1225, 1226, 1227, 1228, 1229,\n    1230, 1231, 1232, 1233, 1234, 1235, 1236, 1237,\n    1238, 1239, 1240, 1241, 1242, 1243, 1244, 1245,\n    1246, 1247, 1248, 1249, 1250, 1251, 1252, 1253,\n    1254, 1255, 1256, 1257, 1258, 1259, 1260, 1261,\n    1262, 1263, 1264, 1265, 1266, 1267, 1268, 1269,\n    1270, 1271, 1272, 1273, 1274, 1275, 1276, 1277,\n    1278, 1279, 1280, 1281, 1282, 1283, 0};\n\nstatic const int address_start = 1;\n\nbool is_address(const char *p, const char *pe)\n{\n\tint cs = 0;\n\n\tconst char *eof = pe;\n\n\tbool result = false;\n\n\t{\n\t\tcs = (int) address_start;\n\t}\n\t{\n\t\tint _klen;\n\t\tunsigned int _trans = 0;\n\t\tconst signed char *_keys;\n\t\tconst signed char *_acts;\n\t\tunsigned int _nacts;\n\t_resume: {\n\t}\n\t\tif (p == pe && p != eof)\n\t\t\tgoto _out;\n\t\tif (p == eof) {\n\t\t\tif (_address_eof_trans[cs] > 0) {\n\t\t\t\t_trans = (unsigned int) _address_eof_trans[cs] - 1;\n\t\t\t}\n\t\t} else {\n\t\t\t_keys = (_address_trans_keys + (_address_key_offsets[cs]));\n\t\t\t_trans = (unsigned int) _address_index_offsets[cs];\n\n\t\t\t_klen = (int) _address_single_lengths[cs];\n\t\t\tif (_klen > 0) {\n\t\t\t\tconst signed char *_lower = _keys;\n\t\t\t\tconst signed char *_upper = _keys + _klen - 1;\n\t\t\t\tconst signed char *_mid;\n\t\t\t\twhile (1) {\n\t\t\t\t\tif (_upper < _lower) {\n\t\t\t\t\t\t_keys += _klen;\n\t\t\t\t\t\t_trans += (unsigned int) _klen;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\t_mid = _lower + ((_upper - _lower) >> 1);\n\t\t\t\t\tif (((*(p))) < (*(_mid)))\n\t\t\t\t\t\t_upper = _mid - 1;\n\t\t\t\t\telse if (((*(p))) > (*(_mid)))\n\t\t\t\t\t\t_lower = _mid + 1;\n\t\t\t\t\telse {\n\t\t\t\t\t\t_trans += (unsigned int) (_mid - _keys);\n\t\t\t\t\t\tgoto _match;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t_klen = (int) _address_range_lengths[cs];\n\t\t\tif (_klen > 0) {\n\t\t\t\tconst signed char *_lower = _keys;\n\t\t\t\tconst signed char *_upper = _keys + (_klen << 1) - 2;\n\t\t\t\tconst signed char *_mid;\n\t\t\t\twhile (1) {\n\t\t\t\t\tif (_upper < _lower) {\n\t\t\t\t\t\t_trans += (unsigned int) _klen;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\t_mid = _lower + (((_upper - _lower) >> 1) & ~1);\n\t\t\t\t\tif (((*(p))) < (*(_mid)))\n\t\t\t\t\t\t_upper = _mid - 2;\n\t\t\t\t\telse if (((*(p))) > (*(_mid + 1)))\n\t\t\t\t\t\t_lower = _mid + 2;\n\t\t\t\t\telse {\n\t\t\t\t\t\t_trans += (unsigned int) ((_mid - _keys) >> 1);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t_match: {\n\t\t}\n\t\t}\n\t\tcs = (int) _address_cond_targs[_trans];\n\n\t\tif (_address_cond_actions[_trans] != 0) {\n\n\t\t\t_acts = (_address_actions + (_address_cond_actions[_trans]));\n\t\t\t_nacts = (unsigned int) (*(_acts));\n\t\t\t_acts += 1;\n\t\t\twhile (_nacts > 0) {\n\t\t\t\tswitch ((*(_acts))) {\n\t\t\t\tcase 0: {\n\t\t\t\t\t{\n\t\t\t\t\t\tresult = true;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase 1: {\n\t\t\t\t\t{\n\t\t\t\t\t\tresult = false;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t_nacts -= 1;\n\t\t\t\t_acts += 1;\n\t\t\t}\n\t\t}\n\n\t\tif (p == eof) {\n\t\t\tif (cs >= 196)\n\t\t\t\tgoto _out;\n\t\t} else {\n\t\t\tif (cs != 0) {\n\t\t\t\tp += 1;\n\t\t\t\tgoto _resume;\n\t\t\t}\n\t\t}\n\t_out: {\n\t}\n\t}\n\treturn result;\n}\n"
  },
  {
    "path": "src/smtp-address-validator.hpp",
    "content": "#ifndef SMTP_ADDRESS_PARSER_HPP_INCLUDED\n#define SMTP_ADDRESS_PARSER_HPP_INCLUDED\n\n/*\n\nSnarfed from <https://github.com/gene-hightower/smtp-address-validator>\n\n<http://opensource.org/licenses/MIT>:\n\nCopyright (c) 2021 Gene Hightower\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\nof the Software, and to permit persons to whom the Software is furnished to do\nso, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n*/\n\nbool is_address(const char *p, const char *pe);\n\n#endif // SMTP_ADDRESS_PARSER_HPP_INCLUDED\n"
  },
  {
    "path": "src/string-format-check.cpp",
    "content": "#include <nlohmann/json-schema.hpp>\n\n#include \"smtp-address-validator.hpp\"\n\n#include <algorithm>\n#include <exception>\n#include <iostream>\n#include <regex>\n#include <sstream>\n#include <string>\n#include <utility>\n#include <vector>\n\n#ifdef JSON_SCHEMA_BOOST_REGEX\n#\tinclude <boost/regex.hpp>\n#\tdefine REGEX_NAMESPACE boost\n#elif defined(JSON_SCHEMA_NO_REGEX)\n#\tdefine NO_STD_REGEX\n#else\n#\tinclude <regex>\n#\tdefine REGEX_NAMESPACE std\n#endif\n\n/**\n * Many of the RegExes are from @see http://jmrware.com/articles/2009/uri_regexp/URI_regex.html\n */\n\nnamespace\n{\ntemplate <typename T>\nvoid range_check(const T value, const T min, const T max)\n{\n\tif (!((value >= min) && (value <= max))) {\n\t\tstd::stringstream out;\n\t\tout << \"Value \" << value << \" should be in interval [\" << min << \",\" << max << \"] but is not!\";\n\t\tthrow std::invalid_argument(out.str());\n\t}\n}\n\n/** @see date_time_check */\nvoid rfc3339_date_check(const std::string &value)\n{\n\tconst static REGEX_NAMESPACE::regex dateRegex{R\"(^([0-9]{4})\\-([0-9]{2})\\-([0-9]{2})$)\"};\n\n\tREGEX_NAMESPACE::smatch matches;\n\tif (!REGEX_NAMESPACE::regex_match(value, matches, dateRegex)) {\n\t\tthrow std::invalid_argument(value + \" is not a date string according to RFC 3339.\");\n\t}\n\n\tconst auto year = std::stoi(matches[1].str());\n\tconst auto month = std::stoi(matches[2].str());\n\tconst auto mday = std::stoi(matches[3].str());\n\n\tconst auto isLeapYear = (year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0));\n\n\trange_check(month, 1, 12);\n\tif (month == 2) {\n\t\trange_check(mday, 1, isLeapYear ? 29 : 28);\n\t} else if (month <= 7) {\n\t\trange_check(mday, 1, month % 2 == 0 ? 30 : 31);\n\t} else {\n\t\trange_check(mday, 1, month % 2 == 0 ? 31 : 30);\n\t}\n}\n\n/** @see date_time_check */\nvoid rfc3339_time_check(const std::string &value)\n{\n\tconst static REGEX_NAMESPACE::regex timeRegex{R\"(^([0-9]{2})\\:([0-9]{2})\\:([0-9]{2})(\\.[0-9]+)?(?:[Zz]|((?:\\+|\\-)[0-9]{2})\\:([0-9]{2}))$)\"};\n\n\tREGEX_NAMESPACE::smatch matches;\n\tif (!REGEX_NAMESPACE::regex_match(value, matches, timeRegex)) {\n\t\tthrow std::invalid_argument(value + \" is not a time string according to RFC 3339.\");\n\t}\n\n\tauto hour = std::stoi(matches[1].str());\n\tauto minute = std::stoi(matches[2].str());\n\tauto second = std::stoi(matches[3].str());\n\t// const auto secfrac      = std::stof( matches[4].str() );\n\n\trange_check(hour, 0, 23);\n\trange_check(minute, 0, 59);\n\n\tint offsetHour = 0,\n\t    offsetMinute = 0;\n\n\t/* don't check the numerical offset if time zone is specified as 'Z' */\n\tif (!matches[5].str().empty()) {\n\t\toffsetHour = std::stoi(matches[5].str());\n\t\toffsetMinute = std::stoi(matches[6].str());\n\n\t\trange_check(offsetHour, -23, 23);\n\t\trange_check(offsetMinute, 0, 59);\n\t\tif (offsetHour < 0)\n\t\t\toffsetMinute *= -1;\n\t}\n\n\t/**\n\t * @todo Could be made more exact by querying a leap second database and choosing the\n\t *       correct maximum in {58,59,60}. This current solution might match some invalid dates\n\t *       but it won't lead to false negatives. This only works if we know the full date, however\n\t */\n\n\tauto day_minutes = hour * 60 + minute - (offsetHour * 60 + offsetMinute);\n\tif (day_minutes < 0)\n\t\tday_minutes += 60 * 24;\n\thour = day_minutes % 24;\n\tminute = day_minutes / 24;\n\n\tif (hour == 23 && minute == 59)\n\t\trange_check(second, 0, 60); // possible leap-second\n\telse\n\t\trange_check(second, 0, 59);\n}\n\n/**\n * @see https://tools.ietf.org/html/rfc3339#section-5.6\n *\n * @verbatim\n * date-fullyear   = 4DIGIT\n * date-month      = 2DIGIT  ; 01-12\n * date-mday       = 2DIGIT  ; 01-28, 01-29, 01-30, 01-31 based on\n *                          ; month/year\n * time-hour       = 2DIGIT  ; 00-23\n * time-minute     = 2DIGIT  ; 00-59\n * time-second     = 2DIGIT  ; 00-58, 00-59, 00-60 based on leap second\n *                          ; rules\n * time-secfrac    = \".\" 1*DIGIT\n * time-numoffset  = (\"+\" / \"-\") time-hour \":\" time-minute\n * time-offset     = \"Z\" / time-numoffset\n *\n * partial-time    = time-hour \":\" time-minute \":\" time-second\n *                  [time-secfrac]\n * full-date       = date-fullyear \"-\" date-month \"-\" date-mday\n * full-time       = partial-time time-offset\n *\n * date-time       = full-date \"T\" full-time\n * @endverbatim\n * NOTE: Per [ABNF] and ISO8601, the \"T\" and \"Z\" characters in this\n *       syntax may alternatively be lower case \"t\" or \"z\" respectively.\n */\nvoid rfc3339_date_time_check(const std::string &value)\n{\n\tconst static REGEX_NAMESPACE::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}))$)\"};\n\n\tREGEX_NAMESPACE::smatch matches;\n\tif (!REGEX_NAMESPACE::regex_match(value, matches, dateTimeRegex)) {\n\t\tthrow std::invalid_argument(value + \" is not a date-time string according to RFC 3339.\");\n\t}\n\n\trfc3339_date_check(matches[1].str());\n\trfc3339_time_check(matches[2].str());\n}\n\nconst std::string decOctet{R\"((?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9]))\"}; // matches numbers 0-255\nconst std::string ipv4Address{\"(?:\" + decOctet + R\"(\\.){3})\" + decOctet};\nconst std::string h16{R\"([0-9A-Fa-f]{1,4})\"};\nconst std::string h16Left{\"(?:\" + h16 + \":)\"};\nconst std::string ipv6Address{\n    \"(?:\"\n    \"(?:\" +\n    h16Left + \"{6}\"\n              \"|::\" +\n    h16Left + \"{5}\"\n              \"|(?:\" +\n    h16 + \")?::\" + h16Left + \"{4}\"\n                             \"|(?:\" +\n    h16Left + \"{0,1}\" + h16 + \")?::\" + h16Left + \"{3}\"\n                                                 \"|(?:\" +\n    h16Left + \"{0,2}\" + h16 + \")?::\" + h16Left + \"{2}\"\n                                                 \"|(?:\" +\n    h16Left + \"{0,3}\" + h16 + \")?::\" + h16Left +\n    \"|(?:\" + h16Left + \"{0,4}\" + h16 + \")?::\"\n                                       \")(?:\" +\n    h16Left + h16 + \"|\" + ipv4Address + \")\"\n                                        \"|(?:\" +\n    h16Left + \"{0,5}\" + h16 + \")?::\" + h16 +\n    \"|(?:\" + h16Left + \"{0,6}\" + h16 + \")?::\"\n                                       \")\"};\nconst std::string ipvFuture{R\"([Vv][0-9A-Fa-f]+\\.[A-Za-z0-9\\-._~!$&'()*+,;=:]+)\"};\nconst std::string regName{R\"((?:[A-Za-z0-9\\-._~!$&'()*+,;=]|%[0-9A-Fa-f]{2})*)\"};\nconst std::string host{\n    \"(?:\"\n    R\"(\\[(?:)\" +\n    ipv6Address + \"|\" + ipvFuture + R\"()\\])\" +\n    \"|\" + ipv4Address +\n    \"|\" + regName +\n    \")\"};\n\nconst std::string uuid{R\"([0-9a-fA-F]{8}\\-[0-9a-fA-F]{4}\\-[0-9a-fA-F]{4}\\-[0-9a-fA-F]{4}\\-[0-9a-fA-F]{12})\"};\n\n// from http://stackoverflow.com/questions/106179/regular-expression-to-match-dns-hostname-or-ip-address\nconst 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]))*$)\"};\n\nbool is_ascii(std::string const &value)\n{\n\tfor (auto ch : value) {\n\t\tif (ch & 0x80) {\n\t\t\treturn false;\n\t\t}\n\t}\n\treturn true;\n}\n\n/**\n * @see\n *\n * @verbatim\n * URI           = scheme \":\" hier-part [ \"?\" query ] [ \"#\" fragment ]\n *\n *  hier-part     = \"//\" authority path-abempty\n *               / path-absolute\n *               / path-rootless\n *               / path-empty\n *\n * URI-reference = URI / relative-ref\n *\n * absolute-URI  = scheme \":\" hier-part [ \"?\" query ]\n *\n * relative-ref  = relative-part [ \"?\" query ] [ \"#\" fragment ]\n *\n * relative-part = \"//\" authority path-abempty\n *               / path-absolute\n *               / path-noscheme\n *               / path-empty\n *\n * scheme        = ALPHA *( ALPHA / DIGIT / \"+\" / \"-\" / \".\" )\n *\n * authority     = [ userinfo \"@\" ] host [ \":\" port ]\n * userinfo      = *( unreserved / pct-encoded / sub-delims / \":\" )\n * host          = IP-literal / IPv4address / reg-name\n * port          = *DIGIT\n *\n * IP-literal    = \"[\" ( IPv6address / IPvFuture  ) \"]\"\n *\n * IPvFuture     = \"v\" 1*HEXDIG \".\" 1*( unreserved / sub-delims / \":\" )\n *\n * IPv6address   =                            6( h16 \":\" ) ls32\n *               /                       \"::\" 5( h16 \":\" ) ls32\n *               / [               h16 ] \"::\" 4( h16 \":\" ) ls32\n *               / [ *1( h16 \":\" ) h16 ] \"::\" 3( h16 \":\" ) ls32\n *               / [ *2( h16 \":\" ) h16 ] \"::\" 2( h16 \":\" ) ls32\n *               / [ *3( h16 \":\" ) h16 ] \"::\"    h16 \":\"   ls32\n *               / [ *4( h16 \":\" ) h16 ] \"::\"              ls32\n *               / [ *5( h16 \":\" ) h16 ] \"::\"              h16\n *               / [ *6( h16 \":\" ) h16 ] \"::\"\n *\n * h16           = 1*4HEXDIG\n * ls32          = ( h16 \":\" h16 ) / IPv4address\n * IPv4address   = dec-octet \".\" dec-octet \".\" dec-octet \".\" dec-octet\n *    dec-octet     = DIGIT                 ; 0-9\n *               / %x31-39 DIGIT         ; 10-99\n *               / \"1\" 2DIGIT            ; 100-199\n *               / \"2\" %x30-34 DIGIT     ; 200-249\n *               / \"25\" %x30-35          ; 250-255\n *\n * reg-name      = *( unreserved / pct-encoded / sub-delims )\n *\n * path          = path-abempty    ; begins with \"/\" or is empty\n *               / path-absolute   ; begins with \"/\" but not \"//\"\n *               / path-noscheme   ; begins with a non-colon segment\n *               / path-rootless   ; begins with a segment\n *               / path-empty      ; zero characters\n *\n * path-abempty  = *( \"/\" segment )\n * path-absolute = \"/\" [ segment-nz *( \"/\" segment ) ]\n * path-noscheme = segment-nz-nc *( \"/\" segment )\n * path-rootless = segment-nz *( \"/\" segment )\n * path-empty    = 0<pchar>\n *\n * segment       = *pchar\n * segment-nz    = 1*pchar\n * segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / \"@\" )\n *               ; non-zero-length segment without any colon \":\"\n *\n * pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *\n * query         = *( pchar / \"/\" / \"?\" )\n *\n * fragment      = *( pchar / \"/\" / \"?\" )\n *\n * pct-encoded   = \"%\" HEXDIG HEXDIG\n *\n * unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n * reserved      = gen-delims / sub-delims\n * gen-delims    = \":\" / \"/\" / \"?\" / \"#\" / \"[\" / \"]\" / \"@\"\n * sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *               / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n *\n * @endverbatim\n * @see adapted from: https://github.com/jhermsmeier/uri.regex/blob/master/uri.regex\n *\n */\nvoid rfc3986_uri_check(const std::string &value)\n{\n\tconst static std::string scheme{R\"(([A-Za-z][A-Za-z0-9+\\-.]*):)\"};\n\tconst static std::string hierPart{\n\t    R\"((?:(\\/\\/)(?:((?:[A-Za-z0-9\\-._~!$&'()*+,;=:]|)\"\n\t    R\"(%[0-9A-Fa-f]{2})*)@)?((?:\\[(?:(?:(?:(?:[0-9A-Fa-f]{1,4}:){6}|)\"\n\t    R\"(::(?:[0-9A-Fa-f]{1,4}:){5}|)\"\n\t    R\"((?:[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){4}|)\"\n\t    R\"((?:(?:[0-9A-Fa-f]{1,4}:){0,1}[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){3}|)\"\n\t    R\"((?:(?:[0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){2}|)\"\n\t    R\"((?:(?:[0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})?::[0-9A-Fa-f]{1,4}:|)\"\n\t    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}|)\"\n\t    R\"((?:(?:25[0-5]|2[0-4][0-9]|)\"\n\t    R\"([01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|)\"\n\t    R\"(2[0-4][0-9]|)\"\n\t    R\"([01]?[0-9][0-9]?))|)\"\n\t    R\"((?:(?:[0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})?::[0-9A-Fa-f]{1,4}|)\"\n\t    R\"((?:(?:[0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})?::)|)\"\n\t    R\"([Vv][0-9A-Fa-f]+\\.[A-Za-z0-9\\-._~!$&'()*+,;=:]+)\\]|)\"\n\t    R\"((?:(?:25[0-5]|)\"\n\t    R\"(2[0-4][0-9]|)\"\n\t    R\"([01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|)\"\n\t    R\"(2[0-4][0-9]|)\"\n\t    R\"([01]?[0-9][0-9]?)|)\"\n\t    R\"((?:[A-Za-z0-9\\-._~!$&'()*+,;=]|)\"\n\t    R\"(%[0-9A-Fa-f]{2})*))(?::([0-9]*))?((?:\\/(?:[A-Za-z0-9\\-._~!$&'()*+,;=:@]|)\"\n\t    R\"(%[0-9A-Fa-f]{2})*)*)|)\"\n\t    R\"(\\/((?:(?:[A-Za-z0-9\\-._~!$&'()*+,;=:@]|)\"\n\t    R\"(%[0-9A-Fa-f]{2})+(?:\\/(?:[A-Za-z0-9\\-._~!$&'()*+,;=:@]|)\"\n\t    R\"(%[0-9A-Fa-f]{2})*)*)?)|)\"\n\t    R\"(((?:[A-Za-z0-9\\-._~!$&'()*+,;=:@]|)\"\n\t    R\"(%[0-9A-Fa-f]{2})+(?:\\/(?:[A-Za-z0-9\\-._~!$&'()*+,;=:@]|)\"\n\t    R\"(%[0-9A-Fa-f]{2})*)*)|))\"};\n\n\tconst static std::string query{R\"((?:\\?((?:[A-Za-z0-9\\-._~!$&'()*+,;=:@\\/?]|%[0-9A-Fa-f]{2})*))?)\"};\n\tconst static std::string fragment{\n\t    R\"((?:\\#((?:[A-Za-z0-9\\-._~!$&'()*+,;=:@\\/?]|%[0-9A-Fa-f]{2})*))?)\"};\n\tconst static std::string uriFormat{scheme + hierPart + query + fragment};\n\n\tconst static REGEX_NAMESPACE::regex uriRegex{uriFormat};\n\n\tif (!REGEX_NAMESPACE::regex_match(value, uriRegex)) {\n\t\tthrow std::invalid_argument(value + \" is not a URI string according to RFC 3986.\");\n\t}\n}\n\n} // namespace\n\nnamespace nlohmann\n{\nnamespace json_schema\n{\n/**\n * Checks validity for built-ins by converting the definitions given as ABNF in the linked RFC from\n * @see https://json-schema.org/understanding-json-schema/reference/string.html#built-in-formats\n * into regular expressions using @see https://www.msweet.org/abnf/ and some manual editing.\n *\n * @see https://json-schema.org/latest/json-schema-validation.html\n */\nvoid default_string_format_check(const std::string &format, const std::string &value)\n{\n\tif (format == \"date-time\") {\n\t\trfc3339_date_time_check(value);\n\t} else if (format == \"date\") {\n\t\trfc3339_date_check(value);\n\t} else if (format == \"time\") {\n\t\trfc3339_time_check(value);\n\t} else if (format == \"uri\") {\n\t\trfc3986_uri_check(value);\n\t} else if (format == \"email\") {\n\t\tif (!is_ascii(value)) {\n\t\t\tthrow std::invalid_argument(value + \" contains non-ASCII values, not RFC 5321 compliant.\");\n\t\t}\n\t\tif (!is_address(&*value.begin(), &*value.end())) {\n\t\t\tthrow std::invalid_argument(value + \" is not a valid email according to RFC 5321.\");\n\t\t}\n\t} else if (format == \"idn-email\") {\n\t\tif (!is_address(&*value.begin(), &*value.end())) {\n\t\t\tthrow std::invalid_argument(value + \" is not a valid idn-email according to RFC 6531.\");\n\t\t}\n\t} else if (format == \"hostname\") {\n\t\tstatic const REGEX_NAMESPACE::regex hostRegex{hostname};\n\t\tif (!REGEX_NAMESPACE::regex_match(value, hostRegex)) {\n\t\t\tthrow std::invalid_argument(value + \" is not a valid hostname according to RFC 3986 Appendix A.\");\n\t\t}\n\t} else if (format == \"ipv4\") {\n\t\tconst static REGEX_NAMESPACE::regex ipv4Regex{\"^\" + ipv4Address + \"$\"};\n\t\tif (!REGEX_NAMESPACE::regex_match(value, ipv4Regex)) {\n\t\t\tthrow std::invalid_argument(value + \" is not an IPv4 string according to RFC 2673.\");\n\t\t}\n\t} else if (format == \"ipv6\") {\n\t\tstatic const REGEX_NAMESPACE::regex ipv6Regex{ipv6Address};\n\t\tif (!REGEX_NAMESPACE::regex_match(value, ipv6Regex)) {\n\t\t\tthrow std::invalid_argument(value + \" is not an IPv6 string according to RFC 5954.\");\n\t\t}\n\t} else if (format == \"uuid\") {\n\t\tstatic const REGEX_NAMESPACE::regex uuidRegex{uuid};\n\t\tif (!REGEX_NAMESPACE::regex_match(value, uuidRegex)) {\n\t\t\tthrow std::invalid_argument(value + \" is not an uuid string according to RFC 4122.\");\n\t\t}\n\t} else if (format == \"regex\") {\n\t\ttry {\n\t\t\tREGEX_NAMESPACE::regex re(value, std::regex::ECMAScript);\n\t\t} catch (std::exception &exception) {\n\t\t\tthrow exception;\n\t\t}\n\t} else {\n\t\t/* yet unsupported JSON schema draft 7 built-ins */\n\t\tstatic const std::vector<std::string> jsonSchemaStringFormatBuiltIns{\n\t\t    \"date-time\", \"time\", \"date\", \"email\", \"idn-email\", \"hostname\", \"idn-hostname\", \"ipv4\", \"ipv6\", \"uri\",\n\t\t    \"uri-reference\", \"iri\", \"iri-reference\", \"uri-template\", \"json-pointer\", \"relative-json-pointer\", \"regex\"};\n\t\tif (std::find(jsonSchemaStringFormatBuiltIns.begin(), jsonSchemaStringFormatBuiltIns.end(), format) != jsonSchemaStringFormatBuiltIns.end()) {\n\t\t\tthrow std::logic_error(\"JSON schema string format built-in \" + format + \" not yet supported. \" +\n\t\t\t                       \"Please open an issue or use a custom format checker.\");\n\t\t}\n\n\t\tthrow std::logic_error(\"Don't know how to validate \" + format);\n\t}\n}\n} // namespace json_schema\n} // namespace nlohmann\n"
  },
  {
    "path": "test/CMakeLists.txt",
    "content": "set(PIPE_IN_TEST_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/test-pipe-in.sh)\n\n# simple nlohmann_json_schema_validator-executable\nadd_executable(json-schema-validate json-schema-validate.cpp)\ntarget_link_libraries(json-schema-validate nlohmann_json_schema_validator)\n\nfunction(add_test_simple_schema name schema instance)\n    add_test(\n        NAME ${name}\n        COMMAND ${PIPE_IN_TEST_SCRIPT}\n            $<TARGET_FILE:json-schema-validate>\n            ${schema}\n            ${instance}\n        WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})\nendfunction()\n\nfile(GLOB TEST_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/*)\n\nforeach(DIR ${TEST_DIRS})\n    if(IS_DIRECTORY ${DIR})\n        add_subdirectory(${DIR})\n    endif()\nendforeach()\n\nadd_executable(uri uri.cpp)\ntarget_link_libraries(uri nlohmann_json_schema_validator)\nadd_test(NAME uri COMMAND uri)\n\nadd_executable(errors errors.cpp)\ntarget_link_libraries(errors nlohmann_json_schema_validator)\nadd_test(NAME errors COMMAND errors)\n\nadd_executable(issue-70 issue-70.cpp)\ntarget_link_libraries(issue-70 nlohmann_json_schema_validator)\nadd_test(NAME issue-70 COMMAND issue-70)\n\nadd_executable(issue-70-root-schema-constructor issue-70-root-schema-constructor.cpp)\ntarget_link_libraries(issue-70-root-schema-constructor nlohmann_json_schema_validator)\nadd_test(NAME issue-70-root-schema-constructor COMMAND issue-70-root-schema-constructor)\n\nadd_executable(issue-25-default-values issue-25-default-values.cpp)\ntarget_link_libraries(issue-25-default-values nlohmann_json_schema_validator)\nadd_test(NAME issue-25-default-values COMMAND issue-25-default-values)\n\nadd_executable(issue-98 issue-98.cpp)\ntarget_link_libraries(issue-98 nlohmann_json_schema_validator)\nadd_test(NAME issue-98-erase-exception-unknown-keywords COMMAND issue-98)\n\nadd_executable(issue-293 issue-293.cpp)\ntarget_link_libraries(issue-293 nlohmann_json_schema_validator)\nadd_test(NAME issue-293-float-point-error COMMAND issue-293)\n\n# Unit test for string format checks\nadd_executable(string-format-check-test string-format-check-test.cpp)\ntarget_include_directories(string-format-check-test PRIVATE ${PROJECT_SOURCE_DIR}/src/)\ntarget_link_libraries(string-format-check-test nlohmann_json_schema_validator)\n\nadd_test(NAME string-format-check-test COMMAND string-format-check-test)\n\n# Unit test for json-patch\nadd_executable(json-patch json-patch.cpp)\ntarget_include_directories(json-patch PRIVATE ${PROJECT_SOURCE_DIR}/src)\ntarget_link_libraries(json-patch nlohmann_json_schema_validator)\nadd_test(NAME json-patch COMMAND json-patch)\n\n# Unit test for format checker fail at schema parsing time\nadd_executable(issue-117-format-error issue-117-format-error.cpp)\ntarget_link_libraries(issue-117-format-error nlohmann_json_schema_validator)\nadd_test(NAME issue-117-format-error COMMAND issue-117-format-error)\n\nadd_executable(binary-validation binary-validation.cpp)\ntarget_include_directories(binary-validation PRIVATE ${PROJECT_SOURCE_DIR}/src)\ntarget_link_libraries(binary-validation PRIVATE nlohmann_json_schema_validator)\nadd_test(NAME binary-validation COMMAND binary-validation)\n\nadd_executable(issue-149-entry-selection issue-149-entry-selection.cpp)\ntarget_link_libraries(issue-149-entry-selection PRIVATE nlohmann_json_schema_validator)\nadd_test(NAME issue-149-entry-selection COMMAND issue-149-entry-selection)\n\nadd_executable(issue-189-default-values issue-189-default-values.cpp)\ntarget_link_libraries(issue-189-default-values nlohmann_json_schema_validator)\nadd_test(NAME issue-189-default-values COMMAND issue-189-default-values)\n\nadd_executable(issue-229-oneof-default-values issue-229-oneof-default-values.cpp)\ntarget_link_libraries(issue-229-oneof-default-values nlohmann_json_schema_validator)\nadd_test(NAME issue-229-oneof-default-values COMMAND issue-229-oneof-default-values)\n\nadd_executable(issue-243-root-default-values issue-243-root-default-values.cpp)\ntarget_link_libraries(issue-243-root-default-values nlohmann_json_schema_validator)\nadd_test(NAME issue-243-root-default-values COMMAND issue-243-root-default-values)\n\nadd_executable(issue-255-error-message-limit-precision issue-255-error-message-limit-precision.cpp)\ntarget_link_libraries(issue-255-error-message-limit-precision nlohmann_json_schema_validator)\nadd_test(NAME issue-255-error-message-limit-precision COMMAND issue-255-error-message-limit-precision)\n\nadd_executable(issue-105-verbose-combination-errors issue-105-verbose-combination-errors.cpp)\ntarget_link_libraries(issue-105-verbose-combination-errors nlohmann_json_schema_validator)\nadd_test(NAME issue-105-verbose-combination-errors COMMAND issue-105-verbose-combination-errors)\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/CMakeLists.txt",
    "content": "set(JSON_SCHEMA_TEST_PREFIX \"JSON-Suite\" CACHE STRING \"prefix for JSON-tests added to ctest\")\n\nset(DRAFT \"draft7\")\n\n# find schema-test-suite\nfind_path(JSON_SCHEMA_TEST_SUITE_PATH\n    NAMES\n        tests/${DRAFT})\n\nif (NOT JSON_SCHEMA_TEST_SUITE_PATH)\n    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.\")\n    set(JSON_SCHEMA_TEST_SUITE_PATH ${CMAKE_CURRENT_SOURCE_DIR})\nendif()\n\nif(JSON_SCHEMA_TEST_SUITE_PATH)\n    # json-schema-validator-tester\n    add_executable(json-schema-test json-schema-test.cpp)\n    target_link_libraries(json-schema-test nlohmann_json_schema_validator)\n    target_compile_definitions(json-schema-test\n        PRIVATE\n            JSON_SCHEMA_TEST_SUITE_PATH=\"${JSON_SCHEMA_TEST_SUITE_PATH}\")\n\n    option(JSON_SCHEMA_ENABLE_OPTIONAL_TESTS \"Enable optional tests of the JSONSchema Test Suite\" ON)\n\n    # create tests foreach test-file\n    file(GLOB TEST_FILES ${JSON_SCHEMA_TEST_SUITE_PATH}/tests/${DRAFT}/*.json)\n\n    foreach(TEST_FILE ${TEST_FILES})\n        get_filename_component(TEST_NAME ${TEST_FILE} NAME_WE)\n        add_test(NAME \"${JSON_SCHEMA_TEST_PREFIX}::${TEST_NAME}\"\n                 COMMAND ${PIPE_IN_TEST_SCRIPT} $<TARGET_FILE:json-schema-test> ${TEST_FILE})\n    endforeach()\n\n    if (JSON_SCHEMA_ENABLE_OPTIONAL_TESTS)\n        file(GLOB OPT_TEST_FILES ${JSON_SCHEMA_TEST_SUITE_PATH}/tests/${DRAFT}/optional/*.json)\n        file(GLOB FORMAT_TEST_FILES ${JSON_SCHEMA_TEST_SUITE_PATH}/tests/${DRAFT}/optional/format/*.json)\n\n        foreach(TEST_FILE ${OPT_TEST_FILES})\n            get_filename_component(TEST_NAME ${TEST_FILE} NAME_WE)\n            add_test(NAME \"${JSON_SCHEMA_TEST_PREFIX}::Optional::${TEST_NAME}\"\n                     COMMAND ${PIPE_IN_TEST_SCRIPT} $<TARGET_FILE:json-schema-test> ${TEST_FILE})\n        endforeach()\n\n        foreach(TEST_FILE ${FORMAT_TEST_FILES})\n            get_filename_component(TEST_NAME ${TEST_FILE} NAME_WE)\n            add_test(NAME \"${JSON_SCHEMA_TEST_PREFIX}::Optional::Format::${TEST_NAME}\"\n                     COMMAND ${PIPE_IN_TEST_SCRIPT} $<TARGET_FILE:json-schema-test> ${TEST_FILE})\n        endforeach()\n\n        # some optional tests will fail\n        set_tests_properties(\n            JSON-Suite::Optional::bignum\n            JSON-Suite::Optional::non-bmp-regex\n            JSON-Suite::Optional::float-overflow\n\n            JSON-Suite::Optional::ecmascript-regex\n            JSON-Suite::Optional::Format::idn-hostname\n            JSON-Suite::Optional::Format::iri-reference\n            JSON-Suite::Optional::Format::iri\n            JSON-Suite::Optional::Format::json-pointer\n            JSON-Suite::Optional::Format::relative-json-pointer\n            JSON-Suite::Optional::Format::uri-reference\n            JSON-Suite::Optional::Format::uri-template\n            JSON-Suite::Optional::unicode\n\n            PROPERTIES\n                WILL_FAIL ON)\n    endif()\nelse()\nendif()\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/json-schema-test.cpp",
    "content": "/*\n * JSON schema validator for JSON for modern C++\n *\n * Copyright (c) 2016-2019 Patrick Boettcher <p@yai.se>.\n *\n * SPDX-License-Identifier: MIT\n *\n */\n#include <nlohmann/json-schema.hpp>\n\n#include <fstream>\n#include <iostream>\n#include <regex>\n\nusing nlohmann::json;\nusing nlohmann::json_uri;\nusing nlohmann::json_schema::json_validator;\n\nstatic void loader(const json_uri &uri, json &schema)\n{\n\tif (uri.location() == \"http://json-schema.org/draft-07/schema\") {\n\t\tschema = nlohmann::json_schema::draft7_schema_builtin;\n\t\treturn;\n\t}\n\n\tstd::string fn = JSON_SCHEMA_TEST_SUITE_PATH;\n\tfn += \"/remotes\";\n\tfn += uri.path();\n\tstd::cerr << fn << \"\\n\";\n\n\tstd::fstream s(fn.c_str());\n\tif (!s.good())\n\t\tthrow std::invalid_argument(\"could not open \" + uri.url() + \" for schema loading\\n\");\n\n\ttry {\n\t\ts >> schema;\n\t} catch (std::exception &e) {\n\t\tthrow e;\n\t}\n}\n\n// from here\n// https://stackoverflow.com/a/34571089/880584\nstatic std::string base64_decode(const std::string &in)\n{\n\tstd::string out;\n\n\tstd::vector<int> T(256, -1);\n\tfor (int i = 0; i < 64; i++)\n\t\tT[\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\"[i]] = i;\n\n\tunsigned val = 0;\n\tint valb = -8;\n\tfor (uint8_t c : in) {\n\t\tif (c == '=')\n\t\t\tbreak;\n\n\t\tif (T[c] == -1) {\n\t\t\tthrow std::invalid_argument(\"base64-decode: unexpected character in encode string: '\" + std::string(1, c) + \"'\");\n\t\t}\n\t\tval = (val << 6) + T[c];\n\t\tvalb += 6;\n\t\tif (valb >= 0) {\n\t\t\tout.push_back(char((val >> valb) & 0xFF));\n\t\t\tvalb -= 8;\n\t\t}\n\t}\n\treturn out;\n}\n\nstatic void content(const std::string &contentEncoding, const std::string &contentMediaType, const json &instance)\n{\n\tstd::string content = instance;\n\n\tif (contentEncoding == \"base64\")\n\t\tcontent = base64_decode(instance);\n\telse if (contentEncoding != \"\")\n\t\tthrow std::invalid_argument(\"unable to check for contentEncoding '\" + contentEncoding + \"'\");\n\n\tif (contentMediaType == \"application/json\")\n\t\tauto dummy = json::parse(content); // throws if conversion fails\n\telse if (contentMediaType != \"\")\n\t\tthrow std::invalid_argument(\"unable to check for contentMediaType '\" + contentMediaType + \"'\");\n}\n\nint main(void)\n{\n\tjson validation; // a validation case following the JSON-test-suite-schema\n\n\ttry {\n\t\tstd::cin >> validation;\n\t} catch (std::exception &e) {\n\t\tstd::cout << e.what() << \"\\n\";\n\t\treturn EXIT_FAILURE;\n\t}\n\n\tsize_t total_failed = 0,\n\t       total = 0;\n\n\tfor (auto &test_group : validation) {\n\t\tsize_t group_failed = 0,\n\t\t       group_total = 0;\n\n\t\tstd::cout << \"Testing Group \" << test_group[\"description\"] << \"\\n\";\n\n\t\tconst auto &schema = test_group[\"schema\"];\n\n\t\tjson_validator validator(loader,\n\t\t                         nlohmann::json_schema::default_string_format_check,\n\t\t                         content);\n\n\t\tvalidator.set_root_schema(schema);\n\n\t\tfor (auto &test_case : test_group[\"tests\"]) {\n\t\t\tstd::cout << \"  Testing Case \" << test_case[\"description\"] << \"\\n\";\n\n\t\t\tbool valid = true;\n\n\t\t\ttry {\n\t\t\t\tvalidator.validate(test_case[\"data\"]);\n\t\t\t} catch (const std::out_of_range &e) {\n\t\t\t\tvalid = false;\n\t\t\t\tstd::cout << \"    Test Case Exception (out of range): \" << e.what() << \"\\n\";\n\n\t\t\t} catch (const std::invalid_argument &e) {\n\t\t\t\tvalid = false;\n\t\t\t\tstd::cout << \"    Test Case Exception (invalid argument): \" << e.what() << \"\\n\";\n\n\t\t\t} catch (const std::logic_error &e) {\n\t\t\t\tvalid = !test_case[\"valid\"]; /* force test-case failure */\n\t\t\t\tstd::cout << \"    Not yet implemented: \" << e.what() << \"\\n\";\n\t\t\t}\n\n\t\t\tif (valid == test_case[\"valid\"])\n\t\t\t\tstd::cout << \"      --> Test Case exited with \" << valid << \" as expected.\\n\";\n\t\t\telse {\n\t\t\t\tgroup_failed++;\n\t\t\t\tstd::cout << \"      --> Test Case exited with \" << valid << \" NOT expected.\\n\";\n\t\t\t}\n\t\t\tgroup_total++;\n\t\t\tstd::cout << \"\\n\";\n\t\t}\n\t\ttotal_failed += group_failed;\n\t\ttotal += group_total;\n\t\tstd::cout << \"Group RESULT: \" << test_group[\"description\"] << \" \"\n\t\t          << (group_total - group_failed) << \" of \" << group_total\n\t\t          << \" have succeeded - \" << group_failed << \" failed\\n\";\n\t\tstd::cout << \"-------------\\n\";\n\t}\n\n\tstd::cout << \"Total RESULT: \" << (total - total_failed) << \" of \" << total << \" have succeeded - \" << total_failed << \" failed\\n\";\n\n\treturn total_failed;\n}\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/remotes/baseUriChange/folderInteger.json",
    "content": "{\n    \"type\": \"integer\"\n}\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/remotes/baseUriChangeFolder/folderInteger.json",
    "content": "{\n    \"type\": \"integer\"\n}\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/remotes/baseUriChangeFolderInSubschema/folderInteger.json",
    "content": "{\n    \"type\": \"integer\"\n}\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/remotes/folder/folderInteger.json",
    "content": "{\n    \"type\": \"integer\"\n}\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/remotes/integer.json",
    "content": "{\n    \"type\": \"integer\"\n}\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/remotes/name-defs.json",
    "content": "{\n    \"$defs\": {\n        \"orNull\": {\n            \"anyOf\": [\n                {\n                    \"type\": \"null\"\n                },\n                {\n                    \"$ref\": \"#\"\n                }\n            ]\n        }\n    },\n    \"type\": \"string\"\n}\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/remotes/name.json",
    "content": "{\n    \"definitions\": {\n        \"orNull\": {\n            \"anyOf\": [\n                {\n                    \"type\": \"null\"\n                },\n                {\n                    \"$ref\": \"#\"\n                }\n            ]\n        }\n    },\n    \"type\": \"string\"\n}\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/remotes/ref-and-definitions.json",
    "content": "{\n    \"$id\": \"http://localhost:1234/ref-and-definitions.json\",\n    \"definitions\": {\n        \"inner\": {\n            \"properties\": {\n                \"bar\": { \"type\": \"string\" }\n            }\n        }\n    },\n    \"allOf\": [ { \"$ref\": \"#/definitions/inner\" } ]\n}\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/remotes/ref-and-defs.json",
    "content": "{\n    \"$id\": \"http://localhost:1234/ref-and-defs.json\",\n    \"$defs\": {\n        \"inner\": {\n            \"properties\": {\n                \"bar\": { \"type\": \"string\" }\n            }\n        }\n    },\n    \"$ref\": \"#/$defs/inner\"\n}\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/remotes/subSchemas-defs.json",
    "content": "{\n    \"$defs\": {\n        \"integer\": {\n            \"type\": \"integer\"\n        },\n        \"refToInteger\": {\n            \"$ref\": \"#/$defs/integer\"\n        }\n    }\n}\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/remotes/subSchemas.json",
    "content": "{\n    \"integer\": {\n        \"type\": \"integer\"\n    },\n    \"refToInteger\": {\n        \"$ref\": \"#/integer\"\n    }\n}\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/additionalItems.json",
    "content": "[\n    {\n        \"description\": \"additionalItems as schema\",\n        \"schema\": {\n            \"items\": [{}],\n            \"additionalItems\": {\"type\": \"integer\"}\n        },\n        \"tests\": [\n            {\n                \"description\": \"additional items match schema\",\n                \"data\": [ null, 2, 3, 4 ],\n                \"valid\": true\n            },\n            {\n                \"description\": \"additional items do not match schema\",\n                \"data\": [ null, 2, 3, \"foo\" ],\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"when items is schema, additionalItems does nothing\",\n        \"schema\": {\n            \"items\": {},\n            \"additionalItems\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"all items match schema\",\n                \"data\": [ 1, 2, 3, 4, 5 ],\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"array of items with no additionalItems permitted\",\n        \"schema\": {\n            \"items\": [{}, {}, {}],\n            \"additionalItems\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"empty array\",\n                \"data\": [ ],\n                \"valid\": true\n            },\n            {\n                \"description\": \"fewer number of items present (1)\",\n                \"data\": [ 1 ],\n                \"valid\": true\n            },\n            {\n                \"description\": \"fewer number of items present (2)\",\n                \"data\": [ 1, 2 ],\n                \"valid\": true\n            },\n            {\n                \"description\": \"equal number of items present\",\n                \"data\": [ 1, 2, 3 ],\n                \"valid\": true\n            },\n            {\n                \"description\": \"additional items are not permitted\",\n                \"data\": [ 1, 2, 3, 4 ],\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"additionalItems as false without items\",\n        \"schema\": {\"additionalItems\": false},\n        \"tests\": [\n            {\n                \"description\":\n                    \"items defaults to empty schema so everything is valid\",\n                \"data\": [ 1, 2, 3, 4, 5 ],\n                \"valid\": true\n            },\n            {\n                \"description\": \"ignores non-arrays\",\n                \"data\": {\"foo\" : \"bar\"},\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"additionalItems are allowed by default\",\n        \"schema\": {\"items\": [{\"type\": \"integer\"}]},\n        \"tests\": [\n            {\n                \"description\": \"only the first item is validated\",\n                \"data\": [1, \"foo\", false],\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"additionalItems should not look in applicators, valid case\",\n        \"schema\": {\n            \"allOf\": [\n                { \"items\": [ { \"type\": \"integer\" } ] }\n            ],\n            \"additionalItems\": { \"type\": \"boolean\" }\n        },\n        \"tests\": [\n            {\n                \"description\": \"items defined in allOf are not examined\",\n                \"data\": [ 1, null ],\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"additionalItems should not look in applicators, invalid case\",\n        \"schema\": {\n            \"allOf\": [\n                { \"items\": [ { \"type\": \"integer\" }, { \"type\": \"string\" } ] }\n            ],\n            \"items\": [ {\"type\": \"integer\" } ],\n            \"additionalItems\": { \"type\": \"boolean\" }\n        },\n        \"tests\": [\n            {\n                \"description\": \"items defined in allOf are not examined\",\n                \"data\": [ 1, \"hello\" ],\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"items validation adjusts the starting index for additionalItems\",\n        \"schema\": {\n            \"items\": [ { \"type\": \"string\" } ],\n            \"additionalItems\": { \"type\": \"integer\" }\n        },\n        \"tests\": [\n            {\n                \"description\": \"valid items\",\n                \"data\": [ \"x\", 2, 3 ],\n                \"valid\": true\n            },\n            {\n                \"description\": \"wrong type of second item\",\n                \"data\": [ \"x\", \"y\" ],\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/additionalProperties.json",
    "content": "[\n    {\n        \"description\":\n            \"additionalProperties being false does not allow other properties\",\n        \"schema\": {\n            \"properties\": {\"foo\": {}, \"bar\": {}},\n            \"patternProperties\": { \"^v\": {} },\n            \"additionalProperties\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"no additional properties is valid\",\n                \"data\": {\"foo\": 1},\n                \"valid\": true\n            },\n            {\n                \"description\": \"an additional property is invalid\",\n                \"data\": {\"foo\" : 1, \"bar\" : 2, \"quux\" : \"boom\"},\n                \"valid\": false\n            },\n            {\n                \"description\": \"ignores arrays\",\n                \"data\": [1, 2, 3],\n                \"valid\": true\n            },\n            {\n                \"description\": \"ignores strings\",\n                \"data\": \"foobarbaz\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"ignores other non-objects\",\n                \"data\": 12,\n                \"valid\": true\n            },\n            {\n                \"description\": \"patternProperties are not additional properties\",\n                \"data\": {\"foo\":1, \"vroom\": 2},\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"non-ASCII pattern with additionalProperties\",\n        \"schema\": {\n            \"patternProperties\": {\"^á\": {}},\n            \"additionalProperties\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"matching the pattern is valid\",\n                \"data\": {\"ármányos\": 2},\n                \"valid\": true\n            },\n            {\n                \"description\": \"not matching the pattern is invalid\",\n                \"data\": {\"élmény\": 2},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\":\n            \"additionalProperties allows a schema which should validate\",\n        \"schema\": {\n            \"properties\": {\"foo\": {}, \"bar\": {}},\n            \"additionalProperties\": {\"type\": \"boolean\"}\n        },\n        \"tests\": [\n            {\n                \"description\": \"no additional properties is valid\",\n                \"data\": {\"foo\": 1},\n                \"valid\": true\n            },\n            {\n                \"description\": \"an additional valid property is valid\",\n                \"data\": {\"foo\" : 1, \"bar\" : 2, \"quux\" : true},\n                \"valid\": true\n            },\n            {\n                \"description\": \"an additional invalid property is invalid\",\n                \"data\": {\"foo\" : 1, \"bar\" : 2, \"quux\" : 12},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\":\n            \"additionalProperties can exist by itself\",\n        \"schema\": {\n            \"additionalProperties\": {\"type\": \"boolean\"}\n        },\n        \"tests\": [\n            {\n                \"description\": \"an additional valid property is valid\",\n                \"data\": {\"foo\" : true},\n                \"valid\": true\n            },\n            {\n                \"description\": \"an additional invalid property is invalid\",\n                \"data\": {\"foo\" : 1},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"additionalProperties are allowed by default\",\n        \"schema\": {\"properties\": {\"foo\": {}, \"bar\": {}}},\n        \"tests\": [\n            {\n                \"description\": \"additional properties are allowed\",\n                \"data\": {\"foo\": 1, \"bar\": 2, \"quux\": true},\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"additionalProperties should not look in applicators\",\n        \"schema\": {\n            \"allOf\": [\n                {\"properties\": {\"foo\": {}}}\n            ],\n            \"additionalProperties\": {\"type\": \"boolean\"}\n        },\n        \"tests\": [\n            {\n                \"description\": \"properties defined in allOf are not examined\",\n                \"data\": {\"foo\": 1, \"bar\": true},\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/allOf.json",
    "content": "[\n    {\n        \"description\": \"allOf\",\n        \"schema\": {\n            \"allOf\": [\n                {\n                    \"properties\": {\n                        \"bar\": {\"type\": \"integer\"}\n                    },\n                    \"required\": [\"bar\"]\n                },\n                {\n                    \"properties\": {\n                        \"foo\": {\"type\": \"string\"}\n                    },\n                    \"required\": [\"foo\"]\n                }\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"allOf\",\n                \"data\": {\"foo\": \"baz\", \"bar\": 2},\n                \"valid\": true\n            },\n            {\n                \"description\": \"mismatch second\",\n                \"data\": {\"foo\": \"baz\"},\n                \"valid\": false\n            },\n            {\n                \"description\": \"mismatch first\",\n                \"data\": {\"bar\": 2},\n                \"valid\": false\n            },\n            {\n                \"description\": \"wrong type\",\n                \"data\": {\"foo\": \"baz\", \"bar\": \"quux\"},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"allOf with base schema\",\n        \"schema\": {\n            \"properties\": {\"bar\": {\"type\": \"integer\"}},\n            \"required\": [\"bar\"],\n            \"allOf\" : [\n                {\n                    \"properties\": {\n                        \"foo\": {\"type\": \"string\"}\n                    },\n                    \"required\": [\"foo\"]\n                },\n                {\n                    \"properties\": {\n                        \"baz\": {\"type\": \"null\"}\n                    },\n                    \"required\": [\"baz\"]\n                }\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"valid\",\n                \"data\": {\"foo\": \"quux\", \"bar\": 2, \"baz\": null},\n                \"valid\": true\n            },\n            {\n                \"description\": \"mismatch base schema\",\n                \"data\": {\"foo\": \"quux\", \"baz\": null},\n                \"valid\": false\n            },\n            {\n                \"description\": \"mismatch first allOf\",\n                \"data\": {\"bar\": 2, \"baz\": null},\n                \"valid\": false\n            },\n            {\n                \"description\": \"mismatch second allOf\",\n                \"data\": {\"foo\": \"quux\", \"bar\": 2},\n                \"valid\": false\n            },\n            {\n                \"description\": \"mismatch both\",\n                \"data\": {\"bar\": 2},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"allOf simple types\",\n        \"schema\": {\n            \"allOf\": [\n                {\"maximum\": 30},\n                {\"minimum\": 20}\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"valid\",\n                \"data\": 25,\n                \"valid\": true\n            },\n            {\n                \"description\": \"mismatch one\",\n                \"data\": 35,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"allOf with boolean schemas, all true\",\n        \"schema\": {\"allOf\": [true, true]},\n        \"tests\": [\n            {\n                \"description\": \"any value is valid\",\n                \"data\": \"foo\",\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"allOf with boolean schemas, some false\",\n        \"schema\": {\"allOf\": [true, false]},\n        \"tests\": [\n            {\n                \"description\": \"any value is invalid\",\n                \"data\": \"foo\",\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"allOf with boolean schemas, all false\",\n        \"schema\": {\"allOf\": [false, false]},\n        \"tests\": [\n            {\n                \"description\": \"any value is invalid\",\n                \"data\": \"foo\",\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"allOf with one empty schema\",\n        \"schema\": {\n            \"allOf\": [\n                {}\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"any data is valid\",\n                \"data\": 1,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"allOf with two empty schemas\",\n        \"schema\": {\n            \"allOf\": [\n                {},\n                {}\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"any data is valid\",\n                \"data\": 1,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"allOf with the first empty schema\",\n        \"schema\": {\n            \"allOf\": [\n                {},\n                { \"type\": \"number\" }\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"number is valid\",\n                \"data\": 1,\n                \"valid\": true\n            },\n            {\n                \"description\": \"string is invalid\",\n                \"data\": \"foo\",\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"allOf with the last empty schema\",\n        \"schema\": {\n            \"allOf\": [\n                { \"type\": \"number\" },\n                {}\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"number is valid\",\n                \"data\": 1,\n                \"valid\": true\n            },\n            {\n                \"description\": \"string is invalid\",\n                \"data\": \"foo\",\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"nested allOf, to check validation semantics\",\n        \"schema\": {\n            \"allOf\": [\n                {\n                    \"allOf\": [\n                        {\n                            \"type\": \"null\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"null is valid\",\n                \"data\": null,\n                \"valid\": true\n            },\n            {\n                \"description\": \"anything non-null is invalid\",\n                \"data\": 123,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"allOf combined with anyOf, oneOf\",\n        \"schema\": {\n            \"allOf\": [ { \"multipleOf\": 2 } ],\n            \"anyOf\": [ { \"multipleOf\": 3 } ],\n            \"oneOf\": [ { \"multipleOf\": 5 } ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"allOf: false, anyOf: false, oneOf: false\",\n                \"data\": 1,\n                \"valid\": false\n            },\n            {\n                \"description\": \"allOf: false, anyOf: false, oneOf: true\",\n                \"data\": 5,\n                \"valid\": false\n            },\n            {\n                \"description\": \"allOf: false, anyOf: true, oneOf: false\",\n                \"data\": 3,\n                \"valid\": false\n            },\n            {\n                \"description\": \"allOf: false, anyOf: true, oneOf: true\",\n                \"data\": 15,\n                \"valid\": false\n            },\n            {\n                \"description\": \"allOf: true, anyOf: false, oneOf: false\",\n                \"data\": 2,\n                \"valid\": false\n            },\n            {\n                \"description\": \"allOf: true, anyOf: false, oneOf: true\",\n                \"data\": 10,\n                \"valid\": false\n            },\n            {\n                \"description\": \"allOf: true, anyOf: true, oneOf: false\",\n                \"data\": 6,\n                \"valid\": false\n            },\n            {\n                \"description\": \"allOf: true, anyOf: true, oneOf: true\",\n                \"data\": 30,\n                \"valid\": true\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/anyOf.json",
    "content": "[\n    {\n        \"description\": \"anyOf\",\n        \"schema\": {\n            \"anyOf\": [\n                {\n                    \"type\": \"integer\"\n                },\n                {\n                    \"minimum\": 2\n                }\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"first anyOf valid\",\n                \"data\": 1,\n                \"valid\": true\n            },\n            {\n                \"description\": \"second anyOf valid\",\n                \"data\": 2.5,\n                \"valid\": true\n            },\n            {\n                \"description\": \"both anyOf valid\",\n                \"data\": 3,\n                \"valid\": true\n            },\n            {\n                \"description\": \"neither anyOf valid\",\n                \"data\": 1.5,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"anyOf with base schema\",\n        \"schema\": {\n            \"type\": \"string\",\n            \"anyOf\" : [\n                {\n                    \"maxLength\": 2\n                },\n                {\n                    \"minLength\": 4\n                }\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"mismatch base schema\",\n                \"data\": 3,\n                \"valid\": false\n            },\n            {\n                \"description\": \"one anyOf valid\",\n                \"data\": \"foobar\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"both anyOf invalid\",\n                \"data\": \"foo\",\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"anyOf with boolean schemas, all true\",\n        \"schema\": {\"anyOf\": [true, true]},\n        \"tests\": [\n            {\n                \"description\": \"any value is valid\",\n                \"data\": \"foo\",\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"anyOf with boolean schemas, some true\",\n        \"schema\": {\"anyOf\": [true, false]},\n        \"tests\": [\n            {\n                \"description\": \"any value is valid\",\n                \"data\": \"foo\",\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"anyOf with boolean schemas, all false\",\n        \"schema\": {\"anyOf\": [false, false]},\n        \"tests\": [\n            {\n                \"description\": \"any value is invalid\",\n                \"data\": \"foo\",\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"anyOf complex types\",\n        \"schema\": {\n            \"anyOf\": [\n                {\n                    \"properties\": {\n                        \"bar\": {\"type\": \"integer\"}\n                    },\n                    \"required\": [\"bar\"]\n                },\n                {\n                    \"properties\": {\n                        \"foo\": {\"type\": \"string\"}\n                    },\n                    \"required\": [\"foo\"]\n                }\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"first anyOf valid (complex)\",\n                \"data\": {\"bar\": 2},\n                \"valid\": true\n            },\n            {\n                \"description\": \"second anyOf valid (complex)\",\n                \"data\": {\"foo\": \"baz\"},\n                \"valid\": true\n            },\n            {\n                \"description\": \"both anyOf valid (complex)\",\n                \"data\": {\"foo\": \"baz\", \"bar\": 2},\n                \"valid\": true\n            },\n            {\n                \"description\": \"neither anyOf valid (complex)\",\n                \"data\": {\"foo\": 2, \"bar\": \"quux\"},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"anyOf with one empty schema\",\n        \"schema\": {\n            \"anyOf\": [\n                { \"type\": \"number\" },\n                {}\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"string is valid\",\n                \"data\": \"foo\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"number is valid\",\n                \"data\": 123,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"nested anyOf, to check validation semantics\",\n        \"schema\": {\n            \"anyOf\": [\n                {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"null\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"null is valid\",\n                \"data\": null,\n                \"valid\": true\n            },\n            {\n                \"description\": \"anything non-null is invalid\",\n                \"data\": 123,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"nested anyOf, to check validation semantics\",\n        \"schema\": {\n            \"anyOf\": [\n                {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"null\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"null is valid\",\n                \"data\": null,\n                \"valid\": true\n            },\n            {\n                \"description\": \"anything non-null is invalid\",\n                \"data\": 123,\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/boolean_schema.json",
    "content": "[\n    {\n        \"description\": \"boolean schema 'true'\",\n        \"schema\": true,\n        \"tests\": [\n            {\n                \"description\": \"number is valid\",\n                \"data\": 1,\n                \"valid\": true\n            },\n            {\n                \"description\": \"string is valid\",\n                \"data\": \"foo\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"boolean true is valid\",\n                \"data\": true,\n                \"valid\": true\n            },\n            {\n                \"description\": \"boolean false is valid\",\n                \"data\": false,\n                \"valid\": true\n            },\n            {\n                \"description\": \"null is valid\",\n                \"data\": null,\n                \"valid\": true\n            },\n            {\n                \"description\": \"object is valid\",\n                \"data\": {\"foo\": \"bar\"},\n                \"valid\": true\n            },\n            {\n                \"description\": \"empty object is valid\",\n                \"data\": {},\n                \"valid\": true\n            },\n            {\n                \"description\": \"array is valid\",\n                \"data\": [\"foo\"],\n                \"valid\": true\n            },\n            {\n                \"description\": \"empty array is valid\",\n                \"data\": [],\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"boolean schema 'false'\",\n        \"schema\": false,\n        \"tests\": [\n            {\n                \"description\": \"number is invalid\",\n                \"data\": 1,\n                \"valid\": false\n            },\n            {\n                \"description\": \"string is invalid\",\n                \"data\": \"foo\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"boolean true is invalid\",\n                \"data\": true,\n                \"valid\": false\n            },\n            {\n                \"description\": \"boolean false is invalid\",\n                \"data\": false,\n                \"valid\": false\n            },\n            {\n                \"description\": \"null is invalid\",\n                \"data\": null,\n                \"valid\": false\n            },\n            {\n                \"description\": \"object is invalid\",\n                \"data\": {\"foo\": \"bar\"},\n                \"valid\": false\n            },\n            {\n                \"description\": \"empty object is invalid\",\n                \"data\": {},\n                \"valid\": false\n            },\n            {\n                \"description\": \"array is invalid\",\n                \"data\": [\"foo\"],\n                \"valid\": false\n            },\n            {\n                \"description\": \"empty array is invalid\",\n                \"data\": [],\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/const.json",
    "content": "[\n    {\n        \"description\": \"const validation\",\n        \"schema\": {\"const\": 2},\n        \"tests\": [\n            {\n                \"description\": \"same value is valid\",\n                \"data\": 2,\n                \"valid\": true\n            },\n            {\n                \"description\": \"another value is invalid\",\n                \"data\": 5,\n                \"valid\": false\n            },\n            {\n                \"description\": \"another type is invalid\",\n                \"data\": \"a\",\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"const with object\",\n        \"schema\": {\"const\": {\"foo\": \"bar\", \"baz\": \"bax\"}},\n        \"tests\": [\n            {\n                \"description\": \"same object is valid\",\n                \"data\": {\"foo\": \"bar\", \"baz\": \"bax\"},\n                \"valid\": true\n            },\n            {\n                \"description\": \"same object with different property order is valid\",\n                \"data\": {\"baz\": \"bax\", \"foo\": \"bar\"},\n                \"valid\": true\n            },\n            {\n                \"description\": \"another object is invalid\",\n                \"data\": {\"foo\": \"bar\"},\n                \"valid\": false\n            },\n            {\n                \"description\": \"another type is invalid\",\n                \"data\": [1, 2],\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"const with array\",\n        \"schema\": {\"const\": [{ \"foo\": \"bar\" }]},\n        \"tests\": [\n            {\n                \"description\": \"same array is valid\",\n                \"data\": [{\"foo\": \"bar\"}],\n                \"valid\": true\n            },\n            {\n                \"description\": \"another array item is invalid\",\n                \"data\": [2],\n                \"valid\": false\n            },\n            {\n                \"description\": \"array with additional items is invalid\",\n                \"data\": [1, 2, 3],\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"const with null\",\n        \"schema\": {\"const\": null},\n        \"tests\": [\n            {\n                \"description\": \"null is valid\",\n                \"data\": null,\n                \"valid\": true\n            },\n            {\n                \"description\": \"not null is invalid\",\n                \"data\": 0,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"const with false does not match 0\",\n        \"schema\": {\"const\": false},\n        \"tests\": [\n            {\n                \"description\": \"false is valid\",\n                \"data\": false,\n                \"valid\": true\n            },\n            {\n                \"description\": \"integer zero is invalid\",\n                \"data\": 0,\n                \"valid\": false\n            },\n            {\n                \"description\": \"float zero is invalid\",\n                \"data\": 0.0,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"const with true does not match 1\",\n        \"schema\": {\"const\": true},\n        \"tests\": [\n            {\n                \"description\": \"true is valid\",\n                \"data\": true,\n                \"valid\": true\n            },\n            {\n                \"description\": \"integer one is invalid\",\n                \"data\": 1,\n                \"valid\": false\n            },\n            {\n                \"description\": \"float one is invalid\",\n                \"data\": 1.0,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"const with [false] does not match [0]\",\n        \"schema\": {\"const\": [false]},\n        \"tests\": [\n            {\n                \"description\": \"[false] is valid\",\n                \"data\": [false],\n                \"valid\": true\n            },\n            {\n                \"description\": \"[0] is invalid\",\n                \"data\": [0],\n                \"valid\": false\n            },\n            {\n                \"description\": \"[0.0] is invalid\",\n                \"data\": [0.0],\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"const with [true] does not match [1]\",\n        \"schema\": {\"const\": [true]},\n        \"tests\": [\n            {\n                \"description\": \"[true] is valid\",\n                \"data\": [true],\n                \"valid\": true\n            },\n            {\n                \"description\": \"[1] is invalid\",\n                \"data\": [1],\n                \"valid\": false\n            },\n            {\n                \"description\": \"[1.0] is invalid\",\n                \"data\": [1.0],\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"const with {\\\"a\\\": false} does not match {\\\"a\\\": 0}\",\n        \"schema\": {\"const\": {\"a\": false}},\n        \"tests\": [\n            {\n                \"description\": \"{\\\"a\\\": false} is valid\",\n                \"data\": {\"a\": false},\n                \"valid\": true\n            },\n            {\n                \"description\": \"{\\\"a\\\": 0} is invalid\",\n                \"data\": {\"a\": 0},\n                \"valid\": false\n            },\n            {\n                \"description\": \"{\\\"a\\\": 0.0} is invalid\",\n                \"data\": {\"a\": 0.0},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"const with {\\\"a\\\": true} does not match {\\\"a\\\": 1}\",\n        \"schema\": {\"const\": {\"a\": true}},\n        \"tests\": [\n            {\n                \"description\": \"{\\\"a\\\": true} is valid\",\n                \"data\": {\"a\": true},\n                \"valid\": true\n            },\n            {\n                \"description\": \"{\\\"a\\\": 1} is invalid\",\n                \"data\": {\"a\": 1},\n                \"valid\": false\n            },\n            {\n                \"description\": \"{\\\"a\\\": 1.0} is invalid\",\n                \"data\": {\"a\": 1.0},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"const with 0 does not match other zero-like types\",\n        \"schema\": {\"const\": 0},\n        \"tests\": [\n            {\n                \"description\": \"false is invalid\",\n                \"data\": false,\n                \"valid\": false\n            },\n            {\n                \"description\": \"integer zero is valid\",\n                \"data\": 0,\n                \"valid\": true\n            },\n            {\n                \"description\": \"float zero is valid\",\n                \"data\": 0.0,\n                \"valid\": true\n            },\n            {\n                \"description\": \"empty object is invalid\",\n                \"data\": {},\n                \"valid\": false\n            },\n            {\n                \"description\": \"empty array is invalid\",\n                \"data\": [],\n                \"valid\": false\n            },\n            {\n                \"description\": \"empty string is invalid\",\n                \"data\": \"\",\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"const with 1 does not match true\",\n        \"schema\": {\"const\": 1},\n        \"tests\": [\n            {\n                \"description\": \"true is invalid\",\n                \"data\": true,\n                \"valid\": false\n            },\n            {\n                \"description\": \"integer one is valid\",\n                \"data\": 1,\n                \"valid\": true\n            },\n            {\n                \"description\": \"float one is valid\",\n                \"data\": 1.0,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"const with -2.0 matches integer and float types\",\n        \"schema\": {\"const\": -2.0},\n        \"tests\": [\n            {\n                \"description\": \"integer -2 is valid\",\n                \"data\": -2,\n                \"valid\": true\n            },\n            {\n                \"description\": \"integer 2 is invalid\",\n                \"data\": 2,\n                \"valid\": false\n            },\n            {\n                \"description\": \"float -2.0 is valid\",\n                \"data\": -2.0,\n                \"valid\": true\n            },\n            {\n                \"description\": \"float 2.0 is invalid\",\n                \"data\": 2.0,\n                \"valid\": false\n            },\n            {\n                \"description\": \"float -2.00001 is invalid\",\n                \"data\": -2.00001,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"float and integers are equal up to 64-bit representation limits\",\n        \"schema\": {\"const\": 9007199254740992},\n        \"tests\": [\n            {\n                \"description\": \"integer is valid\",\n                \"data\": 9007199254740992,\n                \"valid\": true\n            },\n            {\n                \"description\": \"integer minus one is invalid\",\n                \"data\": 9007199254740991,\n                \"valid\": false\n            },\n            {\n                \"description\": \"float is valid\",\n                \"data\": 9007199254740992.0,\n                \"valid\": true\n            },\n            {\n                \"description\": \"float minus one is invalid\",\n                \"data\": 9007199254740991.0,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"nul characters in strings\",\n        \"schema\": { \"const\": \"hello\\u0000there\" },\n        \"tests\": [\n            {\n                \"description\": \"match string with nul\",\n                \"data\": \"hello\\u0000there\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"do not match string lacking nul\",\n                \"data\": \"hellothere\",\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/contains.json",
    "content": "[\n    {\n        \"description\": \"contains keyword validation\",\n        \"schema\": {\n            \"contains\": {\"minimum\": 5}\n        },\n        \"tests\": [\n            {\n                \"description\": \"array with item matching schema (5) is valid\",\n                \"data\": [3, 4, 5],\n                \"valid\": true\n            },\n            {\n                \"description\": \"array with item matching schema (6) is valid\",\n                \"data\": [3, 4, 6],\n                \"valid\": true\n            },\n            {\n                \"description\": \"array with two items matching schema (5, 6) is valid\",\n                \"data\": [3, 4, 5, 6],\n                \"valid\": true\n            },\n            {\n                \"description\": \"array without items matching schema is invalid\",\n                \"data\": [2, 3, 4],\n                \"valid\": false\n            },\n            {\n                \"description\": \"empty array is invalid\",\n                \"data\": [],\n                \"valid\": false\n            },\n            {\n                \"description\": \"not array is valid\",\n                \"data\": {},\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"contains keyword with const keyword\",\n        \"schema\": {\n            \"contains\": { \"const\": 5 }\n        },\n        \"tests\": [\n            {\n                \"description\": \"array with item 5 is valid\",\n                \"data\": [3, 4, 5],\n                \"valid\": true\n            },\n            {\n                \"description\": \"array with two items 5 is valid\",\n                \"data\": [3, 4, 5, 5],\n                \"valid\": true\n            },\n            {\n                \"description\": \"array without item 5 is invalid\",\n                \"data\": [1, 2, 3, 4],\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"contains keyword with boolean schema true\",\n        \"schema\": {\"contains\": true},\n        \"tests\": [\n            {\n                \"description\": \"any non-empty array is valid\",\n                \"data\": [\"foo\"],\n                \"valid\": true\n            },\n            {\n                \"description\": \"empty array is invalid\",\n                \"data\": [],\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"contains keyword with boolean schema false\",\n        \"schema\": {\"contains\": false},\n        \"tests\": [\n            {\n                \"description\": \"any non-empty array is invalid\",\n                \"data\": [\"foo\"],\n                \"valid\": false\n            },\n            {\n                \"description\": \"empty array is invalid\",\n                \"data\": [],\n                \"valid\": false\n            },\n            {\n                \"description\": \"non-arrays are valid\",\n                \"data\": \"contains does not apply to strings\",\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"items + contains\",\n        \"schema\": {\n            \"items\": { \"multipleOf\": 2 },\n            \"contains\": { \"multipleOf\": 3 }\n        },\n        \"tests\": [\n            {\n                \"description\": \"matches items, does not match contains\",\n                \"data\": [ 2, 4, 8 ],\n                \"valid\": false\n            },\n            {\n                \"description\": \"does not match items, matches contains\",\n                \"data\": [ 3, 6, 9 ],\n                \"valid\": false\n            },\n            {\n                \"description\": \"matches both items and contains\",\n                \"data\": [ 6, 12 ],\n                \"valid\": true\n            },\n            {\n                \"description\": \"matches neither items nor contains\",\n                \"data\": [ 1, 5 ],\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"contains with false if subschema\",\n        \"schema\": {\n            \"contains\": {\n                \"if\": false,\n                \"else\": true\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"any non-empty array is valid\",\n                \"data\": [\"foo\"],\n                \"valid\": true\n            },\n            {\n                \"description\": \"empty array is invalid\",\n                \"data\": [],\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/default.json",
    "content": "[\n    {\n        \"description\": \"invalid type for default\",\n        \"schema\": {\n            \"properties\": {\n                \"foo\": {\n                    \"type\": \"integer\",\n                    \"default\": []\n                }\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"valid when property is specified\",\n                \"data\": {\"foo\": 13},\n                \"valid\": true\n            },\n            {\n                \"description\": \"still valid when the invalid default is used\",\n                \"data\": {},\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"invalid string value for default\",\n        \"schema\": {\n            \"properties\": {\n                \"bar\": {\n                    \"type\": \"string\",\n                    \"minLength\": 4,\n                    \"default\": \"bad\"\n                }\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"valid when property is specified\",\n                \"data\": {\"bar\": \"good\"},\n                \"valid\": true\n            },\n            {\n                \"description\": \"still valid when the invalid default is used\",\n                \"data\": {},\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"the default keyword does not do anything if the property is missing\",\n        \"schema\": {\n            \"type\": \"object\",\n            \"properties\": {\n                \"alpha\": {\n                    \"type\": \"number\",\n                    \"maximum\": 3,\n                    \"default\": 5\n                }\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"an explicit property value is checked against maximum (passing)\",\n                \"data\": { \"alpha\": 1 },\n                \"valid\": true\n            },\n            {\n                \"description\": \"an explicit property value is checked against maximum (failing)\",\n                \"data\": { \"alpha\": 5 },\n                \"valid\": false\n            },\n            {\n                \"description\": \"missing properties are not filled in with the default\",\n                \"data\": {},\n                \"valid\": true\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/definitions.json",
    "content": "[\n    {\n        \"description\": \"validate definition against metaschema\",\n        \"schema\": {\"$ref\": \"http://json-schema.org/draft-07/schema#\"},\n        \"tests\": [\n            {\n                \"description\": \"valid definition schema\",\n                \"data\": {\n                    \"definitions\": {\n                        \"foo\": {\"type\": \"integer\"}\n                    }\n                },\n                \"valid\": true\n            },\n            {\n                \"description\": \"invalid definition schema\",\n                \"data\": {\n                    \"definitions\": {\n                        \"foo\": {\"type\": 1}\n                    }\n                },\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/dependencies.json",
    "content": "[\n    {\n        \"description\": \"dependencies\",\n        \"schema\": {\n            \"dependencies\": {\"bar\": [\"foo\"]}\n        },\n        \"tests\": [\n            {\n                \"description\": \"neither\",\n                \"data\": {},\n                \"valid\": true\n            },\n            {\n                \"description\": \"nondependant\",\n                \"data\": {\"foo\": 1},\n                \"valid\": true\n            },\n            {\n                \"description\": \"with dependency\",\n                \"data\": {\"foo\": 1, \"bar\": 2},\n                \"valid\": true\n            },\n            {\n                \"description\": \"missing dependency\",\n                \"data\": {\"bar\": 2},\n                \"valid\": false\n            },\n            {\n                \"description\": \"ignores arrays\",\n                \"data\": [\"bar\"],\n                \"valid\": true\n            },\n            {\n                \"description\": \"ignores strings\",\n                \"data\": \"foobar\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"ignores other non-objects\",\n                \"data\": 12,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"dependencies with empty array\",\n        \"schema\": {\n            \"dependencies\": {\"bar\": []}\n        },\n        \"tests\": [\n            {\n                \"description\": \"empty object\",\n                \"data\": {},\n                \"valid\": true\n            },\n            {\n                \"description\": \"object with one property\",\n                \"data\": {\"bar\": 2},\n                \"valid\": true\n            },\n            {\n                \"description\": \"non-object is valid\",\n                \"data\": 1,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"multiple dependencies\",\n        \"schema\": {\n            \"dependencies\": {\"quux\": [\"foo\", \"bar\"]}\n        },\n        \"tests\": [\n            {\n                \"description\": \"neither\",\n                \"data\": {},\n                \"valid\": true\n            },\n            {\n                \"description\": \"nondependants\",\n                \"data\": {\"foo\": 1, \"bar\": 2},\n                \"valid\": true\n            },\n            {\n                \"description\": \"with dependencies\",\n                \"data\": {\"foo\": 1, \"bar\": 2, \"quux\": 3},\n                \"valid\": true\n            },\n            {\n                \"description\": \"missing dependency\",\n                \"data\": {\"foo\": 1, \"quux\": 2},\n                \"valid\": false\n            },\n            {\n                \"description\": \"missing other dependency\",\n                \"data\": {\"bar\": 1, \"quux\": 2},\n                \"valid\": false\n            },\n            {\n                \"description\": \"missing both dependencies\",\n                \"data\": {\"quux\": 1},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"multiple dependencies subschema\",\n        \"schema\": {\n            \"dependencies\": {\n                \"bar\": {\n                    \"properties\": {\n                        \"foo\": {\"type\": \"integer\"},\n                        \"bar\": {\"type\": \"integer\"}\n                    }\n                }\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"valid\",\n                \"data\": {\"foo\": 1, \"bar\": 2},\n                \"valid\": true\n            },\n            {\n                \"description\": \"no dependency\",\n                \"data\": {\"foo\": \"quux\"},\n                \"valid\": true\n            },\n            {\n                \"description\": \"wrong type\",\n                \"data\": {\"foo\": \"quux\", \"bar\": 2},\n                \"valid\": false\n            },\n            {\n                \"description\": \"wrong type other\",\n                \"data\": {\"foo\": 2, \"bar\": \"quux\"},\n                \"valid\": false\n            },\n            {\n                \"description\": \"wrong type both\",\n                \"data\": {\"foo\": \"quux\", \"bar\": \"quux\"},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"dependencies with boolean subschemas\",\n        \"schema\": {\n            \"dependencies\": {\n                \"foo\": true,\n                \"bar\": false\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"object with property having schema true is valid\",\n                \"data\": {\"foo\": 1},\n                \"valid\": true\n            },\n            {\n                \"description\": \"object with property having schema false is invalid\",\n                \"data\": {\"bar\": 2},\n                \"valid\": false\n            },\n            {\n                \"description\": \"object with both properties is invalid\",\n                \"data\": {\"foo\": 1, \"bar\": 2},\n                \"valid\": false\n            },\n            {\n                \"description\": \"empty object is valid\",\n                \"data\": {},\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"dependencies with escaped characters\",\n        \"schema\": {\n            \"dependencies\": {\n                \"foo\\nbar\": [\"foo\\rbar\"],\n                \"foo\\tbar\": {\n                    \"minProperties\": 4\n                },\n                \"foo'bar\": {\"required\": [\"foo\\\"bar\"]},\n                \"foo\\\"bar\": [\"foo'bar\"]\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"valid object 1\",\n                \"data\": {\n                    \"foo\\nbar\": 1,\n                    \"foo\\rbar\": 2\n                },\n                \"valid\": true\n            },\n            {\n                \"description\": \"valid object 2\",\n                \"data\": {\n                    \"foo\\tbar\": 1,\n                    \"a\": 2,\n                    \"b\": 3,\n                    \"c\": 4\n                },\n                \"valid\": true\n            },\n            {\n                \"description\": \"valid object 3\",\n                \"data\": {\n                    \"foo'bar\": 1,\n                    \"foo\\\"bar\": 2\n                },\n                \"valid\": true\n            },\n            {\n                \"description\": \"invalid object 1\",\n                \"data\": {\n                    \"foo\\nbar\": 1,\n                    \"foo\": 2\n                },\n                \"valid\": false\n            },\n            {\n                \"description\": \"invalid object 2\",\n                \"data\": {\n                    \"foo\\tbar\": 1,\n                    \"a\": 2\n                },\n                \"valid\": false\n            },\n            {\n                \"description\": \"invalid object 3\",\n                \"data\": {\n                    \"foo'bar\": 1\n                },\n                \"valid\": false\n            },\n            {\n                \"description\": \"invalid object 4\",\n                \"data\": {\n                    \"foo\\\"bar\": 2\n                },\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/enum.json",
    "content": "[\n    {\n        \"description\": \"simple enum validation\",\n        \"schema\": {\"enum\": [1, 2, 3]},\n        \"tests\": [\n            {\n                \"description\": \"one of the enum is valid\",\n                \"data\": 1,\n                \"valid\": true\n            },\n            {\n                \"description\": \"something else is invalid\",\n                \"data\": 4,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"heterogeneous enum validation\",\n        \"schema\": {\"enum\": [6, \"foo\", [], true, {\"foo\": 12}]},\n        \"tests\": [\n            {\n                \"description\": \"one of the enum is valid\",\n                \"data\": [],\n                \"valid\": true\n            },\n            {\n                \"description\": \"something else is invalid\",\n                \"data\": null,\n                \"valid\": false\n            },\n            {\n                \"description\": \"objects are deep compared\",\n                \"data\": {\"foo\": false},\n                \"valid\": false\n            },\n            {\n                \"description\": \"valid object matches\",\n                \"data\": {\"foo\": 12},\n                \"valid\": true\n            },\n            {\n                \"description\": \"extra properties in object is invalid\",\n                \"data\": {\"foo\": 12, \"boo\": 42},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"heterogeneous enum-with-null validation\",\n        \"schema\": { \"enum\": [6, null] },\n        \"tests\": [\n            {\n                \"description\": \"null is valid\",\n                \"data\": null,\n                \"valid\": true\n            },\n            {\n                \"description\": \"number is valid\",\n                \"data\": 6,\n                \"valid\": true\n            },\n            {\n                \"description\": \"something else is invalid\",\n                \"data\": \"test\",\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"enums in properties\",\n        \"schema\": {\n            \"type\":\"object\",\n            \"properties\": {\n                \"foo\": {\"enum\":[\"foo\"]},\n                \"bar\": {\"enum\":[\"bar\"]}\n            },\n            \"required\": [\"bar\"]\n        },\n        \"tests\": [\n            {\n                \"description\": \"both properties are valid\",\n                \"data\": {\"foo\":\"foo\", \"bar\":\"bar\"},\n                \"valid\": true\n            },\n            {\n                \"description\": \"wrong foo value\",\n                \"data\": {\"foo\":\"foot\", \"bar\":\"bar\"},\n                \"valid\": false\n            },\n            {\n                \"description\": \"wrong bar value\",\n                \"data\": {\"foo\":\"foo\", \"bar\":\"bart\"},\n                \"valid\": false\n            },\n            {\n                \"description\": \"missing optional property is valid\",\n                \"data\": {\"bar\":\"bar\"},\n                \"valid\": true\n            },\n            {\n                \"description\": \"missing required property is invalid\",\n                \"data\": {\"foo\":\"foo\"},\n                \"valid\": false\n            },\n            {\n                \"description\": \"missing all properties is invalid\",\n                \"data\": {},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"enum with escaped characters\",\n        \"schema\": {\n            \"enum\": [\"foo\\nbar\", \"foo\\rbar\"]\n        },\n        \"tests\": [\n            {\n                \"description\": \"member 1 is valid\",\n                \"data\": \"foo\\nbar\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"member 2 is valid\",\n                \"data\": \"foo\\rbar\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"another string is invalid\",\n                \"data\": \"abc\",\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"enum with false does not match 0\",\n        \"schema\": {\"enum\": [false]},\n        \"tests\": [\n            {\n                \"description\": \"false is valid\",\n                \"data\": false,\n                \"valid\": true\n            },\n            {\n                \"description\": \"integer zero is invalid\",\n                \"data\": 0,\n                \"valid\": false\n            },\n            {\n                \"description\": \"float zero is invalid\",\n                \"data\": 0.0,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"enum with true does not match 1\",\n        \"schema\": {\"enum\": [true]},\n        \"tests\": [\n            {\n                \"description\": \"true is valid\",\n                \"data\": true,\n                \"valid\": true\n            },\n            {\n                \"description\": \"integer one is invalid\",\n                \"data\": 1,\n                \"valid\": false\n            },\n            {\n                \"description\": \"float one is invalid\",\n                \"data\": 1.0,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"enum with 0 does not match false\",\n        \"schema\": {\"enum\": [0]},\n        \"tests\": [\n            {\n                \"description\": \"false is invalid\",\n                \"data\": false,\n                \"valid\": false\n            },\n            {\n                \"description\": \"integer zero is valid\",\n                \"data\": 0,\n                \"valid\": true\n            },\n            {\n                \"description\": \"float zero is valid\",\n                \"data\": 0.0,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"enum with 1 does not match true\",\n        \"schema\": {\"enum\": [1]},\n        \"tests\": [\n            {\n                \"description\": \"true is invalid\",\n                \"data\": true,\n                \"valid\": false\n            },\n            {\n                \"description\": \"integer one is valid\",\n                \"data\": 1,\n                \"valid\": true\n            },\n            {\n                \"description\": \"float one is valid\",\n                \"data\": 1.0,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"nul characters in strings\",\n        \"schema\": { \"enum\": [ \"hello\\u0000there\" ] },\n        \"tests\": [\n            {\n                \"description\": \"match string with nul\",\n                \"data\": \"hello\\u0000there\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"do not match string lacking nul\",\n                \"data\": \"hellothere\",\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/exclusiveMaximum.json",
    "content": "[\n    {\n        \"description\": \"exclusiveMaximum validation\",\n        \"schema\": {\n            \"exclusiveMaximum\": 3.0\n        },\n        \"tests\": [\n            {\n                \"description\": \"below the exclusiveMaximum is valid\",\n                \"data\": 2.2,\n                \"valid\": true\n            },\n            {\n                \"description\": \"boundary point is invalid\",\n                \"data\": 3.0,\n                \"valid\": false\n            },\n            {\n                \"description\": \"above the exclusiveMaximum is invalid\",\n                \"data\": 3.5,\n                \"valid\": false\n            },\n            {\n                \"description\": \"ignores non-numbers\",\n                \"data\": \"x\",\n                \"valid\": true\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/exclusiveMinimum.json",
    "content": "[\n    {\n        \"description\": \"exclusiveMinimum validation\",\n        \"schema\": {\n            \"exclusiveMinimum\": 1.1\n        },\n        \"tests\": [\n            {\n                \"description\": \"above the exclusiveMinimum is valid\",\n                \"data\": 1.2,\n                \"valid\": true\n            },\n            {\n                \"description\": \"boundary point is invalid\",\n                \"data\": 1.1,\n                \"valid\": false\n            },\n            {\n                \"description\": \"below the exclusiveMinimum is invalid\",\n                \"data\": 0.6,\n                \"valid\": false\n            },\n            {\n                \"description\": \"ignores non-numbers\",\n                \"data\": \"x\",\n                \"valid\": true\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/format.json",
    "content": "[\n    {\n        \"description\": \"email format\",\n        \"schema\": { \"format\": \"email\" },\n        \"tests\": [\n            {\n                \"description\": \"all string formats ignore integers\",\n                \"data\": 12,\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore floats\",\n                \"data\": 13.7,\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore objects\",\n                \"data\": {},\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore arrays\",\n                \"data\": [],\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore booleans\",\n                \"data\": false,\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore nulls\",\n                \"data\": null,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"idn-email format\",\n        \"schema\": { \"format\": \"idn-email\" },\n        \"tests\": [\n            {\n                \"description\": \"all string formats ignore integers\",\n                \"data\": 12,\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore floats\",\n                \"data\": 13.7,\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore objects\",\n                \"data\": {},\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore arrays\",\n                \"data\": [],\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore booleans\",\n                \"data\": false,\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore nulls\",\n                \"data\": null,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"regex format\",\n        \"schema\": { \"format\": \"regex\" },\n        \"tests\": [\n            {\n                \"description\": \"all string formats ignore integers\",\n                \"data\": 12,\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore floats\",\n                \"data\": 13.7,\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore objects\",\n                \"data\": {},\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore arrays\",\n                \"data\": [],\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore booleans\",\n                \"data\": false,\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore nulls\",\n                \"data\": null,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"ipv4 format\",\n        \"schema\": { \"format\": \"ipv4\" },\n        \"tests\": [\n            {\n                \"description\": \"all string formats ignore integers\",\n                \"data\": 12,\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore floats\",\n                \"data\": 13.7,\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore objects\",\n                \"data\": {},\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore arrays\",\n                \"data\": [],\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore booleans\",\n                \"data\": false,\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore nulls\",\n                \"data\": null,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"ipv6 format\",\n        \"schema\": { \"format\": \"ipv6\" },\n        \"tests\": [\n            {\n                \"description\": \"all string formats ignore integers\",\n                \"data\": 12,\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore floats\",\n                \"data\": 13.7,\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore objects\",\n                \"data\": {},\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore arrays\",\n                \"data\": [],\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore booleans\",\n                \"data\": false,\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore nulls\",\n                \"data\": null,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"idn-hostname format\",\n        \"schema\": { \"format\": \"idn-hostname\" },\n        \"tests\": [\n            {\n                \"description\": \"all string formats ignore integers\",\n                \"data\": 12,\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore floats\",\n                \"data\": 13.7,\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore objects\",\n                \"data\": {},\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore arrays\",\n                \"data\": [],\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore booleans\",\n                \"data\": false,\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore nulls\",\n                \"data\": null,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"hostname format\",\n        \"schema\": { \"format\": \"hostname\" },\n        \"tests\": [\n            {\n                \"description\": \"all string formats ignore integers\",\n                \"data\": 12,\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore floats\",\n                \"data\": 13.7,\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore objects\",\n                \"data\": {},\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore arrays\",\n                \"data\": [],\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore booleans\",\n                \"data\": false,\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore nulls\",\n                \"data\": null,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"date format\",\n        \"schema\": { \"format\": \"date\" },\n        \"tests\": [\n            {\n                \"description\": \"all string formats ignore integers\",\n                \"data\": 12,\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore floats\",\n                \"data\": 13.7,\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore objects\",\n                \"data\": {},\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore arrays\",\n                \"data\": [],\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore booleans\",\n                \"data\": false,\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore nulls\",\n                \"data\": null,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"date-time format\",\n        \"schema\": { \"format\": \"date-time\" },\n        \"tests\": [\n            {\n                \"description\": \"all string formats ignore integers\",\n                \"data\": 12,\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore floats\",\n                \"data\": 13.7,\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore objects\",\n                \"data\": {},\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore arrays\",\n                \"data\": [],\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore booleans\",\n                \"data\": false,\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore nulls\",\n                \"data\": null,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"time format\",\n        \"schema\": { \"format\": \"time\" },\n        \"tests\": [\n            {\n                \"description\": \"all string formats ignore integers\",\n                \"data\": 12,\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore floats\",\n                \"data\": 13.7,\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore objects\",\n                \"data\": {},\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore arrays\",\n                \"data\": [],\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore booleans\",\n                \"data\": false,\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore nulls\",\n                \"data\": null,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"json-pointer format\",\n        \"schema\": { \"format\": \"json-pointer\" },\n        \"tests\": [\n            {\n                \"description\": \"all string formats ignore integers\",\n                \"data\": 12,\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore floats\",\n                \"data\": 13.7,\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore objects\",\n                \"data\": {},\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore arrays\",\n                \"data\": [],\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore booleans\",\n                \"data\": false,\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore nulls\",\n                \"data\": null,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"relative-json-pointer format\",\n        \"schema\": { \"format\": \"relative-json-pointer\" },\n        \"tests\": [\n            {\n                \"description\": \"all string formats ignore integers\",\n                \"data\": 12,\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore floats\",\n                \"data\": 13.7,\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore objects\",\n                \"data\": {},\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore arrays\",\n                \"data\": [],\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore booleans\",\n                \"data\": false,\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore nulls\",\n                \"data\": null,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"iri format\",\n        \"schema\": { \"format\": \"iri\" },\n        \"tests\": [\n            {\n                \"description\": \"all string formats ignore integers\",\n                \"data\": 12,\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore floats\",\n                \"data\": 13.7,\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore objects\",\n                \"data\": {},\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore arrays\",\n                \"data\": [],\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore booleans\",\n                \"data\": false,\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore nulls\",\n                \"data\": null,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"iri-reference format\",\n        \"schema\": { \"format\": \"iri-reference\" },\n        \"tests\": [\n            {\n                \"description\": \"all string formats ignore integers\",\n                \"data\": 12,\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore floats\",\n                \"data\": 13.7,\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore objects\",\n                \"data\": {},\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore arrays\",\n                \"data\": [],\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore booleans\",\n                \"data\": false,\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore nulls\",\n                \"data\": null,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"uri format\",\n        \"schema\": { \"format\": \"uri\" },\n        \"tests\": [\n            {\n                \"description\": \"all string formats ignore integers\",\n                \"data\": 12,\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore floats\",\n                \"data\": 13.7,\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore objects\",\n                \"data\": {},\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore arrays\",\n                \"data\": [],\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore booleans\",\n                \"data\": false,\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore nulls\",\n                \"data\": null,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"uri-reference format\",\n        \"schema\": { \"format\": \"uri-reference\" },\n        \"tests\": [\n            {\n                \"description\": \"all string formats ignore integers\",\n                \"data\": 12,\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore floats\",\n                \"data\": 13.7,\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore objects\",\n                \"data\": {},\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore arrays\",\n                \"data\": [],\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore booleans\",\n                \"data\": false,\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore nulls\",\n                \"data\": null,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"uri-template format\",\n        \"schema\": { \"format\": \"uri-template\" },\n        \"tests\": [\n            {\n                \"description\": \"all string formats ignore integers\",\n                \"data\": 12,\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore floats\",\n                \"data\": 13.7,\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore objects\",\n                \"data\": {},\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore arrays\",\n                \"data\": [],\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore booleans\",\n                \"data\": false,\n                \"valid\": true\n            },\n            {\n                \"description\": \"all string formats ignore nulls\",\n                \"data\": null,\n                \"valid\": true\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/id.json",
    "content": "[\n    {\n        \"description\": \"id inside an enum is not a real identifier\",\n        \"comment\": \"the implementation must not be confused by an id buried in the enum\",\n        \"schema\": {\n            \"definitions\": {\n                \"id_in_enum\": {\n                    \"enum\": [\n                        {\n                          \"$id\": \"https://localhost:1234/id/my_identifier.json\",\n                          \"type\": \"null\"\n                        }\n                    ]\n                },\n                \"real_id_in_schema\": {\n                    \"$id\": \"https://localhost:1234/id/my_identifier.json\",\n                    \"type\": \"string\"\n                },\n                \"zzz_id_in_const\": {\n                    \"const\": {\n                        \"$id\": \"https://localhost:1234/id/my_identifier.json\",\n                        \"type\": \"null\"\n                    }\n                }\n            },\n            \"anyOf\": [\n                { \"$ref\": \"#/definitions/id_in_enum\" },\n                { \"$ref\": \"https://localhost:1234/id/my_identifier.json\" }\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"exact match to enum, and type matches\",\n                \"data\": {\n                    \"$id\": \"https://localhost:1234/id/my_identifier.json\",\n                    \"type\": \"null\"\n                },\n                \"valid\": true\n            },\n            {\n                \"description\": \"match $ref to id\",\n                \"data\": \"a string to match #/definitions/id_in_enum\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"no match on enum or $ref to id\",\n                \"data\": 1,\n                \"valid\": false\n            }\n        ]\n    }\n\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/if-then-else.json",
    "content": "[\n    {\n        \"description\": \"ignore if without then or else\",\n        \"schema\": {\n            \"if\": {\n                \"const\": 0\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"valid when valid against lone if\",\n                \"data\": 0,\n                \"valid\": true\n            },\n            {\n                \"description\": \"valid when invalid against lone if\",\n                \"data\": \"hello\",\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"ignore then without if\",\n        \"schema\": {\n            \"then\": {\n                \"const\": 0\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"valid when valid against lone then\",\n                \"data\": 0,\n                \"valid\": true\n            },\n            {\n                \"description\": \"valid when invalid against lone then\",\n                \"data\": \"hello\",\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"ignore else without if\",\n        \"schema\": {\n            \"else\": {\n                \"const\": 0\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"valid when valid against lone else\",\n                \"data\": 0,\n                \"valid\": true\n            },\n            {\n                \"description\": \"valid when invalid against lone else\",\n                \"data\": \"hello\",\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"if and then without else\",\n        \"schema\": {\n            \"if\": {\n                \"exclusiveMaximum\": 0\n            },\n            \"then\": {\n                \"minimum\": -10\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"valid through then\",\n                \"data\": -1,\n                \"valid\": true\n            },\n            {\n                \"description\": \"invalid through then\",\n                \"data\": -100,\n                \"valid\": false\n            },\n            {\n                \"description\": \"valid when if test fails\",\n                \"data\": 3,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"if and else without then\",\n        \"schema\": {\n            \"if\": {\n                \"exclusiveMaximum\": 0\n            },\n            \"else\": {\n                \"multipleOf\": 2\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"valid when if test passes\",\n                \"data\": -1,\n                \"valid\": true\n            },\n            {\n                \"description\": \"valid through else\",\n                \"data\": 4,\n                \"valid\": true\n            },\n            {\n                \"description\": \"invalid through else\",\n                \"data\": 3,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"validate against correct branch, then vs else\",\n        \"schema\": {\n            \"if\": {\n                \"exclusiveMaximum\": 0\n            },\n            \"then\": {\n                \"minimum\": -10\n            },\n            \"else\": {\n                \"multipleOf\": 2\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"valid through then\",\n                \"data\": -1,\n                \"valid\": true\n            },\n            {\n                \"description\": \"invalid through then\",\n                \"data\": -100,\n                \"valid\": false\n            },\n            {\n                \"description\": \"valid through else\",\n                \"data\": 4,\n                \"valid\": true\n            },\n            {\n                \"description\": \"invalid through else\",\n                \"data\": 3,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"non-interference across combined schemas\",\n        \"schema\": {\n            \"allOf\": [\n                {\n                    \"if\": {\n                        \"exclusiveMaximum\": 0\n                    }\n                },\n                {\n                    \"then\": {\n                        \"minimum\": -10\n                    }\n                },\n                {\n                    \"else\": {\n                        \"multipleOf\": 2\n                    }\n                }\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"valid, but would have been invalid through then\",\n                \"data\": -100,\n                \"valid\": true\n            },\n            {\n                \"description\": \"valid, but would have been invalid through else\",\n                \"data\": 3,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"if with boolean schema true\",\n        \"schema\": {\n            \"if\": true,\n            \"then\": { \"const\": \"then\" },\n            \"else\": { \"const\": \"else\" }\n        },\n        \"tests\": [\n            {\n                \"description\": \"boolean schema true in if always chooses the then path (valid)\",\n                \"data\": \"then\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"boolean schema true in if always chooses the then path (invalid)\",\n                \"data\": \"else\",\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"if with boolean schema false\",\n        \"schema\": {\n            \"if\": false,\n            \"then\": { \"const\": \"then\" },\n            \"else\": { \"const\": \"else\" }\n        },\n        \"tests\": [\n            {\n                \"description\": \"boolean schema false in if always chooses the else path (invalid)\",\n                \"data\": \"then\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"boolean schema false in if always chooses the else path (valid)\",\n                \"data\": \"else\",\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"if appears at the end when serialized (keyword processing sequence)\",\n        \"schema\": {\n            \"then\": { \"const\": \"yes\" },\n            \"else\": { \"const\": \"other\" },\n            \"if\": { \"maxLength\": 4 }\n        },\n        \"tests\": [\n            {\n                \"description\": \"yes redirects to then and passes\",\n                \"data\": \"yes\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"other redirects to else and passes\",\n                \"data\": \"other\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"no redirects to then and fails\",\n                \"data\": \"no\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"invalid redirects to else and fails\",\n                \"data\": \"invalid\",\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/infinite-loop-detection.json",
    "content": "[\n    {\n        \"description\": \"evaluating the same schema location against the same data location twice is not a sign of an infinite loop\",\n        \"schema\": {\n            \"definitions\": {\n                \"int\": { \"type\": \"integer\" }\n            },\n            \"allOf\": [\n                {\n                    \"properties\": {\n                        \"foo\": {\n                            \"$ref\": \"#/definitions/int\"\n                        }\n                    }\n                },\n                {\n                    \"additionalProperties\": {\n                        \"$ref\": \"#/definitions/int\"\n                    }\n                }\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"passing case\",\n                \"data\": { \"foo\": 1 },\n                \"valid\": true\n            },\n            {\n                \"description\": \"failing case\",\n                \"data\": { \"foo\": \"a string\" },\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/items.json",
    "content": "[\n    {\n        \"description\": \"a schema given for items\",\n        \"schema\": {\n            \"items\": {\"type\": \"integer\"}\n        },\n        \"tests\": [\n            {\n                \"description\": \"valid items\",\n                \"data\": [ 1, 2, 3 ],\n                \"valid\": true\n            },\n            {\n                \"description\": \"wrong type of items\",\n                \"data\": [1, \"x\"],\n                \"valid\": false\n            },\n            {\n                \"description\": \"ignores non-arrays\",\n                \"data\": {\"foo\" : \"bar\"},\n                \"valid\": true\n            },\n            {\n                \"description\": \"JavaScript pseudo-array is valid\",\n                \"data\": {\n                    \"0\": \"invalid\",\n                    \"length\": 1\n                },\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"an array of schemas for items\",\n        \"schema\": {\n            \"items\": [\n                {\"type\": \"integer\"},\n                {\"type\": \"string\"}\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"correct types\",\n                \"data\": [ 1, \"foo\" ],\n                \"valid\": true\n            },\n            {\n                \"description\": \"wrong types\",\n                \"data\": [ \"foo\", 1 ],\n                \"valid\": false\n            },\n            {\n                \"description\": \"incomplete array of items\",\n                \"data\": [ 1 ],\n                \"valid\": true\n            },\n            {\n                \"description\": \"array with additional items\",\n                \"data\": [ 1, \"foo\", true ],\n                \"valid\": true\n            },\n            {\n                \"description\": \"empty array\",\n                \"data\": [ ],\n                \"valid\": true\n            },\n            {\n                \"description\": \"JavaScript pseudo-array is valid\",\n                \"data\": {\n                    \"0\": \"invalid\",\n                    \"1\": \"valid\",\n                    \"length\": 2\n                },\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"items with boolean schema (true)\",\n        \"schema\": {\"items\": true},\n        \"tests\": [\n            {\n                \"description\": \"any array is valid\",\n                \"data\": [ 1, \"foo\", true ],\n                \"valid\": true\n            },\n            {\n                \"description\": \"empty array is valid\",\n                \"data\": [],\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"items with boolean schema (false)\",\n        \"schema\": {\"items\": false},\n        \"tests\": [\n            {\n                \"description\": \"any non-empty array is invalid\",\n                \"data\": [ 1, \"foo\", true ],\n                \"valid\": false\n            },\n            {\n                \"description\": \"empty array is valid\",\n                \"data\": [],\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"items with boolean schemas\",\n        \"schema\": {\n            \"items\": [true, false]\n        },\n        \"tests\": [\n            {\n                \"description\": \"array with one item is valid\",\n                \"data\": [ 1 ],\n                \"valid\": true\n            },\n            {\n                \"description\": \"array with two items is invalid\",\n                \"data\": [ 1, \"foo\" ],\n                \"valid\": false\n            },\n            {\n                \"description\": \"empty array is valid\",\n                \"data\": [],\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"items and subitems\",\n        \"schema\": {\n            \"definitions\": {\n                \"item\": {\n                    \"type\": \"array\",\n                    \"additionalItems\": false,\n                    \"items\": [\n                        { \"$ref\": \"#/definitions/sub-item\" },\n                        { \"$ref\": \"#/definitions/sub-item\" }\n                    ]\n                },\n                \"sub-item\": {\n                    \"type\": \"object\",\n                    \"required\": [\"foo\"]\n                }\n            },\n            \"type\": \"array\",\n            \"additionalItems\": false,\n            \"items\": [\n                { \"$ref\": \"#/definitions/item\" },\n                { \"$ref\": \"#/definitions/item\" },\n                { \"$ref\": \"#/definitions/item\" }\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"valid items\",\n                \"data\": [\n                    [ {\"foo\": null}, {\"foo\": null} ],\n                    [ {\"foo\": null}, {\"foo\": null} ],\n                    [ {\"foo\": null}, {\"foo\": null} ]\n                ],\n                \"valid\": true\n            },\n            {\n                \"description\": \"too many items\",\n                \"data\": [\n                    [ {\"foo\": null}, {\"foo\": null} ],\n                    [ {\"foo\": null}, {\"foo\": null} ],\n                    [ {\"foo\": null}, {\"foo\": null} ],\n                    [ {\"foo\": null}, {\"foo\": null} ]\n                ],\n                \"valid\": false\n            },\n            {\n                \"description\": \"too many sub-items\",\n                \"data\": [\n                    [ {\"foo\": null}, {\"foo\": null}, {\"foo\": null} ],\n                    [ {\"foo\": null}, {\"foo\": null} ],\n                    [ {\"foo\": null}, {\"foo\": null} ]\n                ],\n                \"valid\": false\n            },\n            {\n                \"description\": \"wrong item\",\n                \"data\": [\n                    {\"foo\": null},\n                    [ {\"foo\": null}, {\"foo\": null} ],\n                    [ {\"foo\": null}, {\"foo\": null} ]\n                ],\n                \"valid\": false\n            },\n            {\n                \"description\": \"wrong sub-item\",\n                \"data\": [\n                    [ {}, {\"foo\": null} ],\n                    [ {\"foo\": null}, {\"foo\": null} ],\n                    [ {\"foo\": null}, {\"foo\": null} ]\n                ],\n                \"valid\": false\n            },\n            {\n                \"description\": \"fewer items is valid\",\n                \"data\": [\n                    [ {\"foo\": null} ],\n                    [ {\"foo\": null} ]\n                ],\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"nested items\",\n        \"schema\": {\n            \"type\": \"array\",\n            \"items\": {\n                \"type\": \"array\",\n                \"items\": {\n                    \"type\": \"array\",\n                    \"items\": {\n                        \"type\": \"array\",\n                        \"items\": {\n                            \"type\": \"number\"\n                        }\n                    }\n                }\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"valid nested array\",\n                \"data\": [[[[1]], [[2],[3]]], [[[4], [5], [6]]]],\n                \"valid\": true\n            },\n            {\n                \"description\": \"nested array with invalid type\",\n                \"data\": [[[[\"1\"]], [[2],[3]]], [[[4], [5], [6]]]],\n                \"valid\": false\n            },\n            {\n                \"description\": \"not deep enough\",\n                \"data\": [[[1], [2],[3]], [[4], [5], [6]]],\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/maxItems.json",
    "content": "[\n    {\n        \"description\": \"maxItems validation\",\n        \"schema\": {\"maxItems\": 2},\n        \"tests\": [\n            {\n                \"description\": \"shorter is valid\",\n                \"data\": [1],\n                \"valid\": true\n            },\n            {\n                \"description\": \"exact length is valid\",\n                \"data\": [1, 2],\n                \"valid\": true\n            },\n            {\n                \"description\": \"too long is invalid\",\n                \"data\": [1, 2, 3],\n                \"valid\": false\n            },\n            {\n                \"description\": \"ignores non-arrays\",\n                \"data\": \"foobar\",\n                \"valid\": true\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/maxLength.json",
    "content": "[\n    {\n        \"description\": \"maxLength validation\",\n        \"schema\": {\"maxLength\": 2},\n        \"tests\": [\n            {\n                \"description\": \"shorter is valid\",\n                \"data\": \"f\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"exact length is valid\",\n                \"data\": \"fo\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"too long is invalid\",\n                \"data\": \"foo\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"ignores non-strings\",\n                \"data\": 100,\n                \"valid\": true\n            },\n            {\n                \"description\": \"two supplementary Unicode code points is long enough\",\n                \"data\": \"\\uD83D\\uDCA9\\uD83D\\uDCA9\",\n                \"valid\": true\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/maxProperties.json",
    "content": "[\n    {\n        \"description\": \"maxProperties validation\",\n        \"schema\": {\"maxProperties\": 2},\n        \"tests\": [\n            {\n                \"description\": \"shorter is valid\",\n                \"data\": {\"foo\": 1},\n                \"valid\": true\n            },\n            {\n                \"description\": \"exact length is valid\",\n                \"data\": {\"foo\": 1, \"bar\": 2},\n                \"valid\": true\n            },\n            {\n                \"description\": \"too long is invalid\",\n                \"data\": {\"foo\": 1, \"bar\": 2, \"baz\": 3},\n                \"valid\": false\n            },\n            {\n                \"description\": \"ignores arrays\",\n                \"data\": [1, 2, 3],\n                \"valid\": true\n            },\n            {\n                \"description\": \"ignores strings\",\n                \"data\": \"foobar\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"ignores other non-objects\",\n                \"data\": 12,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"maxProperties = 0 means the object is empty\",\n        \"schema\": { \"maxProperties\": 0 },\n        \"tests\": [\n            {\n                \"description\": \"no properties is valid\",\n                \"data\": {},\n                \"valid\": true\n            },\n            {\n                \"description\": \"one property is invalid\",\n                \"data\": { \"foo\": 1 },\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/maximum.json",
    "content": "[\n    {\n        \"description\": \"maximum validation\",\n        \"schema\": {\"maximum\": 3.0},\n        \"tests\": [\n            {\n                \"description\": \"below the maximum is valid\",\n                \"data\": 2.6,\n                \"valid\": true\n            },\n            {\n                \"description\": \"boundary point is valid\",\n                \"data\": 3.0,\n                \"valid\": true\n            },\n            {\n                \"description\": \"above the maximum is invalid\",\n                \"data\": 3.5,\n                \"valid\": false\n            },\n            {\n                \"description\": \"ignores non-numbers\",\n                \"data\": \"x\",\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"maximum validation with unsigned integer\",\n        \"schema\": {\"maximum\": 300},\n        \"tests\":  [\n            {\n                \"description\": \"below the maximum is invalid\",\n                \"data\": 299.97,\n                \"valid\": true\n            },\n            {\n                \"description\": \"boundary point integer is valid\",\n                \"data\": 300,\n                \"valid\": true\n            },\n            {\n                \"description\": \"boundary point float is valid\",\n                \"data\": 300.00,\n                \"valid\": true\n            },\n            {\n                \"description\": \"above the maximum is invalid\",\n                \"data\": 300.5,\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/minItems.json",
    "content": "[\n    {\n        \"description\": \"minItems validation\",\n        \"schema\": {\"minItems\": 1},\n        \"tests\": [\n            {\n                \"description\": \"longer is valid\",\n                \"data\": [1, 2],\n                \"valid\": true\n            },\n            {\n                \"description\": \"exact length is valid\",\n                \"data\": [1],\n                \"valid\": true\n            },\n            {\n                \"description\": \"too short is invalid\",\n                \"data\": [],\n                \"valid\": false\n            },\n            {\n                \"description\": \"ignores non-arrays\",\n                \"data\": \"\",\n                \"valid\": true\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/minLength.json",
    "content": "[\n    {\n        \"description\": \"minLength validation\",\n        \"schema\": {\"minLength\": 2},\n        \"tests\": [\n            {\n                \"description\": \"longer is valid\",\n                \"data\": \"foo\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"exact length is valid\",\n                \"data\": \"fo\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"too short is invalid\",\n                \"data\": \"f\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"ignores non-strings\",\n                \"data\": 1,\n                \"valid\": true\n            },\n            {\n                \"description\": \"one supplementary Unicode code point is not long enough\",\n                \"data\": \"\\uD83D\\uDCA9\",\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/minProperties.json",
    "content": "[\n    {\n        \"description\": \"minProperties validation\",\n        \"schema\": {\"minProperties\": 1},\n        \"tests\": [\n            {\n                \"description\": \"longer is valid\",\n                \"data\": {\"foo\": 1, \"bar\": 2},\n                \"valid\": true\n            },\n            {\n                \"description\": \"exact length is valid\",\n                \"data\": {\"foo\": 1},\n                \"valid\": true\n            },\n            {\n                \"description\": \"too short is invalid\",\n                \"data\": {},\n                \"valid\": false\n            },\n            {\n                \"description\": \"ignores arrays\",\n                \"data\": [],\n                \"valid\": true\n            },\n            {\n                \"description\": \"ignores strings\",\n                \"data\": \"\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"ignores other non-objects\",\n                \"data\": 12,\n                \"valid\": true\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/minimum.json",
    "content": "[\n    {\n        \"description\": \"minimum validation\",\n        \"schema\": {\"minimum\": 1.1},\n        \"tests\": [\n            {\n                \"description\": \"above the minimum is valid\",\n                \"data\": 2.6,\n                \"valid\": true\n            },\n            {\n                \"description\": \"boundary point is valid\",\n                \"data\": 1.1,\n                \"valid\": true\n            },\n            {\n                \"description\": \"below the minimum is invalid\",\n                \"data\": 0.6,\n                \"valid\": false\n            },\n            {\n                \"description\": \"ignores non-numbers\",\n                \"data\": \"x\",\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"minimum validation with signed integer\",\n        \"schema\": {\"minimum\": -2},\n        \"tests\": [\n            {\n                \"description\": \"negative above the minimum is valid\",\n                \"data\": -1,\n                \"valid\": true\n            },\n            {\n                \"description\": \"positive above the minimum is valid\",\n                \"data\": 0,\n                \"valid\": true\n            },\n            {\n                \"description\": \"boundary point is valid\",\n                \"data\": -2,\n                \"valid\": true\n            },\n            {\n                \"description\": \"boundary point with float is valid\",\n                \"data\": -2.0,\n                \"valid\": true\n            },\n            {\n                \"description\": \"float below the minimum is invalid\",\n                \"data\": -2.0001,\n                \"valid\": false\n            },\n            {\n                \"description\": \"int below the minimum is invalid\",\n                \"data\": -3,\n                \"valid\": false\n            },\n            {\n                \"description\": \"ignores non-numbers\",\n                \"data\": \"x\",\n                \"valid\": true\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/multipleOf.json",
    "content": "[\n    {\n        \"description\": \"by int\",\n        \"schema\": {\"multipleOf\": 2},\n        \"tests\": [\n            {\n                \"description\": \"int by int\",\n                \"data\": 10,\n                \"valid\": true\n            },\n            {\n                \"description\": \"int by int fail\",\n                \"data\": 7,\n                \"valid\": false\n            },\n            {\n                \"description\": \"ignores non-numbers\",\n                \"data\": \"foo\",\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"by number\",\n        \"schema\": {\"multipleOf\": 1.5},\n        \"tests\": [\n            {\n                \"description\": \"zero is multiple of anything\",\n                \"data\": 0,\n                \"valid\": true\n            },\n            {\n                \"description\": \"4.5 is multiple of 1.5\",\n                \"data\": 4.5,\n                \"valid\": true\n            },\n            {\n                \"description\": \"35 is not multiple of 1.5\",\n                \"data\": 35,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"by small number\",\n        \"schema\": {\"multipleOf\": 0.0001},\n        \"tests\": [\n            {\n                \"description\": \"0.0075 is multiple of 0.0001\",\n                \"data\": 0.0075,\n                \"valid\": true\n            },\n            {\n                \"description\": \"0.00751 is not multiple of 0.0001\",\n                \"data\": 0.00751,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"invalid instance should not raise error when float division = inf\",\n        \"schema\": {\"type\": \"integer\", \"multipleOf\": 0.123456789},\n        \"tests\": [\n            {\n                \"description\": \"always invalid, but naive implementations may raise an overflow error\",\n                \"data\": 1e308,\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/not.json",
    "content": "[\n    {\n        \"description\": \"not\",\n        \"schema\": {\n            \"not\": {\"type\": \"integer\"}\n        },\n        \"tests\": [\n            {\n                \"description\": \"allowed\",\n                \"data\": \"foo\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"disallowed\",\n                \"data\": 1,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"not multiple types\",\n        \"schema\": {\n            \"not\": {\"type\": [\"integer\", \"boolean\"]}\n        },\n        \"tests\": [\n            {\n                \"description\": \"valid\",\n                \"data\": \"foo\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"mismatch\",\n                \"data\": 1,\n                \"valid\": false\n            },\n            {\n                \"description\": \"other mismatch\",\n                \"data\": true,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"not more complex schema\",\n        \"schema\": {\n            \"not\": {\n                \"type\": \"object\",\n                \"properties\": {\n                    \"foo\": {\n                        \"type\": \"string\"\n                    }\n                }\n             }\n        },\n        \"tests\": [\n            {\n                \"description\": \"match\",\n                \"data\": 1,\n                \"valid\": true\n            },\n            {\n                \"description\": \"other match\",\n                \"data\": {\"foo\": 1},\n                \"valid\": true\n            },\n            {\n                \"description\": \"mismatch\",\n                \"data\": {\"foo\": \"bar\"},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"forbidden property\",\n        \"schema\": {\n            \"properties\": {\n                \"foo\": {\n                    \"not\": {}\n                }\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"property present\",\n                \"data\": {\"foo\": 1, \"bar\": 2},\n                \"valid\": false\n            },\n            {\n                \"description\": \"property absent\",\n                \"data\": {\"bar\": 1, \"baz\": 2},\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"not with boolean schema true\",\n        \"schema\": {\"not\": true},\n        \"tests\": [\n            {\n                \"description\": \"any value is invalid\",\n                \"data\": \"foo\",\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"not with boolean schema false\",\n        \"schema\": {\"not\": false},\n        \"tests\": [\n            {\n                \"description\": \"any value is valid\",\n                \"data\": \"foo\",\n                \"valid\": true\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/oneOf.json",
    "content": "[\n    {\n        \"description\": \"oneOf\",\n        \"schema\": {\n            \"oneOf\": [\n                {\n                    \"type\": \"integer\"\n                },\n                {\n                    \"minimum\": 2\n                }\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"first oneOf valid\",\n                \"data\": 1,\n                \"valid\": true\n            },\n            {\n                \"description\": \"second oneOf valid\",\n                \"data\": 2.5,\n                \"valid\": true\n            },\n            {\n                \"description\": \"both oneOf valid\",\n                \"data\": 3,\n                \"valid\": false\n            },\n            {\n                \"description\": \"neither oneOf valid\",\n                \"data\": 1.5,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"oneOf with base schema\",\n        \"schema\": {\n            \"type\": \"string\",\n            \"oneOf\" : [\n                {\n                    \"minLength\": 2\n                },\n                {\n                    \"maxLength\": 4\n                }\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"mismatch base schema\",\n                \"data\": 3,\n                \"valid\": false\n            },\n            {\n                \"description\": \"one oneOf valid\",\n                \"data\": \"foobar\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"both oneOf valid\",\n                \"data\": \"foo\",\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"oneOf with boolean schemas, all true\",\n        \"schema\": {\"oneOf\": [true, true, true]},\n        \"tests\": [\n            {\n                \"description\": \"any value is invalid\",\n                \"data\": \"foo\",\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"oneOf with boolean schemas, one true\",\n        \"schema\": {\"oneOf\": [true, false, false]},\n        \"tests\": [\n            {\n                \"description\": \"any value is valid\",\n                \"data\": \"foo\",\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"oneOf with boolean schemas, more than one true\",\n        \"schema\": {\"oneOf\": [true, true, false]},\n        \"tests\": [\n            {\n                \"description\": \"any value is invalid\",\n                \"data\": \"foo\",\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"oneOf with boolean schemas, all false\",\n        \"schema\": {\"oneOf\": [false, false, false]},\n        \"tests\": [\n            {\n                \"description\": \"any value is invalid\",\n                \"data\": \"foo\",\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"oneOf complex types\",\n        \"schema\": {\n            \"oneOf\": [\n                {\n                    \"properties\": {\n                        \"bar\": {\"type\": \"integer\"}\n                    },\n                    \"required\": [\"bar\"]\n                },\n                {\n                    \"properties\": {\n                        \"foo\": {\"type\": \"string\"}\n                    },\n                    \"required\": [\"foo\"]\n                }\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"first oneOf valid (complex)\",\n                \"data\": {\"bar\": 2},\n                \"valid\": true\n            },\n            {\n                \"description\": \"second oneOf valid (complex)\",\n                \"data\": {\"foo\": \"baz\"},\n                \"valid\": true\n            },\n            {\n                \"description\": \"both oneOf valid (complex)\",\n                \"data\": {\"foo\": \"baz\", \"bar\": 2},\n                \"valid\": false\n            },\n            {\n                \"description\": \"neither oneOf valid (complex)\",\n                \"data\": {\"foo\": 2, \"bar\": \"quux\"},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"oneOf with empty schema\",\n        \"schema\": {\n            \"oneOf\": [\n                { \"type\": \"number\" },\n                {}\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"one valid - valid\",\n                \"data\": \"foo\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"both valid - invalid\",\n                \"data\": 123,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"oneOf with required\",\n        \"schema\": {\n            \"type\": \"object\",\n            \"oneOf\": [\n                { \"required\": [\"foo\", \"bar\"] },\n                { \"required\": [\"foo\", \"baz\"] }\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"both invalid - invalid\",\n                \"data\": {\"bar\": 2},\n                \"valid\": false\n            },\n            {\n                \"description\": \"first valid - valid\",\n                \"data\": {\"foo\": 1, \"bar\": 2},\n                \"valid\": true\n            },\n            {\n                \"description\": \"second valid - valid\",\n                \"data\": {\"foo\": 1, \"baz\": 3},\n                \"valid\": true\n            },\n            {\n                \"description\": \"both valid - invalid\",\n                \"data\": {\"foo\": 1, \"bar\": 2, \"baz\" : 3},\n                \"valid\": false\n            }\n        ]\n    },\n\t{\n        \"description\": \"oneOf with missing optional property\",\n        \"schema\": {\n            \"oneOf\": [\n                {\n                    \"properties\": {\n                        \"bar\": true,\n                        \"baz\": true\n                    },\n                    \"required\": [\"bar\"]\n                },\n                {\n                    \"properties\": {\n                        \"foo\": true\n                    },\n                    \"required\": [\"foo\"]\n                }\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"first oneOf valid\",\n                \"data\": {\"bar\": 8},\n                \"valid\": true\n            },\n            {\n                \"description\": \"second oneOf valid\",\n                \"data\": {\"foo\": \"foo\"},\n                \"valid\": true\n            },\n            {\n                \"description\": \"both oneOf valid\",\n                \"data\": {\"foo\": \"foo\", \"bar\": 8},\n                \"valid\": false\n            },\n            {\n                \"description\": \"neither oneOf valid\",\n                \"data\": {\"baz\": \"quux\"},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"nested oneOf, to check validation semantics\",\n        \"schema\": {\n            \"oneOf\": [\n                {\n                    \"oneOf\": [\n                        {\n                            \"type\": \"null\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"null is valid\",\n                \"data\": null,\n                \"valid\": true\n            },\n            {\n                \"description\": \"anything non-null is invalid\",\n                \"data\": 123,\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/optional/bignum.json",
    "content": "[\n    {\n        \"description\": \"integer\",\n        \"schema\": { \"type\": \"integer\" },\n        \"tests\": [\n            {\n                \"description\": \"a bignum is an integer\",\n                \"data\": 12345678910111213141516171819202122232425262728293031,\n                \"valid\": true\n            },\n            {\n                \"description\": \"a negative bignum is an integer\",\n                \"data\": -12345678910111213141516171819202122232425262728293031,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"number\",\n        \"schema\": { \"type\": \"number\" },\n        \"tests\": [\n            {\n                \"description\": \"a bignum is a number\",\n                \"data\": 98249283749234923498293171823948729348710298301928331,\n                \"valid\": true\n            },\n            {\n                \"description\": \"a negative bignum is a number\",\n                \"data\": -98249283749234923498293171823948729348710298301928331,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"string\",\n        \"schema\": { \"type\": \"string\" },\n        \"tests\": [\n            {\n                \"description\": \"a bignum is not a string\",\n                \"data\": 98249283749234923498293171823948729348710298301928331,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"integer comparison\",\n        \"schema\": { \"maximum\": 18446744073709551615 },\n        \"tests\": [\n            {\n                \"description\": \"comparison works for high numbers\",\n                \"data\": 18446744073709551600,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"float comparison with high precision\",\n        \"schema\": {\n            \"exclusiveMaximum\": 972783798187987123879878123.18878137\n        },\n        \"tests\": [\n            {\n                \"description\": \"comparison works for high numbers\",\n                \"data\": 972783798187987123879878123.188781371,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"integer comparison\",\n        \"schema\": { \"minimum\": -18446744073709551615 },\n        \"tests\": [\n            {\n                \"description\": \"comparison works for very negative numbers\",\n                \"data\": -18446744073709551600,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"float comparison with high precision on negative numbers\",\n        \"schema\": {\n            \"exclusiveMinimum\": -972783798187987123879878123.18878137\n        },\n        \"tests\": [\n            {\n                \"description\": \"comparison works for very negative numbers\",\n                \"data\": -972783798187987123879878123.188781371,\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/optional/content.json",
    "content": "[\n    {\n        \"description\": \"validation of string-encoded content based on media type\",\n        \"schema\": {\n            \"contentMediaType\": \"application/json\"\n        },\n        \"tests\": [\n            {\n                \"description\": \"a valid JSON document\",\n                \"data\": \"{\\\"foo\\\": \\\"bar\\\"}\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"an invalid JSON document\",\n                \"data\": \"{:}\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"ignores non-strings\",\n                \"data\": 100,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"validation of binary string-encoding\",\n        \"schema\": {\n            \"contentEncoding\": \"base64\"\n        },\n        \"tests\": [\n            {\n                \"description\": \"a valid base64 string\",\n                \"data\": \"eyJmb28iOiAiYmFyIn0K\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"an invalid base64 string (% is not a valid character)\",\n                \"data\": \"eyJmb28iOi%iYmFyIn0K\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"ignores non-strings\",\n                \"data\": 100,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"validation of binary-encoded media type documents\",\n        \"schema\": {\n            \"contentMediaType\": \"application/json\",\n            \"contentEncoding\": \"base64\"\n        },\n        \"tests\": [\n            {\n                \"description\": \"a valid base64-encoded JSON document\",\n                \"data\": \"eyJmb28iOiAiYmFyIn0K\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a validly-encoded invalid JSON document\",\n                \"data\": \"ezp9Cg==\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"an invalid base64 string that is valid JSON\",\n                \"data\": \"{}\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"ignores non-strings\",\n                \"data\": 100,\n                \"valid\": true\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/optional/ecmascript-regex.json",
    "content": "[\n    {\n        \"description\": \"ECMA 262 regex $ does not match trailing newline\",\n        \"schema\": {\n            \"type\": \"string\",\n            \"pattern\": \"^abc$\"\n        },\n        \"tests\": [\n            {\n                \"description\": \"matches in Python, but should not in jsonschema\",\n                \"data\": \"abc\\\\n\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"should match\",\n                \"data\": \"abc\",\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"ECMA 262 regex converts \\\\t to horizontal tab\",\n        \"schema\": {\n            \"type\": \"string\",\n            \"pattern\": \"^\\\\t$\"\n        },\n        \"tests\": [\n            {\n                \"description\": \"does not match\",\n                \"data\": \"\\\\t\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"matches\",\n                \"data\": \"\\u0009\",\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"ECMA 262 regex escapes control codes with \\\\c and upper letter\",\n        \"schema\": {\n            \"type\": \"string\",\n            \"pattern\": \"^\\\\cC$\"\n        },\n        \"tests\": [\n            {\n                \"description\": \"does not match\",\n                \"data\": \"\\\\cC\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"matches\",\n                \"data\": \"\\u0003\",\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"ECMA 262 regex escapes control codes with \\\\c and lower letter\",\n        \"schema\": {\n            \"type\": \"string\",\n            \"pattern\": \"^\\\\cc$\"\n        },\n        \"tests\": [\n            {\n                \"description\": \"does not match\",\n                \"data\": \"\\\\cc\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"matches\",\n                \"data\": \"\\u0003\",\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"ECMA 262 \\\\d matches ascii digits only\",\n        \"schema\": {\n            \"type\": \"string\",\n            \"pattern\": \"^\\\\d$\"\n        },\n        \"tests\": [\n            {\n                \"description\": \"ASCII zero matches\",\n                \"data\": \"0\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"NKO DIGIT ZERO does not match (unlike e.g. Python)\",\n                \"data\": \"߀\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"NKO DIGIT ZERO (as \\\\u escape) does not match\",\n                \"data\": \"\\u07c0\",\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"ECMA 262 \\\\D matches everything but ascii digits\",\n        \"schema\": {\n            \"type\": \"string\",\n            \"pattern\": \"^\\\\D$\"\n        },\n        \"tests\": [\n            {\n                \"description\": \"ASCII zero does not match\",\n                \"data\": \"0\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"NKO DIGIT ZERO matches (unlike e.g. Python)\",\n                \"data\": \"߀\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"NKO DIGIT ZERO (as \\\\u escape) matches\",\n                \"data\": \"\\u07c0\",\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"ECMA 262 \\\\w matches ascii letters only\",\n        \"schema\": {\n            \"type\": \"string\",\n            \"pattern\": \"^\\\\w$\"\n        },\n        \"tests\": [\n            {\n                \"description\": \"ASCII 'a' matches\",\n                \"data\": \"a\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"latin-1 e-acute does not match (unlike e.g. Python)\",\n                \"data\": \"é\",\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"ECMA 262 \\\\W matches everything but ascii letters\",\n        \"schema\": {\n            \"type\": \"string\",\n            \"pattern\": \"^\\\\W$\"\n        },\n        \"tests\": [\n            {\n                \"description\": \"ASCII 'a' does not match\",\n                \"data\": \"a\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"latin-1 e-acute matches (unlike e.g. Python)\",\n                \"data\": \"é\",\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"ECMA 262 \\\\s matches whitespace\",\n        \"schema\": {\n            \"type\": \"string\",\n            \"pattern\": \"^\\\\s$\"\n        },\n        \"tests\": [\n            {\n                \"description\": \"ASCII space matches\",\n                \"data\": \" \",\n                \"valid\": true\n            },\n            {\n                \"description\": \"Character tabulation matches\",\n                \"data\": \"\\t\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"Line tabulation matches\",\n                \"data\": \"\\u000b\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"Form feed matches\",\n                \"data\": \"\\u000c\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"latin-1 non-breaking-space matches\",\n                \"data\": \"\\u00a0\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"zero-width whitespace matches\",\n                \"data\": \"\\ufeff\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"line feed matches (line terminator)\",\n                \"data\": \"\\u000a\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"paragraph separator matches (line terminator)\",\n                \"data\": \"\\u2029\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"EM SPACE matches (Space_Separator)\",\n                \"data\": \"\\u2003\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"Non-whitespace control does not match\",\n                \"data\": \"\\u0001\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"Non-whitespace does not match\",\n                \"data\": \"\\u2013\",\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"ECMA 262 \\\\S matches everything but whitespace\",\n        \"schema\": {\n            \"type\": \"string\",\n            \"pattern\": \"^\\\\S$\"\n        },\n        \"tests\": [\n            {\n                \"description\": \"ASCII space does not match\",\n                \"data\": \" \",\n                \"valid\": false\n            },\n            {\n                \"description\": \"Character tabulation does not match\",\n                \"data\": \"\\t\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"Line tabulation does not match\",\n                \"data\": \"\\u000b\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"Form feed does not match\",\n                \"data\": \"\\u000c\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"latin-1 non-breaking-space does not match\",\n                \"data\": \"\\u00a0\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"zero-width whitespace does not match\",\n                \"data\": \"\\ufeff\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"line feed does not match (line terminator)\",\n                \"data\": \"\\u000a\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"paragraph separator does not match (line terminator)\",\n                \"data\": \"\\u2029\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"EM SPACE does not match (Space_Separator)\",\n                \"data\": \"\\u2003\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"Non-whitespace control matches\",\n                \"data\": \"\\u0001\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"Non-whitespace matches\",\n                \"data\": \"\\u2013\",\n                \"valid\": true\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/optional/float-overflow.json",
    "content": "[\n    {\n        \"description\": \"all integers are multiples of 0.5, if overflow is handled\",\n        \"schema\": {\"type\": \"integer\", \"multipleOf\": 0.5},\n        \"tests\": [\n            {\n                \"description\": \"valid if optional overflow handling is implemented\",\n                \"data\": 1e308,\n                \"valid\": true\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/optional/format/date-time.json",
    "content": "[\n    {\n        \"description\": \"validation of date-time strings\",\n        \"schema\": {\"format\": \"date-time\"},\n        \"tests\": [\n            {\n                \"description\": \"a valid date-time string\",\n                \"data\": \"1963-06-19T08:30:06.283185Z\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a valid date-time string without second fraction\",\n                \"data\": \"1963-06-19T08:30:06Z\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a valid date-time string with plus offset\",\n                \"data\": \"1937-01-01T12:00:27.87+00:20\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a valid date-time string with minus offset\",\n                \"data\": \"1990-12-31T15:59:50.123-08:00\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a invalid day in date-time string\",\n                \"data\": \"1990-02-31T15:59:60.123-08:00\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"an invalid offset in date-time string\",\n                \"data\": \"1990-12-31T15:59:60-24:00\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"an invalid date-time string\",\n                \"data\": \"06/19/1963 08:30:06 PST\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"case-insensitive T and Z\",\n                \"data\": \"1963-06-19t08:30:06.283185z\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"only RFC3339 not all of ISO 8601 are valid\",\n                \"data\": \"2013-350T01:01:01\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"invalid non-padded month dates\",\n                \"data\": \"1963-6-19T08:30:06.283185Z\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"invalid non-padded day dates\",\n                \"data\": \"1963-06-1T08:30:06.283185Z\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"non-ascii digits should be rejected in the date portion\",\n                \"data\": \"1963-06-1৪T00:00:00Z\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"non-ascii digits should be rejected in the time portion\",\n                \"data\": \"1963-06-11T0৪:00:00Z\",\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/optional/format/date.json",
    "content": "[\n    {\n        \"description\": \"validation of date strings\",\n        \"schema\": {\"format\": \"date\"},\n        \"tests\": [\n            {\n                \"description\": \"a valid date string\",\n                \"data\": \"1963-06-19\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a valid date string with 31 days in January\",\n                \"data\": \"2020-01-31\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a invalid date string with 32 days in January\",\n                \"data\": \"2020-01-32\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"a valid date string with 28 days in February (normal)\",\n                \"data\": \"2021-02-28\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a invalid date string with 29 days in February (normal)\",\n                \"data\": \"2021-02-29\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"a valid date string with 29 days in February (leap)\",\n                \"data\": \"2020-02-29\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a invalid date string with 30 days in February (leap)\",\n                \"data\": \"2020-02-30\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"a valid date string with 31 days in March\",\n                \"data\": \"2020-03-31\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a invalid date string with 32 days in March\",\n                \"data\": \"2020-03-32\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"a valid date string with 30 days in April\",\n                \"data\": \"2020-04-30\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a invalid date string with 31 days in April\",\n                \"data\": \"2020-04-31\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"a valid date string with 31 days in May\",\n                \"data\": \"2020-05-31\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a invalid date string with 32 days in May\",\n                \"data\": \"2020-05-32\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"a valid date string with 30 days in June\",\n                \"data\": \"2020-06-30\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a invalid date string with 31 days in June\",\n                \"data\": \"2020-06-31\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"a valid date string with 31 days in July\",\n                \"data\": \"2020-07-31\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a invalid date string with 32 days in July\",\n                \"data\": \"2020-07-32\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"a valid date string with 31 days in August\",\n                \"data\": \"2020-08-31\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a invalid date string with 32 days in August\",\n                \"data\": \"2020-08-32\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"a valid date string with 30 days in September\",\n                \"data\": \"2020-09-30\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a invalid date string with 31 days in September\",\n                \"data\": \"2020-09-31\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"a valid date string with 31 days in October\",\n                \"data\": \"2020-10-31\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a invalid date string with 32 days in October\",\n                \"data\": \"2020-10-32\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"a valid date string with 30 days in November\",\n                \"data\": \"2020-11-30\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a invalid date string with 31 days in November\",\n                \"data\": \"2020-11-31\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"a valid date string with 31 days in December\",\n                \"data\": \"2020-12-31\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a invalid date string with 32 days in December\",\n                \"data\": \"2020-12-32\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"a invalid date string with invalid month\",\n                \"data\": \"2020-13-01\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"an invalid date string\",\n                \"data\": \"06/19/1963\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"only RFC3339 not all of ISO 8601 are valid\",\n                \"data\": \"2013-350\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"non-padded month dates are not valid\",\n                \"data\": \"1998-1-20\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"non-padded day dates are not valid\",\n                \"data\": \"1998-01-1\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"invalid month\",\n                \"data\": \"1998-13-01\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"invalid month-day combination\",\n                \"data\": \"1998-04-31\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"2021 is not a leap year\",\n                \"data\": \"2021-02-29\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"2020 is a leap year\",\n                \"data\": \"2020-02-29\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"non-ascii digits should be rejected\",\n                \"data\": \"1963-06-1৪\",\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/optional/format/email.json",
    "content": "[\n    {\n        \"description\": \"validation of e-mail addresses\",\n        \"schema\": {\"format\": \"email\"},\n        \"tests\": [\n            {\n                \"description\": \"a valid e-mail address\",\n                \"data\": \"joe.bloggs@example.com\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"an invalid e-mail address\",\n                \"data\": \"2962\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"tilde in local part is valid\",\n                \"data\": \"te~st@example.com\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"tilde before local part is valid\",\n                \"data\": \"~test@example.com\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"tilde after local part is valid\",\n                \"data\": \"test~@example.com\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"dot before local part is not valid\",\n                \"data\": \".test@example.com\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"dot after local part is not valid\",\n                \"data\": \"test.@example.com\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"two separated dots inside local part are valid\",\n                \"data\": \"te.s.t@example.com\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"two subsequent dots inside local part are not valid\",\n                \"data\": \"te..st@example.com\",\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/optional/format/hostname.json",
    "content": "[\n    {\n        \"description\": \"validation of host names\",\n        \"schema\": {\"format\": \"hostname\"},\n        \"tests\": [\n            {\n                \"description\": \"a valid host name\",\n                \"data\": \"www.example.com\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a valid punycoded IDN hostname\",\n                \"data\": \"xn--4gbwdl.xn--wgbh1c\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a host name starting with an illegal character\",\n                \"data\": \"-a-host-name-that-starts-with--\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"a host name containing illegal characters\",\n                \"data\": \"not_a_valid_host_name\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"a host name with a component too long\",\n                \"data\": \"a-vvvvvvvvvvvvvvvveeeeeeeeeeeeeeeerrrrrrrrrrrrrrrryyyyyyyyyyyyyyyy-long-host-name-component\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"starts with hyphen\",\n                \"data\": \"-hostname\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"ends with hyphen\",\n                \"data\": \"hostname-\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"starts with underscore\",\n                \"data\": \"_hostname\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"ends with underscore\",\n                \"data\": \"hostname_\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"contains underscore\",\n                \"data\": \"host_name\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"maximum label length\",\n                \"data\": \"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk.com\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"exceeds maximum label length\",\n                \"data\": \"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl.com\",\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/optional/format/idn-email.json",
    "content": "[\n    {\n        \"description\": \"validation of an internationalized e-mail addresses\",\n        \"schema\": {\"format\": \"idn-email\"},\n        \"tests\": [\n            {\n                \"description\": \"a valid idn e-mail (example@example.test in Hangul)\",\n                \"data\": \"실례@실례.테스트\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"an invalid idn e-mail address\",\n                \"data\": \"2962\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"a valid e-mail address\",\n                \"data\": \"joe.bloggs@example.com\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"an invalid e-mail address\",\n                \"data\": \"2962\",\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/optional/format/idn-hostname.json",
    "content": "[\n    {\n        \"description\": \"validation of internationalized host names\",\n        \"schema\": {\"format\": \"idn-hostname\"},\n        \"tests\": [\n            {\n                \"description\": \"a valid host name (example.test in Hangul)\",\n                \"data\": \"실례.테스트\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"illegal first char U+302E Hangul single dot tone mark\",\n                \"data\": \"〮실례.테스트\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"contains illegal char U+302E Hangul single dot tone mark\",\n                \"data\": \"실〮례.테스트\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"a host name with a component too long\",\n                \"data\": \"실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실례례테스트례례례례례례례례례례례례례례례례례테스트례례례례례례례례례례례례례례례례례례례테스트례례례례례례례례례례례례테스트례례실례.테스트\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"invalid label, correct Punycode\",\n                \"comment\": \"https://tools.ietf.org/html/rfc5890#section-2.3.2.1 https://tools.ietf.org/html/rfc5891#section-4.4 https://tools.ietf.org/html/rfc3492#section-7.1\",\n                \"data\": \"-> $1.00 <--\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"valid Chinese Punycode\",\n                \"comment\": \"https://tools.ietf.org/html/rfc5890#section-2.3.2.1 https://tools.ietf.org/html/rfc5891#section-4.4\",\n                \"data\": \"xn--ihqwcrb4cv8a8dqg056pqjye\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"invalid Punycode\",\n                \"comment\": \"https://tools.ietf.org/html/rfc5891#section-4.4 https://tools.ietf.org/html/rfc5890#section-2.3.2.1\",\n                \"data\": \"xn--X\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"U-label contains \\\"--\\\" in the 3rd and 4th position\",\n                \"comment\": \"https://tools.ietf.org/html/rfc5891#section-4.2.3.1 https://tools.ietf.org/html/rfc5890#section-2.3.2.1\",\n                \"data\": \"XN--aa---o47jg78q\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"U-label starts with a dash\",\n                \"comment\": \"https://tools.ietf.org/html/rfc5891#section-4.2.3.1\",\n                \"data\": \"-hello\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"U-label ends with a dash\",\n                \"comment\": \"https://tools.ietf.org/html/rfc5891#section-4.2.3.1\",\n                \"data\": \"hello-\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"U-label starts and ends with a dash\",\n                \"comment\": \"https://tools.ietf.org/html/rfc5891#section-4.2.3.1\",\n                \"data\": \"-hello-\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"Begins with a Spacing Combining Mark\",\n                \"comment\": \"https://tools.ietf.org/html/rfc5891#section-4.2.3.2\",\n                \"data\": \"\\u0903hello\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"Begins with a Nonspacing Mark\",\n                \"comment\": \"https://tools.ietf.org/html/rfc5891#section-4.2.3.2\",\n                \"data\": \"\\u0300hello\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"Begins with an Enclosing Mark\",\n                \"comment\": \"https://tools.ietf.org/html/rfc5891#section-4.2.3.2\",\n                \"data\": \"\\u0488hello\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"Exceptions that are PVALID, left-to-right chars\",\n                \"comment\": \"https://tools.ietf.org/html/rfc5891#section-4.2.2 https://tools.ietf.org/html/rfc5892#section-2.6\",\n                \"data\": \"\\u00df\\u03c2\\u0f0b\\u3007\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"Exceptions that are PVALID, right-to-left chars\",\n                \"comment\": \"https://tools.ietf.org/html/rfc/rfc5891#section-4.2.2 https://tools.ietf.org/html/rfc5892#section-2.6\",\n                \"data\": \"\\u06fd\\u06fe\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"Exceptions that are DISALLOWED, right-to-left chars\",\n                \"comment\": \"https://tools.ietf.org/html/rfc5891#section-4.2.2 https://tools.ietf.org/html/rfc5892#section-2.6\",\n                \"data\": \"\\u0640\\u07fa\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"Exceptions that are DISALLOWED, left-to-right chars\",\n                \"comment\": \"https://tools.ietf.org/html/rfc5891#section-4.2.2 https://tools.ietf.org/html/rfc5892#section-2.6 Note: The two combining marks (U+302E and U+302F) are in the middle and not at the start\",\n                \"data\": \"\\u3031\\u3032\\u3033\\u3034\\u3035\\u302e\\u302f\\u303b\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"MIDDLE DOT with no preceding 'l'\",\n                \"comment\": \"https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.3\",\n                \"data\": \"a\\u00b7l\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"MIDDLE DOT with nothing preceding\",\n                \"comment\": \"https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.3\",\n                \"data\": \"\\u00b7l\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"MIDDLE DOT with no following 'l'\",\n                \"comment\": \"https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.3\",\n                \"data\": \"l\\u00b7a\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"MIDDLE DOT with nothing following\",\n                \"comment\": \"https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.3\",\n                \"data\": \"l\\u00b7\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"MIDDLE DOT with surrounding 'l's\",\n                \"comment\": \"https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.3\",\n                \"data\": \"l\\u00b7l\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"Greek KERAIA not followed by Greek\",\n                \"comment\": \"https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.4\",\n                \"data\": \"\\u03b1\\u0375S\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"Greek KERAIA not followed by anything\",\n                \"comment\": \"https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.4\",\n                \"data\": \"\\u03b1\\u0375\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"Greek KERAIA followed by Greek\",\n                \"comment\": \"https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.4\",\n                \"data\": \"\\u03b1\\u0375\\u03b2\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"Hebrew GERESH not preceded by Hebrew\",\n                \"comment\": \"https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.5\",\n                \"data\": \"A\\u05f3\\u05d1\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"Hebrew GERESH not preceded by anything\",\n                \"comment\": \"https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.5\",\n                \"data\": \"\\u05f3\\u05d1\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"Hebrew GERESH preceded by Hebrew\",\n                \"comment\": \"https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.5\",\n                \"data\": \"\\u05d0\\u05f3\\u05d1\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"Hebrew GERSHAYIM not preceded by Hebrew\",\n                \"comment\": \"https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.6\",\n                \"data\": \"A\\u05f4\\u05d1\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"Hebrew GERSHAYIM not preceded by anything\",\n                \"comment\": \"https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.6\",\n                \"data\": \"\\u05f4\\u05d1\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"Hebrew GERSHAYIM preceded by Hebrew\",\n                \"comment\": \"https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.6\",\n                \"data\": \"\\u05d0\\u05f4\\u05d1\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"KATAKANA MIDDLE DOT with no Hiragana, Katakana, or Han\",\n                \"comment\": \"https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.7\",\n                \"data\": \"def\\u30fbabc\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"KATAKANA MIDDLE DOT with no other characters\",\n                \"comment\": \"https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.7\",\n                \"data\": \"\\u30fb\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"KATAKANA MIDDLE DOT with Hiragana\",\n                \"comment\": \"https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.7\",\n                \"data\": \"\\u30fb\\u3041\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"KATAKANA MIDDLE DOT with Katakana\",\n                \"comment\": \"https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.7\",\n                \"data\": \"\\u30fb\\u30a1\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"KATAKANA MIDDLE DOT with Han\",\n                \"comment\": \"https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.7\",\n                \"data\": \"\\u30fb\\u4e08\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"Arabic-Indic digits mixed with Extended Arabic-Indic digits\",\n                \"comment\": \"https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.8\",\n                \"data\": \"\\u0660\\u06f0\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"Arabic-Indic digits not mixed with Extended Arabic-Indic digits\",\n                \"comment\": \"https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.8\",\n                \"data\": \"\\u0628\\u0660\\u0628\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"Extended Arabic-Indic digits not mixed with Arabic-Indic digits\",\n                \"comment\": \"https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.9\",\n                \"data\": \"\\u06f00\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"ZERO WIDTH JOINER not preceded by Virama\",\n                \"comment\": \"https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.2 https://www.unicode.org/review/pr-37.pdf\",\n                \"data\": \"\\u0915\\u200d\\u0937\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"ZERO WIDTH JOINER not preceded by anything\",\n                \"comment\": \"https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.2 https://www.unicode.org/review/pr-37.pdf\",\n                \"data\": \"\\u200d\\u0937\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"ZERO WIDTH JOINER preceded by Virama\",\n                \"comment\": \"https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.2 https://www.unicode.org/review/pr-37.pdf\",\n                \"data\": \"\\u0915\\u094d\\u200d\\u0937\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"ZERO WIDTH NON-JOINER preceded by Virama\",\n                \"comment\": \"https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.1\",\n                \"data\": \"\\u0915\\u094d\\u200c\\u0937\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"ZERO WIDTH NON-JOINER not preceded by Virama but matches regexp\",\n                \"comment\": \"https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.1 https://www.w3.org/TR/alreq/#h_disjoining_enforcement\",\n                \"data\": \"\\u0628\\u064a\\u200c\\u0628\\u064a\",\n                \"valid\": true\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/optional/format/ipv4.json",
    "content": "[\n    {\n        \"description\": \"validation of IP addresses\",\n        \"schema\": {\"format\": \"ipv4\"},\n        \"tests\": [\n            {\n                \"description\": \"a valid IP address\",\n                \"data\": \"192.168.0.1\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"an IP address with too many components\",\n                \"data\": \"127.0.0.0.1\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"an IP address with out-of-range values\",\n                \"data\": \"256.256.256.256\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"an IP address without 4 components\",\n                \"data\": \"127.0\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"an IP address as an integer\",\n                \"data\": \"0x7f000001\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"an IP address as an integer (decimal)\",\n                \"data\": \"2130706433\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"leading zeroes should be rejected, as they are treated as octals\",\n                \"comment\": \"see https://sick.codes/universal-netmask-npm-package-used-by-270000-projects-vulnerable-to-octal-input-data-server-side-request-forgery-remote-file-inclusion-local-file-inclusion-and-more-cve-2021-28918/\",\n                \"data\": \"087.10.0.1\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"value without leading zero is valid\",\n                \"data\": \"87.10.0.1\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"non-ascii digits should be rejected\",\n                \"data\": \"1২7.0.0.1\",\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/optional/format/ipv6.json",
    "content": "[\n    {\n        \"description\": \"validation of IPv6 addresses\",\n        \"schema\": {\"format\": \"ipv6\"},\n        \"tests\": [\n            {\n                \"description\": \"a valid IPv6 address\",\n                \"data\": \"::1\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"an IPv6 address with out-of-range values\",\n                \"data\": \"12345::\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"an IPv6 address with too many components\",\n                \"data\": \"1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"an IPv6 address containing illegal characters\",\n                \"data\": \"::laptop\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"no digits is valid\",\n                \"data\": \"::\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"leading colons is valid\",\n                \"data\": \"::42:ff:1\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"trailing colons is valid\",\n                \"data\": \"d6::\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"missing leading octet is invalid\",\n                \"data\": \":2:3:4:5:6:7:8\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"missing trailing octet is invalid\",\n                \"data\": \"1:2:3:4:5:6:7:\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"missing leading octet with omitted octets later\",\n                \"data\": \":2:3:4::8\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"two sets of double colons is invalid\",\n                \"data\": \"1::d6::42\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"mixed format with the ipv4 section as decimal octets\",\n                \"data\": \"1::d6:192.168.0.1\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"mixed format with double colons between the sections\",\n                \"data\": \"1:2::192.168.0.1\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"mixed format with ipv4 section with octet out of range\",\n                \"data\": \"1::2:192.168.256.1\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"mixed format with ipv4 section with a hex octet\",\n                \"data\": \"1::2:192.168.ff.1\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"mixed format with leading double colons (ipv4-mapped ipv6 address)\",\n                \"data\": \"::ffff:192.168.0.1\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"triple colons is invalid\",\n                \"data\": \"1:2:3:4:5:::8\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"8 octets\",\n                \"data\": \"1:2:3:4:5:6:7:8\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"insufficient octets without double colons\",\n                \"data\": \"1:2:3:4:5:6:7\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"no colons is invalid\",\n                \"data\": \"1\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"ipv4 is not ipv6\",\n                \"data\": \"127.0.0.1\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"ipv4 segment must have 4 octets\",\n                \"data\": \"1:2:3:4:1.2.3\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"leading whitespace is invalid\",\n                \"data\": \"  ::1\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"trailing whitespace is invalid\",\n                \"data\": \"::1  \",\n                \"valid\": false\n            },\n            {\n                \"description\": \"netmask is not a part of ipv6 address\",\n                \"data\": \"fe80::/64\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"zone id is not a part of ipv6 address\",\n                \"data\": \"fe80::a%eth1\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"a long valid ipv6\",\n                \"data\": \"1000:1000:1000:1000:1000:1000:255.255.255.255\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a long invalid ipv6, below length limit, first\",\n                \"data\": \"100:100:100:100:100:100:255.255.255.255.255\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"a long invalid ipv6, below length limit, second\",\n                \"data\": \"100:100:100:100:100:100:100:255.255.255.255\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"non-ascii digits should be rejected\",\n                \"data\": \"1:2:3:4:5:6:7:৪\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"non-ascii digits should be rejected in the ipv4 portion also\",\n                \"data\": \"1:2::192.16৪.0.1\",\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/optional/format/iri-reference.json",
    "content": "[\n    {\n        \"description\": \"validation of IRI References\",\n        \"schema\": {\"format\": \"iri-reference\"},\n        \"tests\": [\n            {\n                \"description\": \"a valid IRI\",\n                \"data\": \"http://ƒøø.ßår/?∂éœ=πîx#πîüx\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a valid protocol-relative IRI Reference\",\n                \"data\": \"//ƒøø.ßår/?∂éœ=πîx#πîüx\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a valid relative IRI Reference\",\n                \"data\": \"/âππ\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"an invalid IRI Reference\",\n                \"data\": \"\\\\\\\\WINDOWS\\\\filëßåré\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"a valid IRI Reference\",\n                \"data\": \"âππ\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a valid IRI fragment\",\n                \"data\": \"#ƒrägmênt\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"an invalid IRI fragment\",\n                \"data\": \"#ƒräg\\\\mênt\",\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/optional/format/iri.json",
    "content": "[\n    {\n        \"description\": \"validation of IRIs\",\n        \"schema\": {\"format\": \"iri\"},\n        \"tests\": [\n            {\n                \"description\": \"a valid IRI with anchor tag\",\n                \"data\": \"http://ƒøø.ßår/?∂éœ=πîx#πîüx\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a valid IRI with anchor tag and parentheses\",\n                \"data\": \"http://ƒøø.com/blah_(wîkïpédiå)_blah#ßité-1\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a valid IRI with URL-encoded stuff\",\n                \"data\": \"http://ƒøø.ßår/?q=Test%20URL-encoded%20stuff\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a valid IRI with many special characters\",\n                \"data\": \"http://-.~_!$&'()*+,;=:%40:80%2f::::::@example.com\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a valid IRI based on IPv6\",\n                \"data\": \"http://[2001:0db8:85a3:0000:0000:8a2e:0370:7334]\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"an invalid IRI based on IPv6\",\n                \"data\": \"http://2001:0db8:85a3:0000:0000:8a2e:0370:7334\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"an invalid relative IRI Reference\",\n                \"data\": \"/abc\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"an invalid IRI\",\n                \"data\": \"\\\\\\\\WINDOWS\\\\filëßåré\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"an invalid IRI though valid IRI reference\",\n                \"data\": \"âππ\",\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/optional/format/json-pointer.json",
    "content": "[\n    {\n        \"description\": \"validation of JSON-pointers (JSON String Representation)\",\n        \"schema\": {\"format\": \"json-pointer\"},\n        \"tests\": [\n            {\n                \"description\": \"a valid JSON-pointer\",\n                \"data\": \"/foo/bar~0/baz~1/%a\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"not a valid JSON-pointer (~ not escaped)\",\n                \"data\": \"/foo/bar~\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"valid JSON-pointer with empty segment\",\n                \"data\": \"/foo//bar\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"valid JSON-pointer with the last empty segment\",\n                \"data\": \"/foo/bar/\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"valid JSON-pointer as stated in RFC 6901 #1\",\n                \"data\": \"\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"valid JSON-pointer as stated in RFC 6901 #2\",\n                \"data\": \"/foo\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"valid JSON-pointer as stated in RFC 6901 #3\",\n                \"data\": \"/foo/0\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"valid JSON-pointer as stated in RFC 6901 #4\",\n                \"data\": \"/\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"valid JSON-pointer as stated in RFC 6901 #5\",\n                \"data\": \"/a~1b\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"valid JSON-pointer as stated in RFC 6901 #6\",\n                \"data\": \"/c%d\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"valid JSON-pointer as stated in RFC 6901 #7\",\n                \"data\": \"/e^f\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"valid JSON-pointer as stated in RFC 6901 #8\",\n                \"data\": \"/g|h\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"valid JSON-pointer as stated in RFC 6901 #9\",\n                \"data\": \"/i\\\\j\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"valid JSON-pointer as stated in RFC 6901 #10\",\n                \"data\": \"/k\\\"l\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"valid JSON-pointer as stated in RFC 6901 #11\",\n                \"data\": \"/ \",\n                \"valid\": true\n            },\n            {\n                \"description\": \"valid JSON-pointer as stated in RFC 6901 #12\",\n                \"data\": \"/m~0n\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"valid JSON-pointer used adding to the last array position\",\n                \"data\": \"/foo/-\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"valid JSON-pointer (- used as object member name)\",\n                \"data\": \"/foo/-/bar\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"valid JSON-pointer (multiple escaped characters)\",\n                \"data\": \"/~1~0~0~1~1\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"valid JSON-pointer (escaped with fraction part) #1\",\n                \"data\": \"/~1.1\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"valid JSON-pointer (escaped with fraction part) #2\",\n                \"data\": \"/~0.1\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"not a valid JSON-pointer (URI Fragment Identifier) #1\",\n                \"data\": \"#\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"not a valid JSON-pointer (URI Fragment Identifier) #2\",\n                \"data\": \"#/\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"not a valid JSON-pointer (URI Fragment Identifier) #3\",\n                \"data\": \"#a\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"not a valid JSON-pointer (some escaped, but not all) #1\",\n                \"data\": \"/~0~\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"not a valid JSON-pointer (some escaped, but not all) #2\",\n                \"data\": \"/~0/~\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"not a valid JSON-pointer (wrong escape character) #1\",\n                \"data\": \"/~2\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"not a valid JSON-pointer (wrong escape character) #2\",\n                \"data\": \"/~-1\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"not a valid JSON-pointer (multiple characters not escaped)\",\n                \"data\": \"/~~\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"not a valid JSON-pointer (isn't empty nor starts with /) #1\",\n                \"data\": \"a\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"not a valid JSON-pointer (isn't empty nor starts with /) #2\",\n                \"data\": \"0\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"not a valid JSON-pointer (isn't empty nor starts with /) #3\",\n                \"data\": \"a/a\",\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/optional/format/regex.json",
    "content": "[\n    {\n        \"description\": \"validation of regular expressions\",\n        \"schema\": {\"format\": \"regex\"},\n        \"tests\": [\n            {\n                \"description\": \"a valid regular expression\",\n                \"data\": \"([abc])+\\\\s+$\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a regular expression with unclosed parens is invalid\",\n                \"data\": \"^(abc]\",\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/optional/format/relative-json-pointer.json",
    "content": "[\n    {\n        \"description\": \"validation of Relative JSON Pointers (RJP)\",\n        \"schema\": {\"format\": \"relative-json-pointer\"},\n        \"tests\": [\n            {\n                \"description\": \"a valid upwards RJP\",\n                \"data\": \"1\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a valid downwards RJP\",\n                \"data\": \"0/foo/bar\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a valid up and then down RJP, with array index\",\n                \"data\": \"2/0/baz/1/zip\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a valid RJP taking the member or index name\",\n                \"data\": \"0#\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"an invalid RJP that is a valid JSON Pointer\",\n                \"data\": \"/foo/bar\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"negative prefix\",\n                \"data\": \"-1/foo/bar\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"## is not a valid json-pointer\",\n                \"data\": \"0##\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"zero cannot be followed by other digits, plus json-pointer\",\n                \"data\": \"01/a\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"zero cannot be followed by other digits, plus octothorpe\",\n                \"data\": \"01#\",\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/optional/format/time.json",
    "content": "[\n    {\n        \"description\": \"validation of time strings\",\n        \"schema\": {\"format\": \"time\"},\n        \"tests\": [\n            {\n                \"description\": \"a valid time string\",\n                \"data\": \"08:30:06Z\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a valid time string with leap second, Zulu\",\n                \"data\": \"23:59:60Z\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"invalid leap second, Zulu (wrong hour)\",\n                \"data\": \"22:59:60Z\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"invalid leap second, Zulu (wrong minute)\",\n                \"data\": \"23:58:60Z\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"valid leap second, zero time-offset\",\n                \"data\": \"23:59:60+00:00\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"invalid leap second, zero time-offset (wrong hour)\",\n                \"data\": \"22:59:60+00:00\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"invalid leap second, zero time-offset (wrong minute)\",\n                \"data\": \"23:58:60+00:00\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"valid leap second, positive time-offset\",\n                \"data\": \"01:29:60+01:30\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"valid leap second, large positive time-offset\",\n                \"data\": \"23:29:60+23:30\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"invalid leap second, positive time-offset (wrong hour)\",\n                \"data\": \"23:59:60+01:00\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"invalid leap second, positive time-offset (wrong minute)\",\n                \"data\": \"23:59:60+00:30\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"valid leap second, negative time-offset\",\n                \"data\": \"15:59:60-08:00\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"valid leap second, large negative time-offset\",\n                \"data\": \"00:29:60-23:30\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"invalid leap second, negative time-offset (wrong hour)\",\n                \"data\": \"23:59:60-01:00\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"invalid leap second, negative time-offset (wrong minute)\",\n                \"data\": \"23:59:60-00:30\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"a valid time string with second fraction\",\n                \"data\": \"23:20:50.52Z\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a valid time string with precise second fraction\",\n                \"data\": \"08:30:06.283185Z\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a valid time string with plus offset\",\n                \"data\": \"08:30:06+00:20\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a valid time string with minus offset\",\n                \"data\": \"08:30:06-08:00\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a valid time string with case-insensitive Z\",\n                \"data\": \"08:30:06z\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"an invalid time string with invalid hour\",\n                \"data\": \"24:00:00Z\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"an invalid time string with invalid minute\",\n                \"data\": \"00:60:00Z\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"an invalid time string with invalid second\",\n                \"data\": \"00:00:61Z\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"an invalid time string with invalid leap second (wrong hour)\",\n                \"data\": \"22:59:60Z\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"an invalid time string with invalid leap second (wrong minute)\",\n                \"data\": \"23:58:60Z\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"an invalid time string with invalid time numoffset hour\",\n                \"data\": \"01:02:03+24:00\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"an invalid time string with invalid time numoffset minute\",\n                \"data\": \"01:02:03+00:60\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"an invalid time string with invalid time with both Z and numoffset\",\n                \"data\": \"01:02:03Z+00:30\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"an invalid offset indicator\",\n                \"data\": \"08:30:06 PST\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"only RFC3339 not all of ISO 8601 are valid\",\n                \"data\": \"01:01:01,1111\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"no time offset\",\n                \"data\": \"12:00:00\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"non-ascii digits should be rejected\",\n                \"data\": \"1২:00:00Z\",\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/optional/format/uri-reference.json",
    "content": "[\n    {\n        \"description\": \"validation of URI References\",\n        \"schema\": {\"format\": \"uri-reference\"},\n        \"tests\": [\n            {\n                \"description\": \"a valid URI\",\n                \"data\": \"http://foo.bar/?baz=qux#quux\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a valid protocol-relative URI Reference\",\n                \"data\": \"//foo.bar/?baz=qux#quux\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a valid relative URI Reference\",\n                \"data\": \"/abc\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"an invalid URI Reference\",\n                \"data\": \"\\\\\\\\WINDOWS\\\\fileshare\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"a valid URI Reference\",\n                \"data\": \"abc\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a valid URI fragment\",\n                \"data\": \"#fragment\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"an invalid URI fragment\",\n                \"data\": \"#frag\\\\ment\",\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/optional/format/uri-template.json",
    "content": "[\n    {\n        \"description\": \"format: uri-template\",\n        \"schema\": {\"format\": \"uri-template\"},\n        \"tests\": [\n            {\n                \"description\": \"a valid uri-template\",\n                \"data\": \"http://example.com/dictionary/{term:1}/{term}\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"an invalid uri-template\",\n                \"data\": \"http://example.com/dictionary/{term:1}/{term\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"a valid uri-template without variables\",\n                \"data\": \"http://example.com/dictionary\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a valid relative uri-template\",\n                \"data\": \"dictionary/{term:1}/{term}\",\n                \"valid\": true\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/optional/format/uri.json",
    "content": "[\n    {\n        \"description\": \"validation of URIs\",\n        \"schema\": {\"format\": \"uri\"},\n        \"tests\": [\n            {\n                \"description\": \"a valid URL with anchor tag\",\n                \"data\": \"http://foo.bar/?baz=qux#quux\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a valid URL with anchor tag and parentheses\",\n                \"data\": \"http://foo.com/blah_(wikipedia)_blah#cite-1\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a valid URL with URL-encoded stuff\",\n                \"data\": \"http://foo.bar/?q=Test%20URL-encoded%20stuff\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a valid puny-coded URL \",\n                \"data\": \"http://xn--nw2a.xn--j6w193g/\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a valid URL with many special characters\",\n                \"data\": \"http://-.~_!$&'()*+,;=:%40:80%2f::::::@example.com\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a valid URL based on IPv4\",\n                \"data\": \"http://223.255.255.254\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a valid URL with ftp scheme\",\n                \"data\": \"ftp://ftp.is.co.za/rfc/rfc1808.txt\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a valid URL for a simple text file\",\n                \"data\": \"http://www.ietf.org/rfc/rfc2396.txt\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a valid URL \",\n                \"data\": \"ldap://[2001:db8::7]/c=GB?objectClass?one\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a valid mailto URI\",\n                \"data\": \"mailto:John.Doe@example.com\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a valid newsgroup URI\",\n                \"data\": \"news:comp.infosystems.www.servers.unix\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a valid tel URI\",\n                \"data\": \"tel:+1-816-555-1212\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a valid URN\",\n                \"data\": \"urn:oasis:names:specification:docbook:dtd:xml:4.1.2\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"an invalid protocol-relative URI Reference\",\n                \"data\": \"//foo.bar/?baz=qux#quux\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"an invalid relative URI Reference\",\n                \"data\": \"/abc\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"an invalid URI\",\n                \"data\": \"\\\\\\\\WINDOWS\\\\fileshare\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"an invalid URI though valid URI reference\",\n                \"data\": \"abc\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"an invalid URI with spaces\",\n                \"data\": \"http:// shouldfail.com\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"an invalid URI with spaces and missing scheme\",\n                \"data\": \":// should fail\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"an invalid URI with comma in scheme\",\n                \"data\": \"bar,baz:foo\",\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/optional/format/uuid.json",
    "content": "[\n    {\n        \"description\": \"uuid format\",\n        \"schema\": {\n            \"format\": \"uuid\"\n        },\n        \"tests\": [\n            {\n                \"description\": \"all upper-case\",\n                \"data\": \"2EB8AA08-AA98-11EA-B4AA-73B441D16380\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"all lower-case\",\n                \"data\": \"2eb8aa08-aa98-11ea-b4aa-73b441d16380\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"mixed case\",\n                \"data\": \"2eb8aa08-AA98-11ea-B4Aa-73B441D16380\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"all zeroes is valid\",\n                \"data\": \"00000000-0000-0000-0000-000000000000\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"wrong length\",\n                \"data\": \"2eb8aa08-aa98-11ea-b4aa-73b441d1638\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"missing section\",\n                \"data\": \"2eb8aa08-aa98-11ea-73b441d16380\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"bad characters (not hex)\",\n                \"data\": \"2eb8aa08-aa98-11ea-b4ga-73b441d16380\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"no dashes\",\n                \"data\": \"2eb8aa08aa9811eab4aa73b441d16380\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"too few dashes\",\n                \"data\": \"2eb8aa08aa98-11ea-b4aa73b441d16380\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"too many dashes\",\n                \"data\": \"2eb8-aa08-aa98-11ea-b4aa73b44-1d16380\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"dashes in the wrong spot\",\n                \"data\": \"2eb8aa08aa9811eab4aa73b441d16380----\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"valid version 4\",\n                \"data\": \"98d80576-482e-427f-8434-7f86890ab222\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"valid version 5\",\n                \"data\": \"99c17cbb-656f-564a-940f-1a4568f03487\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"hypothetical version 6\",\n                \"data\": \"99c17cbb-656f-664a-940f-1a4568f03487\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"hypothetical version 15\",\n                \"data\": \"99c17cbb-656f-f64a-940f-1a4568f03487\",\n                \"valid\": true\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/optional/non-bmp-regex.json",
    "content": "[\n    {\n        \"description\": \"Proper UTF-16 surrogate pair handling: pattern\",\n        \"comment\": \"Optional because .Net doesn't correctly handle 32-bit Unicode characters\",\n        \"schema\": { \"pattern\": \"^🐲*$\" },\n        \"tests\": [\n            {\n                \"description\": \"matches empty\",\n                \"data\": \"\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"matches single\",\n                \"data\": \"🐲\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"matches two\",\n                \"data\": \"🐲🐲\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"doesn't match one\",\n                \"data\": \"🐉\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"doesn't match two\",\n                \"data\": \"🐉🐉\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"doesn't match one ASCII\",\n                \"data\": \"D\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"doesn't match two ASCII\",\n                \"data\": \"DD\",\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"Proper UTF-16 surrogate pair handling: patternProperties\",\n        \"comment\": \"Optional because .Net doesn't correctly handle 32-bit Unicode characters\",\n        \"schema\": {\n            \"patternProperties\": {\n                \"^🐲*$\": {\n                    \"type\": \"integer\"\n                }\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"matches empty\",\n                \"data\": { \"\": 1 },\n                \"valid\": true\n            },\n            {\n                \"description\": \"matches single\",\n                \"data\": { \"🐲\": 1 },\n                \"valid\": true\n            },\n            {\n                \"description\": \"matches two\",\n                \"data\": { \"🐲🐲\": 1 },\n                \"valid\": true\n            },\n            {\n                \"description\": \"doesn't match one\",\n                \"data\": { \"🐲\": \"hello\" },\n                \"valid\": false\n            },\n            {\n                \"description\": \"doesn't match two\",\n                \"data\": { \"🐲🐲\": \"hello\" },\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/optional/unicode.json",
    "content": "[\n    {\n        \"description\": \"unicode semantics should be used for all pattern matching\",\n        \"schema\": { \"pattern\": \"\\\\wcole\" },\n        \"tests\": [\n            {\n                \"description\": \"literal unicode character in json string\",\n                \"data\": \"Les hivers de mon enfance étaient des saisons longues, longues. Nous vivions en trois lieux: l'école, l'église et la patinoire; mais la vraie vie était sur la patinoire.\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"unicode character in hex format in string\",\n                \"data\": \"Les hivers de mon enfance étaient des saisons longues, longues. Nous vivions en trois lieux: l'\\u00e9cole, l'église et la patinoire; mais la vraie vie était sur la patinoire.\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"unicode matching is case-sensitive\",\n                \"data\": \"LES HIVERS DE MON ENFANCE ÉTAIENT DES SAISONS LONGUES, LONGUES. NOUS VIVIONS EN TROIS LIEUX: L'ÉCOLE, L'ÉGLISE ET LA PATINOIRE; MAIS LA VRAIE VIE ÉTAIT SUR LA PATINOIRE.\",\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"unicode characters do not match ascii ranges\",\n        \"schema\": { \"pattern\": \"[a-z]cole\" },\n        \"tests\": [\n            {\n                \"description\": \"literal unicode character in json string\",\n                \"data\": \"Les hivers de mon enfance étaient des saisons longues, longues. Nous vivions en trois lieux: l'école, l'église et la patinoire; mais la vraie vie était sur la patinoire.\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"unicode character in hex format in string\",\n                \"data\": \"Les hivers de mon enfance étaient des saisons longues, longues. Nous vivions en trois lieux: l'\\u00e9cole, l'église et la patinoire; mais la vraie vie était sur la patinoire.\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"ascii characters match\",\n                \"data\": \"Les hivers de mon enfance etaient des saisons longues, longues. Nous vivions en trois lieux: l'ecole, l'eglise et la patinoire; mais la vraie vie etait sur la patinoire.\",\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"unicode digits are more than 0 through 9\",\n        \"schema\": { \"pattern\": \"^\\\\d+$\" },\n        \"tests\": [\n            {\n                \"description\": \"ascii digits\",\n                \"data\": \"42\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"ascii non-digits\",\n                \"data\": \"-%#\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"non-ascii digits (BENGALI DIGIT FOUR, BENGALI DIGIT TWO)\",\n                \"data\": \"৪২\",\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"unicode semantics should be used for all patternProperties matching\",\n        \"schema\": {\n            \"type\": \"object\",\n            \"patternProperties\": {\n                \"\\\\wcole\": true\n            },\n            \"additionalProperties\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"literal unicode character in json string\",\n                \"data\": { \"l'école\": \"pas de vraie vie\" },\n                \"valid\": true\n            },\n            {\n                \"description\": \"unicode character in hex format in string\",\n                \"data\": { \"l'\\u00e9cole\": \"pas de vraie vie\" },\n                \"valid\": true\n            },\n            {\n                \"description\": \"unicode matching is case-sensitive\",\n                \"data\": { \"L'ÉCOLE\": \"PAS DE VRAIE VIE\" },\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"unicode characters do not match ascii ranges\",\n        \"schema\": {\n            \"type\": \"object\",\n            \"patternProperties\": {\n                \"[a-z]cole\": true\n            },\n            \"additionalProperties\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"literal unicode character in json string\",\n                \"data\": { \"l'école\": \"pas de vraie vie\" },\n                \"valid\": false\n            },\n            {\n                \"description\": \"unicode character in hex format in string\",\n                \"data\": { \"l'\\u00e9cole\": \"pas de vraie vie\" },\n                \"valid\": false\n            },\n            {\n                \"description\": \"ascii characters match\",\n                \"data\": { \"l'ecole\": \"pas de vraie vie\" },\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"unicode digits are more than 0 through 9\",\n        \"schema\": {\n            \"type\": \"object\",\n            \"patternProperties\": {\n                \"^\\\\d+$\": true\n            },\n            \"additionalProperties\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"ascii digits\",\n                \"data\": { \"42\": \"life, the universe, and everything\" },\n                \"valid\": true\n            },\n            {\n                \"description\": \"ascii non-digits\",\n                \"data\": { \"-%#\": \"spending the year dead for tax reasons\" },\n                \"valid\": false\n            },\n            {\n                \"description\": \"non-ascii digits (BENGALI DIGIT FOUR, BENGALI DIGIT TWO)\",\n                \"data\": { \"৪২\": \"khajit has wares if you have coin\" },\n                \"valid\": true\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/pattern.json",
    "content": "[\n    {\n        \"description\": \"pattern validation\",\n        \"schema\": {\"pattern\": \"^a*$\"},\n        \"tests\": [\n            {\n                \"description\": \"a matching pattern is valid\",\n                \"data\": \"aaa\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a non-matching pattern is invalid\",\n                \"data\": \"abc\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"ignores booleans\",\n                \"data\": true,\n                \"valid\": true\n            },\n            {\n                \"description\": \"ignores integers\",\n                \"data\": 123,\n                \"valid\": true\n            },\n            {\n                \"description\": \"ignores floats\",\n                \"data\": 1.0,\n                \"valid\": true\n            },\n            {\n                \"description\": \"ignores objects\",\n                \"data\": {},\n                \"valid\": true\n            },\n            {\n                \"description\": \"ignores arrays\",\n                \"data\": [],\n                \"valid\": true\n            },\n            {\n                \"description\": \"ignores null\",\n                \"data\": null,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"pattern is not anchored\",\n        \"schema\": {\"pattern\": \"a+\"},\n        \"tests\": [\n            {\n                \"description\": \"matches a substring\",\n                \"data\": \"xxaayy\",\n                \"valid\": true\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/patternProperties.json",
    "content": "[\n    {\n        \"description\":\n            \"patternProperties validates properties matching a regex\",\n        \"schema\": {\n            \"patternProperties\": {\n                \"f.*o\": {\"type\": \"integer\"}\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"a single valid match is valid\",\n                \"data\": {\"foo\": 1},\n                \"valid\": true\n            },\n            {\n                \"description\": \"multiple valid matches is valid\",\n                \"data\": {\"foo\": 1, \"foooooo\" : 2},\n                \"valid\": true\n            },\n            {\n                \"description\": \"a single invalid match is invalid\",\n                \"data\": {\"foo\": \"bar\", \"fooooo\": 2},\n                \"valid\": false\n            },\n            {\n                \"description\": \"multiple invalid matches is invalid\",\n                \"data\": {\"foo\": \"bar\", \"foooooo\" : \"baz\"},\n                \"valid\": false\n            },\n            {\n                \"description\": \"ignores arrays\",\n                \"data\": [\"foo\"],\n                \"valid\": true\n            },\n            {\n                \"description\": \"ignores strings\",\n                \"data\": \"foo\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"ignores other non-objects\",\n                \"data\": 12,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"multiple simultaneous patternProperties are validated\",\n        \"schema\": {\n            \"patternProperties\": {\n                \"a*\": {\"type\": \"integer\"},\n                \"aaa*\": {\"maximum\": 20}\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"a single valid match is valid\",\n                \"data\": {\"a\": 21},\n                \"valid\": true\n            },\n            {\n                \"description\": \"a simultaneous match is valid\",\n                \"data\": {\"aaaa\": 18},\n                \"valid\": true\n            },\n            {\n                \"description\": \"multiple matches is valid\",\n                \"data\": {\"a\": 21, \"aaaa\": 18},\n                \"valid\": true\n            },\n            {\n                \"description\": \"an invalid due to one is invalid\",\n                \"data\": {\"a\": \"bar\"},\n                \"valid\": false\n            },\n            {\n                \"description\": \"an invalid due to the other is invalid\",\n                \"data\": {\"aaaa\": 31},\n                \"valid\": false\n            },\n            {\n                \"description\": \"an invalid due to both is invalid\",\n                \"data\": {\"aaa\": \"foo\", \"aaaa\": 31},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"regexes are not anchored by default and are case sensitive\",\n        \"schema\": {\n            \"patternProperties\": {\n                \"[0-9]{2,}\": { \"type\": \"boolean\" },\n                \"X_\": { \"type\": \"string\" }\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"non recognized members are ignored\",\n                \"data\": { \"answer 1\": \"42\" },\n                \"valid\": true\n            },\n            {\n                \"description\": \"recognized members are accounted for\",\n                \"data\": { \"a31b\": null },\n                \"valid\": false\n            },\n            {\n                \"description\": \"regexes are case sensitive\",\n                \"data\": { \"a_x_3\": 3 },\n                \"valid\": true\n            },\n            {\n                \"description\": \"regexes are case sensitive, 2\",\n                \"data\": { \"a_X_3\": 3 },\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"patternProperties with boolean schemas\",\n        \"schema\": {\n            \"patternProperties\": {\n                \"f.*\": true,\n                \"b.*\": false\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"object with property matching schema true is valid\",\n                \"data\": {\"foo\": 1},\n                \"valid\": true\n            },\n            {\n                \"description\": \"object with property matching schema false is invalid\",\n                \"data\": {\"bar\": 2},\n                \"valid\": false\n            },\n            {\n                \"description\": \"object with both properties is invalid\",\n                \"data\": {\"foo\": 1, \"bar\": 2},\n                \"valid\": false\n            },\n            {\n                \"description\": \"object with a property matching both true and false is invalid\",\n                \"data\": {\"foobar\":1},\n                \"valid\": false\n            },\n            {\n                \"description\": \"empty object is valid\",\n                \"data\": {},\n                \"valid\": true\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/properties.json",
    "content": "[\n    {\n        \"description\": \"object properties validation\",\n        \"schema\": {\n            \"properties\": {\n                \"foo\": {\"type\": \"integer\"},\n                \"bar\": {\"type\": \"string\"}\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"both properties present and valid is valid\",\n                \"data\": {\"foo\": 1, \"bar\": \"baz\"},\n                \"valid\": true\n            },\n            {\n                \"description\": \"one property invalid is invalid\",\n                \"data\": {\"foo\": 1, \"bar\": {}},\n                \"valid\": false\n            },\n            {\n                \"description\": \"both properties invalid is invalid\",\n                \"data\": {\"foo\": [], \"bar\": {}},\n                \"valid\": false\n            },\n            {\n                \"description\": \"doesn't invalidate other properties\",\n                \"data\": {\"quux\": []},\n                \"valid\": true\n            },\n            {\n                \"description\": \"ignores arrays\",\n                \"data\": [],\n                \"valid\": true\n            },\n            {\n                \"description\": \"ignores other non-objects\",\n                \"data\": 12,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\":\n            \"properties, patternProperties, additionalProperties interaction\",\n        \"schema\": {\n            \"properties\": {\n                \"foo\": {\"type\": \"array\", \"maxItems\": 3},\n                \"bar\": {\"type\": \"array\"}\n            },\n            \"patternProperties\": {\"f.o\": {\"minItems\": 2}},\n            \"additionalProperties\": {\"type\": \"integer\"}\n        },\n        \"tests\": [\n            {\n                \"description\": \"property validates property\",\n                \"data\": {\"foo\": [1, 2]},\n                \"valid\": true\n            },\n            {\n                \"description\": \"property invalidates property\",\n                \"data\": {\"foo\": [1, 2, 3, 4]},\n                \"valid\": false\n            },\n            {\n                \"description\": \"patternProperty invalidates property\",\n                \"data\": {\"foo\": []},\n                \"valid\": false\n            },\n            {\n                \"description\": \"patternProperty validates nonproperty\",\n                \"data\": {\"fxo\": [1, 2]},\n                \"valid\": true\n            },\n            {\n                \"description\": \"patternProperty invalidates nonproperty\",\n                \"data\": {\"fxo\": []},\n                \"valid\": false\n            },\n            {\n                \"description\": \"additionalProperty ignores property\",\n                \"data\": {\"bar\": []},\n                \"valid\": true\n            },\n            {\n                \"description\": \"additionalProperty validates others\",\n                \"data\": {\"quux\": 3},\n                \"valid\": true\n            },\n            {\n                \"description\": \"additionalProperty invalidates others\",\n                \"data\": {\"quux\": \"foo\"},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"properties with boolean schema\",\n        \"schema\": {\n            \"properties\": {\n                \"foo\": true,\n                \"bar\": false\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"no property present is valid\",\n                \"data\": {},\n                \"valid\": true\n            },\n            {\n                \"description\": \"only 'true' property present is valid\",\n                \"data\": {\"foo\": 1},\n                \"valid\": true\n            },\n            {\n                \"description\": \"only 'false' property present is invalid\",\n                \"data\": {\"bar\": 2},\n                \"valid\": false\n            },\n            {\n                \"description\": \"both properties present is invalid\",\n                \"data\": {\"foo\": 1, \"bar\": 2},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"properties with escaped characters\",\n        \"schema\": {\n            \"properties\": {\n                \"foo\\nbar\": {\"type\": \"number\"},\n                \"foo\\\"bar\": {\"type\": \"number\"},\n                \"foo\\\\bar\": {\"type\": \"number\"},\n                \"foo\\rbar\": {\"type\": \"number\"},\n                \"foo\\tbar\": {\"type\": \"number\"},\n                \"foo\\fbar\": {\"type\": \"number\"}\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"object with all numbers is valid\",\n                \"data\": {\n                    \"foo\\nbar\": 1,\n                    \"foo\\\"bar\": 1,\n                    \"foo\\\\bar\": 1,\n                    \"foo\\rbar\": 1,\n                    \"foo\\tbar\": 1,\n                    \"foo\\fbar\": 1\n                },\n                \"valid\": true\n            },\n            {\n                \"description\": \"object with strings is invalid\",\n                \"data\": {\n                    \"foo\\nbar\": \"1\",\n                    \"foo\\\"bar\": \"1\",\n                    \"foo\\\\bar\": \"1\",\n                    \"foo\\rbar\": \"1\",\n                    \"foo\\tbar\": \"1\",\n                    \"foo\\fbar\": \"1\"\n                },\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/propertyNames.json",
    "content": "[\n    {\n        \"description\": \"propertyNames validation\",\n        \"schema\": {\n            \"propertyNames\": {\"maxLength\": 3}\n        },\n        \"tests\": [\n            {\n                \"description\": \"all property names valid\",\n                \"data\": {\n                    \"f\": {},\n                    \"foo\": {}\n                },\n                \"valid\": true\n            },\n            {\n                \"description\": \"some property names invalid\",\n                \"data\": {\n                    \"foo\": {},\n                    \"foobar\": {}\n                },\n                \"valid\": false\n            },\n            {\n                \"description\": \"object without properties is valid\",\n                \"data\": {},\n                \"valid\": true\n            },\n            {\n                \"description\": \"ignores arrays\",\n                \"data\": [1, 2, 3, 4],\n                \"valid\": true\n            },\n            {\n                \"description\": \"ignores strings\",\n                \"data\": \"foobar\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"ignores other non-objects\",\n                \"data\": 12,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"propertyNames validation with pattern\",\n        \"schema\": {\n            \"propertyNames\": { \"pattern\": \"^a+$\" }\n        },\n        \"tests\": [\n            {\n                \"description\": \"matching property names valid\",\n                \"data\": {\n                    \"a\": {},\n                    \"aa\": {},\n                    \"aaa\": {}\n                },\n                \"valid\": true\n            },\n            {\n                \"description\": \"non-matching property name is invalid\",\n                \"data\": {\n                    \"aaA\": {}\n                },\n                \"valid\": false\n            },\n            {\n                \"description\": \"object without properties is valid\",\n                \"data\": {},\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"propertyNames with boolean schema true\",\n        \"schema\": {\"propertyNames\": true},\n        \"tests\": [\n            {\n                \"description\": \"object with any properties is valid\",\n                \"data\": {\"foo\": 1},\n                \"valid\": true\n            },\n            {\n                \"description\": \"empty object is valid\",\n                \"data\": {},\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"propertyNames with boolean schema false\",\n        \"schema\": {\"propertyNames\": false},\n        \"tests\": [\n            {\n                \"description\": \"object with any properties is invalid\",\n                \"data\": {\"foo\": 1},\n                \"valid\": false\n            },\n            {\n                \"description\": \"empty object is valid\",\n                \"data\": {},\n                \"valid\": true\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/ref.json",
    "content": "[\n    {\n        \"description\": \"root pointer ref\",\n        \"schema\": {\n            \"properties\": {\n                \"foo\": {\"$ref\": \"#\"}\n            },\n            \"additionalProperties\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"match\",\n                \"data\": {\"foo\": false},\n                \"valid\": true\n            },\n            {\n                \"description\": \"recursive match\",\n                \"data\": {\"foo\": {\"foo\": false}},\n                \"valid\": true\n            },\n            {\n                \"description\": \"mismatch\",\n                \"data\": {\"bar\": false},\n                \"valid\": false\n            },\n            {\n                \"description\": \"recursive mismatch\",\n                \"data\": {\"foo\": {\"bar\": false}},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"relative pointer ref to object\",\n        \"schema\": {\n            \"properties\": {\n                \"foo\": {\"type\": \"integer\"},\n                \"bar\": {\"$ref\": \"#/properties/foo\"}\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"match\",\n                \"data\": {\"bar\": 3},\n                \"valid\": true\n            },\n            {\n                \"description\": \"mismatch\",\n                \"data\": {\"bar\": true},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"relative pointer ref to array\",\n        \"schema\": {\n            \"items\": [\n                {\"type\": \"integer\"},\n                {\"$ref\": \"#/items/0\"}\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"match array\",\n                \"data\": [1, 2],\n                \"valid\": true\n            },\n            {\n                \"description\": \"mismatch array\",\n                \"data\": [1, \"foo\"],\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"escaped pointer ref\",\n        \"schema\": {\n            \"definitions\": {\n                \"tilde~field\": {\"type\": \"integer\"},\n                \"slash/field\": {\"type\": \"integer\"},\n                \"percent%field\": {\"type\": \"integer\"}\n            },\n            \"properties\": {\n                \"tilde\": {\"$ref\": \"#/definitions/tilde~0field\"},\n                \"slash\": {\"$ref\": \"#/definitions/slash~1field\"},\n                \"percent\": {\"$ref\": \"#/definitions/percent%25field\"}\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"slash invalid\",\n                \"data\": {\"slash\": \"aoeu\"},\n                \"valid\": false\n            },\n            {\n                \"description\": \"tilde invalid\",\n                \"data\": {\"tilde\": \"aoeu\"},\n                \"valid\": false\n            },\n            {\n                \"description\": \"percent invalid\",\n                \"data\": {\"percent\": \"aoeu\"},\n                \"valid\": false\n            },\n            {\n                \"description\": \"slash valid\",\n                \"data\": {\"slash\": 123},\n                \"valid\": true\n            },\n            {\n                \"description\": \"tilde valid\",\n                \"data\": {\"tilde\": 123},\n                \"valid\": true\n            },\n            {\n                \"description\": \"percent valid\",\n                \"data\": {\"percent\": 123},\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"nested refs\",\n        \"schema\": {\n            \"definitions\": {\n                \"a\": {\"type\": \"integer\"},\n                \"b\": {\"$ref\": \"#/definitions/a\"},\n                \"c\": {\"$ref\": \"#/definitions/b\"}\n            },\n            \"allOf\": [{ \"$ref\": \"#/definitions/c\" }]\n        },\n        \"tests\": [\n            {\n                \"description\": \"nested ref valid\",\n                \"data\": 5,\n                \"valid\": true\n            },\n            {\n                \"description\": \"nested ref invalid\",\n                \"data\": \"a\",\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"ref overrides any sibling keywords\",\n        \"schema\": {\n            \"definitions\": {\n                \"reffed\": {\n                    \"type\": \"array\"\n                }\n            },\n            \"properties\": {\n                \"foo\": {\n                    \"$ref\": \"#/definitions/reffed\",\n                    \"maxItems\": 2\n                }\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"ref valid\",\n                \"data\": { \"foo\": [] },\n                \"valid\": true\n            },\n            {\n                \"description\": \"ref valid, maxItems ignored\",\n                \"data\": { \"foo\": [ 1, 2, 3] },\n                \"valid\": true\n            },\n            {\n                \"description\": \"ref invalid\",\n                \"data\": { \"foo\": \"string\" },\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"$ref prevents a sibling $id from changing the base uri\",\n        \"schema\": {\n            \"$id\": \"http://localhost:1234/sibling_id/base/\",\n            \"definitions\": {\n                \"foo\": {\n                    \"$id\": \"http://localhost:1234/sibling_id/foo.json\",\n                    \"minimum\": 2\n                },\n                \"base_foo\": {\n                    \"$comment\": \"this canonical uri is http://localhost:1234/sibling_id/base/foo.json\",\n                    \"$id\": \"foo.json\",\n                    \"minimum\": 5\n                }\n            },\n            \"allOf\": [\n                {\n                    \"$comment\": \"$ref resolves to http://localhost:1234/sibling_id/base/foo.json, not ttp://localhost:1234/sibling_id/foo.json\",\n                    \"$id\": \"http://localhost:1234/sibling_id/\",\n                    \"$ref\": \"foo.json\"\n                }\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"$ref resolves to /definitions/foo, data validates\",\n                \"data\": 10,\n                \"valid\": true\n            },\n            {\n                \"description\": \"$ref resolves to /definitions/foo, data does not validate\",\n                \"data\": 1,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"remote ref, containing refs itself\",\n        \"schema\": {\"$ref\": \"http://json-schema.org/draft-07/schema#\"},\n        \"tests\": [\n            {\n                \"description\": \"remote ref valid\",\n                \"data\": {\"minLength\": 1},\n                \"valid\": true\n            },\n            {\n                \"description\": \"remote ref invalid\",\n                \"data\": {\"minLength\": -1},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"property named $ref that is not a reference\",\n        \"schema\": {\n            \"properties\": {\n                \"$ref\": {\"type\": \"string\"}\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"property named $ref valid\",\n                \"data\": {\"$ref\": \"a\"},\n                \"valid\": true\n            },\n            {\n                \"description\": \"property named $ref invalid\",\n                \"data\": {\"$ref\": 2},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"property named $ref, containing an actual $ref\",\n        \"schema\": {\n            \"properties\": {\n                \"$ref\": {\"$ref\": \"#/definitions/is-string\"}\n            },\n            \"definitions\": {\n                \"is-string\": {\n                    \"type\": \"string\"\n                }\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"property named $ref valid\",\n                \"data\": {\"$ref\": \"a\"},\n                \"valid\": true\n            },\n            {\n                \"description\": \"property named $ref invalid\",\n                \"data\": {\"$ref\": 2},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"$ref to boolean schema true\",\n        \"schema\": {\n            \"allOf\": [{ \"$ref\": \"#/definitions/bool\" }],\n            \"definitions\": {\n                \"bool\": true\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"any value is valid\",\n                \"data\": \"foo\",\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"$ref to boolean schema false\",\n        \"schema\": {\n            \"allOf\": [{ \"$ref\": \"#/definitions/bool\" }],\n            \"definitions\": {\n                \"bool\": false\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"any value is invalid\",\n                \"data\": \"foo\",\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"Recursive references between schemas\",\n        \"schema\": {\n            \"$id\": \"http://localhost:1234/tree\",\n            \"description\": \"tree of nodes\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"meta\": {\"type\": \"string\"},\n                \"nodes\": {\n                    \"type\": \"array\",\n                    \"items\": {\"$ref\": \"node\"}\n                }\n            },\n            \"required\": [\"meta\", \"nodes\"],\n            \"definitions\": {\n                \"node\": {\n                    \"$id\": \"http://localhost:1234/node\",\n                    \"description\": \"node\",\n                    \"type\": \"object\",\n                    \"properties\": {\n                        \"value\": {\"type\": \"number\"},\n                        \"subtree\": {\"$ref\": \"tree\"}\n                    },\n                    \"required\": [\"value\"]\n                }\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"valid tree\",\n                \"data\": {\n                    \"meta\": \"root\",\n                    \"nodes\": [\n                        {\n                            \"value\": 1,\n                            \"subtree\": {\n                                \"meta\": \"child\",\n                                \"nodes\": [\n                                    {\"value\": 1.1},\n                                    {\"value\": 1.2}\n                                ]\n                            }\n                        },\n                        {\n                            \"value\": 2,\n                            \"subtree\": {\n                                \"meta\": \"child\",\n                                \"nodes\": [\n                                    {\"value\": 2.1},\n                                    {\"value\": 2.2}\n                                ]\n                            }\n                        }\n                    ]\n                },\n                \"valid\": true\n            },\n            {\n                \"description\": \"invalid tree\",\n                \"data\": {\n                    \"meta\": \"root\",\n                    \"nodes\": [\n                        {\n                            \"value\": 1,\n                            \"subtree\": {\n                                \"meta\": \"child\",\n                                \"nodes\": [\n                                    {\"value\": \"string is invalid\"},\n                                    {\"value\": 1.2}\n                                ]\n                            }\n                        },\n                        {\n                            \"value\": 2,\n                            \"subtree\": {\n                                \"meta\": \"child\",\n                                \"nodes\": [\n                                    {\"value\": 2.1},\n                                    {\"value\": 2.2}\n                                ]\n                            }\n                        }\n                    ]\n                },\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"refs with quote\",\n        \"schema\": {\n            \"properties\": {\n                \"foo\\\"bar\": {\"$ref\": \"#/definitions/foo%22bar\"}\n            },\n            \"definitions\": {\n                \"foo\\\"bar\": {\"type\": \"number\"}\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"object with numbers is valid\",\n                \"data\": {\n                    \"foo\\\"bar\": 1\n                },\n                \"valid\": true\n            },\n            {\n                \"description\": \"object with strings is invalid\",\n                \"data\": {\n                    \"foo\\\"bar\": \"1\"\n                },\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"Location-independent identifier\",\n        \"schema\": {\n            \"allOf\": [{\n                \"$ref\": \"#foo\"\n            }],\n            \"definitions\": {\n                \"A\": {\n                    \"$id\": \"#foo\",\n                    \"type\": \"integer\"\n                }\n            }\n        },\n        \"tests\": [\n            {\n                \"data\": 1,\n                \"description\": \"match\",\n                \"valid\": true\n            },\n            {\n                \"data\": \"a\",\n                \"description\": \"mismatch\",\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"Location-independent identifier with base URI change in subschema\",\n        \"schema\": {\n            \"$id\": \"http://localhost:1234/root\",\n            \"allOf\": [{\n                \"$ref\": \"http://localhost:1234/nested.json#foo\"\n            }],\n            \"definitions\": {\n                \"A\": {\n                    \"$id\": \"nested.json\",\n                    \"definitions\": {\n                        \"B\": {\n                            \"$id\": \"#foo\",\n                            \"type\": \"integer\"\n                        }\n                    }\n                }\n            }\n        },\n        \"tests\": [\n            {\n                \"data\": 1,\n                \"description\": \"match\",\n                \"valid\": true\n            },\n            {\n                \"data\": \"a\",\n                \"description\": \"mismatch\",\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"naive replacement of $ref with its destination is not correct\",\n        \"schema\": {\n            \"definitions\": {\n                \"a_string\": { \"type\": \"string\" }\n            },\n            \"enum\": [\n                { \"$ref\": \"#/definitions/a_string\" }\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"do not evaluate the $ref inside the enum, matching any string\",\n                \"data\": \"this is a string\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"do not evaluate the $ref inside the enum, definition exact match\",\n                \"data\": { \"type\": \"string\" },\n                \"valid\": false\n            },\n            {\n                \"description\": \"match the enum exactly\",\n                \"data\": { \"$ref\": \"#/definitions/a_string\" },\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"refs with relative uris and defs\",\n        \"schema\": {\n            \"$id\": \"http://example.com/schema-relative-uri-defs1.json\",\n            \"properties\": {\n                \"foo\": {\n                    \"$id\": \"schema-relative-uri-defs2.json\",\n                    \"definitions\": {\n                        \"inner\": {\n                            \"properties\": {\n                                \"bar\": { \"type\": \"string\" }\n                            }\n                        }\n                    },\n                    \"allOf\": [ { \"$ref\": \"#/definitions/inner\" } ]\n                }\n            },\n            \"allOf\": [ { \"$ref\": \"schema-relative-uri-defs2.json\" } ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"invalid on inner field\",\n                \"data\": {\n                    \"foo\": {\n                        \"bar\": 1\n                    },\n                    \"bar\": \"a\"\n                },\n                \"valid\": false\n            },\n            {\n                \"description\": \"invalid on outer field\",\n                \"data\": {\n                    \"foo\": {\n                        \"bar\": \"a\"\n                    },\n                    \"bar\": 1\n                },\n                \"valid\": false\n            },\n            {\n                \"description\": \"valid on both fields\",\n                \"data\": {\n                    \"foo\": {\n                        \"bar\": \"a\"\n                    },\n                    \"bar\": \"a\"\n                },\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"relative refs with absolute uris and defs\",\n        \"schema\": {\n            \"$id\": \"http://example.com/schema-refs-absolute-uris-defs1.json\",\n            \"properties\": {\n                \"foo\": {\n                    \"$id\": \"http://example.com/schema-refs-absolute-uris-defs2.json\",\n                    \"definitions\": {\n                        \"inner\": {\n                            \"properties\": {\n                                \"bar\": { \"type\": \"string\" }\n                            }\n                        }\n                    },\n                    \"allOf\": [ { \"$ref\": \"#/definitions/inner\" } ]\n                }\n            },\n            \"allOf\": [ { \"$ref\": \"schema-refs-absolute-uris-defs2.json\" } ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"invalid on inner field\",\n                \"data\": {\n                    \"foo\": {\n                        \"bar\": 1\n                    },\n                    \"bar\": \"a\"\n                },\n                \"valid\": false\n            },\n            {\n                \"description\": \"invalid on outer field\",\n                \"data\": {\n                    \"foo\": {\n                        \"bar\": \"a\"\n                    },\n                    \"bar\": 1\n                },\n                \"valid\": false\n            },\n            {\n                \"description\": \"valid on both fields\",\n                \"data\": {\n                    \"foo\": {\n                        \"bar\": \"a\"\n                    },\n                    \"bar\": \"a\"\n                },\n                \"valid\": true\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/refRemote.json",
    "content": "[\n    {\n        \"description\": \"remote ref\",\n        \"schema\": {\"$ref\": \"http://localhost:1234/integer.json\"},\n        \"tests\": [\n            {\n                \"description\": \"remote ref valid\",\n                \"data\": 1,\n                \"valid\": true\n            },\n            {\n                \"description\": \"remote ref invalid\",\n                \"data\": \"a\",\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"fragment within remote ref\",\n        \"schema\": {\"$ref\": \"http://localhost:1234/subSchemas.json#/integer\"},\n        \"tests\": [\n            {\n                \"description\": \"remote fragment valid\",\n                \"data\": 1,\n                \"valid\": true\n            },\n            {\n                \"description\": \"remote fragment invalid\",\n                \"data\": \"a\",\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"ref within remote ref\",\n        \"schema\": {\n            \"$ref\": \"http://localhost:1234/subSchemas.json#/refToInteger\"\n        },\n        \"tests\": [\n            {\n                \"description\": \"ref within ref valid\",\n                \"data\": 1,\n                \"valid\": true\n            },\n            {\n                \"description\": \"ref within ref invalid\",\n                \"data\": \"a\",\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"base URI change\",\n        \"schema\": {\n            \"$id\": \"http://localhost:1234/\",\n            \"items\": {\n                \"$id\": \"baseUriChange/\",\n                \"items\": {\"$ref\": \"folderInteger.json\"}\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"base URI change ref valid\",\n                \"data\": [[1]],\n                \"valid\": true\n            },\n            {\n                \"description\": \"base URI change ref invalid\",\n                \"data\": [[\"a\"]],\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"base URI change - change folder\",\n        \"schema\": {\n            \"$id\": \"http://localhost:1234/scope_change_defs1.json\",\n            \"type\" : \"object\",\n            \"properties\": {\n                \"list\": {\"$ref\": \"#/definitions/baz\"}\n            },\n            \"definitions\": {\n                \"baz\": {\n                    \"$id\": \"baseUriChangeFolder/\",\n                    \"type\": \"array\",\n                    \"items\": {\"$ref\": \"folderInteger.json\"}\n                }\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"number is valid\",\n                \"data\": {\"list\": [1]},\n                \"valid\": true\n            },\n            {\n                \"description\": \"string is invalid\",\n                \"data\": {\"list\": [\"a\"]},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"base URI change - change folder in subschema\",\n        \"schema\": {\n            \"$id\": \"http://localhost:1234/scope_change_defs2.json\",\n            \"type\" : \"object\",\n            \"properties\": {\n                \"list\": {\"$ref\": \"#/definitions/baz/definitions/bar\"}\n            },\n            \"definitions\": {\n                \"baz\": {\n                    \"$id\": \"baseUriChangeFolderInSubschema/\",\n                    \"definitions\": {\n                        \"bar\": {\n                            \"type\": \"array\",\n                            \"items\": {\"$ref\": \"folderInteger.json\"}\n                        }\n                    }\n                }\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"number is valid\",\n                \"data\": {\"list\": [1]},\n                \"valid\": true\n            },\n            {\n                \"description\": \"string is invalid\",\n                \"data\": {\"list\": [\"a\"]},\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"root ref in remote ref\",\n        \"schema\": {\n            \"$id\": \"http://localhost:1234/object\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"name\": {\"$ref\": \"name.json#/definitions/orNull\"}\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"string is valid\",\n                \"data\": {\n                    \"name\": \"foo\"\n                },\n                \"valid\": true\n            },\n            {\n                \"description\": \"null is valid\",\n                \"data\": {\n                    \"name\": null\n                },\n                \"valid\": true\n            },\n            {\n                \"description\": \"object is invalid\",\n                \"data\": {\n                    \"name\": {\n                        \"name\": null\n                    }\n                },\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"remote ref with ref to definitions\",\n        \"schema\": {\n            \"$id\": \"http://localhost:1234/schema-remote-ref-ref-defs1.json\",\n            \"allOf\": [\n                { \"$ref\": \"ref-and-definitions.json\" }\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"invalid\",\n                \"data\": {\n                    \"bar\": 1\n                },\n                \"valid\": false\n            },\n            {\n                \"description\": \"valid\",\n                \"data\": {\n                    \"bar\": \"a\"\n                },\n                \"valid\": true\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/required.json",
    "content": "[\n    {\n        \"description\": \"required validation\",\n        \"schema\": {\n            \"properties\": {\n                \"foo\": {},\n                \"bar\": {}\n            },\n            \"required\": [\"foo\"]\n        },\n        \"tests\": [\n            {\n                \"description\": \"present required property is valid\",\n                \"data\": {\"foo\": 1},\n                \"valid\": true\n            },\n            {\n                \"description\": \"non-present required property is invalid\",\n                \"data\": {\"bar\": 1},\n                \"valid\": false\n            },\n            {\n                \"description\": \"ignores arrays\",\n                \"data\": [],\n                \"valid\": true\n            },\n            {\n                \"description\": \"ignores strings\",\n                \"data\": \"\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"ignores other non-objects\",\n                \"data\": 12,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"required default validation\",\n        \"schema\": {\n            \"properties\": {\n                \"foo\": {}\n            }\n        },\n        \"tests\": [\n            {\n                \"description\": \"not required by default\",\n                \"data\": {},\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"required with empty array\",\n        \"schema\": {\n            \"properties\": {\n                \"foo\": {}\n            },\n            \"required\": []\n        },\n        \"tests\": [\n            {\n                \"description\": \"property not required\",\n                \"data\": {},\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"required with escaped characters\",\n        \"schema\": {\n            \"required\": [\n                \"foo\\nbar\",\n                \"foo\\\"bar\",\n                \"foo\\\\bar\",\n                \"foo\\rbar\",\n                \"foo\\tbar\",\n                \"foo\\fbar\"\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"object with all properties present is valid\",\n                \"data\": {\n                    \"foo\\nbar\": 1,\n                    \"foo\\\"bar\": 1,\n                    \"foo\\\\bar\": 1,\n                    \"foo\\rbar\": 1,\n                    \"foo\\tbar\": 1,\n                    \"foo\\fbar\": 1\n                },\n                \"valid\": true\n            },\n            {\n                \"description\": \"object with some properties missing is invalid\",\n                \"data\": {\n                    \"foo\\nbar\": \"1\",\n                    \"foo\\\"bar\": \"1\"\n                },\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/type.json",
    "content": "[\n    {\n        \"description\": \"integer type matches integers\",\n        \"schema\": {\"type\": \"integer\"},\n        \"tests\": [\n            {\n                \"description\": \"an integer is an integer\",\n                \"data\": 1,\n                \"valid\": true\n            },\n            {\n                \"description\": \"a float is not an integer\",\n                \"data\": 1.1,\n                \"valid\": false\n            },\n            {\n                \"description\": \"a string is not an integer\",\n                \"data\": \"foo\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"a string is still not an integer, even if it looks like one\",\n                \"data\": \"1\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"an object is not an integer\",\n                \"data\": {},\n                \"valid\": false\n            },\n            {\n                \"description\": \"an array is not an integer\",\n                \"data\": [],\n                \"valid\": false\n            },\n            {\n                \"description\": \"a boolean is not an integer\",\n                \"data\": true,\n                \"valid\": false\n            },\n            {\n                \"description\": \"null is not an integer\",\n                \"data\": null,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"number type matches numbers\",\n        \"schema\": {\"type\": \"number\"},\n        \"tests\": [\n            {\n                \"description\": \"an integer is a number\",\n                \"data\": 1,\n                \"valid\": true\n            },\n            {\n                \"description\": \"a float with zero fractional part is a number (and an integer)\",\n                \"data\": 1.0,\n                \"valid\": true\n            },\n            {\n                \"description\": \"a float is a number\",\n                \"data\": 1.1,\n                \"valid\": true\n            },\n            {\n                \"description\": \"a string is not a number\",\n                \"data\": \"foo\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"a string is still not a number, even if it looks like one\",\n                \"data\": \"1\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"an object is not a number\",\n                \"data\": {},\n                \"valid\": false\n            },\n            {\n                \"description\": \"an array is not a number\",\n                \"data\": [],\n                \"valid\": false\n            },\n            {\n                \"description\": \"a boolean is not a number\",\n                \"data\": true,\n                \"valid\": false\n            },\n            {\n                \"description\": \"null is not a number\",\n                \"data\": null,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"string type matches strings\",\n        \"schema\": {\"type\": \"string\"},\n        \"tests\": [\n            {\n                \"description\": \"1 is not a string\",\n                \"data\": 1,\n                \"valid\": false\n            },\n            {\n                \"description\": \"a float is not a string\",\n                \"data\": 1.1,\n                \"valid\": false\n            },\n            {\n                \"description\": \"a string is a string\",\n                \"data\": \"foo\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a string is still a string, even if it looks like a number\",\n                \"data\": \"1\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"an empty string is still a string\",\n                \"data\": \"\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"an object is not a string\",\n                \"data\": {},\n                \"valid\": false\n            },\n            {\n                \"description\": \"an array is not a string\",\n                \"data\": [],\n                \"valid\": false\n            },\n            {\n                \"description\": \"a boolean is not a string\",\n                \"data\": true,\n                \"valid\": false\n            },\n            {\n                \"description\": \"null is not a string\",\n                \"data\": null,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"object type matches objects\",\n        \"schema\": {\"type\": \"object\"},\n        \"tests\": [\n            {\n                \"description\": \"an integer is not an object\",\n                \"data\": 1,\n                \"valid\": false\n            },\n            {\n                \"description\": \"a float is not an object\",\n                \"data\": 1.1,\n                \"valid\": false\n            },\n            {\n                \"description\": \"a string is not an object\",\n                \"data\": \"foo\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"an object is an object\",\n                \"data\": {},\n                \"valid\": true\n            },\n            {\n                \"description\": \"an array is not an object\",\n                \"data\": [],\n                \"valid\": false\n            },\n            {\n                \"description\": \"a boolean is not an object\",\n                \"data\": true,\n                \"valid\": false\n            },\n            {\n                \"description\": \"null is not an object\",\n                \"data\": null,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"array type matches arrays\",\n        \"schema\": {\"type\": \"array\"},\n        \"tests\": [\n            {\n                \"description\": \"an integer is not an array\",\n                \"data\": 1,\n                \"valid\": false\n            },\n            {\n                \"description\": \"a float is not an array\",\n                \"data\": 1.1,\n                \"valid\": false\n            },\n            {\n                \"description\": \"a string is not an array\",\n                \"data\": \"foo\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"an object is not an array\",\n                \"data\": {},\n                \"valid\": false\n            },\n            {\n                \"description\": \"an array is an array\",\n                \"data\": [],\n                \"valid\": true\n            },\n            {\n                \"description\": \"a boolean is not an array\",\n                \"data\": true,\n                \"valid\": false\n            },\n            {\n                \"description\": \"null is not an array\",\n                \"data\": null,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"boolean type matches booleans\",\n        \"schema\": {\"type\": \"boolean\"},\n        \"tests\": [\n            {\n                \"description\": \"an integer is not a boolean\",\n                \"data\": 1,\n                \"valid\": false\n            },\n            {\n                \"description\": \"zero is not a boolean\",\n                \"data\": 0,\n                \"valid\": false\n            },\n            {\n                \"description\": \"a float is not a boolean\",\n                \"data\": 1.1,\n                \"valid\": false\n            },\n            {\n                \"description\": \"a string is not a boolean\",\n                \"data\": \"foo\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"an empty string is not a boolean\",\n                \"data\": \"\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"an object is not a boolean\",\n                \"data\": {},\n                \"valid\": false\n            },\n            {\n                \"description\": \"an array is not a boolean\",\n                \"data\": [],\n                \"valid\": false\n            },\n            {\n                \"description\": \"true is a boolean\",\n                \"data\": true,\n                \"valid\": true\n            },\n            {\n                \"description\": \"false is a boolean\",\n                \"data\": false,\n                \"valid\": true\n            },\n            {\n                \"description\": \"null is not a boolean\",\n                \"data\": null,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"null type matches only the null object\",\n        \"schema\": {\"type\": \"null\"},\n        \"tests\": [\n            {\n                \"description\": \"an integer is not null\",\n                \"data\": 1,\n                \"valid\": false\n            },\n            {\n                \"description\": \"a float is not null\",\n                \"data\": 1.1,\n                \"valid\": false\n            },\n            {\n                \"description\": \"zero is not null\",\n                \"data\": 0,\n                \"valid\": false\n            },\n            {\n                \"description\": \"a string is not null\",\n                \"data\": \"foo\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"an empty string is not null\",\n                \"data\": \"\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"an object is not null\",\n                \"data\": {},\n                \"valid\": false\n            },\n            {\n                \"description\": \"an array is not null\",\n                \"data\": [],\n                \"valid\": false\n            },\n            {\n                \"description\": \"true is not null\",\n                \"data\": true,\n                \"valid\": false\n            },\n            {\n                \"description\": \"false is not null\",\n                \"data\": false,\n                \"valid\": false\n            },\n            {\n                \"description\": \"null is null\",\n                \"data\": null,\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"multiple types can be specified in an array\",\n        \"schema\": {\"type\": [\"integer\", \"string\"]},\n        \"tests\": [\n            {\n                \"description\": \"an integer is valid\",\n                \"data\": 1,\n                \"valid\": true\n            },\n            {\n                \"description\": \"a string is valid\",\n                \"data\": \"foo\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"a float is invalid\",\n                \"data\": 1.1,\n                \"valid\": false\n            },\n            {\n                \"description\": \"an object is invalid\",\n                \"data\": {},\n                \"valid\": false\n            },\n            {\n                \"description\": \"an array is invalid\",\n                \"data\": [],\n                \"valid\": false\n            },\n            {\n                \"description\": \"a boolean is invalid\",\n                \"data\": true,\n                \"valid\": false\n            },\n            {\n                \"description\": \"null is invalid\",\n                \"data\": null,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"type as array with one item\",\n        \"schema\": {\n            \"type\": [\"string\"]\n        },\n        \"tests\": [\n            {\n                \"description\": \"string is valid\",\n                \"data\": \"foo\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"number is invalid\",\n                \"data\": 123,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"type: array or object\",\n        \"schema\": {\n            \"type\": [\"array\", \"object\"]\n        },\n        \"tests\": [\n            {\n                \"description\": \"array is valid\",\n                \"data\": [1,2,3],\n                \"valid\": true\n            },\n            {\n                \"description\": \"object is valid\",\n                \"data\": {\"foo\": 123},\n                \"valid\": true\n            },\n            {\n                \"description\": \"number is invalid\",\n                \"data\": 123,\n                \"valid\": false\n            },\n            {\n                \"description\": \"string is invalid\",\n                \"data\": \"foo\",\n                \"valid\": false\n            },\n            {\n                \"description\": \"null is invalid\",\n                \"data\": null,\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"type: array, object or null\",\n        \"schema\": {\n            \"type\": [\"array\", \"object\", \"null\"]\n        },\n        \"tests\": [\n            {\n                \"description\": \"array is valid\",\n                \"data\": [1,2,3],\n                \"valid\": true\n            },\n            {\n                \"description\": \"object is valid\",\n                \"data\": {\"foo\": 123},\n                \"valid\": true\n            },\n            {\n                \"description\": \"null is valid\",\n                \"data\": null,\n                \"valid\": true\n            },\n            {\n                \"description\": \"number is invalid\",\n                \"data\": 123,\n                \"valid\": false\n            },\n            {\n                \"description\": \"string is invalid\",\n                \"data\": \"foo\",\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/uniqueItems.json",
    "content": "[\n    {\n        \"description\": \"uniqueItems validation\",\n        \"schema\": {\"uniqueItems\": true},\n        \"tests\": [\n            {\n                \"description\": \"unique array of integers is valid\",\n                \"data\": [1, 2],\n                \"valid\": true\n            },\n            {\n                \"description\": \"non-unique array of integers is invalid\",\n                \"data\": [1, 1],\n                \"valid\": false\n            },\n            {\n                \"description\": \"numbers are unique if mathematically unequal\",\n                \"data\": [1.0, 1.00, 1],\n                \"valid\": false\n            },\n            {\n                \"description\": \"false is not equal to zero\",\n                \"data\": [0, false],\n                \"valid\": true\n            },\n            {\n                \"description\": \"true is not equal to one\",\n                \"data\": [1, true],\n                \"valid\": true\n            },\n            {\n                \"description\": \"unique array of objects is valid\",\n                \"data\": [{\"foo\": \"bar\"}, {\"foo\": \"baz\"}],\n                \"valid\": true\n            },\n            {\n                \"description\": \"non-unique array of objects is invalid\",\n                \"data\": [{\"foo\": \"bar\"}, {\"foo\": \"bar\"}],\n                \"valid\": false\n            },\n            {\n                \"description\": \"unique array of nested objects is valid\",\n                \"data\": [\n                    {\"foo\": {\"bar\" : {\"baz\" : true}}},\n                    {\"foo\": {\"bar\" : {\"baz\" : false}}}\n                ],\n                \"valid\": true\n            },\n            {\n                \"description\": \"non-unique array of nested objects is invalid\",\n                \"data\": [\n                    {\"foo\": {\"bar\" : {\"baz\" : true}}},\n                    {\"foo\": {\"bar\" : {\"baz\" : true}}}\n                ],\n                \"valid\": false\n            },\n            {\n                \"description\": \"unique array of arrays is valid\",\n                \"data\": [[\"foo\"], [\"bar\"]],\n                \"valid\": true\n            },\n            {\n                \"description\": \"non-unique array of arrays is invalid\",\n                \"data\": [[\"foo\"], [\"foo\"]],\n                \"valid\": false\n            },\n            {\n                \"description\": \"1 and true are unique\",\n                \"data\": [1, true],\n                \"valid\": true\n            },\n            {\n                \"description\": \"0 and false are unique\",\n                \"data\": [0, false],\n                \"valid\": true\n            },\n            {\n                \"description\": \"[1] and [true] are unique\",\n                \"data\": [[1], [true]],\n                \"valid\": true\n            },\n            {\n                \"description\": \"[0] and [false] are unique\",\n                \"data\": [[0], [false]],\n                \"valid\": true\n            },\n            {\n                \"description\": \"nested [1] and [true] are unique\",\n                \"data\": [[[1], \"foo\"], [[true], \"foo\"]],\n                \"valid\": true\n            },\n            {\n                \"description\": \"nested [0] and [false] are unique\",\n                \"data\": [[[0], \"foo\"], [[false], \"foo\"]],\n                \"valid\": true\n            },\n            {\n                \"description\": \"unique heterogeneous types are valid\",\n                \"data\": [{}, [1], true, null, 1, \"{}\"],\n                \"valid\": true\n            },\n            {\n                \"description\": \"non-unique heterogeneous types are invalid\",\n                \"data\": [{}, [1], true, null, {}, 1],\n                \"valid\": false\n            },\n            {\n                \"description\": \"different objects are unique\",\n                \"data\": [{\"a\": 1, \"b\": 2}, {\"a\": 2, \"b\": 1}],\n                \"valid\": true\n            },\n            {\n                \"description\": \"objects are non-unique despite key order\",\n                \"data\": [{\"a\": 1, \"b\": 2}, {\"b\": 2, \"a\": 1}],\n                \"valid\": false\n            },\n            {\n                \"description\": \"{\\\"a\\\": false} and {\\\"a\\\": 0} are unique\",\n                \"data\": [{\"a\": false}, {\"a\": 0}],\n                \"valid\": true\n            },\n            {\n                \"description\": \"{\\\"a\\\": true} and {\\\"a\\\": 1} are unique\",\n                \"data\": [{\"a\": true}, {\"a\": 1}],\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"uniqueItems with an array of items\",\n        \"schema\": {\n            \"items\": [{\"type\": \"boolean\"}, {\"type\": \"boolean\"}],\n            \"uniqueItems\": true\n        },\n        \"tests\": [\n            {\n                \"description\": \"[false, true] from items array is valid\",\n                \"data\": [false, true],\n                \"valid\": true\n            },\n            {\n                \"description\": \"[true, false] from items array is valid\",\n                \"data\": [true, false],\n                \"valid\": true\n            },\n            {\n                \"description\": \"[false, false] from items array is not valid\",\n                \"data\": [false, false],\n                \"valid\": false\n            },\n            {\n                \"description\": \"[true, true] from items array is not valid\",\n                \"data\": [true, true],\n                \"valid\": false\n            },\n            {\n                \"description\": \"unique array extended from [false, true] is valid\",\n                \"data\": [false, true, \"foo\", \"bar\"],\n                \"valid\": true\n            },\n            {\n                \"description\": \"unique array extended from [true, false] is valid\",\n                \"data\": [true, false, \"foo\", \"bar\"],\n                \"valid\": true\n            },\n            {\n                \"description\": \"non-unique array extended from [false, true] is not valid\",\n                \"data\": [false, true, \"foo\", \"foo\"],\n                \"valid\": false\n            },\n            {\n                \"description\": \"non-unique array extended from [true, false] is not valid\",\n                \"data\": [true, false, \"foo\", \"foo\"],\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"uniqueItems with an array of items and additionalItems=false\",\n        \"schema\": {\n            \"items\": [{\"type\": \"boolean\"}, {\"type\": \"boolean\"}],\n            \"uniqueItems\": true,\n            \"additionalItems\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"[false, true] from items array is valid\",\n                \"data\": [false, true],\n                \"valid\": true\n            },\n            {\n                \"description\": \"[true, false] from items array is valid\",\n                \"data\": [true, false],\n                \"valid\": true\n            },\n            {\n                \"description\": \"[false, false] from items array is not valid\",\n                \"data\": [false, false],\n                \"valid\": false\n            },\n            {\n                \"description\": \"[true, true] from items array is not valid\",\n                \"data\": [true, true],\n                \"valid\": false\n            },\n            {\n                \"description\": \"extra items are invalid even if unique\",\n                \"data\": [false, true, null],\n                \"valid\": false\n            }\n        ]\n    },\n    {\n        \"description\": \"uniqueItems=false validation\",\n        \"schema\": { \"uniqueItems\": false },\n        \"tests\": [\n            {\n                \"description\": \"unique array of integers is valid\",\n                \"data\": [1, 2],\n                \"valid\": true\n            },\n            {\n                \"description\": \"non-unique array of integers is valid\",\n                \"data\": [1, 1],\n                \"valid\": true\n            },\n            {\n                \"description\": \"numbers are unique if mathematically unequal\",\n                \"data\": [1.0, 1.00, 1],\n                \"valid\": true\n            },\n            {\n                \"description\": \"false is not equal to zero\",\n                \"data\": [0, false],\n                \"valid\": true\n            },\n            {\n                \"description\": \"true is not equal to one\",\n                \"data\": [1, true],\n                \"valid\": true\n            },\n            {\n                \"description\": \"unique array of objects is valid\",\n                \"data\": [{\"foo\": \"bar\"}, {\"foo\": \"baz\"}],\n                \"valid\": true\n            },\n            {\n                \"description\": \"non-unique array of objects is valid\",\n                \"data\": [{\"foo\": \"bar\"}, {\"foo\": \"bar\"}],\n                \"valid\": true\n            },\n            {\n                \"description\": \"unique array of nested objects is valid\",\n                \"data\": [\n                    {\"foo\": {\"bar\" : {\"baz\" : true}}},\n                    {\"foo\": {\"bar\" : {\"baz\" : false}}}\n                ],\n                \"valid\": true\n            },\n            {\n                \"description\": \"non-unique array of nested objects is valid\",\n                \"data\": [\n                    {\"foo\": {\"bar\" : {\"baz\" : true}}},\n                    {\"foo\": {\"bar\" : {\"baz\" : true}}}\n                ],\n                \"valid\": true\n            },\n            {\n                \"description\": \"unique array of arrays is valid\",\n                \"data\": [[\"foo\"], [\"bar\"]],\n                \"valid\": true\n            },\n            {\n                \"description\": \"non-unique array of arrays is valid\",\n                \"data\": [[\"foo\"], [\"foo\"]],\n                \"valid\": true\n            },\n            {\n                \"description\": \"1 and true are unique\",\n                \"data\": [1, true],\n                \"valid\": true\n            },\n            {\n                \"description\": \"0 and false are unique\",\n                \"data\": [0, false],\n                \"valid\": true\n            },\n            {\n                \"description\": \"unique heterogeneous types are valid\",\n                \"data\": [{}, [1], true, null, 1],\n                \"valid\": true\n            },\n            {\n                \"description\": \"non-unique heterogeneous types are valid\",\n                \"data\": [{}, [1], true, null, {}, 1],\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"uniqueItems=false with an array of items\",\n        \"schema\": {\n            \"items\": [{\"type\": \"boolean\"}, {\"type\": \"boolean\"}],\n            \"uniqueItems\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"[false, true] from items array is valid\",\n                \"data\": [false, true],\n                \"valid\": true\n            },\n            {\n                \"description\": \"[true, false] from items array is valid\",\n                \"data\": [true, false],\n                \"valid\": true\n            },\n            {\n                \"description\": \"[false, false] from items array is valid\",\n                \"data\": [false, false],\n                \"valid\": true\n            },\n            {\n                \"description\": \"[true, true] from items array is valid\",\n                \"data\": [true, true],\n                \"valid\": true\n            },\n            {\n                \"description\": \"unique array extended from [false, true] is valid\",\n                \"data\": [false, true, \"foo\", \"bar\"],\n                \"valid\": true\n            },\n            {\n                \"description\": \"unique array extended from [true, false] is valid\",\n                \"data\": [true, false, \"foo\", \"bar\"],\n                \"valid\": true\n            },\n            {\n                \"description\": \"non-unique array extended from [false, true] is valid\",\n                \"data\": [false, true, \"foo\", \"foo\"],\n                \"valid\": true\n            },\n            {\n                \"description\": \"non-unique array extended from [true, false] is valid\",\n                \"data\": [true, false, \"foo\", \"foo\"],\n                \"valid\": true\n            }\n        ]\n    },\n    {\n        \"description\": \"uniqueItems=false with an array of items and additionalItems=false\",\n        \"schema\": {\n            \"items\": [{\"type\": \"boolean\"}, {\"type\": \"boolean\"}],\n            \"uniqueItems\": false,\n            \"additionalItems\": false\n        },\n        \"tests\": [\n            {\n                \"description\": \"[false, true] from items array is valid\",\n                \"data\": [false, true],\n                \"valid\": true\n            },\n            {\n                \"description\": \"[true, false] from items array is valid\",\n                \"data\": [true, false],\n                \"valid\": true\n            },\n            {\n                \"description\": \"[false, false] from items array is valid\",\n                \"data\": [false, false],\n                \"valid\": true\n            },\n            {\n                \"description\": \"[true, true] from items array is valid\",\n                \"data\": [true, true],\n                \"valid\": true\n            },\n            {\n                \"description\": \"extra items are invalid even if unique\",\n                \"data\": [false, true, null],\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/JSON-Schema-Test-Suite/tests/draft7/unknownKeyword.json",
    "content": "[\n    {\n        \"description\": \"$id inside an unknown keyword is not a real identifier\",\n        \"comment\": \"the implementation must not be confused by an $id in locations we do not know how to parse\",\n        \"schema\": {\n            \"definitions\": {\n                \"id_in_unknown0\": {\n                    \"not\": {\n                        \"array_of_schemas\": [\n                            {\n                              \"$id\": \"https://localhost:1234/unknownKeyword/my_identifier.json\",\n                              \"type\": \"null\"\n                            }\n                        ]\n                    }\n                },\n                \"real_id_in_schema\": {\n                    \"$id\": \"https://localhost:1234/unknownKeyword/my_identifier.json\",\n                    \"type\": \"string\"\n                },\n                \"id_in_unknown1\": {\n                    \"not\": {\n                        \"object_of_schemas\": {\n                            \"foo\": {\n                              \"$id\": \"https://localhost:1234/unknownKeyword/my_identifier.json\",\n                              \"type\": \"integer\"\n                            }\n                        }\n                    }\n                }\n            },\n            \"anyOf\": [\n                { \"$ref\": \"#/definitions/id_in_unknown0\" },\n                { \"$ref\": \"#/definitions/id_in_unknown1\" },\n                { \"$ref\": \"https://localhost:1234/unknownKeyword/my_identifier.json\" }\n            ]\n        },\n        \"tests\": [\n            {\n                \"description\": \"type matches second anyOf, which has a real schema in it\",\n                \"data\": \"a string\",\n                \"valid\": true\n            },\n            {\n                \"description\": \"type matches non-schema in first anyOf\",\n                \"data\": null,\n                \"valid\": false\n            },\n            {\n                \"description\": \"type matches non-schema in third anyOf\",\n                \"data\": 1,\n                \"valid\": false\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/binary-validation.cpp",
    "content": "// bson-validate.cpp\n\n#include <iostream>\n#include <nlohmann/json-schema.hpp>\n#include <nlohmann/json.hpp>\n\nstatic int error_count = 0;\n\n#define EXPECT_EQ(a, b)                                              \\\n\tdo {                                                             \\\n\t\tif (a != b) {                                                \\\n\t\t\tstd::cerr << \"Failed: '\" << a << \"' != '\" << b << \"'\\n\"; \\\n\t\t\terror_count++;                                           \\\n\t\t}                                                            \\\n\t} while (0)\n\n#define EXPECT_THROW(foo)            \\\n\t{                                \\\n\t\tbool ok = false;             \\\n\t\ttry {                        \\\n\t\t\tfoo;                     \\\n\t\t} catch (std::exception &) { \\\n\t\t\tok = true;               \\\n\t\t}                            \\\n\t\tif (ok == false) {           \\\n\t\t\terror_count++;           \\\n\t\t}                            \\\n\t}\n\nusing json = nlohmann::json;\nusing validator = nlohmann::json_schema::json_validator;\n\n// check binary data validation\nconst json bson_schema = json::parse(R\"(\n{\n  \"type\": \"object\",\n  \"properties\": {\n    \"standard_string\": {\n      \"type\": \"string\"\n    },\n    \"binary_data\": {\n      \"type\": \"string\",\n      \"contentEncoding\": \"binary\"\n    }\n  },\n  \"additionalProperties\": false\n}\n)\");\n\nconst json array_of_types = json::parse(R\"(\n{\n  \"type\": \"object\",\n  \"properties\": {\n    \"something\": {\n      \"type\": [\"string\", \"number\", \"boolean\"],\n      \"contentEncoding\": \"binary\"\n    }\n  }\n}\n)\");\n\nconst json array_of_types_without_binary = json::parse(R\"(\n{\n  \"type\": \"object\",\n  \"properties\": {\n    \"something\": {\n      \"type\": [\"string\", \"number\", \"boolean\"]\n    }\n  }\n}\n)\");\n\nclass store_ptr_err_handler : public nlohmann::json_schema::basic_error_handler\n{\n\tvoid error(const nlohmann::json::json_pointer &ptr, const json &, const std::string &message) override\n\t{\n\t\tnlohmann::json_schema::basic_error_handler::error(ptr, \"\", message);\n\t\tstd::cerr << \"ERROR: '\" << ptr << \"' - '\"\n\t\t          << \"\"\n\t\t          << \"': \" << message << \"\\n\";\n\t\tfailed_pointers.push_back(ptr);\n\t}\n\npublic:\n\tstd::vector<nlohmann::json::json_pointer> failed_pointers;\n\n\tvoid reset() override\n\t{\n\t\tnlohmann::json_schema::basic_error_handler::reset();\n\t\tfailed_pointers.clear();\n\t}\n};\n\nstatic void content(const std::string &contentEncoding, const std::string &contentMediaType, const json &instance)\n{\n\tstd::cerr << \"mediaType: '\" << contentMediaType << \"', encoding: '\" << contentEncoding << \"'\\n\";\n\n\tif (contentEncoding == \"binary\") {\n\t\tif (instance.type() != json::value_t::binary) {\n\t\t\tthrow std::invalid_argument{\"expected binary data\"};\n\t\t}\n\t} else {\n\t\tif (instance.type() == json::value_t::binary) {\n\t\t\tthrow std::invalid_argument{\"expected string, but get binary\"};\n\t\t}\n\t}\n}\n\nint main()\n{\n\tvalidator val(nullptr, nullptr, content);\n\n\t// create some bson doc\n\tjson::binary_t arr;\n\tstd::string as_binary = \"hello world\";\n\tstd::copy(as_binary.begin(), as_binary.end(), std::back_inserter(arr));\n\n\tjson binary = json::binary(arr);\n\n\tstore_ptr_err_handler err;\n\n\t/////////////////////////////////////\n\tval.set_root_schema(bson_schema);\n\n\t// all right\n\tval.validate({{\"standard_string\", \"some string\"}, {\"binary_data\", binary}}, err);\n\tEXPECT_EQ(err.failed_pointers.size(), 0);\n\terr.reset();\n\n\t// invalid binary data\n\tval.validate({{\"binary_data\", \"string, but expect binary data\"}}, err);\n\tEXPECT_EQ(err.failed_pointers.size(), 1);\n\tEXPECT_EQ(err.failed_pointers[0].to_string(), \"/binary_data\");\n\terr.reset();\n\n\t// also check that simple string not accept binary data\n\tval.validate({{\"standard_string\", binary}, {\"binary_data\", binary}}, err);\n\tEXPECT_EQ(err.failed_pointers.size(), 1);\n\tEXPECT_EQ(err.failed_pointers[0].to_string(), \"/standard_string\");\n\terr.reset();\n\n\t/////////////////////////////////////\n\t// check with array of types\n\n\t// check simple types\n\tval.set_root_schema(array_of_types);\n\tval.validate({{\"something\", 1}}, err);\n\tval.validate({{\"something\", false}}, err);\n\t// TODO when we set `string` in array and set `contentEncoding` = \"binary\" - what it means? We expected string or binary?\n\t// Or we expect only binary? Now if you set `contentEncoding` = \"binary\", then it means that you expect only binary data,\n\t// not string\n\t// val.validate({{\"something\", \"string\"}}, err); -> produce error about type\n\tEXPECT_EQ(err.failed_pointers.size(), 0);\n\terr.reset();\n\n\t// check binary data\n\tval.validate({{\"something\", binary}}, err);\n\tEXPECT_EQ(err.failed_pointers.size(), 0);\n\terr.reset();\n\n\t/////////////////////////////////////\n\t// and check that you can't set binary data if contentEncoding don't set\n\tval.set_root_schema(array_of_types_without_binary);\n\tval.validate({{\"something\", binary}}, err);\n\tEXPECT_EQ(err.failed_pointers.size(), 1);\n\tEXPECT_EQ(err.failed_pointers[0].to_string(), \"/something\");\n\terr.reset();\n\n\t// check that without content callback you get exception with schema with contentEncoding or contentMeditType\n\tvalidator val_no_content;\n\n\tEXPECT_THROW(val_no_content.set_root_schema(bson_schema));\n\n\treturn error_count;\n}\n"
  },
  {
    "path": "test/errors.cpp",
    "content": "#include <nlohmann/json-schema.hpp>\n\n#include <iostream>\n\nstatic int error_count;\n\n#define EXPECT_EQ(a, b)                                              \\\n\tdo {                                                             \\\n\t\tif (a != b) {                                                \\\n\t\t\tstd::cerr << \"Failed: '\" << a << \"' != '\" << b << \"'\\n\"; \\\n\t\t\terror_count++;                                           \\\n\t\t}                                                            \\\n\t} while (0)\n\nusing nlohmann::json;\nusing nlohmann::json_schema::json_validator;\n\nnamespace\n{\n\n// The schema is defined based upon a string literal\nstatic json person_schema = R\"(\n{\n    \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n    \"title\": \"A person\",\n    \"properties\": {\n        \"name\": {\n            \"description\": \"Name\",\n            \"type\": \"string\"\n        },\n        \"age\": {\n            \"description\": \"Age of the person\",\n            \"type\": \"number\",\n            \"minimum\": 2,\n            \"maximum\": 200\n        },\n        \"phones\": {\n            \"type\": \"array\",\n            \"items\": {\n                 \"type\": \"number\"\n            }\n        }\n    },\n    \"required\": [\n                 \"name\",\n                 \"age\"\n                 ],\n    \"additionalProperties\": false,\n    \"type\": \"object\"\n})\"_json;\n\nclass store_ptr_err_handler : public nlohmann::json_schema::basic_error_handler\n{\n\tvoid error(const nlohmann::json::json_pointer &ptr, const json &instance, const std::string &message) override\n\t{\n\t\tnlohmann::json_schema::basic_error_handler::error(ptr, instance, message);\n\t\tstd::cerr << \"ERROR: '\" << ptr << \"' - '\" << instance << \"': \" << message << \"\\n\";\n\t\tfailed_pointers.push_back(ptr);\n\t}\n\npublic:\n\tstd::vector<nlohmann::json::json_pointer> failed_pointers;\n\n\tvoid reset() override\n\t{\n\t\tnlohmann::json_schema::basic_error_handler::reset();\n\t\tfailed_pointers.clear();\n\t}\n};\n\n} // namespace\n\nint main(void)\n{\n\tjson_validator validator;\n\n\ttry {\n\t\tvalidator.set_root_schema(person_schema); // insert root-schema\n\t} catch (const std::exception &e) {\n\t\tstd::cerr << \"Validation of schema failed, here is why: \" << e.what() << \"\\n\";\n\t\treturn EXIT_FAILURE;\n\t}\n\n\tstore_ptr_err_handler err;\n\n\tvalidator.validate({{\"age\", 42}, {\"name\", \"John\"}}, err); // OK\n\tEXPECT_EQ(err.failed_pointers.size(), 0);\n\terr.reset();\n\n\tvalidator.validate({{\"age\", 42}}, err); // no name\n\n\tEXPECT_EQ(err.failed_pointers.size(), 1);\n\tEXPECT_EQ(err.failed_pointers[0].to_string(), \"\");\n\terr.reset();\n\n\tvalidator.validate({{\"street\", \"Boulevard\"}}, err); // no name and no age\n\tEXPECT_EQ(err.failed_pointers.size(), 3);\n\tEXPECT_EQ(err.failed_pointers[0].to_string(), \"\");\n\tEXPECT_EQ(err.failed_pointers[1].to_string(), \"\");\n\tEXPECT_EQ(err.failed_pointers[2].to_string(), \"\");\n\terr.reset();\n\n\tvalidator.validate({{\"age\", 42}, {\"name\", 12}}, err); // name must be a string\n\tEXPECT_EQ(err.failed_pointers.size(), 1);\n\tEXPECT_EQ(err.failed_pointers[0].to_string(), \"/name\");\n\terr.reset();\n\n\tvalidator.validate({\n\t                       {\"age\", 42},\n\t                       {\"name\", \"John\"},\n\t                       {\"phones\", {1234, \"223\"}},\n\t                   },\n\t                   err); // name must be a string\n\tEXPECT_EQ(err.failed_pointers.size(), 1);\n\tEXPECT_EQ(err.failed_pointers[0].to_string(), \"/phones/1\");\n\terr.reset();\n\n\tvalidator.validate({\n\t                       {\"age\", 42},\n\t                       {\"name\", \"John\"},\n\t                       {\"phones\", {0}},\n\t                       {\"post-code\", 12345},\n\t                   },\n\t                   err); // name must be a string\n\tEXPECT_EQ(err.failed_pointers.size(), 1);\n\tEXPECT_EQ(err.failed_pointers[0].to_string(), \"\");\n\terr.reset();\n\n\treturn error_count;\n}\n"
  },
  {
    "path": "test/id-ref.cpp",
    "content": "#include <nlohmann/json.hpp>\n\n#include <nlohmann/json-schema.hpp>\n\n#include <iostream>\n\nusing nlohmann::json;\n\nauto schema_draft = R\"(\n {\n       \"$id\": \"http://example.com/root.json\",\n       \"definitions\": {\n           \"A\": { \"$id\": \"#foo\" },\n           \"B\": {\n               \"$id\": \"other.json\",\n               \"definitions\": {\n                   \"X\": { \"$id\": \"#bar\" },\n                   \"Y\": { \"$id\": \"t/inner.json\" }\n               }\n           },\n           \"C\": {\n\n               \"$id\": \"urn:uuid:ee564b8a-7a87-4125-8c96-e9f123d6766f\",\n               \"definitions\": {\n                   \"Z\": { \"$id\": \"#bar\" },\n                   \"9\": { \"$id\": \"http://example.com/drole.json\" }\n               }\n           }\n       }\n   }\n)\"_json;\n\n/*  # (document root)\n\n         http://example.com/root.json\n         http://example.com/root.json#\n\n   #/definitions/A\n\n         http://example.com/root.json#foo\n         http://example.com/root.json#/definitions/A\n\n   #/definitions/B\n\n         http://example.com/other.json\n         http://example.com/other.json#\n         http://example.com/root.json#/definitions/B\n\n   #/definitions/B/definitions/X\n\n         http://example.com/other.json#bar\n         http://example.com/other.json#/definitions/X\n         http://example.com/root.json#/definitions/B/definitions/X\n\n   #/definitions/B/definitions/Y\n\n         http://example.com/t/inner.json\n         http://example.com/t/inner.json#\n         http://example.com/other.json#/definitions/Y\n         http://example.com/root.json#/definitions/B/definitions/Y\n\n   #/definitions/C\n\n         urn:uuid:ee564b8a-7a87-4125-8c96-e9f123d6766f\n         urn:uuid:ee564b8a-7a87-4125-8c96-e9f123d6766f#\n         http://example.com/root.json#/definitions/C\n         */\n\nauto schema = R\"(\n{\n\t\"id\": \"http://localhost:1234/scope_change_defs2.json\",\n\t\"type\" : \"object\",\n\t\"properties\": {\n\t\t\"list\": {\"$ref\": \"#/definitions/baz/definitions/bar\"}\n\t},\n\t\"definitions\": {\n\t\t\"baz\": {\n\t\t\t\"id\": \"folder/\",\n\t\t\t\"definitions\": {\n\t\t\t\t\"bar\": {\n\t\t\t\t\t\"type\": \"array\",\n\t\t\t\t\t\"items\": {\"$ref\": \"folderInteger.json\"}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n})\"_json;\n\nclass json_schema_validator\n{\npublic:\n\tstd::vector<json> schemas_;\n\tstd::map<nlohmann::json_uri, const json *> schema_store_;\n\npublic:\n\tvoid insert_schema(json &s, std::vector<nlohmann::json_uri> base_uris)\n\t{\n\t\tauto id = s.find(\"$id\");\n\t\tif (id != s.end())\n\t\t\tbase_uris.push_back(base_uris.back().derive(id.value()));\n\n\t\tfor (auto &u : base_uris)\n\t\t\tschema_store_[u] = &s;\n\n\t\tfor (auto i = s.begin();\n\t\t     i != s.end();\n\t\t     ++i) {\n\n\t\t\tswitch (i.value().type()) {\n\t\t\tcase json::value_t::object: { // child is object, thus a schema\n\t\t\t\tstd::vector<nlohmann::json_uri> subschema_uri = base_uris;\n\n\t\t\t\tfor (auto &ss : subschema_uri)\n\t\t\t\t\tss = ss.append(nlohmann::json_uri::escape(i.key()));\n\n\t\t\t\tinsert_schema(i.value(), subschema_uri);\n\t\t\t} break;\n\n\t\t\tcase json::value_t::string:\n\t\t\t\t// this schema is a reference\n\t\t\t\tif (i.key() == \"$ref\") {\n\t\t\t\t\tauto id = base_uris.back().derive(i.value());\n\t\t\t\t\ti.value() = id.to_string();\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n};\n\nint main(void)\n{\n\tjson_schema_validator store;\n\n\tstore.insert_schema(schema_draft, {{\"#\"}});\n\n\tfor (auto &i : store.schema_store_) {\n\t\tstd::cerr << i.first << \" \" << *i.second << \"\\n\";\n\t}\n\n\treturn 0;\n}\n"
  },
  {
    "path": "test/issue-100/CMakeLists.txt",
    "content": "add_test_simple_schema(Issue::100\n                       ${CMAKE_CURRENT_SOURCE_DIR}/schema.json\n                       ${CMAKE_CURRENT_SOURCE_DIR}/instance.json)\nset_tests_properties(Issue::100\n                     PROPERTIES\n                         WILL_FAIL 1)\n"
  },
  {
    "path": "test/issue-100/instance.json",
    "content": "{\n    \"Prop1\": 1,\n    \"Prop2\": []\n}\n"
  },
  {
    "path": "test/issue-100/schema.json",
    "content": "{\n    \"$id\": \"http://xxx.local/schemas/mySchema.json\",\n    \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\n    \"type\": \"object\",\n    \"properties\": {\n        \"Prop1\": {\n            \"type\": \"integer\",\n            \"$comment\": \"Just a comment\"\n        },\n        \"Prop2\": {\n            \"$ref\": \"#random_ref\"\n        }\n    }\n}\n"
  },
  {
    "path": "test/issue-101/CMakeLists.txt",
    "content": "add_test_simple_schema(Issue::101\n                       ${CMAKE_CURRENT_SOURCE_DIR}/schema.json\n                       ${CMAKE_CURRENT_SOURCE_DIR}/instance.json)\nset_tests_properties(Issue::101\n                     PROPERTIES\n                         WILL_FAIL 1)\n"
  },
  {
    "path": "test/issue-101/instance.json",
    "content": "{\"top\": 1}\n"
  },
  {
    "path": "test/issue-101/schema.json",
    "content": "{\n    \"$id\": \"http://xxx.local/schemas/mySchema.json\",\n    \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n\n    \"type\": \"object\",\n    \"properties\": {\n        \"top\": {\n            \"type\": \"integer\"\n        },\n        \"required\": [\"top\"]\n    }\n}\n"
  },
  {
    "path": "test/issue-105-verbose-combination-errors.cpp",
    "content": "#include \"nlohmann/json-schema.hpp\"\n#include \"nlohmann/json.hpp\"\n\n#include <iostream>\n#include <regex>\n#include <string>\n#include <vector>\n\n//==============================================================================\n// Test macros\n//==============================================================================\n#define LOG_ERROR(LOG_ERROR__ARGS) \\\n\tstd::cerr << __FILE__ << \":\" << __LINE__ << \": \" << LOG_ERROR__ARGS << std::endl\n\n#define EXPECT_THROW_WITH_MESSAGE(EXPRESSION, MESSAGE)                                                                              \\\n\tdo {                                                                                                                            \\\n\t\ttry {                                                                                                                       \\\n\t\t\tEXPRESSION;                                                                                                             \\\n\t\t\tLOG_ERROR(\"Expected exception not thrown with matching regex: \\\"\" << MESSAGE << \"\\\"\");                                  \\\n\t\t\t++g_error_count;                                                                                                        \\\n\t\t} catch (const std::exception &error) {                                                                                     \\\n\t\t\tconst std::regex error_re{MESSAGE};                                                                                     \\\n\t\t\tif (!std::regex_search(error.what(), error_re)) {                                                                       \\\n\t\t\t\tLOG_ERROR(\"Expected exception with matching regex: \\\"\" << MESSAGE << \"\\\", but got this instead: \" << error.what()); \\\n\t\t\t\t++g_error_count;                                                                                                    \\\n\t\t\t}                                                                                                                       \\\n\t\t}                                                                                                                           \\\n\t} while (false)\n\n#define ASSERT_OR_EXPECT_EQ(FIRST_THING, SECOND_THING, RETURN_IN_CASE_OF_ERROR)                                                                               \\\n\tdo {                                                                                                                                                      \\\n\t\tif ((FIRST_THING) != (SECOND_THING)) {                                                                                                                \\\n\t\t\tLOG_ERROR(\"The two values of \" << (FIRST_THING) << \" (\" #FIRST_THING << \") and \" << (SECOND_THING) << \" (\" #SECOND_THING << \") should be equal\"); \\\n\t\t\tif (RETURN_IN_CASE_OF_ERROR) {                                                                                                                    \\\n\t\t\t\treturn;                                                                                                                                       \\\n\t\t\t}                                                                                                                                                 \\\n\t\t}                                                                                                                                                     \\\n\t} while (false)\n\n#define ASSERT_EQ(FIRST_THING, SECOND_THING) ASSERT_OR_EXPECT_EQ(FIRST_THING, SECOND_THING, true)\n#define EXPECT_EQ(FIRST_THING, SECOND_THING) ASSERT_OR_EXPECT_EQ(FIRST_THING, SECOND_THING, true)\n\n#define EXPECT_MATCH(STRING, REGEX)                                                                     \\\n\tdo {                                                                                                \\\n\t\tif (!std::regex_search((STRING), std::regex{(REGEX)})) {                                        \\\n\t\t\tLOG_ERROR(\"String \\\"\" << (STRING) << \"\\\" doesn't match with regex: \\\"\" << (REGEX) << \"\\\"\"); \\\n\t\t\t++g_error_count;                                                                            \\\n\t\t}                                                                                               \\\n\t} while (false)\n\nnamespace\n{\n\n//==============================================================================\n// Test environment\n//==============================================================================\nint g_error_count = 0;\n\n//==============================================================================\n// The schema used for testing\n//==============================================================================\nconst std::string g_schema_template = R\"(\n{\n    \"properties\": {\n        \"first\": {\n            \"%COMBINATION_FIRST_LEVEL%\": [\n                {\n                    \"properties\": {\n                        \"second\": {\n                            \"%COMBINATION_SECOND_LEVEL%\": [\n                                {\n                                    \"minimum\": 5,\n                                    \"type\": \"integer\"\n                                },\n                                {\n                                    \"multipleOf\": 2,\n                                    \"type\": \"integer\"\n                                }\n                            ]\n                        }\n                    },\n                    \"type\": \"object\"\n                },\n                {\n                    \"minimum\": 20,\n                    \"type\": \"integer\"\n                },\n                {\n                    \"minLength\": 10,\n                    \"type\": \"string\"\n                }\n            ]\n        }\n    },\n    \"type\": \"object\"\n}\n)\";\n\nauto generateSchema(const std::string &first_combination, const std::string &second_combination) -> nlohmann::json\n{\n\tstatic const std::regex first_replace_re{\"%COMBINATION_FIRST_LEVEL%\"};\n\tstatic const std::regex second_replace_re{\"%COMBINATION_SECOND_LEVEL%\"};\n\n\tstd::string intermediate = std::regex_replace(g_schema_template, first_replace_re, first_combination);\n\n\treturn nlohmann::json::parse(std::regex_replace(intermediate, second_replace_re, second_combination));\n}\n\n//==============================================================================\n// Error handler to catch all the errors generated by the validator - also inside the combinations\n//==============================================================================\nclass MyErrorHandler : public nlohmann::json_schema::error_handler\n{\npublic:\n\tstruct ErrorEntry {\n\t\tnlohmann::json::json_pointer ptr;\n\t\tnlohmann::json intance;\n\t\tstd::string message;\n\t};\n\n\tusing ErrorEntryList = std::vector<ErrorEntry>;\n\n\tauto getErrors() const -> const ErrorEntryList &\n\t{\n\t\treturn m_error_list;\n\t}\n\nprivate:\n\tauto error(const nlohmann::json::json_pointer &ptr, const nlohmann::json &instance, const std::string &message) -> void override\n\t{\n\t\tm_error_list.push_back(ErrorEntry{ptr, instance, message});\n\t}\n\n\tErrorEntryList m_error_list;\n};\n\n//==============================================================================\n// Error string helpers\n//==============================================================================\nauto operator<<(std::string first, const std::string &second) -> std::string\n{\n\tfirst += \".*\";\n\tfirst += second;\n\treturn first;\n}\n\nauto rootError(const std::string &combination_type, std::size_t number_of_subschemas) -> std::string\n{\n\treturn \"no subschema has succeeded, but one of them is required to validate. Type: \" + combination_type + \", number of failed subschemas: \" + std::to_string(number_of_subschemas);\n}\n\nauto combinationError(const std::string &combination_type, std::size_t test_case_number) -> std::string\n{\n\treturn \"[combination: \" + combination_type + \" / case#\" + std::to_string(test_case_number) + \"]\";\n}\n\n//==============================================================================\n// Validator function - for simplicity\n//==============================================================================\nauto validate(const nlohmann::json &schema, const nlohmann::json &instance, nlohmann::json_schema::error_handler *error_handler = nullptr) -> void\n{\n\tnlohmann::json_schema::json_validator validator;\n\tvalidator.set_root_schema(schema);\n\n\tif (error_handler) {\n\t\tvalidator.validate(instance, *error_handler);\n\t} else {\n\t\tvalidator.validate(instance);\n\t}\n}\n\n//==============================================================================\n// The test cases\n//==============================================================================\nauto simpleTest(const std::string &first_combination, const std::string &second_combination) -> void\n{\n\tconst nlohmann::json schema = generateSchema(first_combination, second_combination);\n\tEXPECT_THROW_WITH_MESSAGE(validate(schema, nlohmann::json{{\"first\", {{\"second\", 1}}}}), rootError(first_combination, 3));\n\tif (second_combination == \"oneOf\") {\n\t\tEXPECT_THROW_WITH_MESSAGE(validate(schema, nlohmann::json{{\"first\", {{\"second\", 8}}}}), rootError(first_combination, 3));\n\t}\n\tEXPECT_THROW_WITH_MESSAGE(validate(schema, nlohmann::json{{\"first\", 10}}), rootError(first_combination, 3));\n\tEXPECT_THROW_WITH_MESSAGE(validate(schema, nlohmann::json{{\"first\", \"short\"}}), rootError(first_combination, 3));\n}\n\nauto verboseTest(const std::string &first_combination, const std::string &second_combination) -> void\n{\n\tconst nlohmann::json schema = generateSchema(first_combination, second_combination);\n\n\t{\n\t\tMyErrorHandler error_handler;\n\t\tvalidate(schema, nlohmann::json{{\"first\", {{\"second\", 1}}}}, &error_handler);\n\n\t\tconst MyErrorHandler::ErrorEntryList &error_list = error_handler.getErrors();\n\t\tEXPECT_EQ(error_list.size(), 6);\n\n\t\tEXPECT_EQ(error_list[0].ptr, nlohmann::json::json_pointer{\"/first\"});\n\t\tEXPECT_MATCH(error_list[0].message, rootError(first_combination, 3));\n\n\t\tEXPECT_EQ(error_list[1].ptr, nlohmann::json::json_pointer{\"/first/second\"});\n\t\tEXPECT_MATCH(error_list[1].message, combinationError(first_combination, 0) << rootError(second_combination, 2));\n\n\t\tEXPECT_EQ(error_list[2].ptr, nlohmann::json::json_pointer{\"/first/second\"});\n\t\tEXPECT_MATCH(error_list[2].message, combinationError(first_combination, 0) << combinationError(second_combination, 0) << \"instance is below minimum of 5\");\n\n\t\tEXPECT_EQ(error_list[3].ptr, nlohmann::json::json_pointer{\"/first/second\"});\n\t\tEXPECT_MATCH(error_list[3].message, combinationError(first_combination, 0) << combinationError(second_combination, 1) << \"instance is not a multiple of 2.0\");\n\n\t\tEXPECT_EQ(error_list[4].ptr, nlohmann::json::json_pointer{\"/first\"});\n\t\tEXPECT_MATCH(error_list[4].message, combinationError(first_combination, 1) << \"unexpected instance type\");\n\n\t\tEXPECT_EQ(error_list[5].ptr, nlohmann::json::json_pointer{\"/first\"});\n\t\tEXPECT_MATCH(error_list[5].message, combinationError(first_combination, 2) << \"unexpected instance type\");\n\t}\n\n\t{\n\t\tMyErrorHandler error_handler;\n\t\tvalidate(schema, nlohmann::json{{\"first\", {{\"second\", \"not-an-integer\"}}}}, &error_handler);\n\n\t\tconst MyErrorHandler::ErrorEntryList &error_list = error_handler.getErrors();\n\t\tEXPECT_EQ(error_list.size(), 6);\n\n\t\tEXPECT_EQ(error_list[0].ptr, nlohmann::json::json_pointer{\"/first\"});\n\t\tEXPECT_MATCH(error_list[0].message, rootError(first_combination, 3));\n\n\t\tEXPECT_EQ(error_list[1].ptr, nlohmann::json::json_pointer{\"/first/second\"});\n\t\tEXPECT_MATCH(error_list[1].message, combinationError(first_combination, 0) << rootError(second_combination, 2));\n\n\t\tEXPECT_EQ(error_list[2].ptr, nlohmann::json::json_pointer{\"/first/second\"});\n\t\tEXPECT_MATCH(error_list[2].message, combinationError(first_combination, 0) << combinationError(second_combination, 0) << \"unexpected instance type\");\n\n\t\tEXPECT_EQ(error_list[3].ptr, nlohmann::json::json_pointer{\"/first/second\"});\n\t\tEXPECT_MATCH(error_list[3].message, combinationError(first_combination, 0) << combinationError(second_combination, 1) << \"unexpected instance type\");\n\n\t\tEXPECT_EQ(error_list[4].ptr, nlohmann::json::json_pointer{\"/first\"});\n\t\tEXPECT_MATCH(error_list[4].message, combinationError(first_combination, 1) << \"unexpected instance type\");\n\n\t\tEXPECT_EQ(error_list[5].ptr, nlohmann::json::json_pointer{\"/first\"});\n\t\tEXPECT_MATCH(error_list[5].message, combinationError(first_combination, 2) << \"unexpected instance type\");\n\t}\n\n\tif (second_combination == \"oneOf\") {\n\t\tMyErrorHandler error_handler;\n\t\tvalidate(schema, nlohmann::json{{\"first\", {{\"second\", 8}}}}, &error_handler);\n\n\t\tconst MyErrorHandler::ErrorEntryList &error_list = error_handler.getErrors();\n\t\tEXPECT_EQ(error_list.size(), 4);\n\n\t\tEXPECT_EQ(error_list[0].ptr, nlohmann::json::json_pointer{\"/first\"});\n\t\tEXPECT_MATCH(error_list[0].message, rootError(first_combination, 3));\n\n\t\tEXPECT_EQ(error_list[1].ptr, nlohmann::json::json_pointer{\"/first/second\"});\n\t\tEXPECT_MATCH(error_list[1].message, combinationError(first_combination, 0) << \"more than one subschema has succeeded, but exactly one of them is required to validate\");\n\n\t\tEXPECT_EQ(error_list[2].ptr, nlohmann::json::json_pointer{\"/first\"});\n\t\tEXPECT_MATCH(error_list[2].message, combinationError(first_combination, 1) << \"unexpected instance type\");\n\n\t\tEXPECT_EQ(error_list[3].ptr, nlohmann::json::json_pointer{\"/first\"});\n\t\tEXPECT_MATCH(error_list[3].message, combinationError(first_combination, 2) << \"unexpected instance type\");\n\t}\n\n\t{\n\t\tMyErrorHandler error_handler;\n\t\tvalidate(schema, nlohmann::json{{\"first\", 10}}, &error_handler);\n\n\t\tconst MyErrorHandler::ErrorEntryList &error_list = error_handler.getErrors();\n\t\tEXPECT_EQ(error_list.size(), 4);\n\n\t\tEXPECT_EQ(error_list[0].ptr, nlohmann::json::json_pointer{\"/first\"});\n\t\tEXPECT_MATCH(error_list[0].message, rootError(first_combination, 3));\n\n\t\tEXPECT_EQ(error_list[1].ptr, nlohmann::json::json_pointer{\"/first\"});\n\t\tEXPECT_MATCH(error_list[1].message, combinationError(first_combination, 0) << \"unexpected instance type\");\n\n\t\tEXPECT_EQ(error_list[2].ptr, nlohmann::json::json_pointer{\"/first\"});\n\t\tEXPECT_MATCH(error_list[2].message, combinationError(first_combination, 1) << \"instance is below minimum of 20\");\n\n\t\tEXPECT_EQ(error_list[3].ptr, nlohmann::json::json_pointer{\"/first\"});\n\t\tEXPECT_MATCH(error_list[3].message, combinationError(first_combination, 2) << \"unexpected instance type\");\n\t}\n\n\t{\n\t\tMyErrorHandler error_handler;\n\t\tvalidate(schema, nlohmann::json{{\"first\", \"short\"}}, &error_handler);\n\n\t\tconst MyErrorHandler::ErrorEntryList &error_list = error_handler.getErrors();\n\t\tEXPECT_EQ(error_list.size(), 4);\n\n\t\tEXPECT_EQ(error_list[0].ptr, nlohmann::json::json_pointer{\"/first\"});\n\t\tEXPECT_MATCH(error_list[0].message, rootError(first_combination, 3));\n\n\t\tEXPECT_EQ(error_list[1].ptr, nlohmann::json::json_pointer{\"/first\"});\n\t\tEXPECT_MATCH(error_list[1].message, combinationError(first_combination, 0) << \"unexpected instance type\");\n\n\t\tEXPECT_EQ(error_list[2].ptr, nlohmann::json::json_pointer{\"/first\"});\n\t\tEXPECT_MATCH(error_list[2].message, combinationError(first_combination, 1) << \"unexpected instance type\");\n\n\t\tEXPECT_EQ(error_list[3].ptr, nlohmann::json::json_pointer{\"/first\"});\n\t\tEXPECT_MATCH(error_list[3].message, combinationError(first_combination, 2) << \"instance is too short as per minLength:10\");\n\t}\n}\n\n} // namespace\n\n//==============================================================================\n// MAIN - calling the test cases\n//==============================================================================\nauto main() -> int\n{\n\tsimpleTest(\"anyOf\", \"anyOf\");\n\tsimpleTest(\"anyOf\", \"oneOf\");\n\tsimpleTest(\"oneOf\", \"anyOf\");\n\tsimpleTest(\"oneOf\", \"oneOf\");\n\n\tverboseTest(\"anyOf\", \"anyOf\");\n\tverboseTest(\"anyOf\", \"oneOf\");\n\tverboseTest(\"oneOf\", \"anyOf\");\n\tverboseTest(\"oneOf\", \"oneOf\");\n\n\treturn g_error_count;\n}\n"
  },
  {
    "path": "test/issue-117-format-error.cpp",
    "content": "// issue-00-format-error.cpp\n\n#include \"nlohmann/json-schema.hpp\"\n#include \"nlohmann/json.hpp\"\n#include <iostream>\n\nstatic int error_count = 0;\n\n#define CHECK_THROW(x, msg)                \\\n\t{                                      \\\n\t\tbool fail = false;                 \\\n\t\ttry {                              \\\n\t\t\tx;                             \\\n\t\t} catch (std::exception &) {       \\\n\t\t\tfail = true;                   \\\n\t\t}                                  \\\n\t\tif (fail == false) {               \\\n\t\t\t++error_count;                 \\\n\t\t\tstd::cout << msg << std::endl; \\\n\t\t}                                  \\\n\t}\n\n#define CHECK_NO_THROW(x, msg)                                        \\\n\t{                                                                 \\\n\t\tbool fail = false;                                            \\\n\t\tstd::string exception_error;                                  \\\n\t\ttry {                                                         \\\n\t\t\tx;                                                        \\\n\t\t} catch (std::exception & e) {                                \\\n\t\t\tfail = true;                                              \\\n\t\t\texception_error = e.what();                               \\\n\t\t}                                                             \\\n\t\tif (fail == true) {                                           \\\n\t\t\t++error_count;                                            \\\n\t\t\tstd::cout << msg << \": \" << exception_error << std::endl; \\\n\t\t}                                                             \\\n\t}\n\nusing json = nlohmann::json;\nusing validator = nlohmann::json_schema::json_validator;\n\njson schema_with_format = json::parse(R\"(\n{\n  \"type\": \"object\",\n  \"properties\": {\n    \"str\": {\n      \"type\": \"string\",\n      \"format\": \"placeholder\"\n    }\n  }\n}\n)\");\n\nint main()\n{\n\t// check that if we get validator without format checker we get error at schema loading\n\tvalidator without_format_checker;\n\n\tCHECK_THROW(without_format_checker.set_root_schema(schema_with_format), \"validator without format checker must fail at schema loading\");\n\n\t// check that with format checker all works fine\n\tvalidator with_format_checker{nullptr, [](const std::string &, const std::string &) {}};\n\n\tCHECK_NO_THROW(with_format_checker.set_root_schema(schema_with_format), \"schema must be succesed by validator with format checker\");\n\n\tCHECK_NO_THROW(with_format_checker.validate(json{{\"str\", \"placeholder\"}}), \"validator must not throw while validation schema with format\");\n\n\treturn error_count;\n}\n"
  },
  {
    "path": "test/issue-12/CMakeLists.txt",
    "content": "add_test_simple_schema(Issue::12\n                       ${CMAKE_CURRENT_SOURCE_DIR}/schema.json\n                       ${CMAKE_CURRENT_SOURCE_DIR}/instance.json)\n"
  },
  {
    "path": "test/issue-12/instance.json",
    "content": "{\n    \"x\": 1503681668603\n}\n"
  },
  {
    "path": "test/issue-12/schema.json",
    "content": "{\n    \"$schema\": \"http://json-schema.org/draft-04/schema#\",\n    \"properties\": {\n        \"x\": {\n            \"type\": \"integer\",\n            \"minimum\": 1000000000000,\n            \"maximum\": 2000000000000\n        }\n    }\n}\n"
  },
  {
    "path": "test/issue-143/CMakeLists.txt",
    "content": "add_test_simple_schema(Issue::143-1\n                       ${CMAKE_CURRENT_SOURCE_DIR}/schema.json\n                       ${CMAKE_CURRENT_SOURCE_DIR}/instance-fail-1.json)\nadd_test_simple_schema(Issue::143-a\n                       ${CMAKE_CURRENT_SOURCE_DIR}/schema.json\n                       ${CMAKE_CURRENT_SOURCE_DIR}/instance-fail-a.json)\nadd_test_simple_schema(Issue::143-ok\n                       ${CMAKE_CURRENT_SOURCE_DIR}/schema.json\n                       ${CMAKE_CURRENT_SOURCE_DIR}/instance.json)\n\nset_tests_properties(Issue::143-1 Issue::143-a\n                     PROPERTIES\n                     WILL_FAIL 1)\n"
  },
  {
    "path": "test/issue-143/instance-fail-1.json",
    "content": "{\n    \"ref1\": \"a\",\n    \"refa\": \"a\"\n}\n"
  },
  {
    "path": "test/issue-143/instance-fail-a.json",
    "content": "{\n    \"ref1\": 12,\n    \"refa\": 12\n}\n"
  },
  {
    "path": "test/issue-143/instance.json",
    "content": "{\n    \"ref1\": 12,\n    \"refa\": \"a\"\n}\n"
  },
  {
    "path": "test/issue-143/schema.json",
    "content": "{\n    \"type\": \"object\",\n\n    \"properties\": {\n        \"unknown_keyword_storage\": {\n            \"1\": {\n                \"type\": \"number\"\n            },\n            \"a\": {\n                \"type\": \"string\"\n            }\n        },\n        \"ref1\": {\n            \"$ref\": \"#/properties/unknown_keyword_storage/1\"\n        },\n        \"refa\": {\n            \"$ref\": \"#/properties/unknown_keyword_storage/a\"\n        }\n    },\n    \"additionalProperties\": false\n}\n"
  },
  {
    "path": "test/issue-149-entry-selection.cpp",
    "content": "#include <nlohmann/json-schema.hpp>\n\n#include <iostream>\n\nusing nlohmann::json;\nusing nlohmann::json_uri;\nusing nlohmann::json_schema::json_validator;\n\nnamespace\n{\n\nstatic int error_count;\n#define EXPECT_EQ(a, b)                                              \\\n\tdo {                                                             \\\n\t\tif (a != b) {                                                \\\n\t\t\tstd::cerr << \"Failed: '\" << a << \"' != '\" << b << \"'\\n\"; \\\n\t\t\terror_count++;                                           \\\n\t\t}                                                            \\\n\t} while (0)\n\n// The schema is defined based upon a string literal\nstatic json person_schema = R\"(\n{\n    \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n    \"type\": \"integer\",\n    \"definitions\": {\n        \"A\": {\n            \"type\": \"object\",\n            \"properties\": {\n                \"b\": {\n                    \"$ref\": \"#/definitions/B\"\n                }\n            }\n        },\n        \"B\": {\n            \"type\": \"integer\"\n        }\n    }\n})\"_json;\n\nclass store_err_handler : public nlohmann::json_schema::basic_error_handler\n{\n\tvoid error(const nlohmann::json::json_pointer &ptr, const json &instance, const std::string &message) override\n\t{\n\t\tnlohmann::json_schema::basic_error_handler::error(ptr, instance, message);\n\t\tstd::cerr << \"ERROR: '\" << ptr << \"' - '\" << instance << \"': \" << message << \"\\n\";\n\t\tfailed.push_back(ptr);\n\t}\n\npublic:\n\tstd::vector<nlohmann::json::json_pointer> failed;\n\n\tvoid reset() override\n\t{\n\t\tnlohmann::json_schema::basic_error_handler::reset();\n\t\tfailed.clear();\n\t}\n};\n\n} // namespace\n\nstatic json_validator validator(person_schema);\n\nint main(void)\n{\n\tstore_err_handler err;\n\n\tvalidator.validate(1, err); // OK\n\tEXPECT_EQ(err.failed.size(), 0);\n\terr.reset();\n\n\tvalidator.validate(\"1\", err); // no name\n\tEXPECT_EQ(err.failed.size(), 1);\n\terr.reset();\n\n\tvalidator.validate(1, err, json_uri(\"#/definitions/B\"));\n\tEXPECT_EQ(err.failed.size(), 0);\n\terr.reset();\n\n\tvalidator.validate(\"1\", err, json_uri(\"#/definitions/B\"));\n\tEXPECT_EQ(err.failed.size(), 1);\n\terr.reset();\n\n\tvalidator.validate({{\"b\", 1}}, err, json_uri(\"#/definitions/A\"));\n\tEXPECT_EQ(err.failed.size(), 0);\n\terr.reset();\n\n\tvalidator.validate({{\"b\", \"1\"}}, err, json_uri(\"#/definitions/A\"));\n\tEXPECT_EQ(err.failed.size(), 1);\n\terr.reset();\n\n\treturn error_count;\n}\n"
  },
  {
    "path": "test/issue-189-default-values.cpp",
    "content": "#include <iostream>\n#include <nlohmann/json-schema.hpp>\n\nusing nlohmann::json;\nusing nlohmann::json_uri;\nusing nlohmann::json_schema::json_validator;\n\nstatic const json rectangle_schema = R\"(\n{\n    \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n    \"properties\": {\n        \"width\": {\n            \"$ref\": \"#/definitions/length\",\n            \"default\": 20\n        },\n        \"height\": {\n            \"$ref\": \"#/definitions/length\"\n        }\n    },\n    \"definitions\": {\n        \"length\": {\n            \"type\": \"integer\",\n            \"default\": 10\n        }\n    }\n})\"_json;\n\nstatic const json quad_schema = R\"(\n{\n    \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n    \"properties\": {\n        \"width\": {\n            \"$ref\": \"#/properties/height\",\n            \"default\": 20\n        },\n        \"height\": {\n            \"$ref\": \"#/definitions/length\"\n        },\n        \"depth\": {\n            \"$ref\": \"default_schema#/definitions/defaultLength\"\n        },\n\t\t\"time\": {\n            \"$ref\": \"#/definitions/time\"\n\t\t}\n    },\n    \"definitions\": {\n        \"length\": {\n            \"$ref\": \"default_schema#/definitions/defaultLength\",\n            \"default\": 10\n        },\n        \"time\": {\n            \"type\": \"integer\",\n            \"default\": 15\n        }\n    }\n})\"_json;\n\nstatic const json default_schema = R\"(\n{\n    \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n    \"definitions\": {\n        \"defaultLength\": {\n            \"default\": 5\n        }\n    }\n})\"_json;\n\nstatic void loader(const json_uri &uri, json &schema)\n{\n\tschema = default_schema;\n}\n\nint main(void)\n{\n\tjson_validator validator(loader);\n\n\tvalidator.set_root_schema(quad_schema);\n\n\t{\n\t\tjson empty_quad = R\"({})\"_json;\n\n\t\tconst auto default_patch = validator.validate(empty_quad);\n\t\tconst auto actual = empty_quad.patch(default_patch);\n\n\t\tconst auto expected = R\"({\"height\":10,\"width\":20,\"depth\":5,\"time\":15})\"_json;\n\t\tif (actual != expected) {\n\t\t\tstd::cerr << \"Patch with defaults contains wrong value: '\" << actual << \"' instead of expected '\" << expected.dump() << \"'\" << std::endl;\n\t\t\treturn 1;\n\t\t}\n\t}\n\n\tvalidator.set_root_schema(rectangle_schema);\n\n\t{\n\t\tjson empty_rectangle = R\"({})\"_json;\n\n\t\tconst auto default_patch = validator.validate(empty_rectangle);\n\t\tconst auto actual = empty_rectangle.patch(default_patch);\n\n\t\t// height must be 10 according to the default specified in the length definition while width must be 10 overridden by the width element\n\t\tconst auto expected = R\"({\"height\":10,\"width\":20})\"_json;\n\t\tif (actual != expected) {\n\t\t\tstd::cerr << \"Patch with defaults contains wrong value: '\" << actual << \"' instead of expected '\" << expected.dump() << \"'\" << std::endl;\n\t\t\treturn 1;\n\t\t}\n\t}\n\n\treturn 0;\n}\n"
  },
  {
    "path": "test/issue-209/CMakeLists.txt",
    "content": "add_test_simple_schema(Issue::209\n                       ${CMAKE_CURRENT_SOURCE_DIR}/entities.schema.json\n                       ${CMAKE_CURRENT_SOURCE_DIR}/instance.json)\n"
  },
  {
    "path": "test/issue-209/color.schema.json",
    "content": "{\n        \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n        \"$id\": \"https://example.invalid/color.schema.json\",\n        \"title\": \"color\",\n        \"description\": \"X11/HTML/CSS color name as a JSON string\",\n        \"type\": \"string\",\n        \"enum\": [ \"White\", \"Black\", \"Red\" ]\n}\n"
  },
  {
    "path": "test/issue-209/entities.schema.json",
    "content": "{\n        \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n        \"$id\": \"https://example.invalid/entities.schema.json\",\n        \"title\": \"Entities\",\n        \"type\": \"array\",\n        \"items\": {\n                \"type\": \"object\",\n                \"required\": [ \"name\" ],\n                \"properties\": {\n                        \"name\": {\n                                \"type\": \"string\"\n                        },\n                        \"fg\": { \"$ref\": \"color.schema.json\", \"default\": \"Black\" }\n                }\n        }\n}\n"
  },
  {
    "path": "test/issue-209/instance.json",
    "content": "[\n        {\n                \"name\": \"player\",\n                \"fg\": \"White\"\n        },\n        {\n                \"name\": \"enemy\",\n                \"fg\": \"Red\"\n        }\n]\n"
  },
  {
    "path": "test/issue-229-oneof-default-values.cpp",
    "content": "#include <iostream>\n#include <nlohmann/json-schema.hpp>\n\nusing nlohmann::json;\nusing nlohmann::json_uri;\nusing nlohmann::json_schema::json_validator;\n\nstatic const json default_schema = R\"(\n{\n    \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n    \"type\": \"object\",\n    \"oneOf\": [\n        {\n            \"type\": \"object\",\n            \"properties\": {\n                \"name\": {\n                    \"enum\": \"foo\"\n                },\n                \"code\": {\n                    \"const\": 1,\n                    \"default\": 1\n                }\n            }\n        },\n        {\n            \"type\": \"object\",\n            \"properties\": {\n                \"name\": {\n                    \"enum\": \"bar\"\n                },\n                \"code\": {\n                    \"const\": 2,\n                    \"default\": 2\n                }\n            }\n        }\n    ]\n})\"_json;\n\nstatic void loader(const json_uri &uri, json &schema)\n{\n\tschema = default_schema;\n}\n\nint main(void)\n{\n\tjson_validator validator(loader);\n\n\tvalidator.set_root_schema(default_schema);\n\n\tjson data = R\"({\"name\": \"bar\"})\"_json;\n\tjson expected = R\"(\n        [\n            {\n                \"op\": \"add\",\n                \"path\": \"/code\",\n                \"value\": 2\n            }\n        ]\n    )\"_json;\n\n\tjson patch = validator.validate(data);\n\tif (patch != expected) {\n\t\tstd::cerr << \"Patch contains wrong operation: '\" << patch.dump() << \"' instead of expected '\" << expected.dump() << \"'\" << std::endl;\n\t\treturn 1;\n\t}\n\n\treturn 0;\n}\n"
  },
  {
    "path": "test/issue-243-root-default-values.cpp",
    "content": "#include <iostream>\n#include <nlohmann/json-schema.hpp>\n\nusing nlohmann::json;\nusing nlohmann::json_uri;\nusing nlohmann::json_schema::json_validator;\n\nstatic const json root_default = R\"(\n{\n    \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n    \"properties\": {\n        \"width\": {\n            \"type\": \"integer\"\n        }\n    },\n    \"default\": {\n        \"width\": 42\n    }\n})\"_json;\n\nint main(void)\n{\n\tjson_validator validator{};\n\n\tvalidator.set_root_schema(root_default);\n\n\t{\n\t\tjson nul_json;\n\t\tif (!nul_json.is_null()) {\n\t\t\treturn 1;\n\t\t}\n\n\t\tconst auto default_patch = validator.validate(nul_json);\n\n\t\tif (default_patch.is_null()) {\n\t\t\tstd::cerr << \"Patch is null but should contain operation to add defaults to root\" << std::endl;\n\t\t\treturn 1;\n\t\t}\n\n\t\tconst auto actual = nul_json.patch(default_patch);\n\t\tconst auto expected = R\"({\"width\": 42})\"_json;\n\t\tif (actual != expected) {\n\t\t\tstd::cerr << \"Patch of defaults is wrong for root schema: '\" << actual.dump() << \"' instead of expected '\" << expected.dump() << \"'\" << std::endl;\n\t\t}\n\t}\n\n\treturn 0;\n}\n"
  },
  {
    "path": "test/issue-25-default-values.cpp",
    "content": "#include <iostream>\n#include <nlohmann/json-schema.hpp>\n\nusing nlohmann::json;\nusing nlohmann::json_schema::json_validator;\n\nstatic const json person_schema = R\"(\n{\n    \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n    \"title\": \"A person\",\n    \"properties\": {\n        \"name\": {\n            \"description\": \"Name\",\n            \"type\": \"string\"\n        },\n        \"age\": {\n            \"description\": \"Age of the person\",\n            \"type\": \"number\",\n            \"minimum\": 2,\n            \"maximum\": 200\n        },\n        \"address\": {\n            \"type\": \"object\",\n            \"default\": {},\n            \"properties\": {\n                \"street\": {\n                    \"type\": \"string\",\n                    \"default\": \"Abbey Road\"\n                }\n            }\n        },\n        \"work address\": {\n            \"type\": \"object\",\n            \"default\": null,\n            \"properties\": {\n                \"street\": {\n                    \"type\": \"string\",\n                    \"default\": \"Abbey Road\"\n                }\n            }\n        },\n        \"other address\": {\n            \"type\": \"object\",\n            \"properties\": {\n                \"street\": {\n                    \"type\": \"string\",\n                    \"default\": \"Abbey Road\"\n                }\n            }\n        }\n    },\n    \"required\": [\n                 \"name\",\n                 \"age\"\n                 ],\n    \"additionalProperties\": false,\n    \"type\": \"object\"\n})\"_json;\n\nint main(void)\n{\n\tjson_validator validator{};\n\tvalidator.set_root_schema(person_schema);\n\n\t{\n\t\t// add address which is optional that should generate a diff containing a default street\n\t\tjson person_emtpy_address = R\"({\n\t\t\"name\": \"Hans\",\n\t\t\"age\": 69,\n\t\t\"address\": {}\n\t\t})\"_json;\n\n\t\tconst auto default_patch = validator.validate(person_emtpy_address);\n\n\t\tif (!default_patch.is_array()) {\n\t\t\tstd::cerr << \"Patch with defaults is expected to be an array\" << std::endl;\n\t\t\treturn 1;\n\t\t}\n\n\t\tif (default_patch.size() != 1) {\n\t\t\tstd::cerr << \"Patch with defaults is expected to contain one opperation\" << std::endl;\n\t\t\treturn 1;\n\t\t}\n\n\t\tconst auto &single_op = default_patch[0];\n\n\t\tif (!single_op.contains(\"op\")) {\n\t\t\tstd::cerr << \"Patch with defaults is expected to contain opperation entry\" << std::endl;\n\t\t\treturn 1;\n\t\t}\n\n\t\tif (single_op[\"op\"].get<std::string>() != \"add\") {\n\t\t\tstd::cerr << \"Patch with defaults is expected to contain add opperation\" << std::endl;\n\t\t\treturn 1;\n\t\t}\n\n\t\tif (!single_op.contains(\"path\")) {\n\t\t\tstd::cerr << \"Patch with defaults is expected to contain a path\" << std::endl;\n\t\t\treturn 1;\n\t\t}\n\n\t\tconst auto &readPath = single_op[\"path\"].get<std::string>();\n\t\tif (readPath != \"/address/street\") {\n\t\t\tstd::cerr << \"Patch with defaults contains wrong path. It is \" << readPath << \" and should be \"\n\t\t\t          << \"/address/street\" << std::endl;\n\t\t\treturn 1;\n\t\t}\n\n\t\tif (!single_op.contains(\"value\")) {\n\t\t\tstd::cerr << \"Patch with defaults is expected to contain a value\" << std::endl;\n\t\t\treturn 1;\n\t\t}\n\n\t\tif (single_op[\"value\"].get<std::string>() != \"Abbey Road\") {\n\t\t\tstd::cerr << \"Patch with defaults contains wrong value\" << std::endl;\n\t\t\treturn 1;\n\t\t}\n\t}\n\t{\n\t\t// add address which is optional that should generate a diff containing a empty object\n\t\t// but not work address which is null or other address which has no default\n\t\tjson person_missing_address = R\"({\n\t\t\"name\": \"Hans\",\n\t\t\"age\": 69\n\t\t})\"_json;\n\n\t\tconst auto default_patch = validator.validate(person_missing_address);\n\n\t\tif (!default_patch.is_array()) {\n\t\t\tstd::cerr << \"Patch with defaults is expected to be an array\" << std::endl;\n\t\t\treturn 1;\n\t\t}\n\n\t\tif (default_patch.size() != 1) {\n\t\t\tstd::cerr << \"Patch with defaults is expected to contain one opperation\" << std::endl;\n\t\t\treturn 1;\n\t\t}\n\n\t\tconst auto &single_op = default_patch[0];\n\n\t\tif (!single_op.contains(\"op\")) {\n\t\t\tstd::cerr << \"Patch with defaults is expected to contain opperation entry\" << std::endl;\n\t\t\treturn 1;\n\t\t}\n\n\t\tif (single_op[\"op\"].get<std::string>() != \"add\") {\n\t\t\tstd::cerr << \"Patch with defaults is expected to contain add opperation\" << std::endl;\n\t\t\treturn 1;\n\t\t}\n\n\t\tif (!single_op.contains(\"path\")) {\n\t\t\tstd::cerr << \"Patch with defaults is expected to contain a path\" << std::endl;\n\t\t\treturn 1;\n\t\t}\n\n\t\tconst auto &readPath = single_op[\"path\"].get<std::string>();\n\t\tif (readPath != \"/address\") {\n\t\t\tstd::cerr << \"Patch with defaults contains wrong path. It is \" << readPath << \" and should be \"\n\t\t\t          << \"/address\" << std::endl;\n\t\t\treturn 1;\n\t\t}\n\n\t\tif (!single_op.contains(\"value\")) {\n\t\t\tstd::cerr << \"Patch with defaults is expected to contain a value\" << std::endl;\n\t\t\treturn 1;\n\t\t}\n\n\t\tif (!single_op[\"value\"].is_object() || !single_op[\"value\"].empty()) {\n\t\t\tstd::cerr << \"Patch with defaults contains wrong value\" << std::endl;\n\t\t\treturn 1;\n\t\t}\n\t}\n\treturn 0;\n}\n"
  },
  {
    "path": "test/issue-255-error-message-limit-precision.cpp",
    "content": "#include <nlohmann/json-schema.hpp>\n#include <stdexcept>\n\nusing nlohmann::json;\nusing nlohmann::json_schema::json_validator;\n\nstatic const json schema = R\"(\n{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"arc.schema.json\",\n  \"properties\": {\n    \"angle\": {\n      \"type\": \"number\",\n      \"description\": \"Radians, from -π to π.\",\n      \"minimum\": -3.14159265358979323846,\n      \"maximum\": 3.14159265358979323846\n    }\n  }\n})\"_json;\n\nclass custom_error_handler : public nlohmann::json_schema::basic_error_handler\n{\n\tvoid error(const nlohmann::json::json_pointer &ptr, const json &instance, const std::string &message) override\n\t{\n\t\tif (message != \"instance exceeds maximum of 3.141592653589793\")\n\t\t\tthrow std::invalid_argument(\"Precision print does not work.\");\n\t}\n};\n\nint main(void)\n{\n\tjson_validator validator;\n\n\tauto instance = R\"({ \"angle\": 3.1415927410125732 })\"_json;\n\n\tvalidator.set_root_schema(schema);\n\tcustom_error_handler err;\n\tvalidator.validate(instance, err);\n\n\treturn 0;\n}\n"
  },
  {
    "path": "test/issue-27/CMakeLists.txt",
    "content": "add_test_simple_schema(Issue::27\n                       ${CMAKE_CURRENT_SOURCE_DIR}/schema.json\n                       ${CMAKE_CURRENT_SOURCE_DIR}/instance.json)\nset_tests_properties(Issue::27\n                     PROPERTIES\n                         WILL_FAIL 1)\n"
  },
  {
    "path": "test/issue-27/README",
    "content": "Numbers higher that UINT32_MAX\n"
  },
  {
    "path": "test/issue-27/instance.json",
    "content": "{\"gps_time\": 4294967296}\n"
  },
  {
    "path": "test/issue-27/schema.json",
    "content": "{\n    \"properties\": {\n        \"gps_time\": {\n            \"type\": \"number\",\n            \"minimum\": 0,\n            \"maximum\": 4294967295\n        }\n    },\n    \"required\": [\n        \"gps_time\"\n    ],\n    \"type\": \"object\"\n}\n"
  },
  {
    "path": "test/issue-293.cpp",
    "content": "#include \"nlohmann/json-schema.hpp\"\n\nusing nlohmann::json_schema::json_validator;\n\ntemplate <typename T>\nint should_throw(const nlohmann::json &schema, T value)\n{\n\ttry {\n\t\tjson_validator(schema).validate(value);\n\t} catch (const std::exception &ex) {\n\t\treturn 0;\n\t}\n\treturn 1;\n}\n\nint main(void)\n{\n\n\tjson_validator({{\"type\", \"number\"}, {\"multipleOf\", 0.001}}).validate(0.3 - 0.2);\n\tjson_validator({{\"type\", \"number\"}, {\"multipleOf\", 3.3}}).validate(8.0 - 1.4);\n\tjson_validator({{\"type\", \"number\"}, {\"multipleOf\", 1000.01}}).validate((1000.03 - 0.02) * 15.0);\n\tjson_validator({{\"type\", \"number\"}, {\"multipleOf\", 0.001}}).validate(0.030999999999999993);\n\tjson_validator({{\"type\", \"number\"}, {\"multipleOf\", 0.100000}}).validate(1.9);\n\tjson_validator({{\"type\", \"number\"}, {\"multipleOf\", 100000.1}}).validate(9000009);\n\n\tint exc_count = 0;\n\texc_count += should_throw({{\"type\", \"number\"}, {\"multipleOf\", 0.001}}, 0.3 - 0.2005);\n\texc_count += should_throw({{\"type\", \"number\"}, {\"multipleOf\", 1000.02}}, (1000.03 - 0.02) * 15.0);\n\texc_count += should_throw({{\"type\", \"number\"}, {\"multipleOf\", 100000.11}}, 9000009);\n\n\treturn exc_count;\n}\n"
  },
  {
    "path": "test/issue-311/CMakeLists.txt",
    "content": "add_test_simple_schema(Issue::311\n                       ${CMAKE_CURRENT_SOURCE_DIR}/schema.json\n                       ${CMAKE_CURRENT_SOURCE_DIR}/instance.json)\n"
  },
  {
    "path": "test/issue-311/instance.json",
    "content": "{\n  \"element\": [1],\n  \"element2\": \"test\"\n}\n"
  },
  {
    "path": "test/issue-311/schema.json",
    "content": "{\n  \"type\": \"object\",\n  \"properties\": {\n    \"element\": {\n      \"$ref\": \"#/$defs/element\"\n    },\n    \"element2\": {\n      \"$ref\": \"#/$defs/element/items/0/$defs/element2\"\n    }\n  },\n  \"$defs\": {\n    \"element\": {\n      \"type\": \"array\",\n      \"items\": [\n        {\n          \"$defs\": {\n            \"element2\": {\n              \"type\": \"string\"\n            }\n          },\n          \"type\": \"number\"\n        }\n      ]\n    }\n  }\n}\n"
  },
  {
    "path": "test/issue-48/CMakeLists.txt",
    "content": "add_test_simple_schema(Issue::48\n                       ${CMAKE_CURRENT_SOURCE_DIR}/schema.json\n                       ${CMAKE_CURRENT_SOURCE_DIR}/instance.json)\n"
  },
  {
    "path": "test/issue-48/instance.json",
    "content": "1.2\n"
  },
  {
    "path": "test/issue-48/schema.json",
    "content": "{\n    \"multipleOf\": 0.1\n}\n"
  },
  {
    "path": "test/issue-54/CMakeLists.txt",
    "content": "add_test_simple_schema(Issue::54\n                       ${CMAKE_CURRENT_SOURCE_DIR}/schema.json\n                       ${CMAKE_CURRENT_SOURCE_DIR}/instance.json)\n"
  },
  {
    "path": "test/issue-54/instance.json",
    "content": "0\n"
  },
  {
    "path": "test/issue-54/schema.json",
    "content": "{\n    \"type\": \"integer\",\n    \"minimum\": -2\n}\n"
  },
  {
    "path": "test/issue-70-root-schema-constructor.cpp",
    "content": "#include <nlohmann/json-schema.hpp>\n\n#include <iostream>\n\nstatic int error_count;\n\n#define EXPECT_EQ(a, b)                                              \\\n\tdo {                                                             \\\n\t\tif (a != b) {                                                \\\n\t\t\tstd::cerr << \"Failed: '\" << a << \"' != '\" << b << \"'\\n\"; \\\n\t\t\terror_count++;                                           \\\n\t\t}                                                            \\\n\t} while (0)\n\nusing nlohmann::json;\nusing nlohmann::json_schema::json_validator;\n\nnamespace\n{\n\n// The schema is defined based upon a string literal\nstatic json person_schema = R\"(\n{\n    \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n    \"title\": \"A person\",\n    \"properties\": {\n        \"name\": {\n            \"description\": \"Name\",\n            \"type\": \"string\"\n        },\n        \"age\": {\n            \"description\": \"Age of the person\",\n            \"type\": \"number\",\n            \"minimum\": 2,\n            \"maximum\": 200\n        },\n        \"phones\": {\n            \"type\": \"array\",\n            \"items\": {\n                 \"type\": \"number\"\n            }\n        }\n    },\n    \"required\": [\n                 \"name\",\n                 \"age\"\n                 ],\n    \"additionalProperties\": false,\n    \"type\": \"object\"\n})\"_json;\n\nclass store_ptr_err_handler : public nlohmann::json_schema::basic_error_handler\n{\n\tvoid error(const nlohmann::json::json_pointer &ptr, const json &instance, const std::string &message) override\n\t{\n\t\tnlohmann::json_schema::basic_error_handler::error(ptr, instance, message);\n\t\tstd::cerr << \"ERROR: '\" << ptr << \"' - '\" << instance << \"': \" << message << \"\\n\";\n\t\tfailed_pointers.push_back(ptr);\n\t}\n\npublic:\n\tstd::vector<nlohmann::json::json_pointer> failed_pointers;\n\n\tvoid reset() override\n\t{\n\t\tnlohmann::json_schema::basic_error_handler::reset();\n\t\tfailed_pointers.clear();\n\t}\n};\n\n} // namespace\n\nstatic json_validator validator(person_schema);\n\nint main(void)\n{\n\tstore_ptr_err_handler err;\n\n\tvalidator.validate({{\"age\", 42}, {\"name\", \"John\"}}, err); // OK\n\tEXPECT_EQ(err.failed_pointers.size(), 0);\n\terr.reset();\n\n\tvalidator.validate({{\"age\", 42}}, err); // no name\n\n\tEXPECT_EQ(err.failed_pointers.size(), 1);\n\tEXPECT_EQ(err.failed_pointers[0].to_string(), \"\");\n\terr.reset();\n\n\tvalidator.validate({{\"street\", \"Boulevard\"}}, err); // no name and no age\n\tEXPECT_EQ(err.failed_pointers.size(), 3);\n\tEXPECT_EQ(err.failed_pointers[0].to_string(), \"\");\n\tEXPECT_EQ(err.failed_pointers[1].to_string(), \"\");\n\tEXPECT_EQ(err.failed_pointers[2].to_string(), \"\");\n\terr.reset();\n\n\tvalidator.validate({{\"age\", 42}, {\"name\", 12}}, err); // name must be a string\n\tEXPECT_EQ(err.failed_pointers.size(), 1);\n\tEXPECT_EQ(err.failed_pointers[0].to_string(), \"/name\");\n\terr.reset();\n\n\tvalidator.validate({\n\t                       {\"age\", 42},\n\t                       {\"name\", \"John\"},\n\t                       {\"phones\", {1234, \"223\"}},\n\t                   },\n\t                   err); // name must be a string\n\tEXPECT_EQ(err.failed_pointers.size(), 1);\n\tEXPECT_EQ(err.failed_pointers[0].to_string(), \"/phones/1\");\n\terr.reset();\n\n\tvalidator.validate({\n\t                       {\"age\", 42},\n\t                       {\"name\", \"John\"},\n\t                       {\"phones\", {0}},\n\t                       {\"post-code\", 12345},\n\t                   },\n\t                   err); // name must be a string\n\tEXPECT_EQ(err.failed_pointers.size(), 1);\n\tEXPECT_EQ(err.failed_pointers[0].to_string(), \"\");\n\terr.reset();\n\n\treturn error_count;\n}\n"
  },
  {
    "path": "test/issue-70.cpp",
    "content": "#include <nlohmann/json-schema.hpp>\n\nusing nlohmann::json;\nusing nlohmann::json_schema::json_validator;\n\nstatic const json person_schema = R\"(\n{\n    \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n    \"title\": \"A person\",\n    \"properties\": {\n        \"name\": {\n            \"description\": \"Name\",\n            \"type\": \"string\"\n        },\n        \"age\": {\n            \"description\": \"Age of the person\",\n            \"type\": \"number\",\n            \"minimum\": 2,\n            \"maximum\": 200\n        },\n        \"phones\": {\n            \"type\": \"array\",\n            \"items\": {\n                 \"type\": \"number\"\n            }\n        }\n    },\n    \"required\": [\n                 \"name\",\n                 \"age\"\n                 ],\n    \"additionalProperties\": false,\n    \"type\": \"object\"\n})\"_json;\n\nint main(void)\n{\n\tjson_validator validator;\n\n\tvalidator.set_root_schema(person_schema);\n\tvalidator.set_root_schema(person_schema);\n\n\treturn 0;\n}\n"
  },
  {
    "path": "test/issue-75/CMakeLists.txt",
    "content": "add_test_simple_schema(Issue::75\n                       ${CMAKE_CURRENT_SOURCE_DIR}/schema.json\n                       ${CMAKE_CURRENT_SOURCE_DIR}/instance.json)\n"
  },
  {
    "path": "test/issue-75/TypeId.json",
    "content": "{\n    \"data\" : {\n        \"TypeId\" : {\n            \"type\" : \"string\",\n            \"description\" : \"POD type of data matching bmf::data::TypeId enum\",\n            \"enum\" : [ \"CHAR\", \"UCHAR\", \"SHORT\", \"USHORT\", \"INT\", \"UINT\",\n                       \"LONG\", \"ULONG\", \"FLOAT\", \"DOUBLE\" ]\n       }\n    }\n}\n"
  },
  {
    "path": "test/issue-75/instance.json",
    "content": "[\"INT\", \"LONG\"]\n"
  },
  {
    "path": "test/issue-75/schema.json",
    "content": "{\n    \"type\" : \"array\",\n    \"items\": {\n        \"$ref\": \"TypeId.json#/data/TypeId\"\n    }\n}\n"
  },
  {
    "path": "test/issue-9/CMakeLists.txt",
    "content": "add_test_simple_schema(Issue::9\n                       ${CMAKE_CURRENT_SOURCE_DIR}/base.json\n                       ${CMAKE_CURRENT_SOURCE_DIR}/instance.json)\n"
  },
  {
    "path": "test/issue-9/bar.json",
    "content": "{\r\n  \"$schema\": \"http://json-schema.org/draft-04/schema#\",\r\n  \"description\": \"Describes bar\",\r\n  \"type\": \"object\",\r\n  \"required\": [\r\n    \"name\"\r\n  ],\r\n  \"properties\": {\r\n    \"name\": {\r\n      \"type\": \"string\"\r\n    }\r\n  }\r\n}\n"
  },
  {
    "path": "test/issue-9/base.json",
    "content": "{\r\n  \"$schema\": \"http://json-schema.org/draft-04/schema#\",\r\n  \"description\": \"Describes foo\",\r\n  \"type\": \"object\",\r\n  \"allOf\": [\r\n    { \"$ref\": \"bar.json\" },\r\n    { \"$ref\": \"foo/foo.json\" }\r\n  ]\r\n}\r\n"
  },
  {
    "path": "test/issue-9/foo/baz/baz.json",
    "content": "{\r\n  \"$schema\": \"http://json-schema.org/draft-04/schema#\",\r\n  \"description\": \"Describes baz\",\r\n  \"$ref\": \"qux/qux.json\"\r\n}\r\n"
  },
  {
    "path": "test/issue-9/foo/baz/qux/qux.json",
    "content": "{\r\n  \"$schema\": \"http://json-schema.org/draft-04/schema#\",\r\n  \"description\": \"Describes qux\",\r\n  \"type\": \"object\",\r\n  \"required\": [\r\n    \"name\"\r\n  ],\r\n  \"properties\": {\r\n    \"name\": {\r\n      \"type\": \"string\"\r\n    }\r\n  }\r\n}\n"
  },
  {
    "path": "test/issue-9/foo/foo.json",
    "content": "{\r\n  \"$schema\": \"http://json-schema.org/draft-04/schema#\",\r\n  \"description\": \"Describes foo\",\r\n  \"$ref\": \"baz/baz.json\"\r\n}\r\n"
  },
  {
    "path": "test/issue-9/instance.json",
    "content": "{\n    \"name\": \"name\"\n}\n"
  },
  {
    "path": "test/issue-93/CMakeLists.txt",
    "content": "\nadd_executable(issue-93 issue-93.cpp)\ntarget_link_libraries(issue-93 nlohmann_json_schema_validator)\n\nadd_test(NAME issue-93\n         COMMAND issue-93\n         WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})\n"
  },
  {
    "path": "test/issue-93/blueprints.schema.json",
    "content": "{\n    \"type\":\"array\",\n    \"items\": {\n        \"type\":\"object\",\n        \"properties\": {\n            \"renderable\": {\n                \"$ref\":\"/components.schema.json#/Renderable\"\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "test/issue-93/components.schema.json",
    "content": "{\n    \"Renderable\": {\n        \"type\":\"object\",\n        \"properties\": {\n            \"fg\":{\n                \"$ref\":\"/types/color.schema.json\"\n            },\n            \"bg\":{\n                \"$ref\":\"/types/color.schema.json\"\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "test/issue-93/issue-93.cpp",
    "content": "#include <nlohmann/json-schema.hpp>\n\n#include <fstream>\n#include <iostream>\n\nusing nlohmann::json;\nusing nlohmann::json_uri;\nusing nlohmann::json_schema::json_validator;\n\nstatic const auto expected_patch = R\"(\n[{\"op\":\"add\",\"path\":\"/0/renderable/bg\",\"value\":\"Black\"}]\n)\"_json;\n\nstatic const auto instance = R\"(\n[\n    {\n        \"name\":\"player\",\n        \"renderable\": {\n            \"fg\":\"White\"\n        }\n    }\n]\n)\"_json;\n\nstatic void loader(const json_uri &uri, json &schema)\n{\n\tstd::string filename = \"./\" + uri.path();\n\tstd::ifstream lf(filename);\n\tif (!lf.good())\n\t\tthrow std::invalid_argument(\"could not open \" + uri.url() + \" tried with \" + filename);\n\ttry {\n\t\tlf >> schema;\n\t} catch (const std::exception &e) {\n\t\tthrow e;\n\t}\n}\n\nint main(void)\n{\n\tjson_validator validator(loader);\n\n\tstd::fstream f(\"blueprints.schema.json\");\n\n\tjson schema;\n\tf >> schema;\n\n\tvalidator.set_root_schema(schema);\n\n\tauto missing_default_patch = validator.validate(instance);\n\n\tstd::cerr << missing_default_patch << \"\\n\";\n\tstd::cerr << expected_patch << \"\\n\";\n\n\treturn missing_default_patch != expected_patch;\n}\n"
  },
  {
    "path": "test/issue-93/types/color.schema.json",
    "content": "{\n    \"type\":\"string\",\n    \"default\":\"Black\"\n}\n"
  },
  {
    "path": "test/issue-96/CMakeLists.txt",
    "content": "add_test_simple_schema(Issue::96\n                       ${CMAKE_CURRENT_SOURCE_DIR}/schema.json\n                       ${CMAKE_CURRENT_SOURCE_DIR}/instance.json)\nset_tests_properties(Issue::96\n                     PROPERTIES\n                     WILL_FAIL 1)\n"
  },
  {
    "path": "test/issue-96/instance.json",
    "content": "{\"top\": {\"value\": 101}}\n"
  },
  {
    "path": "test/issue-96/schema.json",
    "content": "{\n    \"$id\": \"http://xxx.local/schemas/mySchema.json\",\n    \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n    \"definitions\": {\n        \"topDef\": {\n            \"$id\": \"#topDef_ref\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"value\": {\n                    \"type\": \"integer\",\n                    \"maximum\": 100\n                }\n            }\n        }\n    },\n\n    \"type\": \"object\",\n    \"properties\": {\n        \"top\": {\n            \"$ref\": \"#/definitions/topDef\"\n        }\n    }\n}\n"
  },
  {
    "path": "test/issue-98.cpp",
    "content": "#include <nlohmann/json-schema.hpp>\n\nint main(void)\n{\n\tnlohmann::json nlBase{{\"$ref\", \"#/unknown/keywords\"}};\n\tnlohmann::json_schema::json_validator validator;\n\n\ttry {\n\t\tvalidator.set_root_schema(nlBase); // this line will log the caught exception\n\t} catch (const std::exception &e) {\n\n\t\tif (std::string(\"after all files have been parsed, '<root>' has still the following undefined references: [/unknown/keywords]\") == e.what())\n\t\t\treturn EXIT_SUCCESS;\n\t}\n\treturn EXIT_FAILURE;\n}\n"
  },
  {
    "path": "test/json-patch.cpp",
    "content": "#include \"../src/json-patch.hpp\"\n\n#include <iostream>\n\nusing nlohmann::json_patch;\n\n#define OK(code)                                                    \\\n\tdo {                                                            \\\n\t\ttry {                                                       \\\n\t\t\tcode;                                                   \\\n\t\t} catch (const std::exception &e) {                         \\\n\t\t\tstd::cerr << \"UNEXPECTED FAILED: \" << e.what() << \"\\n\"; \\\n\t\t\treturn 1;                                               \\\n\t\t}                                                           \\\n\t} while (0)\n\n#define KO(code)                                                \\\n\tdo {                                                        \\\n\t\ttry {                                                   \\\n\t\t\tcode;                                               \\\n\t\t\tstd::cerr << \"UNEXPECTED SUCCESS.\\n\";               \\\n\t\t\treturn 1;                                           \\\n\t\t} catch (const std::exception &e) {                     \\\n\t\t\tstd::cerr << \"EXPECTED FAIL: \" << e.what() << \"\\n\"; \\\n\t\t}                                                       \\\n\t} while (0)\n\nint main(void)\n{\n\tOK(json_patch p1(R\"([{\"op\":\"add\",\"path\":\"/0/renderable/bg\",\"value\":\"Black\"}])\"_json));\n\tOK(json_patch p1(R\"([{\"op\":\"replace\",\"path\":\"/0/renderable/bg\",\"value\":\"Black\"}])\"_json));\n\tOK(json_patch p1(R\"([{\"op\":\"remove\",\"path\":\"/0/renderable/bg\"}])\"_json));\n\n\t// value not needed\n\tKO(json_patch p1(R\"([{\"op\":\"remove\",\"path\":\"/0/renderable/bg\", \"value\":\"Black\"}])\"_json));\n\t// value missing\n\tKO(json_patch p1(R\"([{\"op\":\"add\",\"path\":\"/0/renderable/bg\"}])\"_json));\n\t// value missing\n\tKO(json_patch p1(R\"([{\"op\":\"replace\",\"path\":\"/0/renderable/bg\"}])\"_json));\n\n\t// wrong op\n\tKO(json_patch p1(R\"([{\"op\":\"ad\",\"path\":\"/0/renderable/bg\",\"value\":\"Black\"}])\"_json));\n\n\t// invalid json-pointer\n\tKO(json_patch p1(R\"([{\"op\":\"add\",\"path\":\"0/renderable/bg\",\"value\":\"Black\"}])\"_json));\n\n\treturn 0;\n}\n"
  },
  {
    "path": "test/json-schema-validate.cpp",
    "content": "/*\n * JSON schema validator for JSON for modern C++\n *\n * Copyright (c) 2016-2019 Patrick Boettcher <p@yai.se>.\n *\n * SPDX-License-Identifier: MIT\n *\n */\n#include <nlohmann/json-schema.hpp>\n\n#include <fstream>\n#include <iostream>\n\nusing nlohmann::json;\nusing nlohmann::json_uri;\nusing nlohmann::json_schema::json_validator;\n\nstatic void usage(const char *name)\n{\n\tstd::cerr << \"Usage: \" << name << \" <schema> < <document>\\n\";\n\texit(EXIT_FAILURE);\n}\n\nstatic void loader(const json_uri &uri, json &schema)\n{\n\tstd::string filename = \"./\" + uri.path();\n\tstd::ifstream lf(filename);\n\tif (!lf.good())\n\t\tthrow std::invalid_argument(\"could not open \" + uri.url() + \" tried with \" + filename);\n\ttry {\n\t\tlf >> schema;\n\t} catch (const std::exception &e) {\n\t\tthrow e;\n\t}\n}\n\nclass custom_error_handler : public nlohmann::json_schema::basic_error_handler\n{\n\tvoid error(const nlohmann::json::json_pointer &ptr, const json &instance, const std::string &message) override\n\t{\n\t\tnlohmann::json_schema::basic_error_handler::error(ptr, instance, message);\n\t\tstd::cerr << \"ERROR: '\" << ptr << \"' - '\" << instance << \"': \" << message << \"\\n\";\n\t}\n};\n\nint main(int argc, char *argv[])\n{\n\tif (argc != 2)\n\t\tusage(argv[0]);\n\n\tstd::ifstream f(argv[1]);\n\tif (!f.good()) {\n\t\tstd::cerr << \"could not open \" << argv[1] << \" for reading\\n\";\n\t\tusage(argv[0]);\n\t}\n\n\t// 1) Read the schema for the document you want to validate\n\tjson schema;\n\ttry {\n\t\tf >> schema;\n\t} catch (const std::exception &e) {\n\t\tstd::cerr << e.what() << \" at \" << f.tellg() << \" - while parsing the schema\\n\";\n\t\treturn EXIT_FAILURE;\n\t}\n\n\t// 2) create the validator and\n\tjson_validator validator(loader,\n\t                         nlohmann::json_schema::default_string_format_check);\n\n\ttry {\n\t\t// insert this schema as the root to the validator\n\t\t// this resolves remote-schemas, sub-schemas and references via the given loader-function\n\t\tvalidator.set_root_schema(schema);\n\t} catch (const std::exception &e) {\n\t\tstd::cerr << \"setting root schema failed\\n\";\n\t\tstd::cerr << e.what() << \"\\n\";\n\t}\n\n\t// 3) do the actual validation of the document\n\tjson document;\n\n\ttry {\n\t\tstd::cin >> document;\n\t} catch (const std::exception &e) {\n\t\tstd::cerr << \"json parsing failed: \" << e.what() << \" at offset: \" << std::cin.tellg() << \"\\n\";\n\t\treturn EXIT_FAILURE;\n\t}\n\n\tcustom_error_handler err;\n\tvalidator.validate(document, err);\n\n\tif (err) {\n\t\tstd::cerr << \"schema validation failed\\n\";\n\t\treturn EXIT_FAILURE;\n\t}\n\n\tstd::cerr << \"document is valid\\n\";\n\n\treturn EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/string-format-check-test.cpp",
    "content": "#include <iostream>\n\n#include <nlohmann/json-schema.hpp>\n\n/** @return number of failed tests */\nsize_t\ntestStringFormat(const std::string &format,\n                 const std::vector<std::pair<std::string, bool>> &stringValidTests)\n{\n\tsize_t numberOfErrors = 0;\n\n\tfor (auto stringValid = stringValidTests.begin(); stringValid != stringValidTests.end(); ++stringValid) {\n\t\tstd::cout << \"[INFO] Testing \" << format << \": \" << stringValid->first << \"\\n\";\n\n\t\ttry {\n\t\t\tnlohmann::json_schema::default_string_format_check(format, stringValid->first);\n\n\t\t\tif (!stringValid->second) {\n\t\t\t\t++numberOfErrors;\n\t\t\t\tstd::cerr << \"[ERROR] String with \" << format << \" format '\" << stringValid->first\n\t\t\t\t          << \"' validated even though it should NOT!\\n\";\n\t\t\t}\n\t\t} catch (std::exception &exception) {\n\t\t\tstd::cout << \"[INFO] Validation failed with: \" << exception.what() << \"\\n\";\n\t\t\tif (stringValid->second) {\n\t\t\t\t++numberOfErrors;\n\t\t\t\tstd::cerr << \"[ERROR] String with \" << format << \" format '\" << stringValid->first\n\t\t\t\t          << \"' did NOT validate even though it should!\\n\";\n\t\t\t}\n\t\t}\n\t}\n\n\treturn numberOfErrors;\n}\n\nint main()\n{\n\tsize_t numberOfErrors = 0;\n\n\tconst std::vector<std::pair<std::string, bool>> dateTimeChecks{\n\t    {\"1985-04-12T23:20:50.52Z\", true},\n\t    {\"1996-12-19T16:39:57-08:00\", true},\n\t    {\"1990-12-31T23:59:60Z\", true},\n\t    {\"1990-12-31T15:59:60-08:00\", true},\n\t    {\"1937-01-01T12:00:27.87+00:20\", true},\n\t    {\"1985-4-12T23:20:50.52Z\", false},\n\t    {\"1985-04-12T23:20:50.52\", false},\n\t    {\"1985-04-12T24:00:00\", false},\n\t    {\"\", false},\n\t    {\"2019-04-30T11:11:11+01:00\", true},\n\t    {\"2019-04-31T11:11:11+01:00\", false},\n\t    {\"2019-02-28T11:11:11+01:00\", true},\n\t    {\"2019-02-29T11:11:11+01:00\", false},\n\t    {\"2020-02-29T11:11:11+01:00\", true},\n\t    {\"2020-02-30T11:11:11+01:00\", false},\n\t    {\"2020-02-29T23:59:59+01:00\", true},\n\t    {\"2020-02-29T23:59:60+01:00\", false},\n\t    {\"2020-02-29T23:59:60+00:00\", true},\n\t    {\"2020-02-29T23:60:59+01:00\", false},\n\t    {\"2019-09-30T11:11:11+01:00\", true},\n\t    {\"2019-09-31T11:11:11+01:00\", false},\n\t    {\"2019-09-30T11:11:11+23:59\", true},\n\t    {\"2019-09-30T11:11:11+24:00\", false}};\n\n\tnumberOfErrors += testStringFormat(\"date-time\", dateTimeChecks);\n\n\tconst std::vector<std::pair<std::string, bool>> ipv4Checks{\n\t    {\"\", false},\n\t    {\"x99.99.99.99\", false},\n\t    {\"99.99.99.99x\", false},\n\t    {\"192.168.0.1\", true},\n\t    {\"127.0.0\", false},\n\t    {\"127.0.0.1\", true},\n\t    {\"127.0.0.0.1\", false},\n\t    {\"255.255.255.255\", true},\n\t    {\"255.255.255.256\", false},\n\t    {\"255.255.256.255\", false},\n\t    {\"255.256.255.255\", false},\n\t    {\"256.255.255.255\", false},\n\t    {\"256.256.256.256\", false},\n\t    {\"0x7f000001\", false}};\n\n\tnumberOfErrors += testStringFormat(\"ipv4\", ipv4Checks);\n\n\tconst std::vector<std::pair<std::string, bool>> uriChecks{\n\t    {\"http://www.google.com/search?q=regular%20expression\", true},\n\t    {\"http://www.google.com/\", true},\n\t    {\"http://www.google.com/search?q=regular%20expression\", true},\n\t    {\"www.google.com\", false},\n\t    {\"http://www.google.comj\", true},\n\t    {\"ldap://[2001:db8::7]/c=GB?objectClass?one\", true},\n\t    {\"mailto:John.Doe@example.com\", true},\n\t    {\"news:comp.infosystems.www.servers.unix\", true},\n\t    {\"https://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top\", true},\n\t    {\"tel:+1-816-555-1212\", true},\n\t    {\"telnet://192.0.2.16:80/\", true},\n\t    {\"urn:oasis:names:specification:docbook:dtd:xml:4.1.2\", true}};\n\n\tnumberOfErrors += testStringFormat(\"uri\", uriChecks);\n\n\treturn numberOfErrors;\n}\n"
  },
  {
    "path": "test/test-pipe-in.sh",
    "content": "#!/bin/bash\n\n# all argument are considered as a program to call (with its arguments),\n# the last argument is read from stdin via '<'\n\nset -e\n\narr=( \"$@\" )\n\ninput=${arr[${#arr[@]}-1]}\nunset 'arr[${#arr[@]}-1]'\n\n${arr[@]} < $input\n"
  },
  {
    "path": "test/uri.cpp",
    "content": "/*\n * JSON schema validator for JSON for modern C++\n *\n * Copyright (c) 2016-2019 Patrick Boettcher <p@yai.se>.\n *\n * SPDX-License-Identifier: MIT\n *\n */\n#include <cstdlib>\n#include <nlohmann/json-schema.hpp>\n\n#include <iostream>\n\nusing nlohmann::json;\nusing nlohmann::json_uri;\n\nstatic int errors;\n\nstatic void EXPECT_EQ(const std::string &a, const std::string &b)\n{\n\tif (a != b) {\n\t\tstd::cerr << \"Failed: '\" << a << \"' != '\" << b << \"'\\n\";\n\t\terrors++;\n\t}\n}\n\nstatic void EXPECT_EQ(const nlohmann::json_uri &a, const std::string &b)\n{\n\tEXPECT_EQ(a.to_string(), b);\n}\n\nstatic void paths(json_uri start,\n                  const std::string &full,\n                  const std::string &full_path,\n                  const std::string &no_path)\n{\n\tEXPECT_EQ(start, full + \" # \");\n\n\tauto a = start.derive(\"other.json\");\n\tEXPECT_EQ(a, full_path + \"/other.json # \");\n\n\tauto b = a.derive(\"base.json\");\n\tEXPECT_EQ(b, full_path + \"/base.json # \");\n\n\tauto c = b.derive(\"subdir/base.json\");\n\tEXPECT_EQ(c, full_path + \"/subdir/base.json # \");\n\n\tauto d = c.derive(\"subdir2/base.json\");\n\tEXPECT_EQ(d, full_path + \"/subdir/subdir2/base.json # \");\n\n\tauto e = c.derive(\"/subdir2/base.json\");\n\tEXPECT_EQ(e, no_path + \"/subdir2/base.json # \");\n\n\tauto f = c.derive(\"new.json\");\n\tEXPECT_EQ(f, full_path + \"/subdir/new.json # \");\n\n\tauto g = c.derive(\"/new.json\");\n\tEXPECT_EQ(g, no_path + \"/new.json # \");\n}\n\nstatic void pointer_plain_name(json_uri start,\n                               const std::string &full,\n                               const std::string &full_path,\n                               const std::string &no_path)\n{\n\tauto a = start.derive(\"#/json/path\");\n\tEXPECT_EQ(a, full + \" # /json/path\");\n\n\ta = start.derive(\"#/json/special_%22\");\n\tEXPECT_EQ(a, full + \" # /json/special_\\\"\");\n\n\ta = a.derive(\"#foo\");\n\tEXPECT_EQ(a, full + \" # foo\");\n\n\ta = a.derive(\"#foo/looks_like_json/poiner/but/isnt\");\n\tEXPECT_EQ(a, full + \" # foo/looks_like_json/poiner/but/isnt\");\n\tEXPECT_EQ(a.identifier(), \"foo/looks_like_json/poiner/but/isnt\");\n\tEXPECT_EQ(a.pointer().to_string(), \"\");\n\n\ta = a.derive(\"#/looks_like_json/poiner/and/it/is\");\n\tEXPECT_EQ(a, full + \" # /looks_like_json/poiner/and/it/is\");\n\tEXPECT_EQ(a.pointer().to_string(), \"/looks_like_json/poiner/and/it/is\");\n\tEXPECT_EQ(a.identifier(), \"\");\n}\n\nint main(void)\n{\n\tjson_uri empty(\"\");\n\tpaths(empty,\n\t      \"\",\n\t      \"\",\n\t      \"\");\n\n\tjson_uri http(\"http://json-schema.org/draft-07/schema#\");\n\tpaths(http,\n\t      \"http://json-schema.org/draft-07/schema\",\n\t      \"http://json-schema.org/draft-07\",\n\t      \"http://json-schema.org\");\n\n\tpointer_plain_name(http,\n\t                   \"http://json-schema.org/draft-07/schema\",\n\t                   \"http://json-schema.org/draft-07\",\n\t                   \"http://json-schema.org\");\n\n\treturn errors;\n}\n"
  }
]