LLVMFuzzerTestOneInput:
    9|  3.43k|{
   10|       |   // use a vector with null termination instead of a std::string to avoid
   11|       |   // small string optimization to hide bounds problems
   12|  3.43k|   std::vector<char> buffer{Data, Data + Size};
   13|       |
   14|       |   // non-null terminated
   15|  3.43k|   {
   16|  3.43k|      [[maybe_unused]] auto maybe_smaller = glz::minify_json(buffer);
   17|  3.43k|   }
   18|       |
   19|       |   // null terminated
   20|  3.43k|   {
   21|  3.43k|      buffer.push_back('\0');
   22|  3.43k|      [[maybe_unused]] auto maybe_smaller = glz::minify_json(buffer);
   23|  3.43k|   }
   24|       |
   25|       |   // The comment enabled path is a different scan: read_jsonc_comment only runs here, and it is
   26|       |   // the scanner that has to report an unterminated comment rather than swallow the buffer. Fuzzed
   27|       |   // as its own input because a document rejected by the plain path may be accepted by this one.
   28|  3.43k|   {
   29|  3.43k|      std::vector<char> jsonc{Data, Data + Size};
   30|  3.43k|      [[maybe_unused]] auto maybe_smaller = glz::minify_jsonc(jsonc);
   31|  3.43k|   }
   32|       |
   33|       |   // Only a self-terminating buffer selects the null terminated scan, whose run ends on the
   34|       |   // sentinel rather than on a bound in its loop condition. A vector carrying a trailing NUL does
   35|       |   // not: that NUL is just a byte inside the document.
   36|  3.43k|   {
   37|  3.43k|      std::string jsonc{Data, Data + Size};
   38|  3.43k|      [[maybe_unused]] auto maybe_smaller = glz::minify_jsonc(jsonc);
   39|  3.43k|   }
   40|       |
   41|       |   // Minifying only ever removes bytes, so a bounded output large enough for the input is large
   42|       |   // enough for the result -- and one that is not has to say so rather than be written past.
   43|  3.43k|   {
   44|  3.43k|      std::vector<char> jsonc{Data, Data + Size};
   45|  3.43k|      std::array<char, 64> bounded{};
   46|  3.43k|      [[maybe_unused]] const auto ec = glz::minify_jsonc(jsonc, bounded);
   47|  3.43k|   }
   48|       |
   49|  3.43k|   return 0;
   50|  3.43k|}

_ZN3glz12ensure_spaceINSt3__15arrayIcLm64EEETkNS_10is_contextENS_7contextEEEbRT0_RT_m:
  265|  20.9k|   {
  266|  20.9k|      using Buffer = std::remove_cvref_t<B>;
  267|       |
  268|       |      if constexpr (vector_like<Buffer>) {
  269|       |         if (required > b.size()) [[unlikely]] {
  270|       |            grow_buffer(b, required);
  271|       |         }
  272|       |         return true;
  273|       |      }
  274|  20.9k|      else if constexpr (has_bounded_capacity<Buffer>) {
  275|  20.9k|         if (required > buffer_traits<Buffer>::capacity(b)) [[unlikely]] {
  ------------------
  |  Branch (275:14): [True: 295, False: 20.6k]
  ------------------
  276|    295|            ctx.error = error_code::buffer_overflow;
  277|    295|            return false;
  278|    295|         }
  279|  20.6k|         return true;
  280|       |      }
  281|       |      else {
  282|       |         return true; // Raw pointer or other - trust caller
  283|       |      }
  284|  20.9k|   }
_ZN3glz13buffer_traitsINSt3__15arrayIcLm64EEEE8capacityERKS3_:
  250|  20.9k|      GLZ_ALWAYS_INLINE static constexpr size_t capacity(const std::array<T, N>&) noexcept { return N; }

_ZN3glz14read_iteratorsITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1EEETkNS_10contiguousERNSt3__16vectorIcNS2_9allocatorIcEEEEEEDaOT0_:
   40|  6.86k|   {
   41|  6.86k|      static_assert(sizeof(decltype(*buffer.data())) == 1);
   42|       |
   43|  6.86k|      auto it = reinterpret_cast<const char*>(buffer.data());
   44|  6.86k|      auto end = it + buffer.size();
   45|       |
   46|  6.86k|      return std::pair{it, end};
   47|  6.86k|   }
_ZN3glz14read_iteratorsITnDaXtlNS_4optsELj10ELb1ELb1ELb1ELb1EEETkNS_10contiguousERNSt3__16vectorIcNS2_9allocatorIcEEEEEEDaOT0_:
   40|  6.86k|   {
   41|  6.86k|      static_assert(sizeof(decltype(*buffer.data())) == 1);
   42|       |
   43|  6.86k|      auto it = reinterpret_cast<const char*>(buffer.data());
   44|  6.86k|      auto end = it + buffer.size();
   45|       |
   46|  6.86k|      return std::pair{it, end};
   47|  6.86k|   }
_ZN3glz14read_iteratorsITnDaXtlNS_4optsELj10ELb1ELb1ELb1ELb1EEETkNS_10contiguousERNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEEEDaOT0_:
   40|  3.43k|   {
   41|  3.43k|      static_assert(sizeof(decltype(*buffer.data())) == 1);
   42|       |
   43|  3.43k|      auto it = reinterpret_cast<const char*>(buffer.data());
   44|  3.43k|      auto end = it + buffer.size();
   45|       |
   46|  3.43k|      return std::pair{it, end};
   47|  3.43k|   }

_ZN3glz6detail16read_json_stringITkNS_10is_contextERNS_7contextERPKcS5_EENSt3__117basic_string_viewIcNS7_11char_traitsIcEEEEOT_OT0_T1_:
  156|  6.94k|   {
  157|  6.94k|      auto start = it;
  158|  6.94k|      ++it; // skip quote
  159|       |      // The bound as a pointer, so each chunk costs one compare. Where eight bytes are not left,
  160|       |      // the fallback is the opening quote, which sits before `it` and fails the test on the first
  161|       |      // look; never `it` itself, which would pass and read a chunk past `end`.
  162|  6.94k|      const auto* const chunk_limit = (end - it >= 8) ? end - 8 : it - 1;
  ------------------
  |  Branch (162:39): [True: 6.00k, False: 938]
  ------------------
  163|  5.08M|      while (it <= chunk_limit) {
  ------------------
  |  Branch (163:14): [True: 5.08M, False: 1.32k]
  ------------------
  164|  5.08M|         uint64_t chunk;
  165|  5.08M|         std::memcpy(&chunk, it, 8);
  166|       |         if constexpr (std::endian::native == std::endian::big) {
  167|       |            chunk = std::byteswap(chunk);
  168|       |         }
  169|  5.08M|         const uint64_t quote = has_quote(chunk);
  170|  5.08M|         if (quote) {
  ------------------
  |  Branch (170:14): [True: 6.35k, False: 5.07M]
  ------------------
  171|  6.35k|            it += (countr_zero(quote) >> 3);
  172|       |
  173|  6.35k|            auto* prev = it - 1;
  174|  7.80k|            while (*prev == '\\') {
  ------------------
  |  Branch (174:20): [True: 1.45k, False: 6.35k]
  ------------------
  175|  1.45k|               --prev;
  176|  1.45k|            }
  177|  6.35k|            if (size_t(it - prev) % 2) {
  ------------------
  |  Branch (177:17): [True: 5.62k, False: 725]
  ------------------
  178|  5.62k|               ++it; // add quote
  179|  5.62k|               return {start, size_t(it - start)};
  180|  5.62k|            }
  181|    725|            ++it; // skip escaped quote and continue
  182|    725|         }
  183|  5.07M|         else {
  184|  5.07M|            it += 8;
  185|  5.07M|         }
  186|  5.08M|      }
  187|       |
  188|  3.29k|      while (it < end) {
  ------------------
  |  Branch (188:14): [True: 2.77k, False: 515]
  ------------------
  189|  2.77k|         if (*it == '"') {
  ------------------
  |  Branch (189:14): [True: 919, False: 1.85k]
  ------------------
  190|    919|            auto* prev = it - 1;
  191|  2.64k|            while (*prev == '\\') {
  ------------------
  |  Branch (191:20): [True: 1.72k, False: 919]
  ------------------
  192|  1.72k|               --prev;
  193|  1.72k|            }
  194|    919|            if (size_t(it - prev) % 2) {
  ------------------
  |  Branch (194:17): [True: 806, False: 113]
  ------------------
  195|    806|               ++it; // add quote
  196|    806|               return {start, size_t(it - start)};
  197|    806|            }
  198|    919|         }
  199|  1.97k|         ++it;
  200|  1.97k|      }
  201|       |
  202|    515|      ctx.error = error_code::unexpected_end;
  203|    515|      return {};
  204|  1.32k|   }
_ZN3glz6detail10emit_bytesILb0ENSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEETkNS_10is_contextENS_7contextENS2_17basic_string_viewIcS5_EEEEbRT1_RT0_RmRKT2_:
   91|  13.9k|   {
   92|  13.9k|      using T = std::remove_cvref_t<decltype(x)>;
   93|       |      if constexpr (byte_sized<T>) {
   94|       |         if constexpr (has_bounded_capacity<B>) {
   95|       |            if (not ensure_space(ctx, b, ix + 1)) [[unlikely]] {
   96|       |               return false;
   97|       |            }
   98|       |         }
   99|       |         dump<Checked>(x, b, ix);
  100|       |      }
  101|  13.9k|      else {
  102|  13.9k|         const sv s = [&] {
  103|  13.9k|            if constexpr (std::is_bounded_array_v<T>) {
  104|  13.9k|               return sv{x, std::extent_v<T> - 1}; // a string literal, without its terminator
  105|  13.9k|            }
  106|  13.9k|            else {
  107|  13.9k|               return sv{x};
  108|  13.9k|            }
  109|  13.9k|         }();
  110|       |         if constexpr (has_bounded_capacity<B>) {
  111|       |            if (not ensure_space(ctx, b, ix + s.size())) [[unlikely]] {
  112|       |               return false;
  113|       |            }
  114|       |         }
  115|  13.9k|         dump<Checked>(s, b, ix);
  116|  13.9k|      }
  117|  13.9k|      return true;
  118|  13.9k|   }
_ZZN3glz6detail10emit_bytesILb0ENSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEETkNS_10is_contextENS_7contextENS2_17basic_string_viewIcS5_EEEEbRT1_RT0_RmRKT2_ENKUlvE_clEv:
  102|  13.9k|         const sv s = [&] {
  103|       |            if constexpr (std::is_bounded_array_v<T>) {
  104|       |               return sv{x, std::extent_v<T> - 1}; // a string literal, without its terminator
  105|       |            }
  106|  13.9k|            else {
  107|  13.9k|               return sv{x};
  108|  13.9k|            }
  109|  13.9k|         }();
_ZN3glz6detail10emit_bytesILb0ENSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEETkNS_10is_contextENS_7contextEcEEbRT1_RT0_RmRKT2_:
   91|  97.1k|   {
   92|  97.1k|      using T = std::remove_cvref_t<decltype(x)>;
   93|  97.1k|      if constexpr (byte_sized<T>) {
   94|       |         if constexpr (has_bounded_capacity<B>) {
   95|       |            if (not ensure_space(ctx, b, ix + 1)) [[unlikely]] {
   96|       |               return false;
   97|       |            }
   98|       |         }
   99|  97.1k|         dump<Checked>(x, b, ix);
  100|       |      }
  101|       |      else {
  102|       |         const sv s = [&] {
  103|       |            if constexpr (std::is_bounded_array_v<T>) {
  104|       |               return sv{x, std::extent_v<T> - 1}; // a string literal, without its terminator
  105|       |            }
  106|       |            else {
  107|       |               return sv{x};
  108|       |            }
  109|       |         }();
  110|       |         if constexpr (has_bounded_capacity<B>) {
  111|       |            if (not ensure_space(ctx, b, ix + s.size())) [[unlikely]] {
  112|       |               return false;
  113|       |            }
  114|       |         }
  115|       |         dump<Checked>(s, b, ix);
  116|       |      }
  117|  97.1k|      return true;
  118|  97.1k|   }
_ZN3glz6detail16read_json_numberILb0ERPKcS3_EENSt3__117basic_string_viewIcNS5_11char_traitsIcEEEEOT0_T1_:
  304|  5.12k|   {
  305|  5.12k|      auto start = it;
  306|       |      if constexpr (null_terminated) {
  307|       |         while (numeric_table[uint8_t(*it)]) {
  308|       |            ++it;
  309|       |         }
  310|       |      }
  311|  5.12k|      else {
  312|  13.3M|         while ((it < end) && numeric_table[uint8_t(*it)]) {
  ------------------
  |  Branch (312:17): [True: 13.3M, False: 177]
  |  Branch (312:31): [True: 13.3M, False: 4.95k]
  ------------------
  313|  13.3M|            ++it;
  314|  13.3M|         }
  315|  5.12k|      }
  316|  5.12k|      return {start, size_t(it - start)};
  317|  5.12k|   }
_ZN3glz6detail13match_literalITnNS_14string_literalEXtlNS2_ILm5EEEtlA5_cLc110ELc117ELc108ELc108EEEETkNS_10is_contextERNS_7contextERPKcS8_EEbOT0_OT1_T2_:
  130|  3.51k|   {
  131|  3.51k|      static constexpr auto s = literal.sv();
  132|  3.51k|      if (end - it < std::ptrdiff_t(s.size())) [[unlikely]] {
  ------------------
  |  Branch (132:11): [True: 125, False: 3.38k]
  ------------------
  133|    125|         ctx.error = error_code::unexpected_end;
  134|    125|         return false;
  135|    125|      }
  136|  3.38k|      if (not comparitor<s>(it)) [[unlikely]] {
  ------------------
  |  Branch (136:11): [True: 455, False: 2.93k]
  ------------------
  137|    455|         ctx.error = error_code::syntax_error;
  138|    455|         return false;
  139|    455|      }
  140|  2.93k|      it += s.size();
  141|  2.93k|      return true;
  142|  3.38k|   }
_ZN3glz6detail10emit_bytesILb0ENSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEETkNS_10is_contextENS_7contextEA5_cEEbRT1_RT0_RmRKT2_:
   91|  6.28k|   {
   92|  6.28k|      using T = std::remove_cvref_t<decltype(x)>;
   93|       |      if constexpr (byte_sized<T>) {
   94|       |         if constexpr (has_bounded_capacity<B>) {
   95|       |            if (not ensure_space(ctx, b, ix + 1)) [[unlikely]] {
   96|       |               return false;
   97|       |            }
   98|       |         }
   99|       |         dump<Checked>(x, b, ix);
  100|       |      }
  101|  6.28k|      else {
  102|  6.28k|         const sv s = [&] {
  103|  6.28k|            if constexpr (std::is_bounded_array_v<T>) {
  104|  6.28k|               return sv{x, std::extent_v<T> - 1}; // a string literal, without its terminator
  105|  6.28k|            }
  106|  6.28k|            else {
  107|  6.28k|               return sv{x};
  108|  6.28k|            }
  109|  6.28k|         }();
  110|       |         if constexpr (has_bounded_capacity<B>) {
  111|       |            if (not ensure_space(ctx, b, ix + s.size())) [[unlikely]] {
  112|       |               return false;
  113|       |            }
  114|       |         }
  115|  6.28k|         dump<Checked>(s, b, ix);
  116|  6.28k|      }
  117|  6.28k|      return true;
  118|  6.28k|   }
_ZZN3glz6detail10emit_bytesILb0ENSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEETkNS_10is_contextENS_7contextEA5_cEEbRT1_RT0_RmRKT2_ENKUlvE_clEv:
  102|  6.28k|         const sv s = [&] {
  103|  6.28k|            if constexpr (std::is_bounded_array_v<T>) {
  104|  6.28k|               return sv{x, std::extent_v<T> - 1}; // a string literal, without its terminator
  105|       |            }
  106|       |            else {
  107|       |               return sv{x};
  108|       |            }
  109|  6.28k|         }();
_ZN3glz6detail13match_literalITnNS_14string_literalEXtlNS2_ILm5EEEtlA5_cLc116ELc114ELc117ELc101EEEETkNS_10is_contextERNS_7contextERPKcS8_EEbOT0_OT1_T2_:
  130|  4.53k|   {
  131|  4.53k|      static constexpr auto s = literal.sv();
  132|  4.53k|      if (end - it < std::ptrdiff_t(s.size())) [[unlikely]] {
  ------------------
  |  Branch (132:11): [True: 107, False: 4.43k]
  ------------------
  133|    107|         ctx.error = error_code::unexpected_end;
  134|    107|         return false;
  135|    107|      }
  136|  4.43k|      if (not comparitor<s>(it)) [[unlikely]] {
  ------------------
  |  Branch (136:11): [True: 406, False: 4.02k]
  ------------------
  137|    406|         ctx.error = error_code::syntax_error;
  138|    406|         return false;
  139|    406|      }
  140|  4.02k|      it += s.size();
  141|  4.02k|      return true;
  142|  4.43k|   }
