LLVMFuzzerTestOneInput:
  164|  4.04k|extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
  165|  4.04k|  constexpr auto optionbytes = 4u;
  166|  4.04k|  static_assert(optionbytes % 2 == 0,
  167|  4.04k|                "optionbytes must be even to avoid misaligned char16 pointers");
  168|  4.04k|  if (size < optionbytes) {
  ------------------
  |  Branch (168:7): [True: 2, False: 4.04k]
  ------------------
  169|      2|    return 0;
  170|      2|  }
  171|       |
  172|  4.04k|  constexpr auto Ncases = 2u;
  173|  4.04k|  constexpr auto actionmask = std::bit_ceil(Ncases) - 1;
  174|  4.04k|  const auto action = data[0] & actionmask;
  175|       |
  176|  4.04k|  const auto opt = [](auto index) {
  177|  4.04k|    if (index >= options.size()) {
  178|  4.04k|      return options[0];
  179|  4.04k|    }
  180|  4.04k|    return options[index];
  181|  4.04k|  }(data[1] & (std::bit_ceil(options.size()) - 1));
  182|       |
  183|  4.04k|  const auto lco =
  184|  4.04k|      (opt == simdutf::base64_url || opt == simdutf::base64_default_no_padding)
  ------------------
  |  Branch (184:8): [True: 681, False: 3.36k]
  |  Branch (184:38): [True: 383, False: 2.97k]
  ------------------
  185|  4.04k|          ? simdutf::last_chunk_handling_options::loose
  186|  4.04k|          : [](auto index) {
  187|  2.97k|              if (index >= last_chunk.size()) {
  188|  2.97k|                return last_chunk[0];
  189|  2.97k|              }
  190|  2.97k|              return last_chunk[index];
  191|  2.97k|            }(data[2] & (std::bit_ceil(last_chunk.size()) - 1));
  192|       |
  193|       |  // data[3] reserved for future use / alignment.
  194|       |
  195|  4.04k|  data += optionbytes;
  196|  4.04k|  size -= optionbytes;
  197|       |
  198|  4.04k|  switch (action) {
  ------------------
  |  Branch (198:11): [True: 4.04k, False: 0]
  ------------------
  199|  2.03k|  case 0: {
  ------------------
  |  Branch (199:3): [True: 2.03k, False: 2.00k]
  ------------------
  200|  2.03k|    const std::span<const char> chardata{reinterpret_cast<const char*>(data),
  201|  2.03k|                                         size};
  202|  2.03k|    test_details(chardata, opt, lco);
  203|  2.03k|  } break;
  204|  2.00k|  case 1: {
  ------------------
  |  Branch (204:3): [True: 2.00k, False: 2.03k]
  ------------------
  205|  2.00k|    const std::span<const char16_t> chardata{
  206|  2.00k|        reinterpret_cast<const char16_t*>(data), size / sizeof(char16_t)};
  207|  2.00k|    test_details(chardata, opt, lco);
  208|  2.00k|  } break;
  209|  4.04k|  }
  210|       |
  211|  4.04k|  return 0;
  212|  4.04k|}
base64_details.cpp:_ZZ22LLVMFuzzerTestOneInputENK3$_0clImEEDaT_:
  176|  4.04k|  const auto opt = [](auto index) {
  177|  4.04k|    if (index >= options.size()) {
  ------------------
  |  Branch (177:9): [True: 0, False: 4.04k]
  ------------------
  178|      0|      return options[0];
  179|      0|    }
  180|  4.04k|    return options[index];
  181|  4.04k|  }(data[1] & (std::bit_ceil(options.size()) - 1));
base64_details.cpp:_ZZ22LLVMFuzzerTestOneInputENK3$_1clImEEDaT_:
  186|  2.97k|          : [](auto index) {
  187|  2.97k|              if (index >= last_chunk.size()) {
  ------------------
  |  Branch (187:19): [True: 338, False: 2.63k]
  ------------------
  188|    338|                return last_chunk[0];
  189|    338|              }
  190|  2.63k|              return last_chunk[index];
  191|  2.97k|            }(data[2] & (std::bit_ceil(last_chunk.size()) - 1));
base64_details.cpp:_ZL12test_detailsIcEvNSt3__14spanIKT_Lm18446744073709551615EEEN7simdutf14base64_optionsENS5_27last_chunk_handling_optionsE:
   57|  2.03k|                         simdutf::last_chunk_handling_options lco) {
   58|  2.03k|  const auto implementations = get_supported_implementations();
   59|  2.03k|  if (implementations.empty()) {
  ------------------
  |  Branch (59:7): [True: 0, False: 2.03k]
  ------------------
   60|      0|    return;
   61|      0|  }
   62|       |
   63|  2.03k|  std::vector<comparable_full_result> results;
   64|  2.03k|  results.reserve(implementations.size());
   65|       |
   66|  6.11k|  for (auto impl : implementations) {
  ------------------
  |  Branch (66:18): [True: 6.11k, False: 2.03k]
  ------------------
   67|       |    // Use a fresh buffer for base64_to_binary_details.
   68|  6.11k|    const std::size_t maxbinary =
   69|  6.11k|        impl->maximal_binary_length_from_base64(input.data(), input.size());
   70|  6.11k|    std::vector<char> out_details(maxbinary);
   71|       |
   72|  6.11k|    const simdutf::full_result fr = impl->base64_to_binary_details(
   73|  6.11k|        input.data(), input.size(), out_details.data(), opt, lco);
   74|       |
   75|       |    // Bounds checks.
   76|  6.11k|    if (fr.input_count > input.size()) {
  ------------------
  |  Branch (76:9): [True: 0, False: 6.11k]
  ------------------
   77|      0|      std::cerr << "base64_to_binary_details: input_count=" << fr.input_count
   78|      0|                << " > input.size()=" << input.size()
   79|      0|                << " impl=" << impl->name() << "\n";
   80|      0|      std::abort();
   81|      0|    }
   82|  6.11k|    if (fr.output_count > maxbinary) {
  ------------------
  |  Branch (82:9): [True: 0, False: 6.11k]
  ------------------
   83|      0|      std::cerr << "base64_to_binary_details: output_count=" << fr.output_count
   84|      0|                << " > maxbinary=" << maxbinary << " impl=" << impl->name()
   85|      0|                << "\n";
   86|      0|      std::abort();
   87|      0|    }
   88|       |
   89|       |    // Consistency check: full_result cast to result must equal
   90|       |    // base64_to_binary.
   91|  6.11k|    std::vector<char> out_plain(maxbinary);
   92|  6.11k|    const simdutf::result r = impl->base64_to_binary(
   93|  6.11k|        input.data(), input.size(), out_plain.data(), opt, lco);
   94|  6.11k|    const simdutf::result r_from_fr = static_cast<simdutf::result>(fr);
   95|       |
   96|  6.11k|    if (r != r_from_fr) {
  ------------------
  |  Branch (96:9): [True: 0, False: 6.11k]
  ------------------
   97|      0|      std::cerr << "base64_to_binary_details vs base64_to_binary inconsistency"
   98|      0|                << " impl=" << impl->name()
   99|      0|                << " base64_to_binary=[error=" << r.error
  100|      0|                << " count=" << r.count << "]"
  101|      0|                << " full_result cast=[error=" << r_from_fr.error
  102|      0|                << " count=" << r_from_fr.count << "]\n";
  103|      0|      std::abort();
  104|      0|    }
  105|       |
  106|       |    // On success, output bytes from both functions must match.
  107|  6.11k|    if (fr.error == simdutf::error_code::SUCCESS) {
  ------------------
  |  Branch (107:9): [True: 2.23k, False: 3.87k]
  ------------------
  108|  2.23k|      if (fr.output_count != r.count) {
  ------------------
  |  Branch (108:11): [True: 0, False: 2.23k]
  ------------------
  109|      0|        std::cerr << "base64_to_binary_details: SUCCESS but output_count="
  110|      0|                  << fr.output_count << " != r.count=" << r.count
  111|      0|                  << " impl=" << impl->name() << "\n";
  112|      0|        std::abort();
  113|      0|      }
  114|  2.23k|      const auto span_details =
  115|  2.23k|          std::span(out_details).subspan(0, fr.output_count);
  116|  2.23k|      const auto span_plain = std::span(out_plain).subspan(0, r.count);
  117|  2.23k|      if (!std::ranges::equal(span_details, span_plain)) {
  ------------------
  |  Branch (117:11): [True: 0, False: 2.23k]
  ------------------
  118|      0|        std::cerr << "base64_to_binary_details: output bytes differ from "
  119|      0|                     "base64_to_binary on SUCCESS"
  120|      0|                  << " impl=" << impl->name() << "\n";
  121|      0|        std::abort();
  122|      0|      }
  123|  2.23k|    }
  124|       |
  125|       |    // Store result for cross-implementation comparison.
  126|       |    //
  127|       |    // output_count on error is implementation-defined: SIMD implementations
  128|       |    // process input in different chunk widths and may write different numbers
  129|       |    // of output bytes before detecting an invalid character. Only compare
  130|       |    // output_count (and output_hash) when the conversion succeeds.
  131|       |    //
  132|       |    // input_count on success is also implementation-defined: with
  133|       |    // stop_before_partial and trailing ignored whitespace, some implementations
  134|       |    // include the trailing whitespace in input_count and others do not. The
  135|       |    // full_result::operator result() cast only uses output_count on success
  136|       |    // (input_count is not part of the base contract there). Only compare
  137|       |    // input_count when the conversion fails, where it carries the error
  138|       |    // position (which must be deterministic).
  139|  6.11k|    comparable_full_result cfr;
  140|  6.11k|    cfr.error = fr.error;
  141|  6.11k|    cfr.padding_error = fr.padding_error;
  142|  6.11k|    if (fr.error == simdutf::error_code::SUCCESS) {
  ------------------
  |  Branch (142:9): [True: 2.23k, False: 3.87k]
  ------------------
  143|  2.23k|      cfr.output_count = fr.output_count;
  144|  2.23k|      cfr.output_hash = FNV1A_hash::as_str(
  145|  2.23k|          std::span(out_details).subspan(0, fr.output_count));
  146|  3.87k|    } else {
  147|  3.87k|      cfr.input_count = fr.input_count;
  148|  3.87k|    }
  149|  6.11k|    results.push_back(std::move(cfr));
  150|  6.11k|  }
  151|       |
  152|       |  // All implementations must agree on the full_result.
  153|  2.03k|  auto neq = [](const auto& a, const auto& b) { return a != b; };
  154|  2.03k|  if (std::ranges::adjacent_find(results, neq) != results.end()) {
  ------------------
  |  Branch (154:7): [True: 0, False: 2.03k]
  ------------------
  155|      0|    std::cerr << "base64_to_binary_details: implementations disagree\n";
  156|      0|    for (std::size_t i = 0; i < implementations.size(); ++i) {
  ------------------
  |  Branch (156:29): [True: 0, False: 0]
  ------------------
  157|      0|      std::cerr << "  " << implementations[i]->name() << ": " << results[i]
  158|      0|                << "\n";
  159|      0|    }
  160|      0|    std::abort();
  161|      0|  }
  162|  2.03k|}
base64_details.cpp:_ZZL12test_detailsIcEvNSt3__14spanIKT_Lm18446744073709551615EEEN7simdutf14base64_optionsENS5_27last_chunk_handling_optionsEENKUlRS3_RKT0_E_clI22comparable_full_resultSE_EEDaS8_SB_:
  153|  4.07k|  auto neq = [](const auto& a, const auto& b) { return a != b; };
base64_details.cpp:_ZL12test_detailsIDsEvNSt3__14spanIKT_Lm18446744073709551615EEEN7simdutf14base64_optionsENS5_27last_chunk_handling_optionsE:
   57|  2.00k|                         simdutf::last_chunk_handling_options lco) {
   58|  2.00k|  const auto implementations = get_supported_implementations();
   59|  2.00k|  if (implementations.empty()) {
  ------------------
  |  Branch (59:7): [True: 0, False: 2.00k]
  ------------------
   60|      0|    return;
   61|      0|  }
   62|       |
   63|  2.00k|  std::vector<comparable_full_result> results;
   64|  2.00k|  results.reserve(implementations.size());
   65|       |
   66|  6.01k|  for (auto impl : implementations) {
  ------------------
  |  Branch (66:18): [True: 6.01k, False: 2.00k]
  ------------------
   67|       |    // Use a fresh buffer for base64_to_binary_details.
   68|  6.01k|    const std::size_t maxbinary =
   69|  6.01k|        impl->maximal_binary_length_from_base64(input.data(), input.size());
   70|  6.01k|    std::vector<char> out_details(maxbinary);
   71|       |
   72|  6.01k|    const simdutf::full_result fr = impl->base64_to_binary_details(
   73|  6.01k|        input.data(), input.size(), out_details.data(), opt, lco);
   74|       |
   75|       |    // Bounds checks.
   76|  6.01k|    if (fr.input_count > input.size()) {
  ------------------
  |  Branch (76:9): [True: 0, False: 6.01k]
  ------------------
   77|      0|      std::cerr << "base64_to_binary_details: input_count=" << fr.input_count
   78|      0|                << " > input.size()=" << input.size()
   79|      0|                << " impl=" << impl->name() << "\n";
   80|      0|      std::abort();
   81|      0|    }
   82|  6.01k|    if (fr.output_count > maxbinary) {
  ------------------
  |  Branch (82:9): [True: 0, False: 6.01k]
  ------------------
   83|      0|      std::cerr << "base64_to_binary_details: output_count=" << fr.output_count
   84|      0|                << " > maxbinary=" << maxbinary << " impl=" << impl->name()
   85|      0|                << "\n";
   86|      0|      std::abort();
   87|      0|    }
   88|       |
   89|       |    // Consistency check: full_result cast to result must equal
   90|       |    // base64_to_binary.
   91|  6.01k|    std::vector<char> out_plain(maxbinary);
   92|  6.01k|    const simdutf::result r = impl->base64_to_binary(
   93|  6.01k|        input.data(), input.size(), out_plain.data(), opt, lco);
   94|  6.01k|    const simdutf::result r_from_fr = static_cast<simdutf::result>(fr);
   95|       |
   96|  6.01k|    if (r != r_from_fr) {
  ------------------
  |  Branch (96:9): [True: 0, False: 6.01k]
  ------------------
   97|      0|      std::cerr << "base64_to_binary_details vs base64_to_binary inconsistency"
   98|      0|                << " impl=" << impl->name()
   99|      0|                << " base64_to_binary=[error=" << r.error
  100|      0|                << " count=" << r.count << "]"
  101|      0|                << " full_result cast=[error=" << r_from_fr.error
  102|      0|                << " count=" << r_from_fr.count << "]\n";
  103|      0|      std::abort();
  104|      0|    }
  105|       |
  106|       |    // On success, output bytes from both functions must match.
  107|  6.01k|    if (fr.error == simdutf::error_code::SUCCESS) {
  ------------------
  |  Branch (107:9): [True: 1.74k, False: 4.26k]
  ------------------
  108|  1.74k|      if (fr.output_count != r.count) {
  ------------------
  |  Branch (108:11): [True: 0, False: 1.74k]
  ------------------
  109|      0|        std::cerr << "base64_to_binary_details: SUCCESS but output_count="
  110|      0|                  << fr.output_count << " != r.count=" << r.count
  111|      0|                  << " impl=" << impl->name() << "\n";
  112|      0|        std::abort();
  113|      0|      }
  114|  1.74k|      const auto span_details =
  115|  1.74k|          std::span(out_details).subspan(0, fr.output_count);
  116|  1.74k|      const auto span_plain = std::span(out_plain).subspan(0, r.count);
  117|  1.74k|      if (!std::ranges::equal(span_details, span_plain)) {
  ------------------
  |  Branch (117:11): [True: 0, False: 1.74k]
  ------------------
  118|      0|        std::cerr << "base64_to_binary_details: output bytes differ from "
  119|      0|                     "base64_to_binary on SUCCESS"
  120|      0|                  << " impl=" << impl->name() << "\n";
  121|      0|        std::abort();
  122|      0|      }
  123|  1.74k|    }
  124|       |
  125|       |    // Store result for cross-implementation comparison.
  126|       |    //
  127|       |    // output_count on error is implementation-defined: SIMD implementations
  128|       |    // process input in different chunk widths and may write different numbers
  129|       |    // of output bytes before detecting an invalid character. Only compare
  130|       |    // output_count (and output_hash) when the conversion succeeds.
  131|       |    //
  132|       |    // input_count on success is also implementation-defined: with
  133|       |    // stop_before_partial and trailing ignored whitespace, some implementations
  134|       |    // include the trailing whitespace in input_count and others do not. The
  135|       |    // full_result::operator result() cast only uses output_count on success
  136|       |    // (input_count is not part of the base contract there). Only compare
  137|       |    // input_count when the conversion fails, where it carries the error
  138|       |    // position (which must be deterministic).
  139|  6.01k|    comparable_full_result cfr;
  140|  6.01k|    cfr.error = fr.error;
  141|  6.01k|    cfr.padding_error = fr.padding_error;
  142|  6.01k|    if (fr.error == simdutf::error_code::SUCCESS) {
  ------------------
  |  Branch (142:9): [True: 1.74k, False: 4.26k]
  ------------------
  143|  1.74k|      cfr.output_count = fr.output_count;
  144|  1.74k|      cfr.output_hash = FNV1A_hash::as_str(
  145|  1.74k|          std::span(out_details).subspan(0, fr.output_count));
  146|  4.26k|    } else {
  147|  4.26k|      cfr.input_count = fr.input_count;
  148|  4.26k|    }
  149|  6.01k|    results.push_back(std::move(cfr));
  150|  6.01k|  }
  151|       |
  152|       |  // All implementations must agree on the full_result.
  153|  2.00k|  auto neq = [](const auto& a, const auto& b) { return a != b; };
  154|  2.00k|  if (std::ranges::adjacent_find(results, neq) != results.end()) {
  ------------------
  |  Branch (154:7): [True: 0, False: 2.00k]
  ------------------
  155|      0|    std::cerr << "base64_to_binary_details: implementations disagree\n";
  156|      0|    for (std::size_t i = 0; i < implementations.size(); ++i) {
  ------------------
  |  Branch (156:29): [True: 0, False: 0]
  ------------------
  157|      0|      std::cerr << "  " << implementations[i]->name() << ": " << results[i]
  158|      0|                << "\n";
  159|      0|    }
  160|      0|    std::abort();
  161|      0|  }
  162|  2.00k|}
base64_details.cpp:_ZZL12test_detailsIDsEvNSt3__14spanIKT_Lm18446744073709551615EEEN7simdutf14base64_optionsENS5_27last_chunk_handling_optionsEENKUlRS3_RKT0_E_clI22comparable_full_resultSE_EEDaS8_SB_:
  153|  4.00k|  auto neq = [](const auto& a, const auto& b) { return a != b; };

_Z29get_supported_implementationsv:
   26|  4.04k|get_supported_implementations() {
   27|  4.04k|  static const auto impl = []() -> auto {
   28|  4.04k|    std::vector<const simdutf::implementation*> ret;
   29|  4.04k|    for (auto e : simdutf::get_available_implementations()) {
   30|  4.04k|      std::cerr << "implementation " << e->name() << " is available? "
   31|  4.04k|                << e->supported_by_runtime_system() << '\n';
   32|  4.04k|      if (e->supported_by_runtime_system()) {
   33|  4.04k|        ret.push_back(e);
   34|  4.04k|      }
   35|  4.04k|    }
   36|  4.04k|    return ret;
   37|  4.04k|  }();
   38|  4.04k|  return {impl.data(), impl.size()};
   39|  4.04k|}
_ZZ29get_supported_implementationsvENKUlvE_clEv:
   27|      1|  static const auto impl = []() -> auto {
   28|      1|    std::vector<const simdutf::implementation*> ret;
   29|      4|    for (auto e : simdutf::get_available_implementations()) {
  ------------------
  |  Branch (29:17): [True: 4, False: 1]
  ------------------
   30|      4|      std::cerr << "implementation " << e->name() << " is available? "
   31|      4|                << e->supported_by_runtime_system() << '\n';
   32|      4|      if (e->supported_by_runtime_system()) {
  ------------------
  |  Branch (32:11): [True: 3, False: 1]
  ------------------
   33|      3|        ret.push_back(e);
   34|      3|      }
   35|      4|    }
   36|      1|    return ret;
   37|      1|  }();
_ZneRKN7simdutf6resultES2_:
   42|  12.1k|inline bool operator!=(const simdutf::result& a, const simdutf::result& b) {
   43|  12.1k|  return a.count != b.count || a.error != b.error;
  ------------------
  |  Branch (43:10): [True: 0, False: 12.1k]
  |  Branch (43:32): [True: 0, False: 12.1k]
  ------------------
   44|  12.1k|}
_ZN10FNV1A_hash6as_strIJNSt3__14spanIcLm18446744073709551615EEEEEENS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEDpRKT_:
  100|  3.98k|  template <typename... Data> static std::string as_str(const Data&... data) {
  101|  3.98k|    static_assert(sizeof...(Data) > 0, "must hash with at least one argument");
  102|  3.98k|    std::uint64_t h;
  103|       |    if constexpr (sizeof...(Data) > 1) {
  104|       |      const std::array hashes{fnv1ahash_impl(data)...};
  105|       |      const auto s = std::span(hashes);
  106|       |      h = fnv1ahash_impl(s);
  107|  3.98k|    } else {
  108|  3.98k|      h = fnv1ahash_impl(data...);
  109|  3.98k|    }
  110|  3.98k|    constexpr std::size_t expected_chars = 16;
  111|  3.98k|    std::string ret(expected_chars, '0');
  112|  3.98k|    auto c = std::to_chars(ret.data(), ret.data() + ret.size(), h, 16);
  113|  3.98k|    assert(c.ec == std::errc{});
  ------------------
  |  Branch (113:5): [True: 3.98k, False: 0]
  ------------------
  114|  3.98k|    auto nwritten = c.ptr - ret.data();
  115|  3.98k|    assert(nwritten <= expected_chars);
  ------------------
  |  Branch (115:5): [True: 3.98k, False: 0]
  ------------------
  116|  3.98k|    std::rotate(ret.data(), c.ptr, ret.data() + expected_chars);
  117|  3.98k|    return ret;
  118|  3.98k|  }
_ZN10FNV1A_hash14fnv1ahash_implENSt3__14spanIKcLm18446744073709551615EEE:
   75|  3.98k|  static constexpr std::uint64_t fnv1ahash_impl(std::span<const char> bytes) {
   76|  3.98k|    auto hash = offset;
   77|       |
   78|  28.1M|    for (auto byte : bytes) {
  ------------------
  |  Branch (78:20): [True: 28.1M, False: 3.98k]
  ------------------
   79|  28.1M|      hash ^= static_cast<unsigned char>(byte);
   80|  28.1M|      hash *= prime;
   81|  28.1M|    }
   82|       |
   83|  3.98k|    return hash;
   84|  3.98k|  }

_ZN7simdutf11full_resultC2ENS_10error_codeEmm:
  111|  23.8k|      : error{err}, input_count{pos_in}, output_count{pos_out} {}
_ZN7simdutf11full_resultC2ENS_10error_codeEmmb:
  114|    414|      : error{err}, input_count{pos_in}, output_count{pos_out},
  115|    414|        padding_error{padding_err} {}

_ZN7simdutf10is_partialENS_27last_chunk_handling_optionsE:
 4588|  28.8k|is_partial(last_chunk_handling_options options) {
 4589|  28.8k|  return (options == stop_before_partial) || (options == only_full_chunks);
  ------------------
  |  Branch (4589:10): [True: 14.5k, False: 14.3k]
  |  Branch (4589:46): [True: 0, False: 14.3k]
  ------------------
 4590|  28.8k|}
_ZNK7simdutf14implementation4nameEv:
 5562|      4|  virtual std::string_view name() const noexcept { return _name; }
_ZNK7simdutf14implementation25required_instruction_setsEv:
 5613|      8|  virtual uint32_t required_instruction_sets() const {
 5614|      8|    return _required_instruction_sets;
 5615|      8|  }
_ZN7simdutf14implementationC2EPKcS2_j:
 7514|      4|      : _name(name), _description(description),
 7515|      4|        _required_instruction_sets(required_instruction_sets) {}
_ZN7simdutf8internal29available_implementation_listC2Ev:
 7546|      1|  simdutf_really_inline available_implementation_list() {}
_ZN7simdutf16base64_ignorableEcNS_14base64_optionsE:
 5314|  20.5k|base64_ignorable(char input, base64_options options = base64_default) noexcept {
 5315|  20.5k|  return scalar::base64::is_ignorable(input, options);
 5316|  20.5k|}
_ZN7simdutf16base64_ignorableEDsNS_14base64_optionsE:
 5319|  27.1k|                 base64_options options = base64_default) noexcept {
 5320|  27.1k|  return scalar::base64::is_ignorable(input, options);
 5321|  27.1k|}

simdutf.cpp:_ZN7simdutf8internalL30detect_supported_architecturesEv:
  301|      8|static inline uint32_t detect_supported_architectures() {
  302|      8|  uint32_t eax;
  303|      8|  uint32_t ebx = 0;
  304|      8|  uint32_t ecx = 0;
  305|      8|  uint32_t edx = 0;
  306|      8|  uint32_t host_isa = 0x0;
  307|       |
  308|       |  // EBX for EAX=0x1
  309|      8|  eax = 0x1;
  310|      8|  cpuid(&eax, &ebx, &ecx, &edx);
  311|       |
  312|      8|  if (ecx & cpuid_bit::sse42) {
  ------------------
  |  Branch (312:7): [True: 8, False: 0]
  ------------------
  313|      8|    host_isa |= instruction_set::SSE42;
  314|      8|  }
  315|       |
  316|      8|  if (ecx & cpuid_bit::pclmulqdq) {
  ------------------
  |  Branch (316:7): [True: 8, False: 0]
  ------------------
  317|      8|    host_isa |= instruction_set::PCLMULQDQ;
  318|      8|  }
  319|       |
  320|      8|  if ((ecx & cpuid_bit::osxsave) != cpuid_bit::osxsave) {
  ------------------
  |  Branch (320:7): [True: 0, False: 8]
  ------------------
  321|      0|    return host_isa;
  322|      0|  }
  323|       |
  324|       |  // xgetbv for checking if the OS saves registers
  325|      8|  uint64_t xcr0 = xgetbv();
  326|       |
  327|      8|  if ((xcr0 & cpuid_bit::xcr0_bit::avx256_saved) == 0) {
  ------------------
  |  Branch (327:7): [True: 0, False: 8]
  ------------------
  328|      0|    return host_isa;
  329|      0|  }
  330|       |  // ECX for EAX=0x7
  331|      8|  eax = 0x7;
  332|      8|  ecx = 0x0; // Sub-leaf = 0
  333|      8|  cpuid(&eax, &ebx, &ecx, &edx);
  334|      8|  if (ebx & cpuid_bit::ebx::avx2) {
  ------------------
  |  Branch (334:7): [True: 8, False: 0]
  ------------------
  335|      8|    host_isa |= instruction_set::AVX2;
  336|      8|  }
  337|      8|  if (ebx & cpuid_bit::ebx::bmi1) {
  ------------------
  |  Branch (337:7): [True: 8, False: 0]
  ------------------
  338|      8|    host_isa |= instruction_set::BMI1;
  339|      8|  }
  340|      8|  if (ebx & cpuid_bit::ebx::bmi2) {
  ------------------
  |  Branch (340:7): [True: 8, False: 0]
  ------------------
  341|      8|    host_isa |= instruction_set::BMI2;
  342|      8|  }
  343|      8|  if (!((xcr0 & cpuid_bit::xcr0_bit::avx512_saved) ==
  ------------------
  |  Branch (343:7): [True: 8, False: 0]
  ------------------
  344|      8|        cpuid_bit::xcr0_bit::avx512_saved)) {
  345|      8|    return host_isa;
  346|      8|  }
  347|      0|  if (ebx & cpuid_bit::ebx::avx512f) {
  ------------------
  |  Branch (347:7): [True: 0, False: 0]
  ------------------
  348|      0|    host_isa |= instruction_set::AVX512F;
  349|      0|  }
  350|      0|  if (ebx & cpuid_bit::ebx::avx512bw) {
  ------------------
  |  Branch (350:7): [True: 0, False: 0]
  ------------------
  351|      0|    host_isa |= instruction_set::AVX512BW;
  352|      0|  }
  353|      0|  if (ebx & cpuid_bit::ebx::avx512cd) {
  ------------------
  |  Branch (353:7): [True: 0, False: 0]
  ------------------
  354|      0|    host_isa |= instruction_set::AVX512CD;
  355|      0|  }
  356|      0|  if (ebx & cpuid_bit::ebx::avx512dq) {
  ------------------
  |  Branch (356:7): [True: 0, False: 0]
  ------------------
  357|      0|    host_isa |= instruction_set::AVX512DQ;
  358|      0|  }
  359|      0|  if (ebx & cpuid_bit::ebx::avx512vl) {
  ------------------
  |  Branch (359:7): [True: 0, False: 0]
  ------------------
  360|      0|    host_isa |= instruction_set::AVX512VL;
  361|      0|  }
  362|      0|  if (ecx & cpuid_bit::ecx::avx512vbmi2) {
  ------------------
  |  Branch (362:7): [True: 0, False: 0]
  ------------------
  363|      0|    host_isa |= instruction_set::AVX512VBMI2;
  364|      0|  }
  365|      0|  if (ecx & cpuid_bit::ecx::avx512vpopcnt) {
  ------------------
  |  Branch (365:7): [True: 0, False: 0]
  ------------------
  366|      0|    host_isa |= instruction_set::AVX512VPOPCNTDQ;
  367|      0|  }
  368|      0|  return host_isa;
  369|      8|}
simdutf.cpp:_ZN7simdutf8internalL5cpuidEPjS1_S1_S1_:
  267|     16|                         uint32_t *edx) {
  268|       |  #if defined(_MSC_VER)
  269|       |  int cpu_info[4];
  270|       |  __cpuidex(cpu_info, *eax, *ecx);
  271|       |  *eax = cpu_info[0];
  272|       |  *ebx = cpu_info[1];
  273|       |  *ecx = cpu_info[2];
  274|       |  *edx = cpu_info[3];
  275|       |  #elif (defined(HAVE_GCC_GET_CPUID) && defined(USE_GCC_GET_CPUID)) ||         \
  276|       |      defined(__FILC__)
  277|       |  uint32_t level = *eax;
  278|       |  __get_cpuid(level, eax, ebx, ecx, edx);
  279|       |  #else
  280|     16|  uint32_t a = *eax, b, c = *ecx, d;
  281|     16|  asm volatile("cpuid\n\t" : "+a"(a), "=b"(b), "+c"(c), "=d"(d));
  282|     16|  *eax = a;
  283|     16|  *ebx = b;
  284|     16|  *ecx = c;
  285|     16|  *edx = d;
  286|     16|  #endif
  287|     16|}
simdutf.cpp:_ZN7simdutf8internalL6xgetbvEv:
  289|      8|static inline uint64_t xgetbv() {
  290|       |  #if defined(_MSC_VER)
  291|       |  return _xgetbv(0);
  292|       |  #elif defined(__FILC__)
  293|       |  return zxgetbv();
  294|       |  #else
  295|      8|  uint32_t xcr0_lo, xcr0_hi;
  296|      8|  asm volatile("xgetbv\n\t" : "=a"(xcr0_lo), "=d"(xcr0_hi) : "c"(0));
  297|      8|  return xcr0_lo | ((uint64_t)xcr0_hi << 32);
  298|      8|  #endif
  299|      8|}

simdutf.cpp:_ZN7simdutf6scalar12_GLOBAL__N_16base6413is_eight_byteIcEEbT_:
   19|  22.1M|template <class char_type> simdutf_constexpr23 bool is_eight_byte(char_type c) {
   20|  22.1M|  if constexpr (sizeof(char_type) == 1) {
   21|  22.1M|    return true;
   22|  22.1M|  }
   23|      0|  return uint8_t(c) == c;
   24|  22.1M|}
simdutf.cpp:_ZN7simdutf6scalar12_GLOBAL__N_16base6413is_eight_byteIDsEEbT_:
   19|  8.08M|template <class char_type> simdutf_constexpr23 bool is_eight_byte(char_type c) {
   20|       |  if constexpr (sizeof(char_type) == 1) {
   21|       |    return true;
   22|       |  }
   23|  8.08M|  return uint8_t(c) == c;
   24|  8.08M|}
simdutf.cpp:_ZN7simdutf6scalar12_GLOBAL__N_16base6433maximal_binary_length_from_base64IPKcEEmT_m:
  654|  6.11k|maximal_binary_length_from_base64(InputPtr input, size_t length) noexcept {
  655|       |  // We process the padding characters ('=') at the end to make sure
  656|       |  // that we return an exact result when the input has no ignorable characters
  657|       |  // (e.g., spaces).
  658|  6.11k|  size_t padding = 0;
  659|  6.11k|  if (length > 0) {
  ------------------
  |  Branch (659:7): [True: 6.09k, False: 15]
  ------------------
  660|  6.09k|    if (input[length - 1] == '=') {
  ------------------
  |  Branch (660:9): [True: 252, False: 5.84k]
  ------------------
  661|    252|      padding++;
  662|    252|      if (length > 1 && input[length - 2] == '=') {
  ------------------
  |  Branch (662:11): [True: 246, False: 6]
  |  Branch (662:25): [True: 39, False: 207]
  ------------------
  663|     39|        padding++;
  664|     39|      }
  665|    252|    }
  666|  6.09k|  }
  667|       |  // The input is not otherwise processed for ignorable characters or
  668|       |  // validation, so that the function runs in constant time (very fast). In
  669|       |  // practice, base64 inputs without ignorable characters are common and the
  670|       |  // common case are line separated inputs with relatively long lines (e.g., 76
  671|       |  // characters) which leads this function to a slight (1%) overestimation of
  672|       |  // the output size.
  673|       |  //
  674|       |  // Of course, some inputs might contain an arbitrary number of spaces or
  675|       |  // newlines, which would make this function return a very pessimistic output
  676|       |  // size but systems that produce base64 outputs typically do not do that and
  677|       |  // if they do, they do not care much about minimizing memory usage.
  678|       |  //
  679|       |  // In specialized applications, users may know that their input is line
  680|       |  // separated, which can be checked very quickly by by iterating (e.g., over 76
  681|       |  // character chunks, looking for the linefeed characters only). We could
  682|       |  // provide a specialized function for that, but it is not clear that the added
  683|       |  // complexity is worth it for us.
  684|       |  //
  685|  6.11k|  size_t actual_length = length - padding;
  686|  6.11k|  if (actual_length % 4 <= 1) {
  ------------------
  |  Branch (686:7): [True: 5.54k, False: 564]
  ------------------
  687|  5.54k|    return actual_length / 4 * 3;
  688|  5.54k|  }
  689|       |  // if we have a valid input, then the remainder must be 2 or 3 adding one or
  690|       |  // two extra bytes.
  691|    564|  return actual_length / 4 * 3 + (actual_length % 4) - 1;
  692|  6.11k|}
simdutf.cpp:_ZN7simdutf6scalar12_GLOBAL__N_16base6433maximal_binary_length_from_base64IPKDsEEmT_m:
  654|  6.01k|maximal_binary_length_from_base64(InputPtr input, size_t length) noexcept {
  655|       |  // We process the padding characters ('=') at the end to make sure
  656|       |  // that we return an exact result when the input has no ignorable characters
  657|       |  // (e.g., spaces).
  658|  6.01k|  size_t padding = 0;
  659|  6.01k|  if (length > 0) {
  ------------------
  |  Branch (659:7): [True: 6.00k, False: 12]
  ------------------
  660|  6.00k|    if (input[length - 1] == '=') {
  ------------------
  |  Branch (660:9): [True: 234, False: 5.76k]
  ------------------
  661|    234|      padding++;
  662|    234|      if (length > 1 && input[length - 2] == '=') {
  ------------------
  |  Branch (662:11): [True: 228, False: 6]
  |  Branch (662:25): [True: 30, False: 198]
  ------------------
  663|     30|        padding++;
  664|     30|      }
  665|    234|    }
  666|  6.00k|  }
  667|       |  // The input is not otherwise processed for ignorable characters or
  668|       |  // validation, so that the function runs in constant time (very fast). In
  669|       |  // practice, base64 inputs without ignorable characters are common and the
  670|       |  // common case are line separated inputs with relatively long lines (e.g., 76
  671|       |  // characters) which leads this function to a slight (1%) overestimation of
  672|       |  // the output size.
  673|       |  //
  674|       |  // Of course, some inputs might contain an arbitrary number of spaces or
  675|       |  // newlines, which would make this function return a very pessimistic output
  676|       |  // size but systems that produce base64 outputs typically do not do that and
  677|       |  // if they do, they do not care much about minimizing memory usage.
  678|       |  //
  679|       |  // In specialized applications, users may know that their input is line
  680|       |  // separated, which can be checked very quickly by by iterating (e.g., over 76
  681|       |  // character chunks, looking for the linefeed characters only). We could
  682|       |  // provide a specialized function for that, but it is not clear that the added
  683|       |  // complexity is worth it for us.
  684|       |  //
  685|  6.01k|  size_t actual_length = length - padding;
  686|  6.01k|  if (actual_length % 4 <= 1) {
  ------------------
  |  Branch (686:7): [True: 5.55k, False: 459]
  ------------------
  687|  5.55k|    return actual_length / 4 * 3;
  688|  5.55k|  }
  689|       |  // if we have a valid input, then the remainder must be 2 or 3 adding one or
  690|       |  // two extra bytes.
  691|    459|  return actual_length / 4 * 3 + (actual_length % 4) - 1;
  692|  6.01k|}
simdutf.cpp:_ZN7simdutf6scalar12_GLOBAL__N_16base6412is_ignorableIcEEbT_NS_14base64_optionsE:
   28|  20.5k|                                      simdutf::base64_options options) {
   29|  20.5k|  const uint8_t *to_base64 =
   30|  20.5k|      (options & base64_default_or_url)
  ------------------
  |  Branch (30:7): [True: 0, False: 20.5k]
  ------------------
   31|  20.5k|          ? tables::base64::to_base64_default_or_url_value
   32|  20.5k|          : ((options & base64_url) ? tables::base64::to_base64_url_value
  ------------------
  |  Branch (32:14): [True: 8.55k, False: 11.9k]
  ------------------
   33|  20.5k|                                    : tables::base64::to_base64_value);
   34|  20.5k|  const bool ignore_garbage =
   35|  20.5k|      (options == base64_options::base64_url_accept_garbage) ||
  ------------------
  |  Branch (35:7): [True: 0, False: 20.5k]
  ------------------
   36|  20.5k|      (options == base64_options::base64_default_accept_garbage) ||
  ------------------
  |  Branch (36:7): [True: 0, False: 20.5k]
  ------------------
   37|  20.5k|      (options == base64_options::base64_default_or_url_accept_garbage);
  ------------------
  |  Branch (37:7): [True: 0, False: 20.5k]
  ------------------
   38|  20.5k|  uint8_t code = to_base64[uint8_t(c)];
   39|  20.5k|  if (is_eight_byte(c) && code <= 63) {
  ------------------
  |  Branch (39:7): [True: 20.5k, False: 0]
  |  Branch (39:27): [True: 3.09k, False: 17.4k]
  ------------------
   40|  3.09k|    return false;
   41|  3.09k|  }
   42|  17.4k|  if (is_eight_byte(c) && code == 64) {
  ------------------
  |  Branch (42:7): [True: 17.4k, False: 0]
  |  Branch (42:27): [True: 17.4k, False: 0]
  ------------------
   43|  17.4k|    return true;
   44|  17.4k|  }
   45|      0|  return ignore_garbage;
   46|  17.4k|}
simdutf.cpp:_ZN7simdutf6scalar12_GLOBAL__N_16base6412is_ignorableIDsEEbT_NS_14base64_optionsE:
   28|  27.1k|                                      simdutf::base64_options options) {
   29|  27.1k|  const uint8_t *to_base64 =
   30|  27.1k|      (options & base64_default_or_url)
  ------------------
  |  Branch (30:7): [True: 0, False: 27.1k]
  ------------------
   31|  27.1k|          ? tables::base64::to_base64_default_or_url_value
   32|  27.1k|          : ((options & base64_url) ? tables::base64::to_base64_url_value
  ------------------
  |  Branch (32:14): [True: 11.5k, False: 15.5k]
  ------------------
   33|  27.1k|                                    : tables::base64::to_base64_value);
   34|  27.1k|  const bool ignore_garbage =
   35|  27.1k|      (options == base64_options::base64_url_accept_garbage) ||
  ------------------
  |  Branch (35:7): [True: 0, False: 27.1k]
  ------------------
   36|  27.1k|      (options == base64_options::base64_default_accept_garbage) ||
  ------------------
  |  Branch (36:7): [True: 0, False: 27.1k]
  ------------------
   37|  27.1k|      (options == base64_options::base64_default_or_url_accept_garbage);
  ------------------
  |  Branch (37:7): [True: 0, False: 27.1k]
  ------------------
   38|  27.1k|  uint8_t code = to_base64[uint8_t(c)];
   39|  27.1k|  if (is_eight_byte(c) && code <= 63) {
  ------------------
  |  Branch (39:7): [True: 27.1k, False: 0]
  |  Branch (39:27): [True: 2.94k, False: 24.2k]
  ------------------
   40|  2.94k|    return false;
   41|  2.94k|  }
   42|  24.2k|  if (is_eight_byte(c) && code == 64) {
  ------------------
  |  Branch (42:7): [True: 24.2k, False: 0]
  |  Branch (42:27): [True: 24.2k, False: 0]
  ------------------
   43|  24.2k|    return true;
   44|  24.2k|  }
   45|      0|  return ignore_garbage;
   46|  24.2k|}
simdutf.cpp:_ZN7simdutf6scalar12_GLOBAL__N_16base648find_endIcEENS2_13reduced_inputEPKT_mNS_14base64_optionsE:
  100|  12.2k|                                           simdutf::base64_options options) {
  101|  12.2k|  const uint8_t *to_base64 =
  102|  12.2k|      (options & base64_default_or_url)
  ------------------
  |  Branch (102:7): [True: 0, False: 12.2k]
  ------------------
  103|  12.2k|          ? tables::base64::to_base64_default_or_url_value
  104|  12.2k|          : ((options & base64_url) ? tables::base64::to_base64_url_value
  ------------------
  |  Branch (104:14): [True: 5.88k, False: 6.33k]
  ------------------
  105|  12.2k|                                    : tables::base64::to_base64_value);
  106|  12.2k|  const bool ignore_garbage =
  107|  12.2k|      (options == base64_options::base64_url_accept_garbage) ||
  ------------------
  |  Branch (107:7): [True: 0, False: 12.2k]
  ------------------
  108|  12.2k|      (options == base64_options::base64_default_accept_garbage) ||
  ------------------
  |  Branch (108:7): [True: 0, False: 12.2k]
  ------------------
  109|  12.2k|      (options == base64_options::base64_default_or_url_accept_garbage);
  ------------------
  |  Branch (109:7): [True: 0, False: 12.2k]
  ------------------
  110|       |
  111|  12.2k|  size_t equalsigns = 0;
  112|       |  // We intentionally include trailing spaces in the full input length.
  113|       |  // See https://github.com/simdutf/simdutf/issues/824
  114|  12.2k|  size_t full_input_length = srclen;
  115|       |  // skip trailing spaces
  116|  13.6k|  while (!ignore_garbage && srclen > 0 &&
  ------------------
  |  Branch (116:10): [True: 13.6k, False: 0]
  |  Branch (116:29): [True: 13.5k, False: 66]
  ------------------
  117|  13.5k|         scalar::base64::is_eight_byte(src[srclen - 1]) &&
  ------------------
  |  Branch (117:10): [True: 13.5k, False: 0]
  ------------------
  118|  13.5k|         to_base64[uint8_t(src[srclen - 1])] == 64) {
  ------------------
  |  Branch (118:10): [True: 1.42k, False: 12.1k]
  ------------------
  119|  1.42k|    srclen--;
  120|  1.42k|  }
  121|  12.2k|  size_t equallocation =
  122|  12.2k|      srclen; // location of the first padding character if any
  123|  12.2k|  if (ignore_garbage) {
  ------------------
  |  Branch (123:7): [True: 0, False: 12.2k]
  ------------------
  124|       |    // Technically, we don't need to find the first padding character, we can
  125|       |    // just change our algorithms, but it adds substantial complexity.
  126|      0|    auto it = simdutf::find(src, src + srclen, '=');
  127|      0|    if (it != src + srclen) {
  ------------------
  |  Branch (127:9): [True: 0, False: 0]
  ------------------
  128|      0|      equallocation = it - src;
  129|      0|      equalsigns = 1;
  130|      0|      srclen = equallocation;
  131|      0|      full_input_length = equallocation + 1;
  132|      0|    }
  133|      0|    return {equalsigns, equallocation, srclen, full_input_length};
  134|      0|  }
  135|  12.2k|  if (!ignore_garbage && srclen > 0 && src[srclen - 1] == '=') {
  ------------------
  |  Branch (135:7): [True: 12.2k, False: 0]
  |  Branch (135:26): [True: 12.1k, False: 66]
  |  Branch (135:40): [True: 504, False: 11.6k]
  ------------------
  136|       |    // This is the last '=' sign.
  137|    504|    equallocation = srclen - 1;
  138|    504|    srclen--;
  139|    504|    equalsigns = 1;
  140|       |    // skip trailing spaces
  141|  1.31k|    while (srclen > 0 && scalar::base64::is_eight_byte(src[srclen - 1]) &&
  ------------------
  |  Branch (141:12): [True: 1.26k, False: 48]
  |  Branch (141:26): [True: 1.26k, False: 0]
  ------------------
  142|  1.26k|           to_base64[uint8_t(src[srclen - 1])] == 64) {
  ------------------
  |  Branch (142:12): [True: 810, False: 456]
  ------------------
  143|    810|      srclen--;
  144|    810|    }
  145|    504|    if (srclen > 0 && src[srclen - 1] == '=') {
  ------------------
  |  Branch (145:9): [True: 456, False: 48]
  |  Branch (145:23): [True: 78, False: 378]
  ------------------
  146|       |      // This is the second '=' sign.
  147|     78|      equallocation = srclen - 1;
  148|     78|      srclen--;
  149|     78|      equalsigns = 2;
  150|     78|    }
  151|    504|  }
  152|  12.2k|  return {equalsigns, equallocation, srclen, full_input_length};
  153|  12.2k|}
simdutf.cpp:_ZN7simdutf6scalar12_GLOBAL__N_16base6417patch_tail_resultENS_11full_resultEmmmmNS_27last_chunk_handling_optionsE:
  394|  13.6k|                  last_chunk_handling_options last_chunk_options) {
  395|  13.6k|  r.input_count += previous_input;
  396|  13.6k|  r.output_count += previous_output;
  397|  13.6k|  if (r.padding_error) {
  ------------------
  |  Branch (397:7): [True: 300, False: 13.3k]
  ------------------
  398|    300|    r.input_count = equallocation;
  399|    300|  }
  400|       |
  401|  13.6k|  if (r.error == error_code::SUCCESS) {
  ------------------
  |  Branch (401:7): [True: 6.59k, False: 7.02k]
  ------------------
  402|  6.59k|    if (!is_partial(last_chunk_options)) {
  ------------------
  |  Branch (402:9): [True: 2.26k, False: 4.32k]
  ------------------
  403|       |      // A success when we are not in stop_before_partial mode.
  404|       |      // means that we have consumed the whole input buffer.
  405|  2.26k|      r.input_count = full_input_length;
  406|  4.32k|    } else if (r.output_count % 3 != 0) {
  ------------------
  |  Branch (406:16): [True: 24, False: 4.30k]
  ------------------
  407|     24|      r.input_count = full_input_length;
  408|     24|    }
  409|  6.59k|  }
  410|  13.6k|  return r;
  411|  13.6k|}
simdutf.cpp:_ZN7simdutf6scalar12_GLOBAL__N_16base648find_endIDsEENS2_13reduced_inputEPKT_mNS_14base64_optionsE:
  100|  12.0k|                                           simdutf::base64_options options) {
  101|  12.0k|  const uint8_t *to_base64 =
  102|  12.0k|      (options & base64_default_or_url)
  ------------------
  |  Branch (102:7): [True: 0, False: 12.0k]
  ------------------
  103|  12.0k|          ? tables::base64::to_base64_default_or_url_value
  104|  12.0k|          : ((options & base64_url) ? tables::base64::to_base64_url_value
  ------------------
  |  Branch (104:14): [True: 6.11k, False: 5.91k]
  ------------------
  105|  12.0k|                                    : tables::base64::to_base64_value);
  106|  12.0k|  const bool ignore_garbage =
  107|  12.0k|      (options == base64_options::base64_url_accept_garbage) ||
  ------------------
  |  Branch (107:7): [True: 0, False: 12.0k]
  ------------------
  108|  12.0k|      (options == base64_options::base64_default_accept_garbage) ||
  ------------------
  |  Branch (108:7): [True: 0, False: 12.0k]
  ------------------
  109|  12.0k|      (options == base64_options::base64_default_or_url_accept_garbage);
  ------------------
  |  Branch (109:7): [True: 0, False: 12.0k]
  ------------------
  110|       |
  111|  12.0k|  size_t equalsigns = 0;
  112|       |  // We intentionally include trailing spaces in the full input length.
  113|       |  // See https://github.com/simdutf/simdutf/issues/824
  114|  12.0k|  size_t full_input_length = srclen;
  115|       |  // skip trailing spaces
  116|  13.3k|  while (!ignore_garbage && srclen > 0 &&
  ------------------
  |  Branch (116:10): [True: 13.3k, False: 0]
  |  Branch (116:29): [True: 13.2k, False: 60]
  ------------------
  117|  13.2k|         scalar::base64::is_eight_byte(src[srclen - 1]) &&
  ------------------
  |  Branch (117:10): [True: 8.38k, False: 4.88k]
  ------------------
  118|  8.38k|         to_base64[uint8_t(src[srclen - 1])] == 64) {
  ------------------
  |  Branch (118:10): [True: 1.30k, False: 7.08k]
  ------------------
  119|  1.30k|    srclen--;
  120|  1.30k|  }
  121|  12.0k|  size_t equallocation =
  122|  12.0k|      srclen; // location of the first padding character if any
  123|  12.0k|  if (ignore_garbage) {
  ------------------
  |  Branch (123:7): [True: 0, False: 12.0k]
  ------------------
  124|       |    // Technically, we don't need to find the first padding character, we can
  125|       |    // just change our algorithms, but it adds substantial complexity.
  126|      0|    auto it = simdutf::find(src, src + srclen, '=');
  127|      0|    if (it != src + srclen) {
  ------------------
  |  Branch (127:9): [True: 0, False: 0]
  ------------------
  128|      0|      equallocation = it - src;
  129|      0|      equalsigns = 1;
  130|      0|      srclen = equallocation;
  131|      0|      full_input_length = equallocation + 1;
  132|      0|    }
  133|      0|    return {equalsigns, equallocation, srclen, full_input_length};
  134|      0|  }
  135|  12.0k|  if (!ignore_garbage && srclen > 0 && src[srclen - 1] == '=') {
  ------------------
  |  Branch (135:7): [True: 12.0k, False: 0]
  |  Branch (135:26): [True: 11.9k, False: 60]
  |  Branch (135:40): [True: 468, False: 11.4k]
  ------------------
  136|       |    // This is the last '=' sign.
  137|    468|    equallocation = srclen - 1;
  138|    468|    srclen--;
  139|    468|    equalsigns = 1;
  140|       |    // skip trailing spaces
  141|  1.12k|    while (srclen > 0 && scalar::base64::is_eight_byte(src[srclen - 1]) &&
  ------------------
  |  Branch (141:12): [True: 1.07k, False: 54]
  |  Branch (141:26): [True: 942, False: 132]
  ------------------
  142|    942|           to_base64[uint8_t(src[srclen - 1])] == 64) {
  ------------------
  |  Branch (142:12): [True: 660, False: 282]
  ------------------
  143|    660|      srclen--;
  144|    660|    }
  145|    468|    if (srclen > 0 && src[srclen - 1] == '=') {
  ------------------
  |  Branch (145:9): [True: 414, False: 54]
  |  Branch (145:23): [True: 60, False: 354]
  ------------------
  146|       |      // This is the second '=' sign.
  147|     60|      equallocation = srclen - 1;
  148|     60|      srclen--;
  149|     60|      equalsigns = 2;
  150|     60|    }
  151|    468|  }
  152|  12.0k|  return {equalsigns, equallocation, srclen, full_input_length};
  153|  12.0k|}
simdutf.cpp:_ZN7simdutf6scalar12_GLOBAL__N_16base6429base64_to_binary_details_implIcEENS_11full_resultEPKT_mPcNS_14base64_optionsENS_27last_chunk_handling_optionsE:
  727|  4.07k|    last_chunk_handling_options last_chunk_options) noexcept {
  728|  4.07k|  const bool ignore_garbage =
  729|  4.07k|      (options == base64_options::base64_url_accept_garbage) ||
  ------------------
  |  Branch (729:7): [True: 0, False: 4.07k]
  ------------------
  730|  4.07k|      (options == base64_options::base64_default_accept_garbage) ||
  ------------------
  |  Branch (730:7): [True: 0, False: 4.07k]
  ------------------
  731|  4.07k|      (options == base64_options::base64_default_or_url_accept_garbage);
  ------------------
  |  Branch (731:7): [True: 0, False: 4.07k]
  ------------------
  732|  4.07k|  auto ri = simdutf::scalar::base64::find_end(input, length, options);
  733|  4.07k|  size_t equallocation = ri.equallocation;
  734|  4.07k|  size_t equalsigns = ri.equalsigns;
  735|  4.07k|  length = ri.srclen;
  736|  4.07k|  size_t full_input_length = ri.full_input_length;
  737|  4.07k|  if (length == 0) {
  ------------------
  |  Branch (737:7): [True: 40, False: 4.03k]
  ------------------
  738|     40|    if (!ignore_garbage && equalsigns > 0) {
  ------------------
  |  Branch (738:9): [True: 40, False: 0]
  |  Branch (738:28): [True: 18, False: 22]
  ------------------
  739|     18|      return {INVALID_BASE64_CHARACTER, equallocation, 0, true};
  740|     18|    }
  741|     22|    return {SUCCESS, full_input_length, 0};
  742|     40|  }
  743|  4.03k|  full_result r = scalar::base64::base64_tail_decode(
  744|  4.03k|      output, input, length, equalsigns, options, last_chunk_options);
  745|  4.03k|  r = scalar::base64::patch_tail_result(r, 0, 0, equallocation,
  746|  4.03k|                                        full_input_length, last_chunk_options);
  747|  4.03k|  if (!is_partial(last_chunk_options) && r.error == error_code::SUCCESS &&
  ------------------
  |  Branch (747:7): [True: 2.24k, False: 1.79k]
  |  Branch (747:42): [True: 632, False: 1.60k]
  ------------------
  748|    632|      equalsigns > 0 && !ignore_garbage) {
  ------------------
  |  Branch (748:7): [True: 8, False: 624]
  |  Branch (748:25): [True: 8, False: 0]
  ------------------
  749|       |    // additional checks
  750|      8|    if ((r.output_count % 3 == 0) ||
  ------------------
  |  Branch (750:9): [True: 0, False: 8]
  ------------------
  751|      8|        ((r.output_count % 3) + 1 + equalsigns != 4)) {
  ------------------
  |  Branch (751:9): [True: 0, False: 8]
  ------------------
  752|      0|      return {INVALID_BASE64_CHARACTER, equallocation, r.output_count, true};
  753|      0|    }
  754|      8|  }
  755|       |  // When is_partial(last_chunk_options) is true, we must either end with
  756|       |  // the end of the stream (beyond whitespace) or right after a non-ignorable
  757|       |  // character or at the very beginning of the stream.
  758|       |  // See https://tc39.es/proposal-arraybuffer-base64/spec/#sec-frombase64
  759|  4.03k|  if (is_partial(last_chunk_options) && r.error == error_code::SUCCESS &&
  ------------------
  |  Branch (759:7): [True: 1.79k, False: 2.24k]
  |  Branch (759:41): [True: 838, False: 956]
  ------------------
  760|    838|      r.input_count < full_input_length) {
  ------------------
  |  Branch (760:7): [True: 588, False: 250]
  ------------------
  761|       |    // First check if we can extend the input to the end of the stream
  762|  4.73k|    while (r.input_count < full_input_length &&
  ------------------
  |  Branch (762:12): [True: 4.72k, False: 16]
  ------------------
  763|  4.72k|           base64_ignorable(*(input + r.input_count), options)) {
  ------------------
  |  Branch (763:12): [True: 4.15k, False: 572]
  ------------------
  764|  4.15k|      r.input_count++;
  765|  4.15k|    }
  766|       |    // If we are still not at the end of the stream, then we must backtrack
  767|       |    // to the last non-ignorable character.
  768|    588|    if (r.input_count < full_input_length) {
  ------------------
  |  Branch (768:9): [True: 572, False: 16]
  ------------------
  769|  4.45k|      while (r.input_count > 0 &&
  ------------------
  |  Branch (769:14): [True: 4.34k, False: 112]
  ------------------
  770|  4.34k|             base64_ignorable(*(input + r.input_count - 1), options)) {
  ------------------
  |  Branch (770:14): [True: 3.88k, False: 460]
  ------------------
  771|  3.88k|        r.input_count--;
  772|  3.88k|      }
  773|    572|    }
  774|    588|  }
  775|  4.03k|  return r;
  776|  4.03k|}
simdutf.cpp:_ZN7simdutf6scalar12_GLOBAL__N_16base6418base64_tail_decodeIcEENS_11full_resultEPcPKT_mmNS_14base64_optionsENS_27last_chunk_handling_optionsE:
  371|  6.86k|    base64_options options, last_chunk_handling_options last_chunk_options) {
  372|  6.86k|  return base64_tail_decode_impl<false>(dst, 0, src, length, padding_characters,
  373|  6.86k|                                        options, last_chunk_options);
  374|  6.86k|}
simdutf.cpp:_ZN7simdutf6scalar12_GLOBAL__N_16base6423base64_tail_decode_implILb0EcEENS_11full_resultEPcmPKT0_mmNS_14base64_optionsENS_27last_chunk_handling_optionsE:
  164|  6.86k|    base64_options options, last_chunk_handling_options last_chunk_options) {
  165|  6.86k|  char *dstend = dst + outlen;
  166|  6.86k|  (void)dstend;
  167|       |  // This looks like 10 branches, but we expect the compiler to resolve this to
  168|       |  // two branches (easily predicted):
  169|  6.86k|  const uint8_t *to_base64 =
  170|  6.86k|      (options & base64_default_or_url)
  ------------------
  |  Branch (170:7): [True: 0, False: 6.86k]
  ------------------
  171|  6.86k|          ? tables::base64::to_base64_default_or_url_value
  172|  6.86k|          : ((options & base64_url) ? tables::base64::to_base64_url_value
  ------------------
  |  Branch (172:14): [True: 3.20k, False: 3.65k]
  ------------------
  173|  6.86k|                                    : tables::base64::to_base64_value);
  174|  6.86k|  const uint32_t *d0 =
  175|  6.86k|      (options & base64_default_or_url)
  ------------------
  |  Branch (175:7): [True: 0, False: 6.86k]
  ------------------
  176|  6.86k|          ? tables::base64::base64_default_or_url::d0
  177|  6.86k|          : ((options & base64_url) ? tables::base64::base64_url::d0
  ------------------
  |  Branch (177:14): [True: 3.20k, False: 3.65k]
  ------------------
  178|  6.86k|                                    : tables::base64::base64_default::d0);
  179|  6.86k|  const uint32_t *d1 =
  180|  6.86k|      (options & base64_default_or_url)
  ------------------
  |  Branch (180:7): [True: 0, False: 6.86k]
  ------------------
  181|  6.86k|          ? tables::base64::base64_default_or_url::d1
  182|  6.86k|          : ((options & base64_url) ? tables::base64::base64_url::d1
  ------------------
  |  Branch (182:14): [True: 3.20k, False: 3.65k]
  ------------------
  183|  6.86k|                                    : tables::base64::base64_default::d1);
  184|  6.86k|  const uint32_t *d2 =
  185|  6.86k|      (options & base64_default_or_url)
  ------------------
  |  Branch (185:7): [True: 0, False: 6.86k]
  ------------------
  186|  6.86k|          ? tables::base64::base64_default_or_url::d2
  187|  6.86k|          : ((options & base64_url) ? tables::base64::base64_url::d2
  ------------------
  |  Branch (187:14): [True: 3.20k, False: 3.65k]
  ------------------
  188|  6.86k|                                    : tables::base64::base64_default::d2);
  189|  6.86k|  const uint32_t *d3 =
  190|  6.86k|      (options & base64_default_or_url)
  ------------------
  |  Branch (190:7): [True: 0, False: 6.86k]
  ------------------
  191|  6.86k|          ? tables::base64::base64_default_or_url::d3
  192|  6.86k|          : ((options & base64_url) ? tables::base64::base64_url::d3
  ------------------
  |  Branch (192:14): [True: 3.20k, False: 3.65k]
  ------------------
  193|  6.86k|                                    : tables::base64::base64_default::d3);
  194|  6.86k|  const bool ignore_garbage =
  195|  6.86k|      (options == base64_options::base64_url_accept_garbage) ||
  ------------------
  |  Branch (195:7): [True: 0, False: 6.86k]
  ------------------
  196|  6.86k|      (options == base64_options::base64_default_accept_garbage) ||
  ------------------
  |  Branch (196:7): [True: 0, False: 6.86k]
  ------------------
  197|  6.86k|      (options == base64_options::base64_default_or_url_accept_garbage);
  ------------------
  |  Branch (197:7): [True: 0, False: 6.86k]
  ------------------
  198|       |
  199|  6.86k|  const char_type *srcend = src + length;
  200|  6.86k|  const char_type *srcinit = src;
  201|  6.86k|  const char *dstinit = dst;
  202|       |
  203|  6.86k|  uint32_t x;
  204|  6.86k|  size_t idx;
  205|  6.86k|  uint8_t buffer[4];
  206|   100k|  while (true) {
  ------------------
  |  Branch (206:10): [True: 100k, Folded]
  ------------------
  207|  5.26M|    while (srcend - src >= 4 && is_eight_byte(src[0]) &&
  ------------------
  |  Branch (207:12): [True: 5.26M, False: 3.41k]
  |  Branch (207:33): [True: 5.26M, False: 0]
  ------------------
  208|  5.26M|           is_eight_byte(src[1]) && is_eight_byte(src[2]) &&
  ------------------
  |  Branch (208:12): [True: 5.26M, False: 0]
  |  Branch (208:37): [True: 5.26M, False: 0]
  ------------------
  209|  5.26M|           is_eight_byte(src[3]) &&
  ------------------
  |  Branch (209:12): [True: 5.26M, False: 0]
  ------------------
  210|  5.26M|           (x = d0[uint8_t(src[0])] | d1[uint8_t(src[1])] |
  ------------------
  |  Branch (210:12): [True: 5.16M, False: 96.7k]
  ------------------
  211|  5.26M|                d2[uint8_t(src[2])] | d3[uint8_t(src[3])]) < 0x01FFFFFF) {
  212|  5.16M|      if (check_capacity && dstend - dst < 3) {
  ------------------
  |  Branch (212:11): [Folded, False: 5.16M]
  |  Branch (212:29): [True: 0, False: 0]
  ------------------
  213|      0|        return {OUTPUT_BUFFER_TOO_SMALL, size_t(src - srcinit),
  214|      0|                size_t(dst - dstinit)};
  215|      0|      }
  216|  5.16M|      *dst++ = static_cast<char>(x & 0xFF);
  217|  5.16M|      *dst++ = static_cast<char>((x >> 8) & 0xFF);
  218|  5.16M|      *dst++ = static_cast<char>((x >> 16) & 0xFF);
  219|  5.16M|      src += 4;
  220|  5.16M|    }
  221|   100k|    const char_type *srccur = src;
  222|   100k|    idx = 0;
  223|       |    // we need at least four characters.
  224|   100k|#ifdef __clang__
  225|       |    // If possible, we read four characters at a time. (It is an optimization.)
  226|   100k|    if (ignore_garbage && src + 4 <= srcend) {
  ------------------
  |  Branch (226:9): [True: 0, False: 100k]
  |  Branch (226:27): [True: 0, False: 0]
  ------------------
  227|      0|      char_type c0 = src[0];
  228|      0|      char_type c1 = src[1];
  229|      0|      char_type c2 = src[2];
  230|      0|      char_type c3 = src[3];
  231|       |
  232|      0|      uint8_t code0 = to_base64[uint8_t(c0)];
  233|      0|      uint8_t code1 = to_base64[uint8_t(c1)];
  234|      0|      uint8_t code2 = to_base64[uint8_t(c2)];
  235|      0|      uint8_t code3 = to_base64[uint8_t(c3)];
  236|       |
  237|      0|      buffer[idx] = code0;
  238|      0|      idx += (is_eight_byte(c0) && code0 <= 63);
  ------------------
  |  Branch (238:15): [True: 0, False: 0]
  |  Branch (238:36): [True: 0, False: 0]
  ------------------
  239|      0|      buffer[idx] = code1;
  240|      0|      idx += (is_eight_byte(c1) && code1 <= 63);
  ------------------
  |  Branch (240:15): [True: 0, False: 0]
  |  Branch (240:36): [True: 0, False: 0]
  ------------------
  241|      0|      buffer[idx] = code2;
  242|      0|      idx += (is_eight_byte(c2) && code2 <= 63);
  ------------------
  |  Branch (242:15): [True: 0, False: 0]
  |  Branch (242:36): [True: 0, False: 0]
  ------------------
  243|      0|      buffer[idx] = code3;
  244|      0|      idx += (is_eight_byte(c3) && code3 <= 63);
  ------------------
  |  Branch (244:15): [True: 0, False: 0]
  |  Branch (244:36): [True: 0, False: 0]
  ------------------
  245|      0|      src += 4;
  246|      0|    }
  247|   100k|#endif
  248|   833k|    while ((idx < 4) && (src < srcend)) {
  ------------------
  |  Branch (248:12): [True: 739k, False: 93.3k]
  |  Branch (248:25): [True: 735k, False: 4.23k]
  ------------------
  249|   735k|      char_type c = *src;
  250|       |
  251|   735k|      uint8_t code = to_base64[uint8_t(c)];
  252|   735k|      buffer[idx] = uint8_t(code);
  253|   735k|      if (is_eight_byte(c) && code <= 63) {
  ------------------
  |  Branch (253:11): [True: 735k, False: 0]
  |  Branch (253:31): [True: 382k, False: 353k]
  ------------------
  254|   382k|        idx++;
  255|   382k|      } else if (!ignore_garbage &&
  ------------------
  |  Branch (255:18): [True: 353k, False: 0]
  ------------------
  256|   353k|                 (code > 64 || !scalar::base64::is_eight_byte(c))) {
  ------------------
  |  Branch (256:19): [True: 2.62k, False: 350k]
  |  Branch (256:32): [True: 0, False: 350k]
  ------------------
  257|  2.62k|        return {INVALID_BASE64_CHARACTER, size_t(src - srcinit),
  258|  2.62k|                size_t(dst - dstinit)};
  259|   350k|      } else {
  260|       |        // We have a space or a newline or garbage. We ignore it.
  261|   350k|      }
  262|   732k|      src++;
  263|   732k|    }
  264|  97.5k|    if (idx != 4) {
  ------------------
  |  Branch (264:9): [True: 4.23k, False: 93.3k]
  ------------------
  265|  4.23k|      simdutf_log_assert(idx < 4, "idx should be less than 4");
  266|       |      // We never should have that the number of base64 characters + the
  267|       |      // number of padding characters is more than 4.
  268|  4.23k|      if (!ignore_garbage && (idx + padding_characters > 4)) {
  ------------------
  |  Branch (268:11): [True: 4.23k, False: 0]
  |  Branch (268:30): [True: 6, False: 4.23k]
  ------------------
  269|      6|        return {INVALID_BASE64_CHARACTER, size_t(src - srcinit),
  270|      6|                size_t(dst - dstinit), true};
  271|      6|      }
  272|       |
  273|       |      // The idea here is that in loose mode,
  274|       |      // if there is padding at all, it must be used
  275|       |      // to form 4-wise chunk. However, in loose mode,
  276|       |      // we do accept no padding at all.
  277|  4.23k|      if (!ignore_garbage &&
  ------------------
  |  Branch (277:11): [True: 4.23k, False: 0]
  ------------------
  278|  4.23k|          last_chunk_options == last_chunk_handling_options::loose &&
  ------------------
  |  Branch (278:11): [True: 1.61k, False: 2.61k]
  ------------------
  279|  1.61k|          (idx >= 2) && padding_characters > 0 &&
  ------------------
  |  Branch (279:11): [True: 936, False: 676]
  |  Branch (279:25): [True: 30, False: 906]
  ------------------
  280|     30|          ((idx + padding_characters) & 3) != 0) {
  ------------------
  |  Branch (280:11): [True: 18, False: 12]
  ------------------
  281|     18|        return {INVALID_BASE64_CHARACTER, size_t(src - srcinit),
  282|     18|                size_t(dst - dstinit), true};
  283|     18|      } else
  284|       |
  285|       |        // The idea here is that in strict mode, we do not want to accept
  286|       |        // incomplete base64 chunks. So if the chunk was otherwise valid, we
  287|       |        // return BASE64_INPUT_REMAINDER.
  288|  4.21k|        if (!ignore_garbage &&
  ------------------
  |  Branch (288:13): [True: 4.21k, False: 0]
  ------------------
  289|  4.21k|            last_chunk_options == last_chunk_handling_options::strict &&
  ------------------
  |  Branch (289:13): [True: 330, False: 3.88k]
  ------------------
  290|    330|            (idx >= 2) && ((idx + padding_characters) & 3) != 0) {
  ------------------
  |  Branch (290:13): [True: 168, False: 162]
  |  Branch (290:27): [True: 114, False: 54]
  ------------------
  291|       |          // The partial chunk was at src - idx
  292|    114|          return {BASE64_INPUT_REMAINDER, size_t(src - srcinit),
  293|    114|                  size_t(dst - dstinit), true};
  294|    114|        } else
  295|       |          // If there is a partial chunk with insufficient padding, with
  296|       |          // stop_before_partial, we need to just ignore it. In "only full"
  297|       |          // mode, skip the minute there are padding characters.
  298|  4.09k|          if ((last_chunk_options ==
  ------------------
  |  Branch (298:16): [True: 2.28k, False: 1.81k]
  ------------------
  299|  4.09k|                   last_chunk_handling_options::stop_before_partial &&
  300|  2.28k|               (padding_characters + idx < 4) && (idx != 0) &&
  ------------------
  |  Branch (300:16): [True: 2.27k, False: 12]
  |  Branch (300:50): [True: 1.76k, False: 512]
  ------------------
  301|  1.76k|               (idx >= 2 || padding_characters == 0)) ||
  ------------------
  |  Branch (301:17): [True: 810, False: 954]
  |  Branch (301:29): [True: 906, False: 48]
  ------------------
  302|  2.38k|              (last_chunk_options ==
  ------------------
  |  Branch (302:16): [True: 0, False: 2.38k]
  ------------------
  303|  2.38k|                   last_chunk_handling_options::only_full_chunks &&
  304|  1.71k|               (idx >= 2 || padding_characters == 0))) {
  ------------------
  |  Branch (304:17): [True: 0, False: 0]
  |  Branch (304:29): [True: 0, False: 0]
  ------------------
  305|       |            // partial means that we are *not* going to consume the read
  306|       |            // characters. We need to rewind the src pointer.
  307|  1.71k|            src = srccur;
  308|  1.71k|            return {SUCCESS, size_t(src - srcinit), size_t(dst - dstinit)};
  309|  2.38k|          } else {
  310|  2.38k|            if (idx == 2) {
  ------------------
  |  Branch (310:17): [True: 558, False: 1.82k]
  ------------------
  311|    558|              uint32_t triple = (uint32_t(buffer[0]) << 3 * 6) +
  312|    558|                                (uint32_t(buffer[1]) << 2 * 6);
  313|    558|              if (!ignore_garbage &&
  ------------------
  |  Branch (313:19): [True: 558, False: 0]
  ------------------
  314|    558|                  (last_chunk_options == last_chunk_handling_options::strict) &&
  ------------------
  |  Branch (314:19): [True: 24, False: 534]
  ------------------
  315|     24|                  (triple & 0xffff)) {
  ------------------
  |  Branch (315:19): [True: 18, False: 6]
  ------------------
  316|     18|                return {BASE64_EXTRA_BITS, size_t(src - srcinit),
  317|     18|                        size_t(dst - dstinit)};
  318|     18|              }
  319|    540|              if (check_capacity && dstend - dst < 1) {
  ------------------
  |  Branch (319:19): [Folded, False: 540]
  |  Branch (319:37): [True: 0, False: 0]
  ------------------
  320|      0|                return {OUTPUT_BUFFER_TOO_SMALL, size_t(srccur - srcinit),
  321|      0|                        size_t(dst - dstinit)};
  322|      0|              }
  323|    540|              *dst++ = static_cast<char>((triple >> 16) & 0xFF);
  324|  1.82k|            } else if (idx == 3) {
  ------------------
  |  Branch (324:24): [True: 426, False: 1.39k]
  ------------------
  325|    426|              uint32_t triple = (uint32_t(buffer[0]) << 3 * 6) +
  326|    426|                                (uint32_t(buffer[1]) << 2 * 6) +
  327|    426|                                (uint32_t(buffer[2]) << 1 * 6);
  328|    426|              if (!ignore_garbage &&
  ------------------
  |  Branch (328:19): [True: 426, False: 0]
  ------------------
  329|    426|                  (last_chunk_options == last_chunk_handling_options::strict) &&
  ------------------
  |  Branch (329:19): [True: 30, False: 396]
  ------------------
  330|     30|                  (triple & 0xff)) {
  ------------------
  |  Branch (330:19): [True: 24, False: 6]
  ------------------
  331|     24|                return {BASE64_EXTRA_BITS, size_t(src - srcinit),
  332|     24|                        size_t(dst - dstinit)};
  333|     24|              }
  334|    402|              if (check_capacity && dstend - dst < 2) {
  ------------------
  |  Branch (334:19): [Folded, False: 402]
  |  Branch (334:37): [True: 0, False: 0]
  ------------------
  335|      0|                return {OUTPUT_BUFFER_TOO_SMALL, size_t(srccur - srcinit),
  336|      0|                        size_t(dst - dstinit)};
  337|      0|              }
  338|    402|              *dst++ = static_cast<char>((triple >> 16) & 0xFF);
  339|    402|              *dst++ = static_cast<char>((triple >> 8) & 0xFF);
  340|  1.39k|            } else if (!ignore_garbage && idx == 1 &&
  ------------------
  |  Branch (340:24): [True: 1.39k, False: 0]
  |  Branch (340:43): [True: 318, False: 1.08k]
  ------------------
  341|    318|                       (!is_partial(last_chunk_options) ||
  ------------------
  |  Branch (341:25): [True: 270, False: 48]
  ------------------
  342|     48|                        (is_partial(last_chunk_options) &&
  ------------------
  |  Branch (342:26): [True: 48, False: 0]
  ------------------
  343|    318|                         padding_characters > 0))) {
  ------------------
  |  Branch (343:26): [True: 48, False: 0]
  ------------------
  344|    318|              return {BASE64_INPUT_REMAINDER, size_t(src - srcinit),
  345|    318|                      size_t(dst - dstinit)};
  346|  1.08k|            } else if (!ignore_garbage && idx == 0 && padding_characters > 0) {
  ------------------
  |  Branch (346:24): [True: 1.08k, False: 0]
  |  Branch (346:43): [True: 1.08k, False: 0]
  |  Branch (346:55): [True: 12, False: 1.06k]
  ------------------
  347|     12|              return {INVALID_BASE64_CHARACTER, size_t(src - srcinit),
  348|     12|                      size_t(dst - dstinit), true};
  349|     12|            }
  350|  2.01k|            return {SUCCESS, size_t(src - srcinit), size_t(dst - dstinit)};
  351|  2.38k|          }
  352|  4.23k|    }
  353|  93.3k|    if (check_capacity && dstend - dst < 3) {
  ------------------
  |  Branch (353:9): [Folded, False: 93.3k]
  |  Branch (353:27): [True: 0, False: 0]
  ------------------
  354|      0|      return {OUTPUT_BUFFER_TOO_SMALL, size_t(srccur - srcinit),
  355|      0|              size_t(dst - dstinit)};
  356|      0|    }
  357|  93.3k|    uint32_t triple =
  358|  93.3k|        (uint32_t(buffer[0]) << 3 * 6) + (uint32_t(buffer[1]) << 2 * 6) +
  359|  93.3k|        (uint32_t(buffer[2]) << 1 * 6) + (uint32_t(buffer[3]) << 0 * 6);
  360|  93.3k|    *dst++ = static_cast<char>((triple >> 16) & 0xFF);
  361|  93.3k|    *dst++ = static_cast<char>((triple >> 8) & 0xFF);
  362|  93.3k|    *dst++ = static_cast<char>(triple & 0xFF);
  363|  93.3k|  }
  364|  6.86k|}
simdutf.cpp:_ZN7simdutf6scalar12_GLOBAL__N_16base6429base64_to_binary_details_implIDsEENS_11full_resultEPKT_mPcNS_14base64_optionsENS_27last_chunk_handling_optionsE:
  727|  4.00k|    last_chunk_handling_options last_chunk_options) noexcept {
  728|  4.00k|  const bool ignore_garbage =
  729|  4.00k|      (options == base64_options::base64_url_accept_garbage) ||
  ------------------
  |  Branch (729:7): [True: 0, False: 4.00k]
  ------------------
  730|  4.00k|      (options == base64_options::base64_default_accept_garbage) ||
  ------------------
  |  Branch (730:7): [True: 0, False: 4.00k]
  ------------------
  731|  4.00k|      (options == base64_options::base64_default_or_url_accept_garbage);
  ------------------
  |  Branch (731:7): [True: 0, False: 4.00k]
  ------------------
  732|  4.00k|  auto ri = simdutf::scalar::base64::find_end(input, length, options);
  733|  4.00k|  size_t equallocation = ri.equallocation;
  734|  4.00k|  size_t equalsigns = ri.equalsigns;
  735|  4.00k|  length = ri.srclen;
  736|  4.00k|  size_t full_input_length = ri.full_input_length;
  737|  4.00k|  if (length == 0) {
  ------------------
  |  Branch (737:7): [True: 40, False: 3.96k]
  ------------------
  738|     40|    if (!ignore_garbage && equalsigns > 0) {
  ------------------
  |  Branch (738:9): [True: 40, False: 0]
  |  Branch (738:28): [True: 20, False: 20]
  ------------------
  739|     20|      return {INVALID_BASE64_CHARACTER, equallocation, 0, true};
  740|     20|    }
  741|     20|    return {SUCCESS, full_input_length, 0};
  742|     40|  }
  743|  3.96k|  full_result r = scalar::base64::base64_tail_decode(
  744|  3.96k|      output, input, length, equalsigns, options, last_chunk_options);
  745|  3.96k|  r = scalar::base64::patch_tail_result(r, 0, 0, equallocation,
  746|  3.96k|                                        full_input_length, last_chunk_options);
  747|  3.96k|  if (!is_partial(last_chunk_options) && r.error == error_code::SUCCESS &&
  ------------------
  |  Branch (747:7): [True: 2.29k, False: 1.67k]
  |  Branch (747:42): [True: 336, False: 1.95k]
  ------------------
  748|    336|      equalsigns > 0 && !ignore_garbage) {
  ------------------
  |  Branch (748:7): [True: 6, False: 330]
  |  Branch (748:25): [True: 6, False: 0]
  ------------------
  749|       |    // additional checks
  750|      6|    if ((r.output_count % 3 == 0) ||
  ------------------
  |  Branch (750:9): [True: 0, False: 6]
  ------------------
  751|      6|        ((r.output_count % 3) + 1 + equalsigns != 4)) {
  ------------------
  |  Branch (751:9): [True: 0, False: 6]
  ------------------
  752|      0|      return {INVALID_BASE64_CHARACTER, equallocation, r.output_count, true};
  753|      0|    }
  754|      6|  }
  755|       |  // When is_partial(last_chunk_options) is true, we must either end with
  756|       |  // the end of the stream (beyond whitespace) or right after a non-ignorable
  757|       |  // character or at the very beginning of the stream.
  758|       |  // See https://tc39.es/proposal-arraybuffer-base64/spec/#sec-frombase64
  759|  3.96k|  if (is_partial(last_chunk_options) && r.error == error_code::SUCCESS &&
  ------------------
  |  Branch (759:7): [True: 1.67k, False: 2.29k]
  |  Branch (759:41): [True: 806, False: 872]
  ------------------
  760|    806|      r.input_count < full_input_length) {
  ------------------
  |  Branch (760:7): [True: 576, False: 230]
  ------------------
  761|       |    // First check if we can extend the input to the end of the stream
  762|  6.42k|    while (r.input_count < full_input_length &&
  ------------------
  |  Branch (762:12): [True: 6.41k, False: 14]
  ------------------
  763|  6.41k|           base64_ignorable(*(input + r.input_count), options)) {
  ------------------
  |  Branch (763:12): [True: 5.84k, False: 562]
  ------------------
  764|  5.84k|      r.input_count++;
  765|  5.84k|    }
  766|       |    // If we are still not at the end of the stream, then we must backtrack
  767|       |    // to the last non-ignorable character.
  768|    576|    if (r.input_count < full_input_length) {
  ------------------
  |  Branch (768:9): [True: 562, False: 14]
  ------------------
  769|  6.13k|      while (r.input_count > 0 &&
  ------------------
  |  Branch (769:14): [True: 5.99k, False: 142]
  ------------------
  770|  5.99k|             base64_ignorable(*(input + r.input_count - 1), options)) {
  ------------------
  |  Branch (770:14): [True: 5.57k, False: 420]
  ------------------
  771|  5.57k|        r.input_count--;
  772|  5.57k|      }
  773|    562|    }
  774|    576|  }
  775|  3.96k|  return r;
  776|  3.96k|}
simdutf.cpp:_ZN7simdutf6scalar12_GLOBAL__N_16base6418base64_tail_decodeIDsEENS_11full_resultEPcPKT_mmNS_14base64_optionsENS_27last_chunk_handling_optionsE:
  371|  6.76k|    base64_options options, last_chunk_handling_options last_chunk_options) {
  372|  6.76k|  return base64_tail_decode_impl<false>(dst, 0, src, length, padding_characters,
  373|  6.76k|                                        options, last_chunk_options);
  374|  6.76k|}
simdutf.cpp:_ZN7simdutf6scalar12_GLOBAL__N_16base6423base64_tail_decode_implILb0EDsEENS_11full_resultEPcmPKT0_mmNS_14base64_optionsENS_27last_chunk_handling_optionsE:
  164|  6.76k|    base64_options options, last_chunk_handling_options last_chunk_options) {
  165|  6.76k|  char *dstend = dst + outlen;
  166|  6.76k|  (void)dstend;
  167|       |  // This looks like 10 branches, but we expect the compiler to resolve this to
  168|       |  // two branches (easily predicted):
  169|  6.76k|  const uint8_t *to_base64 =
  170|  6.76k|      (options & base64_default_or_url)
  ------------------
  |  Branch (170:7): [True: 0, False: 6.76k]
  ------------------
  171|  6.76k|          ? tables::base64::to_base64_default_or_url_value
  172|  6.76k|          : ((options & base64_url) ? tables::base64::to_base64_url_value
  ------------------
  |  Branch (172:14): [True: 3.44k, False: 3.32k]
  ------------------
  173|  6.76k|                                    : tables::base64::to_base64_value);
  174|  6.76k|  const uint32_t *d0 =
  175|  6.76k|      (options & base64_default_or_url)
  ------------------
  |  Branch (175:7): [True: 0, False: 6.76k]
  ------------------
  176|  6.76k|          ? tables::base64::base64_default_or_url::d0
  177|  6.76k|          : ((options & base64_url) ? tables::base64::base64_url::d0
  ------------------
  |  Branch (177:14): [True: 3.44k, False: 3.32k]
  ------------------
  178|  6.76k|                                    : tables::base64::base64_default::d0);
  179|  6.76k|  const uint32_t *d1 =
  180|  6.76k|      (options & base64_default_or_url)
  ------------------
  |  Branch (180:7): [True: 0, False: 6.76k]
  ------------------
  181|  6.76k|          ? tables::base64::base64_default_or_url::d1
  182|  6.76k|          : ((options & base64_url) ? tables::base64::base64_url::d1
  ------------------
  |  Branch (182:14): [True: 3.44k, False: 3.32k]
  ------------------
  183|  6.76k|                                    : tables::base64::base64_default::d1);
  184|  6.76k|  const uint32_t *d2 =
  185|  6.76k|      (options & base64_default_or_url)
  ------------------
  |  Branch (185:7): [True: 0, False: 6.76k]
  ------------------
  186|  6.76k|          ? tables::base64::base64_default_or_url::d2
  187|  6.76k|          : ((options & base64_url) ? tables::base64::base64_url::d2
  ------------------
  |  Branch (187:14): [True: 3.44k, False: 3.32k]
  ------------------
  188|  6.76k|                                    : tables::base64::base64_default::d2);
  189|  6.76k|  const uint32_t *d3 =
  190|  6.76k|      (options & base64_default_or_url)
  ------------------
  |  Branch (190:7): [True: 0, False: 6.76k]
  ------------------
  191|  6.76k|          ? tables::base64::base64_default_or_url::d3
  192|  6.76k|          : ((options & base64_url) ? tables::base64::base64_url::d3
  ------------------
  |  Branch (192:14): [True: 3.44k, False: 3.32k]
  ------------------
  193|  6.76k|                                    : tables::base64::base64_default::d3);
  194|  6.76k|  const bool ignore_garbage =
  195|  6.76k|      (options == base64_options::base64_url_accept_garbage) ||
  ------------------
  |  Branch (195:7): [True: 0, False: 6.76k]
  ------------------
  196|  6.76k|      (options == base64_options::base64_default_accept_garbage) ||
  ------------------
  |  Branch (196:7): [True: 0, False: 6.76k]
  ------------------
  197|  6.76k|      (options == base64_options::base64_default_or_url_accept_garbage);
  ------------------
  |  Branch (197:7): [True: 0, False: 6.76k]
  ------------------
  198|       |
  199|  6.76k|  const char_type *srcend = src + length;
  200|  6.76k|  const char_type *srcinit = src;
  201|  6.76k|  const char *dstinit = dst;
  202|       |
  203|  6.76k|  uint32_t x;
  204|  6.76k|  size_t idx;
  205|  6.76k|  uint8_t buffer[4];
  206|   111k|  while (true) {
  ------------------
  |  Branch (206:10): [True: 111k, Folded]
  ------------------
  207|  1.77M|    while (srcend - src >= 4 && is_eight_byte(src[0]) &&
  ------------------
  |  Branch (207:12): [True: 1.77M, False: 2.81k]
  |  Branch (207:33): [True: 1.77M, False: 534]
  ------------------
  208|  1.77M|           is_eight_byte(src[1]) && is_eight_byte(src[2]) &&
  ------------------
  |  Branch (208:12): [True: 1.77M, False: 422]
  |  Branch (208:37): [True: 1.77M, False: 386]
  ------------------
  209|  1.77M|           is_eight_byte(src[3]) &&
  ------------------
  |  Branch (209:12): [True: 1.77M, False: 422]
  ------------------
  210|  1.77M|           (x = d0[uint8_t(src[0])] | d1[uint8_t(src[1])] |
  ------------------
  |  Branch (210:12): [True: 1.66M, False: 106k]
  ------------------
  211|  1.77M|                d2[uint8_t(src[2])] | d3[uint8_t(src[3])]) < 0x01FFFFFF) {
  212|  1.66M|      if (check_capacity && dstend - dst < 3) {
  ------------------
  |  Branch (212:11): [Folded, False: 1.66M]
  |  Branch (212:29): [True: 0, False: 0]
  ------------------
  213|      0|        return {OUTPUT_BUFFER_TOO_SMALL, size_t(src - srcinit),
  214|      0|                size_t(dst - dstinit)};
  215|      0|      }
  216|  1.66M|      *dst++ = static_cast<char>(x & 0xFF);
  217|  1.66M|      *dst++ = static_cast<char>((x >> 8) & 0xFF);
  218|  1.66M|      *dst++ = static_cast<char>((x >> 16) & 0xFF);
  219|  1.66M|      src += 4;
  220|  1.66M|    }
  221|   111k|    const char_type *srccur = src;
  222|   111k|    idx = 0;
  223|       |    // we need at least four characters.
  224|   111k|#ifdef __clang__
  225|       |    // If possible, we read four characters at a time. (It is an optimization.)
  226|   111k|    if (ignore_garbage && src + 4 <= srcend) {
  ------------------
  |  Branch (226:9): [True: 0, False: 111k]
  |  Branch (226:27): [True: 0, False: 0]
  ------------------
  227|      0|      char_type c0 = src[0];
  228|      0|      char_type c1 = src[1];
  229|      0|      char_type c2 = src[2];
  230|      0|      char_type c3 = src[3];
  231|       |
  232|      0|      uint8_t code0 = to_base64[uint8_t(c0)];
  233|      0|      uint8_t code1 = to_base64[uint8_t(c1)];
  234|      0|      uint8_t code2 = to_base64[uint8_t(c2)];
  235|      0|      uint8_t code3 = to_base64[uint8_t(c3)];
  236|       |
  237|      0|      buffer[idx] = code0;
  238|      0|      idx += (is_eight_byte(c0) && code0 <= 63);
  ------------------
  |  Branch (238:15): [True: 0, False: 0]
  |  Branch (238:36): [True: 0, False: 0]
  ------------------
  239|      0|      buffer[idx] = code1;
  240|      0|      idx += (is_eight_byte(c1) && code1 <= 63);
  ------------------
  |  Branch (240:15): [True: 0, False: 0]
  |  Branch (240:36): [True: 0, False: 0]
  ------------------
  241|      0|      buffer[idx] = code2;
  242|      0|      idx += (is_eight_byte(c2) && code2 <= 63);
  ------------------
  |  Branch (242:15): [True: 0, False: 0]
  |  Branch (242:36): [True: 0, False: 0]
  ------------------
  243|      0|      buffer[idx] = code3;
  244|      0|      idx += (is_eight_byte(c3) && code3 <= 63);
  ------------------
  |  Branch (244:15): [True: 0, False: 0]
  |  Branch (244:36): [True: 0, False: 0]
  ------------------
  245|      0|      src += 4;
  246|      0|    }
  247|   111k|#endif
  248|   780k|    while ((idx < 4) && (src < srcend)) {
  ------------------
  |  Branch (248:12): [True: 675k, False: 104k]
  |  Branch (248:25): [True: 672k, False: 3.27k]
  ------------------
  249|   672k|      char_type c = *src;
  250|       |
  251|   672k|      uint8_t code = to_base64[uint8_t(c)];
  252|   672k|      buffer[idx] = uint8_t(code);
  253|   672k|      if (is_eight_byte(c) && code <= 63) {
  ------------------
  |  Branch (253:11): [True: 670k, False: 2.64k]
  |  Branch (253:31): [True: 427k, False: 242k]
  ------------------
  254|   427k|        idx++;
  255|   427k|      } else if (!ignore_garbage &&
  ------------------
  |  Branch (255:18): [True: 245k, False: 0]
  ------------------
  256|   245k|                 (code > 64 || !scalar::base64::is_eight_byte(c))) {
  ------------------
  |  Branch (256:19): [True: 2.09k, False: 242k]
  |  Branch (256:32): [True: 1.39k, False: 241k]
  ------------------
  257|  3.48k|        return {INVALID_BASE64_CHARACTER, size_t(src - srcinit),
  258|  3.48k|                size_t(dst - dstinit)};
  259|   241k|      } else {
  260|       |        // We have a space or a newline or garbage. We ignore it.
  261|   241k|      }
  262|   669k|      src++;
  263|   669k|    }
  264|   108k|    if (idx != 4) {
  ------------------
  |  Branch (264:9): [True: 3.27k, False: 104k]
  ------------------
  265|  3.27k|      simdutf_log_assert(idx < 4, "idx should be less than 4");
  266|       |      // We never should have that the number of base64 characters + the
  267|       |      // number of padding characters is more than 4.
  268|  3.27k|      if (!ignore_garbage && (idx + padding_characters > 4)) {
  ------------------
  |  Branch (268:11): [True: 3.27k, False: 0]
  |  Branch (268:30): [True: 6, False: 3.27k]
  ------------------
  269|      6|        return {INVALID_BASE64_CHARACTER, size_t(src - srcinit),
  270|      6|                size_t(dst - dstinit), true};
  271|      6|      }
  272|       |
  273|       |      // The idea here is that in loose mode,
  274|       |      // if there is padding at all, it must be used
  275|       |      // to form 4-wise chunk. However, in loose mode,
  276|       |      // we do accept no padding at all.
  277|  3.27k|      if (!ignore_garbage &&
  ------------------
  |  Branch (277:11): [True: 3.27k, False: 0]
  ------------------
  278|  3.27k|          last_chunk_options == last_chunk_handling_options::loose &&
  ------------------
  |  Branch (278:11): [True: 862, False: 2.41k]
  ------------------
  279|    862|          (idx >= 2) && padding_characters > 0 &&
  ------------------
  |  Branch (279:11): [True: 504, False: 358]
  |  Branch (279:25): [True: 12, False: 492]
  ------------------
  280|     12|          ((idx + padding_characters) & 3) != 0) {
  ------------------
  |  Branch (280:11): [True: 6, False: 6]
  ------------------
  281|      6|        return {INVALID_BASE64_CHARACTER, size_t(src - srcinit),
  282|      6|                size_t(dst - dstinit), true};
  283|      6|      } else
  284|       |
  285|       |        // The idea here is that in strict mode, we do not want to accept
  286|       |        // incomplete base64 chunks. So if the chunk was otherwise valid, we
  287|       |        // return BASE64_INPUT_REMAINDER.
  288|  3.26k|        if (!ignore_garbage &&
  ------------------
  |  Branch (288:13): [True: 3.26k, False: 0]
  ------------------
  289|  3.26k|            last_chunk_options == last_chunk_handling_options::strict &&
  ------------------
  |  Branch (289:13): [True: 280, False: 2.98k]
  ------------------
  290|    280|            (idx >= 2) && ((idx + padding_characters) & 3) != 0) {
  ------------------
  |  Branch (290:13): [True: 150, False: 130]
  |  Branch (290:27): [True: 114, False: 36]
  ------------------
  291|       |          // The partial chunk was at src - idx
  292|    114|          return {BASE64_INPUT_REMAINDER, size_t(src - srcinit),
  293|    114|                  size_t(dst - dstinit), true};
  294|    114|        } else
  295|       |          // If there is a partial chunk with insufficient padding, with
  296|       |          // stop_before_partial, we need to just ignore it. In "only full"
  297|       |          // mode, skip the minute there are padding characters.
  298|  3.15k|          if ((last_chunk_options ==
  ------------------
  |  Branch (298:16): [True: 2.13k, False: 1.02k]
  ------------------
  299|  3.15k|                   last_chunk_handling_options::stop_before_partial &&
  300|  2.13k|               (padding_characters + idx < 4) && (idx != 0) &&
  ------------------
  |  Branch (300:16): [True: 2.11k, False: 12]
  |  Branch (300:50): [True: 1.71k, False: 402]
  ------------------
  301|  1.71k|               (idx >= 2 || padding_characters == 0)) ||
  ------------------
  |  Branch (301:17): [True: 810, False: 906]
  |  Branch (301:29): [True: 876, False: 30]
  ------------------
  302|  1.46k|              (last_chunk_options ==
  ------------------
  |  Branch (302:16): [True: 0, False: 1.46k]
  ------------------
  303|  1.46k|                   last_chunk_handling_options::only_full_chunks &&
  304|  1.68k|               (idx >= 2 || padding_characters == 0))) {
  ------------------
  |  Branch (304:17): [True: 0, False: 0]
  |  Branch (304:29): [True: 0, False: 0]
  ------------------
  305|       |            // partial means that we are *not* going to consume the read
  306|       |            // characters. We need to rewind the src pointer.
  307|  1.68k|            src = srccur;
  308|  1.68k|            return {SUCCESS, size_t(src - srcinit), size_t(dst - dstinit)};
  309|  1.68k|          } else {
  310|  1.46k|            if (idx == 2) {
  ------------------
  |  Branch (310:17): [True: 270, False: 1.19k]
  ------------------
  311|    270|              uint32_t triple = (uint32_t(buffer[0]) << 3 * 6) +
  312|    270|                                (uint32_t(buffer[1]) << 2 * 6);
  313|    270|              if (!ignore_garbage &&
  ------------------
  |  Branch (313:19): [True: 270, False: 0]
  ------------------
  314|    270|                  (last_chunk_options == last_chunk_handling_options::strict) &&
  ------------------
  |  Branch (314:19): [True: 24, False: 246]
  ------------------
  315|     24|                  (triple & 0xffff)) {
  ------------------
  |  Branch (315:19): [True: 18, False: 6]
  ------------------
  316|     18|                return {BASE64_EXTRA_BITS, size_t(src - srcinit),
  317|     18|                        size_t(dst - dstinit)};
  318|     18|              }
  319|    252|              if (check_capacity && dstend - dst < 1) {
  ------------------
  |  Branch (319:19): [Folded, False: 252]
  |  Branch (319:37): [True: 0, False: 0]
  ------------------
  320|      0|                return {OUTPUT_BUFFER_TOO_SMALL, size_t(srccur - srcinit),
  321|      0|                        size_t(dst - dstinit)};
  322|      0|              }
  323|    252|              *dst++ = static_cast<char>((triple >> 16) & 0xFF);
  324|  1.19k|            } else if (idx == 3) {
  ------------------
  |  Branch (324:24): [True: 276, False: 920]
  ------------------
  325|    276|              uint32_t triple = (uint32_t(buffer[0]) << 3 * 6) +
  326|    276|                                (uint32_t(buffer[1]) << 2 * 6) +
  327|    276|                                (uint32_t(buffer[2]) << 1 * 6);
  328|    276|              if (!ignore_garbage &&
  ------------------
  |  Branch (328:19): [True: 276, False: 0]
  ------------------
  329|    276|                  (last_chunk_options == last_chunk_handling_options::strict) &&
  ------------------
  |  Branch (329:19): [True: 12, False: 264]
  ------------------
  330|     12|                  (triple & 0xff)) {
  ------------------
  |  Branch (330:19): [True: 6, False: 6]
  ------------------
  331|      6|                return {BASE64_EXTRA_BITS, size_t(src - srcinit),
  332|      6|                        size_t(dst - dstinit)};
  333|      6|              }
  334|    270|              if (check_capacity && dstend - dst < 2) {
  ------------------
  |  Branch (334:19): [Folded, False: 270]
  |  Branch (334:37): [True: 0, False: 0]
  ------------------
  335|      0|                return {OUTPUT_BUFFER_TOO_SMALL, size_t(srccur - srcinit),
  336|      0|                        size_t(dst - dstinit)};
  337|      0|              }
  338|    270|              *dst++ = static_cast<char>((triple >> 16) & 0xFF);
  339|    270|              *dst++ = static_cast<char>((triple >> 8) & 0xFF);
  340|    920|            } else if (!ignore_garbage && idx == 1 &&
  ------------------
  |  Branch (340:24): [True: 920, False: 0]
  |  Branch (340:43): [True: 234, False: 686]
  ------------------
  341|    234|                       (!is_partial(last_chunk_options) ||
  ------------------
  |  Branch (341:25): [True: 204, False: 30]
  ------------------
  342|     30|                        (is_partial(last_chunk_options) &&
  ------------------
  |  Branch (342:26): [True: 30, False: 0]
  ------------------
  343|    234|                         padding_characters > 0))) {
  ------------------
  |  Branch (343:26): [True: 30, False: 0]
  ------------------
  344|    234|              return {BASE64_INPUT_REMAINDER, size_t(src - srcinit),
  345|    234|                      size_t(dst - dstinit)};
  346|    686|            } else if (!ignore_garbage && idx == 0 && padding_characters > 0) {
  ------------------
  |  Branch (346:24): [True: 686, False: 0]
  |  Branch (346:43): [True: 686, False: 0]
  |  Branch (346:55): [True: 24, False: 662]
  ------------------
  347|     24|              return {INVALID_BASE64_CHARACTER, size_t(src - srcinit),
  348|     24|                      size_t(dst - dstinit), true};
  349|     24|            }
  350|  1.18k|            return {SUCCESS, size_t(src - srcinit), size_t(dst - dstinit)};
  351|  1.46k|          }
  352|  3.27k|    }
  353|   104k|    if (check_capacity && dstend - dst < 3) {
  ------------------
  |  Branch (353:9): [Folded, False: 104k]
  |  Branch (353:27): [True: 0, False: 0]
  ------------------
  354|      0|      return {OUTPUT_BUFFER_TOO_SMALL, size_t(srccur - srcinit),
  355|      0|              size_t(dst - dstinit)};
  356|      0|    }
  357|   104k|    uint32_t triple =
  358|   104k|        (uint32_t(buffer[0]) << 3 * 6) + (uint32_t(buffer[1]) << 2 * 6) +
  359|   104k|        (uint32_t(buffer[2]) << 1 * 6) + (uint32_t(buffer[3]) << 0 * 6);
  360|   104k|    *dst++ = static_cast<char>((triple >> 16) & 0xFF);
  361|   104k|    *dst++ = static_cast<char>((triple >> 8) & 0xFF);
  362|   104k|    *dst++ = static_cast<char>(triple & 0xFF);
  363|   104k|  }
  364|  6.76k|}

_ZN7simdutf6scalar14u32_swap_bytesEj:
   13|  30.3k|u32_swap_bytes(const uint32_t word) {
   14|  30.3k|  return ((word >> 24) & 0xff) |      // move byte 3 to byte 0
   15|  30.3k|         ((word << 8) & 0xff0000) |   // move byte 1 to byte 2
   16|  30.3k|         ((word >> 8) & 0xff00) |     // move byte 2 to byte 1
   17|  30.3k|         ((word << 24) & 0xff000000); // byte 0 to byte 3
   18|  30.3k|}

_ZNK7simdutf8fallback14implementation16base64_to_binaryEPKcmPcNS_14base64_optionsENS_27last_chunk_handling_optionsE:
  541|  2.03k|    last_chunk_handling_options last_chunk_options) const noexcept {
  542|  2.03k|  return simdutf::scalar::base64::base64_to_binary_details_impl(
  543|  2.03k|      input, length, output, options, last_chunk_options);
  544|  2.03k|}
_ZNK7simdutf8fallback14implementation16base64_to_binaryEPKDsmPcNS_14base64_optionsENS_27last_chunk_handling_optionsE:
  548|  2.00k|    last_chunk_handling_options last_chunk_options) const noexcept {
  549|  2.00k|  return simdutf::scalar::base64::base64_to_binary_details_impl(
  550|  2.00k|      input, length, output, options, last_chunk_options);
  551|  2.00k|}
_ZNK7simdutf8fallback14implementation24base64_to_binary_detailsEPKcmPcNS_14base64_optionsENS_27last_chunk_handling_optionsE:
  555|  2.03k|    last_chunk_handling_options last_chunk_options) const noexcept {
  556|  2.03k|  return simdutf::scalar::base64::base64_to_binary_details_impl(
  557|  2.03k|      input, length, output, options, last_chunk_options);
  558|  2.03k|}
_ZNK7simdutf8fallback14implementation24base64_to_binary_detailsEPKDsmPcNS_14base64_optionsENS_27last_chunk_handling_optionsE:
  562|  2.00k|    last_chunk_handling_options last_chunk_options) const noexcept {
  563|  2.00k|  return simdutf::scalar::base64::base64_to_binary_details_impl(
  564|  2.00k|      input, length, output, options, last_chunk_options);
  565|  2.00k|}

simdutf.cpp:_ZN7simdutf7haswell12_GLOBAL__N_16base6422compress_decode_base64ILb1ELb0ELb0EcEENS_11full_resultEPcPKT2_mNS_14base64_optionsENS_27last_chunk_handling_optionsE:
   45|  1.96k|                       last_chunk_handling_options last_chunk_options) {
   46|  1.96k|  const uint8_t *to_base64 =
   47|  1.96k|      default_or_url ? tables::base64::to_base64_default_or_url_value
  ------------------
  |  Branch (47:7): [Folded, False: 1.96k]
  ------------------
   48|  1.96k|                     : (base64_url ? tables::base64::to_base64_url_value
  ------------------
  |  Branch (48:25): [True: 1.96k, Folded]
  ------------------
   49|  1.96k|                                   : tables::base64::to_base64_value);
   50|  1.96k|  auto ri =
   51|  1.96k|      ignore_garbage
  ------------------
  |  Branch (51:7): [Folded, False: 1.96k]
  ------------------
   52|  1.96k|          ? simdutf::scalar::base64::reduced_input{0, srclen, srclen, srclen}
   53|  1.96k|          : simdutf::scalar::base64::find_end(src, srclen, options);
   54|  1.96k|  size_t equallocation = ri.equallocation;
   55|  1.96k|  size_t equalsigns = ri.equalsigns;
   56|  1.96k|  srclen = ri.srclen;
   57|  1.96k|  size_t full_input_length = ri.full_input_length;
   58|  1.96k|  if (srclen == 0) {
  ------------------
  |  Branch (58:7): [True: 16, False: 1.94k]
  ------------------
   59|     16|    if (!ignore_garbage && equalsigns > 0) {
  ------------------
  |  Branch (59:9): [True: 16, Folded]
  |  Branch (59:28): [True: 4, False: 12]
  ------------------
   60|      4|      return {INVALID_BASE64_CHARACTER, equallocation, 0, true};
   61|      4|    }
   62|     12|    return {SUCCESS, full_input_length, 0};
   63|     16|  }
   64|  1.94k|  const chartype *const srcinit = src;
   65|  1.94k|  const char *const dstinit = dst;
   66|  1.94k|  const chartype *srcend = src + srclen;
   67|       |
   68|  1.94k|  constexpr size_t block_size = 6;
   69|  1.94k|  static_assert(block_size >= 2, "block_size must be at least two");
   70|  1.94k|  char buffer[block_size * 64];
   71|  1.94k|  char *bufferptr = buffer;
   72|       |  // A wide block store writes 4 bytes past its 48. That is safe when the next
   73|       |  // store starts 48 bytes later. Pairs of clean blocks wide-store the first
   74|       |  // and end the second on byte 48. Anything shorter, or a block that is not
   75|       |  // clean, uses the exact store. The pair attempt is only worth it on a long
   76|       |  // input: a short one often fails the first block and then repeats that work.
   77|  1.94k|  if (srclen >= 512) {
  ------------------
  |  Branch (77:7): [True: 1.02k, False: 920]
  ------------------
   78|  1.02k|    const chartype *const srcend128 = src + srclen - 128;
   79|  25.0k|    while (bufferptr == buffer && src <= srcend128) {
  ------------------
  |  Branch (79:12): [True: 25.0k, False: 0]
  |  Branch (79:35): [True: 25.0k, False: 16]
  ------------------
   80|  25.0k|      block64 b0(src);
   81|  25.0k|      uint64_t e0 = 0;
   82|  25.0k|      const uint64_t m0 =
   83|  25.0k|          b0.to_base64_mask<base64_url, ignore_garbage, default_or_url>(&e0);
   84|  25.0k|      if ((!ignore_garbage && e0) || m0 != 0) {
  ------------------
  |  Branch (84:12): [True: 25.0k, Folded]
  |  Branch (84:31): [True: 250, False: 24.8k]
  |  Branch (84:38): [True: 336, False: 24.4k]
  ------------------
   85|    586|        break;
   86|    586|      }
   87|  24.4k|      block64 b1(src + 64);
   88|  24.4k|      uint64_t e1 = 0;
   89|  24.4k|      const uint64_t m1 =
   90|  24.4k|          b1.to_base64_mask<base64_url, ignore_garbage, default_or_url>(&e1);
   91|  24.4k|      if ((!ignore_garbage && e1) || m1 != 0) {
  ------------------
  |  Branch (91:12): [True: 24.4k, Folded]
  |  Branch (91:31): [True: 216, False: 24.2k]
  |  Branch (91:38): [True: 208, False: 24.0k]
  ------------------
   92|    424|        break;
   93|    424|      }
   94|  24.0k|      b0.base64_decode_block(dst);
   95|  24.0k|      b1.template base64_decode_block<true>(dst + 48);
   96|  24.0k|      src += 128;
   97|  24.0k|      dst += 96;
   98|  24.0k|    }
   99|  1.02k|  }
  100|  1.94k|  if (srclen >= 64) {
  ------------------
  |  Branch (100:7): [True: 1.71k, False: 230]
  ------------------
  101|  1.71k|    const chartype *const srcend64 = srcinit + srclen - 64;
  102|  54.2k|    while (src <= srcend64) {
  ------------------
  |  Branch (102:12): [True: 53.6k, False: 576]
  ------------------
  103|  53.6k|      block64 b(src);
  104|  53.6k|      uint64_t error = 0;
  105|  53.6k|      const uint64_t badcharmask =
  106|  53.6k|          b.to_base64_mask<base64_url, ignore_garbage, default_or_url>(&error);
  107|  53.6k|      if (!ignore_garbage && error) {
  ------------------
  |  Branch (107:11): [True: 53.6k, Folded]
  |  Branch (107:30): [True: 1.14k, False: 52.5k]
  ------------------
  108|  1.14k|        const size_t error_offset = trailing_zeroes(error);
  109|  1.14k|        return {error_code::INVALID_BASE64_CHARACTER,
  110|  1.14k|                size_t(src - srcinit + error_offset), size_t(dst - dstinit)};
  111|  1.14k|      }
  112|  52.5k|      if (ignore_garbage && badcharmask != 0) {
  ------------------
  |  Branch (112:11): [Folded, False: 52.5k]
  |  Branch (112:29): [True: 0, False: 0]
  ------------------
  113|      0|        const uint64_t equals = block64(src).equal_sign_mask();
  114|      0|        if (equals != 0) {
  ------------------
  |  Branch (114:13): [True: 0, False: 0]
  ------------------
  115|      0|          const size_t offset = trailing_zeroes(equals);
  116|      0|          equallocation = size_t(src - srcinit) + offset;
  117|      0|          equalsigns = 1;
  118|      0|          srclen = equallocation;
  119|      0|          full_input_length = equallocation + 1;
  120|      0|          if (srclen == 0) {
  ------------------
  |  Branch (120:15): [True: 0, False: 0]
  ------------------
  121|      0|            return {SUCCESS, full_input_length, 0};
  122|      0|          }
  123|      0|          srcend = srcinit + srclen;
  124|      0|          src = srcend;
  125|      0|          bufferptr += b.compress_block(badcharmask | (~uint64_t(0) << offset),
  126|      0|                                        bufferptr);
  127|      0|          break;
  128|      0|        }
  129|      0|      }
  130|  52.5k|      src += 64;
  131|  52.5k|      if (badcharmask != 0) {
  ------------------
  |  Branch (131:11): [True: 27.6k, False: 24.9k]
  ------------------
  132|  27.6k|        bufferptr += b.compress_block(badcharmask, bufferptr);
  133|  27.6k|      } else if (bufferptr != buffer) {
  ------------------
  |  Branch (133:18): [True: 24.2k, False: 752]
  ------------------
  134|  24.2k|        b.copy_block(bufferptr);
  135|  24.2k|        bufferptr += 64;
  136|  24.2k|      } else {
  137|    752|        b.template base64_decode_block<true>(dst);
  138|    752|        dst += 48;
  139|    752|      }
  140|  52.5k|      if (bufferptr >= (block_size - 1) * 64 + buffer) {
  ------------------
  |  Branch (140:11): [True: 9.82k, False: 42.7k]
  ------------------
  141|  49.1k|        for (size_t i = 0; i < (block_size - 2); i++) {
  ------------------
  |  Branch (141:28): [True: 39.2k, False: 9.82k]
  ------------------
  142|  39.2k|          base64_decode_block(dst, buffer + i * 64);
  143|  39.2k|          dst += 48;
  144|  39.2k|        }
  145|  9.82k|        base64_decode_block<true>(dst, buffer + (block_size - 2) * 64);
  146|  9.82k|        dst += 48;
  147|  9.82k|        std::memcpy(buffer, buffer + (block_size - 1) * 64,
  148|  9.82k|                    64); // 64 might be too much
  149|  9.82k|        bufferptr -= (block_size - 1) * 64;
  150|  9.82k|      }
  151|  52.5k|    }
  152|  1.71k|  }
  153|       |
  154|    806|  if (ignore_garbage && equalsigns == 0) {
  ------------------
  |  Branch (154:7): [Folded, False: 806]
  |  Branch (154:25): [True: 0, False: 0]
  ------------------
  155|      0|    const chartype *equal = src;
  156|      0|    while (equal < srcend && *equal != '=') {
  ------------------
  |  Branch (156:12): [True: 0, False: 0]
  |  Branch (156:30): [True: 0, False: 0]
  ------------------
  157|      0|      equal++;
  158|      0|    }
  159|      0|    if (equal < srcend) {
  ------------------
  |  Branch (159:9): [True: 0, False: 0]
  ------------------
  160|      0|      equallocation = size_t(equal - srcinit);
  161|      0|      equalsigns = 1;
  162|      0|      srclen = equallocation;
  163|      0|      full_input_length = equallocation + 1;
  164|      0|      if (srclen == 0) {
  ------------------
  |  Branch (164:11): [True: 0, False: 0]
  ------------------
  165|      0|        return {SUCCESS, full_input_length, 0};
  166|      0|      }
  167|      0|      srcend = equal;
  168|      0|    }
  169|      0|  }
  170|    806|  char *buffer_start = buffer;
  171|       |  // Optimization note: if this is almost full, then it is worth our
  172|       |  // time, otherwise, we should just decode directly.
  173|    806|  int last_block = (int)((bufferptr - buffer_start) % 64);
  174|    806|  if (last_block != 0 && srcend - src + last_block >= 64) {
  ------------------
  |  Branch (174:7): [True: 526, False: 280]
  |  Branch (174:26): [True: 70, False: 456]
  ------------------
  175|       |
  176|    788|    while ((bufferptr - buffer_start) % 64 != 0 && src < srcend) {
  ------------------
  |  Branch (176:12): [True: 740, False: 48]
  |  Branch (176:52): [True: 724, False: 16]
  ------------------
  177|    724|      uint8_t val = to_base64[uint8_t(*src)];
  178|    724|      *bufferptr = char(val);
  179|    724|      if (!ignore_garbage &&
  ------------------
  |  Branch (179:11): [True: 724, Folded]
  ------------------
  180|    724|          (!scalar::base64::is_eight_byte(*src) || val > 64)) {
  ------------------
  |  Branch (180:12): [True: 0, False: 724]
  |  Branch (180:52): [True: 6, False: 718]
  ------------------
  181|      6|        return {error_code::INVALID_BASE64_CHARACTER, size_t(src - srcinit),
  182|      6|                size_t(dst - dstinit)};
  183|      6|      }
  184|    718|      bufferptr += (val <= 63 && scalar::base64::is_eight_byte(*src));
  ------------------
  |  Branch (184:21): [True: 384, False: 334]
  |  Branch (184:34): [True: 384, False: 0]
  ------------------
  185|    718|      src++;
  186|    718|    }
  187|     70|  }
  188|       |
  189|  1.22k|  for (; buffer_start + 64 <= bufferptr; buffer_start += 64) {
  ------------------
  |  Branch (189:10): [True: 424, False: 800]
  ------------------
  190|       |    // 8 payload bytes still in the buffer become 6 output bytes, which cover
  191|       |    // the 4-byte tail of a wide store. Fewer than that, and the tail can
  192|       |    // stick out past the real end.
  193|    424|    const size_t after = size_t(bufferptr - (buffer_start + 64));
  194|    424|    if (after >= 8) {
  ------------------
  |  Branch (194:9): [True: 354, False: 70]
  ------------------
  195|    354|      base64_decode_block(dst, buffer_start);
  196|    354|    } else {
  197|     70|      base64_decode_block<true>(dst, buffer_start);
  198|     70|    }
  199|    424|    dst += 48;
  200|    424|  }
  201|    800|  if ((bufferptr - buffer_start) % 64 != 0) {
  ------------------
  |  Branch (201:7): [True: 472, False: 328]
  ------------------
  202|  4.19k|    while (buffer_start + 4 < bufferptr) {
  ------------------
  |  Branch (202:12): [True: 3.72k, False: 472]
  ------------------
  203|  3.72k|      uint32_t triple = ((uint32_t(uint8_t(buffer_start[0])) << 3 * 6) +
  204|  3.72k|                         (uint32_t(uint8_t(buffer_start[1])) << 2 * 6) +
  205|  3.72k|                         (uint32_t(uint8_t(buffer_start[2])) << 1 * 6) +
  206|  3.72k|                         (uint32_t(uint8_t(buffer_start[3])) << 0 * 6))
  207|  3.72k|                        << 8;
  208|  3.72k|#if !SIMDUTF_IS_BIG_ENDIAN
  209|  3.72k|      triple = scalar::u32_swap_bytes(triple);
  210|  3.72k|#endif
  211|  3.72k|      std::memcpy(dst, &triple, 3);
  212|       |
  213|  3.72k|      dst += 3;
  214|  3.72k|      buffer_start += 4;
  215|  3.72k|    }
  216|    472|    if (buffer_start + 4 <= bufferptr) {
  ------------------
  |  Branch (216:9): [True: 124, False: 348]
  ------------------
  217|    124|      uint32_t triple = ((uint32_t(uint8_t(buffer_start[0])) << 3 * 6) +
  218|    124|                         (uint32_t(uint8_t(buffer_start[1])) << 2 * 6) +
  219|    124|                         (uint32_t(uint8_t(buffer_start[2])) << 1 * 6) +
  220|    124|                         (uint32_t(uint8_t(buffer_start[3])) << 0 * 6))
  221|    124|                        << 8;
  222|    124|#if !SIMDUTF_IS_BIG_ENDIAN
  223|    124|      triple = scalar::u32_swap_bytes(triple);
  224|    124|#endif
  225|    124|      std::memcpy(dst, &triple, 3);
  226|       |
  227|    124|      dst += 3;
  228|    124|      buffer_start += 4;
  229|    124|    }
  230|       |    // we may have 1, 2 or 3 bytes left and we need to decode them so let us
  231|       |    // backtrack
  232|    472|    int leftover = int(bufferptr - buffer_start);
  233|  1.14k|    while (leftover > 0) {
  ------------------
  |  Branch (233:12): [True: 674, False: 472]
  ------------------
  234|    674|      if (!ignore_garbage) {
  ------------------
  |  Branch (234:11): [True: 674, Folded]
  ------------------
  235|  4.63k|        while (to_base64[uint8_t(*(src - 1))] == 64) {
  ------------------
  |  Branch (235:16): [True: 3.95k, False: 674]
  ------------------
  236|  3.95k|          src--;
  237|  3.95k|        }
  238|    674|      } else {
  239|      0|        while (!scalar::base64::is_eight_byte(*(src - 1)) ||
  ------------------
  |  Branch (239:16): [True: 0, False: 0]
  ------------------
  240|      0|               to_base64[uint8_t(*(src - 1))] >= 64) {
  ------------------
  |  Branch (240:16): [True: 0, False: 0]
  ------------------
  241|      0|          src--;
  242|      0|        }
  243|      0|      }
  244|    674|      src--;
  245|    674|      leftover--;
  246|    674|    }
  247|    472|  }
  248|    800|  if (src < srcend + equalsigns) {
  ------------------
  |  Branch (248:7): [True: 630, False: 170]
  ------------------
  249|    630|    full_result r = scalar::base64::base64_tail_decode(
  250|    630|        dst, src, srcend - src, equalsigns, options, last_chunk_options);
  251|    630|    r = scalar::base64::patch_tail_result(
  252|    630|        r, size_t(src - srcinit), size_t(dst - dstinit), equallocation,
  253|    630|        full_input_length, last_chunk_options);
  254|       |    // When is_partial(last_chunk_options) is true, we must either end with
  255|       |    // the end of the stream (beyond whitespace) or right after a non-ignorable
  256|       |    // character or at the very beginning of the stream.
  257|       |    // See https://tc39.es/proposal-arraybuffer-base64/spec/#sec-frombase64
  258|    630|    if (is_partial(last_chunk_options) && r.error == error_code::SUCCESS &&
  ------------------
  |  Branch (258:9): [True: 320, False: 310]
  |  Branch (258:43): [True: 302, False: 18]
  ------------------
  259|    302|        r.input_count < full_input_length) {
  ------------------
  |  Branch (259:9): [True: 260, False: 42]
  ------------------
  260|       |      // First check if we can extend the input to the end of the stream
  261|    714|      while (r.input_count < full_input_length &&
  ------------------
  |  Branch (261:14): [True: 708, False: 6]
  ------------------
  262|    708|             base64_ignorable(*(srcinit + r.input_count), options)) {
  ------------------
  |  Branch (262:14): [True: 454, False: 254]
  ------------------
  263|    454|        r.input_count++;
  264|    454|      }
  265|       |      // If we are still not at the end of the stream, then we must backtrack
  266|       |      // to the last non-ignorable character.
  267|    260|      if (r.input_count < full_input_length) {
  ------------------
  |  Branch (267:11): [True: 254, False: 6]
  ------------------
  268|  1.79k|        while (r.input_count > 0 &&
  ------------------
  |  Branch (268:16): [True: 1.73k, False: 56]
  ------------------
  269|  1.73k|               base64_ignorable(*(srcinit + r.input_count - 1), options)) {
  ------------------
  |  Branch (269:16): [True: 1.54k, False: 198]
  ------------------
  270|  1.54k|          r.input_count--;
  271|  1.54k|        }
  272|    254|      }
  273|    260|    }
  274|    630|    return r;
  275|    630|  }
  276|    170|  if (!ignore_garbage && equalsigns > 0) {
  ------------------
  |  Branch (276:7): [True: 170, Folded]
  |  Branch (276:26): [True: 0, False: 170]
  ------------------
  277|      0|    if ((size_t(dst - dstinit) % 3 == 0) ||
  ------------------
  |  Branch (277:9): [True: 0, False: 0]
  ------------------
  278|      0|        ((size_t(dst - dstinit) % 3) + 1 + equalsigns != 4)) {
  ------------------
  |  Branch (278:9): [True: 0, False: 0]
  ------------------
  279|      0|      return {INVALID_BASE64_CHARACTER, equallocation, size_t(dst - dstinit),
  280|      0|              true};
  281|      0|    }
  282|      0|  }
  283|    170|  return {SUCCESS, srclen, size_t(dst - dstinit)};
  284|    170|}
simdutf.cpp:_ZN7simdutf7haswell12_GLOBAL__N_16base6422compress_decode_base64ILb0ELb0ELb0EcEENS_11full_resultEPcPKT2_mNS_14base64_optionsENS_27last_chunk_handling_optionsE:
   45|  2.11k|                       last_chunk_handling_options last_chunk_options) {
   46|  2.11k|  const uint8_t *to_base64 =
   47|  2.11k|      default_or_url ? tables::base64::to_base64_default_or_url_value
  ------------------
  |  Branch (47:7): [Folded, False: 2.11k]
  ------------------
   48|  2.11k|                     : (base64_url ? tables::base64::to_base64_url_value
  ------------------
  |  Branch (48:25): [Folded, False: 2.11k]
  ------------------
   49|  2.11k|                                   : tables::base64::to_base64_value);
   50|  2.11k|  auto ri =
   51|  2.11k|      ignore_garbage
  ------------------
  |  Branch (51:7): [Folded, False: 2.11k]
  ------------------
   52|  2.11k|          ? simdutf::scalar::base64::reduced_input{0, srclen, srclen, srclen}
   53|  2.11k|          : simdutf::scalar::base64::find_end(src, srclen, options);
   54|  2.11k|  size_t equallocation = ri.equallocation;
   55|  2.11k|  size_t equalsigns = ri.equalsigns;
   56|  2.11k|  srclen = ri.srclen;
   57|  2.11k|  size_t full_input_length = ri.full_input_length;
   58|  2.11k|  if (srclen == 0) {
  ------------------
  |  Branch (58:7): [True: 24, False: 2.08k]
  ------------------
   59|     24|    if (!ignore_garbage && equalsigns > 0) {
  ------------------
  |  Branch (59:9): [True: 24, Folded]
  |  Branch (59:28): [True: 14, False: 10]
  ------------------
   60|     14|      return {INVALID_BASE64_CHARACTER, equallocation, 0, true};
   61|     14|    }
   62|     10|    return {SUCCESS, full_input_length, 0};
   63|     24|  }
   64|  2.08k|  const chartype *const srcinit = src;
   65|  2.08k|  const char *const dstinit = dst;
   66|  2.08k|  const chartype *srcend = src + srclen;
   67|       |
   68|  2.08k|  constexpr size_t block_size = 6;
   69|  2.08k|  static_assert(block_size >= 2, "block_size must be at least two");
   70|  2.08k|  char buffer[block_size * 64];
   71|  2.08k|  char *bufferptr = buffer;
   72|       |  // A wide block store writes 4 bytes past its 48. That is safe when the next
   73|       |  // store starts 48 bytes later. Pairs of clean blocks wide-store the first
   74|       |  // and end the second on byte 48. Anything shorter, or a block that is not
   75|       |  // clean, uses the exact store. The pair attempt is only worth it on a long
   76|       |  // input: a short one often fails the first block and then repeats that work.
   77|  2.08k|  if (srclen >= 512) {
  ------------------
  |  Branch (77:7): [True: 1.05k, False: 1.03k]
  ------------------
   78|  1.05k|    const chartype *const srcend128 = src + srclen - 128;
   79|  36.3k|    while (bufferptr == buffer && src <= srcend128) {
  ------------------
  |  Branch (79:12): [True: 36.3k, False: 0]
  |  Branch (79:35): [True: 36.2k, False: 22]
  ------------------
   80|  36.2k|      block64 b0(src);
   81|  36.2k|      uint64_t e0 = 0;
   82|  36.2k|      const uint64_t m0 =
   83|  36.2k|          b0.to_base64_mask<base64_url, ignore_garbage, default_or_url>(&e0);
   84|  36.2k|      if ((!ignore_garbage && e0) || m0 != 0) {
  ------------------
  |  Branch (84:12): [True: 36.2k, Folded]
  |  Branch (84:31): [True: 266, False: 36.0k]
  |  Branch (84:38): [True: 350, False: 35.6k]
  ------------------
   85|    616|        break;
   86|    616|      }
   87|  35.6k|      block64 b1(src + 64);
   88|  35.6k|      uint64_t e1 = 0;
   89|  35.6k|      const uint64_t m1 =
   90|  35.6k|          b1.to_base64_mask<base64_url, ignore_garbage, default_or_url>(&e1);
   91|  35.6k|      if ((!ignore_garbage && e1) || m1 != 0) {
  ------------------
  |  Branch (91:12): [True: 35.6k, Folded]
  |  Branch (91:31): [True: 228, False: 35.4k]
  |  Branch (91:38): [True: 192, False: 35.2k]
  ------------------
   92|    420|        break;
   93|    420|      }
   94|  35.2k|      b0.base64_decode_block(dst);
   95|  35.2k|      b1.template base64_decode_block<true>(dst + 48);
   96|  35.2k|      src += 128;
   97|  35.2k|      dst += 96;
   98|  35.2k|    }
   99|  1.05k|  }
  100|  2.08k|  if (srclen >= 64) {
  ------------------
  |  Branch (100:7): [True: 1.78k, False: 304]
  ------------------
  101|  1.78k|    const chartype *const srcend64 = srcinit + srclen - 64;
  102|   163k|    while (src <= srcend64) {
  ------------------
  |  Branch (102:12): [True: 162k, False: 656]
  ------------------
  103|   162k|      block64 b(src);
  104|   162k|      uint64_t error = 0;
  105|   162k|      const uint64_t badcharmask =
  106|   162k|          b.to_base64_mask<base64_url, ignore_garbage, default_or_url>(&error);
  107|   162k|      if (!ignore_garbage && error) {
  ------------------
  |  Branch (107:11): [True: 162k, Folded]
  |  Branch (107:30): [True: 1.12k, False: 161k]
  ------------------
  108|  1.12k|        const size_t error_offset = trailing_zeroes(error);
  109|  1.12k|        return {error_code::INVALID_BASE64_CHARACTER,
  110|  1.12k|                size_t(src - srcinit + error_offset), size_t(dst - dstinit)};
  111|  1.12k|      }
  112|   161k|      if (ignore_garbage && badcharmask != 0) {
  ------------------
  |  Branch (112:11): [Folded, False: 161k]
  |  Branch (112:29): [True: 0, False: 0]
  ------------------
  113|      0|        const uint64_t equals = block64(src).equal_sign_mask();
  114|      0|        if (equals != 0) {
  ------------------
  |  Branch (114:13): [True: 0, False: 0]
  ------------------
  115|      0|          const size_t offset = trailing_zeroes(equals);
  116|      0|          equallocation = size_t(src - srcinit) + offset;
  117|      0|          equalsigns = 1;
  118|      0|          srclen = equallocation;
  119|      0|          full_input_length = equallocation + 1;
  120|      0|          if (srclen == 0) {
  ------------------
  |  Branch (120:15): [True: 0, False: 0]
  ------------------
  121|      0|            return {SUCCESS, full_input_length, 0};
  122|      0|          }
  123|      0|          srcend = srcinit + srclen;
  124|      0|          src = srcend;
  125|      0|          bufferptr += b.compress_block(badcharmask | (~uint64_t(0) << offset),
  126|      0|                                        bufferptr);
  127|      0|          break;
  128|      0|        }
  129|      0|      }
  130|   161k|      src += 64;
  131|   161k|      if (badcharmask != 0) {
  ------------------
  |  Branch (131:11): [True: 47.2k, False: 114k]
  ------------------
  132|  47.2k|        bufferptr += b.compress_block(badcharmask, bufferptr);
  133|   114k|      } else if (bufferptr != buffer) {
  ------------------
  |  Branch (133:18): [True: 113k, False: 1.03k]
  ------------------
  134|   113k|        b.copy_block(bufferptr);
  135|   113k|        bufferptr += 64;
  136|   113k|      } else {
  137|  1.03k|        b.template base64_decode_block<true>(dst);
  138|  1.03k|        dst += 48;
  139|  1.03k|      }
  140|   161k|      if (bufferptr >= (block_size - 1) * 64 + buffer) {
  ------------------
  |  Branch (140:11): [True: 31.2k, False: 130k]
  ------------------
  141|   156k|        for (size_t i = 0; i < (block_size - 2); i++) {
  ------------------
  |  Branch (141:28): [True: 125k, False: 31.2k]
  ------------------
  142|   125k|          base64_decode_block(dst, buffer + i * 64);
  143|   125k|          dst += 48;
  144|   125k|        }
  145|  31.2k|        base64_decode_block<true>(dst, buffer + (block_size - 2) * 64);
  146|  31.2k|        dst += 48;
  147|  31.2k|        std::memcpy(buffer, buffer + (block_size - 1) * 64,
  148|  31.2k|                    64); // 64 might be too much
  149|  31.2k|        bufferptr -= (block_size - 1) * 64;
  150|  31.2k|      }
  151|   161k|    }
  152|  1.78k|  }
  153|       |
  154|    960|  if (ignore_garbage && equalsigns == 0) {
  ------------------
  |  Branch (154:7): [Folded, False: 960]
  |  Branch (154:25): [True: 0, False: 0]
  ------------------
  155|      0|    const chartype *equal = src;
  156|      0|    while (equal < srcend && *equal != '=') {
  ------------------
  |  Branch (156:12): [True: 0, False: 0]
  |  Branch (156:30): [True: 0, False: 0]
  ------------------
  157|      0|      equal++;
  158|      0|    }
  159|      0|    if (equal < srcend) {
  ------------------
  |  Branch (159:9): [True: 0, False: 0]
  ------------------
  160|      0|      equallocation = size_t(equal - srcinit);
  161|      0|      equalsigns = 1;
  162|      0|      srclen = equallocation;
  163|      0|      full_input_length = equallocation + 1;
  164|      0|      if (srclen == 0) {
  ------------------
  |  Branch (164:11): [True: 0, False: 0]
  ------------------
  165|      0|        return {SUCCESS, full_input_length, 0};
  166|      0|      }
  167|      0|      srcend = equal;
  168|      0|    }
  169|      0|  }
  170|    960|  char *buffer_start = buffer;
  171|       |  // Optimization note: if this is almost full, then it is worth our
  172|       |  // time, otherwise, we should just decode directly.
  173|    960|  int last_block = (int)((bufferptr - buffer_start) % 64);
  174|    960|  if (last_block != 0 && srcend - src + last_block >= 64) {
  ------------------
  |  Branch (174:7): [True: 600, False: 360]
  |  Branch (174:26): [True: 92, False: 508]
  ------------------
  175|       |
  176|  1.65k|    while ((bufferptr - buffer_start) % 64 != 0 && src < srcend) {
  ------------------
  |  Branch (176:12): [True: 1.58k, False: 64]
  |  Branch (176:52): [True: 1.56k, False: 24]
  ------------------
  177|  1.56k|      uint8_t val = to_base64[uint8_t(*src)];
  178|  1.56k|      *bufferptr = char(val);
  179|  1.56k|      if (!ignore_garbage &&
  ------------------
  |  Branch (179:11): [True: 1.56k, Folded]
  ------------------
  180|  1.56k|          (!scalar::base64::is_eight_byte(*src) || val > 64)) {
  ------------------
  |  Branch (180:12): [True: 0, False: 1.56k]
  |  Branch (180:52): [True: 4, False: 1.55k]
  ------------------
  181|      4|        return {error_code::INVALID_BASE64_CHARACTER, size_t(src - srcinit),
  182|      4|                size_t(dst - dstinit)};
  183|      4|      }
  184|  1.55k|      bufferptr += (val <= 63 && scalar::base64::is_eight_byte(*src));
  ------------------
  |  Branch (184:21): [True: 956, False: 602]
  |  Branch (184:34): [True: 956, False: 0]
  ------------------
  185|  1.55k|      src++;
  186|  1.55k|    }
  187|     92|  }
  188|       |
  189|  1.45k|  for (; buffer_start + 64 <= bufferptr; buffer_start += 64) {
  ------------------
  |  Branch (189:10): [True: 498, False: 956]
  ------------------
  190|       |    // 8 payload bytes still in the buffer become 6 output bytes, which cover
  191|       |    // the 4-byte tail of a wide store. Fewer than that, and the tail can
  192|       |    // stick out past the real end.
  193|    498|    const size_t after = size_t(bufferptr - (buffer_start + 64));
  194|    498|    if (after >= 8) {
  ------------------
  |  Branch (194:9): [True: 408, False: 90]
  ------------------
  195|    408|      base64_decode_block(dst, buffer_start);
  196|    408|    } else {
  197|     90|      base64_decode_block<true>(dst, buffer_start);
  198|     90|    }
  199|    498|    dst += 48;
  200|    498|  }
  201|    956|  if ((bufferptr - buffer_start) % 64 != 0) {
  ------------------
  |  Branch (201:7): [True: 532, False: 424]
  ------------------
  202|  4.71k|    while (buffer_start + 4 < bufferptr) {
  ------------------
  |  Branch (202:12): [True: 4.18k, False: 532]
  ------------------
  203|  4.18k|      uint32_t triple = ((uint32_t(uint8_t(buffer_start[0])) << 3 * 6) +
  204|  4.18k|                         (uint32_t(uint8_t(buffer_start[1])) << 2 * 6) +
  205|  4.18k|                         (uint32_t(uint8_t(buffer_start[2])) << 1 * 6) +
  206|  4.18k|                         (uint32_t(uint8_t(buffer_start[3])) << 0 * 6))
  207|  4.18k|                        << 8;
  208|  4.18k|#if !SIMDUTF_IS_BIG_ENDIAN
  209|  4.18k|      triple = scalar::u32_swap_bytes(triple);
  210|  4.18k|#endif
  211|  4.18k|      std::memcpy(dst, &triple, 3);
  212|       |
  213|  4.18k|      dst += 3;
  214|  4.18k|      buffer_start += 4;
  215|  4.18k|    }
  216|    532|    if (buffer_start + 4 <= bufferptr) {
  ------------------
  |  Branch (216:9): [True: 138, False: 394]
  ------------------
  217|    138|      uint32_t triple = ((uint32_t(uint8_t(buffer_start[0])) << 3 * 6) +
  218|    138|                         (uint32_t(uint8_t(buffer_start[1])) << 2 * 6) +
  219|    138|                         (uint32_t(uint8_t(buffer_start[2])) << 1 * 6) +
  220|    138|                         (uint32_t(uint8_t(buffer_start[3])) << 0 * 6))
  221|    138|                        << 8;
  222|    138|#if !SIMDUTF_IS_BIG_ENDIAN
  223|    138|      triple = scalar::u32_swap_bytes(triple);
  224|    138|#endif
  225|    138|      std::memcpy(dst, &triple, 3);
  226|       |
  227|    138|      dst += 3;
  228|    138|      buffer_start += 4;
  229|    138|    }
  230|       |    // we may have 1, 2 or 3 bytes left and we need to decode them so let us
  231|       |    // backtrack
  232|    532|    int leftover = int(bufferptr - buffer_start);
  233|  1.34k|    while (leftover > 0) {
  ------------------
  |  Branch (233:12): [True: 810, False: 532]
  ------------------
  234|    810|      if (!ignore_garbage) {
  ------------------
  |  Branch (234:11): [True: 810, Folded]
  ------------------
  235|  5.54k|        while (to_base64[uint8_t(*(src - 1))] == 64) {
  ------------------
  |  Branch (235:16): [True: 4.73k, False: 810]
  ------------------
  236|  4.73k|          src--;
  237|  4.73k|        }
  238|    810|      } else {
  239|      0|        while (!scalar::base64::is_eight_byte(*(src - 1)) ||
  ------------------
  |  Branch (239:16): [True: 0, False: 0]
  ------------------
  240|      0|               to_base64[uint8_t(*(src - 1))] >= 64) {
  ------------------
  |  Branch (240:16): [True: 0, False: 0]
  ------------------
  241|      0|          src--;
  242|      0|        }
  243|      0|      }
  244|    810|      src--;
  245|    810|      leftover--;
  246|    810|    }
  247|    532|  }
  248|    956|  if (src < srcend + equalsigns) {
  ------------------
  |  Branch (248:7): [True: 784, False: 172]
  ------------------
  249|    784|    full_result r = scalar::base64::base64_tail_decode(
  250|    784|        dst, src, srcend - src, equalsigns, options, last_chunk_options);
  251|    784|    r = scalar::base64::patch_tail_result(
  252|    784|        r, size_t(src - srcinit), size_t(dst - dstinit), equallocation,
  253|    784|        full_input_length, last_chunk_options);
  254|       |    // When is_partial(last_chunk_options) is true, we must either end with
  255|       |    // the end of the stream (beyond whitespace) or right after a non-ignorable
  256|       |    // character or at the very beginning of the stream.
  257|       |    // See https://tc39.es/proposal-arraybuffer-base64/spec/#sec-frombase64
  258|    784|    if (is_partial(last_chunk_options) && r.error == error_code::SUCCESS &&
  ------------------
  |  Branch (258:9): [True: 436, False: 348]
  |  Branch (258:43): [True: 396, False: 40]
  ------------------
  259|    396|        r.input_count < full_input_length) {
  ------------------
  |  Branch (259:9): [True: 328, False: 68]
  ------------------
  260|       |      // First check if we can extend the input to the end of the stream
  261|    686|      while (r.input_count < full_input_length &&
  ------------------
  |  Branch (261:14): [True: 676, False: 10]
  ------------------
  262|    676|             base64_ignorable(*(srcinit + r.input_count), options)) {
  ------------------
  |  Branch (262:14): [True: 358, False: 318]
  ------------------
  263|    358|        r.input_count++;
  264|    358|      }
  265|       |      // If we are still not at the end of the stream, then we must backtrack
  266|       |      // to the last non-ignorable character.
  267|    328|      if (r.input_count < full_input_length) {
  ------------------
  |  Branch (267:11): [True: 318, False: 10]
  ------------------
  268|  2.65k|        while (r.input_count > 0 &&
  ------------------
  |  Branch (268:16): [True: 2.60k, False: 56]
  ------------------
  269|  2.60k|               base64_ignorable(*(srcinit + r.input_count - 1), options)) {
  ------------------
  |  Branch (269:16): [True: 2.34k, False: 262]
  ------------------
  270|  2.34k|          r.input_count--;
  271|  2.34k|        }
  272|    318|      }
  273|    328|    }
  274|    784|    return r;
  275|    784|  }
  276|    172|  if (!ignore_garbage && equalsigns > 0) {
  ------------------
  |  Branch (276:7): [True: 172, Folded]
  |  Branch (276:26): [True: 0, False: 172]
  ------------------
  277|      0|    if ((size_t(dst - dstinit) % 3 == 0) ||
  ------------------
  |  Branch (277:9): [True: 0, False: 0]
  ------------------
  278|      0|        ((size_t(dst - dstinit) % 3) + 1 + equalsigns != 4)) {
  ------------------
  |  Branch (278:9): [True: 0, False: 0]
  ------------------
  279|      0|      return {INVALID_BASE64_CHARACTER, equallocation, size_t(dst - dstinit),
  280|      0|              true};
  281|      0|    }
  282|      0|  }
  283|    172|  return {SUCCESS, srclen, size_t(dst - dstinit)};
  284|    172|}
simdutf.cpp:_ZN7simdutf7haswell12_GLOBAL__N_16base6422compress_decode_base64ILb1ELb0ELb0EDsEENS_11full_resultEPcPKT2_mNS_14base64_optionsENS_27last_chunk_handling_optionsE:
   45|  2.03k|                       last_chunk_handling_options last_chunk_options) {
   46|  2.03k|  const uint8_t *to_base64 =
   47|  2.03k|      default_or_url ? tables::base64::to_base64_default_or_url_value
  ------------------
  |  Branch (47:7): [Folded, False: 2.03k]
  ------------------
   48|  2.03k|                     : (base64_url ? tables::base64::to_base64_url_value
  ------------------
  |  Branch (48:25): [True: 2.03k, Folded]
  ------------------
   49|  2.03k|                                   : tables::base64::to_base64_value);
   50|  2.03k|  auto ri =
   51|  2.03k|      ignore_garbage
  ------------------
  |  Branch (51:7): [Folded, False: 2.03k]
  ------------------
   52|  2.03k|          ? simdutf::scalar::base64::reduced_input{0, srclen, srclen, srclen}
   53|  2.03k|          : simdutf::scalar::base64::find_end(src, srclen, options);
   54|  2.03k|  size_t equallocation = ri.equallocation;
   55|  2.03k|  size_t equalsigns = ri.equalsigns;
   56|  2.03k|  srclen = ri.srclen;
   57|  2.03k|  size_t full_input_length = ri.full_input_length;
   58|  2.03k|  if (srclen == 0) {
  ------------------
  |  Branch (58:7): [True: 14, False: 2.02k]
  ------------------
   59|     14|    if (!ignore_garbage && equalsigns > 0) {
  ------------------
  |  Branch (59:9): [True: 14, Folded]
  |  Branch (59:28): [True: 8, False: 6]
  ------------------
   60|      8|      return {INVALID_BASE64_CHARACTER, equallocation, 0, true};
   61|      8|    }
   62|      6|    return {SUCCESS, full_input_length, 0};
   63|     14|  }
   64|  2.02k|  const chartype *const srcinit = src;
   65|  2.02k|  const char *const dstinit = dst;
   66|  2.02k|  const chartype *srcend = src + srclen;
   67|       |
   68|  2.02k|  constexpr size_t block_size = 6;
   69|  2.02k|  static_assert(block_size >= 2, "block_size must be at least two");
   70|  2.02k|  char buffer[block_size * 64];
   71|  2.02k|  char *bufferptr = buffer;
   72|       |  // A wide block store writes 4 bytes past its 48. That is safe when the next
   73|       |  // store starts 48 bytes later. Pairs of clean blocks wide-store the first
   74|       |  // and end the second on byte 48. Anything shorter, or a block that is not
   75|       |  // clean, uses the exact store. The pair attempt is only worth it on a long
   76|       |  // input: a short one often fails the first block and then repeats that work.
   77|  2.02k|  if (srclen >= 512) {
  ------------------
  |  Branch (77:7): [True: 984, False: 1.04k]
  ------------------
   78|    984|    const chartype *const srcend128 = src + srclen - 128;
   79|  1.43k|    while (bufferptr == buffer && src <= srcend128) {
  ------------------
  |  Branch (79:12): [True: 1.43k, False: 0]
  |  Branch (79:35): [True: 1.42k, False: 12]
  ------------------
   80|  1.42k|      block64 b0(src);
   81|  1.42k|      uint64_t e0 = 0;
   82|  1.42k|      const uint64_t m0 =
   83|  1.42k|          b0.to_base64_mask<base64_url, ignore_garbage, default_or_url>(&e0);
   84|  1.42k|      if ((!ignore_garbage && e0) || m0 != 0) {
  ------------------
  |  Branch (84:12): [True: 1.42k, Folded]
  |  Branch (84:31): [True: 250, False: 1.17k]
  |  Branch (84:38): [True: 318, False: 856]
  ------------------
   85|    568|        break;
   86|    568|      }
   87|    856|      block64 b1(src + 64);
   88|    856|      uint64_t e1 = 0;
   89|    856|      const uint64_t m1 =
   90|    856|          b1.to_base64_mask<base64_url, ignore_garbage, default_or_url>(&e1);
   91|    856|      if ((!ignore_garbage && e1) || m1 != 0) {
  ------------------
  |  Branch (91:12): [True: 856, Folded]
  |  Branch (91:31): [True: 206, False: 650]
  |  Branch (91:38): [True: 198, False: 452]
  ------------------
   92|    404|        break;
   93|    404|      }
   94|    452|      b0.base64_decode_block(dst);
   95|    452|      b1.template base64_decode_block<true>(dst + 48);
   96|    452|      src += 128;
   97|    452|      dst += 96;
   98|    452|    }
   99|    984|  }
  100|  2.02k|  if (srclen >= 64) {
  ------------------
  |  Branch (100:7): [True: 1.71k, False: 308]
  ------------------
  101|  1.71k|    const chartype *const srcend64 = srcinit + srclen - 64;
  102|  48.0k|    while (src <= srcend64) {
  ------------------
  |  Branch (102:12): [True: 47.4k, False: 594]
  ------------------
  103|  47.4k|      block64 b(src);
  104|  47.4k|      uint64_t error = 0;
  105|  47.4k|      const uint64_t badcharmask =
  106|  47.4k|          b.to_base64_mask<base64_url, ignore_garbage, default_or_url>(&error);
  107|  47.4k|      if (!ignore_garbage && error) {
  ------------------
  |  Branch (107:11): [True: 47.4k, Folded]
  |  Branch (107:30): [True: 1.12k, False: 46.3k]
  ------------------
  108|  1.12k|        const size_t error_offset = trailing_zeroes(error);
  109|  1.12k|        return {error_code::INVALID_BASE64_CHARACTER,
  110|  1.12k|                size_t(src - srcinit + error_offset), size_t(dst - dstinit)};
  111|  1.12k|      }
  112|  46.3k|      if (ignore_garbage && badcharmask != 0) {
  ------------------
  |  Branch (112:11): [Folded, False: 46.3k]
  |  Branch (112:29): [True: 0, False: 0]
  ------------------
  113|      0|        const uint64_t equals = block64(src).equal_sign_mask();
  114|      0|        if (equals != 0) {
  ------------------
  |  Branch (114:13): [True: 0, False: 0]
  ------------------
  115|      0|          const size_t offset = trailing_zeroes(equals);
  116|      0|          equallocation = size_t(src - srcinit) + offset;
  117|      0|          equalsigns = 1;
  118|      0|          srclen = equallocation;
  119|      0|          full_input_length = equallocation + 1;
  120|      0|          if (srclen == 0) {
  ------------------
  |  Branch (120:15): [True: 0, False: 0]
  ------------------
  121|      0|            return {SUCCESS, full_input_length, 0};
  122|      0|          }
  123|      0|          srcend = srcinit + srclen;
  124|      0|          src = srcend;
  125|      0|          bufferptr += b.compress_block(badcharmask | (~uint64_t(0) << offset),
  126|      0|                                        bufferptr);
  127|      0|          break;
  128|      0|        }
  129|      0|      }
  130|  46.3k|      src += 64;
  131|  46.3k|      if (badcharmask != 0) {
  ------------------
  |  Branch (131:11): [True: 37.9k, False: 8.33k]
  ------------------
  132|  37.9k|        bufferptr += b.compress_block(badcharmask, bufferptr);
  133|  37.9k|      } else if (bufferptr != buffer) {
  ------------------
  |  Branch (133:18): [True: 7.47k, False: 856]
  ------------------
  134|  7.47k|        b.copy_block(bufferptr);
  135|  7.47k|        bufferptr += 64;
  136|  7.47k|      } else {
  137|    856|        b.template base64_decode_block<true>(dst);
  138|    856|        dst += 48;
  139|    856|      }
  140|  46.3k|      if (bufferptr >= (block_size - 1) * 64 + buffer) {
  ------------------
  |  Branch (140:11): [True: 8.60k, False: 37.7k]
  ------------------
  141|  43.0k|        for (size_t i = 0; i < (block_size - 2); i++) {
  ------------------
  |  Branch (141:28): [True: 34.4k, False: 8.60k]
  ------------------
  142|  34.4k|          base64_decode_block(dst, buffer + i * 64);
  143|  34.4k|          dst += 48;
  144|  34.4k|        }
  145|  8.60k|        base64_decode_block<true>(dst, buffer + (block_size - 2) * 64);
  146|  8.60k|        dst += 48;
  147|  8.60k|        std::memcpy(buffer, buffer + (block_size - 1) * 64,
  148|  8.60k|                    64); // 64 might be too much
  149|  8.60k|        bufferptr -= (block_size - 1) * 64;
  150|  8.60k|      }
  151|  46.3k|    }
  152|  1.71k|  }
  153|       |
  154|    902|  if (ignore_garbage && equalsigns == 0) {
  ------------------
  |  Branch (154:7): [Folded, False: 902]
  |  Branch (154:25): [True: 0, False: 0]
  ------------------
  155|      0|    const chartype *equal = src;
  156|      0|    while (equal < srcend && *equal != '=') {
  ------------------
  |  Branch (156:12): [True: 0, False: 0]
  |  Branch (156:30): [True: 0, False: 0]
  ------------------
  157|      0|      equal++;
  158|      0|    }
  159|      0|    if (equal < srcend) {
  ------------------
  |  Branch (159:9): [True: 0, False: 0]
  ------------------
  160|      0|      equallocation = size_t(equal - srcinit);
  161|      0|      equalsigns = 1;
  162|      0|      srclen = equallocation;
  163|      0|      full_input_length = equallocation + 1;
  164|      0|      if (srclen == 0) {
  ------------------
  |  Branch (164:11): [True: 0, False: 0]
  ------------------
  165|      0|        return {SUCCESS, full_input_length, 0};
  166|      0|      }
  167|      0|      srcend = equal;
  168|      0|    }
  169|      0|  }
  170|    902|  char *buffer_start = buffer;
  171|       |  // Optimization note: if this is almost full, then it is worth our
  172|       |  // time, otherwise, we should just decode directly.
  173|    902|  int last_block = (int)((bufferptr - buffer_start) % 64);
  174|    902|  if (last_block != 0 && srcend - src + last_block >= 64) {
  ------------------
  |  Branch (174:7): [True: 552, False: 350]
  |  Branch (174:26): [True: 96, False: 456]
  ------------------
  175|       |
  176|    584|    while ((bufferptr - buffer_start) % 64 != 0 && src < srcend) {
  ------------------
  |  Branch (176:12): [True: 550, False: 34]
  |  Branch (176:52): [True: 538, False: 12]
  ------------------
  177|    538|      uint8_t val = to_base64[uint8_t(*src)];
  178|    538|      *bufferptr = char(val);
  179|    538|      if (!ignore_garbage &&
  ------------------
  |  Branch (179:11): [True: 538, Folded]
  ------------------
  180|    538|          (!scalar::base64::is_eight_byte(*src) || val > 64)) {
  ------------------
  |  Branch (180:12): [True: 28, False: 510]
  |  Branch (180:52): [True: 22, False: 488]
  ------------------
  181|     50|        return {error_code::INVALID_BASE64_CHARACTER, size_t(src - srcinit),
  182|     50|                size_t(dst - dstinit)};
  183|     50|      }
  184|    488|      bufferptr += (val <= 63 && scalar::base64::is_eight_byte(*src));
  ------------------
  |  Branch (184:21): [True: 202, False: 286]
  |  Branch (184:34): [True: 202, False: 0]
  ------------------
  185|    488|      src++;
  186|    488|    }
  187|     96|  }
  188|       |
  189|  1.20k|  for (; buffer_start + 64 <= bufferptr; buffer_start += 64) {
  ------------------
  |  Branch (189:10): [True: 356, False: 852]
  ------------------
  190|       |    // 8 payload bytes still in the buffer become 6 output bytes, which cover
  191|       |    // the 4-byte tail of a wide store. Fewer than that, and the tail can
  192|       |    // stick out past the real end.
  193|    356|    const size_t after = size_t(bufferptr - (buffer_start + 64));
  194|    356|    if (after >= 8) {
  ------------------
  |  Branch (194:9): [True: 296, False: 60]
  ------------------
  195|    296|      base64_decode_block(dst, buffer_start);
  196|    296|    } else {
  197|     60|      base64_decode_block<true>(dst, buffer_start);
  198|     60|    }
  199|    356|    dst += 48;
  200|    356|  }
  201|    852|  if ((bufferptr - buffer_start) % 64 != 0) {
  ------------------
  |  Branch (201:7): [True: 468, False: 384]
  ------------------
  202|  3.91k|    while (buffer_start + 4 < bufferptr) {
  ------------------
  |  Branch (202:12): [True: 3.44k, False: 468]
  ------------------
  203|  3.44k|      uint32_t triple = ((uint32_t(uint8_t(buffer_start[0])) << 3 * 6) +
  204|  3.44k|                         (uint32_t(uint8_t(buffer_start[1])) << 2 * 6) +
  205|  3.44k|                         (uint32_t(uint8_t(buffer_start[2])) << 1 * 6) +
  206|  3.44k|                         (uint32_t(uint8_t(buffer_start[3])) << 0 * 6))
  207|  3.44k|                        << 8;
  208|  3.44k|#if !SIMDUTF_IS_BIG_ENDIAN
  209|  3.44k|      triple = scalar::u32_swap_bytes(triple);
  210|  3.44k|#endif
  211|  3.44k|      std::memcpy(dst, &triple, 3);
  212|       |
  213|  3.44k|      dst += 3;
  214|  3.44k|      buffer_start += 4;
  215|  3.44k|    }
  216|    468|    if (buffer_start + 4 <= bufferptr) {
  ------------------
  |  Branch (216:9): [True: 114, False: 354]
  ------------------
  217|    114|      uint32_t triple = ((uint32_t(uint8_t(buffer_start[0])) << 3 * 6) +
  218|    114|                         (uint32_t(uint8_t(buffer_start[1])) << 2 * 6) +
  219|    114|                         (uint32_t(uint8_t(buffer_start[2])) << 1 * 6) +
  220|    114|                         (uint32_t(uint8_t(buffer_start[3])) << 0 * 6))
  221|    114|                        << 8;
  222|    114|#if !SIMDUTF_IS_BIG_ENDIAN
  223|    114|      triple = scalar::u32_swap_bytes(triple);
  224|    114|#endif
  225|    114|      std::memcpy(dst, &triple, 3);
  226|       |
  227|    114|      dst += 3;
  228|    114|      buffer_start += 4;
  229|    114|    }
  230|       |    // we may have 1, 2 or 3 bytes left and we need to decode them so let us
  231|       |    // backtrack
  232|    468|    int leftover = int(bufferptr - buffer_start);
  233|  1.17k|    while (leftover > 0) {
  ------------------
  |  Branch (233:12): [True: 706, False: 468]
  ------------------
  234|    706|      if (!ignore_garbage) {
  ------------------
  |  Branch (234:11): [True: 706, Folded]
  ------------------
  235|  6.55k|        while (to_base64[uint8_t(*(src - 1))] == 64) {
  ------------------
  |  Branch (235:16): [True: 5.84k, False: 706]
  ------------------
  236|  5.84k|          src--;
  237|  5.84k|        }
  238|    706|      } else {
  239|      0|        while (!scalar::base64::is_eight_byte(*(src - 1)) ||
  ------------------
  |  Branch (239:16): [True: 0, False: 0]
  ------------------
  240|      0|               to_base64[uint8_t(*(src - 1))] >= 64) {
  ------------------
  |  Branch (240:16): [True: 0, False: 0]
  ------------------
  241|      0|          src--;
  242|      0|        }
  243|      0|      }
  244|    706|      src--;
  245|    706|      leftover--;
  246|    706|    }
  247|    468|  }
  248|    852|  if (src < srcend + equalsigns) {
  ------------------
  |  Branch (248:7): [True: 708, False: 144]
  ------------------
  249|    708|    full_result r = scalar::base64::base64_tail_decode(
  250|    708|        dst, src, srcend - src, equalsigns, options, last_chunk_options);
  251|    708|    r = scalar::base64::patch_tail_result(
  252|    708|        r, size_t(src - srcinit), size_t(dst - dstinit), equallocation,
  253|    708|        full_input_length, last_chunk_options);
  254|       |    // When is_partial(last_chunk_options) is true, we must either end with
  255|       |    // the end of the stream (beyond whitespace) or right after a non-ignorable
  256|       |    // character or at the very beginning of the stream.
  257|       |    // See https://tc39.es/proposal-arraybuffer-base64/spec/#sec-frombase64
  258|    708|    if (is_partial(last_chunk_options) && r.error == error_code::SUCCESS &&
  ------------------
  |  Branch (258:9): [True: 420, False: 288]
  |  Branch (258:43): [True: 330, False: 90]
  ------------------
  259|    330|        r.input_count < full_input_length) {
  ------------------
  |  Branch (259:9): [True: 296, False: 34]
  ------------------
  260|       |      // First check if we can extend the input to the end of the stream
  261|    806|      while (r.input_count < full_input_length &&
  ------------------
  |  Branch (261:14): [True: 802, False: 4]
  ------------------
  262|    802|             base64_ignorable(*(srcinit + r.input_count), options)) {
  ------------------
  |  Branch (262:14): [True: 510, False: 292]
  ------------------
  263|    510|        r.input_count++;
  264|    510|      }
  265|       |      // If we are still not at the end of the stream, then we must backtrack
  266|       |      // to the last non-ignorable character.
  267|    296|      if (r.input_count < full_input_length) {
  ------------------
  |  Branch (267:11): [True: 292, False: 4]
  ------------------
  268|  2.52k|        while (r.input_count > 0 &&
  ------------------
  |  Branch (268:16): [True: 2.44k, False: 78]
  ------------------
  269|  2.44k|               base64_ignorable(*(srcinit + r.input_count - 1), options)) {
  ------------------
  |  Branch (269:16): [True: 2.23k, False: 214]
  ------------------
  270|  2.23k|          r.input_count--;
  271|  2.23k|        }
  272|    292|      }
  273|    296|    }
  274|    708|    return r;
  275|    708|  }
  276|    144|  if (!ignore_garbage && equalsigns > 0) {
  ------------------
  |  Branch (276:7): [True: 144, Folded]
  |  Branch (276:26): [True: 0, False: 144]
  ------------------
  277|      0|    if ((size_t(dst - dstinit) % 3 == 0) ||
  ------------------
  |  Branch (277:9): [True: 0, False: 0]
  ------------------
  278|      0|        ((size_t(dst - dstinit) % 3) + 1 + equalsigns != 4)) {
  ------------------
  |  Branch (278:9): [True: 0, False: 0]
  ------------------
  279|      0|      return {INVALID_BASE64_CHARACTER, equallocation, size_t(dst - dstinit),
  280|      0|              true};
  281|      0|    }
  282|      0|  }
  283|    144|  return {SUCCESS, srclen, size_t(dst - dstinit)};
  284|    144|}
simdutf.cpp:_ZN7simdutf7haswell12_GLOBAL__N_16base6422compress_decode_base64ILb0ELb0ELb0EDsEENS_11full_resultEPcPKT2_mNS_14base64_optionsENS_27last_chunk_handling_optionsE:
   45|  1.97k|                       last_chunk_handling_options last_chunk_options) {
   46|  1.97k|  const uint8_t *to_base64 =
   47|  1.97k|      default_or_url ? tables::base64::to_base64_default_or_url_value
  ------------------
  |  Branch (47:7): [Folded, False: 1.97k]
  ------------------
   48|  1.97k|                     : (base64_url ? tables::base64::to_base64_url_value
  ------------------
  |  Branch (48:25): [Folded, False: 1.97k]
  ------------------
   49|  1.97k|                                   : tables::base64::to_base64_value);
   50|  1.97k|  auto ri =
   51|  1.97k|      ignore_garbage
  ------------------
  |  Branch (51:7): [Folded, False: 1.97k]
  ------------------
   52|  1.97k|          ? simdutf::scalar::base64::reduced_input{0, srclen, srclen, srclen}
   53|  1.97k|          : simdutf::scalar::base64::find_end(src, srclen, options);
   54|  1.97k|  size_t equallocation = ri.equallocation;
   55|  1.97k|  size_t equalsigns = ri.equalsigns;
   56|  1.97k|  srclen = ri.srclen;
   57|  1.97k|  size_t full_input_length = ri.full_input_length;
   58|  1.97k|  if (srclen == 0) {
  ------------------
  |  Branch (58:7): [True: 26, False: 1.94k]
  ------------------
   59|     26|    if (!ignore_garbage && equalsigns > 0) {
  ------------------
  |  Branch (59:9): [True: 26, Folded]
  |  Branch (59:28): [True: 12, False: 14]
  ------------------
   60|     12|      return {INVALID_BASE64_CHARACTER, equallocation, 0, true};
   61|     12|    }
   62|     14|    return {SUCCESS, full_input_length, 0};
   63|     26|  }
   64|  1.94k|  const chartype *const srcinit = src;
   65|  1.94k|  const char *const dstinit = dst;
   66|  1.94k|  const chartype *srcend = src + srclen;
   67|       |
   68|  1.94k|  constexpr size_t block_size = 6;
   69|  1.94k|  static_assert(block_size >= 2, "block_size must be at least two");
   70|  1.94k|  char buffer[block_size * 64];
   71|  1.94k|  char *bufferptr = buffer;
   72|       |  // A wide block store writes 4 bytes past its 48. That is safe when the next
   73|       |  // store starts 48 bytes later. Pairs of clean blocks wide-store the first
   74|       |  // and end the second on byte 48. Anything shorter, or a block that is not
   75|       |  // clean, uses the exact store. The pair attempt is only worth it on a long
   76|       |  // input: a short one often fails the first block and then repeats that work.
   77|  1.94k|  if (srclen >= 512) {
  ------------------
  |  Branch (77:7): [True: 970, False: 974]
  ------------------
   78|    970|    const chartype *const srcend128 = src + srclen - 128;
   79|  1.36k|    while (bufferptr == buffer && src <= srcend128) {
  ------------------
  |  Branch (79:12): [True: 1.36k, False: 0]
  |  Branch (79:35): [True: 1.35k, False: 6]
  ------------------
   80|  1.35k|      block64 b0(src);
   81|  1.35k|      uint64_t e0 = 0;
   82|  1.35k|      const uint64_t m0 =
   83|  1.35k|          b0.to_base64_mask<base64_url, ignore_garbage, default_or_url>(&e0);
   84|  1.35k|      if ((!ignore_garbage && e0) || m0 != 0) {
  ------------------
  |  Branch (84:12): [True: 1.35k, Folded]
  |  Branch (84:31): [True: 232, False: 1.12k]
  |  Branch (84:38): [True: 308, False: 816]
  ------------------
   85|    540|        break;
   86|    540|      }
   87|    816|      block64 b1(src + 64);
   88|    816|      uint64_t e1 = 0;
   89|    816|      const uint64_t m1 =
   90|    816|          b1.to_base64_mask<base64_url, ignore_garbage, default_or_url>(&e1);
   91|    816|      if ((!ignore_garbage && e1) || m1 != 0) {
  ------------------
  |  Branch (91:12): [True: 816, Folded]
  |  Branch (91:31): [True: 216, False: 600]
  |  Branch (91:38): [True: 208, False: 392]
  ------------------
   92|    424|        break;
   93|    424|      }
   94|    392|      b0.base64_decode_block(dst);
   95|    392|      b1.template base64_decode_block<true>(dst + 48);
   96|    392|      src += 128;
   97|    392|      dst += 96;
   98|    392|    }
   99|    970|  }
  100|  1.94k|  if (srclen >= 64) {
  ------------------
  |  Branch (100:7): [True: 1.64k, False: 296]
  ------------------
  101|  1.64k|    const chartype *const srcend64 = srcinit + srclen - 64;
  102|  67.1k|    while (src <= srcend64) {
  ------------------
  |  Branch (102:12): [True: 66.6k, False: 576]
  ------------------
  103|  66.6k|      block64 b(src);
  104|  66.6k|      uint64_t error = 0;
  105|  66.6k|      const uint64_t badcharmask =
  106|  66.6k|          b.to_base64_mask<base64_url, ignore_garbage, default_or_url>(&error);
  107|  66.6k|      if (!ignore_garbage && error) {
  ------------------
  |  Branch (107:11): [True: 66.6k, Folded]
  |  Branch (107:30): [True: 1.07k, False: 65.5k]
  ------------------
  108|  1.07k|        const size_t error_offset = trailing_zeroes(error);
  109|  1.07k|        return {error_code::INVALID_BASE64_CHARACTER,
  110|  1.07k|                size_t(src - srcinit + error_offset), size_t(dst - dstinit)};
  111|  1.07k|      }
  112|  65.5k|      if (ignore_garbage && badcharmask != 0) {
  ------------------
  |  Branch (112:11): [Folded, False: 65.5k]
  |  Branch (112:29): [True: 0, False: 0]
  ------------------
  113|      0|        const uint64_t equals = block64(src).equal_sign_mask();
  114|      0|        if (equals != 0) {
  ------------------
  |  Branch (114:13): [True: 0, False: 0]
  ------------------
  115|      0|          const size_t offset = trailing_zeroes(equals);
  116|      0|          equallocation = size_t(src - srcinit) + offset;
  117|      0|          equalsigns = 1;
  118|      0|          srclen = equallocation;
  119|      0|          full_input_length = equallocation + 1;
  120|      0|          if (srclen == 0) {
  ------------------
  |  Branch (120:15): [True: 0, False: 0]
  ------------------
  121|      0|            return {SUCCESS, full_input_length, 0};
  122|      0|          }
  123|      0|          srcend = srcinit + srclen;
  124|      0|          src = srcend;
  125|      0|          bufferptr += b.compress_block(badcharmask | (~uint64_t(0) << offset),
  126|      0|                                        bufferptr);
  127|      0|          break;
  128|      0|        }
  129|      0|      }
  130|  65.5k|      src += 64;
  131|  65.5k|      if (badcharmask != 0) {
  ------------------
  |  Branch (131:11): [True: 52.0k, False: 13.4k]
  ------------------
  132|  52.0k|        bufferptr += b.compress_block(badcharmask, bufferptr);
  133|  52.0k|      } else if (bufferptr != buffer) {
  ------------------
  |  Branch (133:18): [True: 12.8k, False: 648]
  ------------------
  134|  12.8k|        b.copy_block(bufferptr);
  135|  12.8k|        bufferptr += 64;
  136|  12.8k|      } else {
  137|    648|        b.template base64_decode_block<true>(dst);
  138|    648|        dst += 48;
  139|    648|      }
  140|  65.5k|      if (bufferptr >= (block_size - 1) * 64 + buffer) {
  ------------------
  |  Branch (140:11): [True: 12.4k, False: 53.0k]
  ------------------
  141|  62.3k|        for (size_t i = 0; i < (block_size - 2); i++) {
  ------------------
  |  Branch (141:28): [True: 49.8k, False: 12.4k]
  ------------------
  142|  49.8k|          base64_decode_block(dst, buffer + i * 64);
  143|  49.8k|          dst += 48;
  144|  49.8k|        }
  145|  12.4k|        base64_decode_block<true>(dst, buffer + (block_size - 2) * 64);
  146|  12.4k|        dst += 48;
  147|  12.4k|        std::memcpy(buffer, buffer + (block_size - 1) * 64,
  148|  12.4k|                    64); // 64 might be too much
  149|  12.4k|        bufferptr -= (block_size - 1) * 64;
  150|  12.4k|      }
  151|  65.5k|    }
  152|  1.64k|  }
  153|       |
  154|    872|  if (ignore_garbage && equalsigns == 0) {
  ------------------
  |  Branch (154:7): [Folded, False: 872]
  |  Branch (154:25): [True: 0, False: 0]
  ------------------
  155|      0|    const chartype *equal = src;
  156|      0|    while (equal < srcend && *equal != '=') {
  ------------------
  |  Branch (156:12): [True: 0, False: 0]
  |  Branch (156:30): [True: 0, False: 0]
  ------------------
  157|      0|      equal++;
  158|      0|    }
  159|      0|    if (equal < srcend) {
  ------------------
  |  Branch (159:9): [True: 0, False: 0]
  ------------------
  160|      0|      equallocation = size_t(equal - srcinit);
  161|      0|      equalsigns = 1;
  162|      0|      srclen = equallocation;
  163|      0|      full_input_length = equallocation + 1;
  164|      0|      if (srclen == 0) {
  ------------------
  |  Branch (164:11): [True: 0, False: 0]
  ------------------
  165|      0|        return {SUCCESS, full_input_length, 0};
  166|      0|      }
  167|      0|      srcend = equal;
  168|      0|    }
  169|      0|  }
  170|    872|  char *buffer_start = buffer;
  171|       |  // Optimization note: if this is almost full, then it is worth our
  172|       |  // time, otherwise, we should just decode directly.
  173|    872|  int last_block = (int)((bufferptr - buffer_start) % 64);
  174|    872|  if (last_block != 0 && srcend - src + last_block >= 64) {
  ------------------
  |  Branch (174:7): [True: 550, False: 322]
  |  Branch (174:26): [True: 106, False: 444]
  ------------------
  175|       |
  176|    828|    while ((bufferptr - buffer_start) % 64 != 0 && src < srcend) {
  ------------------
  |  Branch (176:12): [True: 784, False: 44]
  |  Branch (176:52): [True: 772, False: 12]
  ------------------
  177|    772|      uint8_t val = to_base64[uint8_t(*src)];
  178|    772|      *bufferptr = char(val);
  179|    772|      if (!ignore_garbage &&
  ------------------
  |  Branch (179:11): [True: 772, Folded]
  ------------------
  180|    772|          (!scalar::base64::is_eight_byte(*src) || val > 64)) {
  ------------------
  |  Branch (180:12): [True: 32, False: 740]
  |  Branch (180:52): [True: 18, False: 722]
  ------------------
  181|     50|        return {error_code::INVALID_BASE64_CHARACTER, size_t(src - srcinit),
  182|     50|                size_t(dst - dstinit)};
  183|     50|      }
  184|    722|      bufferptr += (val <= 63 && scalar::base64::is_eight_byte(*src));
  ------------------
  |  Branch (184:21): [True: 400, False: 322]
  |  Branch (184:34): [True: 400, False: 0]
  ------------------
  185|    722|      src++;
  186|    722|    }
  187|    106|  }
  188|       |
  189|  1.19k|  for (; buffer_start + 64 <= bufferptr; buffer_start += 64) {
  ------------------
  |  Branch (189:10): [True: 372, False: 822]
  ------------------
  190|       |    // 8 payload bytes still in the buffer become 6 output bytes, which cover
  191|       |    // the 4-byte tail of a wide store. Fewer than that, and the tail can
  192|       |    // stick out past the real end.
  193|    372|    const size_t after = size_t(bufferptr - (buffer_start + 64));
  194|    372|    if (after >= 8) {
  ------------------
  |  Branch (194:9): [True: 310, False: 62]
  ------------------
  195|    310|      base64_decode_block(dst, buffer_start);
  196|    310|    } else {
  197|     62|      base64_decode_block<true>(dst, buffer_start);
  198|     62|    }
  199|    372|    dst += 48;
  200|    372|  }
  201|    822|  if ((bufferptr - buffer_start) % 64 != 0) {
  ------------------
  |  Branch (201:7): [True: 456, False: 366]
  ------------------
  202|  3.79k|    while (buffer_start + 4 < bufferptr) {
  ------------------
  |  Branch (202:12): [True: 3.33k, False: 456]
  ------------------
  203|  3.33k|      uint32_t triple = ((uint32_t(uint8_t(buffer_start[0])) << 3 * 6) +
  204|  3.33k|                         (uint32_t(uint8_t(buffer_start[1])) << 2 * 6) +
  205|  3.33k|                         (uint32_t(uint8_t(buffer_start[2])) << 1 * 6) +
  206|  3.33k|                         (uint32_t(uint8_t(buffer_start[3])) << 0 * 6))
  207|  3.33k|                        << 8;
  208|  3.33k|#if !SIMDUTF_IS_BIG_ENDIAN
  209|  3.33k|      triple = scalar::u32_swap_bytes(triple);
  210|  3.33k|#endif
  211|  3.33k|      std::memcpy(dst, &triple, 3);
  212|       |
  213|  3.33k|      dst += 3;
  214|  3.33k|      buffer_start += 4;
  215|  3.33k|    }
  216|    456|    if (buffer_start + 4 <= bufferptr) {
  ------------------
  |  Branch (216:9): [True: 112, False: 344]
  ------------------
  217|    112|      uint32_t triple = ((uint32_t(uint8_t(buffer_start[0])) << 3 * 6) +
  218|    112|                         (uint32_t(uint8_t(buffer_start[1])) << 2 * 6) +
  219|    112|                         (uint32_t(uint8_t(buffer_start[2])) << 1 * 6) +
  220|    112|                         (uint32_t(uint8_t(buffer_start[3])) << 0 * 6))
  221|    112|                        << 8;
  222|    112|#if !SIMDUTF_IS_BIG_ENDIAN
  223|    112|      triple = scalar::u32_swap_bytes(triple);
  224|    112|#endif
  225|    112|      std::memcpy(dst, &triple, 3);
  226|       |
  227|    112|      dst += 3;
  228|    112|      buffer_start += 4;
  229|    112|    }
  230|       |    // we may have 1, 2 or 3 bytes left and we need to decode them so let us
  231|       |    // backtrack
  232|    456|    int leftover = int(bufferptr - buffer_start);
  233|  1.13k|    while (leftover > 0) {
  ------------------
  |  Branch (233:12): [True: 680, False: 456]
  ------------------
  234|    680|      if (!ignore_garbage) {
  ------------------
  |  Branch (234:11): [True: 680, Folded]
  ------------------
  235|  5.57k|        while (to_base64[uint8_t(*(src - 1))] == 64) {
  ------------------
  |  Branch (235:16): [True: 4.89k, False: 680]
  ------------------
  236|  4.89k|          src--;
  237|  4.89k|        }
  238|    680|      } else {
  239|      0|        while (!scalar::base64::is_eight_byte(*(src - 1)) ||
  ------------------
  |  Branch (239:16): [True: 0, False: 0]
  ------------------
  240|      0|               to_base64[uint8_t(*(src - 1))] >= 64) {
  ------------------
  |  Branch (240:16): [True: 0, False: 0]
  ------------------
  241|      0|          src--;
  242|      0|        }
  243|      0|      }
  244|    680|      src--;
  245|    680|      leftover--;
  246|    680|    }
  247|    456|  }
  248|    822|  if (src < srcend + equalsigns) {
  ------------------
  |  Branch (248:7): [True: 688, False: 134]
  ------------------
  249|    688|    full_result r = scalar::base64::base64_tail_decode(
  250|    688|        dst, src, srcend - src, equalsigns, options, last_chunk_options);
  251|    688|    r = scalar::base64::patch_tail_result(
  252|    688|        r, size_t(src - srcinit), size_t(dst - dstinit), equallocation,
  253|    688|        full_input_length, last_chunk_options);
  254|       |    // When is_partial(last_chunk_options) is true, we must either end with
  255|       |    // the end of the stream (beyond whitespace) or right after a non-ignorable
  256|       |    // character or at the very beginning of the stream.
  257|       |    // See https://tc39.es/proposal-arraybuffer-base64/spec/#sec-frombase64
  258|    688|    if (is_partial(last_chunk_options) && r.error == error_code::SUCCESS &&
  ------------------
  |  Branch (258:9): [True: 372, False: 316]
  |  Branch (258:43): [True: 314, False: 58]
  ------------------
  259|    314|        r.input_count < full_input_length) {
  ------------------
  |  Branch (259:9): [True: 278, False: 36]
  ------------------
  260|       |      // First check if we can extend the input to the end of the stream
  261|    608|      while (r.input_count < full_input_length &&
  ------------------
  |  Branch (261:14): [True: 600, False: 8]
  ------------------
  262|    600|             base64_ignorable(*(srcinit + r.input_count), options)) {
  ------------------
  |  Branch (262:14): [True: 330, False: 270]
  ------------------
  263|    330|        r.input_count++;
  264|    330|      }
  265|       |      // If we are still not at the end of the stream, then we must backtrack
  266|       |      // to the last non-ignorable character.
  267|    278|      if (r.input_count < full_input_length) {
  ------------------
  |  Branch (267:11): [True: 270, False: 8]
  ------------------
  268|  3.61k|        while (r.input_count > 0 &&
  ------------------
  |  Branch (268:16): [True: 3.54k, False: 64]
  ------------------
  269|  3.54k|               base64_ignorable(*(srcinit + r.input_count - 1), options)) {
  ------------------
  |  Branch (269:16): [True: 3.34k, False: 206]
  ------------------
  270|  3.34k|          r.input_count--;
  271|  3.34k|        }
  272|    270|      }
  273|    278|    }
  274|    688|    return r;
  275|    688|  }
  276|    134|  if (!ignore_garbage && equalsigns > 0) {
  ------------------
  |  Branch (276:7): [True: 134, Folded]
  |  Branch (276:26): [True: 0, False: 134]
  ------------------
  277|      0|    if ((size_t(dst - dstinit) % 3 == 0) ||
  ------------------
  |  Branch (277:9): [True: 0, False: 0]
  ------------------
  278|      0|        ((size_t(dst - dstinit) % 3) + 1 + equalsigns != 4)) {
  ------------------
  |  Branch (278:9): [True: 0, False: 0]
  ------------------
  279|      0|      return {INVALID_BASE64_CHARACTER, equallocation, size_t(dst - dstinit),
  280|      0|              true};
  281|      0|    }
  282|      0|  }
  283|    134|  return {SUCCESS, srclen, size_t(dst - dstinit)};
  284|    134|}
simdutf.cpp:_ZN7simdutf8westmere12_GLOBAL__N_16base6422compress_decode_base64ILb1ELb0ELb0EcEENS_11full_resultEPcPKT2_mNS_14base64_optionsENS_27last_chunk_handling_optionsE:
   45|  1.96k|                       last_chunk_handling_options last_chunk_options) {
   46|  1.96k|  const uint8_t *to_base64 =
   47|  1.96k|      default_or_url ? tables::base64::to_base64_default_or_url_value
  ------------------
  |  Branch (47:7): [Folded, False: 1.96k]
  ------------------
   48|  1.96k|                     : (base64_url ? tables::base64::to_base64_url_value
  ------------------
  |  Branch (48:25): [True: 1.96k, Folded]
  ------------------
   49|  1.96k|                                   : tables::base64::to_base64_value);
   50|  1.96k|  auto ri =
   51|  1.96k|      ignore_garbage
  ------------------
  |  Branch (51:7): [Folded, False: 1.96k]
  ------------------
   52|  1.96k|          ? simdutf::scalar::base64::reduced_input{0, srclen, srclen, srclen}
   53|  1.96k|          : simdutf::scalar::base64::find_end(src, srclen, options);
   54|  1.96k|  size_t equallocation = ri.equallocation;
   55|  1.96k|  size_t equalsigns = ri.equalsigns;
   56|  1.96k|  srclen = ri.srclen;
   57|  1.96k|  size_t full_input_length = ri.full_input_length;
   58|  1.96k|  if (srclen == 0) {
  ------------------
  |  Branch (58:7): [True: 16, False: 1.94k]
  ------------------
   59|     16|    if (!ignore_garbage && equalsigns > 0) {
  ------------------
  |  Branch (59:9): [True: 16, Folded]
  |  Branch (59:28): [True: 4, False: 12]
  ------------------
   60|      4|      return {INVALID_BASE64_CHARACTER, equallocation, 0, true};
   61|      4|    }
   62|     12|    return {SUCCESS, full_input_length, 0};
   63|     16|  }
   64|  1.94k|  const chartype *const srcinit = src;
   65|  1.94k|  const char *const dstinit = dst;
   66|  1.94k|  const chartype *srcend = src + srclen;
   67|       |
   68|  1.94k|  constexpr size_t block_size = 6;
   69|  1.94k|  static_assert(block_size >= 2, "block_size must be at least two");
   70|  1.94k|  char buffer[block_size * 64];
   71|  1.94k|  char *bufferptr = buffer;
   72|       |  // A wide block store writes 4 bytes past its 48. That is safe when the next
   73|       |  // store starts 48 bytes later. Pairs of clean blocks wide-store the first
   74|       |  // and end the second on byte 48. Anything shorter, or a block that is not
   75|       |  // clean, uses the exact store. The pair attempt is only worth it on a long
   76|       |  // input: a short one often fails the first block and then repeats that work.
   77|  1.94k|  if (srclen >= 512) {
  ------------------
  |  Branch (77:7): [True: 1.02k, False: 920]
  ------------------
   78|  1.02k|    const chartype *const srcend128 = src + srclen - 128;
   79|  25.0k|    while (bufferptr == buffer && src <= srcend128) {
  ------------------
  |  Branch (79:12): [True: 25.0k, False: 0]
  |  Branch (79:35): [True: 25.0k, False: 16]
  ------------------
   80|  25.0k|      block64 b0(src);
   81|  25.0k|      uint64_t e0 = 0;
   82|  25.0k|      const uint64_t m0 =
   83|  25.0k|          b0.to_base64_mask<base64_url, ignore_garbage, default_or_url>(&e0);
   84|  25.0k|      if ((!ignore_garbage && e0) || m0 != 0) {
  ------------------
  |  Branch (84:12): [True: 25.0k, Folded]
  |  Branch (84:31): [True: 250, False: 24.8k]
  |  Branch (84:38): [True: 336, False: 24.4k]
  ------------------
   85|    586|        break;
   86|    586|      }
   87|  24.4k|      block64 b1(src + 64);
   88|  24.4k|      uint64_t e1 = 0;
   89|  24.4k|      const uint64_t m1 =
   90|  24.4k|          b1.to_base64_mask<base64_url, ignore_garbage, default_or_url>(&e1);
   91|  24.4k|      if ((!ignore_garbage && e1) || m1 != 0) {
  ------------------
  |  Branch (91:12): [True: 24.4k, Folded]
  |  Branch (91:31): [True: 216, False: 24.2k]
  |  Branch (91:38): [True: 208, False: 24.0k]
  ------------------
   92|    424|        break;
   93|    424|      }
   94|  24.0k|      b0.base64_decode_block(dst);
   95|  24.0k|      b1.template base64_decode_block<true>(dst + 48);
   96|  24.0k|      src += 128;
   97|  24.0k|      dst += 96;
   98|  24.0k|    }
   99|  1.02k|  }
  100|  1.94k|  if (srclen >= 64) {
  ------------------
  |  Branch (100:7): [True: 1.71k, False: 230]
  ------------------
  101|  1.71k|    const chartype *const srcend64 = srcinit + srclen - 64;
  102|  54.2k|    while (src <= srcend64) {
  ------------------
  |  Branch (102:12): [True: 53.6k, False: 576]
  ------------------
  103|  53.6k|      block64 b(src);
  104|  53.6k|      uint64_t error = 0;
  105|  53.6k|      const uint64_t badcharmask =
  106|  53.6k|          b.to_base64_mask<base64_url, ignore_garbage, default_or_url>(&error);
  107|  53.6k|      if (!ignore_garbage && error) {
  ------------------
  |  Branch (107:11): [True: 53.6k, Folded]
  |  Branch (107:30): [True: 1.14k, False: 52.5k]
  ------------------
  108|  1.14k|        const size_t error_offset = trailing_zeroes(error);
  109|  1.14k|        return {error_code::INVALID_BASE64_CHARACTER,
  110|  1.14k|                size_t(src - srcinit + error_offset), size_t(dst - dstinit)};
  111|  1.14k|      }
  112|  52.5k|      if (ignore_garbage && badcharmask != 0) {
  ------------------
  |  Branch (112:11): [Folded, False: 52.5k]
  |  Branch (112:29): [True: 0, False: 0]
  ------------------
  113|      0|        const uint64_t equals = block64(src).equal_sign_mask();
  114|      0|        if (equals != 0) {
  ------------------
  |  Branch (114:13): [True: 0, False: 0]
  ------------------
  115|      0|          const size_t offset = trailing_zeroes(equals);
  116|      0|          equallocation = size_t(src - srcinit) + offset;
  117|      0|          equalsigns = 1;
  118|      0|          srclen = equallocation;
  119|      0|          full_input_length = equallocation + 1;
  120|      0|          if (srclen == 0) {
  ------------------
  |  Branch (120:15): [True: 0, False: 0]
  ------------------
  121|      0|            return {SUCCESS, full_input_length, 0};
  122|      0|          }
  123|      0|          srcend = srcinit + srclen;
  124|      0|          src = srcend;
  125|      0|          bufferptr += b.compress_block(badcharmask | (~uint64_t(0) << offset),
  126|      0|                                        bufferptr);
  127|      0|          break;
  128|      0|        }
  129|      0|      }
  130|  52.5k|      src += 64;
  131|  52.5k|      if (badcharmask != 0) {
  ------------------
  |  Branch (131:11): [True: 27.6k, False: 24.9k]
  ------------------
  132|  27.6k|        bufferptr += b.compress_block(badcharmask, bufferptr);
  133|  27.6k|      } else if (bufferptr != buffer) {
  ------------------
  |  Branch (133:18): [True: 24.2k, False: 752]
  ------------------
  134|  24.2k|        b.copy_block(bufferptr);
  135|  24.2k|        bufferptr += 64;
  136|  24.2k|      } else {
  137|    752|        b.template base64_decode_block<true>(dst);
  138|    752|        dst += 48;
  139|    752|      }
  140|  52.5k|      if (bufferptr >= (block_size - 1) * 64 + buffer) {
  ------------------
  |  Branch (140:11): [True: 9.82k, False: 42.7k]
  ------------------
  141|  49.1k|        for (size_t i = 0; i < (block_size - 2); i++) {
  ------------------
  |  Branch (141:28): [True: 39.2k, False: 9.82k]
  ------------------
  142|  39.2k|          base64_decode_block(dst, buffer + i * 64);
  143|  39.2k|          dst += 48;
  144|  39.2k|        }
  145|  9.82k|        base64_decode_block<true>(dst, buffer + (block_size - 2) * 64);
  146|  9.82k|        dst += 48;
  147|  9.82k|        std::memcpy(buffer, buffer + (block_size - 1) * 64,
  148|  9.82k|                    64); // 64 might be too much
  149|  9.82k|        bufferptr -= (block_size - 1) * 64;
  150|  9.82k|      }
  151|  52.5k|    }
  152|  1.71k|  }
  153|       |
  154|    806|  if (ignore_garbage && equalsigns == 0) {
  ------------------
  |  Branch (154:7): [Folded, False: 806]
  |  Branch (154:25): [True: 0, False: 0]
  ------------------
  155|      0|    const chartype *equal = src;
  156|      0|    while (equal < srcend && *equal != '=') {
  ------------------
  |  Branch (156:12): [True: 0, False: 0]
  |  Branch (156:30): [True: 0, False: 0]
  ------------------
  157|      0|      equal++;
  158|      0|    }
  159|      0|    if (equal < srcend) {
  ------------------
  |  Branch (159:9): [True: 0, False: 0]
  ------------------
  160|      0|      equallocation = size_t(equal - srcinit);
  161|      0|      equalsigns = 1;
  162|      0|      srclen = equallocation;
  163|      0|      full_input_length = equallocation + 1;
  164|      0|      if (srclen == 0) {
  ------------------
  |  Branch (164:11): [True: 0, False: 0]
  ------------------
  165|      0|        return {SUCCESS, full_input_length, 0};
  166|      0|      }
  167|      0|      srcend = equal;
  168|      0|    }
  169|      0|  }
  170|    806|  char *buffer_start = buffer;
  171|       |  // Optimization note: if this is almost full, then it is worth our
  172|       |  // time, otherwise, we should just decode directly.
  173|    806|  int last_block = (int)((bufferptr - buffer_start) % 64);
  174|    806|  if (last_block != 0 && srcend - src + last_block >= 64) {
  ------------------
  |  Branch (174:7): [True: 526, False: 280]
  |  Branch (174:26): [True: 70, False: 456]
  ------------------
  175|       |
  176|    788|    while ((bufferptr - buffer_start) % 64 != 0 && src < srcend) {
  ------------------
  |  Branch (176:12): [True: 740, False: 48]
  |  Branch (176:52): [True: 724, False: 16]
  ------------------
  177|    724|      uint8_t val = to_base64[uint8_t(*src)];
  178|    724|      *bufferptr = char(val);
  179|    724|      if (!ignore_garbage &&
  ------------------
  |  Branch (179:11): [True: 724, Folded]
  ------------------
  180|    724|          (!scalar::base64::is_eight_byte(*src) || val > 64)) {
  ------------------
  |  Branch (180:12): [True: 0, False: 724]
  |  Branch (180:52): [True: 6, False: 718]
  ------------------
  181|      6|        return {error_code::INVALID_BASE64_CHARACTER, size_t(src - srcinit),
  182|      6|                size_t(dst - dstinit)};
  183|      6|      }
  184|    718|      bufferptr += (val <= 63 && scalar::base64::is_eight_byte(*src));
  ------------------
  |  Branch (184:21): [True: 384, False: 334]
  |  Branch (184:34): [True: 384, False: 0]
  ------------------
  185|    718|      src++;
  186|    718|    }
  187|     70|  }
  188|       |
  189|  1.22k|  for (; buffer_start + 64 <= bufferptr; buffer_start += 64) {
  ------------------
  |  Branch (189:10): [True: 424, False: 800]
  ------------------
  190|       |    // 8 payload bytes still in the buffer become 6 output bytes, which cover
  191|       |    // the 4-byte tail of a wide store. Fewer than that, and the tail can
  192|       |    // stick out past the real end.
  193|    424|    const size_t after = size_t(bufferptr - (buffer_start + 64));
  194|    424|    if (after >= 8) {
  ------------------
  |  Branch (194:9): [True: 354, False: 70]
  ------------------
  195|    354|      base64_decode_block(dst, buffer_start);
  196|    354|    } else {
  197|     70|      base64_decode_block<true>(dst, buffer_start);
  198|     70|    }
  199|    424|    dst += 48;
  200|    424|  }
  201|    800|  if ((bufferptr - buffer_start) % 64 != 0) {
  ------------------
  |  Branch (201:7): [True: 472, False: 328]
  ------------------
  202|  4.19k|    while (buffer_start + 4 < bufferptr) {
  ------------------
  |  Branch (202:12): [True: 3.72k, False: 472]
  ------------------
  203|  3.72k|      uint32_t triple = ((uint32_t(uint8_t(buffer_start[0])) << 3 * 6) +
  204|  3.72k|                         (uint32_t(uint8_t(buffer_start[1])) << 2 * 6) +
  205|  3.72k|                         (uint32_t(uint8_t(buffer_start[2])) << 1 * 6) +
  206|  3.72k|                         (uint32_t(uint8_t(buffer_start[3])) << 0 * 6))
  207|  3.72k|                        << 8;
  208|  3.72k|#if !SIMDUTF_IS_BIG_ENDIAN
  209|  3.72k|      triple = scalar::u32_swap_bytes(triple);
  210|  3.72k|#endif
  211|  3.72k|      std::memcpy(dst, &triple, 3);
  212|       |
  213|  3.72k|      dst += 3;
  214|  3.72k|      buffer_start += 4;
  215|  3.72k|    }
  216|    472|    if (buffer_start + 4 <= bufferptr) {
  ------------------
  |  Branch (216:9): [True: 124, False: 348]
  ------------------
  217|    124|      uint32_t triple = ((uint32_t(uint8_t(buffer_start[0])) << 3 * 6) +
  218|    124|                         (uint32_t(uint8_t(buffer_start[1])) << 2 * 6) +
  219|    124|                         (uint32_t(uint8_t(buffer_start[2])) << 1 * 6) +
  220|    124|                         (uint32_t(uint8_t(buffer_start[3])) << 0 * 6))
  221|    124|                        << 8;
  222|    124|#if !SIMDUTF_IS_BIG_ENDIAN
  223|    124|      triple = scalar::u32_swap_bytes(triple);
  224|    124|#endif
  225|    124|      std::memcpy(dst, &triple, 3);
  226|       |
  227|    124|      dst += 3;
  228|    124|      buffer_start += 4;
  229|    124|    }
  230|       |    // we may have 1, 2 or 3 bytes left and we need to decode them so let us
  231|       |    // backtrack
  232|    472|    int leftover = int(bufferptr - buffer_start);
  233|  1.14k|    while (leftover > 0) {
  ------------------
  |  Branch (233:12): [True: 674, False: 472]
  ------------------
  234|    674|      if (!ignore_garbage) {
  ------------------
  |  Branch (234:11): [True: 674, Folded]
  ------------------
  235|  4.63k|        while (to_base64[uint8_t(*(src - 1))] == 64) {
  ------------------
  |  Branch (235:16): [True: 3.95k, False: 674]
  ------------------
  236|  3.95k|          src--;
  237|  3.95k|        }
  238|    674|      } else {
  239|      0|        while (!scalar::base64::is_eight_byte(*(src - 1)) ||
  ------------------
  |  Branch (239:16): [True: 0, False: 0]
  ------------------
  240|      0|               to_base64[uint8_t(*(src - 1))] >= 64) {
  ------------------
  |  Branch (240:16): [True: 0, False: 0]
  ------------------
  241|      0|          src--;
  242|      0|        }
  243|      0|      }
  244|    674|      src--;
  245|    674|      leftover--;
  246|    674|    }
  247|    472|  }
  248|    800|  if (src < srcend + equalsigns) {
  ------------------
  |  Branch (248:7): [True: 630, False: 170]
  ------------------
  249|    630|    full_result r = scalar::base64::base64_tail_decode(
  250|    630|        dst, src, srcend - src, equalsigns, options, last_chunk_options);
  251|    630|    r = scalar::base64::patch_tail_result(
  252|    630|        r, size_t(src - srcinit), size_t(dst - dstinit), equallocation,
  253|    630|        full_input_length, last_chunk_options);
  254|       |    // When is_partial(last_chunk_options) is true, we must either end with
  255|       |    // the end of the stream (beyond whitespace) or right after a non-ignorable
  256|       |    // character or at the very beginning of the stream.
  257|       |    // See https://tc39.es/proposal-arraybuffer-base64/spec/#sec-frombase64
  258|    630|    if (is_partial(last_chunk_options) && r.error == error_code::SUCCESS &&
  ------------------
  |  Branch (258:9): [True: 320, False: 310]
  |  Branch (258:43): [True: 302, False: 18]
  ------------------
  259|    302|        r.input_count < full_input_length) {
  ------------------
  |  Branch (259:9): [True: 260, False: 42]
  ------------------
  260|       |      // First check if we can extend the input to the end of the stream
  261|    714|      while (r.input_count < full_input_length &&
  ------------------
  |  Branch (261:14): [True: 708, False: 6]
  ------------------
  262|    708|             base64_ignorable(*(srcinit + r.input_count), options)) {
  ------------------
  |  Branch (262:14): [True: 454, False: 254]
  ------------------
  263|    454|        r.input_count++;
  264|    454|      }
  265|       |      // If we are still not at the end of the stream, then we must backtrack
  266|       |      // to the last non-ignorable character.
  267|    260|      if (r.input_count < full_input_length) {
  ------------------
  |  Branch (267:11): [True: 254, False: 6]
  ------------------
  268|  1.79k|        while (r.input_count > 0 &&
  ------------------
  |  Branch (268:16): [True: 1.73k, False: 56]
  ------------------
  269|  1.73k|               base64_ignorable(*(srcinit + r.input_count - 1), options)) {
  ------------------
  |  Branch (269:16): [True: 1.54k, False: 198]
  ------------------
  270|  1.54k|          r.input_count--;
  271|  1.54k|        }
  272|    254|      }
  273|    260|    }
  274|    630|    return r;
  275|    630|  }
  276|    170|  if (!ignore_garbage && equalsigns > 0) {
  ------------------
  |  Branch (276:7): [True: 170, Folded]
  |  Branch (276:26): [True: 0, False: 170]
  ------------------
  277|      0|    if ((size_t(dst - dstinit) % 3 == 0) ||
  ------------------
  |  Branch (277:9): [True: 0, False: 0]
  ------------------
  278|      0|        ((size_t(dst - dstinit) % 3) + 1 + equalsigns != 4)) {
  ------------------
  |  Branch (278:9): [True: 0, False: 0]
  ------------------
  279|      0|      return {INVALID_BASE64_CHARACTER, equallocation, size_t(dst - dstinit),
  280|      0|              true};
  281|      0|    }
  282|      0|  }
  283|    170|  return {SUCCESS, srclen, size_t(dst - dstinit)};
  284|    170|}
simdutf.cpp:_ZN7simdutf8westmere12_GLOBAL__N_16base6422compress_decode_base64ILb0ELb0ELb0EcEENS_11full_resultEPcPKT2_mNS_14base64_optionsENS_27last_chunk_handling_optionsE:
   45|  2.11k|                       last_chunk_handling_options last_chunk_options) {
   46|  2.11k|  const uint8_t *to_base64 =
   47|  2.11k|      default_or_url ? tables::base64::to_base64_default_or_url_value
  ------------------
  |  Branch (47:7): [Folded, False: 2.11k]
  ------------------
   48|  2.11k|                     : (base64_url ? tables::base64::to_base64_url_value
  ------------------
  |  Branch (48:25): [Folded, False: 2.11k]
  ------------------
   49|  2.11k|                                   : tables::base64::to_base64_value);
   50|  2.11k|  auto ri =
   51|  2.11k|      ignore_garbage
  ------------------
  |  Branch (51:7): [Folded, False: 2.11k]
  ------------------
   52|  2.11k|          ? simdutf::scalar::base64::reduced_input{0, srclen, srclen, srclen}
   53|  2.11k|          : simdutf::scalar::base64::find_end(src, srclen, options);
   54|  2.11k|  size_t equallocation = ri.equallocation;
   55|  2.11k|  size_t equalsigns = ri.equalsigns;
   56|  2.11k|  srclen = ri.srclen;
   57|  2.11k|  size_t full_input_length = ri.full_input_length;
   58|  2.11k|  if (srclen == 0) {
  ------------------
  |  Branch (58:7): [True: 24, False: 2.08k]
  ------------------
   59|     24|    if (!ignore_garbage && equalsigns > 0) {
  ------------------
  |  Branch (59:9): [True: 24, Folded]
  |  Branch (59:28): [True: 14, False: 10]
  ------------------
   60|     14|      return {INVALID_BASE64_CHARACTER, equallocation, 0, true};
   61|     14|    }
   62|     10|    return {SUCCESS, full_input_length, 0};
   63|     24|  }
   64|  2.08k|  const chartype *const srcinit = src;
   65|  2.08k|  const char *const dstinit = dst;
   66|  2.08k|  const chartype *srcend = src + srclen;
   67|       |
   68|  2.08k|  constexpr size_t block_size = 6;
   69|  2.08k|  static_assert(block_size >= 2, "block_size must be at least two");
   70|  2.08k|  char buffer[block_size * 64];
   71|  2.08k|  char *bufferptr = buffer;
   72|       |  // A wide block store writes 4 bytes past its 48. That is safe when the next
   73|       |  // store starts 48 bytes later. Pairs of clean blocks wide-store the first
   74|       |  // and end the second on byte 48. Anything shorter, or a block that is not
   75|       |  // clean, uses the exact store. The pair attempt is only worth it on a long
   76|       |  // input: a short one often fails the first block and then repeats that work.
   77|  2.08k|  if (srclen >= 512) {
  ------------------
  |  Branch (77:7): [True: 1.05k, False: 1.03k]
  ------------------
   78|  1.05k|    const chartype *const srcend128 = src + srclen - 128;
   79|  36.3k|    while (bufferptr == buffer && src <= srcend128) {
  ------------------
  |  Branch (79:12): [True: 36.3k, False: 0]
  |  Branch (79:35): [True: 36.2k, False: 22]
  ------------------
   80|  36.2k|      block64 b0(src);
   81|  36.2k|      uint64_t e0 = 0;
   82|  36.2k|      const uint64_t m0 =
   83|  36.2k|          b0.to_base64_mask<base64_url, ignore_garbage, default_or_url>(&e0);
   84|  36.2k|      if ((!ignore_garbage && e0) || m0 != 0) {
  ------------------
  |  Branch (84:12): [True: 36.2k, Folded]
  |  Branch (84:31): [True: 266, False: 36.0k]
  |  Branch (84:38): [True: 350, False: 35.6k]
  ------------------
   85|    616|        break;
   86|    616|      }
   87|  35.6k|      block64 b1(src + 64);
   88|  35.6k|      uint64_t e1 = 0;
   89|  35.6k|      const uint64_t m1 =
   90|  35.6k|          b1.to_base64_mask<base64_url, ignore_garbage, default_or_url>(&e1);
   91|  35.6k|      if ((!ignore_garbage && e1) || m1 != 0) {
  ------------------
  |  Branch (91:12): [True: 35.6k, Folded]
  |  Branch (91:31): [True: 228, False: 35.4k]
  |  Branch (91:38): [True: 192, False: 35.2k]
  ------------------
   92|    420|        break;
   93|    420|      }
   94|  35.2k|      b0.base64_decode_block(dst);
   95|  35.2k|      b1.template base64_decode_block<true>(dst + 48);
   96|  35.2k|      src += 128;
   97|  35.2k|      dst += 96;
   98|  35.2k|    }
   99|  1.05k|  }
  100|  2.08k|  if (srclen >= 64) {
  ------------------
  |  Branch (100:7): [True: 1.78k, False: 304]
  ------------------
  101|  1.78k|    const chartype *const srcend64 = srcinit + srclen - 64;
  102|   163k|    while (src <= srcend64) {
  ------------------
  |  Branch (102:12): [True: 162k, False: 656]
  ------------------
  103|   162k|      block64 b(src);
  104|   162k|      uint64_t error = 0;
  105|   162k|      const uint64_t badcharmask =
  106|   162k|          b.to_base64_mask<base64_url, ignore_garbage, default_or_url>(&error);
  107|   162k|      if (!ignore_garbage && error) {
  ------------------
  |  Branch (107:11): [True: 162k, Folded]
  |  Branch (107:30): [True: 1.12k, False: 161k]
  ------------------
  108|  1.12k|        const size_t error_offset = trailing_zeroes(error);
  109|  1.12k|        return {error_code::INVALID_BASE64_CHARACTER,
  110|  1.12k|                size_t(src - srcinit + error_offset), size_t(dst - dstinit)};
  111|  1.12k|      }
  112|   161k|      if (ignore_garbage && badcharmask != 0) {
  ------------------
  |  Branch (112:11): [Folded, False: 161k]
  |  Branch (112:29): [True: 0, False: 0]
  ------------------
  113|      0|        const uint64_t equals = block64(src).equal_sign_mask();
  114|      0|        if (equals != 0) {
  ------------------
  |  Branch (114:13): [True: 0, False: 0]
  ------------------
  115|      0|          const size_t offset = trailing_zeroes(equals);
  116|      0|          equallocation = size_t(src - srcinit) + offset;
  117|      0|          equalsigns = 1;
  118|      0|          srclen = equallocation;
  119|      0|          full_input_length = equallocation + 1;
  120|      0|          if (srclen == 0) {
  ------------------
  |  Branch (120:15): [True: 0, False: 0]
  ------------------
  121|      0|            return {SUCCESS, full_input_length, 0};
  122|      0|          }
  123|      0|          srcend = srcinit + srclen;
  124|      0|          src = srcend;
  125|      0|          bufferptr += b.compress_block(badcharmask | (~uint64_t(0) << offset),
  126|      0|                                        bufferptr);
  127|      0|          break;
  128|      0|        }
  129|      0|      }
  130|   161k|      src += 64;
  131|   161k|      if (badcharmask != 0) {
  ------------------
  |  Branch (131:11): [True: 47.2k, False: 114k]
  ------------------
  132|  47.2k|        bufferptr += b.compress_block(badcharmask, bufferptr);
  133|   114k|      } else if (bufferptr != buffer) {
  ------------------
  |  Branch (133:18): [True: 113k, False: 1.03k]
  ------------------
  134|   113k|        b.copy_block(bufferptr);
  135|   113k|        bufferptr += 64;
  136|   113k|      } else {
  137|  1.03k|        b.template base64_decode_block<true>(dst);
  138|  1.03k|        dst += 48;
  139|  1.03k|      }
  140|   161k|      if (bufferptr >= (block_size - 1) * 64 + buffer) {
  ------------------
  |  Branch (140:11): [True: 31.2k, False: 130k]
  ------------------
  141|   156k|        for (size_t i = 0; i < (block_size - 2); i++) {
  ------------------
  |  Branch (141:28): [True: 125k, False: 31.2k]
  ------------------
  142|   125k|          base64_decode_block(dst, buffer + i * 64);
  143|   125k|          dst += 48;
  144|   125k|        }
  145|  31.2k|        base64_decode_block<true>(dst, buffer + (block_size - 2) * 64);
  146|  31.2k|        dst += 48;
  147|  31.2k|        std::memcpy(buffer, buffer + (block_size - 1) * 64,
  148|  31.2k|                    64); // 64 might be too much
  149|  31.2k|        bufferptr -= (block_size - 1) * 64;
  150|  31.2k|      }
  151|   161k|    }
  152|  1.78k|  }
  153|       |
  154|    960|  if (ignore_garbage && equalsigns == 0) {
  ------------------
  |  Branch (154:7): [Folded, False: 960]
  |  Branch (154:25): [True: 0, False: 0]
  ------------------
  155|      0|    const chartype *equal = src;
  156|      0|    while (equal < srcend && *equal != '=') {
  ------------------
  |  Branch (156:12): [True: 0, False: 0]
  |  Branch (156:30): [True: 0, False: 0]
  ------------------
  157|      0|      equal++;
  158|      0|    }
  159|      0|    if (equal < srcend) {
  ------------------
  |  Branch (159:9): [True: 0, False: 0]
  ------------------
  160|      0|      equallocation = size_t(equal - srcinit);
  161|      0|      equalsigns = 1;
  162|      0|      srclen = equallocation;
  163|      0|      full_input_length = equallocation + 1;
  164|      0|      if (srclen == 0) {
  ------------------
  |  Branch (164:11): [True: 0, False: 0]
  ------------------
  165|      0|        return {SUCCESS, full_input_length, 0};
  166|      0|      }
  167|      0|      srcend = equal;
  168|      0|    }
  169|      0|  }
  170|    960|  char *buffer_start = buffer;
  171|       |  // Optimization note: if this is almost full, then it is worth our
  172|       |  // time, otherwise, we should just decode directly.
  173|    960|  int last_block = (int)((bufferptr - buffer_start) % 64);
  174|    960|  if (last_block != 0 && srcend - src + last_block >= 64) {
  ------------------
  |  Branch (174:7): [True: 600, False: 360]
  |  Branch (174:26): [True: 92, False: 508]
  ------------------
  175|       |
  176|  1.65k|    while ((bufferptr - buffer_start) % 64 != 0 && src < srcend) {
  ------------------
  |  Branch (176:12): [True: 1.58k, False: 64]
  |  Branch (176:52): [True: 1.56k, False: 24]
  ------------------
  177|  1.56k|      uint8_t val = to_base64[uint8_t(*src)];
  178|  1.56k|      *bufferptr = char(val);
  179|  1.56k|      if (!ignore_garbage &&
  ------------------
  |  Branch (179:11): [True: 1.56k, Folded]
  ------------------
  180|  1.56k|          (!scalar::base64::is_eight_byte(*src) || val > 64)) {
  ------------------
  |  Branch (180:12): [True: 0, False: 1.56k]
  |  Branch (180:52): [True: 4, False: 1.55k]
  ------------------
  181|      4|        return {error_code::INVALID_BASE64_CHARACTER, size_t(src - srcinit),
  182|      4|                size_t(dst - dstinit)};
  183|      4|      }
  184|  1.55k|      bufferptr += (val <= 63 && scalar::base64::is_eight_byte(*src));
  ------------------
  |  Branch (184:21): [True: 956, False: 602]
  |  Branch (184:34): [True: 956, False: 0]
  ------------------
  185|  1.55k|      src++;
  186|  1.55k|    }
  187|     92|  }
  188|       |
  189|  1.45k|  for (; buffer_start + 64 <= bufferptr; buffer_start += 64) {
  ------------------
  |  Branch (189:10): [True: 498, False: 956]
  ------------------
  190|       |    // 8 payload bytes still in the buffer become 6 output bytes, which cover
  191|       |    // the 4-byte tail of a wide store. Fewer than that, and the tail can
  192|       |    // stick out past the real end.
  193|    498|    const size_t after = size_t(bufferptr - (buffer_start + 64));
  194|    498|    if (after >= 8) {
  ------------------
  |  Branch (194:9): [True: 408, False: 90]
  ------------------
  195|    408|      base64_decode_block(dst, buffer_start);
  196|    408|    } else {
  197|     90|      base64_decode_block<true>(dst, buffer_start);
  198|     90|    }
  199|    498|    dst += 48;
  200|    498|  }
  201|    956|  if ((bufferptr - buffer_start) % 64 != 0) {
  ------------------
  |  Branch (201:7): [True: 532, False: 424]
  ------------------
  202|  4.71k|    while (buffer_start + 4 < bufferptr) {
  ------------------
  |  Branch (202:12): [True: 4.18k, False: 532]
  ------------------
  203|  4.18k|      uint32_t triple = ((uint32_t(uint8_t(buffer_start[0])) << 3 * 6) +
  204|  4.18k|                         (uint32_t(uint8_t(buffer_start[1])) << 2 * 6) +
  205|  4.18k|                         (uint32_t(uint8_t(buffer_start[2])) << 1 * 6) +
  206|  4.18k|                         (uint32_t(uint8_t(buffer_start[3])) << 0 * 6))
  207|  4.18k|                        << 8;
  208|  4.18k|#if !SIMDUTF_IS_BIG_ENDIAN
  209|  4.18k|      triple = scalar::u32_swap_bytes(triple);
  210|  4.18k|#endif
  211|  4.18k|      std::memcpy(dst, &triple, 3);
  212|       |
  213|  4.18k|      dst += 3;
  214|  4.18k|      buffer_start += 4;
  215|  4.18k|    }
  216|    532|    if (buffer_start + 4 <= bufferptr) {
  ------------------
  |  Branch (216:9): [True: 138, False: 394]
  ------------------
  217|    138|      uint32_t triple = ((uint32_t(uint8_t(buffer_start[0])) << 3 * 6) +
  218|    138|                         (uint32_t(uint8_t(buffer_start[1])) << 2 * 6) +
  219|    138|                         (uint32_t(uint8_t(buffer_start[2])) << 1 * 6) +
  220|    138|                         (uint32_t(uint8_t(buffer_start[3])) << 0 * 6))
  221|    138|                        << 8;
  222|    138|#if !SIMDUTF_IS_BIG_ENDIAN
  223|    138|      triple = scalar::u32_swap_bytes(triple);
  224|    138|#endif
  225|    138|      std::memcpy(dst, &triple, 3);
  226|       |
  227|    138|      dst += 3;
  228|    138|      buffer_start += 4;
  229|    138|    }
  230|       |    // we may have 1, 2 or 3 bytes left and we need to decode them so let us
  231|       |    // backtrack
  232|    532|    int leftover = int(bufferptr - buffer_start);
  233|  1.34k|    while (leftover > 0) {
  ------------------
  |  Branch (233:12): [True: 810, False: 532]
  ------------------
  234|    810|      if (!ignore_garbage) {
  ------------------
  |  Branch (234:11): [True: 810, Folded]
  ------------------
  235|  5.54k|        while (to_base64[uint8_t(*(src - 1))] == 64) {
  ------------------
  |  Branch (235:16): [True: 4.73k, False: 810]
  ------------------
  236|  4.73k|          src--;
  237|  4.73k|        }
  238|    810|      } else {
  239|      0|        while (!scalar::base64::is_eight_byte(*(src - 1)) ||
  ------------------
  |  Branch (239:16): [True: 0, False: 0]
  ------------------
  240|      0|               to_base64[uint8_t(*(src - 1))] >= 64) {
  ------------------
  |  Branch (240:16): [True: 0, False: 0]
  ------------------
  241|      0|          src--;
  242|      0|        }
  243|      0|      }
  244|    810|      src--;
  245|    810|      leftover--;
  246|    810|    }
  247|    532|  }
  248|    956|  if (src < srcend + equalsigns) {
  ------------------
  |  Branch (248:7): [True: 784, False: 172]
  ------------------
  249|    784|    full_result r = scalar::base64::base64_tail_decode(
  250|    784|        dst, src, srcend - src, equalsigns, options, last_chunk_options);
  251|    784|    r = scalar::base64::patch_tail_result(
  252|    784|        r, size_t(src - srcinit), size_t(dst - dstinit), equallocation,
  253|    784|        full_input_length, last_chunk_options);
  254|       |    // When is_partial(last_chunk_options) is true, we must either end with
  255|       |    // the end of the stream (beyond whitespace) or right after a non-ignorable
  256|       |    // character or at the very beginning of the stream.
  257|       |    // See https://tc39.es/proposal-arraybuffer-base64/spec/#sec-frombase64
  258|    784|    if (is_partial(last_chunk_options) && r.error == error_code::SUCCESS &&
  ------------------
  |  Branch (258:9): [True: 436, False: 348]
  |  Branch (258:43): [True: 396, False: 40]
  ------------------
  259|    396|        r.input_count < full_input_length) {
  ------------------
  |  Branch (259:9): [True: 328, False: 68]
  ------------------
  260|       |      // First check if we can extend the input to the end of the stream
  261|    686|      while (r.input_count < full_input_length &&
  ------------------
  |  Branch (261:14): [True: 676, False: 10]
  ------------------
  262|    676|             base64_ignorable(*(srcinit + r.input_count), options)) {
  ------------------
  |  Branch (262:14): [True: 358, False: 318]
  ------------------
  263|    358|        r.input_count++;
  264|    358|      }
  265|       |      // If we are still not at the end of the stream, then we must backtrack
  266|       |      // to the last non-ignorable character.
  267|    328|      if (r.input_count < full_input_length) {
  ------------------
  |  Branch (267:11): [True: 318, False: 10]
  ------------------
  268|  2.65k|        while (r.input_count > 0 &&
  ------------------
  |  Branch (268:16): [True: 2.60k, False: 56]
  ------------------
  269|  2.60k|               base64_ignorable(*(srcinit + r.input_count - 1), options)) {
  ------------------
  |  Branch (269:16): [True: 2.34k, False: 262]
  ------------------
  270|  2.34k|          r.input_count--;
  271|  2.34k|        }
  272|    318|      }
  273|    328|    }
  274|    784|    return r;
  275|    784|  }
  276|    172|  if (!ignore_garbage && equalsigns > 0) {
  ------------------
  |  Branch (276:7): [True: 172, Folded]
  |  Branch (276:26): [True: 0, False: 172]
  ------------------
  277|      0|    if ((size_t(dst - dstinit) % 3 == 0) ||
  ------------------
  |  Branch (277:9): [True: 0, False: 0]
  ------------------
  278|      0|        ((size_t(dst - dstinit) % 3) + 1 + equalsigns != 4)) {
  ------------------
  |  Branch (278:9): [True: 0, False: 0]
  ------------------
  279|      0|      return {INVALID_BASE64_CHARACTER, equallocation, size_t(dst - dstinit),
  280|      0|              true};
  281|      0|    }
  282|      0|  }
  283|    172|  return {SUCCESS, srclen, size_t(dst - dstinit)};
  284|    172|}
simdutf.cpp:_ZN7simdutf8westmere12_GLOBAL__N_16base6422compress_decode_base64ILb1ELb0ELb0EDsEENS_11full_resultEPcPKT2_mNS_14base64_optionsENS_27last_chunk_handling_optionsE:
   45|  2.03k|                       last_chunk_handling_options last_chunk_options) {
   46|  2.03k|  const uint8_t *to_base64 =
   47|  2.03k|      default_or_url ? tables::base64::to_base64_default_or_url_value
  ------------------
  |  Branch (47:7): [Folded, False: 2.03k]
  ------------------
   48|  2.03k|                     : (base64_url ? tables::base64::to_base64_url_value
  ------------------
  |  Branch (48:25): [True: 2.03k, Folded]
  ------------------
   49|  2.03k|                                   : tables::base64::to_base64_value);
   50|  2.03k|  auto ri =
   51|  2.03k|      ignore_garbage
  ------------------
  |  Branch (51:7): [Folded, False: 2.03k]
  ------------------
   52|  2.03k|          ? simdutf::scalar::base64::reduced_input{0, srclen, srclen, srclen}
   53|  2.03k|          : simdutf::scalar::base64::find_end(src, srclen, options);
   54|  2.03k|  size_t equallocation = ri.equallocation;
   55|  2.03k|  size_t equalsigns = ri.equalsigns;
   56|  2.03k|  srclen = ri.srclen;
   57|  2.03k|  size_t full_input_length = ri.full_input_length;
   58|  2.03k|  if (srclen == 0) {
  ------------------
  |  Branch (58:7): [True: 14, False: 2.02k]
  ------------------
   59|     14|    if (!ignore_garbage && equalsigns > 0) {
  ------------------
  |  Branch (59:9): [True: 14, Folded]
  |  Branch (59:28): [True: 8, False: 6]
  ------------------
   60|      8|      return {INVALID_BASE64_CHARACTER, equallocation, 0, true};
   61|      8|    }
   62|      6|    return {SUCCESS, full_input_length, 0};
   63|     14|  }
   64|  2.02k|  const chartype *const srcinit = src;
   65|  2.02k|  const char *const dstinit = dst;
   66|  2.02k|  const chartype *srcend = src + srclen;
   67|       |
   68|  2.02k|  constexpr size_t block_size = 6;
   69|  2.02k|  static_assert(block_size >= 2, "block_size must be at least two");
   70|  2.02k|  char buffer[block_size * 64];
   71|  2.02k|  char *bufferptr = buffer;
   72|       |  // A wide block store writes 4 bytes past its 48. That is safe when the next
   73|       |  // store starts 48 bytes later. Pairs of clean blocks wide-store the first
   74|       |  // and end the second on byte 48. Anything shorter, or a block that is not
   75|       |  // clean, uses the exact store. The pair attempt is only worth it on a long
   76|       |  // input: a short one often fails the first block and then repeats that work.
   77|  2.02k|  if (srclen >= 512) {
  ------------------
  |  Branch (77:7): [True: 984, False: 1.04k]
  ------------------
   78|    984|    const chartype *const srcend128 = src + srclen - 128;
   79|  1.43k|    while (bufferptr == buffer && src <= srcend128) {
  ------------------
  |  Branch (79:12): [True: 1.43k, False: 0]
  |  Branch (79:35): [True: 1.42k, False: 12]
  ------------------
   80|  1.42k|      block64 b0(src);
   81|  1.42k|      uint64_t e0 = 0;
   82|  1.42k|      const uint64_t m0 =
   83|  1.42k|          b0.to_base64_mask<base64_url, ignore_garbage, default_or_url>(&e0);
   84|  1.42k|      if ((!ignore_garbage && e0) || m0 != 0) {
  ------------------
  |  Branch (84:12): [True: 1.42k, Folded]
  |  Branch (84:31): [True: 250, False: 1.17k]
  |  Branch (84:38): [True: 318, False: 856]
  ------------------
   85|    568|        break;
   86|    568|      }
   87|    856|      block64 b1(src + 64);
   88|    856|      uint64_t e1 = 0;
   89|    856|      const uint64_t m1 =
   90|    856|          b1.to_base64_mask<base64_url, ignore_garbage, default_or_url>(&e1);
   91|    856|      if ((!ignore_garbage && e1) || m1 != 0) {
  ------------------
  |  Branch (91:12): [True: 856, Folded]
  |  Branch (91:31): [True: 206, False: 650]
  |  Branch (91:38): [True: 198, False: 452]
  ------------------
   92|    404|        break;
   93|    404|      }
   94|    452|      b0.base64_decode_block(dst);
   95|    452|      b1.template base64_decode_block<true>(dst + 48);
   96|    452|      src += 128;
   97|    452|      dst += 96;
   98|    452|    }
   99|    984|  }
  100|  2.02k|  if (srclen >= 64) {
  ------------------
  |  Branch (100:7): [True: 1.71k, False: 308]
  ------------------
  101|  1.71k|    const chartype *const srcend64 = srcinit + srclen - 64;
  102|  48.0k|    while (src <= srcend64) {
  ------------------
  |  Branch (102:12): [True: 47.4k, False: 594]
  ------------------
  103|  47.4k|      block64 b(src);
  104|  47.4k|      uint64_t error = 0;
  105|  47.4k|      const uint64_t badcharmask =
  106|  47.4k|          b.to_base64_mask<base64_url, ignore_garbage, default_or_url>(&error);
  107|  47.4k|      if (!ignore_garbage && error) {
  ------------------
  |  Branch (107:11): [True: 47.4k, Folded]
  |  Branch (107:30): [True: 1.12k, False: 46.3k]
  ------------------
  108|  1.12k|        const size_t error_offset = trailing_zeroes(error);
  109|  1.12k|        return {error_code::INVALID_BASE64_CHARACTER,
  110|  1.12k|                size_t(src - srcinit + error_offset), size_t(dst - dstinit)};
  111|  1.12k|      }
  112|  46.3k|      if (ignore_garbage && badcharmask != 0) {
  ------------------
  |  Branch (112:11): [Folded, False: 46.3k]
  |  Branch (112:29): [True: 0, False: 0]
  ------------------
  113|      0|        const uint64_t equals = block64(src).equal_sign_mask();
  114|      0|        if (equals != 0) {
  ------------------
  |  Branch (114:13): [True: 0, False: 0]
  ------------------
  115|      0|          const size_t offset = trailing_zeroes(equals);
  116|      0|          equallocation = size_t(src - srcinit) + offset;
  117|      0|          equalsigns = 1;
  118|      0|          srclen = equallocation;
  119|      0|          full_input_length = equallocation + 1;
  120|      0|          if (srclen == 0) {
  ------------------
  |  Branch (120:15): [True: 0, False: 0]
  ------------------
  121|      0|            return {SUCCESS, full_input_length, 0};
  122|      0|          }
  123|      0|          srcend = srcinit + srclen;
  124|      0|          src = srcend;
  125|      0|          bufferptr += b.compress_block(badcharmask | (~uint64_t(0) << offset),
  126|      0|                                        bufferptr);
  127|      0|          break;
  128|      0|        }
  129|      0|      }
  130|  46.3k|      src += 64;
  131|  46.3k|      if (badcharmask != 0) {
  ------------------
  |  Branch (131:11): [True: 37.9k, False: 8.33k]
  ------------------
  132|  37.9k|        bufferptr += b.compress_block(badcharmask, bufferptr);
  133|  37.9k|      } else if (bufferptr != buffer) {
  ------------------
  |  Branch (133:18): [True: 7.47k, False: 856]
  ------------------
  134|  7.47k|        b.copy_block(bufferptr);
  135|  7.47k|        bufferptr += 64;
  136|  7.47k|      } else {
  137|    856|        b.template base64_decode_block<true>(dst);
  138|    856|        dst += 48;
  139|    856|      }
  140|  46.3k|      if (bufferptr >= (block_size - 1) * 64 + buffer) {
  ------------------
  |  Branch (140:11): [True: 8.60k, False: 37.7k]
  ------------------
  141|  43.0k|        for (size_t i = 0; i < (block_size - 2); i++) {
  ------------------
  |  Branch (141:28): [True: 34.4k, False: 8.60k]
  ------------------
  142|  34.4k|          base64_decode_block(dst, buffer + i * 64);
  143|  34.4k|          dst += 48;
  144|  34.4k|        }
  145|  8.60k|        base64_decode_block<true>(dst, buffer + (block_size - 2) * 64);
  146|  8.60k|        dst += 48;
  147|  8.60k|        std::memcpy(buffer, buffer + (block_size - 1) * 64,
  148|  8.60k|                    64); // 64 might be too much
  149|  8.60k|        bufferptr -= (block_size - 1) * 64;
  150|  8.60k|      }
  151|  46.3k|    }
  152|  1.71k|  }
  153|       |
  154|    902|  if (ignore_garbage && equalsigns == 0) {
  ------------------
  |  Branch (154:7): [Folded, False: 902]
  |  Branch (154:25): [True: 0, False: 0]
  ------------------
  155|      0|    const chartype *equal = src;
  156|      0|    while (equal < srcend && *equal != '=') {
  ------------------
  |  Branch (156:12): [True: 0, False: 0]
  |  Branch (156:30): [True: 0, False: 0]
  ------------------
  157|      0|      equal++;
  158|      0|    }
  159|      0|    if (equal < srcend) {
  ------------------
  |  Branch (159:9): [True: 0, False: 0]
  ------------------
  160|      0|      equallocation = size_t(equal - srcinit);
  161|      0|      equalsigns = 1;
  162|      0|      srclen = equallocation;
  163|      0|      full_input_length = equallocation + 1;
  164|      0|      if (srclen == 0) {
  ------------------
  |  Branch (164:11): [True: 0, False: 0]
  ------------------
  165|      0|        return {SUCCESS, full_input_length, 0};
  166|      0|      }
  167|      0|      srcend = equal;
  168|      0|    }
  169|      0|  }
  170|    902|  char *buffer_start = buffer;
  171|       |  // Optimization note: if this is almost full, then it is worth our
  172|       |  // time, otherwise, we should just decode directly.
  173|    902|  int last_block = (int)((bufferptr - buffer_start) % 64);
  174|    902|  if (last_block != 0 && srcend - src + last_block >= 64) {
  ------------------
  |  Branch (174:7): [True: 552, False: 350]
  |  Branch (174:26): [True: 96, False: 456]
  ------------------
  175|       |
  176|    584|    while ((bufferptr - buffer_start) % 64 != 0 && src < srcend) {
  ------------------
  |  Branch (176:12): [True: 550, False: 34]
  |  Branch (176:52): [True: 538, False: 12]
  ------------------
  177|    538|      uint8_t val = to_base64[uint8_t(*src)];
  178|    538|      *bufferptr = char(val);
  179|    538|      if (!ignore_garbage &&
  ------------------
  |  Branch (179:11): [True: 538, Folded]
  ------------------
  180|    538|          (!scalar::base64::is_eight_byte(*src) || val > 64)) {
  ------------------
  |  Branch (180:12): [True: 28, False: 510]
  |  Branch (180:52): [True: 22, False: 488]
  ------------------
  181|     50|        return {error_code::INVALID_BASE64_CHARACTER, size_t(src - srcinit),
  182|     50|                size_t(dst - dstinit)};
  183|     50|      }
  184|    488|      bufferptr += (val <= 63 && scalar::base64::is_eight_byte(*src));
  ------------------
  |  Branch (184:21): [True: 202, False: 286]
  |  Branch (184:34): [True: 202, False: 0]
  ------------------
  185|    488|      src++;
  186|    488|    }
  187|     96|  }
  188|       |
  189|  1.20k|  for (; buffer_start + 64 <= bufferptr; buffer_start += 64) {
  ------------------
  |  Branch (189:10): [True: 356, False: 852]
  ------------------
  190|       |    // 8 payload bytes still in the buffer become 6 output bytes, which cover
  191|       |    // the 4-byte tail of a wide store. Fewer than that, and the tail can
  192|       |    // stick out past the real end.
  193|    356|    const size_t after = size_t(bufferptr - (buffer_start + 64));
  194|    356|    if (after >= 8) {
  ------------------
  |  Branch (194:9): [True: 296, False: 60]
  ------------------
  195|    296|      base64_decode_block(dst, buffer_start);
  196|    296|    } else {
  197|     60|      base64_decode_block<true>(dst, buffer_start);
  198|     60|    }
  199|    356|    dst += 48;
  200|    356|  }
  201|    852|  if ((bufferptr - buffer_start) % 64 != 0) {
  ------------------
  |  Branch (201:7): [True: 468, False: 384]
  ------------------
  202|  3.91k|    while (buffer_start + 4 < bufferptr) {
  ------------------
  |  Branch (202:12): [True: 3.44k, False: 468]
  ------------------
  203|  3.44k|      uint32_t triple = ((uint32_t(uint8_t(buffer_start[0])) << 3 * 6) +
  204|  3.44k|                         (uint32_t(uint8_t(buffer_start[1])) << 2 * 6) +
  205|  3.44k|                         (uint32_t(uint8_t(buffer_start[2])) << 1 * 6) +
  206|  3.44k|                         (uint32_t(uint8_t(buffer_start[3])) << 0 * 6))
  207|  3.44k|                        << 8;
  208|  3.44k|#if !SIMDUTF_IS_BIG_ENDIAN
  209|  3.44k|      triple = scalar::u32_swap_bytes(triple);
  210|  3.44k|#endif
  211|  3.44k|      std::memcpy(dst, &triple, 3);
  212|       |
  213|  3.44k|      dst += 3;
  214|  3.44k|      buffer_start += 4;
  215|  3.44k|    }
  216|    468|    if (buffer_start + 4 <= bufferptr) {
  ------------------
  |  Branch (216:9): [True: 114, False: 354]
  ------------------
  217|    114|      uint32_t triple = ((uint32_t(uint8_t(buffer_start[0])) << 3 * 6) +
  218|    114|                         (uint32_t(uint8_t(buffer_start[1])) << 2 * 6) +
  219|    114|                         (uint32_t(uint8_t(buffer_start[2])) << 1 * 6) +
  220|    114|                         (uint32_t(uint8_t(buffer_start[3])) << 0 * 6))
  221|    114|                        << 8;
  222|    114|#if !SIMDUTF_IS_BIG_ENDIAN
  223|    114|      triple = scalar::u32_swap_bytes(triple);
  224|    114|#endif
  225|    114|      std::memcpy(dst, &triple, 3);
  226|       |
  227|    114|      dst += 3;
  228|    114|      buffer_start += 4;
  229|    114|    }
  230|       |    // we may have 1, 2 or 3 bytes left and we need to decode them so let us
  231|       |    // backtrack
  232|    468|    int leftover = int(bufferptr - buffer_start);
  233|  1.17k|    while (leftover > 0) {
  ------------------
  |  Branch (233:12): [True: 706, False: 468]
  ------------------
  234|    706|      if (!ignore_garbage) {
  ------------------
  |  Branch (234:11): [True: 706, Folded]
  ------------------
  235|  6.55k|        while (to_base64[uint8_t(*(src - 1))] == 64) {
  ------------------
  |  Branch (235:16): [True: 5.84k, False: 706]
  ------------------
  236|  5.84k|          src--;
  237|  5.84k|        }
  238|    706|      } else {
  239|      0|        while (!scalar::base64::is_eight_byte(*(src - 1)) ||
  ------------------
  |  Branch (239:16): [True: 0, False: 0]
  ------------------
  240|      0|               to_base64[uint8_t(*(src - 1))] >= 64) {
  ------------------
  |  Branch (240:16): [True: 0, False: 0]
  ------------------
  241|      0|          src--;
  242|      0|        }
  243|      0|      }
  244|    706|      src--;
  245|    706|      leftover--;
  246|    706|    }
  247|    468|  }
  248|    852|  if (src < srcend + equalsigns) {
  ------------------
  |  Branch (248:7): [True: 708, False: 144]
  ------------------
  249|    708|    full_result r = scalar::base64::base64_tail_decode(
  250|    708|        dst, src, srcend - src, equalsigns, options, last_chunk_options);
  251|    708|    r = scalar::base64::patch_tail_result(
  252|    708|        r, size_t(src - srcinit), size_t(dst - dstinit), equallocation,
  253|    708|        full_input_length, last_chunk_options);
  254|       |    // When is_partial(last_chunk_options) is true, we must either end with
  255|       |    // the end of the stream (beyond whitespace) or right after a non-ignorable
  256|       |    // character or at the very beginning of the stream.
  257|       |    // See https://tc39.es/proposal-arraybuffer-base64/spec/#sec-frombase64
  258|    708|    if (is_partial(last_chunk_options) && r.error == error_code::SUCCESS &&
  ------------------
  |  Branch (258:9): [True: 420, False: 288]
  |  Branch (258:43): [True: 330, False: 90]
  ------------------
  259|    330|        r.input_count < full_input_length) {
  ------------------
  |  Branch (259:9): [True: 296, False: 34]
  ------------------
  260|       |      // First check if we can extend the input to the end of the stream
  261|    806|      while (r.input_count < full_input_length &&
  ------------------
  |  Branch (261:14): [True: 802, False: 4]
  ------------------
  262|    802|             base64_ignorable(*(srcinit + r.input_count), options)) {
  ------------------
  |  Branch (262:14): [True: 510, False: 292]
  ------------------
  263|    510|        r.input_count++;
  264|    510|      }
  265|       |      // If we are still not at the end of the stream, then we must backtrack
  266|       |      // to the last non-ignorable character.
  267|    296|      if (r.input_count < full_input_length) {
  ------------------
  |  Branch (267:11): [True: 292, False: 4]
  ------------------
  268|  2.52k|        while (r.input_count > 0 &&
  ------------------
  |  Branch (268:16): [True: 2.44k, False: 78]
  ------------------
  269|  2.44k|               base64_ignorable(*(srcinit + r.input_count - 1), options)) {
  ------------------
  |  Branch (269:16): [True: 2.23k, False: 214]
  ------------------
  270|  2.23k|          r.input_count--;
  271|  2.23k|        }
  272|    292|      }
  273|    296|    }
  274|    708|    return r;
  275|    708|  }
  276|    144|  if (!ignore_garbage && equalsigns > 0) {
  ------------------
  |  Branch (276:7): [True: 144, Folded]
  |  Branch (276:26): [True: 0, False: 144]
  ------------------
  277|      0|    if ((size_t(dst - dstinit) % 3 == 0) ||
  ------------------
  |  Branch (277:9): [True: 0, False: 0]
  ------------------
  278|      0|        ((size_t(dst - dstinit) % 3) + 1 + equalsigns != 4)) {
  ------------------
  |  Branch (278:9): [True: 0, False: 0]
  ------------------
  279|      0|      return {INVALID_BASE64_CHARACTER, equallocation, size_t(dst - dstinit),
  280|      0|              true};
  281|      0|    }
  282|      0|  }
  283|    144|  return {SUCCESS, srclen, size_t(dst - dstinit)};
  284|    144|}
simdutf.cpp:_ZN7simdutf8westmere12_GLOBAL__N_16base6422compress_decode_base64ILb0ELb0ELb0EDsEENS_11full_resultEPcPKT2_mNS_14base64_optionsENS_27last_chunk_handling_optionsE:
   45|  1.97k|                       last_chunk_handling_options last_chunk_options) {
   46|  1.97k|  const uint8_t *to_base64 =
   47|  1.97k|      default_or_url ? tables::base64::to_base64_default_or_url_value
  ------------------
  |  Branch (47:7): [Folded, False: 1.97k]
  ------------------
   48|  1.97k|                     : (base64_url ? tables::base64::to_base64_url_value
  ------------------
  |  Branch (48:25): [Folded, False: 1.97k]
  ------------------
   49|  1.97k|                                   : tables::base64::to_base64_value);
   50|  1.97k|  auto ri =
   51|  1.97k|      ignore_garbage
  ------------------
  |  Branch (51:7): [Folded, False: 1.97k]
  ------------------
   52|  1.97k|          ? simdutf::scalar::base64::reduced_input{0, srclen, srclen, srclen}
   53|  1.97k|          : simdutf::scalar::base64::find_end(src, srclen, options);
   54|  1.97k|  size_t equallocation = ri.equallocation;
   55|  1.97k|  size_t equalsigns = ri.equalsigns;
   56|  1.97k|  srclen = ri.srclen;
   57|  1.97k|  size_t full_input_length = ri.full_input_length;
   58|  1.97k|  if (srclen == 0) {
  ------------------
  |  Branch (58:7): [True: 26, False: 1.94k]
  ------------------
   59|     26|    if (!ignore_garbage && equalsigns > 0) {
  ------------------
  |  Branch (59:9): [True: 26, Folded]
  |  Branch (59:28): [True: 12, False: 14]
  ------------------
   60|     12|      return {INVALID_BASE64_CHARACTER, equallocation, 0, true};
   61|     12|    }
   62|     14|    return {SUCCESS, full_input_length, 0};
   63|     26|  }
   64|  1.94k|  const chartype *const srcinit = src;
   65|  1.94k|  const char *const dstinit = dst;
   66|  1.94k|  const chartype *srcend = src + srclen;
   67|       |
   68|  1.94k|  constexpr size_t block_size = 6;
   69|  1.94k|  static_assert(block_size >= 2, "block_size must be at least two");
   70|  1.94k|  char buffer[block_size * 64];
   71|  1.94k|  char *bufferptr = buffer;
   72|       |  // A wide block store writes 4 bytes past its 48. That is safe when the next
   73|       |  // store starts 48 bytes later. Pairs of clean blocks wide-store the first
   74|       |  // and end the second on byte 48. Anything shorter, or a block that is not
   75|       |  // clean, uses the exact store. The pair attempt is only worth it on a long
   76|       |  // input: a short one often fails the first block and then repeats that work.
   77|  1.94k|  if (srclen >= 512) {
  ------------------
  |  Branch (77:7): [True: 970, False: 974]
  ------------------
   78|    970|    const chartype *const srcend128 = src + srclen - 128;
   79|  1.36k|    while (bufferptr == buffer && src <= srcend128) {
  ------------------
  |  Branch (79:12): [True: 1.36k, False: 0]
  |  Branch (79:35): [True: 1.35k, False: 6]
  ------------------
   80|  1.35k|      block64 b0(src);
   81|  1.35k|      uint64_t e0 = 0;
   82|  1.35k|      const uint64_t m0 =
   83|  1.35k|          b0.to_base64_mask<base64_url, ignore_garbage, default_or_url>(&e0);
   84|  1.35k|      if ((!ignore_garbage && e0) || m0 != 0) {
  ------------------
  |  Branch (84:12): [True: 1.35k, Folded]
  |  Branch (84:31): [True: 232, False: 1.12k]
  |  Branch (84:38): [True: 308, False: 816]
  ------------------
   85|    540|        break;
   86|    540|      }
   87|    816|      block64 b1(src + 64);
   88|    816|      uint64_t e1 = 0;
   89|    816|      const uint64_t m1 =
   90|    816|          b1.to_base64_mask<base64_url, ignore_garbage, default_or_url>(&e1);
   91|    816|      if ((!ignore_garbage && e1) || m1 != 0) {
  ------------------
  |  Branch (91:12): [True: 816, Folded]
  |  Branch (91:31): [True: 216, False: 600]
  |  Branch (91:38): [True: 208, False: 392]
  ------------------
   92|    424|        break;
   93|    424|      }
   94|    392|      b0.base64_decode_block(dst);
   95|    392|      b1.template base64_decode_block<true>(dst + 48);
   96|    392|      src += 128;
   97|    392|      dst += 96;
   98|    392|    }
   99|    970|  }
  100|  1.94k|  if (srclen >= 64) {
  ------------------
  |  Branch (100:7): [True: 1.64k, False: 296]
  ------------------
  101|  1.64k|    const chartype *const srcend64 = srcinit + srclen - 64;
  102|  67.1k|    while (src <= srcend64) {
  ------------------
  |  Branch (102:12): [True: 66.6k, False: 576]
  ------------------
  103|  66.6k|      block64 b(src);
  104|  66.6k|      uint64_t error = 0;
  105|  66.6k|      const uint64_t badcharmask =
  106|  66.6k|          b.to_base64_mask<base64_url, ignore_garbage, default_or_url>(&error);
  107|  66.6k|      if (!ignore_garbage && error) {
  ------------------
  |  Branch (107:11): [True: 66.6k, Folded]
  |  Branch (107:30): [True: 1.07k, False: 65.5k]
  ------------------
  108|  1.07k|        const size_t error_offset = trailing_zeroes(error);
  109|  1.07k|        return {error_code::INVALID_BASE64_CHARACTER,
  110|  1.07k|                size_t(src - srcinit + error_offset), size_t(dst - dstinit)};
  111|  1.07k|      }
  112|  65.5k|      if (ignore_garbage && badcharmask != 0) {
  ------------------
  |  Branch (112:11): [Folded, False: 65.5k]
  |  Branch (112:29): [True: 0, False: 0]
  ------------------
  113|      0|        const uint64_t equals = block64(src).equal_sign_mask();
  114|      0|        if (equals != 0) {
  ------------------
  |  Branch (114:13): [True: 0, False: 0]
  ------------------
  115|      0|          const size_t offset = trailing_zeroes(equals);
  116|      0|          equallocation = size_t(src - srcinit) + offset;
  117|      0|          equalsigns = 1;
  118|      0|          srclen = equallocation;
  119|      0|          full_input_length = equallocation + 1;
  120|      0|          if (srclen == 0) {
  ------------------
  |  Branch (120:15): [True: 0, False: 0]
  ------------------
  121|      0|            return {SUCCESS, full_input_length, 0};
  122|      0|          }
  123|      0|          srcend = srcinit + srclen;
  124|      0|          src = srcend;
  125|      0|          bufferptr += b.compress_block(badcharmask | (~uint64_t(0) << offset),
  126|      0|                                        bufferptr);
  127|      0|          break;
  128|      0|        }
  129|      0|      }
  130|  65.5k|      src += 64;
  131|  65.5k|      if (badcharmask != 0) {
  ------------------
  |  Branch (131:11): [True: 52.0k, False: 13.4k]
  ------------------
  132|  52.0k|        bufferptr += b.compress_block(badcharmask, bufferptr);
  133|  52.0k|      } else if (bufferptr != buffer) {
  ------------------
  |  Branch (133:18): [True: 12.8k, False: 648]
  ------------------
  134|  12.8k|        b.copy_block(bufferptr);
  135|  12.8k|        bufferptr += 64;
  136|  12.8k|      } else {
  137|    648|        b.template base64_decode_block<true>(dst);
  138|    648|        dst += 48;
  139|    648|      }
  140|  65.5k|      if (bufferptr >= (block_size - 1) * 64 + buffer) {
  ------------------
  |  Branch (140:11): [True: 12.4k, False: 53.0k]
  ------------------
  141|  62.3k|        for (size_t i = 0; i < (block_size - 2); i++) {
  ------------------
  |  Branch (141:28): [True: 49.8k, False: 12.4k]
  ------------------
  142|  49.8k|          base64_decode_block(dst, buffer + i * 64);
  143|  49.8k|          dst += 48;
  144|  49.8k|        }
  145|  12.4k|        base64_decode_block<true>(dst, buffer + (block_size - 2) * 64);
  146|  12.4k|        dst += 48;
  147|  12.4k|        std::memcpy(buffer, buffer + (block_size - 1) * 64,
  148|  12.4k|                    64); // 64 might be too much
  149|  12.4k|        bufferptr -= (block_size - 1) * 64;
  150|  12.4k|      }
  151|  65.5k|    }
  152|  1.64k|  }
  153|       |
  154|    872|  if (ignore_garbage && equalsigns == 0) {
  ------------------
  |  Branch (154:7): [Folded, False: 872]
  |  Branch (154:25): [True: 0, False: 0]
  ------------------
  155|      0|    const chartype *equal = src;
  156|      0|    while (equal < srcend && *equal != '=') {
  ------------------
  |  Branch (156:12): [True: 0, False: 0]
  |  Branch (156:30): [True: 0, False: 0]
  ------------------
  157|      0|      equal++;
  158|      0|    }
  159|      0|    if (equal < srcend) {
  ------------------
  |  Branch (159:9): [True: 0, False: 0]
  ------------------
  160|      0|      equallocation = size_t(equal - srcinit);
  161|      0|      equalsigns = 1;
  162|      0|      srclen = equallocation;
  163|      0|      full_input_length = equallocation + 1;
  164|      0|      if (srclen == 0) {
  ------------------
  |  Branch (164:11): [True: 0, False: 0]
  ------------------
  165|      0|        return {SUCCESS, full_input_length, 0};
  166|      0|      }
  167|      0|      srcend = equal;
  168|      0|    }
  169|      0|  }
  170|    872|  char *buffer_start = buffer;
  171|       |  // Optimization note: if this is almost full, then it is worth our
  172|       |  // time, otherwise, we should just decode directly.
  173|    872|  int last_block = (int)((bufferptr - buffer_start) % 64);
  174|    872|  if (last_block != 0 && srcend - src + last_block >= 64) {
  ------------------
  |  Branch (174:7): [True: 550, False: 322]
  |  Branch (174:26): [True: 106, False: 444]
  ------------------
  175|       |
  176|    828|    while ((bufferptr - buffer_start) % 64 != 0 && src < srcend) {
  ------------------
  |  Branch (176:12): [True: 784, False: 44]
  |  Branch (176:52): [True: 772, False: 12]
  ------------------
  177|    772|      uint8_t val = to_base64[uint8_t(*src)];
  178|    772|      *bufferptr = char(val);
  179|    772|      if (!ignore_garbage &&
  ------------------
  |  Branch (179:11): [True: 772, Folded]
  ------------------
  180|    772|          (!scalar::base64::is_eight_byte(*src) || val > 64)) {
  ------------------
  |  Branch (180:12): [True: 32, False: 740]
  |  Branch (180:52): [True: 18, False: 722]
  ------------------
  181|     50|        return {error_code::INVALID_BASE64_CHARACTER, size_t(src - srcinit),
  182|     50|                size_t(dst - dstinit)};
  183|     50|      }
  184|    722|      bufferptr += (val <= 63 && scalar::base64::is_eight_byte(*src));
  ------------------
  |  Branch (184:21): [True: 400, False: 322]
  |  Branch (184:34): [True: 400, False: 0]
  ------------------
  185|    722|      src++;
  186|    722|    }
  187|    106|  }
  188|       |
  189|  1.19k|  for (; buffer_start + 64 <= bufferptr; buffer_start += 64) {
  ------------------
  |  Branch (189:10): [True: 372, False: 822]
  ------------------
  190|       |    // 8 payload bytes still in the buffer become 6 output bytes, which cover
  191|       |    // the 4-byte tail of a wide store. Fewer than that, and the tail can
  192|       |    // stick out past the real end.
  193|    372|    const size_t after = size_t(bufferptr - (buffer_start + 64));
  194|    372|    if (after >= 8) {
  ------------------
  |  Branch (194:9): [True: 310, False: 62]
  ------------------
  195|    310|      base64_decode_block(dst, buffer_start);
  196|    310|    } else {
  197|     62|      base64_decode_block<true>(dst, buffer_start);
  198|     62|    }
  199|    372|    dst += 48;
  200|    372|  }
  201|    822|  if ((bufferptr - buffer_start) % 64 != 0) {
  ------------------
  |  Branch (201:7): [True: 456, False: 366]
  ------------------
  202|  3.79k|    while (buffer_start + 4 < bufferptr) {
  ------------------
  |  Branch (202:12): [True: 3.33k, False: 456]
  ------------------
  203|  3.33k|      uint32_t triple = ((uint32_t(uint8_t(buffer_start[0])) << 3 * 6) +
  204|  3.33k|                         (uint32_t(uint8_t(buffer_start[1])) << 2 * 6) +
  205|  3.33k|                         (uint32_t(uint8_t(buffer_start[2])) << 1 * 6) +
  206|  3.33k|                         (uint32_t(uint8_t(buffer_start[3])) << 0 * 6))
  207|  3.33k|                        << 8;
  208|  3.33k|#if !SIMDUTF_IS_BIG_ENDIAN
  209|  3.33k|      triple = scalar::u32_swap_bytes(triple);
  210|  3.33k|#endif
  211|  3.33k|      std::memcpy(dst, &triple, 3);
  212|       |
  213|  3.33k|      dst += 3;
  214|  3.33k|      buffer_start += 4;
  215|  3.33k|    }
  216|    456|    if (buffer_start + 4 <= bufferptr) {
  ------------------
  |  Branch (216:9): [True: 112, False: 344]
  ------------------
  217|    112|      uint32_t triple = ((uint32_t(uint8_t(buffer_start[0])) << 3 * 6) +
  218|    112|                         (uint32_t(uint8_t(buffer_start[1])) << 2 * 6) +
  219|    112|                         (uint32_t(uint8_t(buffer_start[2])) << 1 * 6) +
  220|    112|                         (uint32_t(uint8_t(buffer_start[3])) << 0 * 6))
  221|    112|                        << 8;
  222|    112|#if !SIMDUTF_IS_BIG_ENDIAN
  223|    112|      triple = scalar::u32_swap_bytes(triple);
  224|    112|#endif
  225|    112|      std::memcpy(dst, &triple, 3);
  226|       |
  227|    112|      dst += 3;
  228|    112|      buffer_start += 4;
  229|    112|    }
  230|       |    // we may have 1, 2 or 3 bytes left and we need to decode them so let us
  231|       |    // backtrack
  232|    456|    int leftover = int(bufferptr - buffer_start);
  233|  1.13k|    while (leftover > 0) {
  ------------------
  |  Branch (233:12): [True: 680, False: 456]
  ------------------
  234|    680|      if (!ignore_garbage) {
  ------------------
  |  Branch (234:11): [True: 680, Folded]
  ------------------
  235|  5.57k|        while (to_base64[uint8_t(*(src - 1))] == 64) {
  ------------------
  |  Branch (235:16): [True: 4.89k, False: 680]
  ------------------
  236|  4.89k|          src--;
  237|  4.89k|        }
  238|    680|      } else {
  239|      0|        while (!scalar::base64::is_eight_byte(*(src - 1)) ||
  ------------------
  |  Branch (239:16): [True: 0, False: 0]
  ------------------
  240|      0|               to_base64[uint8_t(*(src - 1))] >= 64) {
  ------------------
  |  Branch (240:16): [True: 0, False: 0]
  ------------------
  241|      0|          src--;
  242|      0|        }
  243|      0|      }
  244|    680|      src--;
  245|    680|      leftover--;
  246|    680|    }
  247|    456|  }
  248|    822|  if (src < srcend + equalsigns) {
  ------------------
  |  Branch (248:7): [True: 688, False: 134]
  ------------------
  249|    688|    full_result r = scalar::base64::base64_tail_decode(
  250|    688|        dst, src, srcend - src, equalsigns, options, last_chunk_options);
  251|    688|    r = scalar::base64::patch_tail_result(
  252|    688|        r, size_t(src - srcinit), size_t(dst - dstinit), equallocation,
  253|    688|        full_input_length, last_chunk_options);
  254|       |    // When is_partial(last_chunk_options) is true, we must either end with
  255|       |    // the end of the stream (beyond whitespace) or right after a non-ignorable
  256|       |    // character or at the very beginning of the stream.
  257|       |    // See https://tc39.es/proposal-arraybuffer-base64/spec/#sec-frombase64
  258|    688|    if (is_partial(last_chunk_options) && r.error == error_code::SUCCESS &&
  ------------------
  |  Branch (258:9): [True: 372, False: 316]
  |  Branch (258:43): [True: 314, False: 58]
  ------------------
  259|    314|        r.input_count < full_input_length) {
  ------------------
  |  Branch (259:9): [True: 278, False: 36]
  ------------------
  260|       |      // First check if we can extend the input to the end of the stream
  261|    608|      while (r.input_count < full_input_length &&
  ------------------
  |  Branch (261:14): [True: 600, False: 8]
  ------------------
  262|    600|             base64_ignorable(*(srcinit + r.input_count), options)) {
  ------------------
  |  Branch (262:14): [True: 330, False: 270]
  ------------------
  263|    330|        r.input_count++;
  264|    330|      }
  265|       |      // If we are still not at the end of the stream, then we must backtrack
  266|       |      // to the last non-ignorable character.
  267|    278|      if (r.input_count < full_input_length) {
  ------------------
  |  Branch (267:11): [True: 270, False: 8]
  ------------------
  268|  3.61k|        while (r.input_count > 0 &&
  ------------------
  |  Branch (268:16): [True: 3.54k, False: 64]
  ------------------
  269|  3.54k|               base64_ignorable(*(srcinit + r.input_count - 1), options)) {
  ------------------
  |  Branch (269:16): [True: 3.34k, False: 206]
  ------------------
  270|  3.34k|          r.input_count--;
  271|  3.34k|        }
  272|    270|      }
  273|    278|    }
  274|    688|    return r;
  275|    688|  }
  276|    134|  if (!ignore_garbage && equalsigns > 0) {
  ------------------
  |  Branch (276:7): [True: 134, Folded]
  |  Branch (276:26): [True: 0, False: 134]
  ------------------
  277|      0|    if ((size_t(dst - dstinit) % 3 == 0) ||
  ------------------
  |  Branch (277:9): [True: 0, False: 0]
  ------------------
  278|      0|        ((size_t(dst - dstinit) % 3) + 1 + equalsigns != 4)) {
  ------------------
  |  Branch (278:9): [True: 0, False: 0]
  ------------------
  279|      0|      return {INVALID_BASE64_CHARACTER, equallocation, size_t(dst - dstinit),
  280|      0|              true};
  281|      0|    }
  282|      0|  }
  283|    134|  return {SUCCESS, srclen, size_t(dst - dstinit)};
  284|    134|}

simdutf.cpp:_ZN7simdutf7haswell12_GLOBAL__N_17block64C2EPKc:
  488|   338k|  simdutf_really_inline block64(const char *src) {
  489|   338k|    chunks[0] = _mm256_loadu_si256(reinterpret_cast<const __m256i *>(src));
  490|   338k|    chunks[1] = _mm256_loadu_si256(reinterpret_cast<const __m256i *>(src + 32));
  491|   338k|  }
simdutf.cpp:_ZN7simdutf7haswell12_GLOBAL__N_17block6419base64_decode_blockILb0EEEvPc:
  529|  60.1k|  simdutf_really_inline void base64_decode_block(char *out) {
  530|  60.1k|    base64_decode(out, chunks[0]);
  531|  60.1k|    base64_decode<exact_tail>(out + 24, chunks[1]);
  532|  60.1k|  }
simdutf.cpp:_ZN7simdutf7haswell12_GLOBAL__N_113base64_decodeILb0EEEvPcDv4_x:
  450|   746k|simdutf_really_inline void base64_decode(char *out, __m256i str) {
  451|       |  // credit: aqrit
  452|   746k|  const __m256i pack_shuffle =
  453|   746k|      _mm256_setr_epi8(2, 1, 0, 6, 5, 4, 10, 9, 8, 14, 13, 12, -1, -1, -1, -1,
  454|   746k|                       2, 1, 0, 6, 5, 4, 10, 9, 8, 14, 13, 12, -1, -1, -1, -1);
  455|   746k|  const __m256i t0 = _mm256_maddubs_epi16(str, _mm256_set1_epi32(0x01400140));
  456|   746k|  const __m256i t1 = _mm256_madd_epi16(t0, _mm256_set1_epi32(0x00011000));
  457|   746k|  const __m256i t2 = _mm256_shuffle_epi8(t1, pack_shuffle);
  458|       |
  459|       |  // Store the output:
  460|   746k|  _mm_storeu_si128((__m128i *)out, _mm256_castsi256_si128(t2));
  461|   746k|  const __m128i hi = _mm256_extracti128_si256(t2, 1);
  462|       |  if constexpr (exact_tail) {
  463|       |    _mm_storel_epi64((__m128i *)(out + 12), hi);
  464|       |    const int32_t last = _mm_extract_epi32(hi, 2);
  465|       |    std::memcpy(out + 20, &last, sizeof(last));
  466|   746k|  } else {
  467|   746k|    _mm_storeu_si128((__m128i *)(out + 12), hi);
  468|   746k|  }
  469|   746k|}
simdutf.cpp:_ZN7simdutf7haswell12_GLOBAL__N_17block6419base64_decode_blockILb1EEEvPc:
  529|  63.4k|  simdutf_really_inline void base64_decode_block(char *out) {
  530|  63.4k|    base64_decode(out, chunks[0]);
  531|  63.4k|    base64_decode<exact_tail>(out + 24, chunks[1]);
  532|  63.4k|  }
simdutf.cpp:_ZN7simdutf7haswell12_GLOBAL__N_113base64_decodeILb1EEEvPcDv4_x:
  450|   125k|simdutf_really_inline void base64_decode(char *out, __m256i str) {
  451|       |  // credit: aqrit
  452|   125k|  const __m256i pack_shuffle =
  453|   125k|      _mm256_setr_epi8(2, 1, 0, 6, 5, 4, 10, 9, 8, 14, 13, 12, -1, -1, -1, -1,
  454|   125k|                       2, 1, 0, 6, 5, 4, 10, 9, 8, 14, 13, 12, -1, -1, -1, -1);
  455|   125k|  const __m256i t0 = _mm256_maddubs_epi16(str, _mm256_set1_epi32(0x01400140));
  456|   125k|  const __m256i t1 = _mm256_madd_epi16(t0, _mm256_set1_epi32(0x00011000));
  457|   125k|  const __m256i t2 = _mm256_shuffle_epi8(t1, pack_shuffle);
  458|       |
  459|       |  // Store the output:
  460|   125k|  _mm_storeu_si128((__m128i *)out, _mm256_castsi256_si128(t2));
  461|   125k|  const __m128i hi = _mm256_extracti128_si256(t2, 1);
  462|   125k|  if constexpr (exact_tail) {
  463|   125k|    _mm_storel_epi64((__m128i *)(out + 12), hi);
  464|   125k|    const int32_t last = _mm_extract_epi32(hi, 2);
  465|   125k|    std::memcpy(out + 20, &last, sizeof(last));
  466|       |  } else {
  467|       |    _mm_storeu_si128((__m128i *)(out + 12), hi);
  468|       |  }
  469|   125k|}
simdutf.cpp:_ZN7simdutf7haswell12_GLOBAL__N_17block6414compress_blockEmPc:
  671|   164k|  simdutf_really_inline uint64_t compress_block(uint64_t mask, char *output) {
  672|   164k|    if (is_power_of_two(mask)) {
  ------------------
  |  Branch (672:9): [True: 127k, False: 37.6k]
  ------------------
  673|   127k|      return compress_block_single(mask, output);
  674|   127k|    }
  675|       |
  676|  37.6k|    uint64_t nmask = ~mask;
  677|  37.6k|    compress(chunks[0], uint32_t(mask), output);
  678|  37.6k|    compress(chunks[1], uint32_t(mask >> 32),
  679|  37.6k|             output + count_ones(nmask & 0xFFFFFFFF));
  680|  37.6k|    return count_ones(nmask);
  681|   164k|  }
simdutf.cpp:_ZN7simdutf7haswell12_GLOBAL__N_17block6421compress_block_singleEmPc:
  684|   127k|                                                     char *output) {
  685|   127k|    const size_t pos64 = trailing_zeroes(mask);
  686|   127k|    const int8_t pos = pos64 & 0xf;
  687|   127k|    switch (pos64 >> 4) {
  ------------------
  |  Branch (687:13): [True: 127k, False: 0]
  ------------------
  688|  30.9k|    case 0b00: {
  ------------------
  |  Branch (688:5): [True: 30.9k, False: 96.3k]
  ------------------
  689|  30.9k|      const __m128i lane0 = _mm256_extracti128_si256(chunks[0], 0);
  690|  30.9k|      const __m128i lane1 = _mm256_extracti128_si256(chunks[0], 1);
  691|       |
  692|  30.9k|      const __m128i v0 = _mm_set1_epi8(char(pos - 1));
  693|  30.9k|      const __m128i v1 =
  694|  30.9k|          _mm_setr_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
  695|  30.9k|      const __m128i v2 = _mm_cmpgt_epi8(v1, v0);
  696|  30.9k|      const __m128i sh = _mm_sub_epi8(v1, v2);
  697|  30.9k|      const __m128i compressed = _mm_shuffle_epi8(lane0, sh);
  698|       |
  699|  30.9k|      _mm_storeu_si128((__m128i *)(output + 0 * 16), compressed);
  700|  30.9k|      _mm_storeu_si128((__m128i *)(output + 1 * 16 - 1), lane1);
  701|  30.9k|      _mm256_storeu_si256((__m256i *)(output + 2 * 16 - 1), chunks[1]);
  702|  30.9k|    } break;
  703|  33.0k|    case 0b01: {
  ------------------
  |  Branch (703:5): [True: 33.0k, False: 94.2k]
  ------------------
  704|  33.0k|      const __m128i lane0 = _mm256_extracti128_si256(chunks[0], 0);
  705|  33.0k|      const __m128i lane1 = _mm256_extracti128_si256(chunks[0], 1);
  706|  33.0k|      _mm_storeu_si128((__m128i *)(output + 0 * 16), lane0);
  707|       |
  708|  33.0k|      const __m128i v0 = _mm_set1_epi8(char(pos - 1));
  709|  33.0k|      const __m128i v1 =
  710|  33.0k|          _mm_setr_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
  711|  33.0k|      const __m128i v2 = _mm_cmpgt_epi8(v1, v0);
  712|  33.0k|      const __m128i sh = _mm_sub_epi8(v1, v2);
  713|  33.0k|      const __m128i compressed = _mm_shuffle_epi8(lane1, sh);
  714|       |
  715|  33.0k|      _mm_storeu_si128((__m128i *)(output + 1 * 16), compressed);
  716|  33.0k|      _mm256_storeu_si256((__m256i *)(output + 2 * 16 - 1), chunks[1]);
  717|  33.0k|    } break;
  718|  32.7k|    case 0b10: {
  ------------------
  |  Branch (718:5): [True: 32.7k, False: 94.5k]
  ------------------
  719|  32.7k|      const __m128i lane2 = _mm256_extracti128_si256(chunks[1], 0);
  720|  32.7k|      const __m128i lane3 = _mm256_extracti128_si256(chunks[1], 1);
  721|       |
  722|  32.7k|      _mm256_storeu_si256((__m256i *)(output + 0 * 16), chunks[0]);
  723|       |
  724|  32.7k|      const __m128i v0 = _mm_set1_epi8(char(pos - 1));
  725|  32.7k|      const __m128i v1 =
  726|  32.7k|          _mm_setr_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
  727|  32.7k|      const __m128i v2 = _mm_cmpgt_epi8(v1, v0);
  728|  32.7k|      const __m128i sh = _mm_sub_epi8(v1, v2);
  729|  32.7k|      const __m128i compressed = _mm_shuffle_epi8(lane2, sh);
  730|       |
  731|  32.7k|      _mm_storeu_si128((__m128i *)(output + 2 * 16), compressed);
  732|  32.7k|      _mm_storeu_si128((__m128i *)(output + 3 * 16 - 1), lane3);
  733|  32.7k|    } break;
  734|  30.5k|    case 0b11: {
  ------------------
  |  Branch (734:5): [True: 30.5k, False: 96.7k]
  ------------------
  735|  30.5k|      const __m128i lane2 = _mm256_extracti128_si256(chunks[1], 0);
  736|  30.5k|      const __m128i lane3 = _mm256_extracti128_si256(chunks[1], 1);
  737|       |
  738|  30.5k|      _mm256_storeu_si256((__m256i *)(output + 0 * 16), chunks[0]);
  739|  30.5k|      _mm_storeu_si128((__m128i *)(output + 2 * 16), lane2);
  740|       |
  741|  30.5k|      const __m128i v0 = _mm_set1_epi8(char(pos - 1));
  742|  30.5k|      const __m128i v1 =
  743|  30.5k|          _mm_setr_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
  744|  30.5k|      const __m128i v2 = _mm_cmpgt_epi8(v1, v0);
  745|  30.5k|      const __m128i sh = _mm_sub_epi8(v1, v2);
  746|  30.5k|      const __m128i compressed = _mm_shuffle_epi8(lane3, sh);
  747|       |
  748|  30.5k|      _mm_storeu_si128((__m128i *)(output + 3 * 16), compressed);
  749|  30.5k|    } break;
  750|   127k|    }
  751|       |
  752|   127k|    return 63;
  753|   127k|  }
simdutf.cpp:_ZN7simdutf7haswell12_GLOBAL__N_18compressIvEEvDv4_xjPc:
  435|  75.2k|simdutf_really_inline void compress(__m256i data, uint32_t mask, char *output) {
  436|  75.2k|  if (mask == 0) {
  ------------------
  |  Branch (436:7): [True: 15.3k, False: 59.8k]
  ------------------
  437|  15.3k|    _mm256_storeu_si256(reinterpret_cast<__m256i *>(output), data);
  438|  15.3k|    return;
  439|  15.3k|  }
  440|  59.8k|  compress(_mm256_castsi256_si128(data), uint16_t(mask), output);
  441|       |  compress(_mm256_extracti128_si256(data, 1), uint16_t(mask >> 16),
  442|  59.8k|           output + count_ones(~mask & 0xFFFF));
  443|  59.8k|}
simdutf.cpp:_ZN7simdutf7haswell12_GLOBAL__N_18compressEDv2_xtPc:
  398|   119k|static inline void compress(__m128i data, uint16_t mask, char *output) {
  399|   119k|  if (mask == 0) {
  ------------------
  |  Branch (399:7): [True: 40.3k, False: 79.4k]
  ------------------
  400|  40.3k|    _mm_storeu_si128(reinterpret_cast<__m128i *>(output), data);
  401|  40.3k|    return;
  402|  40.3k|  }
  403|       |  // this particular implementation was inspired by work done by @animetosho
  404|       |  // we do it in two steps, first 8 bytes and then second 8 bytes
  405|  79.4k|  uint8_t mask1 = uint8_t(mask);      // least significant 8 bits
  406|  79.4k|  uint8_t mask2 = uint8_t(mask >> 8); // most significant 8 bits
  407|       |  // next line just loads the 64-bit values thintable_epi8[mask1] and
  408|       |  // thintable_epi8[mask2] into a 128-bit register, using only
  409|       |  // two instructions on most compilers.
  410|       |
  411|  79.4k|  __m128i shufmask = _mm_set_epi64x(tables::base64::thintable_epi8[mask2],
  412|  79.4k|                                    tables::base64::thintable_epi8[mask1]);
  413|       |  // we increment by 0x08 the second half of the mask
  414|  79.4k|  shufmask =
  415|  79.4k|      _mm_add_epi8(shufmask, _mm_set_epi32(0x08080808, 0x08080808, 0, 0));
  416|       |  // this is the version "nearly pruned"
  417|  79.4k|  __m128i pruned = _mm_shuffle_epi8(data, shufmask);
  418|       |  // we still need to put the two halves together.
  419|       |  // we compute the popcount of the first half:
  420|  79.4k|  int pop1 = tables::base64::BitsSetTable256mul2[mask1];
  421|       |  // then load the corresponding mask, what it does is to write
  422|       |  // only the first pop1 bytes from the first 8 bytes, and then
  423|       |  // it fills in with the bytes from the second 8 bytes + some filling
  424|       |  // at the end.
  425|  79.4k|  __m128i compactmask = _mm_loadu_si128(reinterpret_cast<const __m128i *>(
  426|  79.4k|      tables::base64::pshufb_combine_table + pop1 * 8));
  427|  79.4k|  __m128i answer = _mm_shuffle_epi8(pruned, compactmask);
  428|       |
  429|  79.4k|  _mm_storeu_si128(reinterpret_cast<__m128i *>(output), answer);
  430|  79.4k|}
simdutf.cpp:_ZN7simdutf7haswell12_GLOBAL__N_17block6410copy_blockEPc:
  522|   157k|  simdutf_really_inline void copy_block(char *output) {
  523|   157k|    _mm256_storeu_si256(reinterpret_cast<__m256i *>(output), chunks[0]);
  524|   157k|    _mm256_storeu_si256(reinterpret_cast<__m256i *>(output + 32), chunks[1]);
  525|   157k|  }
simdutf.cpp:_ZN7simdutf7haswell12_GLOBAL__N_119base64_decode_blockILb0EEEvPcPKc:
  472|   250k|simdutf_really_inline void base64_decode_block(char *out, const char *src) {
  473|   250k|  base64_decode(out,
  474|   250k|                _mm256_loadu_si256(reinterpret_cast<const __m256i *>(src)));
  475|   250k|  base64_decode<exact_tail>(
  476|   250k|      out + 24,
  477|   250k|      _mm256_loadu_si256(reinterpret_cast<const __m256i *>(src + 32)));
  478|   250k|}
simdutf.cpp:_ZN7simdutf7haswell12_GLOBAL__N_119base64_decode_blockILb1EEEvPcPKc:
  472|  62.4k|simdutf_really_inline void base64_decode_block(char *out, const char *src) {
  473|  62.4k|  base64_decode(out,
  474|  62.4k|                _mm256_loadu_si256(reinterpret_cast<const __m256i *>(src)));
  475|  62.4k|  base64_decode<exact_tail>(
  476|  62.4k|      out + 24,
  477|  62.4k|      _mm256_loadu_si256(reinterpret_cast<const __m256i *>(src + 32)));
  478|  62.4k|}
simdutf.cpp:_ZN7simdutf7haswell12_GLOBAL__N_17block6414to_base64_maskILb1ELb0ELb0EEEmPm:
  535|   152k|  simdutf_really_inline uint64_t to_base64_mask(uint64_t *error) {
  536|   152k|    uint32_t err0 = 0;
  537|   152k|    uint32_t err1 = 0;
  538|   152k|    uint64_t m0 = to_base64_mask<base64_url, ignore_garbage, default_or_url>(
  539|   152k|        &chunks[0], &err0);
  540|   152k|    uint64_t m1 = to_base64_mask<base64_url, ignore_garbage, default_or_url>(
  541|   152k|        &chunks[1], &err1);
  542|   152k|    if (!ignore_garbage) {
  ------------------
  |  Branch (542:9): [True: 152k, Folded]
  ------------------
  543|   152k|      *error = err0 | ((uint64_t)err1 << 32);
  544|   152k|    }
  545|   152k|    return m0 | (m1 << 32);
  546|   152k|  }
simdutf.cpp:_ZN7simdutf7haswell12_GLOBAL__N_17block6414to_base64_maskILb1ELb0ELb0EEEjPDv4_xPj:
  549|   305k|  simdutf_really_inline uint32_t to_base64_mask(__m256i *src, uint32_t *error) {
  550|   305k|    const __m256i ascii_space_tbl =
  551|   305k|        _mm256_setr_epi8(0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9, 0xa,
  552|   305k|                         0x0, 0xc, 0xd, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0,
  553|   305k|                         0x0, 0x0, 0x0, 0x9, 0xa, 0x0, 0xc, 0xd, 0x0, 0x0);
  554|       |    // credit: aqrit
  555|   305k|    __m256i delta_asso;
  556|   305k|    if (default_or_url) {
  ------------------
  |  Branch (556:9): [Folded, False: 305k]
  ------------------
  557|      0|      delta_asso = _mm256_setr_epi8(
  558|      0|          0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,
  559|      0|          0x00, 0x00, 0x11, 0x00, 0x16, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  560|      0|          0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x16);
  561|   305k|    } else if (base64_url) {
  ------------------
  |  Branch (561:16): [True: 305k, Folded]
  ------------------
  562|   305k|      delta_asso = _mm256_setr_epi8(0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x0,
  563|   305k|                                    0x0, 0x0, 0x0, 0x0, 0xF, 0x0, 0xF, 0x1, 0x1,
  564|   305k|                                    0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0,
  565|   305k|                                    0x0, 0x0, 0xF, 0x0, 0xF);
  566|   305k|    } else {
  567|      0|      delta_asso = _mm256_setr_epi8(
  568|      0|          0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,
  569|      0|          0x00, 0x00, 0x0F, 0x00, 0x0F, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  570|      0|          0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x0F);
  571|      0|    }
  572|       |
  573|   305k|    __m256i delta_values;
  574|   305k|    if (default_or_url) {
  ------------------
  |  Branch (574:9): [Folded, False: 305k]
  ------------------
  575|      0|      delta_values = _mm256_setr_epi8(
  576|      0|          uint8_t(0xBF), uint8_t(0xE0), uint8_t(0xB9), uint8_t(0x13),
  577|      0|          uint8_t(0x04), uint8_t(0xBF), uint8_t(0xBF), uint8_t(0xB9),
  578|      0|          uint8_t(0xB9), uint8_t(0x00), uint8_t(0xFF), uint8_t(0x11),
  579|      0|          uint8_t(0xFF), uint8_t(0xBF), uint8_t(0x10), uint8_t(0xB9),
  580|      0|          uint8_t(0xBF), uint8_t(0xE0), uint8_t(0xB9), uint8_t(0x13),
  581|      0|          uint8_t(0x04), uint8_t(0xBF), uint8_t(0xBF), uint8_t(0xB9),
  582|      0|          uint8_t(0xB9), uint8_t(0x00), uint8_t(0xFF), uint8_t(0x11),
  583|      0|          uint8_t(0xFF), uint8_t(0xBF), uint8_t(0x10), uint8_t(0xB9));
  584|   305k|    } else if (base64_url) {
  ------------------
  |  Branch (584:16): [True: 305k, Folded]
  ------------------
  585|   305k|      delta_values = _mm256_setr_epi8(
  586|   305k|          0x0, 0x0, 0x0, 0x13, 0x4, uint8_t(0xBF), uint8_t(0xBF), uint8_t(0xB9),
  587|   305k|          uint8_t(0xB9), 0x0, 0x11, uint8_t(0xC3), uint8_t(0xBF), uint8_t(0xE0),
  588|   305k|          uint8_t(0xB9), uint8_t(0xB9), 0x0, 0x0, 0x0, 0x13, 0x4, uint8_t(0xBF),
  589|   305k|          uint8_t(0xBF), uint8_t(0xB9), uint8_t(0xB9), 0x0, 0x11, uint8_t(0xC3),
  590|   305k|          uint8_t(0xBF), uint8_t(0xE0), uint8_t(0xB9), uint8_t(0xB9));
  591|   305k|    } else {
  592|      0|      delta_values = _mm256_setr_epi8(
  593|      0|          int8_t(0x00), int8_t(0x00), int8_t(0x00), int8_t(0x13), int8_t(0x04),
  594|      0|          int8_t(0xBF), int8_t(0xBF), int8_t(0xB9), int8_t(0xB9), int8_t(0x00),
  595|      0|          int8_t(0x10), int8_t(0xC3), int8_t(0xBF), int8_t(0xBF), int8_t(0xB9),
  596|      0|          int8_t(0xB9), int8_t(0x00), int8_t(0x00), int8_t(0x00), int8_t(0x13),
  597|      0|          int8_t(0x04), int8_t(0xBF), int8_t(0xBF), int8_t(0xB9), int8_t(0xB9),
  598|      0|          int8_t(0x00), int8_t(0x10), int8_t(0xC3), int8_t(0xBF), int8_t(0xBF),
  599|      0|          int8_t(0xB9), int8_t(0xB9));
  600|      0|    }
  601|       |
  602|   305k|    __m256i check_asso;
  603|   305k|    if (default_or_url) {
  ------------------
  |  Branch (603:9): [Folded, False: 305k]
  ------------------
  604|      0|      check_asso = _mm256_setr_epi8(
  605|      0|          0x0D, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03,
  606|      0|          0x07, 0x0B, 0x0E, 0x0B, 0x06, 0x0D, 0x01, 0x01, 0x01, 0x01, 0x01,
  607|      0|          0x01, 0x01, 0x01, 0x01, 0x03, 0x07, 0x0B, 0x0E, 0x0B, 0x06);
  608|   305k|    } else if (base64_url) {
  ------------------
  |  Branch (608:16): [True: 305k, Folded]
  ------------------
  609|   305k|      check_asso = _mm256_setr_epi8(0xD, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1,
  610|   305k|                                    0x1, 0x3, 0x7, 0xB, 0xE, 0xB, 0x6, 0xD, 0x1,
  611|   305k|                                    0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x3,
  612|   305k|                                    0x7, 0xB, 0xE, 0xB, 0x6);
  613|   305k|    } else {
  614|      0|      check_asso = _mm256_setr_epi8(
  615|      0|          0x0D, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03,
  616|      0|          0x07, 0x0B, 0x0B, 0x0B, 0x0F, 0x0D, 0x01, 0x01, 0x01, 0x01, 0x01,
  617|      0|          0x01, 0x01, 0x01, 0x01, 0x03, 0x07, 0x0B, 0x0B, 0x0B, 0x0F);
  618|      0|    }
  619|   305k|    __m256i check_values;
  620|   305k|    if (default_or_url) {
  ------------------
  |  Branch (620:9): [Folded, False: 305k]
  ------------------
  621|      0|      check_values = _mm256_setr_epi8(
  622|      0|          uint8_t(0x80), uint8_t(0x80), uint8_t(0x80), uint8_t(0x80),
  623|      0|          uint8_t(0xCF), uint8_t(0xBF), uint8_t(0xD5), uint8_t(0xA6),
  624|      0|          uint8_t(0xB5), uint8_t(0xA1), uint8_t(0x00), uint8_t(0x80),
  625|      0|          uint8_t(0x00), uint8_t(0x80), uint8_t(0x00), uint8_t(0x80),
  626|      0|          uint8_t(0x80), uint8_t(0x80), uint8_t(0x80), uint8_t(0x80),
  627|      0|          uint8_t(0xCF), uint8_t(0xBF), uint8_t(0xD5), uint8_t(0xA6),
  628|      0|          uint8_t(0xB5), uint8_t(0xA1), uint8_t(0x00), uint8_t(0x80),
  629|      0|          uint8_t(0x00), uint8_t(0x80), uint8_t(0x00), uint8_t(0x80));
  630|   305k|    } else if (base64_url) {
  ------------------
  |  Branch (630:16): [True: 305k, Folded]
  ------------------
  631|   305k|      check_values = _mm256_setr_epi8(
  632|   305k|          uint8_t(0x80), uint8_t(0x80), uint8_t(0x80), uint8_t(0x80),
  633|   305k|          uint8_t(0xCF), uint8_t(0xBF), uint8_t(0xB6), uint8_t(0xA6),
  634|   305k|          uint8_t(0xB5), uint8_t(0xA1), 0x0, uint8_t(0x80), 0x0, uint8_t(0x80),
  635|   305k|          0x0, uint8_t(0x80), uint8_t(0x80), uint8_t(0x80), uint8_t(0x80),
  636|   305k|          uint8_t(0x80), uint8_t(0xCF), uint8_t(0xBF), uint8_t(0xB6),
  637|   305k|          uint8_t(0xA6), uint8_t(0xB5), uint8_t(0xA1), 0x0, uint8_t(0x80), 0x0,
  638|   305k|          uint8_t(0x80), 0x0, uint8_t(0x80));
  639|   305k|    } else {
  640|      0|      check_values = _mm256_setr_epi8(
  641|      0|          int8_t(0x80), int8_t(0x80), int8_t(0x80), int8_t(0x80), int8_t(0xCF),
  642|      0|          int8_t(0xBF), int8_t(0xD5), int8_t(0xA6), int8_t(0xB5), int8_t(0x86),
  643|      0|          int8_t(0xD1), int8_t(0x80), int8_t(0xB1), int8_t(0x80), int8_t(0x91),
  644|      0|          int8_t(0x80), int8_t(0x80), int8_t(0x80), int8_t(0x80), int8_t(0x80),
  645|      0|          int8_t(0xCF), int8_t(0xBF), int8_t(0xD5), int8_t(0xA6), int8_t(0xB5),
  646|      0|          int8_t(0x86), int8_t(0xD1), int8_t(0x80), int8_t(0xB1), int8_t(0x80),
  647|      0|          int8_t(0x91), int8_t(0x80));
  648|      0|    }
  649|   305k|    const __m256i shifted = _mm256_srli_epi32(*src, 3);
  650|   305k|    __m256i delta_hash =
  651|   305k|        _mm256_avg_epu8(_mm256_shuffle_epi8(delta_asso, *src), shifted);
  652|   305k|    if (default_or_url) {
  ------------------
  |  Branch (652:9): [Folded, False: 305k]
  ------------------
  653|      0|      delta_hash = _mm256_and_si256(delta_hash, _mm256_set1_epi8(0xf));
  654|      0|    }
  655|   305k|    const __m256i check_hash =
  656|   305k|        _mm256_avg_epu8(_mm256_shuffle_epi8(check_asso, *src), shifted);
  657|   305k|    const __m256i out =
  658|   305k|        _mm256_adds_epi8(_mm256_shuffle_epi8(delta_values, delta_hash), *src);
  659|   305k|    const __m256i chk =
  660|   305k|        _mm256_adds_epi8(_mm256_shuffle_epi8(check_values, check_hash), *src);
  661|   305k|    const int mask = _mm256_movemask_epi8(chk);
  662|   305k|    if (!ignore_garbage && mask) {
  ------------------
  |  Branch (662:9): [True: 305k, Folded]
  |  Branch (662:28): [True: 82.7k, False: 223k]
  ------------------
  663|  82.7k|      __m256i ascii_space =
  664|  82.7k|          _mm256_cmpeq_epi8(_mm256_shuffle_epi8(ascii_space_tbl, *src), *src);
  665|  82.7k|      *error = (mask ^ _mm256_movemask_epi8(ascii_space));
  666|  82.7k|    }
  667|   305k|    *src = out;
  668|   305k|    return (uint32_t)mask;
  669|   305k|  }
simdutf.cpp:_ZN7simdutf7haswell12_GLOBAL__N_17block6414to_base64_maskILb0ELb0ELb0EEEmPm:
  535|   303k|  simdutf_really_inline uint64_t to_base64_mask(uint64_t *error) {
  536|   303k|    uint32_t err0 = 0;
  537|   303k|    uint32_t err1 = 0;
  538|   303k|    uint64_t m0 = to_base64_mask<base64_url, ignore_garbage, default_or_url>(
  539|   303k|        &chunks[0], &err0);
  540|   303k|    uint64_t m1 = to_base64_mask<base64_url, ignore_garbage, default_or_url>(
  541|   303k|        &chunks[1], &err1);
  542|   303k|    if (!ignore_garbage) {
  ------------------
  |  Branch (542:9): [True: 303k, Folded]
  ------------------
  543|   303k|      *error = err0 | ((uint64_t)err1 << 32);
  544|   303k|    }
  545|   303k|    return m0 | (m1 << 32);
  546|   303k|  }
simdutf.cpp:_ZN7simdutf7haswell12_GLOBAL__N_17block6414to_base64_maskILb0ELb0ELb0EEEjPDv4_xPj:
  549|   607k|  simdutf_really_inline uint32_t to_base64_mask(__m256i *src, uint32_t *error) {
  550|   607k|    const __m256i ascii_space_tbl =
  551|   607k|        _mm256_setr_epi8(0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9, 0xa,
  552|   607k|                         0x0, 0xc, 0xd, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0,
  553|   607k|                         0x0, 0x0, 0x0, 0x9, 0xa, 0x0, 0xc, 0xd, 0x0, 0x0);
  554|       |    // credit: aqrit
  555|   607k|    __m256i delta_asso;
  556|   607k|    if (default_or_url) {
  ------------------
  |  Branch (556:9): [Folded, False: 607k]
  ------------------
  557|      0|      delta_asso = _mm256_setr_epi8(
  558|      0|          0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,
  559|      0|          0x00, 0x00, 0x11, 0x00, 0x16, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  560|      0|          0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x16);
  561|   607k|    } else if (base64_url) {
  ------------------
  |  Branch (561:16): [Folded, False: 607k]
  ------------------
  562|      0|      delta_asso = _mm256_setr_epi8(0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x0,
  563|      0|                                    0x0, 0x0, 0x0, 0x0, 0xF, 0x0, 0xF, 0x1, 0x1,
  564|      0|                                    0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0,
  565|      0|                                    0x0, 0x0, 0xF, 0x0, 0xF);
  566|   607k|    } else {
  567|   607k|      delta_asso = _mm256_setr_epi8(
  568|   607k|          0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,
  569|   607k|          0x00, 0x00, 0x0F, 0x00, 0x0F, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  570|   607k|          0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x0F);
  571|   607k|    }
  572|       |
  573|   607k|    __m256i delta_values;
  574|   607k|    if (default_or_url) {
  ------------------
  |  Branch (574:9): [Folded, False: 607k]
  ------------------
  575|      0|      delta_values = _mm256_setr_epi8(
  576|      0|          uint8_t(0xBF), uint8_t(0xE0), uint8_t(0xB9), uint8_t(0x13),
  577|      0|          uint8_t(0x04), uint8_t(0xBF), uint8_t(0xBF), uint8_t(0xB9),
  578|      0|          uint8_t(0xB9), uint8_t(0x00), uint8_t(0xFF), uint8_t(0x11),
  579|      0|          uint8_t(0xFF), uint8_t(0xBF), uint8_t(0x10), uint8_t(0xB9),
  580|      0|          uint8_t(0xBF), uint8_t(0xE0), uint8_t(0xB9), uint8_t(0x13),
  581|      0|          uint8_t(0x04), uint8_t(0xBF), uint8_t(0xBF), uint8_t(0xB9),
  582|      0|          uint8_t(0xB9), uint8_t(0x00), uint8_t(0xFF), uint8_t(0x11),
  583|      0|          uint8_t(0xFF), uint8_t(0xBF), uint8_t(0x10), uint8_t(0xB9));
  584|   607k|    } else if (base64_url) {
  ------------------
  |  Branch (584:16): [Folded, False: 607k]
  ------------------
  585|      0|      delta_values = _mm256_setr_epi8(
  586|      0|          0x0, 0x0, 0x0, 0x13, 0x4, uint8_t(0xBF), uint8_t(0xBF), uint8_t(0xB9),
  587|      0|          uint8_t(0xB9), 0x0, 0x11, uint8_t(0xC3), uint8_t(0xBF), uint8_t(0xE0),
  588|      0|          uint8_t(0xB9), uint8_t(0xB9), 0x0, 0x0, 0x0, 0x13, 0x4, uint8_t(0xBF),
  589|      0|          uint8_t(0xBF), uint8_t(0xB9), uint8_t(0xB9), 0x0, 0x11, uint8_t(0xC3),
  590|      0|          uint8_t(0xBF), uint8_t(0xE0), uint8_t(0xB9), uint8_t(0xB9));
  591|   607k|    } else {
  592|   607k|      delta_values = _mm256_setr_epi8(
  593|   607k|          int8_t(0x00), int8_t(0x00), int8_t(0x00), int8_t(0x13), int8_t(0x04),
  594|   607k|          int8_t(0xBF), int8_t(0xBF), int8_t(0xB9), int8_t(0xB9), int8_t(0x00),
  595|   607k|          int8_t(0x10), int8_t(0xC3), int8_t(0xBF), int8_t(0xBF), int8_t(0xB9),
  596|   607k|          int8_t(0xB9), int8_t(0x00), int8_t(0x00), int8_t(0x00), int8_t(0x13),
  597|   607k|          int8_t(0x04), int8_t(0xBF), int8_t(0xBF), int8_t(0xB9), int8_t(0xB9),
  598|   607k|          int8_t(0x00), int8_t(0x10), int8_t(0xC3), int8_t(0xBF), int8_t(0xBF),
  599|   607k|          int8_t(0xB9), int8_t(0xB9));
  600|   607k|    }
  601|       |
  602|   607k|    __m256i check_asso;
  603|   607k|    if (default_or_url) {
  ------------------
  |  Branch (603:9): [Folded, False: 607k]
  ------------------
  604|      0|      check_asso = _mm256_setr_epi8(
  605|      0|          0x0D, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03,
  606|      0|          0x07, 0x0B, 0x0E, 0x0B, 0x06, 0x0D, 0x01, 0x01, 0x01, 0x01, 0x01,
  607|      0|          0x01, 0x01, 0x01, 0x01, 0x03, 0x07, 0x0B, 0x0E, 0x0B, 0x06);
  608|   607k|    } else if (base64_url) {
  ------------------
  |  Branch (608:16): [Folded, False: 607k]
  ------------------
  609|      0|      check_asso = _mm256_setr_epi8(0xD, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1,
  610|      0|                                    0x1, 0x3, 0x7, 0xB, 0xE, 0xB, 0x6, 0xD, 0x1,
  611|      0|                                    0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x3,
  612|      0|                                    0x7, 0xB, 0xE, 0xB, 0x6);
  613|   607k|    } else {
  614|   607k|      check_asso = _mm256_setr_epi8(
  615|   607k|          0x0D, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03,
  616|   607k|          0x07, 0x0B, 0x0B, 0x0B, 0x0F, 0x0D, 0x01, 0x01, 0x01, 0x01, 0x01,
  617|   607k|          0x01, 0x01, 0x01, 0x01, 0x03, 0x07, 0x0B, 0x0B, 0x0B, 0x0F);
  618|   607k|    }
  619|   607k|    __m256i check_values;
  620|   607k|    if (default_or_url) {
  ------------------
  |  Branch (620:9): [Folded, False: 607k]
  ------------------
  621|      0|      check_values = _mm256_setr_epi8(
  622|      0|          uint8_t(0x80), uint8_t(0x80), uint8_t(0x80), uint8_t(0x80),
  623|      0|          uint8_t(0xCF), uint8_t(0xBF), uint8_t(0xD5), uint8_t(0xA6),
  624|      0|          uint8_t(0xB5), uint8_t(0xA1), uint8_t(0x00), uint8_t(0x80),
  625|      0|          uint8_t(0x00), uint8_t(0x80), uint8_t(0x00), uint8_t(0x80),
  626|      0|          uint8_t(0x80), uint8_t(0x80), uint8_t(0x80), uint8_t(0x80),
  627|      0|          uint8_t(0xCF), uint8_t(0xBF), uint8_t(0xD5), uint8_t(0xA6),
  628|      0|          uint8_t(0xB5), uint8_t(0xA1), uint8_t(0x00), uint8_t(0x80),
  629|      0|          uint8_t(0x00), uint8_t(0x80), uint8_t(0x00), uint8_t(0x80));
  630|   607k|    } else if (base64_url) {
  ------------------
  |  Branch (630:16): [Folded, False: 607k]
  ------------------
  631|      0|      check_values = _mm256_setr_epi8(
  632|      0|          uint8_t(0x80), uint8_t(0x80), uint8_t(0x80), uint8_t(0x80),
  633|      0|          uint8_t(0xCF), uint8_t(0xBF), uint8_t(0xB6), uint8_t(0xA6),
  634|      0|          uint8_t(0xB5), uint8_t(0xA1), 0x0, uint8_t(0x80), 0x0, uint8_t(0x80),
  635|      0|          0x0, uint8_t(0x80), uint8_t(0x80), uint8_t(0x80), uint8_t(0x80),
  636|      0|          uint8_t(0x80), uint8_t(0xCF), uint8_t(0xBF), uint8_t(0xB6),
  637|      0|          uint8_t(0xA6), uint8_t(0xB5), uint8_t(0xA1), 0x0, uint8_t(0x80), 0x0,
  638|      0|          uint8_t(0x80), 0x0, uint8_t(0x80));
  639|   607k|    } else {
  640|   607k|      check_values = _mm256_setr_epi8(
  641|   607k|          int8_t(0x80), int8_t(0x80), int8_t(0x80), int8_t(0x80), int8_t(0xCF),
  642|   607k|          int8_t(0xBF), int8_t(0xD5), int8_t(0xA6), int8_t(0xB5), int8_t(0x86),
  643|   607k|          int8_t(0xD1), int8_t(0x80), int8_t(0xB1), int8_t(0x80), int8_t(0x91),
  644|   607k|          int8_t(0x80), int8_t(0x80), int8_t(0x80), int8_t(0x80), int8_t(0x80),
  645|   607k|          int8_t(0xCF), int8_t(0xBF), int8_t(0xD5), int8_t(0xA6), int8_t(0xB5),
  646|   607k|          int8_t(0x86), int8_t(0xD1), int8_t(0x80), int8_t(0xB1), int8_t(0x80),
  647|   607k|          int8_t(0x91), int8_t(0x80));
  648|   607k|    }
  649|   607k|    const __m256i shifted = _mm256_srli_epi32(*src, 3);
  650|   607k|    __m256i delta_hash =
  651|   607k|        _mm256_avg_epu8(_mm256_shuffle_epi8(delta_asso, *src), shifted);
  652|   607k|    if (default_or_url) {
  ------------------
  |  Branch (652:9): [Folded, False: 607k]
  ------------------
  653|      0|      delta_hash = _mm256_and_si256(delta_hash, _mm256_set1_epi8(0xf));
  654|      0|    }
  655|   607k|    const __m256i check_hash =
  656|   607k|        _mm256_avg_epu8(_mm256_shuffle_epi8(check_asso, *src), shifted);
  657|   607k|    const __m256i out =
  658|   607k|        _mm256_adds_epi8(_mm256_shuffle_epi8(delta_values, delta_hash), *src);
  659|   607k|    const __m256i chk =
  660|   607k|        _mm256_adds_epi8(_mm256_shuffle_epi8(check_values, check_hash), *src);
  661|   607k|    const int mask = _mm256_movemask_epi8(chk);
  662|   607k|    if (!ignore_garbage && mask) {
  ------------------
  |  Branch (662:9): [True: 607k, Folded]
  |  Branch (662:28): [True: 119k, False: 487k]
  ------------------
  663|   119k|      __m256i ascii_space =
  664|   119k|          _mm256_cmpeq_epi8(_mm256_shuffle_epi8(ascii_space_tbl, *src), *src);
  665|   119k|      *error = (mask ^ _mm256_movemask_epi8(ascii_space));
  666|   119k|    }
  667|   607k|    *src = out;
  668|   607k|    return (uint32_t)mask;
  669|   607k|  }
simdutf.cpp:_ZN7simdutf7haswell12_GLOBAL__N_17block64C2EPKDs:
  495|   118k|  simdutf_really_inline block64(const char16_t *src) {
  496|   118k|    const auto m1 = _mm256_loadu_si256(reinterpret_cast<const __m256i *>(src));
  497|   118k|    const auto m2 =
  498|   118k|        _mm256_loadu_si256(reinterpret_cast<const __m256i *>(src + 16));
  499|   118k|    const auto m3 =
  500|   118k|        _mm256_loadu_si256(reinterpret_cast<const __m256i *>(src + 32));
  501|   118k|    const auto m4 =
  502|   118k|        _mm256_loadu_si256(reinterpret_cast<const __m256i *>(src + 48));
  503|       |
  504|   118k|    const auto m1p = _mm256_permute2x128_si256(m1, m2, 0x20);
  505|   118k|    const auto m2p = _mm256_permute2x128_si256(m1, m2, 0x31);
  506|   118k|    const auto m3p = _mm256_permute2x128_si256(m3, m4, 0x20);
  507|   118k|    const auto m4p = _mm256_permute2x128_si256(m3, m4, 0x31);
  508|       |
  509|   118k|    chunks[0] = _mm256_packus_epi16(m1p, m2p);
  510|   118k|    chunks[1] = _mm256_packus_epi16(m3p, m4p);
  511|   118k|  }

_ZNK7simdutf7haswell14implementation16base64_to_binaryEPKcmPcNS_14base64_optionsENS_27last_chunk_handling_optionsE:
 1274|  2.03k|    last_chunk_handling_options last_chunk_options) const noexcept {
 1275|  2.03k|  if (options & base64_default_or_url) {
  ------------------
  |  Branch (1275:7): [True: 0, False: 2.03k]
  ------------------
 1276|      0|    if (options == base64_options::base64_default_or_url_accept_garbage) {
  ------------------
  |  Branch (1276:9): [True: 0, False: 0]
  ------------------
 1277|      0|      return base64::compress_decode_base64<false, true, true>(
 1278|      0|          output, input, length, options, last_chunk_options);
 1279|      0|    } else {
 1280|      0|      return base64::compress_decode_base64<false, false, true>(
 1281|      0|          output, input, length, options, last_chunk_options);
 1282|      0|    }
 1283|  2.03k|  } else if (options & base64_url) {
  ------------------
  |  Branch (1283:14): [True: 981, False: 1.05k]
  ------------------
 1284|    981|    if (options == base64_options::base64_url_accept_garbage) {
  ------------------
  |  Branch (1284:9): [True: 0, False: 981]
  ------------------
 1285|      0|      return base64::compress_decode_base64<true, true, false>(
 1286|      0|          output, input, length, options, last_chunk_options);
 1287|    981|    } else {
 1288|    981|      return base64::compress_decode_base64<true, false, false>(
 1289|    981|          output, input, length, options, last_chunk_options);
 1290|    981|    }
 1291|  1.05k|  } else {
 1292|  1.05k|    if (options == base64_options::base64_default_accept_garbage) {
  ------------------
  |  Branch (1292:9): [True: 0, False: 1.05k]
  ------------------
 1293|      0|      return base64::compress_decode_base64<false, true, false>(
 1294|      0|          output, input, length, options, last_chunk_options);
 1295|  1.05k|    } else {
 1296|  1.05k|      return base64::compress_decode_base64<false, false, false>(
 1297|  1.05k|          output, input, length, options, last_chunk_options);
 1298|  1.05k|    }
 1299|  1.05k|  }
 1300|  2.03k|}
_ZNK7simdutf7haswell14implementation24base64_to_binary_detailsEPKcmPcNS_14base64_optionsENS_27last_chunk_handling_optionsE:
 1304|  2.03k|    last_chunk_handling_options last_chunk_options) const noexcept {
 1305|  2.03k|  if (options & base64_default_or_url) {
  ------------------
  |  Branch (1305:7): [True: 0, False: 2.03k]
  ------------------
 1306|      0|    if (options == base64_options::base64_default_or_url_accept_garbage) {
  ------------------
  |  Branch (1306:9): [True: 0, False: 0]
  ------------------
 1307|      0|      return base64::compress_decode_base64<false, true, true>(
 1308|      0|          output, input, length, options, last_chunk_options);
 1309|      0|    } else {
 1310|      0|      return base64::compress_decode_base64<false, false, true>(
 1311|      0|          output, input, length, options, last_chunk_options);
 1312|      0|    }
 1313|  2.03k|  } else if (options & base64_url) {
  ------------------
  |  Branch (1313:14): [True: 981, False: 1.05k]
  ------------------
 1314|    981|    if (options == base64_options::base64_url_accept_garbage) {
  ------------------
  |  Branch (1314:9): [True: 0, False: 981]
  ------------------
 1315|      0|      return base64::compress_decode_base64<true, true, false>(
 1316|      0|          output, input, length, options, last_chunk_options);
 1317|    981|    } else {
 1318|    981|      return base64::compress_decode_base64<true, false, false>(
 1319|    981|          output, input, length, options, last_chunk_options);
 1320|    981|    }
 1321|  1.05k|  } else {
 1322|  1.05k|    if (options == base64_options::base64_default_accept_garbage) {
  ------------------
  |  Branch (1322:9): [True: 0, False: 1.05k]
  ------------------
 1323|      0|      return base64::compress_decode_base64<false, true, false>(
 1324|      0|          output, input, length, options, last_chunk_options);
 1325|  1.05k|    } else {
 1326|  1.05k|      return base64::compress_decode_base64<false, false, false>(
 1327|  1.05k|          output, input, length, options, last_chunk_options);
 1328|  1.05k|    }
 1329|  1.05k|  }
 1330|  2.03k|}
_ZNK7simdutf7haswell14implementation16base64_to_binaryEPKDsmPcNS_14base64_optionsENS_27last_chunk_handling_optionsE:
 1334|  2.00k|    last_chunk_handling_options last_chunk_options) const noexcept {
 1335|  2.00k|  if (options & base64_default_or_url) {
  ------------------
  |  Branch (1335:7): [True: 0, False: 2.00k]
  ------------------
 1336|      0|    if (options == base64_options::base64_default_or_url_accept_garbage) {
  ------------------
  |  Branch (1336:9): [True: 0, False: 0]
  ------------------
 1337|      0|      return base64::compress_decode_base64<false, true, true>(
 1338|      0|          output, input, length, options, last_chunk_options);
 1339|      0|    } else {
 1340|      0|      return base64::compress_decode_base64<false, false, true>(
 1341|      0|          output, input, length, options, last_chunk_options);
 1342|      0|    }
 1343|  2.00k|  } else if (options & base64_url) {
  ------------------
  |  Branch (1343:14): [True: 1.01k, False: 985]
  ------------------
 1344|  1.01k|    if (options == base64_options::base64_url_accept_garbage) {
  ------------------
  |  Branch (1344:9): [True: 0, False: 1.01k]
  ------------------
 1345|      0|      return base64::compress_decode_base64<true, true, false>(
 1346|      0|          output, input, length, options, last_chunk_options);
 1347|  1.01k|    } else {
 1348|  1.01k|      return base64::compress_decode_base64<true, false, false>(
 1349|  1.01k|          output, input, length, options, last_chunk_options);
 1350|  1.01k|    }
 1351|  1.01k|  } else {
 1352|    985|    if (options == base64_options::base64_default_accept_garbage) {
  ------------------
  |  Branch (1352:9): [True: 0, False: 985]
  ------------------
 1353|      0|      return base64::compress_decode_base64<false, true, false>(
 1354|      0|          output, input, length, options, last_chunk_options);
 1355|    985|    } else {
 1356|    985|      return base64::compress_decode_base64<false, false, false>(
 1357|    985|          output, input, length, options, last_chunk_options);
 1358|    985|    }
 1359|    985|  }
 1360|  2.00k|}
_ZNK7simdutf7haswell14implementation24base64_to_binary_detailsEPKDsmPcNS_14base64_optionsENS_27last_chunk_handling_optionsE:
 1364|  2.00k|    last_chunk_handling_options last_chunk_options) const noexcept {
 1365|  2.00k|  if (options & base64_default_or_url) {
  ------------------
  |  Branch (1365:7): [True: 0, False: 2.00k]
  ------------------
 1366|      0|    if (options == base64_options::base64_default_or_url_accept_garbage) {
  ------------------
  |  Branch (1366:9): [True: 0, False: 0]
  ------------------
 1367|      0|      return base64::compress_decode_base64<false, true, true>(
 1368|      0|          output, input, length, options, last_chunk_options);
 1369|      0|    } else {
 1370|      0|      return base64::compress_decode_base64<false, false, true>(
 1371|      0|          output, input, length, options, last_chunk_options);
 1372|      0|    }
 1373|  2.00k|  } else if (options & base64_url) {
  ------------------
  |  Branch (1373:14): [True: 1.01k, False: 985]
  ------------------
 1374|  1.01k|    if (options == base64_options::base64_url_accept_garbage) {
  ------------------
  |  Branch (1374:9): [True: 0, False: 1.01k]
  ------------------
 1375|      0|      return base64::compress_decode_base64<true, true, false>(
 1376|      0|          output, input, length, options, last_chunk_options);
 1377|  1.01k|    } else {
 1378|  1.01k|      return base64::compress_decode_base64<true, false, false>(
 1379|  1.01k|          output, input, length, options, last_chunk_options);
 1380|  1.01k|    }
 1381|  1.01k|  } else {
 1382|    985|    if (options == base64_options::base64_default_accept_garbage) {
  ------------------
  |  Branch (1382:9): [True: 0, False: 985]
  ------------------
 1383|      0|      return base64::compress_decode_base64<false, true, false>(
 1384|      0|          output, input, length, options, last_chunk_options);
 1385|    985|    } else {
 1386|    985|      return base64::compress_decode_base64<false, false, false>(
 1387|    985|          output, input, length, options, last_chunk_options);
 1388|    985|    }
 1389|    985|  }
 1390|  2.00k|}

_ZNK7simdutf14implementation27supported_by_runtime_systemEv:
   64|      8|bool implementation::supported_by_runtime_system() const {
   65|      8|  uint32_t required_instruction_sets = this->required_instruction_sets();
   66|      8|  uint32_t supported_instruction_sets =
   67|      8|      internal::detect_supported_architectures();
   68|      8|  return ((supported_instruction_sets & required_instruction_sets) ==
   69|      8|          required_instruction_sets);
   70|      8|}
_ZNK7simdutf14implementation33maximal_binary_length_from_base64EPKcm:
  117|  6.11k|    const char *input, size_t length) const noexcept {
  118|  6.11k|  return scalar::base64::maximal_binary_length_from_base64(input, length);
  119|  6.11k|}
_ZNK7simdutf14implementation33maximal_binary_length_from_base64EPKDsm:
  122|  6.01k|    const char16_t *input, size_t length) const noexcept {
  123|  6.01k|  return scalar::base64::maximal_binary_length_from_base64(input, length);
  124|  6.01k|}
_ZNK7simdutf8internal29available_implementation_list5beginEv:
 1513|      1|available_implementation_list::begin() const noexcept {
 1514|      1|  return internal::get_available_implementation_pointers().begin();
 1515|      1|}
_ZNK7simdutf8internal29available_implementation_list3endEv:
 1517|      1|available_implementation_list::end() const noexcept {
 1518|      1|  return internal::get_available_implementation_pointers().end();
 1519|      1|}
_ZN7simdutf29get_available_implementationsEv:
 1568|      1|get_available_implementations() {
 1569|      1|#if !SIMDUTF_USE_STATIC_INITIALIZATION
 1570|      1|  static const internal::available_implementation_list
 1571|      1|      available_implementations_instance{};
 1572|      1|#endif
 1573|      1|  return available_implementations_instance;
 1574|      1|}
simdutf.cpp:_ZN7simdutf8internalL37get_available_implementation_pointersEv:
  938|      2|get_available_implementation_pointers() {
  939|      2|#if !SIMDUTF_USE_STATIC_INITIALIZATION
  940|      2|  static const std::initializer_list<const implementation *>
  941|      2|      available_implementation_pointers{
  942|      2|  #if SIMDUTF_IMPLEMENTATION_ICELAKE
  943|      2|          get_icelake_singleton(),
  944|      2|  #endif
  945|      2|  #if SIMDUTF_IMPLEMENTATION_HASWELL
  946|      2|          get_haswell_singleton(),
  947|      2|  #endif
  948|      2|  #if SIMDUTF_IMPLEMENTATION_WESTMERE
  949|      2|          get_westmere_singleton(),
  950|      2|  #endif
  951|       |  #if SIMDUTF_IMPLEMENTATION_ARM64
  952|       |          get_arm64_singleton(),
  953|       |  #endif
  954|       |  #if SIMDUTF_IMPLEMENTATION_PPC64
  955|       |          get_ppc64_singleton(),
  956|       |  #endif
  957|       |  #if SIMDUTF_IMPLEMENTATION_RVV
  958|       |          get_rvv_singleton(),
  959|       |  #endif
  960|       |  #if SIMDUTF_IMPLEMENTATION_LASX
  961|       |          get_lasx_singleton(),
  962|       |  #endif
  963|       |  #if SIMDUTF_IMPLEMENTATION_LSX
  964|       |          get_lsx_singleton(),
  965|       |  #endif
  966|      2|  #if SIMDUTF_IMPLEMENTATION_FALLBACK
  967|      2|          get_fallback_singleton(),
  968|      2|  #endif
  969|      2|      };
  970|      2|#endif
  971|      2|  return available_implementation_pointers;
  972|      2|}
simdutf.cpp:_ZN7simdutf8internalL21get_icelake_singletonEv:
  157|      1|static const icelake::implementation *get_icelake_singleton() {
  158|      1|  #if !SIMDUTF_USE_STATIC_INITIALIZATION
  159|      1|  static const icelake::implementation icelake_singleton{};
  160|      1|  #endif
  161|      1|  return &icelake_singleton;
  162|      1|}
simdutf.cpp:_ZN7simdutf8internalL21get_haswell_singletonEv:
  168|      1|static const haswell::implementation *get_haswell_singleton() {
  169|      1|  #if !SIMDUTF_USE_STATIC_INITIALIZATION
  170|      1|  static const haswell::implementation haswell_singleton{};
  171|      1|  #endif
  172|      1|  return &haswell_singleton;
  173|      1|}
simdutf.cpp:_ZN7simdutf8internalL22get_westmere_singletonEv:
  179|      1|static const westmere::implementation *get_westmere_singleton() {
  180|      1|  #if !SIMDUTF_USE_STATIC_INITIALIZATION
  181|      1|  static const westmere::implementation westmere_singleton{};
  182|      1|  #endif
  183|      1|  return &westmere_singleton;
  184|      1|}
simdutf.cpp:_ZN7simdutf8internalL22get_fallback_singletonEv:
  245|      1|static const fallback::implementation *get_fallback_singleton() {
  246|      1|  #if !SIMDUTF_USE_STATIC_INITIALIZATION
  247|      1|  static const fallback::implementation fallback_singleton{};
  248|      1|  #endif
  249|      1|  return &fallback_singleton;
  250|      1|}

_ZN7simdutf8fallback14implementationC2Ev:
   16|      1|      : simdutf::implementation("fallback", "Generic fallback implementation",
   17|      1|                                0) {}

simdutf.cpp:_ZN7simdutf7haswell12_GLOBAL__N_110count_onesEm:
   14|   135k|simdutf_really_inline long long int count_ones(uint64_t input_num) {
   15|       |  return _popcnt64(input_num);
   16|   135k|}
simdutf.cpp:_ZN7simdutf7haswell12_GLOBAL__N_115trailing_zeroesEm:
   20|   131k|simdutf_really_inline int trailing_zeroes(uint64_t input_num) {
   21|       |  #if SIMDUTF_REGULAR_VISUAL_STUDIO
   22|       |  return (int)_tzcnt_u64(input_num);
   23|       |  #else  // SIMDUTF_REGULAR_VISUAL_STUDIO
   24|   131k|  return __builtin_ctzll(input_num);
   25|   131k|  #endif // SIMDUTF_REGULAR_VISUAL_STUDIO
   26|   131k|}
simdutf.cpp:_ZN7simdutf7haswell12_GLOBAL__N_115is_power_of_twoImEEbT_:
   29|   164k|template <typename T> bool is_power_of_two(T x) { return (x & (x - 1)) == 0; }

_ZN7simdutf7haswell14implementationC2Ev:
   16|      1|      : simdutf::implementation("haswell", "Intel/AMD AVX2",
   17|      1|                                internal::instruction_set::AVX2 |
   18|      1|                                    internal::instruction_set::BMI1 |
   19|      1|                                    internal::instruction_set::BMI2) {}

_ZN7simdutf7icelake14implementationC2Ev:
   16|      1|      : simdutf::implementation(
   17|      1|            "icelake",
   18|      1|            "Intel AVX512 (AVX-512BW, AVX-512CD, AVX-512VL, AVX-512VBMI2 "
   19|      1|            "extensions)",
   20|      1|            internal::instruction_set::AVX2 | internal::instruction_set::BMI1 |
   21|      1|                internal::instruction_set::BMI2 |
   22|      1|                internal::instruction_set::AVX512BW |
   23|      1|                internal::instruction_set::AVX512CD |
   24|      1|                internal::instruction_set::AVX512VL |
   25|      1|                internal::instruction_set::AVX512VBMI2 |
   26|      1|                internal::instruction_set::AVX512VPOPCNTDQ) {}

simdutf.cpp:_ZN7simdutf8westmere12_GLOBAL__N_110count_onesEm:
   14|   150k|simdutf_really_inline long long int count_ones(uint64_t input_num) {
   15|       |  return _popcnt64(input_num);
   16|   150k|}
simdutf.cpp:_ZN7simdutf8westmere12_GLOBAL__N_115trailing_zeroesEm:
   20|   131k|simdutf_really_inline int trailing_zeroes(uint64_t input_num) {
   21|       |  #if SIMDUTF_REGULAR_VISUAL_STUDIO
   22|       |  unsigned long ret;
   23|       |  _BitScanForward64(&ret, input_num);
   24|       |  return (int)ret;
   25|       |  #else  // SIMDUTF_REGULAR_VISUAL_STUDIO
   26|   131k|  return __builtin_ctzll(input_num);
   27|   131k|  #endif // SIMDUTF_REGULAR_VISUAL_STUDIO
   28|   131k|}
simdutf.cpp:_ZN7simdutf8westmere12_GLOBAL__N_115is_power_of_twoImEEbT_:
   31|   164k|template <typename T> bool is_power_of_two(T x) { return (x & (x - 1)) == 0; }

_ZN7simdutf8westmere14implementationC2Ev:
   18|      1|      : simdutf::implementation("westmere", "Intel/AMD SSE4.2",
   19|      1|                                internal::instruction_set::SSE42) {}

_ZNK7simdutf8westmere14implementation16base64_to_binaryEPKcmPcNS_14base64_optionsENS_27last_chunk_handling_optionsE:
 1304|  2.03k|    last_chunk_handling_options last_chunk_options) const noexcept {
 1305|  2.03k|  if (options & base64_default_or_url) {
  ------------------
  |  Branch (1305:7): [True: 0, False: 2.03k]
  ------------------
 1306|      0|    if (options == base64_options::base64_default_or_url_accept_garbage) {
  ------------------
  |  Branch (1306:9): [True: 0, False: 0]
  ------------------
 1307|      0|      return base64::compress_decode_base64<false, true, true>(
 1308|      0|          output, input, length, options, last_chunk_options);
 1309|      0|    } else {
 1310|      0|      return base64::compress_decode_base64<false, false, true>(
 1311|      0|          output, input, length, options, last_chunk_options);
 1312|      0|    }
 1313|  2.03k|  } else if (options & base64_url) {
  ------------------
  |  Branch (1313:14): [True: 981, False: 1.05k]
  ------------------
 1314|    981|    if (options == base64_options::base64_url_accept_garbage) {
  ------------------
  |  Branch (1314:9): [True: 0, False: 981]
  ------------------
 1315|      0|      return base64::compress_decode_base64<true, true, false>(
 1316|      0|          output, input, length, options, last_chunk_options);
 1317|    981|    } else {
 1318|    981|      return base64::compress_decode_base64<true, false, false>(
 1319|    981|          output, input, length, options, last_chunk_options);
 1320|    981|    }
 1321|  1.05k|  } else {
 1322|  1.05k|    if (options == base64_options::base64_default_accept_garbage) {
  ------------------
  |  Branch (1322:9): [True: 0, False: 1.05k]
  ------------------
 1323|      0|      return base64::compress_decode_base64<false, true, false>(
 1324|      0|          output, input, length, options, last_chunk_options);
 1325|  1.05k|    } else {
 1326|  1.05k|      return base64::compress_decode_base64<false, false, false>(
 1327|  1.05k|          output, input, length, options, last_chunk_options);
 1328|  1.05k|    }
 1329|  1.05k|  }
 1330|  2.03k|}
_ZNK7simdutf8westmere14implementation24base64_to_binary_detailsEPKcmPcNS_14base64_optionsENS_27last_chunk_handling_optionsE:
 1334|  2.03k|    last_chunk_handling_options last_chunk_options) const noexcept {
 1335|  2.03k|  if (options & base64_default_or_url) {
  ------------------
  |  Branch (1335:7): [True: 0, False: 2.03k]
  ------------------
 1336|      0|    if (options == base64_options::base64_default_or_url_accept_garbage) {
  ------------------
  |  Branch (1336:9): [True: 0, False: 0]
  ------------------
 1337|      0|      return base64::compress_decode_base64<false, true, true>(
 1338|      0|          output, input, length, options, last_chunk_options);
 1339|      0|    } else {
 1340|      0|      return base64::compress_decode_base64<false, false, true>(
 1341|      0|          output, input, length, options, last_chunk_options);
 1342|      0|    }
 1343|  2.03k|  } else if (options & base64_url) {
  ------------------
  |  Branch (1343:14): [True: 981, False: 1.05k]
  ------------------
 1344|    981|    if (options == base64_options::base64_url_accept_garbage) {
  ------------------
  |  Branch (1344:9): [True: 0, False: 981]
  ------------------
 1345|      0|      return base64::compress_decode_base64<true, true, false>(
 1346|      0|          output, input, length, options, last_chunk_options);
 1347|    981|    } else {
 1348|    981|      return base64::compress_decode_base64<true, false, false>(
 1349|    981|          output, input, length, options, last_chunk_options);
 1350|    981|    }
 1351|  1.05k|  } else {
 1352|  1.05k|    if (options == base64_options::base64_default_accept_garbage) {
  ------------------
  |  Branch (1352:9): [True: 0, False: 1.05k]
  ------------------
 1353|      0|      return base64::compress_decode_base64<false, true, false>(
 1354|      0|          output, input, length, options, last_chunk_options);
 1355|  1.05k|    } else {
 1356|  1.05k|      return base64::compress_decode_base64<false, false, false>(
 1357|  1.05k|          output, input, length, options, last_chunk_options);
 1358|  1.05k|    }
 1359|  1.05k|  }
 1360|  2.03k|}
_ZNK7simdutf8westmere14implementation16base64_to_binaryEPKDsmPcNS_14base64_optionsENS_27last_chunk_handling_optionsE:
 1364|  2.00k|    last_chunk_handling_options last_chunk_options) const noexcept {
 1365|  2.00k|  if (options & base64_default_or_url) {
  ------------------
  |  Branch (1365:7): [True: 0, False: 2.00k]
  ------------------
 1366|      0|    if (options == base64_options::base64_default_or_url_accept_garbage) {
  ------------------
  |  Branch (1366:9): [True: 0, False: 0]
  ------------------
 1367|      0|      return base64::compress_decode_base64<false, true, true>(
 1368|      0|          output, input, length, options, last_chunk_options);
 1369|      0|    } else {
 1370|      0|      return base64::compress_decode_base64<false, false, true>(
 1371|      0|          output, input, length, options, last_chunk_options);
 1372|      0|    }
 1373|  2.00k|  } else if (options & base64_url) {
  ------------------
  |  Branch (1373:14): [True: 1.01k, False: 985]
  ------------------
 1374|  1.01k|    if (options == base64_options::base64_url_accept_garbage) {
  ------------------
  |  Branch (1374:9): [True: 0, False: 1.01k]
  ------------------
 1375|      0|      return base64::compress_decode_base64<true, true, false>(
 1376|      0|          output, input, length, options, last_chunk_options);
 1377|  1.01k|    } else {
 1378|  1.01k|      return base64::compress_decode_base64<true, false, false>(
 1379|  1.01k|          output, input, length, options, last_chunk_options);
 1380|  1.01k|    }
 1381|  1.01k|  } else {
 1382|    985|    if (options == base64_options::base64_default_accept_garbage) {
  ------------------
  |  Branch (1382:9): [True: 0, False: 985]
  ------------------
 1383|      0|      return base64::compress_decode_base64<false, true, false>(
 1384|      0|          output, input, length, options, last_chunk_options);
 1385|    985|    } else {
 1386|    985|      return base64::compress_decode_base64<false, false, false>(
 1387|    985|          output, input, length, options, last_chunk_options);
 1388|    985|    }
 1389|    985|  }
 1390|  2.00k|}
_ZNK7simdutf8westmere14implementation24base64_to_binary_detailsEPKDsmPcNS_14base64_optionsENS_27last_chunk_handling_optionsE:
 1394|  2.00k|    last_chunk_handling_options last_chunk_options) const noexcept {
 1395|  2.00k|  if (options & base64_default_or_url) {
  ------------------
  |  Branch (1395:7): [True: 0, False: 2.00k]
  ------------------
 1396|      0|    if (options == base64_options::base64_default_or_url_accept_garbage) {
  ------------------
  |  Branch (1396:9): [True: 0, False: 0]
  ------------------
 1397|      0|      return base64::compress_decode_base64<false, true, true>(
 1398|      0|          output, input, length, options, last_chunk_options);
 1399|      0|    } else {
 1400|      0|      return base64::compress_decode_base64<false, false, true>(
 1401|      0|          output, input, length, options, last_chunk_options);
 1402|      0|    }
 1403|  2.00k|  } else if (options & base64_url) {
  ------------------
  |  Branch (1403:14): [True: 1.01k, False: 985]
  ------------------
 1404|  1.01k|    if (options == base64_options::base64_url_accept_garbage) {
  ------------------
  |  Branch (1404:9): [True: 0, False: 1.01k]
  ------------------
 1405|      0|      return base64::compress_decode_base64<true, true, false>(
 1406|      0|          output, input, length, options, last_chunk_options);
 1407|  1.01k|    } else {
 1408|  1.01k|      return base64::compress_decode_base64<true, false, false>(
 1409|  1.01k|          output, input, length, options, last_chunk_options);
 1410|  1.01k|    }
 1411|  1.01k|  } else {
 1412|    985|    if (options == base64_options::base64_default_accept_garbage) {
  ------------------
  |  Branch (1412:9): [True: 0, False: 985]
  ------------------
 1413|      0|      return base64::compress_decode_base64<false, true, false>(
 1414|      0|          output, input, length, options, last_chunk_options);
 1415|    985|    } else {
 1416|    985|      return base64::compress_decode_base64<false, false, false>(
 1417|    985|          output, input, length, options, last_chunk_options);
 1418|    985|    }
 1419|    985|  }
 1420|  2.00k|}

simdutf.cpp:_ZN7simdutf8westmere12_GLOBAL__N_17block64C2EPKc:
  408|   338k|  simdutf_really_inline block64(const char *src) {
  409|   338k|    chunks[0] = _mm_loadu_si128(reinterpret_cast<const __m128i *>(src));
  410|   338k|    chunks[1] = _mm_loadu_si128(reinterpret_cast<const __m128i *>(src + 16));
  411|   338k|    chunks[2] = _mm_loadu_si128(reinterpret_cast<const __m128i *>(src + 32));
  412|   338k|    chunks[3] = _mm_loadu_si128(reinterpret_cast<const __m128i *>(src + 48));
  413|   338k|  }
simdutf.cpp:_ZN7simdutf8westmere12_GLOBAL__N_17block6419base64_decode_blockILb0EEEvPc:
  665|  60.1k|  simdutf_really_inline void base64_decode_block(char *out) {
  666|  60.1k|    base64_decode(out, chunks[0]);
  667|  60.1k|    base64_decode(out + 12, chunks[1]);
  668|  60.1k|    base64_decode(out + 24, chunks[2]);
  669|  60.1k|    base64_decode<exact>(out + 36, chunks[3]);
  670|  60.1k|  }
simdutf.cpp:_ZN7simdutf8westmere12_GLOBAL__N_113base64_decodeILb0EEEvPcDv2_x:
  369|  1.61M|static simdutf_really_inline void base64_decode(char *out, __m128i str) {
  370|       |  // credit: aqrit
  371|       |
  372|  1.61M|  const __m128i pack_shuffle =
  373|  1.61M|      _mm_setr_epi8(2, 1, 0, 6, 5, 4, 10, 9, 8, 14, 13, 12, -1, -1, -1, -1);
  374|       |
  375|  1.61M|  const __m128i t0 = _mm_maddubs_epi16(str, _mm_set1_epi32(0x01400140));
  376|  1.61M|  const __m128i t1 = _mm_madd_epi16(t0, _mm_set1_epi32(0x00011000));
  377|  1.61M|  const __m128i t2 = _mm_shuffle_epi8(t1, pack_shuffle);
  378|       |  if constexpr (exact) {
  379|       |    _mm_storel_epi64((__m128i *)out, t2);
  380|       |    const int32_t last = _mm_extract_epi32(t2, 2);
  381|       |    std::memcpy(out + 8, &last, sizeof(last));
  382|  1.61M|  } else {
  383|       |    // this writes 16 bytes, but we only need 12.
  384|  1.61M|    _mm_storeu_si128((__m128i *)out, t2);
  385|  1.61M|  }
  386|  1.61M|}
simdutf.cpp:_ZN7simdutf8westmere12_GLOBAL__N_17block6419base64_decode_blockILb1EEEvPc:
  665|  63.4k|  simdutf_really_inline void base64_decode_block(char *out) {
  666|  63.4k|    base64_decode(out, chunks[0]);
  667|  63.4k|    base64_decode(out + 12, chunks[1]);
  668|  63.4k|    base64_decode(out + 24, chunks[2]);
  669|  63.4k|    base64_decode<exact>(out + 36, chunks[3]);
  670|  63.4k|  }
simdutf.cpp:_ZN7simdutf8westmere12_GLOBAL__N_113base64_decodeILb1EEEvPcDv2_x:
  369|   125k|static simdutf_really_inline void base64_decode(char *out, __m128i str) {
  370|       |  // credit: aqrit
  371|       |
  372|   125k|  const __m128i pack_shuffle =
  373|   125k|      _mm_setr_epi8(2, 1, 0, 6, 5, 4, 10, 9, 8, 14, 13, 12, -1, -1, -1, -1);
  374|       |
  375|   125k|  const __m128i t0 = _mm_maddubs_epi16(str, _mm_set1_epi32(0x01400140));
  376|   125k|  const __m128i t1 = _mm_madd_epi16(t0, _mm_set1_epi32(0x00011000));
  377|   125k|  const __m128i t2 = _mm_shuffle_epi8(t1, pack_shuffle);
  378|   125k|  if constexpr (exact) {
  379|   125k|    _mm_storel_epi64((__m128i *)out, t2);
  380|   125k|    const int32_t last = _mm_extract_epi32(t2, 2);
  381|   125k|    std::memcpy(out + 8, &last, sizeof(last));
  382|       |  } else {
  383|       |    // this writes 16 bytes, but we only need 12.
  384|       |    _mm_storeu_si128((__m128i *)out, t2);
  385|       |  }
  386|   125k|}
simdutf.cpp:_ZN7simdutf8westmere12_GLOBAL__N_17block6414compress_blockEmPc:
  462|   164k|  simdutf_really_inline uint64_t compress_block(uint64_t mask, char *output) {
  463|   164k|    if (is_power_of_two(mask)) {
  ------------------
  |  Branch (463:9): [True: 127k, False: 37.6k]
  ------------------
  464|   127k|      return compress_block_single(mask, output);
  465|   127k|    }
  466|       |
  467|  37.6k|    uint64_t nmask = ~mask;
  468|  37.6k|    compress(chunks[0], uint16_t(mask), output);
  469|  37.6k|    compress(chunks[1], uint16_t(mask >> 16),
  470|  37.6k|             output + count_ones(nmask & 0xFFFF));
  471|  37.6k|    compress(chunks[2], uint16_t(mask >> 32),
  472|  37.6k|             output + count_ones(nmask & 0xFFFFFFFF));
  473|  37.6k|    compress(chunks[3], uint16_t(mask >> 48),
  474|  37.6k|             output + count_ones(nmask & 0xFFFFFFFFFFFFULL));
  475|  37.6k|    return count_ones(nmask);
  476|   164k|  }
simdutf.cpp:_ZN7simdutf8westmere12_GLOBAL__N_17block6421compress_block_singleEmPc:
  480|   127k|                                                     char *output) {
  481|   127k|    const size_t pos64 = trailing_zeroes(mask);
  482|   127k|    const int8_t pos = pos64 & 0xf;
  483|   127k|    switch (pos64 >> 4) {
  ------------------
  |  Branch (483:13): [True: 127k, False: 0]
  ------------------
  484|  30.9k|    case 0b00: {
  ------------------
  |  Branch (484:5): [True: 30.9k, False: 96.3k]
  ------------------
  485|  30.9k|      const __m128i v0 = _mm_set1_epi8(char(pos - 1));
  486|  30.9k|      const __m128i v1 =
  487|  30.9k|          _mm_setr_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
  488|  30.9k|      const __m128i v2 = _mm_cmpgt_epi8(v1, v0);
  489|  30.9k|      const __m128i sh = _mm_sub_epi8(v1, v2);
  490|  30.9k|      const __m128i compressed = _mm_shuffle_epi8(chunks[0], sh);
  491|       |
  492|  30.9k|      _mm_storeu_si128((__m128i *)(output + 0 * 16), compressed);
  493|  30.9k|      _mm_storeu_si128((__m128i *)(output + 1 * 16 - 1), chunks[1]);
  494|  30.9k|      _mm_storeu_si128((__m128i *)(output + 2 * 16 - 1), chunks[2]);
  495|  30.9k|      _mm_storeu_si128((__m128i *)(output + 3 * 16 - 1), chunks[3]);
  496|  30.9k|    } break;
  497|  33.0k|    case 0b01: {
  ------------------
  |  Branch (497:5): [True: 33.0k, False: 94.2k]
  ------------------
  498|  33.0k|      _mm_storeu_si128((__m128i *)(output + 0 * 16), chunks[0]);
  499|       |
  500|  33.0k|      const __m128i v0 = _mm_set1_epi8(char(pos - 1));
  501|  33.0k|      const __m128i v1 =
  502|  33.0k|          _mm_setr_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
  503|  33.0k|      const __m128i v2 = _mm_cmpgt_epi8(v1, v0);
  504|  33.0k|      const __m128i sh = _mm_sub_epi8(v1, v2);
  505|  33.0k|      const __m128i compressed = _mm_shuffle_epi8(chunks[1], sh);
  506|       |
  507|  33.0k|      _mm_storeu_si128((__m128i *)(output + 1 * 16), compressed);
  508|  33.0k|      _mm_storeu_si128((__m128i *)(output + 2 * 16 - 1), chunks[2]);
  509|  33.0k|      _mm_storeu_si128((__m128i *)(output + 3 * 16 - 1), chunks[3]);
  510|  33.0k|    } break;
  511|  32.7k|    case 0b10: {
  ------------------
  |  Branch (511:5): [True: 32.7k, False: 94.5k]
  ------------------
  512|  32.7k|      _mm_storeu_si128((__m128i *)(output + 0 * 16), chunks[0]);
  513|  32.7k|      _mm_storeu_si128((__m128i *)(output + 1 * 16), chunks[1]);
  514|       |
  515|  32.7k|      const __m128i v0 = _mm_set1_epi8(char(pos - 1));
  516|  32.7k|      const __m128i v1 =
  517|  32.7k|          _mm_setr_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
  518|  32.7k|      const __m128i v2 = _mm_cmpgt_epi8(v1, v0);
  519|  32.7k|      const __m128i sh = _mm_sub_epi8(v1, v2);
  520|  32.7k|      const __m128i compressed = _mm_shuffle_epi8(chunks[2], sh);
  521|       |
  522|  32.7k|      _mm_storeu_si128((__m128i *)(output + 2 * 16), compressed);
  523|  32.7k|      _mm_storeu_si128((__m128i *)(output + 3 * 16 - 1), chunks[3]);
  524|  32.7k|    } break;
  525|  30.5k|    case 0b11: {
  ------------------
  |  Branch (525:5): [True: 30.5k, False: 96.7k]
  ------------------
  526|  30.5k|      _mm_storeu_si128((__m128i *)(output + 0 * 16), chunks[0]);
  527|  30.5k|      _mm_storeu_si128((__m128i *)(output + 1 * 16), chunks[1]);
  528|  30.5k|      _mm_storeu_si128((__m128i *)(output + 2 * 16), chunks[2]);
  529|       |
  530|  30.5k|      const __m128i v0 = _mm_set1_epi8(char(pos - 1));
  531|  30.5k|      const __m128i v1 =
  532|  30.5k|          _mm_setr_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
  533|  30.5k|      const __m128i v2 = _mm_cmpgt_epi8(v1, v0);
  534|  30.5k|      const __m128i sh = _mm_sub_epi8(v1, v2);
  535|  30.5k|      const __m128i compressed = _mm_shuffle_epi8(chunks[3], sh);
  536|       |
  537|  30.5k|      _mm_storeu_si128((__m128i *)(output + 3 * 16), compressed);
  538|  30.5k|    } break;
  539|   127k|    }
  540|       |
  541|   127k|    return 63;
  542|   127k|  }
simdutf.cpp:_ZN7simdutf8westmere12_GLOBAL__N_18compressEDv2_xtPc:
  332|   150k|                                           char *output) {
  333|   150k|  if (mask == 0) {
  ------------------
  |  Branch (333:7): [True: 71.0k, False: 79.4k]
  ------------------
  334|  71.0k|    _mm_storeu_si128(reinterpret_cast<__m128i *>(output), data);
  335|  71.0k|    return;
  336|  71.0k|  }
  337|       |
  338|       |  // this particular implementation was inspired by work done by @animetosho
  339|       |  // we do it in two steps, first 8 bytes and then second 8 bytes
  340|  79.4k|  uint8_t mask1 = uint8_t(mask);      // least significant 8 bits
  341|  79.4k|  uint8_t mask2 = uint8_t(mask >> 8); // most significant 8 bits
  342|       |  // next line just loads the 64-bit values thintable_epi8[mask1] and
  343|       |  // thintable_epi8[mask2] into a 128-bit register, using only
  344|       |  // two instructions on most compilers.
  345|       |
  346|  79.4k|  __m128i shufmask = _mm_set_epi64x(tables::base64::thintable_epi8[mask2],
  347|  79.4k|                                    tables::base64::thintable_epi8[mask1]);
  348|       |  // we increment by 0x08 the second half of the mask
  349|  79.4k|  shufmask =
  350|  79.4k|      _mm_add_epi8(shufmask, _mm_set_epi32(0x08080808, 0x08080808, 0, 0));
  351|       |  // this is the version "nearly pruned"
  352|  79.4k|  __m128i pruned = _mm_shuffle_epi8(data, shufmask);
  353|       |  // we still need to put the two halves together.
  354|       |  // we compute the popcount of the first half:
  355|  79.4k|  int pop1 = tables::base64::BitsSetTable256mul2[mask1];
  356|       |  // then load the corresponding mask, what it does is to write
  357|       |  // only the first pop1 bytes from the first 8 bytes, and then
  358|       |  // it fills in with the bytes from the second 8 bytes + some filling
  359|       |  // at the end.
  360|  79.4k|  __m128i compactmask = _mm_loadu_si128(reinterpret_cast<const __m128i *>(
  361|  79.4k|      tables::base64::pshufb_combine_table + pop1 * 8));
  362|  79.4k|  __m128i answer = _mm_shuffle_epi8(pruned, compactmask);
  363|  79.4k|  _mm_storeu_si128(reinterpret_cast<__m128i *>(output), answer);
  364|  79.4k|}
simdutf.cpp:_ZN7simdutf8westmere12_GLOBAL__N_17block6410copy_blockEPc:
  454|   157k|  simdutf_really_inline void copy_block(char *output) {
  455|   157k|    _mm_storeu_si128(reinterpret_cast<__m128i *>(output), chunks[0]);
  456|   157k|    _mm_storeu_si128(reinterpret_cast<__m128i *>(output + 16), chunks[1]);
  457|   157k|    _mm_storeu_si128(reinterpret_cast<__m128i *>(output + 32), chunks[2]);
  458|   157k|    _mm_storeu_si128(reinterpret_cast<__m128i *>(output + 48), chunks[3]);
  459|   157k|  }
simdutf.cpp:_ZN7simdutf8westmere12_GLOBAL__N_119base64_decode_blockILb0EEEvPcPKc:
  390|   250k|static inline void base64_decode_block(char *out, const char *src) {
  391|   250k|  base64_decode(out, _mm_loadu_si128(reinterpret_cast<const __m128i *>(src)));
  392|   250k|  base64_decode(out + 12,
  393|   250k|                _mm_loadu_si128(reinterpret_cast<const __m128i *>(src + 16)));
  394|   250k|  base64_decode(out + 24,
  395|   250k|                _mm_loadu_si128(reinterpret_cast<const __m128i *>(src + 32)));
  396|   250k|  base64_decode<exact>(
  397|   250k|      out + 36, _mm_loadu_si128(reinterpret_cast<const __m128i *>(src + 48)));
  398|   250k|}
simdutf.cpp:_ZN7simdutf8westmere12_GLOBAL__N_119base64_decode_blockILb1EEEvPcPKc:
  390|  62.4k|static inline void base64_decode_block(char *out, const char *src) {
  391|  62.4k|  base64_decode(out, _mm_loadu_si128(reinterpret_cast<const __m128i *>(src)));
  392|  62.4k|  base64_decode(out + 12,
  393|  62.4k|                _mm_loadu_si128(reinterpret_cast<const __m128i *>(src + 16)));
  394|  62.4k|  base64_decode(out + 24,
  395|  62.4k|                _mm_loadu_si128(reinterpret_cast<const __m128i *>(src + 32)));
  396|  62.4k|  base64_decode<exact>(
  397|  62.4k|      out + 36, _mm_loadu_si128(reinterpret_cast<const __m128i *>(src + 48)));
  398|  62.4k|}
simdutf.cpp:_ZN7simdutf8westmere12_GLOBAL__N_17block6414to_base64_maskILb1ELb0ELb0EEEmPm:
  546|   152k|  simdutf_really_inline uint64_t to_base64_mask(uint64_t *error) {
  547|   152k|    uint32_t err0 = 0;
  548|   152k|    uint32_t err1 = 0;
  549|   152k|    uint32_t err2 = 0;
  550|   152k|    uint32_t err3 = 0;
  551|   152k|    uint64_t m0 = to_base64_mask<base64_url, ignore_garbage, default_or_url>(
  552|   152k|        &chunks[0], &err0);
  553|   152k|    uint64_t m1 = to_base64_mask<base64_url, ignore_garbage, default_or_url>(
  554|   152k|        &chunks[1], &err1);
  555|   152k|    uint64_t m2 = to_base64_mask<base64_url, ignore_garbage, default_or_url>(
  556|   152k|        &chunks[2], &err2);
  557|   152k|    uint64_t m3 = to_base64_mask<base64_url, ignore_garbage, default_or_url>(
  558|   152k|        &chunks[3], &err3);
  559|   152k|    if (!ignore_garbage) {
  ------------------
  |  Branch (559:9): [True: 152k, Folded]
  ------------------
  560|   152k|      *error = (err0) | ((uint64_t)err1 << 16) | ((uint64_t)err2 << 32) |
  561|   152k|               ((uint64_t)err3 << 48);
  562|   152k|    }
  563|   152k|    return m0 | (m1 << 16) | (m2 << 32) | (m3 << 48);
  564|   152k|  }
simdutf.cpp:_ZN7simdutf8westmere12_GLOBAL__N_17block6414to_base64_maskILb1ELb0ELb0EEEtPDv2_xPj:
  568|   611k|  simdutf_really_inline uint16_t to_base64_mask(__m128i *src, uint32_t *error) {
  569|   611k|    const __m128i ascii_space_tbl =
  570|   611k|        _mm_setr_epi8(0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9, 0xa,
  571|   611k|                      0x0, 0xc, 0xd, 0x0, 0x0);
  572|       |    // credit: aqrit
  573|   611k|    __m128i delta_asso;
  574|   611k|    if (default_or_url) {
  ------------------
  |  Branch (574:9): [Folded, False: 611k]
  ------------------
  575|      0|      delta_asso =
  576|      0|          _mm_setr_epi8(0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00,
  577|      0|                        0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x16);
  578|   611k|    } else if (base64_url) {
  ------------------
  |  Branch (578:16): [True: 611k, Folded]
  ------------------
  579|   611k|      delta_asso = _mm_setr_epi8(0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x0,
  580|   611k|                                 0x0, 0x0, 0x0, 0x0, 0xF, 0x0, 0xF);
  581|   611k|    } else {
  582|      0|      delta_asso =
  583|      0|          _mm_setr_epi8(0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00,
  584|      0|                        0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x0F);
  585|      0|    }
  586|   611k|    __m128i delta_values;
  587|   611k|    if (default_or_url) {
  ------------------
  |  Branch (587:9): [Folded, False: 611k]
  ------------------
  588|      0|      delta_values = _mm_setr_epi8(
  589|      0|          uint8_t(0xBF), uint8_t(0xE0), uint8_t(0xB9), uint8_t(0x13),
  590|      0|          uint8_t(0x04), uint8_t(0xBF), uint8_t(0xBF), uint8_t(0xB9),
  591|      0|          uint8_t(0xB9), uint8_t(0x00), uint8_t(0xFF), uint8_t(0x11),
  592|      0|          uint8_t(0xFF), uint8_t(0xBF), uint8_t(0x10), uint8_t(0xB9));
  593|       |
  594|   611k|    } else if (base64_url) {
  ------------------
  |  Branch (594:16): [True: 611k, Folded]
  ------------------
  595|   611k|      delta_values = _mm_setr_epi8(0x0, 0x0, 0x0, 0x13, 0x4, uint8_t(0xBF),
  596|   611k|                                   uint8_t(0xBF), uint8_t(0xB9), uint8_t(0xB9),
  597|   611k|                                   0x0, 0x11, uint8_t(0xC3), uint8_t(0xBF),
  598|   611k|                                   uint8_t(0xE0), uint8_t(0xB9), uint8_t(0xB9));
  599|   611k|    } else {
  600|      0|      delta_values =
  601|      0|          _mm_setr_epi8(int8_t(0x00), int8_t(0x00), int8_t(0x00), int8_t(0x13),
  602|      0|                        int8_t(0x04), int8_t(0xBF), int8_t(0xBF), int8_t(0xB9),
  603|      0|                        int8_t(0xB9), int8_t(0x00), int8_t(0x10), int8_t(0xC3),
  604|      0|                        int8_t(0xBF), int8_t(0xBF), int8_t(0xB9), int8_t(0xB9));
  605|      0|    }
  606|   611k|    __m128i check_asso;
  607|   611k|    if (default_or_url) {
  ------------------
  |  Branch (607:9): [Folded, False: 611k]
  ------------------
  608|      0|      check_asso =
  609|      0|          _mm_setr_epi8(0x0D, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  610|      0|                        0x01, 0x03, 0x07, 0x0B, 0x0E, 0x0B, 0x06);
  611|   611k|    } else if (base64_url) {
  ------------------
  |  Branch (611:16): [True: 611k, Folded]
  ------------------
  612|   611k|      check_asso = _mm_setr_epi8(0xD, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1,
  613|   611k|                                 0x1, 0x3, 0x7, 0xB, 0xE, 0xB, 0x6);
  614|   611k|    } else {
  615|      0|      check_asso =
  616|      0|          _mm_setr_epi8(0x0D, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  617|      0|                        0x01, 0x03, 0x07, 0x0B, 0x0B, 0x0B, 0x0F);
  618|      0|    }
  619|   611k|    __m128i check_values;
  620|   611k|    if (default_or_url) {
  ------------------
  |  Branch (620:9): [Folded, False: 611k]
  ------------------
  621|      0|      check_values = _mm_setr_epi8(
  622|      0|          uint8_t(0x80), uint8_t(0x80), uint8_t(0x80), uint8_t(0x80),
  623|      0|          uint8_t(0xCF), uint8_t(0xBF), uint8_t(0xD5), uint8_t(0xA6),
  624|      0|          uint8_t(0xB5), uint8_t(0xA1), uint8_t(0x00), uint8_t(0x80),
  625|      0|          uint8_t(0x00), uint8_t(0x80), uint8_t(0x00), uint8_t(0x80));
  626|   611k|    } else if (base64_url) {
  ------------------
  |  Branch (626:16): [True: 611k, Folded]
  ------------------
  627|   611k|      check_values = _mm_setr_epi8(uint8_t(0x80), uint8_t(0x80), uint8_t(0x80),
  628|   611k|                                   uint8_t(0x80), uint8_t(0xCF), uint8_t(0xBF),
  629|   611k|                                   uint8_t(0xB6), uint8_t(0xA6), uint8_t(0xB5),
  630|   611k|                                   uint8_t(0xA1), 0x0, uint8_t(0x80), 0x0,
  631|   611k|                                   uint8_t(0x80), 0x0, uint8_t(0x80));
  632|   611k|    } else {
  633|      0|      check_values =
  634|      0|          _mm_setr_epi8(int8_t(0x80), int8_t(0x80), int8_t(0x80), int8_t(0x80),
  635|      0|                        int8_t(0xCF), int8_t(0xBF), int8_t(0xD5), int8_t(0xA6),
  636|      0|                        int8_t(0xB5), int8_t(0x86), int8_t(0xD1), int8_t(0x80),
  637|      0|                        int8_t(0xB1), int8_t(0x80), int8_t(0x91), int8_t(0x80));
  638|      0|    }
  639|   611k|    const __m128i shifted = _mm_srli_epi32(*src, 3);
  640|       |
  641|   611k|    __m128i delta_hash =
  642|   611k|        _mm_avg_epu8(_mm_shuffle_epi8(delta_asso, *src), shifted);
  643|   611k|    if (default_or_url) {
  ------------------
  |  Branch (643:9): [Folded, False: 611k]
  ------------------
  644|      0|      delta_hash = _mm_and_si128(delta_hash, _mm_set1_epi8(0xf));
  645|      0|    }
  646|   611k|    const __m128i check_hash =
  647|   611k|        _mm_avg_epu8(_mm_shuffle_epi8(check_asso, *src), shifted);
  648|       |
  649|   611k|    const __m128i out =
  650|   611k|        _mm_adds_epi8(_mm_shuffle_epi8(delta_values, delta_hash), *src);
  651|   611k|    const __m128i chk =
  652|   611k|        _mm_adds_epi8(_mm_shuffle_epi8(check_values, check_hash), *src);
  653|   611k|    const int mask = _mm_movemask_epi8(chk);
  654|   611k|    if (!ignore_garbage && mask) {
  ------------------
  |  Branch (654:9): [True: 611k, Folded]
  |  Branch (654:28): [True: 95.3k, False: 516k]
  ------------------
  655|  95.3k|      __m128i ascii_space =
  656|  95.3k|          _mm_cmpeq_epi8(_mm_shuffle_epi8(ascii_space_tbl, *src), *src);
  657|  95.3k|      *error = (mask ^ _mm_movemask_epi8(ascii_space));
  658|  95.3k|    }
  659|   611k|    *src = out;
  660|   611k|    return (uint16_t)mask;
  661|   611k|  }
simdutf.cpp:_ZN7simdutf8westmere12_GLOBAL__N_17block6414to_base64_maskILb0ELb0ELb0EEEmPm:
  546|   303k|  simdutf_really_inline uint64_t to_base64_mask(uint64_t *error) {
  547|   303k|    uint32_t err0 = 0;
  548|   303k|    uint32_t err1 = 0;
  549|   303k|    uint32_t err2 = 0;
  550|   303k|    uint32_t err3 = 0;
  551|   303k|    uint64_t m0 = to_base64_mask<base64_url, ignore_garbage, default_or_url>(
  552|   303k|        &chunks[0], &err0);
  553|   303k|    uint64_t m1 = to_base64_mask<base64_url, ignore_garbage, default_or_url>(
  554|   303k|        &chunks[1], &err1);
  555|   303k|    uint64_t m2 = to_base64_mask<base64_url, ignore_garbage, default_or_url>(
  556|   303k|        &chunks[2], &err2);
  557|   303k|    uint64_t m3 = to_base64_mask<base64_url, ignore_garbage, default_or_url>(
  558|   303k|        &chunks[3], &err3);
  559|   303k|    if (!ignore_garbage) {
  ------------------
  |  Branch (559:9): [True: 303k, Folded]
  ------------------
  560|   303k|      *error = (err0) | ((uint64_t)err1 << 16) | ((uint64_t)err2 << 32) |
  561|   303k|               ((uint64_t)err3 << 48);
  562|   303k|    }
  563|   303k|    return m0 | (m1 << 16) | (m2 << 32) | (m3 << 48);
  564|   303k|  }
simdutf.cpp:_ZN7simdutf8westmere12_GLOBAL__N_17block6414to_base64_maskILb0ELb0ELb0EEEtPDv2_xPj:
  568|  1.21M|  simdutf_really_inline uint16_t to_base64_mask(__m128i *src, uint32_t *error) {
  569|  1.21M|    const __m128i ascii_space_tbl =
  570|  1.21M|        _mm_setr_epi8(0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9, 0xa,
  571|  1.21M|                      0x0, 0xc, 0xd, 0x0, 0x0);
  572|       |    // credit: aqrit
  573|  1.21M|    __m128i delta_asso;
  574|  1.21M|    if (default_or_url) {
  ------------------
  |  Branch (574:9): [Folded, False: 1.21M]
  ------------------
  575|      0|      delta_asso =
  576|      0|          _mm_setr_epi8(0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00,
  577|      0|                        0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x16);
  578|  1.21M|    } else if (base64_url) {
  ------------------
  |  Branch (578:16): [Folded, False: 1.21M]
  ------------------
  579|      0|      delta_asso = _mm_setr_epi8(0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x0,
  580|      0|                                 0x0, 0x0, 0x0, 0x0, 0xF, 0x0, 0xF);
  581|  1.21M|    } else {
  582|  1.21M|      delta_asso =
  583|  1.21M|          _mm_setr_epi8(0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00,
  584|  1.21M|                        0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x0F);
  585|  1.21M|    }
  586|  1.21M|    __m128i delta_values;
  587|  1.21M|    if (default_or_url) {
  ------------------
  |  Branch (587:9): [Folded, False: 1.21M]
  ------------------
  588|      0|      delta_values = _mm_setr_epi8(
  589|      0|          uint8_t(0xBF), uint8_t(0xE0), uint8_t(0xB9), uint8_t(0x13),
  590|      0|          uint8_t(0x04), uint8_t(0xBF), uint8_t(0xBF), uint8_t(0xB9),
  591|      0|          uint8_t(0xB9), uint8_t(0x00), uint8_t(0xFF), uint8_t(0x11),
  592|      0|          uint8_t(0xFF), uint8_t(0xBF), uint8_t(0x10), uint8_t(0xB9));
  593|       |
  594|  1.21M|    } else if (base64_url) {
  ------------------
  |  Branch (594:16): [Folded, False: 1.21M]
  ------------------
  595|      0|      delta_values = _mm_setr_epi8(0x0, 0x0, 0x0, 0x13, 0x4, uint8_t(0xBF),
  596|      0|                                   uint8_t(0xBF), uint8_t(0xB9), uint8_t(0xB9),
  597|      0|                                   0x0, 0x11, uint8_t(0xC3), uint8_t(0xBF),
  598|      0|                                   uint8_t(0xE0), uint8_t(0xB9), uint8_t(0xB9));
  599|  1.21M|    } else {
  600|  1.21M|      delta_values =
  601|  1.21M|          _mm_setr_epi8(int8_t(0x00), int8_t(0x00), int8_t(0x00), int8_t(0x13),
  602|  1.21M|                        int8_t(0x04), int8_t(0xBF), int8_t(0xBF), int8_t(0xB9),
  603|  1.21M|                        int8_t(0xB9), int8_t(0x00), int8_t(0x10), int8_t(0xC3),
  604|  1.21M|                        int8_t(0xBF), int8_t(0xBF), int8_t(0xB9), int8_t(0xB9));
  605|  1.21M|    }
  606|  1.21M|    __m128i check_asso;
  607|  1.21M|    if (default_or_url) {
  ------------------
  |  Branch (607:9): [Folded, False: 1.21M]
  ------------------
  608|      0|      check_asso =
  609|      0|          _mm_setr_epi8(0x0D, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  610|      0|                        0x01, 0x03, 0x07, 0x0B, 0x0E, 0x0B, 0x06);
  611|  1.21M|    } else if (base64_url) {
  ------------------
  |  Branch (611:16): [Folded, False: 1.21M]
  ------------------
  612|      0|      check_asso = _mm_setr_epi8(0xD, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1,
  613|      0|                                 0x1, 0x3, 0x7, 0xB, 0xE, 0xB, 0x6);
  614|  1.21M|    } else {
  615|  1.21M|      check_asso =
  616|  1.21M|          _mm_setr_epi8(0x0D, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  617|  1.21M|                        0x01, 0x03, 0x07, 0x0B, 0x0B, 0x0B, 0x0F);
  618|  1.21M|    }
  619|  1.21M|    __m128i check_values;
  620|  1.21M|    if (default_or_url) {
  ------------------
  |  Branch (620:9): [Folded, False: 1.21M]
  ------------------
  621|      0|      check_values = _mm_setr_epi8(
  622|      0|          uint8_t(0x80), uint8_t(0x80), uint8_t(0x80), uint8_t(0x80),
  623|      0|          uint8_t(0xCF), uint8_t(0xBF), uint8_t(0xD5), uint8_t(0xA6),
  624|      0|          uint8_t(0xB5), uint8_t(0xA1), uint8_t(0x00), uint8_t(0x80),
  625|      0|          uint8_t(0x00), uint8_t(0x80), uint8_t(0x00), uint8_t(0x80));
  626|  1.21M|    } else if (base64_url) {
  ------------------
  |  Branch (626:16): [Folded, False: 1.21M]
  ------------------
  627|      0|      check_values = _mm_setr_epi8(uint8_t(0x80), uint8_t(0x80), uint8_t(0x80),
  628|      0|                                   uint8_t(0x80), uint8_t(0xCF), uint8_t(0xBF),
  629|      0|                                   uint8_t(0xB6), uint8_t(0xA6), uint8_t(0xB5),
  630|      0|                                   uint8_t(0xA1), 0x0, uint8_t(0x80), 0x0,
  631|      0|                                   uint8_t(0x80), 0x0, uint8_t(0x80));
  632|  1.21M|    } else {
  633|  1.21M|      check_values =
  634|  1.21M|          _mm_setr_epi8(int8_t(0x80), int8_t(0x80), int8_t(0x80), int8_t(0x80),
  635|  1.21M|                        int8_t(0xCF), int8_t(0xBF), int8_t(0xD5), int8_t(0xA6),
  636|  1.21M|                        int8_t(0xB5), int8_t(0x86), int8_t(0xD1), int8_t(0x80),
  637|  1.21M|                        int8_t(0xB1), int8_t(0x80), int8_t(0x91), int8_t(0x80));
  638|  1.21M|    }
  639|  1.21M|    const __m128i shifted = _mm_srli_epi32(*src, 3);
  640|       |
  641|  1.21M|    __m128i delta_hash =
  642|  1.21M|        _mm_avg_epu8(_mm_shuffle_epi8(delta_asso, *src), shifted);
  643|  1.21M|    if (default_or_url) {
  ------------------
  |  Branch (643:9): [Folded, False: 1.21M]
  ------------------
  644|      0|      delta_hash = _mm_and_si128(delta_hash, _mm_set1_epi8(0xf));
  645|      0|    }
  646|  1.21M|    const __m128i check_hash =
  647|  1.21M|        _mm_avg_epu8(_mm_shuffle_epi8(check_asso, *src), shifted);
  648|       |
  649|  1.21M|    const __m128i out =
  650|  1.21M|        _mm_adds_epi8(_mm_shuffle_epi8(delta_values, delta_hash), *src);
  651|  1.21M|    const __m128i chk =
  652|  1.21M|        _mm_adds_epi8(_mm_shuffle_epi8(check_values, check_hash), *src);
  653|  1.21M|    const int mask = _mm_movemask_epi8(chk);
  654|  1.21M|    if (!ignore_garbage && mask) {
  ------------------
  |  Branch (654:9): [True: 1.21M, Folded]
  |  Branch (654:28): [True: 138k, False: 1.07M]
  ------------------
  655|   138k|      __m128i ascii_space =
  656|   138k|          _mm_cmpeq_epi8(_mm_shuffle_epi8(ascii_space_tbl, *src), *src);
  657|   138k|      *error = (mask ^ _mm_movemask_epi8(ascii_space));
  658|   138k|    }
  659|  1.21M|    *src = out;
  660|  1.21M|    return (uint16_t)mask;
  661|  1.21M|  }
simdutf.cpp:_ZN7simdutf8westmere12_GLOBAL__N_17block64C2EPKDs:
  419|   118k|  simdutf_really_inline block64(const char16_t *src) {
  420|   118k|    const auto m1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(src));
  421|   118k|    const auto m2 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(src + 8));
  422|   118k|    const auto m3 =
  423|   118k|        _mm_loadu_si128(reinterpret_cast<const __m128i *>(src + 16));
  424|   118k|    const auto m4 =
  425|   118k|        _mm_loadu_si128(reinterpret_cast<const __m128i *>(src + 24));
  426|   118k|    const auto m5 =
  427|   118k|        _mm_loadu_si128(reinterpret_cast<const __m128i *>(src + 32));
  428|   118k|    const auto m6 =
  429|   118k|        _mm_loadu_si128(reinterpret_cast<const __m128i *>(src + 40));
  430|   118k|    const auto m7 =
  431|   118k|        _mm_loadu_si128(reinterpret_cast<const __m128i *>(src + 48));
  432|   118k|    const auto m8 =
  433|   118k|        _mm_loadu_si128(reinterpret_cast<const __m128i *>(src + 56));
  434|   118k|    chunks[0] = _mm_packus_epi16(m1, m2);
  435|   118k|    chunks[1] = _mm_packus_epi16(m3, m4);
  436|   118k|    chunks[2] = _mm_packus_epi16(m5, m6);
  437|   118k|    chunks[3] = _mm_packus_epi16(m7, m8);
  438|   118k|  }

_ZNK7simdutf11full_resultcvNS_6resultEEv:
  117|  24.2k|  simdutf_really_inline simdutf_constexpr23 operator result() const noexcept {
  118|  24.2k|    if (error == error_code::SUCCESS) {
  ------------------
  |  Branch (118:9): [True: 7.96k, False: 16.2k]
  ------------------
  119|  7.96k|      return result{error, output_count};
  120|  16.2k|    } else {
  121|  16.2k|      return result{error, input_count};
  122|  16.2k|    }
  123|  24.2k|  }
_ZN7simdutf6resultC2ENS_10error_codeEm:
   87|  24.2k|      : error{err}, count{pos} {}

