_ZN7httplib6detail17gzip_decompressorD2Ev:
 8029|    129|inline gzip_decompressor::~gzip_decompressor() { inflateEnd(&strm_); }
_ZN7httplib10ClientImplD2Ev:
15333|  3.02k|inline ClientImpl::~ClientImpl() {
15334|       |  // Wait until all the requests in flight are handled.
15335|  3.02k|  size_t retry_count = 10;
15336|  3.02k|  while (retry_count-- > 0) {
  ------------------
  |  Branch (15336:10): [True: 3.02k, False: 0]
  ------------------
15337|  3.02k|    {
15338|  3.02k|      std::lock_guard<std::mutex> guard(socket_mutex_);
15339|  3.02k|      if (socket_requests_in_flight_ == 0) { break; }
  ------------------
  |  Branch (15339:11): [True: 3.02k, False: 0]
  ------------------
15340|  3.02k|    }
15341|      0|    std::this_thread::sleep_for(std::chrono::milliseconds{1});
15342|      0|  }
15343|       |
15344|  3.02k|  std::lock_guard<std::mutex> guard(socket_mutex_);
15345|  3.02k|  shutdown_socket(socket_);
15346|  3.02k|  close_socket(socket_);
15347|  3.02k|}
_ZN7httplib6detail12decompressorD2Ev:
 3867|    129|  virtual ~decompressor() = default;
_ZN7httplib6StreamD2Ev:
 1997|  6.05k|  virtual ~Stream() = default;
_ZNK7httplib10ClientImpl15shutdown_socketERNS0_6SocketE:
15416|  3.02k|inline void ClientImpl::shutdown_socket(Socket &socket) const {
15417|  3.02k|  if (socket.sock == INVALID_SOCKET) { return; }
  ------------------
  |  |  375|  3.02k|#define INVALID_SOCKET (-1)
  ------------------
  |  Branch (15417:7): [True: 3.02k, False: 0]
  ------------------
15418|      0|  detail::shutdown_socket(socket.sock);
15419|      0|}
_ZN7httplib10ClientImpl12close_socketERNS0_6SocketE:
15421|  3.02k|inline void ClientImpl::close_socket(Socket &socket) {
15422|       |  // If there are requests in flight in another thread, usually closing
15423|       |  // the socket will be fine and they will simply receive an error when
15424|       |  // using the closed socket, but it is still a bug since rarely the OS
15425|       |  // may reassign the socket id to be used for a new socket, and then
15426|       |  // suddenly they will be operating on a live socket that is different
15427|       |  // than the one they intended!
15428|  3.02k|  assert(socket_requests_in_flight_ == 0 ||
  ------------------
  |  Branch (15428:3): [True: 3.02k, False: 0]
  |  Branch (15428:3): [True: 0, False: 0]
  |  Branch (15428:3): [True: 3.02k, False: 0]
  ------------------
15429|  3.02k|         socket_requests_are_from_thread_ == std::this_thread::get_id());
15430|       |
15431|       |  // It is also a bug if this happens while SSL is still active
15432|       |#ifdef CPPHTTPLIB_SSL_ENABLED
15433|       |  assert(socket.ssl == nullptr);
15434|       |#endif
15435|       |
15436|  3.02k|  if (socket.sock == INVALID_SOCKET) { return; }
  ------------------
  |  |  375|  3.02k|#define INVALID_SOCKET (-1)
  ------------------
  |  Branch (15436:7): [True: 3.02k, False: 0]
  ------------------
15437|      0|  detail::close_socket(socket.sock);
15438|      0|  socket.sock = INVALID_SOCKET;
  ------------------
  |  |  375|      0|#define INVALID_SOCKET (-1)
  ------------------
15439|      0|}
_ZN7httplib10ClientImplC2ERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEi:
15325|  3.02k|    : ClientImpl(host, port, std::string(), std::string()) {}
_ZN7httplib10ClientImplC2ERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEiS9_S9_:
15330|  3.02k|    : host_(detail::escape_abstract_namespace_unix_domain(host)), port_(port),
15331|  3.02k|      client_cert_path_(client_cert_path), client_key_path_(client_key_path) {}
_ZN7httplib6detail37escape_abstract_namespace_unix_domainERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
 6939|  3.02k|inline std::string escape_abstract_namespace_unix_domain(const std::string &s) {
 6940|  3.02k|  if (s.size() > 1 && s[0] == '\0') {
  ------------------
  |  Branch (6940:7): [True: 3.02k, False: 0]
  |  Branch (6940:23): [True: 0, False: 3.02k]
  ------------------
 6941|      0|    auto ret = s;
 6942|      0|    ret[0] = '@';
 6943|      0|    return ret;
 6944|      0|  }
 6945|  3.02k|  return s;
 6946|  3.02k|}
_ZN7httplib6detail26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEEC2Ev:
 1249|  16.7k|  insertion_ordered_multimap() = default;
_ZN7httplib6detail13write_headersERNS_6StreamERKNS0_26insertion_ordered_multimapINSt3__112basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEENS0_11case_ignore8equal_toEEE:
 8841|  3.02k|inline ssize_t write_headers(Stream &strm, const Headers &headers) {
 8842|  3.02k|  ssize_t write_len = 0;
 8843|  14.0k|  for (const auto &x : headers) {
  ------------------
  |  Branch (8843:22): [True: 14.0k, False: 3.02k]
  ------------------
 8844|       |    // Skip fields with invalid names or values to prevent response splitting
 8845|       |    // via CR/LF injection, matching set_header(). The client validates request
 8846|       |    // headers up front in check_and_write_headers, but the server passes
 8847|       |    // res.headers straight to this writer, and res.headers is a public field
 8848|       |    // an application can populate directly with request-derived values.
 8849|  14.0k|    if (!fields::is_field_valid(x.first, x.second)) { continue; }
  ------------------
  |  Branch (8849:9): [True: 0, False: 14.0k]
  ------------------
 8850|       |
 8851|  14.0k|    std::string s;
 8852|  14.0k|    s = x.first;
 8853|  14.0k|    s += ": ";
 8854|  14.0k|    s += x.second;
 8855|  14.0k|    s += "\r\n";
 8856|       |
 8857|  14.0k|    auto len = strm.write(s.data(), s.size());
 8858|  14.0k|    if (len < 0) { return len; }
  ------------------
  |  Branch (8858:9): [True: 0, False: 14.0k]
  ------------------
 8859|  14.0k|    write_len += len;
 8860|  14.0k|  }
 8861|  3.02k|  auto len = strm.write("\r\n");
 8862|  3.02k|  if (len < 0) { return len; }
  ------------------
  |  Branch (8862:7): [True: 0, False: 3.02k]
  ------------------
 8863|  3.02k|  write_len += len;
 8864|  3.02k|  return write_len;
 8865|  3.02k|}
_ZNK7httplib6detail26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEE5beginEv:
 1258|  3.02k|  const_iterator begin() const { return make_citer(0, npos()); }
_ZNK7httplib6detail26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEE10make_citerEmm:
 1391|  75.9k|  const_iterator make_citer(size_type idx, size_type key_idx) const {
 1392|  75.9k|    return const_iterator(entries_.data(), idx, entries_.size(), key_idx);
 1393|  75.9k|  }
_ZN7httplib6detail26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEE10iterator_tIKNS2_4pairIS8_S8_EEEC2EPSF_mmm:
 1233|  75.9k|        : data_(data), idx_(idx), size_(size), key_idx_(key_idx) {}
_ZN7httplib6detail26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEE4nposEv:
 1153|   214k|  static size_type npos() { return static_cast<size_type>(-1); }
_ZNK7httplib6detail26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEE3endEv:
 1259|  68.2k|  const_iterator end() const { return make_citer(entries_.size(), npos()); }
_ZNK7httplib6detail26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEE10iterator_tIKNS2_4pairIS8_S8_EEEneISF_EEbRKNSC_IT_EE:
 1224|  53.4k|    template <typename U> bool operator!=(const iterator_t<U> &rhs) const {
 1225|  53.4k|      return idx_ != rhs.idx_;
 1226|  53.4k|    }
_ZNK7httplib6detail26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEE10iterator_tIKNS2_4pairIS8_S8_EEEdeEv:
 1181|  14.0k|    reference operator*() const { return data_[idx_]; }
_ZN7httplib6detail6fields14is_field_validERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEESA_:
10522|  36.0k|inline bool is_field_valid(const std::string &name, const std::string &value) {
10523|  36.0k|  return is_field_name(name) && is_field_value(value);
  ------------------
  |  Branch (10523:10): [True: 36.0k, False: 0]
  |  Branch (10523:33): [True: 36.0k, False: 0]
  ------------------
10524|  36.0k|}
_ZN7httplib6detail6fields13is_field_nameERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE:
10487|  47.5k|inline bool is_field_name(const std::string &s) { return is_token(s); }
_ZN7httplib6detail6fields8is_tokenERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE:
10479|  50.5k|inline bool is_token(const std::string &s) {
10480|  50.5k|  if (s.empty()) { return false; }
  ------------------
  |  Branch (10480:7): [True: 63, False: 50.5k]
  ------------------
10481|   529k|  for (auto c : s) {
  ------------------
  |  Branch (10481:15): [True: 529k, False: 50.3k]
  ------------------
10482|   529k|    if (!is_token_char(c)) { return false; }
  ------------------
  |  Branch (10482:9): [True: 169, False: 529k]
  ------------------
10483|   529k|  }
10484|  50.3k|  return true;
10485|  50.5k|}
_ZN7httplib6detail6fields13is_token_charEc:
10473|   529k|inline bool is_token_char(char c) {
10474|   529k|  return is_ascii_alnum(c) || c == '!' || c == '#' || c == '$' || c == '%' ||
  ------------------
  |  Branch (10474:10): [True: 487k, False: 42.0k]
  |  Branch (10474:31): [True: 856, False: 41.2k]
  |  Branch (10474:43): [True: 1.03k, False: 40.1k]
  |  Branch (10474:55): [True: 651, False: 39.5k]
  |  Branch (10474:67): [True: 450, False: 39.0k]
  ------------------
10475|  39.0k|         c == '&' || c == '\'' || c == '*' || c == '+' || c == '-' ||
  ------------------
  |  Branch (10475:10): [True: 499, False: 38.5k]
  |  Branch (10475:22): [True: 424, False: 38.1k]
  |  Branch (10475:35): [True: 1.05k, False: 37.0k]
  |  Branch (10475:47): [True: 1.06k, False: 36.0k]
  |  Branch (10475:59): [True: 29.6k, False: 6.37k]
  ------------------
10476|  6.37k|         c == '.' || c == '^' || c == '_' || c == '`' || c == '|' || c == '~';
  ------------------
  |  Branch (10476:10): [True: 843, False: 5.53k]
  |  Branch (10476:22): [True: 1.83k, False: 3.69k]
  |  Branch (10476:34): [True: 1.56k, False: 2.13k]
  |  Branch (10476:46): [True: 480, False: 1.65k]
  |  Branch (10476:58): [True: 606, False: 1.04k]
  |  Branch (10476:70): [True: 878, False: 169]
  ------------------
10477|   529k|}
_ZN7httplib6detail14is_ascii_alnumEc:
  648|   529k|inline bool is_ascii_alnum(char c) {
  649|   529k|  return is_ascii_digit(c) || is_ascii_alpha(c);
  ------------------
  |  Branch (649:10): [True: 14.3k, False: 515k]
  |  Branch (649:31): [True: 473k, False: 42.0k]
  ------------------
  650|   529k|}
_ZN7httplib6detail14is_ascii_digitEc:
  642|   581k|inline bool is_ascii_digit(char c) { return '0' <= c && c <= '9'; }
  ------------------
  |  Branch (642:45): [True: 542k, False: 39.1k]
  |  Branch (642:57): [True: 60.4k, False: 482k]
  ------------------
_ZN7httplib6detail14is_ascii_alphaEc:
  644|   515k|inline bool is_ascii_alpha(char c) {
  645|   515k|  return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z');
  ------------------
  |  Branch (645:11): [True: 379k, False: 135k]
  |  Branch (645:23): [True: 378k, False: 1.48k]
  |  Branch (645:37): [True: 100k, False: 36.6k]
  |  Branch (645:49): [True: 95.1k, False: 5.37k]
  ------------------
  646|   515k|}
_ZN7httplib6detail6fields14is_field_valueERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE:
10520|  47.1k|inline bool is_field_value(const std::string &s) { return is_field_content(s); }
_ZN7httplib6detail6fields16is_field_contentERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE:
10495|  47.1k|inline bool is_field_content(const std::string &s) {
10496|  47.1k|  if (s.empty()) { return true; }
  ------------------
  |  Branch (10496:7): [True: 6.81k, False: 40.3k]
  ------------------
10497|       |
10498|  40.3k|  if (s.size() == 1) {
  ------------------
  |  Branch (10498:7): [True: 6.66k, False: 33.6k]
  ------------------
10499|  6.66k|    return is_field_vchar(s[0]);
10500|  33.6k|  } else if (s.size() == 2) {
  ------------------
  |  Branch (10500:14): [True: 322, False: 33.3k]
  ------------------
10501|    322|    return is_field_vchar(s[0]) && is_field_vchar(s[1]);
  ------------------
  |  Branch (10501:12): [True: 320, False: 2]
  |  Branch (10501:36): [True: 318, False: 2]
  ------------------
10502|  33.3k|  } else {
10503|  33.3k|    size_t i = 0;
10504|       |
10505|  33.3k|    if (!is_field_vchar(s[i])) { return false; }
  ------------------
  |  Branch (10505:9): [True: 3, False: 33.3k]
  ------------------
10506|  33.3k|    i++;
10507|       |
10508|  2.39M|    while (i < s.size() - 1) {
  ------------------
  |  Branch (10508:12): [True: 2.36M, False: 33.2k]
  ------------------
10509|  2.36M|      auto c = s[i++];
10510|  2.36M|      if (c == ' ' || c == '\t' || is_field_vchar(c)) {
  ------------------
  |  Branch (10510:11): [True: 21.2k, False: 2.34M]
  |  Branch (10510:23): [True: 2.44k, False: 2.34M]
  |  Branch (10510:36): [True: 2.34M, False: 27]
  ------------------
10511|  2.36M|      } else {
10512|     27|        return false;
10513|     27|      }
10514|  2.36M|    }
10515|       |
10516|  33.2k|    return is_field_vchar(s[i]);
10517|  33.3k|  }
10518|  40.3k|}
_ZN7httplib6detail6fields14is_field_vcharEc:
10493|  2.44M|inline bool is_field_vchar(char c) { return is_vchar(c) || is_obs_text(c); }
  ------------------
  |  Branch (10493:45): [True: 1.46M, False: 978k]
  |  Branch (10493:60): [True: 978k, False: 75]
  ------------------
_ZN7httplib6detail6fields8is_vcharEc:
10489|  2.44M|inline bool is_vchar(char c) { return c >= 33 && c <= 126; }
  ------------------
  |  Branch (10489:39): [True: 1.46M, False: 978k]
  |  Branch (10489:50): [True: 1.46M, False: 4]
  ------------------
_ZN7httplib6detail6fields11is_obs_textEc:
10491|   978k|inline bool is_obs_text(char c) { return 128 <= static_cast<unsigned char>(c); }
_ZN7httplib6detail26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEE10iterator_tIKNS2_4pairIS8_S8_EEEppEv:
 1184|  16.0k|    iterator_t &operator++() {
 1185|       |      // Saturating, so that advancing past the last entry of a key stays at
 1186|       |      // end() instead of running off the container.
 1187|  16.0k|      if (idx_ >= size_) { return *this; }
  ------------------
  |  Branch (1187:11): [True: 0, False: 16.0k]
  ------------------
 1188|  16.0k|      ++idx_;
 1189|  16.0k|      if (key_idx_ != npos()) {
  ------------------
  |  Branch (1189:11): [True: 2.04k, False: 14.0k]
  ------------------
 1190|  2.58k|        while (idx_ < size_ && !matches(idx_)) {
  ------------------
  |  Branch (1190:16): [True: 1.59k, False: 984]
  |  Branch (1190:32): [True: 540, False: 1.05k]
  ------------------
 1191|    540|          ++idx_;
 1192|    540|        }
 1193|  2.04k|      }
 1194|  16.0k|      return *this;
 1195|  16.0k|    }
_ZNK7httplib6detail26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEE10iterator_tIKNS2_4pairIS8_S8_EEE7matchesEm:
 1235|  1.59k|    bool matches(size_type i) const {
 1236|  1.59k|      return keys_equal(data_[i].first, data_[key_idx_].first);
 1237|  1.59k|    }
_ZN7httplib6detail26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEE10keys_equalERKS8_SD_:
 1155|  70.4k|  static bool keys_equal(const std::string &a, const std::string &b) {
 1156|  70.4k|    return KeyEqual()(a, b);
 1157|  70.4k|  }
_ZNK7httplib6detail11case_ignore8equal_toclERKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEESB_:
  703|  70.4k|  bool operator()(const std::string &a, const std::string &b) const {
  704|  70.4k|    return equal(a, b);
  705|  70.4k|  }
_ZN7httplib6detail11case_ignore5equalERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEESA_:
  686|  70.4k|inline bool equal(const std::string &a, const std::string &b) {
  687|  70.4k|  return a.size() == b.size() &&
  ------------------
  |  Branch (687:10): [True: 10.3k, False: 60.1k]
  ------------------
  688|  10.3k|         std::equal(a.begin(), a.end(), b.begin(), [](char ca, char cb) {
  ------------------
  |  Branch (688:10): [True: 7.33k, False: 3.00k]
  ------------------
  689|  10.3k|           return to_lower(ca) == to_lower(cb);
  690|  10.3k|         });
  691|  70.4k|}
_ZZN7httplib6detail11case_ignore5equalERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEESA_ENKUlccE_clEcc:
  688|   133k|         std::equal(a.begin(), a.end(), b.begin(), [](char ca, char cb) {
  689|   133k|           return to_lower(ca) == to_lower(cb);
  690|   133k|         });
_ZN7httplib6detail11case_ignore8to_lowerEi:
  654|   288k|inline unsigned char to_lower(int c) {
  655|   288k|  const static unsigned char table[256] = {
  656|   288k|      0,   1,   2,   3,   4,   5,   6,   7,   8,   9,   10,  11,  12,  13,  14,
  657|   288k|      15,  16,  17,  18,  19,  20,  21,  22,  23,  24,  25,  26,  27,  28,  29,
  658|   288k|      30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,  43,  44,
  659|   288k|      45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,
  660|   288k|      60,  61,  62,  63,  64,  97,  98,  99,  100, 101, 102, 103, 104, 105, 106,
  661|   288k|      107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121,
  662|   288k|      122, 91,  92,  93,  94,  95,  96,  97,  98,  99,  100, 101, 102, 103, 104,
  663|   288k|      105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
  664|   288k|      120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134,
  665|   288k|      135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
  666|   288k|      150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164,
  667|   288k|      165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179,
  668|   288k|      180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 224, 225, 226,
  669|   288k|      227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241,
  670|   288k|      242, 243, 244, 245, 246, 215, 248, 249, 250, 251, 252, 253, 254, 223, 224,
  671|   288k|      225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
  672|   288k|      240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254,
  673|   288k|      255,
  674|   288k|  };
  675|   288k|  return table[(unsigned char)(char)c];
  676|   288k|}
_ZN7httplib6Stream5writeEPKc:
12293|  3.02k|inline ssize_t Stream::write(const char *ptr) {
12294|  3.02k|  return write(ptr, strlen(ptr));
12295|  3.02k|}
_ZN7httplib6detail26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS2_8equal_toIS8_EEEC2Ev:
 1249|  3.02k|  insertion_ordered_multimap() = default;
_ZN7httplib6detail26insertion_ordered_multimapINS_9FormFieldENSt3__18equal_toINS3_12basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEEEEC2Ev:
 1249|  3.02k|  insertion_ordered_multimap() = default;
_ZN7httplib6detail26insertion_ordered_multimapINS_8FormDataENSt3__18equal_toINS3_12basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEEEEC2Ev:
 1249|  3.02k|  insertion_ordered_multimap() = default;
_ZN7httplib8ResponseC2Ev:
 1919|  3.02k|  Response() = default;
_ZN7httplib8UserDataC2Ev:
 1445|  3.02k|  UserData() = default;
