| // __ _____ _____ _____ | |
| // __| | __| | | | JSON for Modern C++ (supporting code) | |
| // | | |__ | | | | | | version 3.12.0 | |
| // |_____|_____|_____|_|___| https://github.com/nlohmann/json | |
| // | |
| // SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me> | |
| // SPDX-License-Identifier: MIT | |
| #pragma once | |
| #include <array> // array | |
| #include <cstdint> // uint8_t | |
| #include <cstddef> // size_t | |
| #include <fstream> // ifstream, ios | |
| #include <iterator> // istream_iterator | |
| #include <vector> // vector | |
| namespace utils | |
| { | |
| // Some tests intentionally discard the [[nodiscard]]/JSON_HEDLEY_WARN_UNUSED_RESULT | |
| // return value of a call they only make to exercise its side effects (e.g. checking | |
| // that it does not throw). A plain (void) cast on the call expression does not | |
| // suppress GCC's warning for functions using the GNU __attribute__((warn_unused_result)) | |
| // form (as opposed to the C++17 [[nodiscard]] attribute) -- passing the value into an | |
| // ordinary function call does. | |
| template<typename T> | |
| inline void ignore_return_value(T&& /*unused*/) noexcept {} | |
| // Advance i toward last (inclusive) by stride, always visiting last. | |
| // stride 7 is coprime to 256, so every low-byte residue is still hit. | |
| template<typename T> | |
| T next_integer_sample(T i, T last, T stride) | |
| { | |
| if (i >= last) | |
| { | |
| return static_cast<T>(last + 1); | |
| } | |
| if (stride > 0 && i > static_cast<T>(last - stride)) | |
| { | |
| return last; | |
| } | |
| const T n = static_cast<T>(i + stride); | |
| return n < last ? n : last; | |
| } | |
| // UTF-8 continuation bytes in [lo, hi] that stand in for all of them in the | |
| // ill-formed UTF-8 tests. Both the lexer's range checks and the serializer's | |
| // decoder (detail::decode) only distinguish the classes 0x80..0x8F, 0x90..0x9F, | |
| // and 0xA0..0xBF, so the first and last byte of each class within [lo, hi] | |
| // exercise every behavior while a test sweeps another byte position through | |
| // all 256 values (#5418). Define JSON_TEST_UTF8_EXHAUSTIVE to get every byte. | |
| inline std::vector<int> utf8_continuation_bytes(int lo, int hi) | |
| { | |
| std::vector<int> result; | |
| #ifdef JSON_TEST_UTF8_EXHAUSTIVE | |
| for (int byte = lo; byte <= hi; ++byte) | |
| { | |
| result.push_back(byte); | |
| } | |
| #else | |
| static const std::array<int, 6> class_ends = {{0x80, 0x8F, 0x90, 0x9F, 0xA0, 0xBF}}; | |
| for (const int byte : class_ends) | |
| { | |
| if (lo <= byte && byte <= hi) | |
| { | |
| result.push_back(byte); | |
| } | |
| } | |
| #endif | |
| return result; | |
| } | |
| inline std::vector<std::uint8_t> read_binary_file(const std::string& filename) | |
| { | |
| std::ifstream file(filename, std::ios::binary); | |
| file.unsetf(std::ios::skipws); | |
| file.seekg(0, std::ios::end); | |
| const auto size = file.tellg(); | |
| file.seekg(0, std::ios::beg); | |
| std::vector<std::uint8_t> byte_vector; | |
| byte_vector.reserve(static_cast<std::size_t>(size)); | |
| byte_vector.insert(byte_vector.begin(), std::istream_iterator<std::uint8_t>(file), std::istream_iterator<std::uint8_t>()); | |
| return byte_vector; | |
| } | |
| // sentinel for istreambuf_iterator; compares != true until EOF is reached | |
| // lets tests read a file directly via the new iterator+sentinel overloads | |
| // instead of buffering the whole file into a vector first. | |
| // Only the iterator-first direction (it != sentinel) is ever evaluated by | |
| // the library's parse loop, so no reversed-order overload is needed. | |
| struct istreambuf_sentinel | |
| { | |
| friend bool operator!=(const std::istreambuf_iterator<char>& it, const istreambuf_sentinel& /*unused*/) noexcept | |
| { | |
| return it != std::istreambuf_iterator<char>(); | |
| } | |
| }; | |
| } // namespace utils |