_ZN3glz6detail13match_literalITnNS_14string_literalEXtlNS2_ILm6EEEtlA6_cLc102ELc97ELc108ELc115ELc101EEEETkNS_10is_contextERNS_7contextERPKcS8_EEbOT0_OT1_T2_:
  130|  3.39k|   {
  131|  3.39k|      static constexpr auto s = literal.sv();
  132|  3.39k|      if (end - it < std::ptrdiff_t(s.size())) [[unlikely]] {
  ------------------
  |  Branch (132:11): [True: 165, False: 3.23k]
  ------------------
  133|    165|         ctx.error = error_code::unexpected_end;
  134|    165|         return false;
  135|    165|      }
  136|  3.23k|      if (not comparitor<s>(it)) [[unlikely]] {
  ------------------
  |  Branch (136:11): [True: 446, False: 2.78k]
  ------------------
  137|    446|         ctx.error = error_code::syntax_error;
  138|    446|         return false;
  139|    446|      }
  140|  2.78k|      it += s.size();
  141|  2.78k|      return true;
  142|  3.23k|   }
_ZN3glz6detail10emit_bytesILb0ENSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEETkNS_10is_contextENS_7contextEA6_cEEbRT1_RT0_RmRKT2_:
   91|  2.56k|   {
   92|  2.56k|      using T = std::remove_cvref_t<decltype(x)>;
   93|       |      if constexpr (byte_sized<T>) {
   94|       |         if constexpr (has_bounded_capacity<B>) {
   95|       |            if (not ensure_space(ctx, b, ix + 1)) [[unlikely]] {
   96|       |               return false;
   97|       |            }
   98|       |         }
   99|       |         dump<Checked>(x, b, ix);
  100|       |      }
  101|  2.56k|      else {
  102|  2.56k|         const sv s = [&] {
  103|  2.56k|            if constexpr (std::is_bounded_array_v<T>) {
  104|  2.56k|               return sv{x, std::extent_v<T> - 1}; // a string literal, without its terminator
  105|  2.56k|            }
  106|  2.56k|            else {
  107|  2.56k|               return sv{x};
  108|  2.56k|            }
  109|  2.56k|         }();
  110|       |         if constexpr (has_bounded_capacity<B>) {
  111|       |            if (not ensure_space(ctx, b, ix + s.size())) [[unlikely]] {
  112|       |               return false;
  113|       |            }
  114|       |         }
  115|  2.56k|         dump<Checked>(s, b, ix);
  116|  2.56k|      }
  117|  2.56k|      return true;
  118|  2.56k|   }
_ZZN3glz6detail10emit_bytesILb0ENSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEETkNS_10is_contextENS_7contextEA6_cEEbRT1_RT0_RmRKT2_ENKUlvE_clEv:
  102|  2.56k|         const sv s = [&] {
  103|  2.56k|            if constexpr (std::is_bounded_array_v<T>) {
  104|  2.56k|               return sv{x, std::extent_v<T> - 1}; // a string literal, without its terminator
  105|       |            }
  106|       |            else {
  107|       |               return sv{x};
  108|       |            }
  109|  2.56k|         }();
_ZN3glz6detail18read_jsonc_commentITkNS_10is_contextERNS_7contextERPKcS5_EENS0_13jsonc_commentEOT_OT0_T1_:
  227|  6.99k|   {
  228|  6.99k|      const auto start = it;
  229|  6.99k|      ++it; // past the opening '/'
  230|       |
  231|       |      // The caller matched one '/'; that says nothing about a second byte being there at all.
  232|       |      // Stepping over both regardless leaves `it` past `end`, and every scan the caller runs after
  233|       |      // this one starts from there.
  234|  6.99k|      if (it == end) [[unlikely]] {
  ------------------
  |  Branch (234:11): [True: 34, False: 6.96k]
  ------------------
  235|     34|         ctx.error = error_code::unexpected_end;
  236|     34|         return {};
  237|     34|      }
  238|       |
  239|  6.96k|      if (*it == '/') {
  ------------------
  |  Branch (239:11): [True: 3.50k, False: 3.46k]
  ------------------
  240|  3.50k|         ++it; // past the second '/'
  241|  6.06k|         while (it != end && *it != '\n' && *it != '\r') {
  ------------------
  |  Branch (241:17): [True: 5.96k, False: 107]
  |  Branch (241:30): [True: 3.58k, False: 2.37k]
  |  Branch (241:45): [True: 2.56k, False: 1.02k]
  ------------------
  242|  2.56k|            ++it;
  243|  2.56k|         }
  244|       |         // The terminator is left where it is: minify drops it along with the rest of the
  245|       |         // whitespace and prettify emits its own break. A carriage return ends the comment on its
  246|       |         // own, so a file with CR line endings is not swallowed by its first comment; a line feed
  247|       |         // behind it is then ordinary whitespace.
  248|  3.50k|         return {sv{start, size_t(it - start)}, true};
  249|  3.50k|      }
  250|       |
  251|  3.46k|      if (*it != '*') [[unlikely]] {
  ------------------
  |  Branch (251:11): [True: 83, False: 3.37k]
  ------------------
  252|     83|         ctx.error = error_code::expected_end_comment;
  253|     83|         return {};
  254|     83|      }
  255|  3.37k|      ++it; // past the '*' of the opener
  256|       |
  257|       |      // Only a '*' after the opening delimiter can close the comment, which is what the `content`
  258|       |      // guards below are for: without them the '*' of the opener closes the comment it opened, so
  259|       |      // "/*/" reads as complete and swallows whatever follows it.
  260|  3.37k|      const auto content = it;
  261|       |
  262|       |      // The bound as a pointer, so each chunk costs one compare. `end - 8` only points into the
  263|       |      // buffer once that much of it is left; where it is not, the fallback is the byte before the
  264|       |      // cursor, which is inside the opener and so fails the test on the first look. Never `it`
  265|       |      // itself -- that passes, and the chunk behind it would read past the end of the buffer.
  266|  3.37k|      const auto* const chunk_limit = (end - it >= 8) ? end - 8 : it - 1;
  ------------------
  |  Branch (266:39): [True: 3.12k, False: 255]
  ------------------
  267|  3.36M|      while (it <= chunk_limit) {
  ------------------
  |  Branch (267:14): [True: 3.36M, False: 510]
  ------------------
  268|  3.36M|         uint64_t chunk;
  269|  3.36M|         std::memcpy(&chunk, it, 8);
  270|       |         if constexpr (std::endian::native == std::endian::big) {
  271|       |            chunk = std::byteswap(chunk);
  272|       |         }
  273|  3.36M|         const uint64_t slash = has_char<'/'>(chunk);
  274|  3.36M|         if (slash) {
  ------------------
  |  Branch (274:14): [True: 24.5k, False: 3.33M]
  ------------------
  275|  24.5k|            it += (countr_zero(slash) >> 3);
  276|       |
  277|  24.5k|            if (it > content && it[-1] == '*') {
  ------------------
  |  Branch (277:17): [True: 23.6k, False: 913]
  |  Branch (277:33): [True: 2.86k, False: 20.7k]
  ------------------
  278|  2.86k|               ++it; // add slash
  279|  2.86k|               return {sv{start, size_t(it - start)}, false};
  280|  2.86k|            }
  281|       |            // skip slash and continue
  282|  21.6k|            ++it;
  283|  21.6k|         }
  284|  3.33M|         else {
  285|  3.33M|            it += 8;
  286|  3.33M|         }
  287|  3.36M|      }
  288|       |
  289|       |      // Tail end of buffer. Should be rare we even get here
  290|  1.82k|      while (it < end) {
  ------------------
  |  Branch (290:14): [True: 1.53k, False: 292]
  ------------------
  291|  1.53k|         if (it > content && it[-1] == '*' && *it == '/') {
  ------------------
  |  Branch (291:14): [True: 1.28k, False: 246]
  |  Branch (291:30): [True: 366, False: 920]
  |  Branch (291:47): [True: 218, False: 148]
  ------------------
  292|    218|            ++it; // add slash
  293|    218|            return {sv{start, size_t(it - start)}, false};
  294|    218|         }
  295|  1.31k|         ++it;
  296|  1.31k|      }
  297|       |
  298|    292|      ctx.error = error_code::expected_end_comment;
  299|    292|      return {};
  300|    510|   }
_ZN3glz6detail16read_json_numberILb1ERPKcS3_EENSt3__117basic_string_viewIcNS5_11char_traitsIcEEEEOT0_T1_:
  304|  1.44k|   {
  305|  1.44k|      auto start = it;
  306|  1.44k|      if constexpr (null_terminated) {
  307|  3.33M|         while (numeric_table[uint8_t(*it)]) {
  ------------------
  |  Branch (307:17): [True: 3.33M, False: 1.44k]
  ------------------
  308|  3.33M|            ++it;
  309|  3.33M|         }
  310|       |      }
  311|       |      else {
  312|       |         while ((it < end) && numeric_table[uint8_t(*it)]) {
  313|       |            ++it;
  314|       |         }
  315|       |      }
  316|  1.44k|      return {start, size_t(it - start)};
  317|  1.44k|   }
_ZN3glz6detail10emit_bytesILb0ENSt3__15arrayIcLm64EEETkNS_10is_contextENS_7contextENS2_17basic_string_viewIcNS2_11char_traitsIcEEEEEEbRT1_RT0_RmRKT2_:
   91|  2.16k|   {
   92|  2.16k|      using T = std::remove_cvref_t<decltype(x)>;
   93|       |      if constexpr (byte_sized<T>) {
   94|       |         if constexpr (has_bounded_capacity<B>) {
   95|       |            if (not ensure_space(ctx, b, ix + 1)) [[unlikely]] {
   96|       |               return false;
   97|       |            }
   98|       |         }
   99|       |         dump<Checked>(x, b, ix);
  100|       |      }
  101|  2.16k|      else {
  102|  2.16k|         const sv s = [&] {
  103|  2.16k|            if constexpr (std::is_bounded_array_v<T>) {
  104|  2.16k|               return sv{x, std::extent_v<T> - 1}; // a string literal, without its terminator
  105|  2.16k|            }
  106|  2.16k|            else {
  107|  2.16k|               return sv{x};
  108|  2.16k|            }
  109|  2.16k|         }();
  110|  2.16k|         if constexpr (has_bounded_capacity<B>) {
  111|  2.16k|            if (not ensure_space(ctx, b, ix + s.size())) [[unlikely]] {
  ------------------
  |  Branch (111:17): [True: 144, False: 2.01k]
  ------------------
  112|    144|               return false;
  113|    144|            }
  114|  2.16k|         }
  115|  2.01k|         dump<Checked>(s, b, ix);
  116|  2.16k|      }
  117|      0|      return true;
  118|  2.16k|   }
_ZZN3glz6detail10emit_bytesILb0ENSt3__15arrayIcLm64EEETkNS_10is_contextENS_7contextENS2_17basic_string_viewIcNS2_11char_traitsIcEEEEEEbRT1_RT0_RmRKT2_ENKUlvE_clEv:
  102|  2.16k|         const sv s = [&] {
  103|       |            if constexpr (std::is_bounded_array_v<T>) {
  104|       |               return sv{x, std::extent_v<T> - 1}; // a string literal, without its terminator
  105|       |            }
  106|  2.16k|            else {
  107|  2.16k|               return sv{x};
  108|  2.16k|            }
  109|  2.16k|         }();
_ZN3glz6detail10emit_bytesILb0ENSt3__15arrayIcLm64EEETkNS_10is_contextENS_7contextEcEEbRT1_RT0_RmRKT2_:
   91|  17.9k|   {
   92|  17.9k|      using T = std::remove_cvref_t<decltype(x)>;
   93|  17.9k|      if constexpr (byte_sized<T>) {
   94|  17.9k|         if constexpr (has_bounded_capacity<B>) {
   95|  17.9k|            if (not ensure_space(ctx, b, ix + 1)) [[unlikely]] {
  ------------------
  |  Branch (95:17): [True: 118, False: 17.7k]
  ------------------
   96|    118|               return false;
   97|    118|            }
   98|  17.9k|         }
   99|  17.7k|         dump<Checked>(x, b, ix);
  100|       |      }
  101|       |      else {
  102|       |         const sv s = [&] {
  103|       |            if constexpr (std::is_bounded_array_v<T>) {
  104|       |               return sv{x, std::extent_v<T> - 1}; // a string literal, without its terminator
  105|       |            }
  106|       |            else {
  107|       |               return sv{x};
  108|       |            }
  109|       |         }();
  110|       |         if constexpr (has_bounded_capacity<B>) {
  111|       |            if (not ensure_space(ctx, b, ix + s.size())) [[unlikely]] {
  112|       |               return false;
  113|       |            }
  114|       |         }
  115|       |         dump<Checked>(s, b, ix);
  116|       |      }
  117|      0|      return true;
  118|  17.9k|   }
_ZN3glz6detail10emit_bytesILb0ENSt3__15arrayIcLm64EEETkNS_10is_contextENS_7contextEA5_cEEbRT1_RT0_RmRKT2_:
   91|    672|   {
   92|    672|      using T = std::remove_cvref_t<decltype(x)>;
   93|       |      if constexpr (byte_sized<T>) {
   94|       |         if constexpr (has_bounded_capacity<B>) {
   95|       |            if (not ensure_space(ctx, b, ix + 1)) [[unlikely]] {
   96|       |               return false;
   97|       |            }
   98|       |         }
   99|       |         dump<Checked>(x, b, ix);
  100|       |      }
  101|    672|      else {
  102|    672|         const sv s = [&] {
  103|    672|            if constexpr (std::is_bounded_array_v<T>) {
  104|    672|               return sv{x, std::extent_v<T> - 1}; // a string literal, without its terminator
  105|    672|            }
  106|    672|            else {
  107|    672|               return sv{x};
  108|    672|            }
  109|    672|         }();
  110|    672|         if constexpr (has_bounded_capacity<B>) {
  111|    672|            if (not ensure_space(ctx, b, ix + s.size())) [[unlikely]] {
  ------------------
  |  Branch (111:17): [True: 22, False: 650]
  ------------------
  112|     22|               return false;
  113|     22|            }
  114|    672|         }
  115|    650|         dump<Checked>(s, b, ix);
  116|    672|      }
  117|      0|      return true;
  118|    672|   }
_ZZN3glz6detail10emit_bytesILb0ENSt3__15arrayIcLm64EEETkNS_10is_contextENS_7contextEA5_cEEbRT1_RT0_RmRKT2_ENKUlvE_clEv:
  102|    672|         const sv s = [&] {
  103|    672|            if constexpr (std::is_bounded_array_v<T>) {
  104|    672|               return sv{x, std::extent_v<T> - 1}; // a string literal, without its terminator
  105|       |            }
  106|       |            else {
  107|       |               return sv{x};
  108|       |            }
  109|    672|         }();
_ZN3glz6detail10emit_bytesILb0ENSt3__15arrayIcLm64EEETkNS_10is_contextENS_7contextEA6_cEEbRT1_RT0_RmRKT2_:
   91|    220|   {
   92|    220|      using T = std::remove_cvref_t<decltype(x)>;
   93|       |      if constexpr (byte_sized<T>) {
   94|       |         if constexpr (has_bounded_capacity<B>) {
   95|       |            if (not ensure_space(ctx, b, ix + 1)) [[unlikely]] {
   96|       |               return false;
   97|       |            }
   98|       |         }
   99|       |         dump<Checked>(x, b, ix);
  100|       |      }
  101|    220|      else {
  102|    220|         const sv s = [&] {
  103|    220|            if constexpr (std::is_bounded_array_v<T>) {
  104|    220|               return sv{x, std::extent_v<T> - 1}; // a string literal, without its terminator
  105|    220|            }
  106|    220|            else {
  107|    220|               return sv{x};
  108|    220|            }
  109|    220|         }();
  110|    220|         if constexpr (has_bounded_capacity<B>) {
  111|    220|            if (not ensure_space(ctx, b, ix + s.size())) [[unlikely]] {
  ------------------
  |  Branch (111:17): [True: 11, False: 209]
  ------------------
  112|     11|               return false;
  113|     11|            }
  114|    220|         }
  115|    209|         dump<Checked>(s, b, ix);
  116|    220|      }
  117|      0|      return true;
  118|    220|   }
_ZZN3glz6detail10emit_bytesILb0ENSt3__15arrayIcLm64EEETkNS_10is_contextENS_7contextEA6_cEEbRT1_RT0_RmRKT2_ENKUlvE_clEv:
  102|    220|         const sv s = [&] {
  103|    220|            if constexpr (std::is_bounded_array_v<T>) {
  104|    220|               return sv{x, std::extent_v<T> - 1}; // a string literal, without its terminator
  105|       |            }
  106|       |            else {
  107|       |               return sv{x};
  108|       |            }
  109|    220|         }();