_ZN7httplib10ClientImpl15process_requestERNS_6StreamERNS_7RequestERNS_8ResponseEbRNS_5ErrorE:
16724|  3.02k|                                        Error &error) {
16725|       |  // Auto-add Expect: 100-continue for large bodies
16726|  3.02k|  if (CPPHTTPLIB_EXPECT_100_THRESHOLD > 0 && !req.has_header("Expect")) {
  ------------------
  |  |   90|  3.02k|#define CPPHTTPLIB_EXPECT_100_THRESHOLD 1024
  ------------------
  |  Branch (16726:7): [True: 3.02k, Folded]
  |  Branch (16726:7): [True: 3.02k, False: 0]
  |  Branch (16726:46): [True: 3.02k, False: 0]
  ------------------
16727|  3.02k|    auto body_size = req.body.empty() ? req.content_length_ : req.body.size();
  ------------------
  |  Branch (16727:22): [True: 3.02k, False: 0]
  ------------------
16728|  3.02k|    if (body_size >= CPPHTTPLIB_EXPECT_100_THRESHOLD) {
  ------------------
  |  |   90|  3.02k|#define CPPHTTPLIB_EXPECT_100_THRESHOLD 1024
  ------------------
  |  Branch (16728:9): [True: 0, False: 3.02k]
  ------------------
16729|      0|      req.set_header("Expect", "100-continue");
16730|      0|    }
16731|  3.02k|  }
16732|       |
16733|       |  // Check for Expect: 100-continue
16734|  3.02k|  auto expect_100_continue =
16735|  3.02k|      detail::has_header_token(req.headers, "Expect", "100-continue");
16736|       |
16737|       |  // Send request (skip body if using Expect: 100-continue)
16738|  3.02k|  auto rejected_locally = false;
16739|  3.02k|  auto write_request_success =
16740|  3.02k|      write_request(strm, req, close_connection, error, expect_100_continue,
16741|  3.02k|                    rejected_locally);
16742|       |
16743|       |  // A failed write normally still reads the response below, since the server
16744|       |  // may have answered early (e.g. 413/414) and closed while the body was being
16745|       |  // sent. A request rejected before any byte reached the socket gets no such
16746|       |  // response, and waiting for one would block until the read timeout.
16747|  3.02k|  if (rejected_locally) { return false; }
  ------------------
  |  Branch (16747:7): [True: 0, False: 3.02k]
  ------------------
16748|       |
16749|       |#ifdef CPPHTTPLIB_SSL_ENABLED
16750|       |  if (is_ssl() && !expect_100_continue) {
16751|       |    auto is_proxy_enabled = is_proxy_enabled_for_host(host_);
16752|       |    if (!is_proxy_enabled) {
16753|       |      if (tls::is_peer_closed(socket_.ssl, socket_.sock)) {
16754|       |        error = Error::SSLPeerCouldBeClosed_;
16755|       |        output_error_log(error, &req);
16756|       |        return false;
16757|       |      }
16758|       |    }
16759|       |  }
16760|       |#endif
16761|       |
16762|       |  // Handle Expect: 100-continue.
16763|       |  //
16764|       |  // Wait for an interim/early response by attempting to read the status line
16765|       |  // under a short timeout, instead of trusting raw socket readability. Over
16766|       |  // TLS, post-handshake records (e.g. session tickets) make the socket
16767|       |  // readable without any HTTP response being available; relying on
16768|       |  // `select_read` there caused the body to be withheld forever and the
16769|       |  // request to fail with `Read` (#2458). If no status line arrives within the
16770|       |  // timeout, send the body anyway (matching curl's behavior).
16771|  3.02k|  auto status_line_read = false;
16772|  3.02k|  if (expect_100_continue && write_request_success) {
  ------------------
  |  Branch (16772:7): [True: 0, False: 3.02k]
  |  Branch (16772:30): [True: 0, False: 0]
  ------------------
16773|      0|    if (CPPHTTPLIB_EXPECT_100_TIMEOUT_MSECOND > 0) {
  ------------------
  |  |   94|      0|#define CPPHTTPLIB_EXPECT_100_TIMEOUT_MSECOND 1000
  ------------------
  |  Branch (16773:9): [True: 0, Folded]
  ------------------
16774|      0|      time_t sec = CPPHTTPLIB_EXPECT_100_TIMEOUT_MSECOND / 1000;
  ------------------
  |  |   94|      0|#define CPPHTTPLIB_EXPECT_100_TIMEOUT_MSECOND 1000
  ------------------
16775|      0|      time_t usec = (CPPHTTPLIB_EXPECT_100_TIMEOUT_MSECOND % 1000) * 1000;
  ------------------
  |  |   94|      0|#define CPPHTTPLIB_EXPECT_100_TIMEOUT_MSECOND 1000
  ------------------
16776|      0|      strm.set_read_timeout(sec, usec);
16777|      0|      status_line_read = read_response_line(strm, req, res, false);
16778|      0|      strm.set_read_timeout(read_timeout_sec_, read_timeout_usec_);
16779|      0|    }
16780|       |
16781|      0|    if (!status_line_read) {
  ------------------
  |  Branch (16781:9): [True: 0, False: 0]
  ------------------
16782|       |      // No interim response within the timeout: send the body and handle the
16783|       |      // response as usual.
16784|      0|      if (!write_request_body(strm, req, error)) { return false; }
  ------------------
  |  Branch (16784:11): [True: 0, False: 0]
  ------------------
16785|      0|      expect_100_continue = false; // Switch to normal response handling
16786|      0|    }
16787|      0|  }
16788|       |
16789|       |  // Receive response and headers
16790|       |  // When using Expect: 100-continue, don't auto-skip `100 Continue` response
16791|  3.02k|  if ((!status_line_read &&
  ------------------
  |  Branch (16791:8): [True: 3.02k, False: 0]
  ------------------
16792|  3.02k|       !read_response_line(strm, req, res, !expect_100_continue)) ||
  ------------------
  |  Branch (16792:8): [True: 758, False: 2.27k]
  ------------------
16793|  2.27k|      !detail::read_headers(strm, res.headers)) {
  ------------------
  |  Branch (16793:7): [True: 717, False: 1.55k]
  ------------------
16794|  1.47k|    if (write_request_success) { error = Error::Read; }
  ------------------
  |  Branch (16794:9): [True: 1.47k, False: 0]
  ------------------
16795|  1.47k|    output_error_log(error, &req);
16796|  1.47k|    return false;
16797|  1.47k|  }
16798|       |
16799|  1.55k|  if (!write_request_success) { return false; }
  ------------------
  |  Branch (16799:7): [True: 0, False: 1.55k]
  ------------------
16800|       |
16801|       |  // Handle Expect: 100-continue response
16802|  1.55k|  if (expect_100_continue) {
  ------------------
  |  Branch (16802:7): [True: 0, False: 1.55k]
  ------------------
16803|      0|    if (res.status == StatusCode::Continue_100) {
  ------------------
  |  Branch (16803:9): [True: 0, False: 0]
  ------------------
16804|       |      // Server accepted, send the body
16805|      0|      if (!write_request_body(strm, req, error)) { return false; }
  ------------------
  |  Branch (16805:11): [True: 0, False: 0]
  ------------------
16806|       |
16807|       |      // Read the actual response
16808|      0|      res.headers.clear();
16809|      0|      res.body.clear();
16810|      0|      if (!read_response_line(strm, req, res) ||
  ------------------
  |  Branch (16810:11): [True: 0, False: 0]
  ------------------
16811|      0|          !detail::read_headers(strm, res.headers)) {
  ------------------
  |  Branch (16811:11): [True: 0, False: 0]
  ------------------
16812|      0|        error = Error::Read;
16813|      0|        output_error_log(error, &req);
16814|      0|        return false;
16815|      0|      }
16816|      0|    } else {
16817|       |      // A final response came first, so the body this request declared was
16818|       |      // never sent, and the server may still be waiting for it. The
16819|       |      // connection cannot carry another request.
16820|      0|      std::lock_guard<std::mutex> guard(socket_mutex_);
16821|      0|      socket_should_be_closed_when_request_is_done_ = true;
16822|      0|    }
16823|      0|  }
16824|       |
16825|       |  // Body
16826|  1.55k|  if ((res.status != StatusCode::NoContent_204) && req.method != "HEAD" &&
  ------------------
  |  Branch (16826:7): [True: 1.54k, False: 8]
  |  Branch (16826:52): [True: 1.54k, False: 0]
  ------------------
16827|  1.54k|      req.method != "CONNECT") {
  ------------------
  |  Branch (16827:7): [True: 1.54k, False: 0]
  ------------------
16828|       |    // Reject ambiguous framing (RFC 9112 §6.3). Unlike a request, a response
16829|       |    // whose final transfer coding is not chunked is not ambiguous: its body
16830|       |    // runs until the server closes the connection, so it is not rejected.
16831|       |    // HEAD/204 are excluded above and a 304 carries no body.
16832|  1.54k|    if (res.status != StatusCode::NotModified_304) {
  ------------------
  |  Branch (16832:9): [True: 1.53k, False: 9]
  ------------------
16833|  1.53k|      if (detail::has_conflicting_content_length(res.headers)) {
  ------------------
  |  Branch (16833:11): [True: 102, False: 1.43k]
  ------------------
16834|    102|        error = Error::Read;
16835|    102|        output_error_log(error, &req);
16836|    102|        return false;
16837|    102|      }
16838|  1.43k|      if (detail::has_faulty_transfer_encoding(res)) {
  ------------------
  |  Branch (16838:11): [True: 417, False: 1.01k]
  ------------------
16839|    417|        std::lock_guard<std::mutex> guard(socket_mutex_);
16840|    417|        socket_should_be_closed_when_request_is_done_ = true;
16841|    417|      }
16842|  1.43k|    }
16843|       |
16844|  1.44k|    auto redirect = 300 < res.status && res.status < 400 &&
  ------------------
  |  Branch (16844:21): [True: 875, False: 569]
  |  Branch (16844:41): [True: 264, False: 611]
  ------------------
16845|    264|                    res.status != StatusCode::NotModified_304 &&
  ------------------
  |  Branch (16845:21): [True: 255, False: 9]
  ------------------
16846|    255|                    follow_location_;
  ------------------
  |  Branch (16846:21): [True: 0, False: 255]
  ------------------
16847|       |
16848|  1.44k|    if (req.response_handler && !redirect) {
  ------------------
  |  Branch (16848:9): [True: 0, False: 1.44k]
  |  Branch (16848:33): [True: 0, False: 0]
  ------------------
16849|      0|      if (!req.response_handler(res)) {
  ------------------
  |  Branch (16849:11): [True: 0, False: 0]
  ------------------
16850|      0|        error = Error::Canceled;
16851|      0|        output_error_log(error, &req);
16852|      0|        return false;
16853|      0|      }
16854|      0|    }
16855|       |
16856|  1.44k|    auto out =
16857|  1.44k|        req.content_receiver
  ------------------
  |  Branch (16857:9): [True: 0, False: 1.44k]
  ------------------
16858|  1.44k|            ? static_cast<ContentReceiverWithProgress>(
16859|      0|                  [&](const char *buf, size_t n, size_t off, size_t len) {
16860|      0|                    if (redirect) { return true; }
16861|      0|                    auto ret = req.content_receiver(buf, n, off, len);
16862|      0|                    if (!ret) {
16863|      0|                      error = Error::Canceled;
16864|      0|                      output_error_log(error, &req);
16865|      0|                    }
16866|      0|                    return ret;
16867|      0|                  })
16868|  1.44k|            : static_cast<ContentReceiverWithProgress>(
16869|  1.44k|                  [&](const char *buf, size_t n, size_t /*off*/,
16870|  1.44k|                      size_t /*len*/) {
16871|  1.44k|                    assert(res.body.size() + n <= res.body.max_size());
16872|  1.44k|                    if (payload_max_length_ > 0 &&
16873|  1.44k|                        (res.body.size() >= payload_max_length_ ||
16874|  1.44k|                         n > payload_max_length_ - res.body.size())) {
16875|  1.44k|                      return false;
16876|  1.44k|                    }
16877|  1.44k|                    res.body.append(buf, n);
16878|  1.44k|                    return true;
16879|  1.44k|                  });
16880|       |
16881|  1.44k|    auto progress = [&](size_t current, size_t total) {
16882|  1.44k|      if (!req.download_progress || redirect) { return true; }
16883|  1.44k|      auto ret = req.download_progress(current, total);
16884|  1.44k|      if (!ret) {
16885|  1.44k|        error = Error::Canceled;
16886|  1.44k|        output_error_log(error, &req);
16887|  1.44k|      }
16888|  1.44k|      return ret;
16889|  1.44k|    };
16890|       |
16891|  1.44k|    if (res.has_header("Content-Length")) {
  ------------------
  |  Branch (16891:9): [True: 466, False: 978]
  ------------------
16892|    466|      if (!req.content_receiver) {
  ------------------
  |  Branch (16892:11): [True: 466, False: 0]
  ------------------
16893|    466|        auto len = res.get_header_value_u64("Content-Length");
16894|    466|        if (len > res.body.max_size()) {
  ------------------
  |  Branch (16894:13): [True: 53, False: 413]
  ------------------
16895|     53|          error = Error::Read;
16896|     53|          output_error_log(error, &req);
16897|     53|          return false;
16898|     53|        }
16899|       |        // Content-Length is only the server's claim, so reserve no more than
16900|       |        // payload_max_length_ allows, nor more than 1 MiB before any of the
16901|       |        // body has arrived. A longer body grows as it is read.
16902|    413|        auto reserve_len =
16903|    413|            (std::min)(static_cast<size_t>(len), size_t(1024 * 1024));
16904|    413|        if (payload_max_length_ > 0) {
  ------------------
  |  Branch (16904:13): [True: 413, False: 0]
  ------------------
16905|    413|          reserve_len = (std::min)(reserve_len, payload_max_length_);
16906|    413|        }
16907|    413|        res.body.reserve(reserve_len);
16908|    413|      }
16909|    466|    }
16910|       |
16911|  1.39k|    if (res.status != StatusCode::NotModified_304) {
  ------------------
  |  Branch (16911:9): [True: 1.38k, False: 9]
  ------------------
16912|  1.38k|      auto content_status = 0;
16913|  1.38k|      auto max_length = (!has_payload_max_length_ && req.content_receiver)
  ------------------
  |  Branch (16913:26): [True: 1.38k, False: 0]
  |  Branch (16913:54): [True: 0, False: 1.38k]
  ------------------
16914|  1.38k|                            ? (std::numeric_limits<size_t>::max)()
16915|  1.38k|                            : payload_max_length_;
16916|  1.38k|      if (!detail::read_content(strm, res, max_length, content_status,
  ------------------
  |  Branch (16916:11): [True: 992, False: 390]
  ------------------
16917|  1.38k|                                std::move(progress), std::move(out),
16918|  1.38k|                                decompress_)) {
16919|    992|        if (error != Error::Canceled) {
  ------------------
  |  Branch (16919:13): [True: 992, False: 0]
  ------------------
16920|       |          // Tell the caller apart from a plain read failure when the body could
16921|       |          // not be decoded because of its Content-Encoding.
16922|    992|          switch (content_status) {
16923|      2|          case StatusCode::UnsupportedMediaType_415:
  ------------------
  |  Branch (16923:11): [True: 2, False: 990]
  ------------------
16924|      2|            error = Error::UnsupportedContentEncoding;
16925|      2|            break;
16926|      0|          case StatusCode::InternalServerError_500:
  ------------------
  |  Branch (16926:11): [True: 0, False: 992]
  ------------------
16927|      0|            error = Error::Compression;
16928|      0|            break;
16929|    990|          default: error = Error::Read; break;
  ------------------
  |  Branch (16929:11): [True: 990, False: 2]
  ------------------
16930|    992|          }
16931|    992|        }
16932|    992|        output_error_log(error, &req);
16933|    992|        return false;
16934|    992|      }
16935|  1.38k|    }
16936|  1.39k|  }
16937|       |
16938|       |  // Log
16939|    407|  output_log(req, res);
16940|       |
16941|    407|  return true;
16942|  1.55k|}
_ZNK7httplib7Request10has_headerERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
11906|  21.2k|inline bool Request::has_header(const std::string &key) const {
11907|  21.2k|  return detail::has_header(headers, key);
11908|  21.2k|}
_ZN7httplib6detail10has_headerERKNS0_26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEEERKS8_:
 8285|  23.5k|inline bool has_header(const Headers &headers, const std::string &key) {
 8286|  23.5k|  if (is_prohibited_header_name(key)) { return false; }
  ------------------
  |  Branch (8286:7): [True: 0, False: 23.5k]
  ------------------
 8287|  23.5k|  return headers.find(key) != headers.end();
 8288|  23.5k|}
_ZN7httplib6detail25is_prohibited_header_nameERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
 8277|  23.5k|inline bool is_prohibited_header_name(const std::string &name) {
 8278|       |  // Field names are case-insensitive (RFC 9110 §5.1)
 8279|  23.5k|  return case_ignore::equal(name, "REMOTE_ADDR") ||
  ------------------
  |  Branch (8279:10): [True: 0, False: 23.5k]
  ------------------
 8280|  23.5k|         case_ignore::equal(name, "REMOTE_PORT") ||
  ------------------
  |  Branch (8280:10): [True: 0, False: 23.5k]
  ------------------
 8281|  23.5k|         case_ignore::equal(name, "LOCAL_ADDR") ||
  ------------------
  |  Branch (8281:10): [True: 0, False: 23.5k]
  ------------------
 8282|  23.5k|         case_ignore::equal(name, "LOCAL_PORT");
  ------------------
  |  Branch (8282:10): [True: 0, False: 23.5k]
  ------------------
 8283|  23.5k|}
_ZN7httplib6detail11case_ignore5equalILm12EEEbRKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEERAT__Kc:
  695|  47.0k|inline bool equal(const std::string &a, const char (&b)[N]) {
  696|  47.0k|  return a.size() == N - 1 &&
  ------------------
  |  Branch (696:10): [True: 0, False: 47.0k]
  ------------------
  697|      0|         std::equal(a.begin(), a.end(), b, [](char ca, char cb) {
  ------------------
  |  Branch (697:10): [True: 0, False: 0]
  ------------------
  698|      0|           return to_lower(ca) == to_lower(cb);
  699|      0|         });
  700|  47.0k|}
_ZN7httplib6detail11case_ignore5equalILm11EEEbRKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEERAT__Kc:
  695|  47.0k|inline bool equal(const std::string &a, const char (&b)[N]) {
  696|  47.0k|  return a.size() == N - 1 &&
  ------------------
  |  Branch (696:10): [True: 6.05k, False: 41.0k]
  ------------------
  697|  6.05k|         std::equal(a.begin(), a.end(), b, [](char ca, char cb) {
  ------------------
  |  Branch (697:10): [True: 0, False: 6.05k]
  ------------------
  698|  6.05k|           return to_lower(ca) == to_lower(cb);
  699|  6.05k|         });
  700|  47.0k|}
_ZZN7httplib6detail11case_ignore5equalILm11EEEbRKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEERAT__KcENKUlccE_clEcc:
  697|  6.05k|         std::equal(a.begin(), a.end(), b, [](char ca, char cb) {
  698|  6.05k|           return to_lower(ca) == to_lower(cb);
  699|  6.05k|         });
_ZNK7httplib6detail26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEE4findERKS8_:
 1295|  27.2k|  const_iterator find(const std::string &key) const {
 1296|  27.2k|    auto i = index_of(key);
 1297|  27.2k|    return i == npos() ? end() : make_citer(i, i);
  ------------------
  |  Branch (1297:12): [True: 24.5k, False: 2.64k]
  ------------------
 1298|  27.2k|  }
_ZNK7httplib6detail26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEE8index_ofERKS8_:
 1380|  38.0k|  size_type index_of(const std::string &key) const {
 1381|  99.9k|    for (size_type i = 0; i < entries_.size(); i++) {
  ------------------
  |  Branch (1381:27): [True: 67.4k, False: 32.5k]
  ------------------
 1382|  67.4k|      if (keys_equal(entries_[i].first, key)) { return i; }
  ------------------
  |  Branch (1382:11): [True: 5.47k, False: 61.9k]
  ------------------
 1383|  67.4k|    }
 1384|  32.5k|    return npos();
 1385|  38.0k|  }
_ZN7httplib7Request10set_headerERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEES9_:
11920|  7.96k|                                const std::string &val) {
11921|  7.96k|  detail::set_header(headers, key, val);
11922|  7.96k|}
_ZN7httplib6detail10set_headerERNS0_26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEEERKS8_SE_:
 8362|  7.96k|                       const std::string &val) {
 8363|  7.96k|  if (fields::is_field_valid(key, val)) { headers.emplace(key, val); }
  ------------------
  |  Branch (8363:7): [True: 7.96k, False: 0]
  ------------------
 8364|  7.96k|}
_ZN7httplib6detail26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEE7emplaceIJRKS8_SE_EEENSB_10iterator_tINS2_4pairIS8_S8_EEEEDpOT_:
 1278|  17.7k|  template <typename... Args> iterator emplace(Args &&...args) {
 1279|  17.7k|    entries_.emplace_back(std::forward<Args>(args)...);
 1280|  17.7k|    return make_iter(entries_.size() - 1, npos());
 1281|  17.7k|  }
_ZN7httplib6detail26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEE9make_iterEmm:
 1387|  42.1k|  iterator make_iter(size_type idx, size_type key_idx) {
 1388|  42.1k|    return iterator(entries_.data(), idx, entries_.size(), key_idx);
 1389|  42.1k|  }
_ZN7httplib6detail26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEE10iterator_tINS2_4pairIS8_S8_EEEC2EPSE_mmm:
 1233|  42.1k|        : data_(data), idx_(idx), size_(size), key_idx_(key_idx) {}
_ZN7httplib6detail16has_header_tokenERKNS0_26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEEERKS8_SF_:
 8334|  3.02k|                             const std::string &token) {
 8335|       |  // RFC 9110 7.6.1: a comma-separated token list field such as Connection may
 8336|       |  // carry several tokens, and RFC 9110 5.3 lets that list be split across
 8337|       |  // several lines. Match complete tokens rather than searching the raw value,
 8338|       |  // so that a value such as "notupgrade" is not read as the token "upgrade".
 8339|  3.02k|  auto rng = headers.equal_range(key);
 8340|  3.02k|  for (auto it = rng.first; it != rng.second; ++it) {
  ------------------
  |  Branch (8340:29): [True: 0, False: 3.02k]
  ------------------
 8341|      0|    const auto &value = it->second;
 8342|      0|    if (split_find(value.data(), value.data() + value.size(), ',',
  ------------------
  |  Branch (8342:9): [True: 0, False: 0]
  ------------------
 8343|      0|                   [&](const char *b, const char *e) {
 8344|      0|                     return case_ignore::equal(std::string(b, e), token);
 8345|      0|                   })) {
 8346|      0|      return true;
 8347|      0|    }
 8348|      0|  }
 8349|  3.02k|  return false;
 8350|  3.02k|}
_ZNK7httplib6detail26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEE11equal_rangeERKS8_:
 1315|  7.68k|  equal_range(const std::string &key) const {
 1316|  7.68k|    auto i = index_of(key);
 1317|  7.68k|    return i == npos() ? std::make_pair(end(), end())
  ------------------
  |  Branch (1317:12): [True: 5.69k, False: 1.99k]
  ------------------
 1318|  7.68k|                       : std::make_pair(make_citer(i, i), end());
 1319|  7.68k|  }
_ZNK7httplib6detail26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEE10iterator_tIKNS2_4pairIS8_S8_EEEptEv:
 1182|  4.57k|    pointer operator->() const { return data_ + idx_; }
_ZN7httplib6detail4trimEPKcS2_mm:
 6192|  17.2k|                                      size_t right) {
 6193|  25.5k|  while (b + left < e && is_space_or_tab(b[left])) {
  ------------------
  |  Branch (6193:10): [True: 25.4k, False: 113]
  |  Branch (6193:26): [True: 8.32k, False: 17.1k]
  ------------------
 6194|  8.32k|    left++;
 6195|  8.32k|  }
 6196|  25.5k|  while (right > 0 && is_space_or_tab(b[right - 1])) {
  ------------------
  |  Branch (6196:10): [True: 25.3k, False: 132]
  |  Branch (6196:23): [True: 8.27k, False: 17.0k]
  ------------------
 6197|  8.27k|    right--;
 6198|  8.27k|  }
 6199|  17.2k|  return std::make_pair(left, right);
 6200|  17.2k|}
_ZN7httplib6detail15is_space_or_tabEc:
 6045|   235k|inline bool is_space_or_tab(char c) { return c == ' ' || c == '\t'; }
  ------------------
  |  Branch (6045:46): [True: 159k, False: 76.5k]
  |  Branch (6045:58): [True: 399, False: 76.1k]
  ------------------
