diff --git a/include/nlohmann/detail/view/builder.hpp b/include/nlohmann/detail/view/builder.hpp index e1aa9c86d..1bcbbb4c0 100644 --- a/include/nlohmann/detail/view/builder.hpp +++ b/include/nlohmann/detail/view/builder.hpp @@ -10,6 +10,7 @@ #pragma once #include // max +#include // array #include // size_t, ptrdiff_t #include // uint8_t, uint16_t, uint32_t, uint64_t #include // memcmp, memcpy @@ -86,8 +87,15 @@ class builder builder(const builder&) = delete; builder& operator=(const builder&) = delete; + builder(builder&&) = delete; + builder& operator=(builder&&) = delete; + ~builder() = default; - parse_failure failure{}; + /// where and why the parse failed (after run() returned false) + const parse_failure& failure() const noexcept + { + return m_failure; + } private: struct frame @@ -100,16 +108,17 @@ class builder document_data& doc; const unsigned char* const b; const unsigned char* const e; + parse_failure m_failure{}; // the open array/object is in the cursor; enclosing ones on a stack that is // inline for the first 64 levels - frame shallow[64]; + frame shallow[64]; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays): not initialized on purpose; filled as containers open std::vector deep{}; NLOHMANN_VIEW_NOINLINE bool fail(error_code c, const unsigned char* at) noexcept { - failure.code = c; - failure.offset = static_cast(at - b); + m_failure.code = c; + m_failure.offset = static_cast(at - b); doc.tape_size = 0; return false; } @@ -187,34 +196,23 @@ class builder const std::uint64_t done = static_cast(at - b) + 1; const std::uint64_t guess = static_cast(n) * static_cast(e - b + 1) / done; doc.tape_size = n; - doc.reserve((std::max)(static_cast(guess + guess / 4 + 64), n + n / 2 + 64)); + doc.reserve((std::max)(static_cast(guess + (guess / 4) + 64), n + (n / 2) + 64)); return doc.tape; } /// four hex digits at p as a code unit (p moves past them), or -1 (p at /// the first bad digit); one table lookup per digit and a single check, - /// as in yyjson's read_hex_u16 + /// the four hex digits of a unicode escape (the library's table, after + /// yyjson's read_hex_u16), or -1 NLOHMANN_VIEW_ALWAYS_INLINE int hex4(const unsigned char*& p) noexcept { - // digit values; 0xF0: not a hex digit - static const std::uint8_t hex[256] = - { - 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, - 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, - 0xF0, 10, 11, 12, 13, 14, 15, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, - 0xF0, 10, 11, 12, 13, 14, 15, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, - 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, - 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, - 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, - 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, - }; if (NLOHMANN_VIEW_LIKELY(e - p >= 4)) { - const unsigned d0 = hex[p[0]], d1 = hex[p[1]], d2 = hex[p[2]], d3 = hex[p[3]]; - if (NLOHMANN_VIEW_LIKELY(((d0 | d1 | d2 | d3) & 0xF0u) == 0)) + const int cp = hex_codepoint(p); + if (NLOHMANN_VIEW_LIKELY(cp >= 0)) { p += 4; - return static_cast((d0 << 12) | (d1 << 8) | (d2 << 4) | d3); + return cp; } } p = hex4_error(p); @@ -239,12 +237,14 @@ class builder NLOHMANN_VIEW_NOINLINE decoded slow_string(const unsigned char* s, const unsigned char* p) { // single-character escapes; 0: invalid (and 'u', handled separately) - static const char simple_escape[128] = + static const std::array simple_escape = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '/', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '\\', 0, 0, 0, - 0, 0, '\b', 0, 0, 0, '\f', 0, 0, 0, 0, 0, 0, 0, '\n', 0, 0, 0, '\r', 0, '\t', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '/', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '\\', 0, 0, 0, + 0, 0, '\b', 0, 0, 0, '\f', 0, 0, 0, 0, 0, 0, 0, '\n', 0, 0, 0, '\r', 0, '\t', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + } }; const std::size_t start = arena_used(); arena_run(s, static_cast(p - s)); @@ -372,8 +372,8 @@ class builder { const std::size_t used = arena_used(); doc.arena.resize((std::max)(doc.arena.size() * 2, used + n + 256)); - aw = &doc.arena[0] + used; - aend = &doc.arena[0] + doc.arena.size(); + aw = &doc.arena[0] + used; // NOLINT(readability-container-data-pointer): data() is const before C++17 + aend = &doc.arena[0] + doc.arena.size(); // NOLINT(readability-container-data-pointer) } /// append the run [r, r + n) to the arena; short runs as one fixed-size @@ -668,7 +668,11 @@ root_done: /// never matches a JSON token, so the error paths tell the end apart. NLOHMANN_VIEW_ALWAYS_INLINE unsigned char cur() const noexcept { - return Sentinel ? *p : (p != e ? *p : 0); + if (Sentinel) + { + return *p; + } + return p != e ? *p : 0; } /// root scalar @@ -731,11 +735,7 @@ root_done: { // (a branch, not an add of the comparison: p must not // wait for the byte after the line break) - if (NLOHMANN_VIEW_LIKELY(cur() == '\n')) - { - ++p; - } - else if ((Sentinel || e - p >= 2) && p[1] == '\n') + if (NLOHMANN_VIEW_UNLIKELY(cur() == '\r') && (Sentinel || e - p >= 2) && p[1] == '\n') { p += 2; } @@ -746,7 +746,7 @@ root_done: // indentation: two spaces per step, fixed offsets (after yyjson) while (e - p >= 32) { -#define NLOHMANN_VIEW_STEP(i) if (NLOHMANN_VIEW_LIKELY(load16(p + 2 * (i)) == 0x2020)) {} else { p += 2 * (i); goto indent_done; } +#define NLOHMANN_VIEW_STEP(i) if (NLOHMANN_VIEW_LIKELY(load16(p + (std::ptrdiff_t{2} * (i))) == 0x2020)) {} else { p += std::ptrdiff_t{2} * (i); goto indent_done; } NLOHMANN_VIEW_REPEAT16(NLOHMANN_VIEW_STEP) #undef NLOHMANN_VIEW_STEP p += 32; @@ -778,7 +778,7 @@ indent_done: { if (NLOHMANN_VIEW_UNLIKELY(out == cap)) { - const std::size_t n = static_cast(out - base); + const auto n = static_cast(out - base); base = cold.grow(n, p); out = base + n; cap = base + cold.doc.tape_cap; @@ -827,7 +827,7 @@ indent_done: n.next = static_cast(out - base) - cur_idx; if (--depth != 0) { - frame f; + frame f{}; if (NLOHMANN_VIEW_LIKELY(depth <= 64)) { f = cold.shallow[depth - 1]; @@ -877,7 +877,7 @@ indent_done: { return fail(error_code::number_after_minus); } - const std::size_t int_digits = static_cast(p - int_start); + const auto int_digits = static_cast(p - int_start); std::size_t frac_digits = 0; bool is_float = false; if (p != e && *p == '.') @@ -910,7 +910,7 @@ indent_done: { if (exponent < 100000) { - exponent = exponent * 10 + (*p - '0'); + exponent = (exponent * 10) + (*p - '0'); } ++p; } @@ -921,7 +921,11 @@ indent_done: is_float = true; } - value_t kind = is_float ? value_t::number_float : (negative ? value_t::number_integer : value_t::number_unsigned); + value_t kind = value_t::number_float; + if (!is_float) + { + kind = negative ? value_t::number_integer : value_t::number_unsigned; + } if (!is_float) { // integers that do not fit become floats, as in parse() @@ -944,19 +948,19 @@ indent_done: // could reach 1e308 need the conversion if (NLOHMANN_VIEW_UNLIKELY(static_cast(int_digits) + exponent > 300 && kind == value_t::number_float)) { - if (cold.float_overflows(s, p)) + if (builder::float_overflows(s, p)) { p = s; return fail(error_code::number_overflow); } } const auto layout = static_cast((int_digits < 255 ? int_digits : 255) | ((frac_digits < 255 ? frac_digits : 255) << 8)); - std::uint64_t second = static_cast(p - s); + auto second = static_cast(p - s); if (kind != value_t::number_float) { // integers are converted now, while their digits are in cache const std::uint64_t m = int_digits <= 19 ? parse_upto19(int_start, static_cast(int_digits), e) - : parse_upto19(int_start, 19, e) * 10 + static_cast(int_start[19] - '0'); + : (parse_upto19(int_start, 19, e) * 10) + static_cast(int_start[19] - '0'); second = negative ? 0 - m : m; } emit(kind, 0, layout, static_cast(s - b), second); @@ -995,12 +999,12 @@ inline bool build_with(document_data& d, const char* src, std::size_t size, bool { builder bld(d, src, size); const bool ok = bld.run(); - failure = bld.failure; + failure = bld.failure(); return ok; } builder bld(d, src, size); const bool ok = bld.run(); - failure = bld.failure; + failure = bld.failure(); return ok; } diff --git a/include/nlohmann/detail/view/document_data.hpp b/include/nlohmann/detail/view/document_data.hpp index 294cc7bc4..d74383a85 100644 --- a/include/nlohmann/detail/view/document_data.hpp +++ b/include/nlohmann/detail/view/document_data.hpp @@ -8,6 +8,7 @@ #pragma once +#include // array #include // size_t #include // memcpy #include // operator new, placement new @@ -34,9 +35,9 @@ struct document_data std::size_t tape_cap = 0; node* inline_tape = nullptr; ///< node array allocated together with this header std::size_t inline_cap = 0; - std::string arena{}; ///< decoded strings that contained escapes - std::string owned{}; ///< owned copy of the input, if any - const char* base[4] = {nullptr, nullptr, nullptr, nullptr}; ///< string bases: source, arena (indexed by flags & node_flags::storage) + std::string arena{}; ///< decoded strings that contained escapes // NOLINT(readability-redundant-member-init) + std::string owned{}; ///< owned copy of the input, if any // NOLINT(readability-redundant-member-init) + std::array base = {{nullptr, nullptr, nullptr, nullptr}}; ///< string bases: source, arena (indexed by flags & node_flags::storage) bool discarded = true; /// one allocation for the header and room for `nodes` nodes; large @@ -45,8 +46,9 @@ struct document_data { nodes = nodes <= 256 ? nodes : 0; void* mem = ::operator new (sizeof(document_data) + (nodes * sizeof(node))); - auto* d = new (mem) document_data(); - d->inline_tape = static_cast(static_cast(static_cast(mem) + sizeof(document_data))); // (aligned: sizeof is a multiple of the alignment) + auto* d = new (mem) document_data(); // NOLINT(cppcoreguidelines-owning-memory): owned by the returned pointer, freed by deleter + // (aligned: sizeof is a multiple of the alignment; through void*, as GCC's -Wcast-align wants) + d->inline_tape = static_cast(static_cast(static_cast(mem) + sizeof(document_data))); // NOLINT(bugprone-casting-through-void) d->inline_cap = nodes; d->tape = d->inline_tape; d->tape_cap = nodes; diff --git a/include/nlohmann/detail/view/scan.hpp b/include/nlohmann/detail/view/scan.hpp index fc9b075aa..fcaf06624 100644 --- a/include/nlohmann/detail/view/scan.hpp +++ b/include/nlohmann/detail/view/scan.hpp @@ -9,6 +9,7 @@ #pragma once +#include // array #include // size_t #include // uint8_t, uint16_t, uint64_t #include // memcpy @@ -30,18 +31,20 @@ namespace view /// 1 for bytes that may appear verbatim in a string: 0x20..0x7F except '"' and '\\' inline const std::uint8_t* string_plain() noexcept { - static const std::uint8_t table[256] = + static const std::array table = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x00..0x1F - 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x20..0x3F ('"') - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 0x40..0x5F ('\\') - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x60..0x7F - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x80..0x9F - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xA0..0xBF - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xC0..0xDF - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xE0..0xFF + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x00..0x1F + 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x20..0x3F ('"') + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 0x40..0x5F ('\\') + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x60..0x7F + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x80..0x9F + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xA0..0xBF + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xC0..0xDF + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xE0..0xFF + } }; - return table; + return table.data(); } NLOHMANN_VIEW_ALWAYS_INLINE bool is_digit(unsigned char c) noexcept @@ -133,11 +136,13 @@ NLOHMANN_VIEW_ALWAYS_INLINE const unsigned char* skip_digits(const unsigned char /// powers of ten up to 10^19 as integers inline std::uint64_t int_pow10(unsigned k) noexcept { - static const std::uint64_t table[20] = + static const std::array table = { - 1u, 10u, 100u, 1000u, 10000u, 100000u, 1000000u, 10000000u, 100000000u, 1000000000u, - 10000000000u, 100000000000u, 1000000000000u, 10000000000000u, 100000000000000u, 1000000000000000u, - 10000000000000000u, 100000000000000000u, 1000000000000000000u, 10000000000000000000u + { + 1u, 10u, 100u, 1000u, 10000u, 100000u, 1000000u, 10000000u, 100000000u, 1000000000u, + 10000000000u, 100000000000u, 1000000000000u, 10000000000000u, 100000000000000u, 1000000000000000u, + 10000000000000000u, 100000000000000000u, 1000000000000000000u, 10000000000000000000u + } }; return table[k]; } diff --git a/tests/src/unit-json_view_builder.cpp b/tests/src/unit-json_view_builder.cpp index 8fba0180e..4d2d3ffd8 100644 --- a/tests/src/unit-json_view_builder.cpp +++ b/tests/src/unit-json_view_builder.cpp @@ -138,7 +138,7 @@ void check_same(const std::string& text) // a small deterministic generator of documents struct generator { - std::mt19937 rng{5295}; + std::mt19937 rng{5295}; // NOLINT(cert-msc32-c,cert-msc51-cpp,bugprone-random-generator-seed) int r(int n) { @@ -155,7 +155,7 @@ struct generator void str(std::string& o) { - static const char* const pieces[] = {"a", "Z", " ", "~", "\\n", "\\\"", "\\\\", "\\/", "\\u00e9", "\\ud83d\\ude00", "\xc3\xa9", "\xe3\x81\x82", "\xf0\x9f\x98\x80", "\x7f", "\\u001f", "long enough text to leave the first 16 bytes"}; + static const char* const pieces[] = {"a", "Z", " ", "~", "\\n", "\\\"", "\\\\", "\\/", "\\u00e9", "\\ud83d\\ude00", "\xc3\xa9", "\xe3\x81\x82", "\xf0\x9f\x98\x80", "\x7f", "\\u001f", "long enough text to leave the first 16 bytes"}; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) o += '"'; for (int n = r(3) == 0 ? r(20) : r(6); n > 0; --n) { @@ -166,7 +166,7 @@ struct generator void num(std::string& o) { - static const char* const numbers[] = {"0", "-0", "1", "-1", "12", "123456789", "1234567890123456789", "9223372036854775807", "-9223372036854775808", + static const char* const numbers[] = {"0", "-0", "1", "-1", "12", "123456789", "1234567890123456789", "9223372036854775807", "-9223372036854775808", // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) "9223372036854775808", "18446744073709551615", "18446744073709551616", "-9223372036854775809", "1.5", "-2.25e-3", "1e10", "1E+2", "0.000001", "3.141592653589793238462643", "1e308", "-1e-400", "123.456e7" }; @@ -206,7 +206,7 @@ struct generator } else { - static const char* const literals[] = {"true", "false", "null"}; + static const char* const literals[] = {"true", "false", "null"}; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) o += literals[r(3)]; } ws(o); @@ -220,8 +220,8 @@ TEST_CASE("json_view builder") { for (const char* text : { - "null", "true", "false", "0", "-0", "42", "-42", "1.5", "\"\"", "\"abc\"", "[]", "{}", "[1,2,3]", "{\"a\":1,\"b\":[true,null]}", - " [ 1 , 2 ] ", "{\"a\" : {\"b\" : {}}}", "[[[]]]", "\"\\u00e4\\n\\ud83d\\ude00\"", "{\"a\":1,\"a\":2}", "18446744073709551616", + "null", "true", "false", "0", "-0", "42", "-42", "1.5", "\"\"", "\"abc\"", "[]", "{}", "[1,2,3]", "{\"a\":1,\"b\":[true,null]}", // NOLINT(modernize-raw-string-literal) + " [ 1 , 2 ] ", "{\"a\" : {\"b\" : {}}}", "[[[]]]", "\"\\u00e4\\n\\ud83d\\ude00\"", "{\"a\":1,\"a\":2}", "18446744073709551616", // NOLINT(modernize-raw-string-literal) "-9223372036854775809", "123456789012345678901234567890", "1e400", "-1e400", "1.7976931348623157e308" }) { @@ -234,7 +234,7 @@ TEST_CASE("json_view builder") for (const char* text : { "", " ", "[", "]", "{", "}", "[1,]", "{\"a\":1,}", "[1 2]", "{\"a\" 1}", "{1:2}", "tru", "nul", "fals", "truex", "-", "01", "1.", ".5", "1e", "1e+", - "\"", "\"abc", "\"\\x\"", "\"\\u12\"", "\"\\u12G4\"", "\"\\ud800\"", "\"\\udc00\"", "\"\\ud800\\u0041\"", "\"\x01\"", "\"\xff\"", "\"\xc3\"", + "\"", "\"abc", "\"\\x\"", "\"\\u12\"", "\"\\u12G4\"", "\"\\ud800\"", "\"\\udc00\"", "\"\\ud800\\u0041\"", "\"\x01\"", "\"\xff\"", "\"\xc3\"", // NOLINT(modernize-raw-string-literal) "\"\xe0\x80\x80\"", "\"\xed\xa0\x80\"", "[1]x", "[1] [2]", "/", "/*", "/* */ 1", "// c\n1", "1 // c", "[1,/*c*/2]", "[1,2,]" }) { @@ -296,7 +296,7 @@ TEST_CASE("json_view builder") // damage: flip one byte, or cut the text std::string damaged = text; const auto at = static_cast(g.r(static_cast(damaged.size()))); - static const char replacements[] = {'x', '"', '\\', ',', ':', ']', '}', '[', '{', '1', '-', '.', 'e', '\0', '\n', '/'}; + static const char replacements[] = {'x', '"', '\\', ',', ':', ']', '}', '[', '{', '1', '-', '.', 'e', '\0', '\n', '/'}; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) damaged[at] = replacements[g.r(16)]; check_same(damaged); check_same(text.substr(0, at));