_ZN3glz11minify_jsonITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1EEETkNS_9resizableENSt3__16vectorIcNS2_9allocatorIcEEEEEENS2_12basic_stringIcNS2_11char_traitsIcEES5_EERT0_:
  288|  6.86k|   {
  289|  6.86k|      context ctx{};
  290|  6.86k|      std::string out{};
  291|  6.86k|      detail::minify_json<Opts>(ctx, in, out);
  292|  6.86k|      if (bool(ctx.error)) [[unlikely]] {
  ------------------
  |  Branch (292:11): [True: 5.81k, False: 1.04k]
  ------------------
  293|  5.81k|         return {}; // an incomplete result is not a document; see above
  294|  5.81k|      }
  295|  1.04k|      return out;
  296|  6.86k|   }
_ZN3glz6detail11minify_jsonITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1EEERNSt3__16vectorIcNS3_9allocatorIcEEEETkNS_13output_bufferERNS3_12basic_stringIcNS3_11char_traitsIcEES6_EETkNS_10is_contextERNS_7contextEQaa10contiguousIT0_E9resizableISG_EEEmOT2_OSG_OT1_:
  230|  6.86k|      {
  231|  6.86k|         if (in.size() == 0) {
  ------------------
  |  Branch (231:14): [True: 0, False: 6.86k]
  ------------------
  232|      0|            return 0;
  233|      0|         }
  234|       |
  235|  6.86k|         if constexpr (resizable<Out>) {
  236|       |            // Minifying only ever removes bytes, so this is room enough for whatever comes out.
  237|       |            // A bounded output is checked per write instead; see the scan above for why.
  238|  6.86k|            out.resize(in.size() + 2 * padding_bytes);
  239|  6.86k|         }
  240|  6.86k|         size_t ix = 0;
  241|  6.86k|         auto [it, end] = read_iterators<Opts>(in);
  242|  6.86k|         if (bool(ctx.error)) [[unlikely]] {
  ------------------
  |  Branch (242:14): [True: 0, False: 6.86k]
  ------------------
  243|      0|            return 0;
  244|      0|         }
  245|       |
  246|       |         // The input is no longer grown and shrunk around this: everything the scan below reads
  247|       |         // through -- read_json_string, read_json_number, skip_matching_ws -- bounds its own loads
  248|       |         // against `end`, so there is nothing left for the padding to protect.
  249|       |         if constexpr (self_terminating<In>) {
  250|       |            minify_json<opt_true<Opts, &opts::null_terminated>>(ctx, it, end, out, ix);
  251|       |         }
  252|  6.86k|         else {
  253|  6.86k|            minify_json<opt_false<Opts, &opts::null_terminated>>(ctx, it, end, out, ix);
  254|  6.86k|         }
  255|       |
  256|  6.86k|         if constexpr (resizable<Out>) {
  257|  6.86k|            out.resize(ix);
  258|  6.86k|         }
  259|  6.86k|         return ix;
  260|  6.86k|      }
_ZN3glz6detail11minify_jsonITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEETkNS_10is_contextERNS_7contextERPKcS7_RNSt3__112basic_stringIcNS8_11char_traitsIcEENS8_9allocatorIcEEEEmEEvOT0_OT1_OT2_OT3_RT4_:
   18|  6.86k|      {
   19|  6.86k|         using enum json_type;
   20|       |
   21|       |         // Every write below goes through this, and the dump it makes is unchecked: the caller's
   22|       |         // one-shot sizing covers a resizable destination, because minifying only ever removes
   23|       |         // bytes, so the input's length is room enough.
   24|       |         //
   25|       |         // A bounded destination cannot be grown, and asking it for the input's length up front
   26|       |         // refuses a buffer that fits the result -- sizing the output to the minified length is the
   27|       |         // obvious thing to do, and `{ "a" : 1 }` into a 7 byte buffer has to work. So each write
   28|       |         // asks for exactly what it stores instead; see emit_bytes for where that count comes from.
   29|       |         // None of it survives for a resizable destination, which keeps the unchecked dumps and
   30|       |         // nothing more.
   31|  6.86k|         const auto put = [&](const auto& x) { return emit_bytes<false>(ctx, b, ix, x); };
   32|       |
   33|  6.86k|         auto ws_start = it;
   34|  6.86k|         uint64_t ws_size{};
   35|       |
   36|  6.86k|         auto skip_expected_whitespace = [&] {
   37|  6.86k|            auto new_ws_start = it;
   38|  6.86k|            if (ws_size && std::ptrdiff_t(ws_size) < end - it) [[likely]] {
   39|  6.86k|               skip_matching_ws(ws_start, it, ws_size);
   40|  6.86k|            }
   41|       |
   42|  6.86k|            if constexpr (Opts.null_terminated) {
   43|  6.86k|               while (whitespace_table[uint8_t(*it)]) {
   44|  6.86k|                  ++it;
   45|  6.86k|               }
   46|  6.86k|            }
   47|  6.86k|            else {
   48|  6.86k|               while ((it < end) && whitespace_table[uint8_t(*it)]) {
   49|  6.86k|                  ++it;
   50|  6.86k|               }
   51|  6.86k|            }
   52|  6.86k|            ws_start = new_ws_start;
   53|  6.86k|            ws_size = size_t(it - new_ws_start);
   54|  6.86k|         };
   55|       |
   56|  6.86k|         auto skip_whitespace = [&] {
   57|  6.86k|            if constexpr (Opts.null_terminated) {
   58|  6.86k|               while (whitespace_table[uint8_t(*it)]) {
   59|  6.86k|                  ++it;
   60|  6.86k|               }
   61|  6.86k|            }
   62|  6.86k|            else {
   63|  6.86k|               while ((it < end) && whitespace_table[uint8_t(*it)]) {
   64|  6.86k|                  ++it;
   65|  6.86k|               }
   66|  6.86k|            }
   67|  6.86k|         };
   68|       |
   69|  6.86k|         skip_whitespace();
   70|       |
   71|  64.9k|         while ([&]() -> bool {
  ------------------
  |  Branch (71:17): [True: 63.8k, False: 1.04k]
  ------------------
   72|  64.9k|            if constexpr (Opts.null_terminated) {
   73|  64.9k|               return true;
   74|  64.9k|            }
   75|  64.9k|            else {
   76|  64.9k|               return it < end;
   77|  64.9k|            }
   78|  64.9k|         }()) {
   79|  63.8k|            switch (json_types[uint8_t(*it)]) {
   80|  2.95k|            case String: {
  ------------------
  |  Branch (80:13): [True: 2.95k, False: 60.9k]
  ------------------
   81|  2.95k|               const auto value = read_json_string(ctx, it, end);
   82|  2.95k|               if (bool(ctx.error)) [[unlikely]] {
  ------------------
  |  Branch (82:20): [True: 198, False: 2.75k]
  ------------------
   83|    198|                  return;
   84|    198|               }
   85|       |               // non-empty: the scanner reports an empty view as an error
   86|  2.75k|               if (not put(value)) [[unlikely]] {
  ------------------
  |  Branch (86:20): [True: 0, False: 2.75k]
  ------------------
   87|      0|                  return;
   88|      0|               }
   89|  2.75k|               skip_whitespace();
   90|  2.75k|               break;
   91|  2.75k|            }
   92|  14.4k|            case Comma: {
  ------------------
  |  Branch (92:13): [True: 14.4k, False: 49.3k]
  ------------------
   93|  14.4k|               if (not put(',')) [[unlikely]] {
  ------------------
  |  Branch (93:20): [True: 0, False: 14.4k]
  ------------------
   94|      0|                  return;
   95|      0|               }
   96|  14.4k|               ++it;
   97|  14.4k|               skip_expected_whitespace();
   98|  14.4k|               break;
   99|  14.4k|            }
  100|  2.80k|            case Number: {
  ------------------
  |  Branch (100:13): [True: 2.80k, False: 61.0k]
  ------------------
  101|  2.80k|               const auto value = read_json_number<Opts.null_terminated>(it, end);
  102|       |               // non-empty: a Number match is one valid character
  103|  2.80k|               if (not put(value)) [[unlikely]] {
  ------------------
  |  Branch (103:20): [True: 0, False: 2.80k]
  ------------------
  104|      0|                  return;
  105|      0|               }
  106|  2.80k|               skip_whitespace();
  107|  2.80k|               break;
  108|  2.80k|            }
  109|  2.59k|            case Colon: {
  ------------------
  |  Branch (109:13): [True: 2.59k, False: 61.2k]
  ------------------
  110|  2.59k|               if (not put(':')) [[unlikely]] {
  ------------------
  |  Branch (110:20): [True: 0, False: 2.59k]
  ------------------
  111|      0|                  return;
  112|      0|               }
  113|  2.59k|               ++it;
  114|  2.59k|               skip_whitespace();
  115|  2.59k|               break;
  116|  2.59k|            }
  117|  12.1k|            case Array_Start: {
  ------------------
  |  Branch (117:13): [True: 12.1k, False: 51.6k]
  ------------------
  118|  12.1k|               if (not put('[')) [[unlikely]] {
  ------------------
  |  Branch (118:20): [True: 0, False: 12.1k]
  ------------------
  119|      0|                  return;
  120|      0|               }
  121|  12.1k|               ++it;
  122|  12.1k|               skip_expected_whitespace();
  123|  12.1k|               break;
  124|  12.1k|            }
  125|  2.50k|            case Array_End: {
  ------------------
  |  Branch (125:13): [True: 2.50k, False: 61.3k]
  ------------------
  126|  2.50k|               if (not put(']')) [[unlikely]] {
  ------------------
  |  Branch (126:20): [True: 0, False: 2.50k]
  ------------------
  127|      0|                  return;
  128|      0|               }
  129|  2.50k|               ++it;
  130|  2.50k|               skip_whitespace();
  131|  2.50k|               break;
  132|  2.50k|            }
  133|  1.55k|            case Null: {
  ------------------
  |  Branch (133:13): [True: 1.55k, False: 62.3k]
  ------------------
  134|       |               // The type table matched on the first byte alone; see match_literal for why writing
  135|       |               // the literal from the writer's own spelling needs the rest of it checked. Stepping
  136|       |               // over it unchecked also puts `it` past `end`, and from there the loop goes on
  137|       |               // minifying whatever follows the document into an output sized for the document.
  138|  1.55k|               if (not match_literal<"null">(ctx, it, end)) [[unlikely]] {
  ------------------
  |  Branch (138:20): [True: 234, False: 1.31k]
  ------------------
  139|    234|                  return;
  140|    234|               }
  141|  1.31k|               if (not put("null")) [[unlikely]] {
  ------------------
  |  Branch (141:20): [True: 0, False: 1.31k]
  ------------------
  142|      0|                  return;
  143|      0|               }
  144|  1.31k|               skip_whitespace();
  145|  1.31k|               break;
  146|  1.31k|            }
  147|  3.53k|            case Bool: {
  ------------------
  |  Branch (147:13): [True: 3.53k, False: 60.3k]
  ------------------
  148|  3.53k|               if (*it == 't') {
  ------------------
  |  Branch (148:20): [True: 2.01k, False: 1.52k]
  ------------------
  149|  2.01k|                  if (not match_literal<"true">(ctx, it, end)) [[unlikely]] {
  ------------------
  |  Branch (149:23): [True: 210, False: 1.80k]
  ------------------
  150|    210|                     return;
  151|    210|                  }
  152|  1.80k|                  if (not put("true")) [[unlikely]] {
  ------------------
  |  Branch (152:23): [True: 0, False: 1.80k]
  ------------------
  153|      0|                     return;
  154|      0|                  }
  155|  1.80k|                  skip_whitespace();
  156|  1.80k|                  break;
  157|  1.80k|               }
  158|  1.52k|               else {
  159|  1.52k|                  if (not match_literal<"false">(ctx, it, end)) [[unlikely]] {
  ------------------
  |  Branch (159:23): [True: 246, False: 1.28k]
  ------------------
  160|    246|                     return;
  161|    246|                  }
  162|  1.28k|                  if (not put("false")) [[unlikely]] {
  ------------------
  |  Branch (162:23): [True: 0, False: 1.28k]
  ------------------
  163|      0|                     return;
  164|      0|                  }
  165|  1.28k|                  skip_whitespace();
  166|  1.28k|                  break;
  167|  1.28k|               }
  168|  3.53k|            }
  169|  13.7k|            case Object_Start: {
  ------------------
  |  Branch (169:13): [True: 13.7k, False: 50.0k]
  ------------------
  170|  13.7k|               if (not put('{')) [[unlikely]] {
  ------------------
  |  Branch (170:20): [True: 0, False: 13.7k]
  ------------------
  171|      0|                  return;
  172|      0|               }
  173|  13.7k|               ++it;
  174|  13.7k|               skip_expected_whitespace();
  175|  13.7k|               break;
  176|  13.7k|            }
  177|  2.57k|            case Object_End: {
  ------------------
  |  Branch (177:13): [True: 2.57k, False: 61.2k]
  ------------------
  178|  2.57k|               if (not put('}')) [[unlikely]] {
  ------------------
  |  Branch (178:20): [True: 0, False: 2.57k]
  ------------------
  179|      0|                  return;
  180|      0|               }
  181|  2.57k|               ++it;
  182|  2.57k|               skip_whitespace();
  183|  2.57k|               break;
  184|  2.57k|            }
  185|    570|            case Comment: {
  ------------------
  |  Branch (185:13): [True: 570, False: 63.2k]
  ------------------
  186|       |               if constexpr (Opts.comments) {
  187|       |                  const auto comment = read_jsonc_comment(ctx, it, end);
  188|       |                  if (bool(ctx.error)) [[unlikely]] {
  189|       |                     return;
  190|       |                  }
  191|       |                  // A line comment is dropped rather than written out. Minifying is what removes
  192|       |                  // the newline that ends it, and a line comment with no line break behind it
  193|       |                  // comments out the whole rest of the output.
  194|       |                  if (not comment.line) {
  195|       |                     // non-empty: an empty view comes with an error
  196|       |                     if (not put(comment.text)) [[unlikely]] {
  197|       |                        return;
  198|       |                     }
  199|       |                  }
  200|       |                  skip_whitespace();
  201|       |                  break;
  202|       |               }
  203|    570|               else {
  204|    570|                  [[fallthrough]];
  205|    570|               }
  206|    570|            }
  207|  4.92k|            [[unlikely]] default: {
  ------------------
  |  Branch (207:26): [True: 4.35k, False: 59.5k]
  ------------------
  208|       |               // A null terminated run carries no bound in its loop condition, so it ends here, on
  209|       |               // the terminator, which is not a JSON token. Reaching it is the end of the document
  210|       |               // rather than an error -- unclassified is how the type table reports both, and
  211|       |               // without this the minifier left syntax_error behind on every input it was ever
  212|       |               // given, valid or not, which is what made its error not worth returning.
  213|       |               if constexpr (Opts.null_terminated) {
  214|       |                  if (it >= end) {
  215|       |                     return;
  216|       |                  }
  217|       |               }
  218|  4.92k|               ctx.error = error_code::syntax_error;
  219|  4.92k|               return;
  220|    570|            }
  221|  63.8k|            }
  222|  63.8k|         }
  223|  6.86k|      }
_ZZN3glz6detail11minify_jsonITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEETkNS_10is_contextERNS_7contextERPKcS7_RNSt3__112basic_stringIcNS8_11char_traitsIcEENS8_9allocatorIcEEEEmEEvOT0_OT1_OT2_OT3_RT4_ENKUlvE0_clEv:
   56|  24.4k|         auto skip_whitespace = [&] {
   57|       |            if constexpr (Opts.null_terminated) {
   58|       |               while (whitespace_table[uint8_t(*it)]) {
   59|       |                  ++it;
   60|       |               }
   61|       |            }
   62|  24.4k|            else {
   63|   231k|               while ((it < end) && whitespace_table[uint8_t(*it)]) {
  ------------------
  |  Branch (63:23): [True: 230k, False: 443]
  |  Branch (63:37): [True: 206k, False: 24.0k]
  ------------------
   64|   206k|                  ++it;
   65|   206k|               }
   66|  24.4k|            }
   67|  24.4k|         };