_ZN7httplib10ClientImpl13write_requestERNS_6StreamERNS_7RequestEbRNS_5ErrorEbRb:
16376|  3.02k|                                      bool skip_body, bool &rejected_locally) {
16377|  3.02k|  rejected_locally = false;
16378|       |
16379|       |  // Prepare additional headers
16380|  3.02k|  if (close_connection) {
  ------------------
  |  Branch (16380:7): [True: 0, False: 3.02k]
  ------------------
16381|      0|    if (!req.has_header("Connection")) {
  ------------------
  |  Branch (16381:9): [True: 0, False: 0]
  ------------------
16382|      0|      req.set_header("Connection", "close");
16383|      0|    }
16384|      0|  }
16385|       |
16386|  3.02k|  std::string ct_for_defaults;
16387|  3.02k|  if (!req.has_header("Content-Type") && !req.body.empty()) {
  ------------------
  |  Branch (16387:7): [True: 3.02k, False: 0]
  |  Branch (16387:7): [True: 0, False: 3.02k]
  |  Branch (16387:42): [True: 0, False: 3.02k]
  ------------------
16388|      0|    ct_for_defaults = "text/plain";
16389|      0|  }
16390|  3.02k|  prepare_default_headers(req, false, ct_for_defaults);
16391|       |
16392|  3.02k|  if (req.body.empty()) {
  ------------------
  |  Branch (16392:7): [True: 3.02k, False: 0]
  ------------------
16393|  3.02k|    if (req.content_provider_) {
  ------------------
  |  Branch (16393:9): [True: 0, False: 3.02k]
  ------------------
16394|      0|      if (!req.is_chunked_content_provider_) {
  ------------------
  |  Branch (16394:11): [True: 0, False: 0]
  ------------------
16395|      0|        if (!req.has_header("Content-Length")) {
  ------------------
  |  Branch (16395:13): [True: 0, False: 0]
  ------------------
16396|      0|          auto length = std::to_string(req.content_length_);
16397|      0|          req.set_header("Content-Length", length);
16398|      0|        }
16399|      0|      }
16400|  3.02k|    } else {
16401|  3.02k|      if (req.method == "POST" || req.method == "PUT" ||
  ------------------
  |  Branch (16401:11): [True: 583, False: 2.44k]
  |  Branch (16401:35): [True: 965, False: 1.48k]
  ------------------
16402|  1.90k|          req.method == "PATCH") {
  ------------------
  |  Branch (16402:11): [True: 359, False: 1.12k]
  ------------------
16403|  1.90k|        req.set_header("Content-Length", "0");
16404|  1.90k|      }
16405|  3.02k|    }
16406|  3.02k|  }
16407|       |
16408|       |  // A CONNECT request is read by the proxy; everything sent through the tunnel
16409|       |  // it opens is read by the origin. Each credential goes only to its own hop.
16410|  3.02k|  auto is_connect = req.method == "CONNECT";
16411|       |
16412|  3.02k|  if (!is_connect && !req.has_header("Authorization")) {
  ------------------
  |  Branch (16412:7): [True: 3.02k, False: 0]
  |  Branch (16412:7): [True: 3.02k, False: 0]
  |  Branch (16412:22): [True: 3.02k, False: 0]
  ------------------
16413|  3.02k|    if (!basic_auth_password_.empty() || !basic_auth_username_.empty()) {
  ------------------
  |  Branch (16413:9): [True: 0, False: 3.02k]
  |  Branch (16413:42): [True: 0, False: 3.02k]
  ------------------
16414|      0|      req.headers.insert(make_basic_authentication_header(
16415|      0|          basic_auth_username_, basic_auth_password_, false));
16416|  3.02k|    } else if (!bearer_token_auth_token_.empty()) {
  ------------------
  |  Branch (16416:16): [True: 0, False: 3.02k]
  ------------------
16417|      0|      req.headers.insert(make_bearer_token_authentication_header(
16418|      0|          bearer_token_auth_token_, false));
16419|      0|    }
16420|  3.02k|  }
16421|       |
16422|       |  // Proxy-Authorization is only sent when the proxy reads this message —
16423|       |  // otherwise NO_PROXY-matched requests, and requests inside a TLS tunnel,
16424|       |  // would leak proxy credentials to the destination server.
16425|  3.02k|  if (is_proxy_enabled_for_host(host_) && (!is_ssl() || is_connect)) {
  ------------------
  |  Branch (16425:7): [True: 0, False: 3.02k]
  |  Branch (16425:44): [True: 0, False: 0]
  |  Branch (16425:57): [True: 0, False: 0]
  ------------------
16426|      0|    if ((!proxy_basic_auth_username_.empty() ||
  ------------------
  |  Branch (16426:9): [True: 0, False: 0]
  |  Branch (16426:10): [True: 0, False: 0]
  ------------------
16427|      0|         !proxy_basic_auth_password_.empty()) &&
  ------------------
  |  Branch (16427:10): [True: 0, False: 0]
  ------------------
16428|      0|        !req.has_header("Proxy-Authorization")) {
  ------------------
  |  Branch (16428:9): [True: 0, False: 0]
  ------------------
16429|      0|      req.headers.insert(make_basic_authentication_header(
16430|      0|          proxy_basic_auth_username_, proxy_basic_auth_password_, true));
16431|      0|    }
16432|      0|    if (!proxy_bearer_token_auth_token_.empty() &&
  ------------------
  |  Branch (16432:9): [True: 0, False: 0]
  |  Branch (16432:9): [True: 0, False: 0]
  ------------------
16433|      0|        !req.has_header("Proxy-Authorization")) {
  ------------------
  |  Branch (16433:9): [True: 0, False: 0]
  ------------------
16434|      0|      req.headers.insert(make_bearer_token_authentication_header(
16435|      0|          proxy_bearer_token_auth_token_, true));
16436|      0|    }
16437|      0|  }
16438|       |
16439|       |  // Request line and headers
16440|  3.02k|  {
16441|  3.02k|    detail::BufferStream bstrm;
16442|       |
16443|  3.02k|    auto path_with_query = make_request_target(req);
16444|       |
16445|       |    // The query already came in through `req.path`; still populate
16446|       |    // `req.params` for handlers/users who read them.
16447|  3.02k|    auto query_part = detail::query_of(req.path);
16448|  3.02k|    if (!query_part.empty()) {
  ------------------
  |  Branch (16448:9): [True: 0, False: 3.02k]
  ------------------
16449|      0|      detail::parse_query_text(query_part, req.params);
16450|      0|    }
16451|       |
16452|       |    // Write request line and headers
16453|  3.02k|    if (detail::write_request_line(bstrm, req.method, path_with_query) < 0) {
  ------------------
  |  Branch (16453:9): [True: 0, False: 3.02k]
  ------------------
16454|       |      // A rejected method (not a token, e.g. carrying CR/LF) or target (e.g.
16455|       |      // CR/LF in a caller-supplied path under set_path_encode(false)) must
16456|       |      // fail the request cleanly instead of emitting a request-line-less,
16457|       |      // header-injecting request.
16458|      0|      error = Error::Write;
16459|      0|      rejected_locally = true;
16460|      0|      output_error_log(error, &req);
16461|      0|      return false;
16462|      0|    }
16463|  3.02k|    if (!detail::check_and_write_headers(bstrm, req.headers, header_writer_,
  ------------------
  |  Branch (16463:9): [True: 0, False: 3.02k]
  ------------------
16464|  3.02k|                                         error)) {
16465|      0|      rejected_locally = true;
16466|      0|      output_error_log(error, &req);
16467|      0|      return false;
16468|      0|    }
16469|       |
16470|       |    // Flush buffer
16471|  3.02k|    auto &data = bstrm.get_buffer();
16472|  3.02k|    if (!detail::write_data(strm, data.data(), data.size())) {
  ------------------
  |  Branch (16472:9): [True: 0, False: 3.02k]
  ------------------
16473|      0|      error = Error::Write;
16474|      0|      output_error_log(error, &req);
16475|      0|      return false;
16476|      0|    }
16477|  3.02k|  }
16478|       |
16479|       |  // After sending request line and headers, wait briefly for an early server
16480|       |  // response (e.g. 4xx) and avoid sending a potentially large request body
16481|       |  // unnecessarily. This workaround is only enabled on Windows because Unix
16482|       |  // platforms surface write errors (EPIPE) earlier; on Windows kernel send
16483|       |  // buffering can accept large writes even when the peer already responded.
16484|       |  // Check the stream first (which covers SSL via `is_readable()`), then
16485|       |  // fall back to select on the socket. Only perform the wait for very large
16486|       |  // request bodies to avoid interfering with normal small requests and
16487|       |  // reduce side-effects. Poll briefly (up to 50ms as default) for an early
16488|       |  // response. Skip this check when using Expect: 100-continue, as the protocol
16489|       |  // handles early responses properly.
16490|       |#if defined(_WIN32)
16491|       |  if (!skip_body &&
16492|       |      req.body.size() > CPPHTTPLIB_WAIT_EARLY_SERVER_RESPONSE_THRESHOLD &&
16493|       |      req.path.size() > CPPHTTPLIB_REQUEST_URI_MAX_LENGTH) {
16494|       |    auto start = std::chrono::high_resolution_clock::now();
16495|       |
16496|       |    for (;;) {
16497|       |      // Prefer socket-level readiness to avoid SSL_pending() false-positives
16498|       |      // from SSL internals. If the underlying socket is readable, assume an
16499|       |      // early response may be present.
16500|       |      auto sock = strm.socket();
16501|       |      if (sock != INVALID_SOCKET && detail::select_read(sock, 0, 0) > 0) {
16502|       |        return false;
16503|       |      }
16504|       |
16505|       |      // Fallback to stream-level check for non-socket streams or when the
16506|       |      // socket isn't reporting readable. Avoid using `is_readable()` for
16507|       |      // SSL, since `SSL_pending()` may report buffered records that do not
16508|       |      // indicate a complete application-level response yet.
16509|       |      if (!is_ssl() && strm.is_readable()) { return false; }
16510|       |
16511|       |      auto now = std::chrono::high_resolution_clock::now();
16512|       |      auto elapsed =
16513|       |          std::chrono::duration_cast<std::chrono::milliseconds>(now - start)
16514|       |              .count();
16515|       |      if (elapsed >= CPPHTTPLIB_WAIT_EARLY_SERVER_RESPONSE_TIMEOUT_MSECOND) {
16516|       |        break;
16517|       |      }
16518|       |
16519|       |      std::this_thread::sleep_for(std::chrono::milliseconds(1));
16520|       |    }
16521|       |  }
16522|       |#endif
16523|       |
16524|       |  // Body
16525|  3.02k|  if (skip_body) { return true; }
  ------------------
  |  Branch (16525:7): [True: 0, False: 3.02k]
  ------------------
16526|       |
16527|  3.02k|  return write_request_body(strm, req, error);
16528|  3.02k|}
_ZN7httplib10ClientImpl23prepare_default_headersERNS_7RequestEbRKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEE:
15619|  3.02k|                                                const std::string &ct) {
15620|  3.02k|  (void)for_stream;
15621|       |  // Default headers are meant for the origin and may carry its credentials, so
15622|       |  // keep them off the CONNECT request the proxy reads.
15623|  3.02k|  if (r.method != "CONNECT") {
  ------------------
  |  Branch (15623:7): [True: 3.02k, False: 0]
  ------------------
15624|  3.02k|    for (const auto &header : default_headers_) {
  ------------------
  |  Branch (15624:29): [True: 0, False: 3.02k]
  ------------------
15625|      0|      if (!r.has_header(header.first)) { r.headers.insert(header); }
  ------------------
  |  Branch (15625:11): [True: 0, False: 0]
  ------------------
15626|      0|    }
15627|  3.02k|  }
15628|       |
15629|       |  // RFC 9110 5.3 recommends sending control data such as Host first, so
15630|       |  // prepend it rather than appending it after the caller's own fields.
15631|  3.02k|  if (!r.has_header("Host")) {
  ------------------
  |  Branch (15631:7): [True: 3.02k, False: 0]
  ------------------
15632|  3.02k|    r.headers.emplace_front(
15633|  3.02k|        "Host", detail::make_default_host_header_value(host_, port_, is_ssl(),
15634|  3.02k|                                                       address_family_));
15635|  3.02k|  }
15636|       |
15637|  3.02k|  if (!r.has_header("Accept")) { r.headers.emplace("Accept", "*/*"); }
  ------------------
  |  Branch (15637:7): [True: 3.02k, False: 0]
  ------------------
15638|       |
15639|  3.02k|  if (!r.content_receiver) {
  ------------------
  |  Branch (15639:7): [True: 3.02k, False: 0]
  ------------------
15640|  3.02k|    if (!r.has_header("Accept-Encoding")) {
  ------------------
  |  Branch (15640:9): [True: 3.02k, False: 0]
  ------------------
15641|  3.02k|      std::string accept_encoding;
15642|       |#ifdef CPPHTTPLIB_BROTLI_SUPPORT
15643|       |      accept_encoding = "br";
15644|       |#endif
15645|  3.02k|#ifdef CPPHTTPLIB_ZLIB_SUPPORT
15646|  3.02k|      if (!accept_encoding.empty()) { accept_encoding += ", "; }
  ------------------
  |  Branch (15646:11): [True: 0, False: 3.02k]
  ------------------
15647|  3.02k|      accept_encoding += "gzip, deflate";
15648|  3.02k|#endif
15649|       |#ifdef CPPHTTPLIB_ZSTD_SUPPORT
15650|       |      if (!accept_encoding.empty()) { accept_encoding += ", "; }
15651|       |      accept_encoding += "zstd";
15652|       |#endif
15653|  3.02k|      r.set_header("Accept-Encoding", accept_encoding);
15654|  3.02k|    }
15655|       |
15656|  3.02k|    detail::add_default_user_agent_header(r);
15657|  3.02k|  }
15658|       |
15659|  3.02k|  if (!r.body.empty()) {
  ------------------
  |  Branch (15659:7): [True: 0, False: 3.02k]
  ------------------
15660|      0|    if (!ct.empty() && !r.has_header("Content-Type")) {
  ------------------
  |  Branch (15660:9): [True: 0, False: 0]
  |  Branch (15660:9): [True: 0, False: 0]
  |  Branch (15660:24): [True: 0, False: 0]
  ------------------
15661|      0|      r.headers.emplace("Content-Type", ct);
15662|      0|    }
15663|      0|    if (!r.has_header("Content-Length")) {
  ------------------
  |  Branch (15663:9): [True: 0, False: 0]
  ------------------
15664|      0|      r.headers.emplace("Content-Length", std::to_string(r.body.size()));
15665|      0|    }
15666|      0|  }
15667|  3.02k|}
_ZN7httplib6detail26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEE5beginEv:
 1256|  6.05k|  iterator begin() { return make_iter(0, npos()); }
_ZN7httplib6detail26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEE3endEv:
 1257|  11.4k|  iterator end() { return make_iter(entries_.size(), npos()); }
_ZNK7httplib6detail26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEE10iterator_tINS2_4pairIS8_S8_EEEneISE_EEbRKNSC_IT_EE:
 1224|  24.6k|    template <typename U> bool operator!=(const iterator_t<U> &rhs) const {
 1225|  24.6k|      return idx_ != rhs.idx_;
 1226|  24.6k|    }
_ZNK7httplib6detail26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEE10iterator_tINS2_4pairIS8_S8_EEEdeEv:
 1181|  14.0k|    reference operator*() const { return data_[idx_]; }
_ZN7httplib6detail26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEE10iterator_tINS2_4pairIS8_S8_EEEppEv:
 1184|  15.4k|    iterator_t &operator++() {
 1185|       |      // Saturating, so that advancing past the last entry of a key stays at
 1186|       |      // end() instead of running off the container.
 1187|  15.4k|      if (idx_ >= size_) { return *this; }
  ------------------
  |  Branch (1187:11): [True: 0, False: 15.4k]
  ------------------
 1188|  15.4k|      ++idx_;
 1189|  15.4k|      if (key_idx_ != npos()) {
  ------------------
  |  Branch (1189:11): [True: 1.47k, False: 14.0k]
  ------------------
 1190|  2.13k|        while (idx_ < size_ && !matches(idx_)) {
  ------------------
  |  Branch (1190:16): [True: 1.47k, False: 663]
  |  Branch (1190:32): [True: 662, False: 809]
  ------------------
 1191|    662|          ++idx_;
 1192|    662|        }
 1193|  1.47k|      }
 1194|  15.4k|      return *this;
 1195|  15.4k|    }
_ZNK7httplib6detail26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEE10iterator_tINS2_4pairIS8_S8_EEE7matchesEm:
 1235|  1.47k|    bool matches(size_type i) const {
 1236|  1.47k|      return keys_equal(data_[i].first, data_[key_idx_].first);
 1237|  1.47k|    }
_ZN7httplib6detail26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEE13emplace_frontIJRA5_KcS8_EEENSB_10iterator_tINS2_4pairIS8_S8_EEEEDpOT_:
 1285|  3.02k|  template <typename... Args> iterator emplace_front(Args &&...args) {
 1286|  3.02k|    entries_.emplace(entries_.begin(), std::forward<Args>(args)...);
 1287|  3.02k|    return make_iter(0, npos());
 1288|  3.02k|  }
_ZN7httplib6detail30make_default_host_header_valueERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEibi:
12877|  3.02k|                                                  int address_family) {
12878|  3.02k|  if (address_family == AF_UNIX) { return "localhost"; }
  ------------------
  |  Branch (12878:7): [True: 0, False: 3.02k]
  ------------------
12879|  3.02k|  return make_host_and_port_string(host, port, is_ssl);
12880|  3.02k|}
_ZN7httplib6detail25make_host_and_port_stringERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEib:
12854|  3.02k|                                             bool is_ssl) {
12855|  3.02k|  auto result = prepare_host_string(host);
12856|       |
12857|       |  // Append port if not default
12858|  3.02k|  if ((!is_ssl && port == 80) || (is_ssl && port == 443)) {
  ------------------
  |  Branch (12858:8): [True: 3.02k, False: 0]
  |  Branch (12858:19): [True: 0, False: 3.02k]
  |  Branch (12858:35): [True: 0, False: 3.02k]
  |  Branch (12858:45): [True: 0, False: 0]
  ------------------
12859|      0|    ; // do nothing
12860|  3.02k|  } else {
12861|  3.02k|    result += ":" + std::to_string(port);
12862|  3.02k|  }
12863|       |
12864|  3.02k|  return result;
12865|  3.02k|}
_ZN7httplib6detail19prepare_host_stringERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
12841|  3.02k|inline std::string prepare_host_string(const std::string &host) {
12842|       |  // Enclose IPv6 address in brackets (but not if already enclosed)
12843|  3.02k|  if (host.find(':') == std::string::npos ||
  ------------------
  |  Branch (12843:7): [True: 3.02k, False: 0]
  ------------------
12844|  3.02k|      (!host.empty() && host[0] == '[')) {
  ------------------
  |  Branch (12844:8): [True: 0, False: 0]
  |  Branch (12844:25): [True: 0, False: 0]
  ------------------
12845|       |    // IPv4, hostname, or already bracketed IPv6
12846|  3.02k|    return host;
12847|  3.02k|  } else {
12848|       |    // IPv6 address without brackets
12849|      0|    return "[" + host + "]";
12850|      0|  }
12851|  3.02k|}
_ZN7httplib6detail26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEE7emplaceIJRA7_KcRA4_SD_EEENSB_10iterator_tINS2_4pairIS8_S8_EEEEDpOT_:
 1278|  3.02k|  template <typename... Args> iterator emplace(Args &&...args) {
 1279|  3.02k|    entries_.emplace_back(std::forward<Args>(args)...);
 1280|  3.02k|    return make_iter(entries_.size() - 1, npos());
 1281|  3.02k|  }
_ZN7httplib6detail29add_default_user_agent_headerERNS_7RequestE:
12882|  3.02k|inline void add_default_user_agent_header(Request &req) {
12883|  3.02k|#ifndef CPPHTTPLIB_NO_DEFAULT_USER_AGENT
12884|  3.02k|  if (!req.has_header("User-Agent")) {
  ------------------
  |  Branch (12884:7): [True: 3.02k, False: 0]
  ------------------
12885|  3.02k|    req.set_header("User-Agent",
12886|  3.02k|                   std::string("cpp-httplib/") + CPPHTTPLIB_VERSION);
  ------------------
  |  |   11|  3.02k|#define CPPHTTPLIB_VERSION "0.61.0"
  ------------------
12887|  3.02k|  }
12888|       |#else
12889|       |  (void)req;
12890|       |#endif
12891|  3.02k|}
_ZNK7httplib10ClientImpl25is_proxy_enabled_for_hostERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
15352|  3.02k|ClientImpl::is_proxy_enabled_for_host(const std::string &host) const {
15353|  3.02k|  if (proxy_host_.empty() || proxy_port_ == -1) { return false; }
  ------------------
  |  Branch (15353:7): [True: 3.02k, False: 0]
  |  Branch (15353:30): [True: 0, False: 0]
  ------------------
15354|      0|  if (no_proxy_entries_.empty()) { return true; }
  ------------------
  |  Branch (15354:7): [True: 0, False: 0]
  ------------------
15355|       |  // host_ is const so its normalized form is invariant; cache it. The
15356|       |  // cross-host path (setup_redirect_client passing next_host) re-normalizes.
15357|      0|  if (host == host_) {
  ------------------
  |  Branch (15357:7): [True: 0, False: 0]
  ------------------
15358|      0|    if (!host_normalized_valid_) {
  ------------------
  |  Branch (15358:9): [True: 0, False: 0]
  ------------------
15359|      0|      host_normalized_ = detail::normalize_target(host_);
15360|      0|      host_normalized_valid_ = true;
15361|      0|    }
15362|      0|    return !detail::host_matches_no_proxy(host_normalized_, no_proxy_entries_);
15363|      0|  }
15364|      0|  auto target = detail::normalize_target(host);
15365|      0|  return !detail::host_matches_no_proxy(target, no_proxy_entries_);
15366|      0|}
_ZN7httplib6detail12BufferStreamC2Ev:
 3836|  3.02k|  BufferStream() = default;
_ZNK7httplib10ClientImpl19make_request_targetERKNS_7RequestE:
16366|  3.02k|inline std::string ClientImpl::make_request_target(const Request &req) const {
16367|  3.02k|  auto target = detail::encode_request_target(req.path, path_encode_);
16368|  3.02k|  if (detail::query_of(req.path).empty() && !req.params.empty()) {
  ------------------
  |  Branch (16368:7): [True: 3.02k, False: 0]
  |  Branch (16368:7): [True: 0, False: 3.02k]
  |  Branch (16368:45): [True: 0, False: 3.02k]
  ------------------
16369|      0|    target = append_query_params(target, req.params);
16370|      0|  }
16371|  3.02k|  return target;
16372|  3.02k|}
_ZN7httplib6detail21encode_request_targetERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEb:
 9313|  3.02k|                                         bool path_encode) {
 9314|       |  // The fragment stays with the client (RFC 9110 §7.1).
 9315|  3.02k|  auto target = uri.substr(0, uri.find('#'));
 9316|       |
 9317|       |  // `substr(0, npos)` yields the whole string, which is what the no-query
 9318|       |  // case needs.
 9319|  3.02k|  auto query_pos = target.find('?');
 9320|  3.02k|  auto path_part = target.substr(0, query_pos);
 9321|  3.02k|  std::string query_part;
 9322|  3.02k|  if (query_pos != std::string::npos) {
  ------------------
  |  Branch (9322:7): [True: 0, False: 3.02k]
  ------------------
 9323|      0|    query_part = target.substr(query_pos + 1);
 9324|      0|  }
 9325|       |
 9326|  3.02k|  auto result = path_encode ? encode_path(path_part) : std::move(path_part);
  ------------------
  |  Branch (9326:17): [True: 3.02k, False: 0]
  ------------------
 9327|       |
 9328|  3.02k|  if (!query_part.empty()) {
  ------------------
  |  Branch (9328:7): [True: 0, False: 3.02k]
  ------------------
 9329|       |    // When path encoding is disabled the caller has supplied an already-encoded
 9330|       |    // target and expects the exact bytes to be sent on the wire, so skip
 9331|       |    // normalization for the query too. Normalizing would decode-then-re-encode
 9332|       |    // it and corrupt pre-encoded binary payloads (e.g. turning `%20` into `+`,
 9333|       |    // which a strict RFC 3986 server decodes back as `+`, not a space).
 9334|      0|    if (path_encode) {
  ------------------
  |  Branch (9334:9): [True: 0, False: 0]
  ------------------
 9335|      0|      auto normalized = normalize_query_string(query_part);
 9336|      0|      if (!normalized.empty()) {
  ------------------
  |  Branch (9336:11): [True: 0, False: 0]
  ------------------
 9337|      0|        result += '?';
 9338|      0|        result += normalized;
 9339|      0|      }
 9340|      0|    } else {
 9341|      0|      result += '?';
 9342|      0|      result += query_part;
 9343|      0|    }
 9344|      0|  }
 9345|       |
 9346|  3.02k|  return result;
 9347|  3.02k|}
_ZN7httplib6detail11encode_pathERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
 6002|  3.02k|inline std::string encode_path(const std::string &s) {
 6003|  3.02k|  std::string result;
 6004|  3.02k|  result.reserve(s.size());
 6005|       |
 6006|  6.05k|  for (size_t i = 0; s[i]; i++) {
  ------------------
  |  Branch (6006:22): [True: 3.02k, False: 3.02k]
  ------------------
 6007|  3.02k|    switch (s[i]) {
 6008|      0|    case ' ': result += "%20"; break;
  ------------------
  |  Branch (6008:5): [True: 0, False: 3.02k]
  ------------------
 6009|      0|    case '+': result += "%2B"; break;
  ------------------
  |  Branch (6009:5): [True: 0, False: 3.02k]
  ------------------
 6010|      0|    case '\'': result += "%27"; break;
  ------------------
  |  Branch (6010:5): [True: 0, False: 3.02k]
  ------------------
 6011|      0|    case ',': result += "%2C"; break;
  ------------------
  |  Branch (6011:5): [True: 0, False: 3.02k]
  ------------------
 6012|       |    // case ':': result += "%3A"; break; // ok? probably...
 6013|      0|    case ';': result += "%3B"; break;
  ------------------
  |  Branch (6013:5): [True: 0, False: 3.02k]
  ------------------
 6014|  3.02k|    default:
  ------------------
  |  Branch (6014:5): [True: 3.02k, False: 0]
  ------------------
 6015|  3.02k|      auto c = static_cast<uint8_t>(s[i]);
 6016|       |      // Control characters (incl. CR/LF) and non-ASCII bytes are not allowed
 6017|       |      // in a request-target as-is.
 6018|  3.02k|      if (c < 0x20 || c == 0x7f || c >= 0x80) {
  ------------------
  |  Branch (6018:11): [True: 0, False: 3.02k]
  |  Branch (6018:23): [True: 0, False: 3.02k]
  |  Branch (6018:36): [True: 0, False: 3.02k]
  ------------------
 6019|      0|        result += '%';
 6020|      0|        char hex[4];
 6021|      0|        auto len = snprintf(hex, sizeof(hex) - 1, "%02X", c);
 6022|      0|        assert(len == 2);
  ------------------
  |  Branch (6022:9): [True: 0, False: 0]
  ------------------
 6023|      0|        result.append(hex, static_cast<size_t>(len));
 6024|  3.02k|      } else {
 6025|  3.02k|        result += s[i];
 6026|  3.02k|      }
 6027|  3.02k|      break;
 6028|  3.02k|    }
 6029|  3.02k|  }
 6030|       |
 6031|  3.02k|  return result;
 6032|  3.02k|}
_ZN7httplib6detail5splitEPKcS2_cNSt3__18functionIFvS2_S2_EEE:
 6252|  1.24k|                  std::function<void(const char *, const char *)> fn) {
 6253|  1.24k|  return split(b, e, d, (std::numeric_limits<size_t>::max)(), std::move(fn));
 6254|  1.24k|}
_ZN7httplib6detail5splitEPKcS2_cmNSt3__18functionIFvS2_S2_EEE:
 6257|  1.24k|                  std::function<void(const char *, const char *)> fn) {
 6258|  1.24k|  size_t i = 0;
 6259|  1.24k|  size_t beg = 0;
 6260|  1.24k|  size_t count = 1;
 6261|       |
 6262|   165k|  while (e ? (b + i < e) : (b[i] != '\0')) {
  ------------------
  |  Branch (6262:10): [True: 165k, False: 0]
  |  Branch (6262:10): [True: 164k, False: 1.24k]
  ------------------
 6263|   164k|    if (b[i] == d && count < m) {
  ------------------
  |  Branch (6263:9): [True: 16.2k, False: 148k]
  |  Branch (6263:22): [True: 16.2k, False: 0]
  ------------------
 6264|  16.2k|      auto r = trim(b, e, beg, i);
 6265|  16.2k|      if (r.first < r.second) { fn(&b[r.first], &b[r.second]); }
  ------------------
  |  Branch (6265:11): [True: 4.20k, False: 12.0k]
  ------------------
 6266|  16.2k|      beg = i + 1;
 6267|  16.2k|      count++;
 6268|  16.2k|    }
 6269|   164k|    i++;
 6270|   164k|  }
 6271|       |
 6272|  1.24k|  if (i) {
  ------------------
  |  Branch (6272:7): [True: 973, False: 276]
  ------------------
 6273|    973|    auto r = trim(b, e, beg, i);
 6274|    973|    if (r.first < r.second) { fn(&b[r.first], &b[r.second]); }
  ------------------
  |  Branch (6274:9): [True: 860, False: 113]
  ------------------
 6275|    973|  }
 6276|  1.24k|}
_ZN7httplib6detail6is_hexEcRi:
 5338|  16.2k|inline bool is_hex(char c, int &v) {
 5339|  16.2k|  if (is_ascii_digit(c)) {
  ------------------
  |  Branch (5339:7): [True: 10.4k, False: 5.83k]
  ------------------
 5340|  10.4k|    v = c - '0';
 5341|  10.4k|    return true;
 5342|  10.4k|  } else if ('A' <= c && c <= 'F') {
  ------------------
  |  Branch (5342:14): [True: 3.25k, False: 2.58k]
  |  Branch (5342:26): [True: 1.36k, False: 1.88k]
  ------------------
 5343|  1.36k|    v = c - 'A' + 10;
 5344|  1.36k|    return true;
 5345|  4.47k|  } else if ('a' <= c && c <= 'f') {
  ------------------
  |  Branch (5345:14): [True: 1.88k, False: 2.58k]
  |  Branch (5345:26): [True: 1.87k, False: 6]
  ------------------
 5346|  1.87k|    v = c - 'a' + 10;
 5347|  1.87k|    return true;
 5348|  1.87k|  }
 5349|  2.59k|  return false;
 5350|  16.2k|}
_ZNK7httplib6detail26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS2_8equal_toIS8_EEE5emptyEv:
 1263|  3.02k|  bool empty() const { return entries_.empty(); }
_ZN7httplib6detail8query_ofERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
 9301|  6.05k|inline std::string query_of(const std::string &path) {
 9302|  6.05k|  auto fragment_pos = path.find('#');
 9303|  6.05k|  auto query_pos = path.find('?');
 9304|  6.05k|  return query_pos < fragment_pos
  ------------------
  |  Branch (9304:10): [True: 0, False: 6.05k]
  ------------------
 9305|  6.05k|             ? path.substr(query_pos + 1, fragment_pos - query_pos - 1)
 9306|  6.05k|             : std::string();
 9307|  6.05k|}
_ZN7httplib6detail18write_request_lineERNS_6StreamERKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEESB_:
 8818|  3.02k|                                  const std::string &path) {
 8819|       |  // Neither the method nor the request target may carry CR/LF, SP or other
 8820|       |  // control octets; otherwise a value smuggled into either splits the request
 8821|       |  // line and injects headers or a whole request.
 8822|  3.02k|  if (!fields::is_token(method)) { return -1; }
  ------------------
  |  Branch (8822:7): [True: 0, False: 3.02k]
  ------------------
 8823|  3.02k|  if (!fields::is_request_target(path)) { return -1; }
  ------------------
  |  Branch (8823:7): [True: 0, False: 3.02k]
  ------------------
 8824|       |
 8825|  3.02k|  std::string s = method;
 8826|  3.02k|  s += ' ';
 8827|  3.02k|  s += path;
 8828|  3.02k|  s += " HTTP/1.1\r\n";
 8829|  3.02k|  return strm.write(s.data(), s.size());
 8830|  3.02k|}
_ZN7httplib6detail6fields17is_request_targetERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE:
10528|  3.02k|inline bool is_request_target(const std::string &s) {
10529|  3.02k|  return std::all_of(s.begin(), s.end(), is_field_vchar);
10530|  3.02k|}
_ZN7httplib6detail23check_and_write_headersINSt3__18functionIFlRNS_6StreamERNS0_26insertion_ordered_multimapINS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEEEEEEEEbS5_SG_T_RNS_5ErrorE:
13057|  3.02k|                                    T header_writer, Error &error) {
13058|  14.0k|  for (const auto &h : headers) {
  ------------------
  |  Branch (13058:22): [True: 14.0k, False: 3.02k]
  ------------------
13059|  14.0k|    if (!detail::fields::is_field_valid(h.first, h.second)) {
  ------------------
  |  Branch (13059:9): [True: 0, False: 14.0k]
  ------------------
13060|      0|      error = Error::InvalidHeaders;
13061|      0|      return false;
13062|      0|    }
13063|  14.0k|  }
13064|  3.02k|  if (header_writer(strm, headers) <= 0) {
  ------------------
  |  Branch (13064:7): [True: 0, False: 3.02k]
  ------------------
13065|      0|    error = Error::Write;
13066|      0|    return false;
13067|      0|  }
13068|  3.02k|  return true;
13069|  3.02k|}
_ZNK7httplib6detail12BufferStream10get_bufferEv:
12732|  3.02k|inline const std::string &BufferStream::get_buffer() const { return buffer; }
_ZN7httplib6detail10write_dataERNS_6StreamEPKcm:
 8867|  3.02k|inline bool write_data(Stream &strm, const char *d, size_t l) {
 8868|  3.02k|  size_t offset = 0;
 8869|  6.05k|  while (offset < l) {
  ------------------
  |  Branch (8869:10): [True: 3.02k, False: 3.02k]
  ------------------
 8870|  3.02k|    auto length = strm.write(d + offset, l - offset);
 8871|  3.02k|    if (length < 0) { return false; }
  ------------------
  |  Branch (8871:9): [True: 0, False: 3.02k]
  ------------------
 8872|  3.02k|    offset += static_cast<size_t>(length);
 8873|  3.02k|  }
 8874|  3.02k|  return true;
 8875|  3.02k|}
_ZNK7httplib10ClientImpl18read_response_lineERNS_6StreamERKNS_7RequestERNS_8ResponseEb:
15449|  3.02k|                                           bool skip_100_continue) const {
15450|  3.02k|  std::array<char, 2048> buf{};
15451|       |
15452|  3.02k|  detail::stream_line_reader line_reader(strm, buf.data(), buf.size());
15453|       |
15454|  3.02k|  if (!line_reader.getline()) { return false; }
  ------------------
  |  Branch (15454:7): [True: 9, False: 3.02k]
  ------------------
15455|       |
15456|  3.02k|  if (!detail::parse_status_line(line_reader.ptr(), res.version, res.status,
  ------------------
  |  Branch (15456:7): [True: 234, False: 2.78k]
  ------------------
15457|  3.02k|                                 res.reason)) {
15458|    234|    return req.method == "CONNECT";
15459|    234|  }
15460|       |
15461|       |  // Skip interim (1xx) responses along with their header fields, except a 100
15462|       |  // Continue the caller handles itself for Expect: 100-continue. 101 ends
15463|       |  // HTTP on the connection, so it is final. A server sending them without end
15464|       |  // would hold the client, so there may be only so many.
15465|  2.78k|  size_t interim_count = 0;
15466|  3.85k|  while (100 <= res.status && res.status < 200 &&
  ------------------
  |  Branch (15466:10): [True: 3.52k, False: 332]
  |  Branch (15466:31): [True: 1.59k, False: 1.92k]
  ------------------
15467|  1.59k|         res.status != StatusCode::SwitchingProtocol_101 &&
  ------------------
  |  Branch (15467:10): [True: 1.58k, False: 16]
  ------------------
15468|  1.58k|         (skip_100_continue || res.status != StatusCode::Continue_100)) {
  ------------------
  |  Branch (15468:11): [True: 1.58k, False: 0]
  |  Branch (15468:32): [True: 0, False: 0]
  ------------------
15469|  1.58k|    if (++interim_count > CPPHTTPLIB_INTERIM_RESPONSE_MAX_COUNT) {
  ------------------
  |  |  134|  1.58k|#define CPPHTTPLIB_INTERIM_RESPONSE_MAX_COUNT 100
  ------------------
  |  Branch (15469:9): [True: 2, False: 1.57k]
  ------------------
15470|      2|      return false;
15471|      2|    }
15472|  1.57k|    Headers interim_headers;
15473|  1.57k|    if (!detail::read_headers(strm, interim_headers)) { return false; }
  ------------------
  |  Branch (15473:9): [True: 216, False: 1.36k]
  ------------------
15474|  1.36k|    if (!line_reader.getline()) { return false; } // next response line
  ------------------
  |  Branch (15474:9): [True: 107, False: 1.25k]
  ------------------
15475|       |
15476|  1.25k|    if (!detail::parse_status_line(line_reader.ptr(), res.version, res.status,
  ------------------
  |  Branch (15476:9): [True: 190, False: 1.06k]
  ------------------
15477|  1.25k|                                   res.reason)) {
15478|    190|      return false;
15479|    190|    }
15480|  1.25k|  }
15481|       |
15482|  2.27k|  return true;
15483|  2.78k|}
_ZN7httplib6detail18stream_line_readerC2ERNS_6StreamEPcm:
 6369|  17.3k|    : strm_(strm), fixed_buffer_(fixed_buffer),
 6370|  17.3k|      fixed_buffer_size_(fixed_buffer_size) {}
_ZN7httplib6detail18stream_line_reader7getlineEv:
 6393|  29.8k|inline bool stream_line_reader::getline() {
 6394|  29.8k|  fixed_buffer_used_size_ = 0;
 6395|  29.8k|  growable_buffer_.clear();
 6396|       |
 6397|  29.8k|#ifndef CPPHTTPLIB_ALLOW_LF_AS_LINE_TERMINATOR
 6398|  29.8k|  char prev_byte = 0;
 6399|  29.8k|#endif
 6400|       |
 6401|  3.67M|  for (size_t i = 0;; i++) {
 6402|       |    // Fast path: whatever the stream has already buffered can be scanned for
 6403|       |    // the terminator in one pass. Asking for a byte at a time costs a virtual
 6404|       |    // call, a bounds check and a one-byte copy per character of the request.
 6405|  3.67M|    size_t buffered_size = 0;
 6406|  3.67M|    if (auto buffered = strm_.buffered_data(buffered_size)) {
  ------------------
  |  Branch (6406:14): [True: 0, False: 3.67M]
  ------------------
 6407|      0|      auto take = buffered_size;
 6408|      0|      auto terminated = false;
 6409|       |
 6410|      0|      for (size_t at = 0; at < buffered_size;) {
  ------------------
  |  Branch (6410:27): [True: 0, False: 0]
  ------------------
 6411|      0|        auto nl = static_cast<const char *>(
 6412|      0|            memchr(buffered + at, '\n', buffered_size - at));
 6413|      0|        if (!nl) { break; }
  ------------------
  |  Branch (6413:13): [True: 0, False: 0]
  ------------------
 6414|      0|        auto pos = static_cast<size_t>(nl - buffered);
 6415|       |#ifdef CPPHTTPLIB_ALLOW_LF_AS_LINE_TERMINATOR
 6416|       |        take = pos + 1;
 6417|       |        terminated = true;
 6418|       |        break;
 6419|       |#else
 6420|       |        // A bare LF does not end the line; keep looking for CRLF. The CR may
 6421|       |        // be the last byte of an earlier chunk, hence prev_byte.
 6422|      0|        if ((pos > 0 ? buffered[pos - 1] : prev_byte) == '\r') {
  ------------------
  |  Branch (6422:13): [True: 0, False: 0]
  |  Branch (6422:14): [True: 0, False: 0]
  ------------------
 6423|      0|          take = pos + 1;
 6424|      0|          terminated = true;
 6425|      0|          break;
 6426|      0|        }
 6427|      0|        at = pos + 1;
 6428|      0|#endif
 6429|      0|      }
 6430|       |
 6431|      0|      if (size() + take > CPPHTTPLIB_MAX_LINE_LENGTH) { return false; }
  ------------------
  |  |  227|      0|#define CPPHTTPLIB_MAX_LINE_LENGTH 32768
  ------------------
  |  Branch (6431:11): [True: 0, False: 0]
  ------------------
 6432|      0|#ifndef CPPHTTPLIB_ALLOW_LF_AS_LINE_TERMINATOR
 6433|      0|      prev_byte = buffered[take - 1];
 6434|      0|#endif
 6435|      0|      append(buffered, take);
 6436|      0|      strm_.consume_buffered(take);
 6437|      0|      i += take;
 6438|      0|      if (terminated) { return true; }
  ------------------
  |  Branch (6438:11): [True: 0, False: 0]
  ------------------
 6439|      0|      continue;
 6440|      0|    }
 6441|       |
 6442|  3.67M|    if (size() >= CPPHTTPLIB_MAX_LINE_LENGTH) {
  ------------------
  |  |  227|  3.67M|#define CPPHTTPLIB_MAX_LINE_LENGTH 32768
  ------------------
  |  Branch (6442:9): [True: 3, False: 3.67M]
  ------------------
 6443|       |      // Treat exceptionally long lines as an error to
 6444|       |      // prevent infinite loops/memory exhaustion
 6445|      3|      return false;
 6446|      3|    }
 6447|  3.67M|    char byte;
 6448|  3.67M|    auto n = strm_.read(&byte, 1);
 6449|       |
 6450|  3.67M|    if (n < 0) {
  ------------------
  |  Branch (6450:9): [True: 0, False: 3.67M]
  ------------------
 6451|      0|      return false;
 6452|  3.67M|    } else if (n == 0) {
  ------------------
  |  Branch (6452:16): [True: 1.30k, False: 3.67M]
  ------------------
 6453|  1.30k|      if (i == 0) {
  ------------------
  |  Branch (6453:11): [True: 495, False: 809]
  ------------------
 6454|    495|        return false;
 6455|    809|      } else {
 6456|    809|        break;
 6457|    809|      }
 6458|  1.30k|    }
 6459|       |
 6460|  3.67M|    append(byte);
 6461|       |
 6462|       |#ifdef CPPHTTPLIB_ALLOW_LF_AS_LINE_TERMINATOR
 6463|       |    if (byte == '\n') { break; }
 6464|       |#else
 6465|  3.67M|    if (prev_byte == '\r' && byte == '\n') { break; }
  ------------------
  |  Branch (6465:9): [True: 29.0k, False: 3.64M]
  |  Branch (6465:30): [True: 28.5k, False: 542]
  ------------------
 6466|  3.64M|    prev_byte = byte;
 6467|  3.64M|#endif
 6468|  3.64M|  }
 6469|       |
 6470|  29.3k|  return true;
 6471|  29.8k|}
_ZNK7httplib6detail18stream_line_reader4sizeEv:
 6380|  3.75M|inline size_t stream_line_reader::size() const {
 6381|  3.75M|  if (growable_buffer_.empty()) {
  ------------------
  |  Branch (6381:7): [True: 2.01M, False: 1.73M]
  ------------------
 6382|  2.01M|    return fixed_buffer_used_size_;
 6383|  2.01M|  } else {
 6384|  1.73M|    return growable_buffer_.size();
 6385|  1.73M|  }
 6386|  3.75M|}
_ZN7httplib6detail18stream_line_reader6appendEPKcm:
 6475|  3.67M|inline void stream_line_reader::append(const char *data, size_t size) {
 6476|       |  // Once the line has outgrown the fixed buffer everything must keep going to
 6477|       |  // the growable one, even if a later chunk would have fit. Without the
 6478|       |  // emptiness check a short append after a long one would land in the fixed
 6479|       |  // buffer, which ptr() and size() no longer look at, and be lost.
 6480|  3.67M|  if (growable_buffer_.empty() &&
  ------------------
  |  Branch (6480:7): [True: 1.94M, False: 1.72M]
  ------------------
 6481|  1.94M|      fixed_buffer_used_size_ + size < fixed_buffer_size_) {
  ------------------
  |  Branch (6481:7): [True: 1.94M, False: 2.83k]
  ------------------
 6482|  1.94M|    memcpy(fixed_buffer_ + fixed_buffer_used_size_, data, size);
 6483|  1.94M|    fixed_buffer_used_size_ += size;
 6484|  1.94M|    fixed_buffer_[fixed_buffer_used_size_] = '\0';
 6485|  1.94M|  } else {
 6486|       |    // Unlike the per-character overload, this can be the very first append of
 6487|       |    // the line, so the fixed buffer may hold nothing and carry no terminator
 6488|       |    // yet. assign() takes an explicit length and does not need one.
 6489|  1.72M|    if (growable_buffer_.empty()) {
  ------------------
  |  Branch (6489:9): [True: 2.83k, False: 1.72M]
  ------------------
 6490|  2.83k|      growable_buffer_.assign(fixed_buffer_, fixed_buffer_used_size_);
 6491|  2.83k|    }
 6492|  1.72M|    growable_buffer_.append(data, size);
 6493|  1.72M|  }
 6494|  3.67M|}
_ZN7httplib6detail18stream_line_reader6appendEc:
 6473|  3.67M|inline void stream_line_reader::append(char c) { append(&c, 1); }