_ZZN3glz6detail11minify_jsonITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEETkNS_10is_contextERNS_7contextERPKcS7_RNSt3__112basic_stringIcNS8_11char_traitsIcEENS8_9allocatorIcEEEEmEEvOT0_OT1_OT2_OT3_RT4_ENKUlvE1_clEv:
   71|  64.9k|         while ([&]() -> bool {
   72|       |            if constexpr (Opts.null_terminated) {
   73|       |               return true;
   74|       |            }
   75|  64.9k|            else {
   76|  64.9k|               return it < end;
   77|  64.9k|            }
   78|  64.9k|         }()) {
_ZZN3glz6detail11minify_jsonITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEETkNS_10is_contextERNS_7contextERPKcS7_RNSt3__112basic_stringIcNS8_11char_traitsIcEENS8_9allocatorIcEEEEmEEvOT0_OT1_OT2_OT3_RT4_ENKUlRKT_E_clINS8_17basic_string_viewIcSB_EEEEDaSS_:
   31|  5.56k|         const auto put = [&](const auto& x) { return emit_bytes<false>(ctx, b, ix, x); };
_ZZN3glz6detail11minify_jsonITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEETkNS_10is_contextERNS_7contextERPKcS7_RNSt3__112basic_stringIcNS8_11char_traitsIcEENS8_9allocatorIcEEEEmEEvOT0_OT1_OT2_OT3_RT4_ENKUlRKT_E_clIcEEDaSS_:
   31|  48.0k|         const auto put = [&](const auto& x) { return emit_bytes<false>(ctx, b, ix, x); };
_ZZN3glz6detail11minify_jsonITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEETkNS_10is_contextERNS_7contextERPKcS7_RNSt3__112basic_stringIcNS8_11char_traitsIcEENS8_9allocatorIcEEEEmEEvOT0_OT1_OT2_OT3_RT4_ENKUlvE_clEv:
   36|  40.4k|         auto skip_expected_whitespace = [&] {
   37|  40.4k|            auto new_ws_start = it;
   38|  40.4k|            if (ws_size && std::ptrdiff_t(ws_size) < end - it) [[likely]] {
  ------------------
  |  Branch (38:17): [True: 29.1k, False: 11.2k]
  |  Branch (38:28): [True: 27.5k, False: 1.56k]
  ------------------
   39|  27.5k|               skip_matching_ws(ws_start, it, ws_size);
   40|  27.5k|            }
   41|       |
   42|       |            if constexpr (Opts.null_terminated) {
   43|       |               while (whitespace_table[uint8_t(*it)]) {
   44|       |                  ++it;
   45|       |               }
   46|       |            }
   47|  40.4k|            else {
   48|  38.7M|               while ((it < end) && whitespace_table[uint8_t(*it)]) {
  ------------------
  |  Branch (48:23): [True: 38.7M, False: 602]
  |  Branch (48:37): [True: 38.6M, False: 39.8k]
  ------------------
   49|  38.6M|                  ++it;
   50|  38.6M|               }
   51|  40.4k|            }
   52|  40.4k|            ws_start = new_ws_start;
   53|  40.4k|            ws_size = size_t(it - new_ws_start);
   54|  40.4k|         };
_ZZN3glz6detail11minify_jsonITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEETkNS_10is_contextERNS_7contextERPKcS7_RNSt3__112basic_stringIcNS8_11char_traitsIcEENS8_9allocatorIcEEEEmEEvOT0_OT1_OT2_OT3_RT4_ENKUlRKT_E_clIA5_cEEDaSS_:
   31|  3.11k|         const auto put = [&](const auto& x) { return emit_bytes<false>(ctx, b, ix, x); };
_ZZN3glz6detail11minify_jsonITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEETkNS_10is_contextERNS_7contextERPKcS7_RNSt3__112basic_stringIcNS8_11char_traitsIcEENS8_9allocatorIcEEEEmEEvOT0_OT1_OT2_OT3_RT4_ENKUlRKT_E_clIA6_cEEDaSS_:
   31|  1.28k|         const auto put = [&](const auto& x) { return emit_bytes<false>(ctx, b, ix, x); };
_ZN3glz12minify_jsoncITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1EEETkNS_9resizableENSt3__16vectorIcNS2_9allocatorIcEEEEEENS2_12basic_stringIcNS2_11char_traitsIcEES5_EERT0_:
  308|  3.43k|   {
  309|  3.43k|      context ctx{};
  310|  3.43k|      std::string out{};
  311|  3.43k|      detail::minify_json<opt_true<Opts, &opts::comments>>(ctx, in, out);
  312|  3.43k|      if (bool(ctx.error)) [[unlikely]] {
  ------------------
  |  Branch (312:11): [True: 2.28k, False: 1.14k]
  ------------------
  313|  2.28k|         return {}; // an incomplete result is not a document; see above
  314|  2.28k|      }
  315|  1.14k|      return out;
  316|  3.43k|   }
_ZN3glz6detail11minify_jsonITnDaXtlNS_4optsELj10ELb1ELb1ELb1ELb1EEERNSt3__16vectorIcNS3_9allocatorIcEEEETkNS_13output_bufferERNS3_12basic_stringIcNS3_11char_traitsIcEES6_EETkNS_10is_contextERNS_7contextEQaa10contiguousIT0_E9resizableISG_EEEmOT2_OSG_OT1_:
  230|  3.43k|      {
  231|  3.43k|         if (in.size() == 0) {
  ------------------
  |  Branch (231:14): [True: 0, False: 3.43k]
  ------------------
  232|      0|            return 0;
  233|      0|         }
  234|       |
  235|  3.43k|         if constexpr (resizable<Out>) {
  236|       |            // Minifying only ever removes bytes, so this is room enough for whatever comes out.
  237|       |            // A bounded output is checked per write instead; see the scan above for why.
  238|  3.43k|            out.resize(in.size() + 2 * padding_bytes);
  239|  3.43k|         }
  240|  3.43k|         size_t ix = 0;
  241|  3.43k|         auto [it, end] = read_iterators<Opts>(in);
  242|  3.43k|         if (bool(ctx.error)) [[unlikely]] {
  ------------------
  |  Branch (242:14): [True: 0, False: 3.43k]
  ------------------
  243|      0|            return 0;
  244|      0|         }
  245|       |
  246|       |         // The input is no longer grown and shrunk around this: everything the scan below reads
  247|       |         // through -- read_json_string, read_json_number, skip_matching_ws -- bounds its own loads
  248|       |         // against `end`, so there is nothing left for the padding to protect.
  249|       |         if constexpr (self_terminating<In>) {
  250|       |            minify_json<opt_true<Opts, &opts::null_terminated>>(ctx, it, end, out, ix);
  251|       |         }
  252|  3.43k|         else {
  253|  3.43k|            minify_json<opt_false<Opts, &opts::null_terminated>>(ctx, it, end, out, ix);
  254|  3.43k|         }
  255|       |
  256|  3.43k|         if constexpr (resizable<Out>) {
  257|  3.43k|            out.resize(ix);
  258|  3.43k|         }
  259|  3.43k|         return ix;
  260|  3.43k|      }
_ZN3glz6detail11minify_jsonITnDaXtlNS_4optsELj10ELb0ELb1ELb1ELb1EEETkNS_10is_contextERNS_7contextERPKcS7_RNSt3__112basic_stringIcNS8_11char_traitsIcEENS8_9allocatorIcEEEEmEEvOT0_OT1_OT2_OT3_RT4_:
   18|  3.43k|      {
   19|  3.43k|         using enum json_type;
   20|       |
   21|       |         // Every write below goes through this, and the dump it makes is unchecked: the caller's
   22|       |         // one-shot sizing covers a resizable destination, because minifying only ever removes
   23|       |         // bytes, so the input's length is room enough.
   24|       |         //
   25|       |         // A bounded destination cannot be grown, and asking it for the input's length up front
   26|       |         // refuses a buffer that fits the result -- sizing the output to the minified length is the
   27|       |         // obvious thing to do, and `{ "a" : 1 }` into a 7 byte buffer has to work. So each write
   28|       |         // asks for exactly what it stores instead; see emit_bytes for where that count comes from.
   29|       |         // None of it survives for a resizable destination, which keeps the unchecked dumps and
   30|       |         // nothing more.
   31|  3.43k|         const auto put = [&](const auto& x) { return emit_bytes<false>(ctx, b, ix, x); };
   32|       |
   33|  3.43k|         auto ws_start = it;
   34|  3.43k|         uint64_t ws_size{};
   35|       |
   36|  3.43k|         auto skip_expected_whitespace = [&] {
   37|  3.43k|            auto new_ws_start = it;
   38|  3.43k|            if (ws_size && std::ptrdiff_t(ws_size) < end - it) [[likely]] {
   39|  3.43k|               skip_matching_ws(ws_start, it, ws_size);
   40|  3.43k|            }
   41|       |
   42|  3.43k|            if constexpr (Opts.null_terminated) {
   43|  3.43k|               while (whitespace_table[uint8_t(*it)]) {
   44|  3.43k|                  ++it;
   45|  3.43k|               }
   46|  3.43k|            }
   47|  3.43k|            else {
   48|  3.43k|               while ((it < end) && whitespace_table[uint8_t(*it)]) {
   49|  3.43k|                  ++it;
   50|  3.43k|               }
   51|  3.43k|            }
   52|  3.43k|            ws_start = new_ws_start;
   53|  3.43k|            ws_size = size_t(it - new_ws_start);
   54|  3.43k|         };
   55|       |
   56|  3.43k|         auto skip_whitespace = [&] {
   57|  3.43k|            if constexpr (Opts.null_terminated) {
   58|  3.43k|               while (whitespace_table[uint8_t(*it)]) {
   59|  3.43k|                  ++it;
   60|  3.43k|               }
   61|  3.43k|            }
   62|  3.43k|            else {
   63|  3.43k|               while ((it < end) && whitespace_table[uint8_t(*it)]) {
   64|  3.43k|                  ++it;
   65|  3.43k|               }
   66|  3.43k|            }
   67|  3.43k|         };
   68|       |
   69|  3.43k|         skip_whitespace();
   70|       |
   71|  35.6k|         while ([&]() -> bool {
  ------------------
  |  Branch (71:17): [True: 34.4k, False: 1.14k]
  ------------------
   72|  35.6k|            if constexpr (Opts.null_terminated) {
   73|  35.6k|               return true;
   74|  35.6k|            }
   75|  35.6k|            else {
   76|  35.6k|               return it < end;
   77|  35.6k|            }
   78|  35.6k|         }()) {
   79|  34.4k|            switch (json_types[uint8_t(*it)]) {
   80|  1.53k|            case String: {
  ------------------
  |  Branch (80:13): [True: 1.53k, False: 32.9k]
  ------------------
   81|  1.53k|               const auto value = read_json_string(ctx, it, end);
   82|  1.53k|               if (bool(ctx.error)) [[unlikely]] {
  ------------------
  |  Branch (82:20): [True: 110, False: 1.42k]
  ------------------
   83|    110|                  return;
   84|    110|               }
   85|       |               // non-empty: the scanner reports an empty view as an error
   86|  1.42k|               if (not put(value)) [[unlikely]] {
  ------------------
  |  Branch (86:20): [True: 0, False: 1.42k]
  ------------------
   87|      0|                  return;
   88|      0|               }
   89|  1.42k|               skip_whitespace();
   90|  1.42k|               break;
   91|  1.42k|            }
   92|  7.30k|            case Comma: {
  ------------------
  |  Branch (92:13): [True: 7.30k, False: 27.1k]
  ------------------
   93|  7.30k|               if (not put(',')) [[unlikely]] {
  ------------------
  |  Branch (93:20): [True: 0, False: 7.30k]
  ------------------
   94|      0|                  return;
   95|      0|               }
   96|  7.30k|               ++it;
   97|  7.30k|               skip_expected_whitespace();
   98|  7.30k|               break;
   99|  7.30k|            }
  100|  1.44k|            case Number: {
  ------------------
  |  Branch (100:13): [True: 1.44k, False: 33.0k]
  ------------------
  101|  1.44k|               const auto value = read_json_number<Opts.null_terminated>(it, end);
  102|       |               // non-empty: a Number match is one valid character
  103|  1.44k|               if (not put(value)) [[unlikely]] {
  ------------------
  |  Branch (103:20): [True: 0, False: 1.44k]
  ------------------
  104|      0|                  return;
  105|      0|               }
  106|  1.44k|               skip_whitespace();
  107|  1.44k|               break;
  108|  1.44k|            }
  109|  1.33k|            case Colon: {
  ------------------
  |  Branch (109:13): [True: 1.33k, False: 33.1k]
  ------------------
  110|  1.33k|               if (not put(':')) [[unlikely]] {
  ------------------
  |  Branch (110:20): [True: 0, False: 1.33k]
  ------------------
  111|      0|                  return;
  112|      0|               }
  113|  1.33k|               ++it;
  114|  1.33k|               skip_whitespace();
  115|  1.33k|               break;
  116|  1.33k|            }
  117|  6.34k|            case Array_Start: {
  ------------------
  |  Branch (117:13): [True: 6.34k, False: 28.1k]
  ------------------
  118|  6.34k|               if (not put('[')) [[unlikely]] {
  ------------------
  |  Branch (118:20): [True: 0, False: 6.34k]
  ------------------
  119|      0|                  return;
  120|      0|               }
  121|  6.34k|               ++it;
  122|  6.34k|               skip_expected_whitespace();
  123|  6.34k|               break;
  124|  6.34k|            }
  125|  1.25k|            case Array_End: {
  ------------------
  |  Branch (125:13): [True: 1.25k, False: 33.2k]
  ------------------
  126|  1.25k|               if (not put(']')) [[unlikely]] {
  ------------------
  |  Branch (126:20): [True: 0, False: 1.25k]
  ------------------
  127|      0|                  return;
  128|      0|               }
  129|  1.25k|               ++it;
  130|  1.25k|               skip_whitespace();
  131|  1.25k|               break;
  132|  1.25k|            }
  133|    777|            case Null: {
  ------------------
  |  Branch (133:13): [True: 777, False: 33.7k]
  ------------------
  134|       |               // The type table matched on the first byte alone; see match_literal for why writing
  135|       |               // the literal from the writer's own spelling needs the rest of it checked. Stepping
  136|       |               // over it unchecked also puts `it` past `end`, and from there the loop goes on
  137|       |               // minifying whatever follows the document into an output sized for the document.
  138|    777|               if (not match_literal<"null">(ctx, it, end)) [[unlikely]] {
  ------------------
  |  Branch (138:20): [True: 118, False: 659]
  ------------------
  139|    118|                  return;
  140|    118|               }
  141|    659|               if (not put("null")) [[unlikely]] {
  ------------------
  |  Branch (141:20): [True: 0, False: 659]
  ------------------
  142|      0|                  return;
  143|      0|               }
  144|    659|               skip_whitespace();
  145|    659|               break;
  146|    659|            }
  147|  1.79k|            case Bool: {
  ------------------
  |  Branch (147:13): [True: 1.79k, False: 32.6k]
  ------------------
  148|  1.79k|               if (*it == 't') {
  ------------------
  |  Branch (148:20): [True: 1.03k, False: 765]
  ------------------
  149|  1.03k|                  if (not match_literal<"true">(ctx, it, end)) [[unlikely]] {
  ------------------
  |  Branch (149:23): [True: 105, False: 926]
  ------------------
  150|    105|                     return;
  151|    105|                  }
  152|    926|                  if (not put("true")) [[unlikely]] {
  ------------------
  |  Branch (152:23): [True: 0, False: 926]
  ------------------
  153|      0|                     return;
  154|      0|                  }
  155|    926|                  skip_whitespace();
  156|    926|                  break;
  157|    926|               }
  158|    765|               else {
  159|    765|                  if (not match_literal<"false">(ctx, it, end)) [[unlikely]] {
  ------------------
  |  Branch (159:23): [True: 124, False: 641]
  ------------------
  160|    124|                     return;
  161|    124|                  }
  162|    641|                  if (not put("false")) [[unlikely]] {
  ------------------
  |  Branch (162:23): [True: 0, False: 641]
  ------------------
  163|      0|                     return;
  164|      0|                  }
  165|    641|                  skip_whitespace();
  166|    641|                  break;
  167|    641|               }
  168|  1.79k|            }
  169|  6.99k|            case Object_Start: {
  ------------------
  |  Branch (169:13): [True: 6.99k, False: 27.4k]
  ------------------
  170|  6.99k|               if (not put('{')) [[unlikely]] {
  ------------------
  |  Branch (170:20): [True: 0, False: 6.99k]
  ------------------
  171|      0|                  return;
  172|      0|               }
  173|  6.99k|               ++it;
  174|  6.99k|               skip_expected_whitespace();
  175|  6.99k|               break;
  176|  6.99k|            }
  177|  1.30k|            case Object_End: {
  ------------------
  |  Branch (177:13): [True: 1.30k, False: 33.1k]
  ------------------
  178|  1.30k|               if (not put('}')) [[unlikely]] {
  ------------------
  |  Branch (178:20): [True: 0, False: 1.30k]
  ------------------
  179|      0|                  return;
  180|      0|               }
  181|  1.30k|               ++it;
  182|  1.30k|               skip_whitespace();
  183|  1.30k|               break;
  184|  1.30k|            }
  185|  2.69k|            case Comment: {
  ------------------
  |  Branch (185:13): [True: 2.69k, False: 31.7k]
  ------------------
  186|  2.69k|               if constexpr (Opts.comments) {
  187|  2.69k|                  const auto comment = read_jsonc_comment(ctx, it, end);
  188|  2.69k|                  if (bool(ctx.error)) [[unlikely]] {
  ------------------
  |  Branch (188:23): [True: 141, False: 2.55k]
  ------------------
  189|    141|                     return;
  190|    141|                  }
  191|       |                  // A line comment is dropped rather than written out. Minifying is what removes
  192|       |                  // the newline that ends it, and a line comment with no line break behind it
  193|       |                  // comments out the whole rest of the output.
  194|  2.55k|                  if (not comment.line) {
  ------------------
  |  Branch (194:23): [True: 1.31k, False: 1.24k]
  ------------------
  195|       |                     // non-empty: an empty view comes with an error
  196|  1.31k|                     if (not put(comment.text)) [[unlikely]] {
  ------------------
  |  Branch (196:26): [True: 0, False: 1.31k]
  ------------------
  197|      0|                        return;
  198|      0|                     }
  199|  1.31k|                  }
  200|  2.55k|                  skip_whitespace();
  201|  2.55k|                  break;
  202|       |               }
  203|       |               else {
  204|       |                  [[fallthrough]];
  205|       |               }
  206|  2.69k|            }
  207|  4.38k|            [[unlikely]] default: {
  ------------------
  |  Branch (207:26): [True: 1.68k, False: 32.8k]
  ------------------
  208|       |               // A null terminated run carries no bound in its loop condition, so it ends here, on
  209|       |               // the terminator, which is not a JSON token. Reaching it is the end of the document
  210|       |               // rather than an error -- unclassified is how the type table reports both, and
  211|       |               // without this the minifier left syntax_error behind on every input it was ever
  212|       |               // given, valid or not, which is what made its error not worth returning.
  213|       |               if constexpr (Opts.null_terminated) {
  214|       |                  if (it >= end) {
  215|       |                     return;
  216|       |                  }
  217|       |               }
  218|  4.38k|               ctx.error = error_code::syntax_error;
  219|  4.38k|               return;
  220|  2.69k|            }
  221|  34.4k|            }
  222|  34.4k|         }
  223|  3.43k|      }
_ZZN3glz6detail11minify_jsonITnDaXtlNS_4optsELj10ELb0ELb1ELb1ELb1EEETkNS_10is_contextERNS_7contextERPKcS7_RNSt3__112basic_stringIcNS8_11char_traitsIcEENS8_9allocatorIcEEEEmEEvOT0_OT1_OT2_OT3_RT4_ENKUlvE0_clEv:
   56|  14.9k|         auto skip_whitespace = [&] {
   57|       |            if constexpr (Opts.null_terminated) {
   58|       |               while (whitespace_table[uint8_t(*it)]) {
   59|       |                  ++it;
   60|       |               }
   61|       |            }
   62|  14.9k|            else {
   63|   122k|               while ((it < end) && whitespace_table[uint8_t(*it)]) {
  ------------------
  |  Branch (63:23): [True: 122k, False: 547]
  |  Branch (63:37): [True: 107k, False: 14.4k]
  ------------------
   64|   107k|                  ++it;
   65|   107k|               }
   66|  14.9k|            }
   67|  14.9k|         };
_ZZN3glz6detail11minify_jsonITnDaXtlNS_4optsELj10ELb0ELb1ELb1ELb1EEETkNS_10is_contextERNS_7contextERPKcS7_RNSt3__112basic_stringIcNS8_11char_traitsIcEENS8_9allocatorIcEEEEmEEvOT0_OT1_OT2_OT3_RT4_ENKUlvE1_clEv:
   71|  35.6k|         while ([&]() -> bool {
   72|       |            if constexpr (Opts.null_terminated) {
   73|       |               return true;
   74|       |            }
   75|  35.6k|            else {
   76|  35.6k|               return it < end;
   77|  35.6k|            }
   78|  35.6k|         }()) {
_ZZN3glz6detail11minify_jsonITnDaXtlNS_4optsELj10ELb0ELb1ELb1ELb1EEETkNS_10is_contextERNS_7contextERPKcS7_RNSt3__112basic_stringIcNS8_11char_traitsIcEENS8_9allocatorIcEEEEmEEvOT0_OT1_OT2_OT3_RT4_ENKUlRKT_E_clINS8_17basic_string_viewIcSB_EEEEDaSS_:
   31|  4.18k|         const auto put = [&](const auto& x) { return emit_bytes<false>(ctx, b, ix, x); };
_ZZN3glz6detail11minify_jsonITnDaXtlNS_4optsELj10ELb0ELb1ELb1ELb1EEETkNS_10is_contextERNS_7contextERPKcS7_RNSt3__112basic_stringIcNS8_11char_traitsIcEENS8_9allocatorIcEEEEmEEvOT0_OT1_OT2_OT3_RT4_ENKUlRKT_E_clIcEEDaSS_:
   31|  24.5k|         const auto put = [&](const auto& x) { return emit_bytes<false>(ctx, b, ix, x); };
_ZZN3glz6detail11minify_jsonITnDaXtlNS_4optsELj10ELb0ELb1ELb1ELb1EEETkNS_10is_contextERNS_7contextERPKcS7_RNSt3__112basic_stringIcNS8_11char_traitsIcEENS8_9allocatorIcEEEEmEEvOT0_OT1_OT2_OT3_RT4_ENKUlvE_clEv:
   36|  20.6k|         auto skip_expected_whitespace = [&] {
   37|  20.6k|            auto new_ws_start = it;
   38|  20.6k|            if (ws_size && std::ptrdiff_t(ws_size) < end - it) [[likely]] {
  ------------------
  |  Branch (38:17): [True: 14.7k, False: 5.91k]
  |  Branch (38:28): [True: 13.4k, False: 1.24k]
  ------------------
   39|  13.4k|               skip_matching_ws(ws_start, it, ws_size);
   40|  13.4k|            }
   41|       |
   42|       |            if constexpr (Opts.null_terminated) {
   43|       |               while (whitespace_table[uint8_t(*it)]) {
   44|       |                  ++it;
   45|       |               }
   46|       |            }
   47|  20.6k|            else {
   48|  19.3M|               while ((it < end) && whitespace_table[uint8_t(*it)]) {
  ------------------
  |  Branch (48:23): [True: 19.3M, False: 602]
  |  Branch (48:37): [True: 19.3M, False: 20.0k]
  ------------------
   49|  19.3M|                  ++it;
   50|  19.3M|               }
   51|  20.6k|            }
   52|  20.6k|            ws_start = new_ws_start;
   53|  20.6k|            ws_size = size_t(it - new_ws_start);
   54|  20.6k|         };
_ZZN3glz6detail11minify_jsonITnDaXtlNS_4optsELj10ELb0ELb1ELb1ELb1EEETkNS_10is_contextERNS_7contextERPKcS7_RNSt3__112basic_stringIcNS8_11char_traitsIcEENS8_9allocatorIcEEEEmEEvOT0_OT1_OT2_OT3_RT4_ENKUlRKT_E_clIA5_cEEDaSS_:
   31|  1.58k|         const auto put = [&](const auto& x) { return emit_bytes<false>(ctx, b, ix, x); };
_ZZN3glz6detail11minify_jsonITnDaXtlNS_4optsELj10ELb0ELb1ELb1ELb1EEETkNS_10is_contextERNS_7contextERPKcS7_RNSt3__112basic_stringIcNS8_11char_traitsIcEENS8_9allocatorIcEEEEmEEvOT0_OT1_OT2_OT3_RT4_ENKUlRKT_E_clIA6_cEEDaSS_:
   31|    641|         const auto put = [&](const auto& x) { return emit_bytes<false>(ctx, b, ix, x); };
_ZN3glz12minify_jsoncITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1EEETkNS_9resizableENSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEEES8_RT0_:
  308|  3.43k|   {
  309|  3.43k|      context ctx{};
  310|  3.43k|      std::string out{};
  311|  3.43k|      detail::minify_json<opt_true<Opts, &opts::comments>>(ctx, in, out);
  312|  3.43k|      if (bool(ctx.error)) [[unlikely]] {
  ------------------
  |  Branch (312:11): [True: 2.28k, False: 1.14k]
  ------------------
  313|  2.28k|         return {}; // an incomplete result is not a document; see above
  314|  2.28k|      }
  315|  1.14k|      return out;
  316|  3.43k|   }
_ZN3glz6detail11minify_jsonITnDaXtlNS_4optsELj10ELb1ELb1ELb1ELb1EEERNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEETkNS_13output_bufferESA_TkNS_10is_contextERNS_7contextEQaa10contiguousIT0_E9resizableISD_EEEmOT2_OSD_OT1_:
  230|  3.43k|      {
  231|  3.43k|         if (in.size() == 0) {
  ------------------
  |  Branch (231:14): [True: 0, False: 3.43k]
  ------------------
  232|      0|            return 0;
  233|      0|         }
  234|       |
  235|  3.43k|         if constexpr (resizable<Out>) {
  236|       |            // Minifying only ever removes bytes, so this is room enough for whatever comes out.
  237|       |            // A bounded output is checked per write instead; see the scan above for why.
  238|  3.43k|            out.resize(in.size() + 2 * padding_bytes);
  239|  3.43k|         }
  240|  3.43k|         size_t ix = 0;
  241|  3.43k|         auto [it, end] = read_iterators<Opts>(in);
  242|  3.43k|         if (bool(ctx.error)) [[unlikely]] {
  ------------------
  |  Branch (242:14): [True: 0, False: 3.43k]
  ------------------
  243|      0|            return 0;
  244|      0|         }
  245|       |
  246|       |         // The input is no longer grown and shrunk around this: everything the scan below reads
  247|       |         // through -- read_json_string, read_json_number, skip_matching_ws -- bounds its own loads
  248|       |         // against `end`, so there is nothing left for the padding to protect.
  249|  3.43k|         if constexpr (self_terminating<In>) {
  250|  3.43k|            minify_json<opt_true<Opts, &opts::null_terminated>>(ctx, it, end, out, ix);
  251|       |         }
  252|       |         else {
  253|       |            minify_json<opt_false<Opts, &opts::null_terminated>>(ctx, it, end, out, ix);
  254|       |         }
  255|       |
  256|  3.43k|         if constexpr (resizable<Out>) {
  257|  3.43k|            out.resize(ix);
  258|  3.43k|         }
  259|  3.43k|         return ix;
  260|  3.43k|      }
_ZN3glz6detail11minify_jsonITnDaXtlNS_4optsELj10ELb1ELb1ELb1ELb1EEETkNS_10is_contextERNS_7contextERPKcS7_RNSt3__112basic_stringIcNS8_11char_traitsIcEENS8_9allocatorIcEEEEmEEvOT0_OT1_OT2_OT3_RT4_:
   18|  3.43k|      {
   19|  3.43k|         using enum json_type;
   20|       |
   21|       |         // Every write below goes through this, and the dump it makes is unchecked: the caller's
   22|       |         // one-shot sizing covers a resizable destination, because minifying only ever removes
   23|       |         // bytes, so the input's length is room enough.
   24|       |         //
   25|       |         // A bounded destination cannot be grown, and asking it for the input's length up front
   26|       |         // refuses a buffer that fits the result -- sizing the output to the minified length is the
   27|       |         // obvious thing to do, and `{ "a" : 1 }` into a 7 byte buffer has to work. So each write
   28|       |         // asks for exactly what it stores instead; see emit_bytes for where that count comes from.
   29|       |         // None of it survives for a resizable destination, which keeps the unchecked dumps and
   30|       |         // nothing more.
   31|  3.43k|         const auto put = [&](const auto& x) { return emit_bytes<false>(ctx, b, ix, x); };
   32|       |
   33|  3.43k|         auto ws_start = it;
   34|  3.43k|         uint64_t ws_size{};
   35|       |
   36|  3.43k|         auto skip_expected_whitespace = [&] {
   37|  3.43k|            auto new_ws_start = it;
   38|  3.43k|            if (ws_size && std::ptrdiff_t(ws_size) < end - it) [[likely]] {
   39|  3.43k|               skip_matching_ws(ws_start, it, ws_size);
   40|  3.43k|            }
   41|       |
   42|  3.43k|            if constexpr (Opts.null_terminated) {
   43|  3.43k|               while (whitespace_table[uint8_t(*it)]) {
   44|  3.43k|                  ++it;
   45|  3.43k|               }
   46|  3.43k|            }
   47|  3.43k|            else {
   48|  3.43k|               while ((it < end) && whitespace_table[uint8_t(*it)]) {
   49|  3.43k|                  ++it;
   50|  3.43k|               }
   51|  3.43k|            }
   52|  3.43k|            ws_start = new_ws_start;
   53|  3.43k|            ws_size = size_t(it - new_ws_start);
   54|  3.43k|         };
   55|       |
   56|  3.43k|         auto skip_whitespace = [&] {
   57|  3.43k|            if constexpr (Opts.null_terminated) {
   58|  3.43k|               while (whitespace_table[uint8_t(*it)]) {
   59|  3.43k|                  ++it;
   60|  3.43k|               }
   61|  3.43k|            }
   62|  3.43k|            else {
   63|  3.43k|               while ((it < end) && whitespace_table[uint8_t(*it)]) {
   64|  3.43k|                  ++it;
   65|  3.43k|               }
   66|  3.43k|            }
   67|  3.43k|         };
   68|       |
   69|  3.43k|         skip_whitespace();
   70|       |
   71|  35.6k|         while ([&]() -> bool {
  ------------------
  |  Branch (71:17): [True: 35.6k, Folded]
  ------------------
   72|  35.6k|            if constexpr (Opts.null_terminated) {
   73|  35.6k|               return true;
   74|  35.6k|            }
   75|  35.6k|            else {
   76|  35.6k|               return it < end;
   77|  35.6k|            }
   78|  35.6k|         }()) {
   79|  35.6k|            switch (json_types[uint8_t(*it)]) {
   80|  1.53k|            case String: {
  ------------------
  |  Branch (80:13): [True: 1.53k, False: 34.1k]
  ------------------
   81|  1.53k|               const auto value = read_json_string(ctx, it, end);
   82|  1.53k|               if (bool(ctx.error)) [[unlikely]] {
  ------------------
  |  Branch (82:20): [True: 110, False: 1.42k]
  ------------------
   83|    110|                  return;
   84|    110|               }
   85|       |               // non-empty: the scanner reports an empty view as an error
   86|  1.42k|               if (not put(value)) [[unlikely]] {
  ------------------
  |  Branch (86:20): [True: 0, False: 1.42k]
  ------------------
   87|      0|                  return;
   88|      0|               }
   89|  1.42k|               skip_whitespace();
   90|  1.42k|               break;
   91|  1.42k|            }
   92|  7.30k|            case Comma: {
  ------------------
  |  Branch (92:13): [True: 7.30k, False: 28.3k]
  ------------------
   93|  7.30k|               if (not put(',')) [[unlikely]] {
  ------------------
  |  Branch (93:20): [True: 0, False: 7.30k]
  ------------------
   94|      0|                  return;
   95|      0|               }
   96|  7.30k|               ++it;
   97|  7.30k|               skip_expected_whitespace();
   98|  7.30k|               break;
   99|  7.30k|            }
  100|  1.44k|            case Number: {
  ------------------
  |  Branch (100:13): [True: 1.44k, False: 34.1k]
  ------------------
  101|  1.44k|               const auto value = read_json_number<Opts.null_terminated>(it, end);
  102|       |               // non-empty: a Number match is one valid character
  103|  1.44k|               if (not put(value)) [[unlikely]] {
  ------------------
  |  Branch (103:20): [True: 0, False: 1.44k]
  ------------------
  104|      0|                  return;
  105|      0|               }
  106|  1.44k|               skip_whitespace();
  107|  1.44k|               break;
  108|  1.44k|            }
  109|  1.33k|            case Colon: {
  ------------------
  |  Branch (109:13): [True: 1.33k, False: 34.2k]
  ------------------
  110|  1.33k|               if (not put(':')) [[unlikely]] {
  ------------------
  |  Branch (110:20): [True: 0, False: 1.33k]
  ------------------
  111|      0|                  return;
  112|      0|               }
  113|  1.33k|               ++it;
  114|  1.33k|               skip_whitespace();
  115|  1.33k|               break;
  116|  1.33k|            }
  117|  6.34k|            case Array_Start: {
  ------------------
  |  Branch (117:13): [True: 6.34k, False: 29.2k]
  ------------------
  118|  6.34k|               if (not put('[')) [[unlikely]] {
  ------------------
  |  Branch (118:20): [True: 0, False: 6.34k]
  ------------------
  119|      0|                  return;
  120|      0|               }
  121|  6.34k|               ++it;
  122|  6.34k|               skip_expected_whitespace();
  123|  6.34k|               break;
  124|  6.34k|            }
  125|  1.25k|            case Array_End: {
  ------------------
  |  Branch (125:13): [True: 1.25k, False: 34.3k]
  ------------------
  126|  1.25k|               if (not put(']')) [[unlikely]] {
  ------------------
  |  Branch (126:20): [True: 0, False: 1.25k]
  ------------------
  127|      0|                  return;
  128|      0|               }
  129|  1.25k|               ++it;
  130|  1.25k|               skip_whitespace();
  131|  1.25k|               break;
  132|  1.25k|            }
  133|    777|            case Null: {
  ------------------
  |  Branch (133:13): [True: 777, False: 34.8k]
  ------------------
  134|       |               // The type table matched on the first byte alone; see match_literal for why writing
  135|       |               // the literal from the writer's own spelling needs the rest of it checked. Stepping
  136|       |               // over it unchecked also puts `it` past `end`, and from there the loop goes on
  137|       |               // minifying whatever follows the document into an output sized for the document.
  138|    777|               if (not match_literal<"null">(ctx, it, end)) [[unlikely]] {
  ------------------
  |  Branch (138:20): [True: 118, False: 659]
  ------------------
  139|    118|                  return;
  140|    118|               }
  141|    659|               if (not put("null")) [[unlikely]] {
  ------------------
  |  Branch (141:20): [True: 0, False: 659]
  ------------------
  142|      0|                  return;
  143|      0|               }
  144|    659|               skip_whitespace();
  145|    659|               break;
  146|    659|            }
  147|  1.79k|            case Bool: {
  ------------------
  |  Branch (147:13): [True: 1.79k, False: 33.8k]
  ------------------
  148|  1.79k|               if (*it == 't') {
  ------------------
  |  Branch (148:20): [True: 1.03k, False: 765]
  ------------------
  149|  1.03k|                  if (not match_literal<"true">(ctx, it, end)) [[unlikely]] {
  ------------------
  |  Branch (149:23): [True: 105, False: 926]
  ------------------
  150|    105|                     return;
  151|    105|                  }
  152|    926|                  if (not put("true")) [[unlikely]] {
  ------------------
  |  Branch (152:23): [True: 0, False: 926]
  ------------------
  153|      0|                     return;
  154|      0|                  }
  155|    926|                  skip_whitespace();
  156|    926|                  break;
  157|    926|               }
  158|    765|               else {
  159|    765|                  if (not match_literal<"false">(ctx, it, end)) [[unlikely]] {
  ------------------
  |  Branch (159:23): [True: 124, False: 641]
  ------------------
  160|    124|                     return;
  161|    124|                  }
  162|    641|                  if (not put("false")) [[unlikely]] {
  ------------------
  |  Branch (162:23): [True: 0, False: 641]
  ------------------
  163|      0|                     return;
  164|      0|                  }
  165|    641|                  skip_whitespace();
  166|    641|                  break;
  167|    641|               }
  168|  1.79k|            }
  169|  6.99k|            case Object_Start: {
  ------------------
  |  Branch (169:13): [True: 6.99k, False: 28.6k]
  ------------------
  170|  6.99k|               if (not put('{')) [[unlikely]] {
  ------------------
  |  Branch (170:20): [True: 0, False: 6.99k]
  ------------------
  171|      0|                  return;
  172|      0|               }
  173|  6.99k|               ++it;
  174|  6.99k|               skip_expected_whitespace();
  175|  6.99k|               break;
  176|  6.99k|            }
  177|  1.30k|            case Object_End: {
  ------------------
  |  Branch (177:13): [True: 1.30k, False: 34.3k]
  ------------------
  178|  1.30k|               if (not put('}')) [[unlikely]] {
  ------------------
  |  Branch (178:20): [True: 0, False: 1.30k]
  ------------------
  179|      0|                  return;
  180|      0|               }
  181|  1.30k|               ++it;
  182|  1.30k|               skip_whitespace();
  183|  1.30k|               break;
  184|  1.30k|            }
  185|  2.69k|            case Comment: {
  ------------------
  |  Branch (185:13): [True: 2.69k, False: 32.9k]
  ------------------
  186|  2.69k|               if constexpr (Opts.comments) {
  187|  2.69k|                  const auto comment = read_jsonc_comment(ctx, it, end);
  188|  2.69k|                  if (bool(ctx.error)) [[unlikely]] {
  ------------------
  |  Branch (188:23): [True: 141, False: 2.55k]
  ------------------
  189|    141|                     return;
  190|    141|                  }
  191|       |                  // A line comment is dropped rather than written out. Minifying is what removes
  192|       |                  // the newline that ends it, and a line comment with no line break behind it
  193|       |                  // comments out the whole rest of the output.
  194|  2.55k|                  if (not comment.line) {
  ------------------
  |  Branch (194:23): [True: 1.31k, False: 1.24k]
  ------------------
  195|       |                     // non-empty: an empty view comes with an error
  196|  1.31k|                     if (not put(comment.text)) [[unlikely]] {
  ------------------
  |  Branch (196:26): [True: 0, False: 1.31k]
  ------------------
  197|      0|                        return;
  198|      0|                     }
  199|  1.31k|                  }
  200|  2.55k|                  skip_whitespace();
  201|  2.55k|                  break;
  202|       |               }
  203|       |               else {
  204|       |                  [[fallthrough]];
  205|       |               }
  206|  2.69k|            }
  207|  5.53k|            [[unlikely]] default: {
  ------------------
  |  Branch (207:26): [True: 2.83k, False: 32.8k]
  ------------------
  208|       |               // A null terminated run carries no bound in its loop condition, so it ends here, on
  209|       |               // the terminator, which is not a JSON token. Reaching it is the end of the document
  210|       |               // rather than an error -- unclassified is how the type table reports both, and
  211|       |               // without this the minifier left syntax_error behind on every input it was ever
  212|       |               // given, valid or not, which is what made its error not worth returning.
  213|  5.53k|               if constexpr (Opts.null_terminated) {
  214|  5.53k|                  if (it >= end) {
  ------------------
  |  Branch (214:23): [True: 1.14k, False: 4.38k]
  ------------------
  215|  1.14k|                     return;
  216|  1.14k|                  }
  217|  5.53k|               }
  218|  4.38k|               ctx.error = error_code::syntax_error;
  219|  5.53k|               return;
  220|  2.69k|            }
  221|  35.6k|            }
  222|  35.6k|         }
  223|  3.43k|      }
_ZZN3glz6detail11minify_jsonITnDaXtlNS_4optsELj10ELb1ELb1ELb1ELb1EEETkNS_10is_contextERNS_7contextERPKcS7_RNSt3__112basic_stringIcNS8_11char_traitsIcEENS8_9allocatorIcEEEEmEEvOT0_OT1_OT2_OT3_RT4_ENKUlvE0_clEv:
   56|  14.9k|         auto skip_whitespace = [&] {
   57|  14.9k|            if constexpr (Opts.null_terminated) {
   58|   122k|               while (whitespace_table[uint8_t(*it)]) {
  ------------------
  |  Branch (58:23): [True: 107k, False: 14.9k]
  ------------------
   59|   107k|                  ++it;
   60|   107k|               }
   61|       |            }
   62|       |            else {
   63|       |               while ((it < end) && whitespace_table[uint8_t(*it)]) {
   64|       |                  ++it;
   65|       |               }
   66|       |            }
   67|  14.9k|         };
_ZZN3glz6detail11minify_jsonITnDaXtlNS_4optsELj10ELb1ELb1ELb1ELb1EEETkNS_10is_contextERNS_7contextERPKcS7_RNSt3__112basic_stringIcNS8_11char_traitsIcEENS8_9allocatorIcEEEEmEEvOT0_OT1_OT2_OT3_RT4_ENKUlvE1_clEv:
   71|  35.6k|         while ([&]() -> bool {
   72|  35.6k|            if constexpr (Opts.null_terminated) {
   73|  35.6k|               return true;
   74|       |            }
   75|       |            else {
   76|       |               return it < end;
   77|       |            }
   78|  35.6k|         }()) {
_ZZN3glz6detail11minify_jsonITnDaXtlNS_4optsELj10ELb1ELb1ELb1ELb1EEETkNS_10is_contextERNS_7contextERPKcS7_RNSt3__112basic_stringIcNS8_11char_traitsIcEENS8_9allocatorIcEEEEmEEvOT0_OT1_OT2_OT3_RT4_ENKUlRKT_E_clINS8_17basic_string_viewIcSB_EEEEDaSS_:
   31|  4.18k|         const auto put = [&](const auto& x) { return emit_bytes<false>(ctx, b, ix, x); };
_ZZN3glz6detail11minify_jsonITnDaXtlNS_4optsELj10ELb1ELb1ELb1ELb1EEETkNS_10is_contextERNS_7contextERPKcS7_RNSt3__112basic_stringIcNS8_11char_traitsIcEENS8_9allocatorIcEEEEmEEvOT0_OT1_OT2_OT3_RT4_ENKUlRKT_E_clIcEEDaSS_:
   31|  24.5k|         const auto put = [&](const auto& x) { return emit_bytes<false>(ctx, b, ix, x); };
_ZZN3glz6detail11minify_jsonITnDaXtlNS_4optsELj10ELb1ELb1ELb1ELb1EEETkNS_10is_contextERNS_7contextERPKcS7_RNSt3__112basic_stringIcNS8_11char_traitsIcEENS8_9allocatorIcEEEEmEEvOT0_OT1_OT2_OT3_RT4_ENKUlvE_clEv:
   36|  20.6k|         auto skip_expected_whitespace = [&] {
   37|  20.6k|            auto new_ws_start = it;
   38|  20.6k|            if (ws_size && std::ptrdiff_t(ws_size) < end - it) [[likely]] {
  ------------------
  |  Branch (38:17): [True: 14.7k, False: 5.91k]
  |  Branch (38:28): [True: 13.4k, False: 1.24k]
  ------------------
   39|  13.4k|               skip_matching_ws(ws_start, it, ws_size);
   40|  13.4k|            }
   41|       |
   42|  20.6k|            if constexpr (Opts.null_terminated) {
   43|  19.3M|               while (whitespace_table[uint8_t(*it)]) {
  ------------------
  |  Branch (43:23): [True: 19.3M, False: 20.6k]
  ------------------
   44|  19.3M|                  ++it;
   45|  19.3M|               }
   46|       |            }
   47|       |            else {
   48|       |               while ((it < end) && whitespace_table[uint8_t(*it)]) {
   49|       |                  ++it;
   50|       |               }
   51|       |            }
   52|  20.6k|            ws_start = new_ws_start;
   53|  20.6k|            ws_size = size_t(it - new_ws_start);
   54|  20.6k|         };
_ZZN3glz6detail11minify_jsonITnDaXtlNS_4optsELj10ELb1ELb1ELb1ELb1EEETkNS_10is_contextERNS_7contextERPKcS7_RNSt3__112basic_stringIcNS8_11char_traitsIcEENS8_9allocatorIcEEEEmEEvOT0_OT1_OT2_OT3_RT4_ENKUlRKT_E_clIA5_cEEDaSS_:
   31|  1.58k|         const auto put = [&](const auto& x) { return emit_bytes<false>(ctx, b, ix, x); };
_ZZN3glz6detail11minify_jsonITnDaXtlNS_4optsELj10ELb1ELb1ELb1ELb1EEETkNS_10is_contextERNS_7contextERPKcS7_RNSt3__112basic_stringIcNS8_11char_traitsIcEENS8_9allocatorIcEEEEmEEvOT0_OT1_OT2_OT3_RT4_ENKUlRKT_E_clIA6_cEEDaSS_:
   31|    641|         const auto put = [&](const auto& x) { return emit_bytes<false>(ctx, b, ix, x); };
_ZN3glz12minify_jsoncITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1EEETkNS_9resizableENSt3__16vectorIcNS2_9allocatorIcEEEENS2_5arrayIcLm64EEEEENS_9error_ctxERT0_RT1_:
  300|  3.43k|   {
  301|  3.43k|      context ctx{};
  302|  3.43k|      const auto n = detail::minify_json<opt_true<Opts, &opts::comments>>(ctx, in, out);
  303|  3.43k|      return {n, ctx.error, ctx.custom_error_message};
  304|  3.43k|   }
_ZN3glz6detail11minify_jsonITnDaXtlNS_4optsELj10ELb1ELb1ELb1ELb1EEERNSt3__16vectorIcNS3_9allocatorIcEEEETkNS_13output_bufferERNS3_5arrayIcLm64EEETkNS_10is_contextERNS_7contextEQaa10contiguousIT0_E9resizableISE_EEEmOT2_OSE_OT1_:
  230|  3.43k|      {
  231|  3.43k|         if (in.size() == 0) {
  ------------------
  |  Branch (231:14): [True: 0, False: 3.43k]
  ------------------
  232|      0|            return 0;
  233|      0|         }
  234|       |
  235|       |         if constexpr (resizable<Out>) {
  236|       |            // Minifying only ever removes bytes, so this is room enough for whatever comes out.
  237|       |            // A bounded output is checked per write instead; see the scan above for why.
  238|       |            out.resize(in.size() + 2 * padding_bytes);
  239|       |         }
  240|  3.43k|         size_t ix = 0;
  241|  3.43k|         auto [it, end] = read_iterators<Opts>(in);
  242|  3.43k|         if (bool(ctx.error)) [[unlikely]] {
  ------------------
  |  Branch (242:14): [True: 0, False: 3.43k]
  ------------------
  243|      0|            return 0;
  244|      0|         }
  245|       |
  246|       |         // The input is no longer grown and shrunk around this: everything the scan below reads
  247|       |         // through -- read_json_string, read_json_number, skip_matching_ws -- bounds its own loads
  248|       |         // against `end`, so there is nothing left for the padding to protect.
  249|       |         if constexpr (self_terminating<In>) {
  250|       |            minify_json<opt_true<Opts, &opts::null_terminated>>(ctx, it, end, out, ix);
  251|       |         }
  252|  3.43k|         else {
  253|  3.43k|            minify_json<opt_false<Opts, &opts::null_terminated>>(ctx, it, end, out, ix);
  254|  3.43k|         }
  255|       |
  256|       |         if constexpr (resizable<Out>) {
  257|       |            out.resize(ix);
  258|       |         }
  259|  3.43k|         return ix;
  260|  3.43k|      }
_ZN3glz6detail11minify_jsonITnDaXtlNS_4optsELj10ELb0ELb1ELb1ELb1EEETkNS_10is_contextERNS_7contextERPKcS7_RNSt3__15arrayIcLm64EEEmEEvOT0_OT1_OT2_OT3_RT4_:
   18|  3.43k|      {
   19|  3.43k|         using enum json_type;
   20|       |
   21|       |         // Every write below goes through this, and the dump it makes is unchecked: the caller's
   22|       |         // one-shot sizing covers a resizable destination, because minifying only ever removes
   23|       |         // bytes, so the input's length is room enough.
   24|       |         //
   25|       |         // A bounded destination cannot be grown, and asking it for the input's length up front
   26|       |         // refuses a buffer that fits the result -- sizing the output to the minified length is the
   27|       |         // obvious thing to do, and `{ "a" : 1 }` into a 7 byte buffer has to work. So each write
   28|       |         // asks for exactly what it stores instead; see emit_bytes for where that count comes from.
   29|       |         // None of it survives for a resizable destination, which keeps the unchecked dumps and
   30|       |         // nothing more.
   31|  3.43k|         const auto put = [&](const auto& x) { return emit_bytes<false>(ctx, b, ix, x); };
   32|       |
   33|  3.43k|         auto ws_start = it;
   34|  3.43k|         uint64_t ws_size{};
   35|       |
   36|  3.43k|         auto skip_expected_whitespace = [&] {
   37|  3.43k|            auto new_ws_start = it;
   38|  3.43k|            if (ws_size && std::ptrdiff_t(ws_size) < end - it) [[likely]] {
   39|  3.43k|               skip_matching_ws(ws_start, it, ws_size);
   40|  3.43k|            }
   41|       |
   42|  3.43k|            if constexpr (Opts.null_terminated) {
   43|  3.43k|               while (whitespace_table[uint8_t(*it)]) {
   44|  3.43k|                  ++it;
   45|  3.43k|               }
   46|  3.43k|            }
   47|  3.43k|            else {
   48|  3.43k|               while ((it < end) && whitespace_table[uint8_t(*it)]) {
   49|  3.43k|                  ++it;
   50|  3.43k|               }
   51|  3.43k|            }
   52|  3.43k|            ws_start = new_ws_start;
   53|  3.43k|            ws_size = size_t(it - new_ws_start);
   54|  3.43k|         };
   55|       |
   56|  3.43k|         auto skip_whitespace = [&] {
   57|  3.43k|            if constexpr (Opts.null_terminated) {
   58|  3.43k|               while (whitespace_table[uint8_t(*it)]) {
   59|  3.43k|                  ++it;
   60|  3.43k|               }
   61|  3.43k|            }
   62|  3.43k|            else {
   63|  3.43k|               while ((it < end) && whitespace_table[uint8_t(*it)]) {
   64|  3.43k|                  ++it;
   65|  3.43k|               }
   66|  3.43k|            }
   67|  3.43k|         };
   68|       |
   69|  3.43k|         skip_whitespace();
   70|       |
   71|  25.1k|         while ([&]() -> bool {
  ------------------
  |  Branch (71:17): [True: 24.1k, False: 989]
  ------------------
   72|  25.1k|            if constexpr (Opts.null_terminated) {
   73|  25.1k|               return true;
   74|  25.1k|            }
   75|  25.1k|            else {
   76|  25.1k|               return it < end;
   77|  25.1k|            }
   78|  25.1k|         }()) {
   79|  24.1k|            switch (json_types[uint8_t(*it)]) {
   80|    929|            case String: {
  ------------------
  |  Branch (80:13): [True: 929, False: 23.2k]
  ------------------
   81|    929|               const auto value = read_json_string(ctx, it, end);
   82|    929|               if (bool(ctx.error)) [[unlikely]] {
  ------------------
  |  Branch (82:20): [True: 97, False: 832]
  ------------------
   83|     97|                  return;
   84|     97|               }
   85|       |               // non-empty: the scanner reports an empty view as an error
   86|    832|               if (not put(value)) [[unlikely]] {
  ------------------
  |  Branch (86:20): [True: 60, False: 772]
  ------------------
   87|     60|                  return;
   88|     60|               }
   89|    772|               skip_whitespace();
   90|    772|               break;
   91|    832|            }
   92|  5.38k|            case Comma: {
  ------------------
  |  Branch (92:13): [True: 5.38k, False: 18.7k]
  ------------------
   93|  5.38k|               if (not put(',')) [[unlikely]] {
  ------------------
  |  Branch (93:20): [True: 34, False: 5.34k]
  ------------------
   94|     34|                  return;
   95|     34|               }
   96|  5.34k|               ++it;
   97|  5.34k|               skip_expected_whitespace();
   98|  5.34k|               break;
   99|  5.38k|            }
  100|    879|            case Number: {
  ------------------
  |  Branch (100:13): [True: 879, False: 23.2k]
  ------------------
  101|    879|               const auto value = read_json_number<Opts.null_terminated>(it, end);
  102|       |               // non-empty: a Number match is one valid character
  103|    879|               if (not put(value)) [[unlikely]] {
  ------------------
  |  Branch (103:20): [True: 32, False: 847]
  ------------------
  104|     32|                  return;
  105|     32|               }
  106|    847|               skip_whitespace();
  107|    847|               break;
  108|    879|            }
  109|  1.06k|            case Colon: {
  ------------------
  |  Branch (109:13): [True: 1.06k, False: 23.0k]
  ------------------
  110|  1.06k|               if (not put(':')) [[unlikely]] {
  ------------------
  |  Branch (110:20): [True: 5, False: 1.05k]
  ------------------
  111|      5|                  return;
  112|      5|               }
  113|  1.05k|               ++it;
  114|  1.05k|               skip_whitespace();
  115|  1.05k|               break;
  116|  1.06k|            }
  117|  4.74k|            case Array_Start: {
  ------------------
  |  Branch (117:13): [True: 4.74k, False: 19.4k]
  ------------------
  118|  4.74k|               if (not put('[')) [[unlikely]] {
  ------------------
  |  Branch (118:20): [True: 32, False: 4.70k]
  ------------------
  119|     32|                  return;
  120|     32|               }
  121|  4.70k|               ++it;
  122|  4.70k|               skip_expected_whitespace();
  123|  4.70k|               break;
  124|  4.74k|            }
  125|    738|            case Array_End: {
  ------------------
  |  Branch (125:13): [True: 738, False: 23.4k]
  ------------------
  126|    738|               if (not put(']')) [[unlikely]] {
  ------------------
  |  Branch (126:20): [True: 9, False: 729]
  ------------------
  127|      9|                  return;
  128|      9|               }
  129|    729|               ++it;
  130|    729|               skip_whitespace();
  131|    729|               break;
  132|    738|            }
  133|    409|            case Null: {
  ------------------
  |  Branch (133:13): [True: 409, False: 23.7k]
  ------------------
  134|       |               // The type table matched on the first byte alone; see match_literal for why writing
  135|       |               // the literal from the writer's own spelling needs the rest of it checked. Stepping
  136|       |               // over it unchecked also puts `it` past `end`, and from there the loop goes on
  137|       |               // minifying whatever follows the document into an output sized for the document.
  138|    409|               if (not match_literal<"null">(ctx, it, end)) [[unlikely]] {
  ------------------
  |  Branch (138:20): [True: 110, False: 299]
  ------------------
  139|    110|                  return;
  140|    110|               }
  141|    299|               if (not put("null")) [[unlikely]] {
  ------------------
  |  Branch (141:20): [True: 11, False: 288]
  ------------------
  142|     11|                  return;
  143|     11|               }
  144|    288|               skip_whitespace();
  145|    288|               break;
  146|    299|            }
  147|    803|            case Bool: {
  ------------------
  |  Branch (147:13): [True: 803, False: 23.3k]
  ------------------
  148|    803|               if (*it == 't') {
  ------------------
  |  Branch (148:20): [True: 466, False: 337]
  ------------------
  149|    466|                  if (not match_literal<"true">(ctx, it, end)) [[unlikely]] {
  ------------------
  |  Branch (149:23): [True: 93, False: 373]
  ------------------
  150|     93|                     return;
  151|     93|                  }
  152|    373|                  if (not put("true")) [[unlikely]] {
  ------------------
  |  Branch (152:23): [True: 11, False: 362]
  ------------------
  153|     11|                     return;
  154|     11|                  }
  155|    362|                  skip_whitespace();
  156|    362|                  break;
  157|    373|               }
  158|    337|               else {
  159|    337|                  if (not match_literal<"false">(ctx, it, end)) [[unlikely]] {
  ------------------
  |  Branch (159:23): [True: 117, False: 220]
  ------------------
  160|    117|                     return;
  161|    117|                  }
  162|    220|                  if (not put("false")) [[unlikely]] {
  ------------------
  |  Branch (162:23): [True: 11, False: 209]
  ------------------
  163|     11|                     return;
  164|     11|                  }
  165|    209|                  skip_whitespace();
  166|    209|                  break;
  167|    220|               }
  168|    803|            }
  169|  5.12k|            case Object_Start: {
  ------------------
  |  Branch (169:13): [True: 5.12k, False: 19.0k]
  ------------------
  170|  5.12k|               if (not put('{')) [[unlikely]] {
  ------------------
  |  Branch (170:20): [True: 30, False: 5.09k]
  ------------------
  171|     30|                  return;
  172|     30|               }
  173|  5.09k|               ++it;
  174|  5.09k|               skip_expected_whitespace();
  175|  5.09k|               break;
  176|  5.12k|            }
  177|    867|            case Object_End: {
  ------------------
  |  Branch (177:13): [True: 867, False: 23.2k]
  ------------------
  178|    867|               if (not put('}')) [[unlikely]] {
  ------------------
  |  Branch (178:20): [True: 8, False: 859]
  ------------------
  179|      8|                  return;
  180|      8|               }
  181|    859|               ++it;
  182|    859|               skip_whitespace();
  183|    859|               break;
  184|    867|            }
  185|  1.60k|            case Comment: {
  ------------------
  |  Branch (185:13): [True: 1.60k, False: 22.5k]
  ------------------
  186|  1.60k|               if constexpr (Opts.comments) {
  187|  1.60k|                  const auto comment = read_jsonc_comment(ctx, it, end);
  188|  1.60k|                  if (bool(ctx.error)) [[unlikely]] {
  ------------------
  |  Branch (188:23): [True: 127, False: 1.47k]
  ------------------
  189|    127|                     return;
  190|    127|                  }
  191|       |                  // A line comment is dropped rather than written out. Minifying is what removes
  192|       |                  // the newline that ends it, and a line comment with no line break behind it
  193|       |                  // comments out the whole rest of the output.
  194|  1.47k|                  if (not comment.line) {
  ------------------
  |  Branch (194:23): [True: 452, False: 1.02k]
  ------------------
  195|       |                     // non-empty: an empty view comes with an error
  196|    452|                     if (not put(comment.text)) [[unlikely]] {
  ------------------
  |  Branch (196:26): [True: 52, False: 400]
  ------------------
  197|     52|                        return;
  198|     52|                     }
  199|    452|                  }
  200|  1.42k|                  skip_whitespace();
  201|  1.42k|                  break;
  202|       |               }
  203|       |               else {
  204|       |                  [[fallthrough]];
  205|       |               }
  206|  1.60k|            }
  207|  3.20k|            [[unlikely]] default: {
  ------------------
  |  Branch (207:26): [True: 1.60k, False: 22.5k]
  ------------------
  208|       |               // A null terminated run carries no bound in its loop condition, so it ends here, on
  209|       |               // the terminator, which is not a JSON token. Reaching it is the end of the document
  210|       |               // rather than an error -- unclassified is how the type table reports both, and
  211|       |               // without this the minifier left syntax_error behind on every input it was ever
  212|       |               // given, valid or not, which is what made its error not worth returning.
  213|       |               if constexpr (Opts.null_terminated) {
  214|       |                  if (it >= end) {
  215|       |                     return;
  216|       |                  }
  217|       |               }
  218|  3.20k|               ctx.error = error_code::syntax_error;
  219|  3.20k|               return;
  220|  1.60k|            }
  221|  24.1k|            }
  222|  24.1k|         }
  223|  3.43k|      }
_ZZN3glz6detail11minify_jsonITnDaXtlNS_4optsELj10ELb0ELb1ELb1ELb1EEETkNS_10is_contextERNS_7contextERPKcS7_RNSt3__15arrayIcLm64EEEmEEvOT0_OT1_OT2_OT3_RT4_ENKUlvE0_clEv:
   56|  9.97k|         auto skip_whitespace = [&] {
   57|       |            if constexpr (Opts.null_terminated) {
   58|       |               while (whitespace_table[uint8_t(*it)]) {
   59|       |                  ++it;
   60|       |               }
   61|       |            }
   62|  9.97k|            else {
   63|   105k|               while ((it < end) && whitespace_table[uint8_t(*it)]) {
  ------------------
  |  Branch (63:23): [True: 105k, False: 444]
  |  Branch (63:37): [True: 95.5k, False: 9.53k]
  ------------------
   64|  95.5k|                  ++it;
   65|  95.5k|               }
   66|  9.97k|            }
   67|  9.97k|         };
_ZZN3glz6detail11minify_jsonITnDaXtlNS_4optsELj10ELb0ELb1ELb1ELb1EEETkNS_10is_contextERNS_7contextERPKcS7_RNSt3__15arrayIcLm64EEEmEEvOT0_OT1_OT2_OT3_RT4_ENKUlvE1_clEv:
   71|  25.1k|         while ([&]() -> bool {
   72|       |            if constexpr (Opts.null_terminated) {
   73|       |               return true;
   74|       |            }
   75|  25.1k|            else {
   76|  25.1k|               return it < end;
   77|  25.1k|            }
   78|  25.1k|         }()) {
_ZZN3glz6detail11minify_jsonITnDaXtlNS_4optsELj10ELb0ELb1ELb1ELb1EEETkNS_10is_contextERNS_7contextERPKcS7_RNSt3__15arrayIcLm64EEEmEEvOT0_OT1_OT2_OT3_RT4_ENKUlRKT_E_clINS8_17basic_string_viewIcNS8_11char_traitsIcEEEEEEDaSO_:
   31|  2.16k|         const auto put = [&](const auto& x) { return emit_bytes<false>(ctx, b, ix, x); };
_ZZN3glz6detail11minify_jsonITnDaXtlNS_4optsELj10ELb0ELb1ELb1ELb1EEETkNS_10is_contextERNS_7contextERPKcS7_RNSt3__15arrayIcLm64EEEmEEvOT0_OT1_OT2_OT3_RT4_ENKUlRKT_E_clIcEEDaSO_:
   31|  17.9k|         const auto put = [&](const auto& x) { return emit_bytes<false>(ctx, b, ix, x); };
_ZZN3glz6detail11minify_jsonITnDaXtlNS_4optsELj10ELb0ELb1ELb1ELb1EEETkNS_10is_contextERNS_7contextERPKcS7_RNSt3__15arrayIcLm64EEEmEEvOT0_OT1_OT2_OT3_RT4_ENKUlvE_clEv:
   36|  15.1k|         auto skip_expected_whitespace = [&] {
   37|  15.1k|            auto new_ws_start = it;
   38|  15.1k|            if (ws_size && std::ptrdiff_t(ws_size) < end - it) [[likely]] {
  ------------------
  |  Branch (38:17): [True: 10.4k, False: 4.75k]
  |  Branch (38:28): [True: 9.19k, False: 1.21k]
  ------------------
   39|  9.19k|               skip_matching_ws(ws_start, it, ws_size);
   40|  9.19k|            }
   41|       |
   42|       |            if constexpr (Opts.null_terminated) {
   43|       |               while (whitespace_table[uint8_t(*it)]) {
   44|       |                  ++it;
   45|       |               }
   46|       |            }
   47|  15.1k|            else {
   48|  19.2M|               while ((it < end) && whitespace_table[uint8_t(*it)]) {
  ------------------
  |  Branch (48:23): [True: 19.2M, False: 545]
  |  Branch (48:37): [True: 19.2M, False: 14.6k]
  ------------------
   49|  19.2M|                  ++it;
   50|  19.2M|               }
   51|  15.1k|            }
   52|  15.1k|            ws_start = new_ws_start;
   53|  15.1k|            ws_size = size_t(it - new_ws_start);
   54|  15.1k|         };
_ZZN3glz6detail11minify_jsonITnDaXtlNS_4optsELj10ELb0ELb1ELb1ELb1EEETkNS_10is_contextERNS_7contextERPKcS7_RNSt3__15arrayIcLm64EEEmEEvOT0_OT1_OT2_OT3_RT4_ENKUlRKT_E_clIA5_cEEDaSO_:
   31|    672|         const auto put = [&](const auto& x) { return emit_bytes<false>(ctx, b, ix, x); };
_ZZN3glz6detail11minify_jsonITnDaXtlNS_4optsELj10ELb0ELb1ELb1ELb1EEETkNS_10is_contextERNS_7contextERPKcS7_RNSt3__15arrayIcLm64EEEmEEvOT0_OT1_OT2_OT3_RT4_ENKUlRKT_E_clIA6_cEEDaSO_:
   31|    220|         const auto put = [&](const auto& x) { return emit_bytes<false>(ctx, b, ix, x); };

_ZN3glz9has_quoteEm:
   86|  5.08M|   {
   87|  5.08M|      return has_zero(chunk ^ repeat_byte8('"'));
   88|  5.08M|   }
_ZN3glz8has_zeroEm:
   81|  8.44M|   {
   82|  8.44M|      return (((chunk - 0x0101010101010101ull) & ~chunk) & 0x8080808080808080ull);
   83|  8.44M|   }
_ZN3glz11countr_zeroEm:
   29|  30.9k|   {
   30|       |#ifdef _MSC_VER
   31|       |      return std::countr_zero(x);
   32|       |#else
   33|  30.9k|#if __has_builtin(__builtin_ctzll)
   34|  30.9k|      return __builtin_ctzll(x);
   35|       |#else
   36|       |      return std::countr_zero(x);
   37|       |#endif
   38|  30.9k|#endif
   39|  30.9k|   }
_ZN3glz8has_charILc47EEEmm:
  102|  3.36M|   {
  103|  3.36M|      return has_zero(chunk ^ repeat_byte8(Char));
  104|  3.36M|   }

_ZN3glz10comparitorIL_ZZNS_6detail13match_literalITnNS_14string_literalEXtlNS3_ILm5EEEtlA5_cLc110ELc117ELc108ELc108EEEETkNS_10is_contextERNS_7contextERPKcS9_EEbOT0_OT1_T2_E1sELm4EcEEbPKSD_:
  245|  3.38k|   {
  246|       |      // pack() builds values in little-endian order (byte 0 in LSB position).
  247|       |      // On big-endian systems, memcpy produces native (big-endian) values,
  248|       |      // so we need to byteswap to match the packed representation.
  249|       |      if constexpr (N == 8) {
  250|       |         static constexpr auto packed = pack<Str, 8>();
  251|       |         uint64_t in;
  252|       |         std::memcpy(&in, other, 8);
  253|       |         if constexpr (std::endian::native == std::endian::big) {
  254|       |            in = std::byteswap(in);
  255|       |         }
  256|       |         return (in == packed);
  257|       |      }
  258|       |      else if constexpr (N == 7) {
  259|       |         static constexpr auto packed = pack_buffered<Str, 8>();
  260|       |         uint64_t in{};
  261|       |         std::memcpy(&in, other, 7);
  262|       |         if constexpr (std::endian::native == std::endian::big) {
  263|       |            in = std::byteswap(in);
  264|       |         }
  265|       |         return (in == packed);
  266|       |      }
  267|       |      else if constexpr (N == 6) {
  268|       |         static constexpr auto packed = pack_buffered<Str, 8>();
  269|       |         uint64_t in{};
  270|       |         std::memcpy(&in, other, 6);
  271|       |         if constexpr (std::endian::native == std::endian::big) {
  272|       |            in = std::byteswap(in);
  273|       |         }
  274|       |         return (in == packed);
  275|       |      }
  276|       |      else if constexpr (N == 5) {
  277|       |         static constexpr auto packed = pack<Str, 4>();
  278|       |         uint32_t in;
  279|       |         std::memcpy(&in, other, 4);
  280|       |         if constexpr (std::endian::native == std::endian::big) {
  281|       |            in = std::byteswap(in);
  282|       |         }
  283|       |         return (in == packed) & (Str[4] == other[4]);
  284|       |      }
  285|  3.38k|      else if constexpr (N == 4) {
  286|  3.38k|         static constexpr auto packed = pack<Str, 4>();
  287|  3.38k|         uint32_t in;
  288|  3.38k|         std::memcpy(&in, other, 4);
  289|       |         if constexpr (std::endian::native == std::endian::big) {
  290|       |            in = std::byteswap(in);
  291|       |         }
  292|  3.38k|         return (in == packed);
  293|       |      }
  294|       |      else if constexpr (N == 3) {
  295|       |         static constexpr auto packed = pack<Str, 2>();
  296|       |         uint16_t in;
  297|       |         std::memcpy(&in, other, 2);
  298|       |         if constexpr (std::endian::native == std::endian::big) {
  299|       |            in = std::byteswap(in);
  300|       |         }
  301|       |         return (in == packed) & (Str[2] == other[2]);
  302|       |      }
  303|       |      else if constexpr (N == 2) {
  304|       |         static constexpr auto packed = pack<Str, 2>();
  305|       |         uint16_t in;
  306|       |         std::memcpy(&in, other, 2);
  307|       |         if constexpr (std::endian::native == std::endian::big) {
  308|       |            in = std::byteswap(in);
  309|       |         }
  310|       |         return (in == packed);
  311|       |      }
  312|       |      else if constexpr (N == 1) {
  313|       |         return Str[0] == other[0];
  314|       |      }
  315|       |      else if constexpr (N == 0) {
  316|       |         return true;
  317|       |      }
  318|       |      else {
  319|       |         // Clang and GCC optimize this extremely well for constexpr std::string_view
  320|       |         // Packing data can create more binary on GCC
  321|       |         // The other cases probably aren't needed as compiler explorer shows them optimized equally well as memcmp
  322|       |         return 0 == std::memcmp(Str.data(), other, N);
  323|       |      }
  324|  3.38k|   }
_ZN3glz10comparitorIL_ZZNS_6detail13match_literalITnNS_14string_literalEXtlNS3_ILm5EEEtlA5_cLc116ELc114ELc117ELc101EEEETkNS_10is_contextERNS_7contextERPKcS9_EEbOT0_OT1_T2_E1sELm4EcEEbPKSD_:
  245|  4.43k|   {
  246|       |      // pack() builds values in little-endian order (byte 0 in LSB position).
  247|       |      // On big-endian systems, memcpy produces native (big-endian) values,
  248|       |      // so we need to byteswap to match the packed representation.
  249|       |      if constexpr (N == 8) {
  250|       |         static constexpr auto packed = pack<Str, 8>();
  251|       |         uint64_t in;
  252|       |         std::memcpy(&in, other, 8);
  253|       |         if constexpr (std::endian::native == std::endian::big) {
  254|       |            in = std::byteswap(in);
  255|       |         }
  256|       |         return (in == packed);
  257|       |      }
  258|       |      else if constexpr (N == 7) {
  259|       |         static constexpr auto packed = pack_buffered<Str, 8>();
  260|       |         uint64_t in{};
  261|       |         std::memcpy(&in, other, 7);
  262|       |         if constexpr (std::endian::native == std::endian::big) {
  263|       |            in = std::byteswap(in);
  264|       |         }
  265|       |         return (in == packed);
  266|       |      }
  267|       |      else if constexpr (N == 6) {
  268|       |         static constexpr auto packed = pack_buffered<Str, 8>();
  269|       |         uint64_t in{};
  270|       |         std::memcpy(&in, other, 6);
  271|       |         if constexpr (std::endian::native == std::endian::big) {
  272|       |            in = std::byteswap(in);
  273|       |         }
  274|       |         return (in == packed);
  275|       |      }
  276|       |      else if constexpr (N == 5) {
  277|       |         static constexpr auto packed = pack<Str, 4>();
  278|       |         uint32_t in;
  279|       |         std::memcpy(&in, other, 4);
  280|       |         if constexpr (std::endian::native == std::endian::big) {
  281|       |            in = std::byteswap(in);
  282|       |         }
  283|       |         return (in == packed) & (Str[4] == other[4]);
  284|       |      }
  285|  4.43k|      else if constexpr (N == 4) {
  286|  4.43k|         static constexpr auto packed = pack<Str, 4>();
  287|  4.43k|         uint32_t in;
  288|  4.43k|         std::memcpy(&in, other, 4);
  289|       |         if constexpr (std::endian::native == std::endian::big) {
  290|       |            in = std::byteswap(in);
  291|       |         }
  292|  4.43k|         return (in == packed);
  293|       |      }
  294|       |      else if constexpr (N == 3) {
  295|       |         static constexpr auto packed = pack<Str, 2>();
  296|       |         uint16_t in;
  297|       |         std::memcpy(&in, other, 2);
  298|       |         if constexpr (std::endian::native == std::endian::big) {
  299|       |            in = std::byteswap(in);
  300|       |         }
  301|       |         return (in == packed) & (Str[2] == other[2]);
  302|       |      }
  303|       |      else if constexpr (N == 2) {
  304|       |         static constexpr auto packed = pack<Str, 2>();
  305|       |         uint16_t in;
  306|       |         std::memcpy(&in, other, 2);
  307|       |         if constexpr (std::endian::native == std::endian::big) {
  308|       |            in = std::byteswap(in);
  309|       |         }
  310|       |         return (in == packed);
  311|       |      }
  312|       |      else if constexpr (N == 1) {
  313|       |         return Str[0] == other[0];
  314|       |      }
  315|       |      else if constexpr (N == 0) {
  316|       |         return true;
  317|       |      }
  318|       |      else {
  319|       |         // Clang and GCC optimize this extremely well for constexpr std::string_view
  320|       |         // Packing data can create more binary on GCC
  321|       |         // The other cases probably aren't needed as compiler explorer shows them optimized equally well as memcmp
  322|       |         return 0 == std::memcmp(Str.data(), other, N);
  323|       |      }
  324|  4.43k|   }
_ZN3glz10comparitorIL_ZZNS_6detail13match_literalITnNS_14string_literalEXtlNS3_ILm6EEEtlA6_cLc102ELc97ELc108ELc115ELc101EEEETkNS_10is_contextERNS_7contextERPKcS9_EEbOT0_OT1_T2_E1sELm5EcEEbPKSD_:
  245|  3.23k|   {
  246|       |      // pack() builds values in little-endian order (byte 0 in LSB position).
  247|       |      // On big-endian systems, memcpy produces native (big-endian) values,
  248|       |      // so we need to byteswap to match the packed representation.
  249|       |      if constexpr (N == 8) {
  250|       |         static constexpr auto packed = pack<Str, 8>();
  251|       |         uint64_t in;
  252|       |         std::memcpy(&in, other, 8);
  253|       |         if constexpr (std::endian::native == std::endian::big) {
  254|       |            in = std::byteswap(in);
  255|       |         }
  256|       |         return (in == packed);
  257|       |      }
  258|       |      else if constexpr (N == 7) {
  259|       |         static constexpr auto packed = pack_buffered<Str, 8>();
  260|       |         uint64_t in{};
  261|       |         std::memcpy(&in, other, 7);
  262|       |         if constexpr (std::endian::native == std::endian::big) {
  263|       |            in = std::byteswap(in);
  264|       |         }
  265|       |         return (in == packed);
  266|       |      }
  267|       |      else if constexpr (N == 6) {
  268|       |         static constexpr auto packed = pack_buffered<Str, 8>();
  269|       |         uint64_t in{};
  270|       |         std::memcpy(&in, other, 6);
  271|       |         if constexpr (std::endian::native == std::endian::big) {
  272|       |            in = std::byteswap(in);
  273|       |         }
  274|       |         return (in == packed);
  275|       |      }
  276|  3.23k|      else if constexpr (N == 5) {
  277|  3.23k|         static constexpr auto packed = pack<Str, 4>();
  278|  3.23k|         uint32_t in;
  279|  3.23k|         std::memcpy(&in, other, 4);
  280|       |         if constexpr (std::endian::native == std::endian::big) {
  281|       |            in = std::byteswap(in);
  282|       |         }
  283|  3.23k|         return (in == packed) & (Str[4] == other[4]);
  284|       |      }
  285|       |      else if constexpr (N == 4) {
  286|       |         static constexpr auto packed = pack<Str, 4>();
  287|       |         uint32_t in;
  288|       |         std::memcpy(&in, other, 4);
  289|       |         if constexpr (std::endian::native == std::endian::big) {
  290|       |            in = std::byteswap(in);
  291|       |         }
  292|       |         return (in == packed);
  293|       |      }
  294|       |      else if constexpr (N == 3) {
  295|       |         static constexpr auto packed = pack<Str, 2>();
  296|       |         uint16_t in;
  297|       |         std::memcpy(&in, other, 2);
  298|       |         if constexpr (std::endian::native == std::endian::big) {
  299|       |            in = std::byteswap(in);
  300|       |         }
  301|       |         return (in == packed) & (Str[2] == other[2]);
  302|       |      }
  303|       |      else if constexpr (N == 2) {
  304|       |         static constexpr auto packed = pack<Str, 2>();
  305|       |         uint16_t in;
  306|       |         std::memcpy(&in, other, 2);
  307|       |         if constexpr (std::endian::native == std::endian::big) {
  308|       |            in = std::byteswap(in);
  309|       |         }
  310|       |         return (in == packed);
  311|       |      }
  312|       |      else if constexpr (N == 1) {
  313|       |         return Str[0] == other[0];
  314|       |      }
  315|       |      else if constexpr (N == 0) {
  316|       |         return true;
  317|       |      }
  318|       |      else {
  319|       |         // Clang and GCC optimize this extremely well for constexpr std::string_view
  320|       |         // Packing data can create more binary on GCC
  321|       |         // The other cases probably aren't needed as compiler explorer shows them optimized equally well as memcmp
  322|       |         return 0 == std::memcmp(Str.data(), other, N);
  323|       |      }
  324|  3.23k|   }

_ZN3glz4dumpILb0ENSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEEEvNS1_17basic_string_viewIcS4_EERT0_Rm:
  192|  22.7k|   {
  193|  22.7k|      const auto n = str.size();
  194|  22.7k|      if constexpr (vector_like<B>) {
  195|       |         if constexpr (Checked) {
  196|       |            const auto k = ix + n;
  197|       |            if (ix + n > b.size()) [[unlikely]] {
  198|       |               grow_buffer(b, k);
  199|       |            }
  200|       |         }
  201|  22.7k|      }
  202|  22.7k|      std::memcpy(&b[ix], str.data(), n);
  203|  22.7k|      ix += n;
  204|  22.7k|   }
_ZN3glz4dumpILb0ENSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEETkNS_10byte_sizedEcEEvT1_RT0_Rm:
  150|  97.1k|   {
  151|       |      if constexpr (Checked && vector_like<B>) {
  152|       |         if (ix == b.size()) [[unlikely]] {
  153|       |            grow_buffer(b, b.size() == 0 ? 64 : ix + 1);
  154|       |         }
  155|       |      }
  156|  97.1k|      assign_maybe_cast(c, b, ix);
  157|  97.1k|      ++ix;
  158|  97.1k|   }
_ZN3glz17assign_maybe_castITkNS_10byte_sizedEcNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEEEvT_RT0_Rm:
   95|  97.1k|   {
   96|  97.1k|      using V = std::decay_t<decltype(b[0])>;
   97|  97.1k|      using C = std::decay_t<decltype(c)>;
   98|  97.1k|      if constexpr (std::same_as<V, C>) {
   99|  97.1k|         b[ix] = c;
  100|       |      }
  101|       |      else {
  102|       |         b[ix] = static_cast<V>(c);
  103|       |      }
  104|  97.1k|   }
_ZN3glz4dumpILb0ENSt3__15arrayIcLm64EEEEEvNS1_17basic_string_viewIcNS1_11char_traitsIcEEEERT0_Rm:
  192|  2.87k|   {
  193|  2.87k|      const auto n = str.size();
  194|       |      if constexpr (vector_like<B>) {
  195|       |         if constexpr (Checked) {
  196|       |            const auto k = ix + n;
  197|       |            if (ix + n > b.size()) [[unlikely]] {
  198|       |               grow_buffer(b, k);
  199|       |            }
  200|       |         }
  201|       |      }
  202|  2.87k|      std::memcpy(&b[ix], str.data(), n);
  203|  2.87k|      ix += n;
  204|  2.87k|   }
_ZN3glz4dumpILb0ENSt3__15arrayIcLm64EEETkNS_10byte_sizedEcEEvT1_RT0_Rm:
  150|  17.7k|   {
  151|       |      if constexpr (Checked && vector_like<B>) {
  152|       |         if (ix == b.size()) [[unlikely]] {
  153|       |            grow_buffer(b, b.size() == 0 ? 64 : ix + 1);
  154|       |         }
  155|       |      }
  156|  17.7k|      assign_maybe_cast(c, b, ix);
  157|  17.7k|      ++ix;
  158|  17.7k|   }
_ZN3glz17assign_maybe_castITkNS_10byte_sizedEcNSt3__15arrayIcLm64EEEEEvT_RT0_Rm:
   95|  17.7k|   {
   96|  17.7k|      using V = std::decay_t<decltype(b[0])>;
   97|  17.7k|      using C = std::decay_t<decltype(c)>;
   98|  17.7k|      if constexpr (std::same_as<V, C>) {
   99|  17.7k|         b[ix] = c;
  100|       |      }
  101|       |      else {
  102|       |         b[ix] = static_cast<V>(c);
  103|       |      }
  104|  17.7k|   }

_ZN3glz16skip_matching_wsIcRPKcEEvPKT_OT0_m:
  730|  63.7k|   {
  731|  63.7k|      if (length > 7) {
  ------------------
  |  Branch (731:11): [True: 29.8k, False: 33.8k]
  ------------------
  732|  29.8k|         uint64_t v[2];
  733|  48.9k|         while (length > 8) {
  ------------------
  |  Branch (733:17): [True: 31.1k, False: 17.8k]
  ------------------
  734|  31.1k|            std::memcpy(v, ws, 8);
  735|  31.1k|            std::memcpy(v + 1, it, 8);
  736|  31.1k|            if (v[0] != v[1]) {
  ------------------
  |  Branch (736:17): [True: 12.0k, False: 19.1k]
  ------------------
  737|  12.0k|               return;
  738|  12.0k|            }
  739|  19.1k|            length -= 8;
  740|  19.1k|            ws += 8;
  741|  19.1k|            it += 8;
  742|  19.1k|         }
  743|       |
  744|  17.8k|         const auto shift = 8 - length;
  745|  17.8k|         ws -= shift;
  746|  17.8k|         it -= shift;
  747|       |
  748|  17.8k|         std::memcpy(v, ws, 8);
  749|  17.8k|         std::memcpy(v + 1, it, 8);
  750|  17.8k|         if (v[0] != v[1]) {
  ------------------
  |  Branch (750:14): [True: 7.67k, False: 10.1k]
  ------------------
  751|  7.67k|            return;
  752|  7.67k|         }
  753|  10.1k|         it += 8;
  754|  10.1k|         return;
  755|  17.8k|      }
  756|  33.8k|      {
  757|  33.8k|         constexpr uint64_t n{sizeof(uint32_t)};
  758|  33.8k|         if (length >= n) {
  ------------------
  |  Branch (758:14): [True: 15.0k, False: 18.8k]
  ------------------
  759|  15.0k|            uint32_t v[2];
  760|  15.0k|            std::memcpy(v, ws, n);
  761|  15.0k|            std::memcpy(v + 1, it, n);
  762|  15.0k|            if (v[0] != v[1]) {
  ------------------
  |  Branch (762:17): [True: 8.24k, False: 6.77k]
  ------------------
  763|  8.24k|               return;
  764|  8.24k|            }
  765|  6.77k|            length -= n;
  766|  6.77k|            ws += n;
  767|  6.77k|            it += n;
  768|  6.77k|         }
  769|  33.8k|      }
  770|  25.6k|      {
  771|  25.6k|         constexpr uint64_t n{sizeof(uint16_t)};
  772|  25.6k|         if (length >= n) {
  ------------------
  |  Branch (772:14): [True: 12.5k, False: 13.0k]
  ------------------
  773|  12.5k|            uint16_t v[2];
  774|  12.5k|            std::memcpy(v, ws, n);
  775|  12.5k|            std::memcpy(v + 1, it, n);
  776|  12.5k|            if (v[0] != v[1]) {
  ------------------
  |  Branch (776:17): [True: 7.03k, False: 5.56k]
  ------------------
  777|  7.03k|               return;
  778|  7.03k|            }
  779|       |            // length -= n;
  780|       |            // ws += n;
  781|  5.56k|            it += n;
  782|  5.56k|         }
  783|  25.6k|      }
  784|       |      // We have to call a whitespace check after this function
  785|       |      // in case the whitespace is mismatching.
  786|       |      // So, we forgo this check as to not duplicate.
  787|       |      /*if (length && *ws == *it) {
  788|       |         ++it;
  789|       |      }*/
  790|  25.6k|   }