_ZN7httplib6detail17parse_status_lineEPKcRNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEERiSA_:
 8425|  4.27k|                              int &status, std::string &reason) {
 8426|  4.27k|  if (std::strncmp(line, "HTTP/1.", 7) != 0 ||
  ------------------
  |  Branch (8426:7): [True: 228, False: 4.04k]
  ------------------
 8427|  4.04k|      (line[7] != '0' && line[7] != '1') || line[8] != ' ' ||
  ------------------
  |  Branch (8427:8): [True: 2.40k, False: 1.64k]
  |  Branch (8427:26): [True: 34, False: 2.37k]
  |  Branch (8427:45): [True: 6, False: 4.00k]
  ------------------
 8428|  4.00k|      !is_ascii_digit(line[9]) || !is_ascii_digit(line[10]) ||
  ------------------
  |  Branch (8428:7): [True: 10, False: 3.99k]
  |  Branch (8428:35): [True: 8, False: 3.99k]
  ------------------
 8429|  3.99k|      !is_ascii_digit(line[11])) {
  ------------------
  |  Branch (8429:7): [True: 8, False: 3.98k]
  ------------------
 8430|    294|    return false;
 8431|    294|  }
 8432|       |
 8433|  3.98k|  auto p = line + 12;
 8434|  3.98k|  auto reason_begin = p;
 8435|  3.98k|  if (*p == ' ') {
  ------------------
  |  Branch (8435:7): [True: 744, False: 3.23k]
  ------------------
 8436|    744|    reason_begin = ++p;
 8437|    744|    p += std::strcspn(p, "\r\n");
 8438|    744|  }
 8439|  3.98k|  auto reason_end = p;
 8440|       |
 8441|       |#ifdef CPPHTTPLIB_ALLOW_LF_AS_LINE_TERMINATOR
 8442|       |  if (*p == '\r') { p++; }
 8443|       |#else
 8444|  3.98k|  if (*p++ != '\r') { return false; }
  ------------------
  |  Branch (8444:7): [True: 127, False: 3.85k]
  ------------------
 8445|  3.85k|#endif
 8446|  3.85k|  if (*p++ != '\n' || *p != '\0') { return false; }
  ------------------
  |  Branch (8446:7): [True: 3, False: 3.85k]
  |  Branch (8446:23): [True: 0, False: 3.85k]
  ------------------
 8447|       |
 8448|  3.85k|  version.assign(line, 8);
 8449|  3.85k|  status = (line[9] - '0') * 100 + (line[10] - '0') * 10 + (line[11] - '0');
 8450|  3.85k|  reason.assign(reason_begin, reason_end);
 8451|  3.85k|  return true;
 8452|  3.85k|}
_ZNK7httplib6detail18stream_line_reader3ptrEv:
 6372|  63.5k|inline const char *stream_line_reader::ptr() const {
 6373|  63.5k|  if (growable_buffer_.empty()) {
  ------------------
  |  Branch (6373:7): [True: 55.1k, False: 8.38k]
  ------------------
 6374|  55.1k|    return fixed_buffer_;
 6375|  55.1k|  } else {
 6376|  8.38k|    return growable_buffer_.data();
 6377|  8.38k|  }
 6378|  63.5k|}
_ZN7httplib10ClientImpl18write_request_bodyERNS_6StreamERNS_7RequestERNS_5ErrorE:
16531|  3.02k|                                           Error &error) {
16532|  3.02k|  if (req.body.empty()) {
  ------------------
  |  Branch (16532:7): [True: 3.02k, False: 0]
  ------------------
16533|  3.02k|    return write_content_with_provider(strm, req, error);
16534|  3.02k|  }
16535|       |
16536|      0|  if (req.upload_progress) {
  ------------------
  |  Branch (16536:7): [True: 0, False: 0]
  ------------------
16537|      0|    auto body_size = req.body.size();
16538|      0|    size_t written = 0;
16539|      0|    auto data = req.body.data();
16540|       |
16541|      0|    while (written < body_size) {
  ------------------
  |  Branch (16541:12): [True: 0, False: 0]
  ------------------
16542|      0|      size_t to_write = (std::min)(CPPHTTPLIB_SEND_BUFSIZ, body_size - written);
  ------------------
  |  |  192|      0|#define CPPHTTPLIB_SEND_BUFSIZ size_t(16384u)
  ------------------
16543|      0|      if (!detail::write_data(strm, data + written, to_write)) {
  ------------------
  |  Branch (16543:11): [True: 0, False: 0]
  ------------------
16544|      0|        error = Error::Write;
16545|      0|        output_error_log(error, &req);
16546|      0|        return false;
16547|      0|      }
16548|      0|      written += to_write;
16549|       |
16550|      0|      if (!req.upload_progress(written, body_size)) {
  ------------------
  |  Branch (16550:11): [True: 0, False: 0]
  ------------------
16551|      0|        error = Error::Canceled;
16552|      0|        output_error_log(error, &req);
16553|      0|        return false;
16554|      0|      }
16555|      0|    }
16556|      0|  } else {
16557|      0|    if (!detail::write_data(strm, req.body.data(), req.body.size())) {
  ------------------
  |  Branch (16557:9): [True: 0, False: 0]
  ------------------
16558|      0|      error = Error::Write;
16559|      0|      output_error_log(error, &req);
16560|      0|      return false;
16561|      0|    }
16562|      0|  }
16563|       |
16564|      0|  return true;
16565|      0|}
_ZNK7httplib10ClientImpl27write_content_with_providerERNS_6StreamERKNS_7RequestERNS_5ErrorE:
16345|  3.02k|                                                    Error &error) const {
16346|  3.02k|  auto is_shutting_down = []() { return false; };
16347|       |
16348|  3.02k|  if (req.is_chunked_content_provider_) {
  ------------------
  |  Branch (16348:7): [True: 0, False: 3.02k]
  ------------------
16349|      0|    auto compressor = compress_ ? detail::create_compressor().first
  ------------------
  |  Branch (16349:23): [True: 0, False: 0]
  ------------------
16350|      0|                                : std::unique_ptr<detail::compressor>();
16351|      0|    if (!compressor) {
  ------------------
  |  Branch (16351:9): [True: 0, False: 0]
  ------------------
16352|      0|      compressor = detail::make_unique<detail::nocompressor>();
16353|      0|    }
16354|       |
16355|      0|    return detail::write_content_chunked(strm, req.content_provider_,
16356|      0|                                         is_shutting_down, *compressor, error);
16357|  3.02k|  } else {
16358|  3.02k|    return detail::write_content_with_progress(
16359|  3.02k|        strm, req.content_provider_, 0, req.content_length_, is_shutting_down,
16360|  3.02k|        req.upload_progress, error);
16361|  3.02k|  }
16362|  3.02k|}
_ZN7httplib8DataSinkC2Ev:
 1551|  3.02k|  DataSink() : os(&sb_), sb_(*this) {}
_ZN7httplib8DataSink19data_sink_streambufC2ERS0_:
 1574|  3.02k|    explicit data_sink_streambuf(DataSink &sink) : sink_(sink) {}
_ZN7httplib6detail27write_content_with_progressIZNKS_10ClientImpl27write_content_with_providerERNS_6StreamERKNS_7RequestERNS_5ErrorEEUlvE_EEbS4_RKNSt3__18functionIFbmmRNS_8DataSinkEEEEmmT_RKNSC_IFbmmEEES9_:
 8883|  3.02k|                                        Error &error) {
 8884|  3.02k|  size_t end_offset = offset + length;
 8885|  3.02k|  size_t start_offset = offset;
 8886|  3.02k|  auto ok = true;
 8887|  3.02k|  auto finished = false;
 8888|  3.02k|  DataSink data_sink;
 8889|       |
 8890|  3.02k|  data_sink.write = [&](const char *d, size_t l) -> bool {
 8891|  3.02k|    if (ok) {
 8892|       |      // Bytes past `length` would follow the framed body, where the peer reads
 8893|       |      // them as the next message. Write only what fits and fail the rest.
 8894|  3.02k|      if (l > end_offset - offset) {
 8895|  3.02k|        l = end_offset - offset;
 8896|  3.02k|        ok = false;
 8897|  3.02k|      }
 8898|  3.02k|      if (write_data(strm, d, l)) {
 8899|  3.02k|        offset += l;
 8900|       |
 8901|  3.02k|        if (upload_progress && length > 0) {
 8902|  3.02k|          size_t current_written = offset - start_offset;
 8903|  3.02k|          if (!upload_progress(current_written, length)) {
 8904|  3.02k|            ok = false;
 8905|  3.02k|            return false;
 8906|  3.02k|          }
 8907|  3.02k|        }
 8908|  3.02k|      } else {
 8909|  3.02k|        ok = false;
 8910|  3.02k|      }
 8911|  3.02k|    }
 8912|  3.02k|    return ok;
 8913|  3.02k|  };
 8914|       |
 8915|  3.02k|  data_sink.is_writable = [&]() -> bool { return strm.is_peer_alive(); };
 8916|       |
 8917|       |  // The body is framed by `length`, so a provider that reports itself done
 8918|       |  // early has truncated it. Record that and let the short-body check below
 8919|       |  // fail the write, rather than calling the provider again forever.
 8920|  3.02k|  data_sink.done = [&]() { finished = true; };
 8921|       |
 8922|  3.02k|  while (offset < end_offset && !finished && !is_shutting_down()) {
  ------------------
  |  Branch (8922:10): [True: 0, False: 3.02k]
  |  Branch (8922:33): [True: 0, False: 0]
  |  Branch (8922:46): [True: 0, False: 0]
  ------------------
 8923|      0|    auto last_offset = offset;
 8924|       |
 8925|      0|    if (!strm.wait_writable() || !strm.is_peer_alive()) {
  ------------------
  |  Branch (8925:9): [True: 0, False: 0]
  |  Branch (8925:34): [True: 0, False: 0]
  ------------------
 8926|      0|      error = Error::Write;
 8927|      0|      return false;
 8928|      0|    } else if (!content_provider(offset, end_offset - offset, data_sink)) {
  ------------------
  |  Branch (8928:16): [True: 0, False: 0]
  ------------------
 8929|      0|      error = Error::Canceled;
 8930|      0|      return false;
 8931|      0|    } else if (!ok) {
  ------------------
  |  Branch (8931:16): [True: 0, False: 0]
  ------------------
 8932|      0|      error = Error::Write;
 8933|      0|      return false;
 8934|      0|    }
 8935|       |
 8936|       |    // A provider that reports success without writing anything and without
 8937|       |    // reporting itself done gets handed the same offset and length again on
 8938|       |    // the next pass, so it would spin here for as long as the peer stays
 8939|       |    // connected. Treat making no progress as a short body, like done() early.
 8940|      0|    if (!finished && offset == last_offset) {
  ------------------
  |  Branch (8940:9): [True: 0, False: 0]
  |  Branch (8940:22): [True: 0, False: 0]
  ------------------
 8941|      0|      error = Error::Write;
 8942|      0|      return false;
 8943|      0|    }
 8944|      0|  }
 8945|       |
 8946|  3.02k|  if (offset < end_offset) { // done() called early, or is_shutting_down()
  ------------------
  |  Branch (8946:7): [True: 0, False: 3.02k]
  ------------------
 8947|      0|    error = Error::Write;
 8948|      0|    return false;
 8949|      0|  }
 8950|       |
 8951|  3.02k|  error = Error::Success;
 8952|  3.02k|  return true;
 8953|  3.02k|}
_ZN7httplib6detail12read_headersERNS_6StreamERNS0_26insertion_ordered_multimapINSt3__112basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEENS0_11case_ignore8equal_toEEE:
 8366|  3.85k|inline bool read_headers(Stream &strm, Headers &headers) {
 8367|  3.85k|  const auto bufsiz = 2048;
 8368|  3.85k|  char buf[bufsiz];
 8369|  3.85k|  stream_line_reader line_reader(strm, buf, bufsiz);
 8370|       |
 8371|  3.85k|  size_t header_count = 0;
 8372|       |
 8373|  13.7k|  for (;;) {
 8374|  13.7k|    if (!line_reader.getline()) { return false; }
  ------------------
  |  Branch (8374:9): [True: 323, False: 13.4k]
  ------------------
 8375|       |
 8376|       |    // Check if the line ends with CRLF.
 8377|  13.4k|    auto line_terminator_len = 2;
 8378|  13.4k|    if (line_reader.end_with_crlf()) {
  ------------------
  |  Branch (8378:9): [True: 13.3k, False: 86]
  ------------------
 8379|       |      // Blank line indicates end of headers.
 8380|  13.3k|      if (line_reader.size() == 2) { break; }
  ------------------
  |  Branch (8380:11): [True: 3.09k, False: 10.2k]
  ------------------
 8381|  13.3k|    } else {
 8382|       |#ifdef CPPHTTPLIB_ALLOW_LF_AS_LINE_TERMINATOR
 8383|       |      // Blank line indicates end of headers.
 8384|       |      if (line_reader.size() == 1) { break; }
 8385|       |      line_terminator_len = 1;
 8386|       |#else
 8387|     86|      continue; // Skip invalid line.
 8388|     86|#endif
 8389|     86|    }
 8390|       |
 8391|  10.2k|    if (line_reader.size() > CPPHTTPLIB_HEADER_MAX_LENGTH) { return false; }
  ------------------
  |  |  122|  10.2k|#define CPPHTTPLIB_HEADER_MAX_LENGTH 8192
  ------------------
  |  Branch (8391:9): [True: 4, False: 10.2k]
  ------------------
 8392|       |
 8393|       |    // Check header count limit
 8394|  10.2k|    if (header_count >= CPPHTTPLIB_HEADER_MAX_COUNT) { return false; }
  ------------------
  |  |  126|  10.2k|#define CPPHTTPLIB_HEADER_MAX_COUNT 100
  ------------------
  |  Branch (8394:9): [True: 1, False: 10.2k]
  ------------------
 8395|       |
 8396|       |    // Exclude line terminator
 8397|  10.2k|    auto end = line_reader.ptr() + line_reader.size() - line_terminator_len;
 8398|       |
 8399|  10.2k|    if (!parse_header(line_reader.ptr(), end,
  ------------------
  |  Branch (8399:9): [True: 428, False: 9.82k]
  ------------------
 8400|  10.2k|                      [&](const std::string &key, const std::string &val) {
 8401|  10.2k|                        headers.emplace(key, val);
 8402|  10.2k|                      })) {
 8403|    428|      return false;
 8404|    428|    }
 8405|       |
 8406|  9.82k|    header_count++;
 8407|  9.82k|  }
 8408|       |
 8409|       |  // RFC 9110 Section 8.6: Reject requests with multiple Content-Length
 8410|       |  // headers that have different values to prevent request smuggling.
 8411|  3.09k|  auto cl_range = headers.equal_range("Content-Length");
 8412|  3.09k|  if (cl_range.first != cl_range.second) {
  ------------------
  |  Branch (8412:7): [True: 840, False: 2.25k]
  ------------------
 8413|    840|    const auto &first_val = cl_range.first->second;
 8414|  1.47k|    for (auto it = std::next(cl_range.first); it != cl_range.second; ++it) {
  ------------------
  |  Branch (8414:47): [True: 809, False: 663]
  ------------------
 8415|    809|      if (it->second != first_val) { return false; }
  ------------------
  |  Branch (8415:11): [True: 177, False: 632]
  ------------------
 8416|    809|    }
 8417|    840|  }
 8418|       |
 8419|  2.91k|  return true;
 8420|  3.09k|}
_ZNK7httplib6detail18stream_line_reader13end_with_crlfEv:
 6388|  18.8k|inline bool stream_line_reader::end_with_crlf() const {
 6389|  18.8k|  auto end = ptr() + size();
 6390|  18.8k|  return size() >= 2 && end[-2] == '\r' && end[-1] == '\n';
  ------------------
  |  Branch (6390:10): [True: 18.8k, False: 66]
  |  Branch (6390:25): [True: 18.5k, False: 218]
  |  Branch (6390:44): [True: 18.5k, False: 20]
  ------------------
 6391|  18.8k|}
_ZN7httplib6detail12parse_headerIZNS0_12read_headersERNS_6StreamERNS0_26insertion_ordered_multimapINSt3__112basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEENS0_11case_ignore8equal_toEEEEUlRKSB_SH_E_EEbPKcSK_T_:
 6051|  10.2k|inline bool parse_header(const char *beg, const char *end, T fn) {
 6052|       |  // Skip trailing spaces and tabs.
 6053|  10.6k|  while (beg < end && is_space_or_tab(end[-1])) {
  ------------------
  |  Branch (6053:10): [True: 10.6k, False: 15]
  |  Branch (6053:23): [True: 390, False: 10.2k]
  ------------------
 6054|    390|    end--;
 6055|    390|  }
 6056|       |
 6057|  10.2k|  auto p = beg;
 6058|   178k|  while (p < end && *p != ':') {
  ------------------
  |  Branch (6058:10): [True: 178k, False: 347]
  |  Branch (6058:21): [True: 168k, False: 9.90k]
  ------------------
 6059|   168k|    p++;
 6060|   168k|  }
 6061|       |
 6062|  10.2k|  auto name = std::string(beg, p);
 6063|  10.2k|  if (!detail::fields::is_field_name(name)) { return false; }
  ------------------
  |  Branch (6063:7): [True: 175, False: 10.0k]
  ------------------
 6064|       |
 6065|  10.0k|  if (p == end) { return false; }
  ------------------
  |  Branch (6065:7): [True: 195, False: 9.88k]
  ------------------
 6066|       |
 6067|  9.88k|  auto key_end = p;
 6068|       |
 6069|  9.88k|  if (*p++ != ':') { return false; }
  ------------------
  |  Branch (6069:7): [True: 0, False: 9.88k]
  ------------------
 6070|       |
 6071|  10.2k|  while (p < end && is_space_or_tab(*p)) {
  ------------------
  |  Branch (6071:10): [True: 4.38k, False: 5.88k]
  |  Branch (6071:21): [True: 384, False: 4.00k]
  ------------------
 6072|    384|    p++;
 6073|    384|  }
 6074|       |
 6075|  9.88k|  if (p <= end) {
  ------------------
  |  Branch (6075:7): [True: 9.88k, False: 0]
  ------------------
 6076|  9.88k|    auto key_len = key_end - beg;
 6077|  9.88k|    if (!key_len) { return false; }
  ------------------
  |  Branch (6077:9): [True: 0, False: 9.88k]
  ------------------
 6078|       |
 6079|  9.88k|    auto key = std::string(beg, key_end);
 6080|  9.88k|    auto val = std::string(p, end);
 6081|       |
 6082|  9.88k|    if (!detail::fields::is_field_value(val)) { return false; }
  ------------------
  |  Branch (6082:9): [True: 58, False: 9.82k]
  ------------------
 6083|       |
 6084|       |    // RFC 9110 §5.5: header field values are opaque octets and MUST NOT be
 6085|       |    // percent-decoded by the recipient. Applications that need to interpret a
 6086|       |    // value as a URI component should call httplib::decode_uri_component()
 6087|       |    // (or decode_path_component()) explicitly.
 6088|  9.82k|    fn(key, val);
 6089|       |
 6090|  9.82k|    return true;
 6091|  9.88k|  }
 6092|       |
 6093|      0|  return false;
 6094|  9.88k|}
_ZZN7httplib6detail12read_headersERNS_6StreamERNS0_26insertion_ordered_multimapINSt3__112basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEENS0_11case_ignore8equal_toEEEENKUlRKSA_SG_E_clESG_SG_:
 8400|  9.82k|                      [&](const std::string &key, const std::string &val) {
 8401|  9.82k|                        headers.emplace(key, val);
 8402|  9.82k|                      })) {
_ZN7httplib6detail26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEE11equal_rangeERKS8_:
 1308|  3.09k|  std::pair<iterator, iterator> equal_range(const std::string &key) {
 1309|  3.09k|    auto i = index_of(key);
 1310|  3.09k|    return i == npos() ? std::make_pair(end(), end())
  ------------------
  |  Branch (1310:12): [True: 2.25k, False: 840]
  ------------------
 1311|  3.09k|                       : std::make_pair(make_iter(i, i), end());
 1312|  3.09k|  }
_ZNK7httplib6detail26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEE10iterator_tINS2_4pairIS8_S8_EEEptEv:
 1182|  1.64k|    pointer operator->() const { return data_ + idx_; }
_ZNK7httplib10ClientImpl16output_error_logERKNS_5ErrorEPKNS_7RequestE:
16715|  2.62k|                                         const Request *req) const {
16716|  2.62k|  if (error_logger_) {
  ------------------
  |  Branch (16716:7): [True: 0, False: 2.62k]
  ------------------
16717|      0|    std::lock_guard<std::mutex> guard(logger_mutex_);
16718|      0|    error_logger_(err, req);
16719|      0|  }
16720|  2.62k|}
_ZN7httplib6detail30has_conflicting_content_lengthERKNS0_26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEEE:
 8691|  1.53k|inline bool has_conflicting_content_length(const Headers &headers) {
 8692|       |  // RFC 9112 §6.3: a message carrying both Transfer-Encoding and a non-zero
 8693|       |  // Content-Length is framed ambiguously. The body readers here delimit it by
 8694|       |  // the transfer coding and drop Content-Length, while an intermediary may do
 8695|       |  // the reverse, so the two disagree on where the body ends and a reused
 8696|       |  // connection is desynchronised (request/response smuggling). Content-Length:
 8697|       |  // 0 is tolerated for compatibility with existing peers.
 8698|  1.53k|  return has_header(headers, "Transfer-Encoding") &&
  ------------------
  |  Branch (8698:10): [True: 919, False: 618]
  ------------------
 8699|    919|         get_header_value_u64(headers, "Content-Length", 0, 0) > 0;
  ------------------
  |  Branch (8699:10): [True: 102, False: 817]
  ------------------
 8700|  1.53k|}
_ZN7httplib6detail20get_header_value_u64ERKNS0_26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEEERKS8_mm:
 3588|  1.38k|                                   size_t id) {
 3589|  1.38k|  auto dummy = false;
 3590|  1.38k|  return get_header_value_u64(headers, key, def, id, dummy);
 3591|  1.38k|}
_ZN7httplib6detail20get_header_value_u64ERKNS0_26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEEERKS8_mmRb:
 3561|  1.77k|                                   size_t id, bool &is_invalid_value) {
 3562|  1.77k|  is_invalid_value = false;
 3563|  1.77k|  auto rng = headers.equal_range(key);
 3564|  1.77k|  auto it = bounded_next(rng.first, id, rng.second);
 3565|  1.77k|  if (it != rng.second) {
  ------------------
  |  Branch (3565:7): [True: 1.00k, False: 772]
  ------------------
 3566|  1.00k|    if (is_numeric(it->second)) {
  ------------------
  |  Branch (3566:9): [True: 808, False: 199]
  ------------------
 3567|       |      // Parse at size_t width so an out-of-range Content-Length is reported
 3568|       |      // rather than silently saturated/truncated (a value above 2^32 would
 3569|       |      // otherwise wrap to a small framing length on 32-bit builds). Flag it
 3570|       |      // and return SIZE_MAX so the existing oversized-value guards reject it.
 3571|    808|      size_t val = 0;
 3572|    808|      const auto &s = it->second;
 3573|    808|      auto r = from_chars(s.data(), s.data() + s.size(), val);
 3574|    808|      if (r.ec == std::errc::result_out_of_range) {
  ------------------
  |  Branch (3574:11): [True: 51, False: 757]
  ------------------
 3575|     51|        is_invalid_value = true;
 3576|     51|        return (std::numeric_limits<size_t>::max)();
 3577|     51|      }
 3578|    757|      return val;
 3579|    808|    } else {
 3580|    199|      is_invalid_value = true;
 3581|    199|    }
 3582|  1.00k|  }
 3583|    971|  return def;
 3584|  1.77k|}
_ZN7httplib6detail12bounded_nextINS0_26insertion_ordered_multimapINSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEENS0_11case_ignore8equal_toEE10iterator_tIKNS3_4pairIS9_S9_EEEEEET_SI_mSI_:
 3552|  1.77k|template <typename It> inline It bounded_next(It first, size_t n, It last) {
 3553|  1.77k|  for (; n > 0 && first != last; --n) {
  ------------------
  |  Branch (3553:10): [True: 0, False: 1.77k]
  |  Branch (3553:19): [True: 0, False: 0]
  ------------------
 3554|      0|    ++first;
 3555|      0|  }
 3556|  1.77k|  return first;
 3557|  1.77k|}
_ZN7httplib6detail10is_numericERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
 3547|  1.00k|inline bool is_numeric(const std::string &str) {
 3548|  1.00k|  return !str.empty() && std::all_of(str.cbegin(), str.cend(), is_ascii_digit);
  ------------------
  |  Branch (3548:10): [True: 869, False: 138]
  |  Branch (3548:26): [True: 808, False: 61]
  ------------------
 3549|  1.00k|}
_ZN7httplib6detail10from_charsImEENS0_17from_chars_resultIT_EEPKcS6_RS3_i:
  763|    808|                                       T &value, int base = 10) {
  764|    808|  value = 0;
  765|    808|  const char *p = first;
  766|    808|  bool negative = false;
  767|       |
  768|    808|  if (p != last && *p == '-') {
  ------------------
  |  Branch (768:7): [True: 808, False: 0]
  |  Branch (768:20): [True: 0, False: 808]
  ------------------
  769|      0|    negative = true;
  770|      0|    ++p;
  771|      0|  }
  772|    808|  if (p == last) { return {first, std::errc::invalid_argument}; }
  ------------------
  |  Branch (772:7): [True: 0, False: 808]
  ------------------
  773|       |
  774|    808|  T result = 0;
  775|  12.5k|  for (; p != last; ++p) {
  ------------------
  |  Branch (775:10): [True: 11.8k, False: 757]
  ------------------
  776|  11.8k|    char c = *p;
  777|  11.8k|    int digit = -1;
  778|  11.8k|    if (is_ascii_digit(c)) {
  ------------------
  |  Branch (778:9): [True: 11.8k, False: 0]
  ------------------
  779|  11.8k|      digit = c - '0';
  780|  11.8k|    } else if ('a' <= c && c <= 'z') {
  ------------------
  |  Branch (780:16): [True: 0, False: 0]
  |  Branch (780:28): [True: 0, False: 0]
  ------------------
  781|      0|      digit = c - 'a' + 10;
  782|      0|    } else if ('A' <= c && c <= 'Z') {
  ------------------
  |  Branch (782:16): [True: 0, False: 0]
  |  Branch (782:28): [True: 0, False: 0]
  ------------------
  783|      0|      digit = c - 'A' + 10;
  784|      0|    } else {
  785|      0|      break;
  786|      0|    }
  787|       |
  788|  11.8k|    if (digit < 0 || digit >= base) { break; }
  ------------------
  |  Branch (788:9): [True: 0, False: 11.8k]
  |  Branch (788:22): [True: 0, False: 11.8k]
  ------------------
  789|  11.8k|    if (result > ((std::numeric_limits<T>::max)() - digit) / base) {
  ------------------
  |  Branch (789:9): [True: 51, False: 11.7k]
  ------------------
  790|     51|      return {p, std::errc::result_out_of_range};
  791|     51|    }
  792|  11.7k|    result = result * base + digit;
  793|  11.7k|  }
  794|       |
  795|    757|  if (p == first || (negative && p == first + 1)) {
  ------------------
  |  Branch (795:7): [True: 0, False: 757]
  |  Branch (795:22): [True: 0, False: 757]
  |  Branch (795:34): [True: 0, False: 0]
  ------------------
  796|      0|    return {first, std::errc::invalid_argument};
  797|      0|  }
  798|       |
  799|    757|  value = negative ? T(0) - result : result;
  ------------------
  |  Branch (799:11): [True: 0, False: 757]
  ------------------
  800|    757|  return {p, std::errc{}};
  801|    757|}
_ZN7httplib6detail28has_faulty_transfer_encodingINS_8ResponseEEEbRKT_:
 8686|  1.43k|template <typename T> inline bool has_faulty_transfer_encoding(const T &msg) {
 8687|  1.43k|  return msg.has_header("Transfer-Encoding") &&
  ------------------
  |  Branch (8687:10): [True: 817, False: 618]
  ------------------
 8688|    817|         (msg.has_header("Content-Length") || msg.version == "HTTP/1.0");
  ------------------
  |  Branch (8688:11): [True: 45, False: 772]
  |  Branch (8688:47): [True: 372, False: 400]
  ------------------
 8689|  1.43k|}
_ZZN7httplib10ClientImpl15process_requestERNS_6StreamERNS_7RequestERNS_8ResponseEbRNS_5ErrorEENKUlPKcmmmE0_clESA_mmm:
16870|   126k|                      size_t /*len*/) {
16871|   126k|                    assert(res.body.size() + n <= res.body.max_size());
  ------------------
  |  Branch (16871:21): [True: 126k, False: 0]
  ------------------
16872|   126k|                    if (payload_max_length_ > 0 &&
  ------------------
  |  Branch (16872:25): [True: 126k, False: 0]
  ------------------
16873|   126k|                        (res.body.size() >= payload_max_length_ ||
  ------------------
  |  Branch (16873:26): [True: 0, False: 126k]
  ------------------
16874|   126k|                         n > payload_max_length_ - res.body.size())) {
  ------------------
  |  Branch (16874:26): [True: 0, False: 126k]
  ------------------
16875|      0|                      return false;
16876|      0|                    }
16877|   126k|                    res.body.append(buf, n);
16878|   126k|                    return true;
16879|   126k|                  });
_ZNK7httplib8Response10has_headerERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
12167|  3.69k|inline bool Response::has_header(const std::string &key) const {
12168|  3.69k|  return headers.find(key) != headers.end();
12169|  3.69k|}
_ZNK7httplib8Response20get_header_value_u64ERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEmm:
12163|    466|                                             size_t id) const {
12164|    466|  return detail::get_header_value_u64(headers, key, def, id);
12165|    466|}
_ZN7httplib6detail12read_contentINS_8ResponseEEEbRNS_6StreamERT_mRiNSt3__18functionIFbmmEEENS9_IFbPKcmmmEEEb:
 8760|  1.38k|                  ContentReceiverWithProgress receiver, bool decompress) {
 8761|  1.38k|  bool exceed_payload_max_length = false;
 8762|  1.38k|  return prepare_content_receiver(
 8763|  1.38k|      x, status, std::move(receiver), decompress, payload_max_length,
 8764|  1.38k|      exceed_payload_max_length, [&](const ContentReceiverWithProgress &out) {
 8765|  1.38k|        auto ret = true;
 8766|       |        // Note: exceed_payload_max_length may also be set by the decompressor
 8767|       |        // wrapper in prepare_content_receiver when the decompressed payload
 8768|       |        // size exceeds the limit.
 8769|       |
 8770|  1.38k|        if (is_chunked_transfer_encoding(x.headers)) {
 8771|  1.38k|          auto result = read_content_chunked(strm, x, payload_max_length, out);
 8772|  1.38k|          if (result == ReadContentResult::Success) {
 8773|  1.38k|            ret = true;
 8774|  1.38k|          } else if (result == ReadContentResult::PayloadTooLarge) {
 8775|  1.38k|            exceed_payload_max_length = true;
 8776|  1.38k|            ret = false;
 8777|  1.38k|          } else {
 8778|  1.38k|            ret = false;
 8779|  1.38k|          }
 8780|  1.38k|        } else if (!has_header(x.headers, "Content-Length")) {
 8781|  1.38k|          auto result =
 8782|  1.38k|              read_content_without_length(strm, payload_max_length, out);
 8783|  1.38k|          if (result == ReadContentResult::Success) {
 8784|  1.38k|            ret = true;
 8785|  1.38k|          } else if (result == ReadContentResult::PayloadTooLarge) {
 8786|  1.38k|            exceed_payload_max_length = true;
 8787|  1.38k|            ret = false;
 8788|  1.38k|          } else {
 8789|  1.38k|            ret = false;
 8790|  1.38k|          }
 8791|  1.38k|        } else {
 8792|  1.38k|          auto is_invalid_value = false;
 8793|  1.38k|          auto len = get_header_value_u64(x.headers, "Content-Length",
 8794|  1.38k|                                          (std::numeric_limits<size_t>::max)(),
 8795|  1.38k|                                          0, is_invalid_value);
 8796|       |
 8797|  1.38k|          if (is_invalid_value) {
 8798|  1.38k|            ret = false;
 8799|  1.38k|          } else if (len > 0) {
 8800|  1.38k|            auto result = read_content_with_length(
 8801|  1.38k|                strm, len, std::move(progress), out, payload_max_length);
 8802|  1.38k|            ret = (result == ReadContentResult::Success);
 8803|  1.38k|            if (result == ReadContentResult::PayloadTooLarge) {
 8804|  1.38k|              exceed_payload_max_length = true;
 8805|  1.38k|            }
 8806|  1.38k|          }
 8807|  1.38k|        }
 8808|       |
 8809|  1.38k|        if (!ret) {
 8810|  1.38k|          status = exceed_payload_max_length ? StatusCode::PayloadTooLarge_413
 8811|  1.38k|                                             : StatusCode::BadRequest_400;
 8812|  1.38k|        }
 8813|  1.38k|        return ret;
 8814|  1.38k|      });
 8815|  1.38k|}
_ZN7httplib6detail24prepare_content_receiverINS_8ResponseEZNS0_12read_contentIS2_EEbRNS_6StreamERT_mRiNSt3__18functionIFbmmEEENSA_IFbPKcmmmEEEbEUlRKSG_E_EEbS7_S8_SG_bmRbT0_:
 8706|  1.38k|                              bool &exceed_payload_max_length, U callback) {
 8707|  1.38k|  if (decompress) {
  ------------------
  |  Branch (8707:7): [True: 1.38k, False: 0]
  ------------------
 8708|  1.38k|    auto encoding = get_combined_header_value(x.headers, "Content-Encoding");
 8709|  1.38k|    std::unique_ptr<decompressor> decompressor;
 8710|       |
 8711|  1.38k|    if (!encoding.empty()) {
  ------------------
  |  Branch (8711:9): [True: 152, False: 1.23k]
  ------------------
 8712|       |      // A coding we know about but were not built with is an error. An
 8713|       |      // unrecognized coding (including "identity") is left alone and the
 8714|       |      // payload is passed through as-is, since some servers misuse the header,
 8715|       |      // e.g. by sending a character set such as "Content-Encoding: UTF-8".
 8716|    152|      decompressor = detail::create_decompressor(encoding);
 8717|    152|      if (!decompressor && detail::is_known_content_encoding(encoding)) {
  ------------------
  |  Branch (8717:11): [True: 23, False: 129]
  |  Branch (8717:28): [True: 2, False: 21]
  ------------------
 8718|      2|        status = StatusCode::UnsupportedMediaType_415;
 8719|      2|        return false;
 8720|      2|      }
 8721|    152|    }
 8722|       |
 8723|  1.38k|    if (decompressor) {
  ------------------
  |  Branch (8723:9): [True: 129, False: 1.25k]
  ------------------
 8724|    129|      if (decompressor->is_valid()) {
  ------------------
  |  Branch (8724:11): [True: 129, False: 0]
  ------------------
 8725|    129|        size_t decompressed_size = 0;
 8726|    129|        ContentReceiverWithProgress out = [&](const char *buf, size_t n,
 8727|    129|                                              size_t off, size_t len) {
 8728|    129|          return decompressor->decompress(
 8729|    129|              buf, n, [&](const char *buf2, size_t n2) {
 8730|       |                // Guard against zip-bomb: check
 8731|       |                // decompressed size against limit.
 8732|    129|                if (payload_max_length > 0 &&
 8733|    129|                    (decompressed_size >= payload_max_length ||
 8734|    129|                     n2 > payload_max_length - decompressed_size)) {
 8735|    129|                  exceed_payload_max_length = true;
 8736|    129|                  return false;
 8737|    129|                }
 8738|    129|                decompressed_size += n2;
 8739|    129|                return receiver(buf2, n2, off, len);
 8740|    129|              });
 8741|    129|        };
 8742|    129|        return callback(std::move(out));
 8743|    129|      } else {
 8744|      0|        status = StatusCode::InternalServerError_500;
 8745|      0|        return false;
 8746|      0|      }
 8747|    129|    }
 8748|  1.38k|  }
 8749|       |
 8750|  1.25k|  ContentReceiverWithProgress out = [&](const char *buf, size_t n, size_t off,
 8751|  1.25k|                                        size_t len) {
 8752|  1.25k|    return receiver(buf, n, off, len);
 8753|  1.25k|  };
 8754|  1.25k|  return callback(std::move(out));
 8755|  1.38k|}
_ZN7httplib6detail25get_combined_header_valueERKNS0_26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEEERKS8_:
 8319|  1.49k|                                             const std::string &key) {
 8320|  1.49k|  std::string combined;
 8321|  1.49k|  auto rng = headers.equal_range(key);
 8322|  2.29k|  for (auto it = rng.first; it != rng.second; ++it) {
  ------------------
  |  Branch (8322:29): [True: 791, False: 1.49k]
  ------------------
 8323|       |    // RFC 9110 Section 5.6.1.2: a recipient has to parse and ignore empty list
 8324|       |    // elements, so an empty field line must not contribute a bare comma to the
 8325|       |    // combined value.
 8326|    791|    if (it->second.empty()) { continue; }
  ------------------
  |  Branch (8326:9): [True: 69, False: 722]
  ------------------
 8327|    722|    if (!combined.empty()) { combined += ", "; }
  ------------------
  |  Branch (8327:9): [True: 570, False: 152]
  ------------------
 8328|    722|    combined += it->second;
 8329|    722|  }
 8330|  1.49k|  return combined;
 8331|  1.49k|}
_ZN7httplib6detail19create_decompressorERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
 8242|    152|create_decompressor(const std::string &encoding) {
 8243|    152|  std::unique_ptr<decompressor> decompressor;
 8244|       |
 8245|    152|  if (is_zlib_encoding(encoding)) {
  ------------------
  |  Branch (8245:7): [True: 129, False: 23]
  ------------------
 8246|    129|#ifdef CPPHTTPLIB_ZLIB_SUPPORT
 8247|    129|    decompressor = detail::make_unique<gzip_decompressor>();
 8248|    129|#endif
 8249|    129|  } else if (is_brotli_encoding(encoding)) {
  ------------------
  |  Branch (8249:14): [True: 1, False: 22]
  ------------------
 8250|       |#ifdef CPPHTTPLIB_BROTLI_SUPPORT
 8251|       |    decompressor = detail::make_unique<brotli_decompressor>();
 8252|       |#endif
 8253|     22|  } else if (is_zstd_encoding(encoding)) {
  ------------------
  |  Branch (8253:14): [True: 1, False: 21]
  ------------------
 8254|       |#ifdef CPPHTTPLIB_ZSTD_SUPPORT
 8255|       |    decompressor = detail::make_unique<zstd_decompressor>();
 8256|       |#endif
 8257|      1|  }
 8258|       |
 8259|    152|  return decompressor;
 8260|    152|}
_ZN7httplib6detail16is_zlib_encodingERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
 8221|    175|inline bool is_zlib_encoding(const std::string &encoding) {
 8222|    175|  return case_ignore::equal(encoding, "gzip") ||
  ------------------
  |  Branch (8222:10): [True: 14, False: 161]
  ------------------
 8223|    161|         case_ignore::equal(encoding, "deflate");
  ------------------
  |  Branch (8223:10): [True: 115, False: 46]
  ------------------
 8224|    175|}
_ZN7httplib6detail11case_ignore5equalILm5EEEbRKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEERAT__Kc:
  695|    219|inline bool equal(const std::string &a, const char (&b)[N]) {
  696|    219|  return a.size() == N - 1 &&
  ------------------
  |  Branch (696:10): [True: 22, False: 197]
  ------------------
  697|     22|         std::equal(a.begin(), a.end(), b, [](char ca, char cb) {
  ------------------
  |  Branch (697:10): [True: 16, False: 6]
  ------------------
  698|     22|           return to_lower(ca) == to_lower(cb);
  699|     22|         });
  700|    219|}
_ZZN7httplib6detail11case_ignore5equalILm5EEEbRKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEERAT__KcENKUlccE_clEcc:
  697|     72|         std::equal(a.begin(), a.end(), b, [](char ca, char cb) {
  698|     72|           return to_lower(ca) == to_lower(cb);
  699|     72|         });
_ZN7httplib6detail11case_ignore5equalILm8EEEbRKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEERAT__Kc:
  695|    978|inline bool equal(const std::string &a, const char (&b)[N]) {
  696|    978|  return a.size() == N - 1 &&
  ------------------
  |  Branch (696:10): [True: 696, False: 282]
  ------------------
  697|    696|         std::equal(a.begin(), a.end(), b, [](char ca, char cb) {
  ------------------
  |  Branch (697:10): [True: 691, False: 5]
  ------------------
  698|    696|           return to_lower(ca) == to_lower(cb);
  699|    696|         });
  700|    978|}
_ZZN7httplib6detail11case_ignore5equalILm8EEEbRKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEERAT__KcENKUlccE_clEcc:
  697|  4.84k|         std::equal(a.begin(), a.end(), b, [](char ca, char cb) {
  698|  4.84k|           return to_lower(ca) == to_lower(cb);
  699|  4.84k|         });
_ZN7httplib6detail11make_uniqueINS0_17gzip_decompressorEJEEENSt3__19enable_ifIXntsr3std8is_arrayIT_EE5valueENS3_10unique_ptrIS5_NS3_14default_deleteIS5_EEEEE4typeEDpOT0_:
  626|    129|make_unique(Args &&...args) {
  627|    129|  return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
  628|    129|}
_ZN7httplib6detail17gzip_decompressorC2Ev:
 8016|    129|inline gzip_decompressor::gzip_decompressor() {
 8017|    129|  std::memset(&strm_, 0, sizeof(strm_));
 8018|    129|  strm_.zalloc = Z_NULL;
 8019|    129|  strm_.zfree = Z_NULL;
 8020|    129|  strm_.opaque = Z_NULL;
 8021|       |
 8022|       |  // 15 is the value of wbits, which should be at the maximum possible value
 8023|       |  // to ensure that any gzip stream can be decoded. The offset of 32 specifies
 8024|       |  // that the stream type should be automatically detected either gzip or
 8025|       |  // deflate.
 8026|    129|  is_valid_ = inflateInit2(&strm_, 32 + 15) == Z_OK;
 8027|    129|}
_ZN7httplib6detail18is_brotli_encodingERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
 8226|     46|inline bool is_brotli_encoding(const std::string &encoding) {
 8227|     46|  return case_ignore::equal(encoding, "br");
 8228|     46|}
_ZN7httplib6detail11case_ignore5equalILm3EEEbRKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEERAT__Kc:
  695|     46|inline bool equal(const std::string &a, const char (&b)[N]) {
  696|     46|  return a.size() == N - 1 &&
  ------------------
  |  Branch (696:10): [True: 2, False: 44]
  ------------------
  697|      2|         std::equal(a.begin(), a.end(), b, [](char ca, char cb) {
  ------------------
  |  Branch (697:10): [True: 2, False: 0]
  ------------------
  698|      2|           return to_lower(ca) == to_lower(cb);
  699|      2|         });
  700|     46|}
_ZZN7httplib6detail11case_ignore5equalILm3EEEbRKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEERAT__KcENKUlccE_clEcc:
  697|      4|         std::equal(a.begin(), a.end(), b, [](char ca, char cb) {
  698|      4|           return to_lower(ca) == to_lower(cb);
  699|      4|         });
_ZN7httplib6detail16is_zstd_encodingERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
 8230|     44|inline bool is_zstd_encoding(const std::string &encoding) {
 8231|     44|  return case_ignore::equal(encoding, "zstd");
 8232|     44|}
_ZN7httplib6detail25is_known_content_encodingERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
 8236|     23|inline bool is_known_content_encoding(const std::string &encoding) {
 8237|     23|  return is_zlib_encoding(encoding) || is_brotli_encoding(encoding) ||
  ------------------
  |  Branch (8237:10): [True: 0, False: 23]
  |  Branch (8237:40): [True: 1, False: 22]
  ------------------
 8238|     22|         is_zstd_encoding(encoding);
  ------------------
  |  Branch (8238:10): [True: 1, False: 21]
  ------------------
 8239|     23|}
_ZZN7httplib6detail24prepare_content_receiverINS_8ResponseEZNS0_12read_contentIS2_EEbRNS_6StreamERT_mRiNSt3__18functionIFbmmEEENSA_IFbPKcmmmEEEbEUlRKSG_E_EEbS7_S8_SG_bmRbT0_ENKUlSE_mmmE_clESE_mmm:
 8727|  2.16k|                                              size_t off, size_t len) {
 8728|  2.16k|          return decompressor->decompress(
 8729|  2.16k|              buf, n, [&](const char *buf2, size_t n2) {
 8730|       |                // Guard against zip-bomb: check
 8731|       |                // decompressed size against limit.
 8732|  2.16k|                if (payload_max_length > 0 &&
 8733|  2.16k|                    (decompressed_size >= payload_max_length ||
 8734|  2.16k|                     n2 > payload_max_length - decompressed_size)) {
 8735|  2.16k|                  exceed_payload_max_length = true;
 8736|  2.16k|                  return false;
 8737|  2.16k|                }
 8738|  2.16k|                decompressed_size += n2;
 8739|  2.16k|                return receiver(buf2, n2, off, len);
 8740|  2.16k|              });
 8741|  2.16k|        };
_ZZZN7httplib6detail24prepare_content_receiverINS_8ResponseEZNS0_12read_contentIS2_EEbRNS_6StreamERT_mRiNSt3__18functionIFbmmEEENSA_IFbPKcmmmEEEbEUlRKSG_E_EEbS7_S8_SG_bmRbT0_ENKUlSE_mmmE_clESE_mmmENKUlSE_mE_clESE_m:
 8729|   121k|              buf, n, [&](const char *buf2, size_t n2) {
 8730|       |                // Guard against zip-bomb: check
 8731|       |                // decompressed size against limit.
 8732|   121k|                if (payload_max_length > 0 &&
  ------------------
  |  Branch (8732:21): [True: 121k, False: 0]
  ------------------
 8733|   121k|                    (decompressed_size >= payload_max_length ||
  ------------------
  |  Branch (8733:22): [True: 1, False: 121k]
  ------------------
 8734|   121k|                     n2 > payload_max_length - decompressed_size)) {
  ------------------
  |  Branch (8734:22): [True: 14, False: 121k]
  ------------------
 8735|     15|                  exceed_payload_max_length = true;
 8736|     15|                  return false;
 8737|     15|                }
 8738|   121k|                decompressed_size += n2;
 8739|   121k|                return receiver(buf2, n2, off, len);
 8740|   121k|              });
_ZZN7httplib6detail12read_contentINS_8ResponseEEEbRNS_6StreamERT_mRiNSt3__18functionIFbmmEEENS9_IFbPKcmmmEEEbENKUlRKSF_E_clESH_:
 8764|  1.38k|      exceed_payload_max_length, [&](const ContentReceiverWithProgress &out) {
 8765|  1.38k|        auto ret = true;
 8766|       |        // Note: exceed_payload_max_length may also be set by the decompressor
 8767|       |        // wrapper in prepare_content_receiver when the decompressed payload
 8768|       |        // size exceeds the limit.
 8769|       |
 8770|  1.38k|        if (is_chunked_transfer_encoding(x.headers)) {
  ------------------
  |  Branch (8770:13): [True: 576, False: 804]
  ------------------
 8771|    576|          auto result = read_content_chunked(strm, x, payload_max_length, out);
 8772|    576|          if (result == ReadContentResult::Success) {
  ------------------
  |  Branch (8772:15): [True: 1, False: 575]
  ------------------
 8773|      1|            ret = true;
 8774|    575|          } else if (result == ReadContentResult::PayloadTooLarge) {
  ------------------
  |  Branch (8774:22): [True: 0, False: 575]
  ------------------
 8775|      0|            exceed_payload_max_length = true;
 8776|      0|            ret = false;
 8777|    575|          } else {
 8778|    575|            ret = false;
 8779|    575|          }
 8780|    804|        } else if (!has_header(x.headers, "Content-Length")) {
  ------------------
  |  Branch (8780:20): [True: 410, False: 394]
  ------------------
 8781|    410|          auto result =
 8782|    410|              read_content_without_length(strm, payload_max_length, out);
 8783|    410|          if (result == ReadContentResult::Success) {
  ------------------
  |  Branch (8783:15): [True: 383, False: 27]
  ------------------
 8784|    383|            ret = true;
 8785|    383|          } else if (result == ReadContentResult::PayloadTooLarge) {
  ------------------
  |  Branch (8785:22): [True: 0, False: 27]
  ------------------
 8786|      0|            exceed_payload_max_length = true;
 8787|      0|            ret = false;
 8788|     27|          } else {
 8789|     27|            ret = false;
 8790|     27|          }
 8791|    410|        } else {
 8792|    394|          auto is_invalid_value = false;
 8793|    394|          auto len = get_header_value_u64(x.headers, "Content-Length",
 8794|    394|                                          (std::numeric_limits<size_t>::max)(),
 8795|    394|                                          0, is_invalid_value);
 8796|       |
 8797|    394|          if (is_invalid_value) {
  ------------------
  |  Branch (8797:15): [True: 70, False: 324]
  ------------------
 8798|     70|            ret = false;
 8799|    324|          } else if (len > 0) {
  ------------------
  |  Branch (8799:22): [True: 319, False: 5]
  ------------------
 8800|    319|            auto result = read_content_with_length(
 8801|    319|                strm, len, std::move(progress), out, payload_max_length);
 8802|    319|            ret = (result == ReadContentResult::Success);
 8803|    319|            if (result == ReadContentResult::PayloadTooLarge) {
  ------------------
  |  Branch (8803:17): [True: 0, False: 319]
  ------------------
 8804|      0|              exceed_payload_max_length = true;
 8805|      0|            }
 8806|    319|          }
 8807|    394|        }
 8808|       |
 8809|  1.38k|        if (!ret) {
  ------------------
  |  Branch (8809:13): [True: 990, False: 390]
  ------------------
 8810|    990|          status = exceed_payload_max_length ? StatusCode::PayloadTooLarge_413
  ------------------
  |  Branch (8810:20): [True: 15, False: 975]
  ------------------
 8811|    990|                                             : StatusCode::BadRequest_400;
 8812|    990|        }
 8813|  1.38k|        return ret;
 8814|  1.38k|      });
_ZN7httplib6detail28is_chunked_transfer_encodingERKNS0_26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEEE:
 8652|  1.38k|inline bool is_chunked_transfer_encoding(const Headers &headers) {
 8653|       |  // RFC 9112 6.1: a message is framed with the chunked coding when "chunked"
 8654|       |  // is the final transfer coding. A single field value may list several
 8655|       |  // codings ("gzip, chunked"), and RFC 9110 5.3 lets that list be split across
 8656|       |  // several Transfer-Encoding lines, which combine into one comma-separated
 8657|       |  // list in the order the lines were received. Headers preserves that order,
 8658|       |  // so the final coding is the last token of the last line. Match it
 8659|       |  // case-insensitively rather than comparing the whole value against
 8660|       |  // "chunked".
 8661|       |  //
 8662|       |  // Security: reading a chunked message as unframed leaves its body in the
 8663|       |  // socket, where a keep-alive connection parses it as a smuggled request.
 8664|       |  // Server::process_request() answers 400 and closes when the final coding is
 8665|       |  // not chunked, so a request whose framing cannot be determined never
 8666|       |  // reaches the "no body" path.
 8667|  1.38k|  auto rng = headers.equal_range("Transfer-Encoding");
 8668|  1.38k|  if (rng.first == rng.second) { return false; }
  ------------------
  |  Branch (8668:7): [True: 563, False: 817]
  ------------------
 8669|       |
 8670|       |  // Cleared per line, so a trailing line carrying no coding at all leaves the
 8671|       |  // combined list ending in nothing rather than inheriting the line before it.
 8672|    817|  std::string last_coding;
 8673|       |
 8674|  2.06k|  for (auto it = rng.first; it != rng.second; ++it) {
  ------------------
  |  Branch (8674:29): [True: 1.24k, False: 817]
  ------------------
 8675|  1.24k|    const auto &value = it->second;
 8676|  1.24k|    last_coding.clear();
 8677|  1.24k|    split(value.data(), value.data() + value.size(), ',',
 8678|  1.24k|          [&](const char *b, const char *e) { last_coding.assign(b, e); });
 8679|  1.24k|  }
 8680|       |
 8681|    817|  return case_ignore::equal(last_coding, "chunked");
 8682|  1.38k|}
_ZNK7httplib6detail26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEE10iterator_tIKNS2_4pairIS8_S8_EEEeqISF_EEbRKNSC_IT_EE:
 1220|  1.38k|    template <typename U> bool operator==(const iterator_t<U> &rhs) const {
 1221|  1.38k|      return idx_ == rhs.idx_;
 1222|  1.38k|    }
_ZZN7httplib6detail28is_chunked_transfer_encodingERKNS0_26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEEEENKUlPKcSF_E_clESF_SF_:
 8678|  5.06k|          [&](const char *b, const char *e) { last_coding.assign(b, e); });
_ZN7httplib6detail20read_content_chunkedINS_8ResponseEEENS0_17ReadContentResultERNS_6StreamERT_mNSt3__18functionIFbPKcmmmEEE:
 8619|    576|                                              ContentReceiverWithProgress out) {
 8620|    576|  detail::ChunkedDecoder dec(strm);
 8621|       |
 8622|    576|  char buf[CPPHTTPLIB_RECV_BUFSIZ];
 8623|    576|  size_t total_len = 0;
 8624|       |
 8625|  6.06k|  for (;;) {
 8626|  6.06k|    size_t chunk_offset = 0;
 8627|  6.06k|    size_t chunk_total = 0;
 8628|  6.06k|    auto n = dec.read_payload(buf, sizeof(buf), chunk_offset, chunk_total);
 8629|  6.06k|    if (n < 0) { return ReadContentResult::Error; }
  ------------------
  |  Branch (8629:9): [True: 440, False: 5.62k]
  ------------------
 8630|       |
 8631|  5.62k|    if (n == 0) {
  ------------------
  |  Branch (8631:9): [True: 132, False: 5.48k]
  ------------------
 8632|    132|      if (!dec.parse_trailers_into(x.trailers, x.headers)) {
  ------------------
  |  Branch (8632:11): [True: 131, False: 1]
  ------------------
 8633|    131|        return ReadContentResult::Error;
 8634|    131|      }
 8635|      1|      return ReadContentResult::Success;
 8636|    132|    }
 8637|       |
 8638|  5.48k|    if (payload_max_length > 0 &&
  ------------------
  |  Branch (8638:9): [True: 5.48k, False: 0]
  ------------------
 8639|  5.48k|        (total_len > payload_max_length ||
  ------------------
  |  Branch (8639:10): [True: 0, False: 5.48k]
  ------------------
 8640|  5.48k|         payload_max_length - total_len < static_cast<size_t>(n))) {
  ------------------
  |  Branch (8640:10): [True: 0, False: 5.48k]
  ------------------
 8641|      0|      return ReadContentResult::PayloadTooLarge;
 8642|      0|    }
 8643|       |
 8644|  5.48k|    if (!out(buf, static_cast<size_t>(n), chunk_offset, chunk_total)) {
  ------------------
  |  Branch (8644:9): [True: 4, False: 5.48k]
  ------------------
 8645|      4|      return ReadContentResult::Error;
 8646|      4|    }
 8647|       |
 8648|  5.48k|    total_len += static_cast<size_t>(n);
 8649|  5.48k|  }
 8650|    576|}
_ZN7httplib6detail14ChunkedDecoderC2ERNS_6StreamE:
15938|    576|inline ChunkedDecoder::ChunkedDecoder(Stream &s) : strm(s) {}
_ZN7httplib6detail14ChunkedDecoder12read_payloadEPcmRmS3_:
15942|  6.06k|                                            size_t &out_chunk_total) {
15943|  6.06k|  if (finished) { return 0; }
  ------------------
  |  Branch (15943:7): [True: 0, False: 6.06k]
  ------------------
15944|       |
15945|  6.06k|  if (chunk_remaining == 0) {
  ------------------
  |  Branch (15945:7): [True: 5.43k, False: 621]
  ------------------
15946|  5.43k|    stream_line_reader lr(strm, line_buf, sizeof(line_buf));
15947|  5.43k|    if (!lr.getline()) { return -1; }
  ------------------
  |  Branch (15947:9): [True: 10, False: 5.42k]
  ------------------
15948|       |
15949|       |    // Everything below is bounded by eol rather than by the buffer's NUL, so
15950|       |    // the line terminator is never mistaken for line content.
15951|  5.42k|    const char *eol = lr.ptr() + lr.size();
15952|  5.42k|    if (lr.end_with_crlf()) {
  ------------------
  |  Branch (15952:9): [True: 5.21k, False: 218]
  ------------------
15953|  5.21k|      eol -= 2;
15954|  5.21k|    } else if (eol != lr.ptr() && eol[-1] == '\n') {
  ------------------
  |  Branch (15954:16): [True: 218, False: 0]
  |  Branch (15954:35): [True: 7, False: 211]
  ------------------
15955|       |      // Only reachable under CPPHTTPLIB_ALLOW_LF_AS_LINE_TERMINATOR, where
15956|       |      // getline() ends the line on a bare LF. That LF is the terminator, so it
15957|       |      // has to come off here or the check below would reject the line.
15958|      7|      eol -= 1;
15959|      7|    }
15960|       |
15961|       |    // RFC 9112 §7.1: chunk-size = 1*HEXDIG
15962|  5.42k|    const char *p = lr.ptr();
15963|  5.42k|    int v = 0;
15964|  5.42k|    if (p == eol || !is_hex(*p, v)) { return -1; }
  ------------------
  |  Branch (15964:9): [True: 9, False: 5.42k]
  |  Branch (15964:21): [True: 34, False: 5.38k]
  ------------------
15965|       |
15966|  5.38k|    size_t chunk_len = 0;
15967|  5.38k|    constexpr size_t chunk_len_max = (std::numeric_limits<size_t>::max)();
15968|  13.6k|    for (; p < eol && is_hex(*p, v); ++p) {
  ------------------
  |  Branch (15968:12): [True: 10.8k, False: 2.81k]
  |  Branch (15968:23): [True: 8.27k, False: 2.56k]
  ------------------
15969|  8.27k|      if (chunk_len > (chunk_len_max >> 4)) { return -1; }
  ------------------
  |  Branch (15969:11): [True: 7, False: 8.27k]
  ------------------
15970|  8.27k|      chunk_len = (chunk_len << 4) | static_cast<size_t>(v);
15971|  8.27k|    }
15972|       |
15973|  16.9k|    while (p < eol && is_space_or_tab(*p)) {
  ------------------
  |  Branch (15973:12): [True: 14.1k, False: 2.84k]
  |  Branch (15973:23): [True: 11.6k, False: 2.53k]
  ------------------
15974|  11.6k|      ++p;
15975|  11.6k|    }
15976|       |
15977|       |    // RFC 9112 §7.1.1: only a chunk-ext may sit between the size and the line
15978|       |    // terminator, and it is built from tokens and quoted-strings, so it never
15979|       |    // holds a CR, LF or any other control character. getline() reads up to the
15980|       |    // CRLF, so a bare LF left in here would be swallowed as extension text
15981|       |    // while an intermediary that ends the line on it delimits the chunks
15982|       |    // differently, and the two disagree on where the body ends (request
15983|       |    // smuggling).
15984|  5.37k|    if (p < eol && *p != ';') { return -1; }
  ------------------
  |  Branch (15984:9): [True: 2.53k, False: 2.84k]
  |  Branch (15984:20): [True: 33, False: 2.50k]
  ------------------
15985|   158k|    for (; p < eol; ++p) {
  ------------------
  |  Branch (15985:12): [True: 153k, False: 5.34k]
  ------------------
15986|   153k|      if (!is_space_or_tab(*p) && !fields::is_field_vchar(*p)) { return -1; }
  ------------------
  |  Branch (15986:11): [True: 23.5k, False: 129k]
  |  Branch (15986:35): [True: 4, False: 23.5k]
  ------------------
15987|   153k|    }
15988|       |
15989|  5.34k|    if (chunk_len == 0) {
  ------------------
  |  Branch (15989:9): [True: 132, False: 5.21k]
  ------------------
15990|    132|      chunk_remaining = 0;
15991|    132|      finished = true;
15992|    132|      out_chunk_offset = 0;
15993|    132|      out_chunk_total = 0;
15994|    132|      return 0;
15995|    132|    }
15996|       |
15997|  5.21k|    chunk_remaining = chunk_len;
15998|  5.21k|    last_chunk_total = chunk_remaining;
15999|  5.21k|    last_chunk_offset = 0;
16000|  5.21k|  }
16001|       |
16002|  5.83k|  auto to_read = (std::min)(chunk_remaining, len);
16003|  5.83k|  auto n = strm.read(buf, to_read);
16004|  5.83k|  if (n <= 0) { return -1; }
  ------------------
  |  Branch (16004:7): [True: 306, False: 5.52k]
  ------------------
16005|       |
16006|  5.52k|  auto offset_before = last_chunk_offset;
16007|  5.52k|  last_chunk_offset += static_cast<size_t>(n);
16008|  5.52k|  chunk_remaining -= static_cast<size_t>(n);
16009|       |
16010|  5.52k|  out_chunk_offset = offset_before;
16011|  5.52k|  out_chunk_total = last_chunk_total;
16012|       |
16013|  5.52k|  if (chunk_remaining == 0) {
  ------------------
  |  Branch (16013:7): [True: 4.90k, False: 625]
  ------------------
16014|  4.90k|    stream_line_reader lr(strm, line_buf, sizeof(line_buf));
16015|  4.90k|    if (!lr.getline()) { return -1; }
  ------------------
  |  Branch (16015:9): [True: 0, False: 4.90k]
  ------------------
16016|  4.90k|    if (std::strcmp(lr.ptr(), "\r\n") != 0) { return -1; }
  ------------------
  |  Branch (16016:9): [True: 37, False: 4.86k]
  ------------------
16017|  4.90k|  }
16018|       |
16019|  5.48k|  return n;
16020|  5.52k|}
_ZN7httplib6detail14ChunkedDecoder19parse_trailers_intoERNS0_26insertion_ordered_multimapINSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEENS0_11case_ignore8equal_toEEERKSC_:
16023|    132|                                                const Headers &src_headers) {
16024|    132|  stream_line_reader lr(strm, line_buf, sizeof(line_buf));
16025|    132|  if (!lr.getline()) { return false; }
  ------------------
  |  Branch (16025:7): [True: 15, False: 117]
  ------------------
16026|    117|  return parse_trailers(lr, dest, src_headers);
16027|    132|}
_ZN7httplib6detail14parse_trailersERNS0_18stream_line_readerERNS0_26insertion_ordered_multimapINSt3__112basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEENS0_11case_ignore8equal_toEEERKSD_:
 6097|    117|                           const Headers &src_headers) {
 6098|       |  // NOTE: In RFC 9112, '7.1 Chunked Transfer Coding' mentions "The chunked
 6099|       |  // transfer coding is complete when a chunk with a chunk-size of zero is
 6100|       |  // received, possibly followed by a trailer section, and finally terminated by
 6101|       |  // an empty line". https://www.rfc-editor.org/rfc/rfc9112.html#section-7.1
 6102|       |  //
 6103|       |  // In '7.1.3. Decoding Chunked', however, the pseudo-code in the section
 6104|       |  // doesn't care for the existence of the final CRLF. In other words, it seems
 6105|       |  // to be ok whether the final CRLF exists or not in the chunked data.
 6106|       |  // https://www.rfc-editor.org/rfc/rfc9112.html#section-7.1.3
 6107|       |  //
 6108|       |  // According to the reference code in RFC 9112, cpp-httplib now allows
 6109|       |  // chunked transfer coding data without the final CRLF.
 6110|       |
 6111|       |  // RFC 7230 Section 4.1.2 - Headers prohibited in trailers
 6112|    117|  thread_local case_ignore::unordered_set<std::string> prohibited_trailers = {
 6113|    117|      "transfer-encoding",
 6114|    117|      "content-length",
 6115|    117|      "host",
 6116|    117|      "authorization",
 6117|    117|      "www-authenticate",
 6118|    117|      "proxy-authenticate",
 6119|    117|      "proxy-authorization",
 6120|    117|      "cookie",
 6121|    117|      "set-cookie",
 6122|    117|      "cache-control",
 6123|    117|      "expect",
 6124|    117|      "max-forwards",
 6125|    117|      "pragma",
 6126|    117|      "range",
 6127|    117|      "te",
 6128|    117|      "age",
 6129|    117|      "expires",
 6130|    117|      "date",
 6131|    117|      "location",
 6132|    117|      "retry-after",
 6133|    117|      "vary",
 6134|    117|      "warning",
 6135|    117|      "content-encoding",
 6136|    117|      "content-type",
 6137|    117|      "content-range",
 6138|    117|      "trailer"};
 6139|       |
 6140|    117|  case_ignore::unordered_set<std::string> declared_trailers;
 6141|    117|  auto trailer_header = get_combined_header_value(src_headers, "Trailer");
 6142|    117|  if (!trailer_header.empty()) {
  ------------------
  |  Branch (6142:7): [True: 0, False: 117]
  ------------------
 6143|       |    // split() trims each token and skips empty ones, so the name arrives ready
 6144|       |    // to look up.
 6145|      0|    split(trailer_header.data(), trailer_header.data() + trailer_header.size(),
 6146|      0|          ',', [&](const char *b, const char *e) {
 6147|       |            // A legitimate message declares only a handful of trailers. Cap the
 6148|       |            // set so a peer cannot grow it without bound: an oversized set only
 6149|       |            // arises from an attempt to force many colliding names into
 6150|       |            // quadratic lookups (case_ignore::hash is unkeyed).
 6151|      0|            if (declared_trailers.size() >= CPPHTTPLIB_HEADER_MAX_COUNT) {
 6152|      0|              return;
 6153|      0|            }
 6154|      0|            std::string key(b, e);
 6155|      0|            if (prohibited_trailers.find(key) == prohibited_trailers.end()) {
 6156|      0|              declared_trailers.insert(key);
 6157|      0|            }
 6158|      0|          });
 6159|      0|  }
 6160|       |
 6161|    117|  size_t trailer_header_count = 0;
 6162|  1.29k|  while (strcmp(line_reader.ptr(), "\r\n") != 0) {
  ------------------
  |  Branch (6162:10): [True: 1.29k, False: 1]
  ------------------
 6163|  1.29k|    if (line_reader.size() > CPPHTTPLIB_HEADER_MAX_LENGTH) { return false; }
  ------------------
  |  |  122|  1.29k|#define CPPHTTPLIB_HEADER_MAX_LENGTH 8192
  ------------------
  |  Branch (6163:9): [True: 1, False: 1.29k]
  ------------------
 6164|       |    // Count every received trailer field, not only the declared ones stored in
 6165|       |    // dest, so undeclared fields cannot keep this loop running past the limit.
 6166|  1.29k|    if (trailer_header_count >= CPPHTTPLIB_HEADER_MAX_COUNT) { return false; }
  ------------------
  |  |  126|  1.29k|#define CPPHTTPLIB_HEADER_MAX_COUNT 100
  ------------------
  |  Branch (6166:9): [True: 1, False: 1.29k]
  ------------------
 6167|       |
 6168|  1.29k|    constexpr auto line_terminator_len = 2;
 6169|  1.29k|    auto line_beg = line_reader.ptr();
 6170|  1.29k|    auto line_end =
 6171|  1.29k|        line_reader.ptr() + line_reader.size() - line_terminator_len;
 6172|       |
 6173|  1.29k|    if (!parse_header(line_beg, line_end,
  ------------------
  |  Branch (6173:9): [True: 80, False: 1.21k]
  ------------------
 6174|  1.29k|                      [&](const std::string &key, const std::string &val) {
 6175|  1.29k|                        if (declared_trailers.find(key) !=
 6176|  1.29k|                            declared_trailers.end()) {
 6177|  1.29k|                          dest.emplace(key, val);
 6178|  1.29k|                        }
 6179|  1.29k|                      })) {
 6180|     80|      return false;
 6181|     80|    }
 6182|       |
 6183|  1.21k|    trailer_header_count++;
 6184|       |
 6185|  1.21k|    if (!line_reader.getline()) { return false; }
  ------------------
  |  Branch (6185:9): [True: 34, False: 1.17k]
  ------------------
 6186|  1.21k|  }
 6187|       |
 6188|      1|  return true;
 6189|    117|}
_ZNK7httplib6detail11case_ignore4hashclERKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEE:
  709|     26|  size_t operator()(const std::string &key) const {
  710|     26|    size_t h = 0;
  711|    253|    for (auto c : key) {
  ------------------
  |  Branch (711:17): [True: 253, False: 26]
  ------------------
  712|       |      // Unsets the 6 high bits of h, therefore no overflow happens
  713|    253|      h = (((std::numeric_limits<size_t>::max)() >> 6) & h * 33) ^
  714|    253|          static_cast<unsigned char>(to_lower(c));
  715|    253|    }
  716|     26|    return h;
  717|     26|  }
_ZN7httplib6detail12parse_headerIZNS0_14parse_trailersERNS0_18stream_line_readerERNS0_26insertion_ordered_multimapINSt3__112basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEENS0_11case_ignore8equal_toEEERKSE_EUlRKSB_SJ_E_EEbPKcSM_T_:
 6051|  1.29k|inline bool parse_header(const char *beg, const char *end, T fn) {
 6052|       |  // Skip trailing spaces and tabs.
 6053|  1.55k|  while (beg < end && is_space_or_tab(end[-1])) {
  ------------------
  |  Branch (6053:10): [True: 1.51k, False: 36]
  |  Branch (6053:23): [True: 259, False: 1.25k]
  ------------------
 6054|    259|    end--;
 6055|    259|  }
 6056|       |
 6057|  1.29k|  auto p = beg;
 6058|  12.0k|  while (p < end && *p != ':') {
  ------------------
  |  Branch (6058:10): [True: 11.9k, False: 63]
  |  Branch (6058:21): [True: 10.7k, False: 1.22k]
  ------------------
 6059|  10.7k|    p++;
 6060|  10.7k|  }
 6061|       |
 6062|  1.29k|  auto name = std::string(beg, p);
 6063|  1.29k|  if (!detail::fields::is_field_name(name)) { return false; }
  ------------------
  |  Branch (6063:7): [True: 57, False: 1.23k]
  ------------------
 6064|       |
 6065|  1.23k|  if (p == end) { return false; }
  ------------------
  |  Branch (6065:7): [True: 10, False: 1.22k]
  ------------------
 6066|       |
 6067|  1.22k|  auto key_end = p;
 6068|       |
 6069|  1.22k|  if (*p++ != ':') { return false; }
  ------------------
  |  Branch (6069:7): [True: 0, False: 1.22k]
  ------------------
 6070|       |
 6071|  1.57k|  while (p < end && is_space_or_tab(*p)) {
  ------------------
  |  Branch (6071:10): [True: 648, False: 931]
  |  Branch (6071:21): [True: 355, False: 293]
  ------------------
 6072|    355|    p++;
 6073|    355|  }
 6074|       |
 6075|  1.22k|  if (p <= end) {
  ------------------
  |  Branch (6075:7): [True: 1.22k, False: 0]
  ------------------
 6076|  1.22k|    auto key_len = key_end - beg;
 6077|  1.22k|    if (!key_len) { return false; }
  ------------------
  |  Branch (6077:9): [True: 0, False: 1.22k]
  ------------------
 6078|       |
 6079|  1.22k|    auto key = std::string(beg, key_end);
 6080|  1.22k|    auto val = std::string(p, end);
 6081|       |
 6082|  1.22k|    if (!detail::fields::is_field_value(val)) { return false; }
  ------------------
  |  Branch (6082:9): [True: 13, False: 1.21k]
  ------------------
 6083|       |
 6084|       |    // RFC 9110 §5.5: header field values are opaque octets and MUST NOT be
 6085|       |    // percent-decoded by the recipient. Applications that need to interpret a
 6086|       |    // value as a URI component should call httplib::decode_uri_component()
 6087|       |    // (or decode_path_component()) explicitly.
 6088|  1.21k|    fn(key, val);
 6089|       |
 6090|  1.21k|    return true;
 6091|  1.22k|  }
 6092|       |
 6093|      0|  return false;
 6094|  1.22k|}
_ZZN7httplib6detail14parse_trailersERNS0_18stream_line_readerERNS0_26insertion_ordered_multimapINSt3__112basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEENS0_11case_ignore8equal_toEEERKSD_ENKUlRKSA_SI_E_clESI_SI_:
 6174|  1.21k|                      [&](const std::string &key, const std::string &val) {
 6175|  1.21k|                        if (declared_trailers.find(key) !=
  ------------------
  |  Branch (6175:29): [True: 0, False: 1.21k]
  ------------------
 6176|  1.21k|                            declared_trailers.end()) {
 6177|      0|                          dest.emplace(key, val);
 6178|      0|                        }
 6179|  1.21k|                      })) {
_ZN7httplib6detail27read_content_without_lengthERNS_6StreamEmNSt3__18functionIFbPKcmmmEEE:
 8592|    410|                            ContentReceiverWithProgress out) {
 8593|    410|  char buf[CPPHTTPLIB_RECV_BUFSIZ];
 8594|    410|  size_t r = 0;
 8595|  1.65k|  for (;;) {
 8596|  1.65k|    auto n = strm.read(buf, CPPHTTPLIB_RECV_BUFSIZ);
  ------------------
  |  |  188|  1.65k|#define CPPHTTPLIB_RECV_BUFSIZ size_t(16384u)
  ------------------
 8597|  1.65k|    if (n == 0) { return ReadContentResult::Success; }
  ------------------
  |  Branch (8597:9): [True: 383, False: 1.27k]
  ------------------
 8598|  1.27k|    if (n < 0) { return ReadContentResult::Error; }
  ------------------
  |  Branch (8598:9): [True: 0, False: 1.27k]
  ------------------
 8599|       |
 8600|       |    // Check if adding this data would exceed the payload limit
 8601|  1.27k|    if (payload_max_length > 0 &&
  ------------------
  |  Branch (8601:9): [True: 1.27k, False: 0]
  ------------------
 8602|  1.27k|        (r > payload_max_length ||
  ------------------
  |  Branch (8602:10): [True: 0, False: 1.27k]
  ------------------
 8603|  1.27k|         payload_max_length - r < static_cast<size_t>(n))) {
  ------------------
  |  Branch (8603:10): [True: 0, False: 1.27k]
  ------------------
 8604|      0|      return ReadContentResult::PayloadTooLarge;
 8605|      0|    }
 8606|       |
 8607|  1.27k|    if (!out(buf, static_cast<size_t>(n), r, 0)) {
  ------------------
  |  Branch (8607:9): [True: 27, False: 1.24k]
  ------------------
 8608|     27|      return ReadContentResult::Error;
 8609|     27|    }
 8610|  1.24k|    r += static_cast<size_t>(n);
 8611|  1.24k|  }
 8612|       |
 8613|      0|  return ReadContentResult::Success;
 8614|    410|}
_ZN7httplib6detail24read_content_with_lengthERNS_6StreamEmNSt3__18functionIFbmmEEENS4_IFbPKcmmmEEEm:
 8552|    319|    size_t payload_max_length = (std::numeric_limits<size_t>::max)()) {
 8553|    319|  char buf[CPPHTTPLIB_RECV_BUFSIZ];
 8554|       |
 8555|    319|  detail::BodyReader br;
 8556|    319|  br.stream = &strm;
 8557|    319|  br.has_content_length = true;
 8558|    319|  br.content_length = len;
 8559|    319|  br.payload_max_length = payload_max_length;
 8560|    319|  br.chunked = false;
 8561|    319|  br.bytes_read = 0;
 8562|    319|  br.last_error = Error::Success;
 8563|       |
 8564|    319|  size_t r = 0;
 8565|    577|  while (r < len) {
  ------------------
  |  Branch (8565:10): [True: 576, False: 1]
  ------------------
 8566|    576|    auto read_len = static_cast<size_t>(len - r);
 8567|    576|    auto to_read = (std::min)(read_len, CPPHTTPLIB_RECV_BUFSIZ);
  ------------------
  |  |  188|    576|#define CPPHTTPLIB_RECV_BUFSIZ size_t(16384u)
  ------------------
 8568|    576|    auto n = detail::read_body_content(&strm, br, buf, to_read);
 8569|    576|    if (n <= 0) {
  ------------------
  |  Branch (8569:9): [True: 316, False: 260]
  ------------------
 8570|       |      // Check if it was a payload size error
 8571|    316|      if (br.last_error == Error::ExceedMaxPayloadSize) {
  ------------------
  |  Branch (8571:11): [True: 0, False: 316]
  ------------------
 8572|      0|        return ReadContentResult::PayloadTooLarge;
 8573|      0|      }
 8574|    316|      return ReadContentResult::Error;
 8575|    316|    }
 8576|       |
 8577|    260|    if (!out(buf, static_cast<size_t>(n), r, len)) {
  ------------------
  |  Branch (8577:9): [True: 2, False: 258]
  ------------------
 8578|      2|      return ReadContentResult::Error;
 8579|      2|    }
 8580|    258|    r += static_cast<size_t>(n);
 8581|       |
 8582|    258|    if (progress) {
  ------------------
  |  Branch (8582:9): [True: 258, False: 0]
  ------------------
 8583|    258|      if (!progress(r, len)) { return ReadContentResult::Error; }
  ------------------
  |  Branch (8583:11): [True: 0, False: 258]
  ------------------
 8584|    258|    }
 8585|    258|  }
 8586|       |
 8587|      1|  return ReadContentResult::Success;
 8588|    319|}
_ZN7httplib6detail17read_body_contentEPNS_6StreamERNS0_10BodyReaderEPcm:
 2701|    576|                                 size_t len) {
 2702|    576|  (void)stream;
 2703|    576|  return br.read(buf, len);
 2704|    576|}
_ZN7httplib6detail10BodyReader4readEPcm:
12302|    576|inline ssize_t detail::BodyReader::read(char *buf, size_t len) {
12303|    576|  if (!stream) {
  ------------------
  |  Branch (12303:7): [True: 0, False: 576]
  ------------------
12304|      0|    last_error = Error::Connection;
12305|      0|    return -1;
12306|      0|  }
12307|    576|  if (eof) { return 0; }
  ------------------
  |  Branch (12307:7): [True: 0, False: 576]
  ------------------
12308|       |
12309|    576|  if (!chunked) {
  ------------------
  |  Branch (12309:7): [True: 576, False: 0]
  ------------------
12310|       |    // Content-Length based reading
12311|    576|    if (has_content_length && bytes_read >= content_length) {
  ------------------
  |  Branch (12311:9): [True: 576, False: 0]
  |  Branch (12311:31): [True: 0, False: 576]
  ------------------
12312|      0|      eof = true;
12313|      0|      return 0;
12314|      0|    }
12315|       |
12316|    576|    auto to_read = len;
12317|    576|    if (has_content_length) {
  ------------------
  |  Branch (12317:9): [True: 576, False: 0]
  ------------------
12318|    576|      auto remaining = content_length - bytes_read;
12319|    576|      to_read = (std::min)(len, remaining);
12320|    576|    }
12321|    576|    auto n = stream->read(buf, to_read);
12322|       |
12323|    576|    if (n < 0) {
  ------------------
  |  Branch (12323:9): [True: 0, False: 576]
  ------------------
12324|      0|      last_error = stream->get_error();
12325|      0|      if (last_error == Error::Success) { last_error = Error::Read; }
  ------------------
  |  Branch (12325:11): [True: 0, False: 0]
  ------------------
12326|      0|      eof = true;
12327|      0|      return n;
12328|      0|    }
12329|    576|    if (n == 0) {
  ------------------
  |  Branch (12329:9): [True: 316, False: 260]
  ------------------
12330|       |      // Unexpected EOF before content_length
12331|    316|      last_error = stream->get_error();
12332|    316|      if (last_error == Error::Success) { last_error = Error::Read; }
  ------------------
  |  Branch (12332:11): [True: 316, False: 0]
  ------------------
12333|    316|      eof = true;
12334|    316|      return 0;
12335|    316|    }
12336|       |
12337|    260|    bytes_read += static_cast<size_t>(n);
12338|    260|    if (has_content_length && bytes_read >= content_length) { eof = true; }
  ------------------
  |  Branch (12338:9): [True: 260, False: 0]
  |  Branch (12338:31): [True: 1, False: 259]
  ------------------
12339|    260|    if (payload_max_length > 0 && bytes_read > payload_max_length) {
  ------------------
  |  Branch (12339:9): [True: 260, False: 0]
  |  Branch (12339:35): [True: 0, False: 260]
  ------------------
12340|      0|      last_error = Error::ExceedMaxPayloadSize;
12341|      0|      eof = true;
12342|      0|      return -1;
12343|      0|    }
12344|    260|    return n;
12345|    260|  }
12346|       |
12347|       |  // Chunked transfer encoding: delegate to shared decoder instance.
12348|      0|  if (!chunked_decoder) { chunked_decoder.reset(new ChunkedDecoder(*stream)); }
  ------------------
  |  Branch (12348:7): [True: 0, False: 0]
  ------------------
12349|       |
12350|      0|  size_t chunk_offset = 0;
12351|      0|  size_t chunk_total = 0;
12352|      0|  auto n = chunked_decoder->read_payload(buf, len, chunk_offset, chunk_total);
12353|      0|  if (n < 0) {
  ------------------
  |  Branch (12353:7): [True: 0, False: 0]
  ------------------
12354|      0|    last_error = stream->get_error();
12355|      0|    if (last_error == Error::Success) { last_error = Error::Read; }
  ------------------
  |  Branch (12355:9): [True: 0, False: 0]
  ------------------
12356|      0|    eof = true;
12357|      0|    return n;
12358|      0|  }
12359|       |
12360|      0|  if (n == 0) {
  ------------------
  |  Branch (12360:7): [True: 0, False: 0]
  ------------------
12361|       |    // Final chunk observed. Leave trailer parsing to the caller (StreamHandle).
12362|      0|    eof = true;
12363|      0|    return 0;
12364|      0|  }
12365|       |
12366|      0|  bytes_read += static_cast<size_t>(n);
12367|      0|  if (payload_max_length > 0 && bytes_read > payload_max_length) {
  ------------------
  |  Branch (12367:7): [True: 0, False: 0]
  |  Branch (12367:33): [True: 0, False: 0]
  ------------------
12368|      0|    last_error = Error::ExceedMaxPayloadSize;
12369|      0|    eof = true;
12370|      0|    return -1;
12371|      0|  }
12372|      0|  return n;
12373|      0|}
_ZNK7httplib6Stream9get_errorEv:
 2036|    316|  Error get_error() const { return error_; }
_ZZN7httplib6detail24prepare_content_receiverINS_8ResponseEZNS0_12read_contentIS2_EEbRNS_6StreamERT_mRiNSt3__18functionIFbmmEEENSA_IFbPKcmmmEEEbEUlRKSG_E_EEbS7_S8_SG_bmRbT0_ENKUlSE_mmmE0_clESE_mmm:
 8751|  4.85k|                                        size_t len) {
 8752|  4.85k|    return receiver(buf, n, off, len);
 8753|  4.85k|  };
_ZZN7httplib10ClientImpl15process_requestERNS_6StreamERNS_7RequestERNS_8ResponseEbRNS_5ErrorEENKUlmmE_clEmm:
16881|    258|    auto progress = [&](size_t current, size_t total) {
16882|    258|      if (!req.download_progress || redirect) { return true; }
  ------------------
  |  Branch (16882:11): [True: 258, False: 0]
  |  Branch (16882:37): [True: 0, False: 0]
  ------------------
16883|      0|      auto ret = req.download_progress(current, total);
16884|      0|      if (!ret) {
  ------------------
  |  Branch (16884:11): [True: 0, False: 0]
  ------------------
16885|      0|        error = Error::Canceled;
16886|      0|        output_error_log(error, &req);
16887|      0|      }
16888|      0|      return ret;
16889|    258|    };
_ZNK7httplib10ClientImpl10output_logERKNS_7RequestERKNS_8ResponseE:
16707|    407|                                   const Response &res) const {
16708|    407|  if (logger_) {
  ------------------
  |  Branch (16708:7): [True: 0, False: 407]
  ------------------
16709|      0|    std::lock_guard<std::mutex> guard(logger_mutex_);
16710|      0|    logger_(req, res);
16711|      0|  }
16712|    407|}
_ZN7httplib8ResponseD2Ev:
 1924|  3.02k|  ~Response() {
 1925|  3.02k|    if (content_provider_resource_releaser_) {
  ------------------
  |  Branch (1925:9): [True: 0, False: 3.02k]
  ------------------
 1926|      0|      content_provider_resource_releaser_(content_provider_success_);
 1927|      0|    }
 1928|  3.02k|  }
_ZNK7httplib6detail17gzip_decompressor8is_validEv:
 8031|    129|inline bool gzip_decompressor::is_valid() const { return is_valid_; }
_ZN7httplib6detail17gzip_decompressor10decompressEPKcmNSt3__18functionIFbS3_mEEE:
 8034|  2.16k|                                          Callback callback) {
 8035|  2.16k|  assert(is_valid_);
  ------------------
  |  Branch (8035:3): [True: 2.16k, False: 0]
  ------------------
 8036|       |
 8037|  2.16k|  auto ret = Z_OK;
 8038|       |
 8039|  2.16k|  do {
 8040|  2.16k|    constexpr size_t max_avail_in =
 8041|  2.16k|        (std::numeric_limits<decltype(strm_.avail_in)>::max)();
 8042|       |
 8043|  2.16k|    strm_.avail_in = static_cast<decltype(strm_.avail_in)>(
 8044|  2.16k|        (std::min)(data_length, max_avail_in));
 8045|  2.16k|    strm_.next_in = const_cast<Bytef *>(reinterpret_cast<const Bytef *>(data));
 8046|       |
 8047|  2.16k|    data_length -= strm_.avail_in;
 8048|  2.16k|    data += strm_.avail_in;
 8049|       |
 8050|  2.16k|    std::array<char, CPPHTTPLIB_COMPRESSION_BUFSIZ> buff{};
 8051|   124k|    while (strm_.avail_in > 0 && ret == Z_OK) {
  ------------------
  |  Branch (8051:12): [True: 122k, False: 1.25k]
  |  Branch (8051:34): [True: 121k, False: 879]
  ------------------
 8052|   121k|      strm_.avail_out = static_cast<uInt>(buff.size());
 8053|   121k|      strm_.next_out = reinterpret_cast<Bytef *>(buff.data());
 8054|       |
 8055|   121k|      ret = inflate(&strm_, Z_NO_FLUSH);
 8056|       |
 8057|   121k|      assert(ret != Z_STREAM_ERROR);
  ------------------
  |  Branch (8057:7): [True: 121k, False: 0]
  ------------------
 8058|   121k|      switch (ret) {
  ------------------
  |  Branch (8058:15): [True: 18, False: 121k]
  ------------------
 8059|      1|      case Z_NEED_DICT:
  ------------------
  |  Branch (8059:7): [True: 1, False: 121k]
  ------------------
 8060|     18|      case Z_DATA_ERROR:
  ------------------
  |  Branch (8060:7): [True: 17, False: 121k]
  ------------------
 8061|     18|      case Z_MEM_ERROR: inflateEnd(&strm_); return false;
  ------------------
  |  Branch (8061:7): [True: 0, False: 121k]
  ------------------
 8062|   121k|      }
 8063|       |
 8064|   121k|      if (!callback(buff.data(), buff.size() - strm_.avail_out)) {
  ------------------
  |  Branch (8064:11): [True: 15, False: 121k]
  ------------------
 8065|     15|        return false;
 8066|     15|      }
 8067|   121k|    }
 8068|       |
 8069|  2.12k|    if (ret != Z_OK && ret != Z_STREAM_END) { return false; }
  ------------------
  |  Branch (8069:9): [True: 880, False: 1.24k]
  |  Branch (8069:24): [True: 0, False: 880]
  ------------------
 8070|       |
 8071|  2.12k|  } while (data_length > 0);
  ------------------
  |  Branch (8071:12): [True: 0, False: 2.12k]
  ------------------
 8072|       |
 8073|  2.12k|  return true;
 8074|  2.16k|}
_ZN7httplib6detail12BufferStreamD2Ev:
 3837|  3.02k|  ~BufferStream() override = default;
_ZN7httplib6detail12BufferStream5writeEPKcm:
12717|  20.0k|inline ssize_t BufferStream::write(const char *ptr, size_t size) {
12718|  20.0k|  buffer.append(ptr, size);
12719|  20.0k|  return static_cast<ssize_t>(size);
12720|  20.0k|}
_ZNK7httplib6Stream13buffered_dataERm:
 2025|  3.67M|  virtual const char *buffered_data(size_t &size) const {
 2026|  3.67M|    size = 0;
 2027|  3.67M|    return nullptr;
 2028|  3.67M|  }
_ZNK7httplib10ClientImpl6is_sslEv:
17000|  3.02k|inline bool ClientImpl::is_ssl() const { return false; }

LLVMFuzzerTestOneInput:
   69|  3.02k|extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
   70|  3.02k|  if (size < 1) return 0;
  ------------------
  |  Branch (70:7): [True: 0, False: 3.02k]
  ------------------
   71|       |
   72|  3.02k|  FuzzedStream stream{data + 1, size - 1};
   73|  3.02k|  FuzzableClient client;
   74|       |
   75|       |  // Use the first byte to select method
   76|  3.02k|  std::string method;
   77|  3.02k|  switch (data[0] % 6) {
  ------------------
  |  Branch (77:11): [True: 3.02k, False: 0]
  ------------------
   78|    178|  case 0: method = "GET"; break;
  ------------------
  |  Branch (78:3): [True: 178, False: 2.85k]
  ------------------
   79|    583|  case 1: method = "POST"; break;
  ------------------
  |  Branch (79:3): [True: 583, False: 2.44k]
  ------------------
   80|    965|  case 2: method = "PUT"; break;
  ------------------
  |  Branch (80:3): [True: 965, False: 2.06k]
  ------------------
   81|    359|  case 3: method = "PATCH"; break;
  ------------------
  |  Branch (81:3): [True: 359, False: 2.67k]
  ------------------
   82|    244|  case 4: method = "DELETE"; break;
  ------------------
  |  Branch (82:3): [True: 244, False: 2.78k]
  ------------------
   83|    700|  case 5: method = "OPTIONS"; break;
  ------------------
  |  Branch (83:3): [True: 700, False: 2.32k]
  ------------------
   84|  3.02k|  }
   85|       |
   86|  3.02k|  client.ProcessFuzzedResponse(stream, method);
   87|  3.02k|  return 0;
   88|  3.02k|}
_ZN12FuzzedStreamC2EPKhm:
    8|  3.02k|      : data_(data), size_(size), read_pos_(0) {}
_ZN12FuzzedStream4readEPcm:
   10|  3.68M|  ssize_t read(char *ptr, size_t size) override {
   11|  3.68M|    if (size + read_pos_ > size_) { size = size_ - read_pos_; }
  ------------------
  |  Branch (11:9): [True: 2.73k, False: 3.67M]
  ------------------
   12|  3.68M|    memcpy(ptr, data_ + read_pos_, size);
   13|  3.68M|    read_pos_ += size;
   14|  3.68M|    return static_cast<ssize_t>(size);
   15|  3.68M|  }
_ZN12FuzzedStream5writeEPKcm:
   17|  3.02k|  ssize_t write(const char *ptr, size_t size) override {
   18|  3.02k|    request_.append(ptr, size);
   19|  3.02k|    return static_cast<ssize_t>(size);
   20|  3.02k|  }
_ZN14FuzzableClientC2Ev:
   55|  3.02k|  FuzzableClient() : httplib::ClientImpl("localhost", 8080) {}
_ZN14FuzzableClient21ProcessFuzzedResponseER12FuzzedStreamRKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE:
   57|  3.02k|  void ProcessFuzzedResponse(FuzzedStream &stream, const std::string &method) {
   58|  3.02k|    httplib::Request req;
   59|  3.02k|    req.method = method;
   60|  3.02k|    req.path = "/";
   61|  3.02k|    httplib::Response res;
   62|  3.02k|    bool close_connection = false;
   63|  3.02k|    httplib::Error error = httplib::Error::Success;
   64|       |
   65|  3.02k|    process_request(stream, req, res, close_connection, error);
   66|  3.02k|  }

