_ZN7httplib6detail17gzip_decompressorD2Ev:
 7433|    135|inline gzip_decompressor::~gzip_decompressor() { inflateEnd(&strm_); }
_ZN7httplib10ClientImplD2Ev:
13687|  3.09k|inline ClientImpl::~ClientImpl() {
13688|       |  // Wait until all the requests in flight are handled.
13689|  3.09k|  size_t retry_count = 10;
13690|  3.09k|  while (retry_count-- > 0) {
  ------------------
  |  Branch (13690:10): [True: 3.09k, False: 0]
  ------------------
13691|  3.09k|    {
13692|  3.09k|      std::lock_guard<std::mutex> guard(socket_mutex_);
13693|  3.09k|      if (socket_requests_in_flight_ == 0) { break; }
  ------------------
  |  Branch (13693:11): [True: 3.09k, False: 0]
  ------------------
13694|  3.09k|    }
13695|      0|    std::this_thread::sleep_for(std::chrono::milliseconds{1});
13696|      0|  }
13697|       |
13698|  3.09k|  std::lock_guard<std::mutex> guard(socket_mutex_);
13699|  3.09k|  shutdown_socket(socket_);
13700|  3.09k|  close_socket(socket_);
13701|  3.09k|}
_ZN7httplib6detail12decompressorD2Ev:
 3557|    135|  virtual ~decompressor() = default;
_ZN7httplib6StreamD2Ev:
 1820|  6.19k|  virtual ~Stream() = default;
_ZNK7httplib10ClientImpl15shutdown_socketERNS0_6SocketE:
13816|  3.09k|inline void ClientImpl::shutdown_socket(Socket &socket) const {
13817|  3.09k|  if (socket.sock == INVALID_SOCKET) { return; }
  ------------------
  |  |  300|  3.09k|#define INVALID_SOCKET (-1)
  ------------------
  |  Branch (13817:7): [True: 3.09k, False: 0]
  ------------------
13818|      0|  detail::shutdown_socket(socket.sock);
13819|      0|}
_ZN7httplib10ClientImpl12close_socketERNS0_6SocketE:
13821|  3.09k|inline void ClientImpl::close_socket(Socket &socket) {
13822|       |  // If there are requests in flight in another thread, usually closing
13823|       |  // the socket will be fine and they will simply receive an error when
13824|       |  // using the closed socket, but it is still a bug since rarely the OS
13825|       |  // may reassign the socket id to be used for a new socket, and then
13826|       |  // suddenly they will be operating on a live socket that is different
13827|       |  // than the one they intended!
13828|  3.09k|  assert(socket_requests_in_flight_ == 0 ||
  ------------------
  |  Branch (13828:3): [True: 3.09k, False: 0]
  |  Branch (13828:3): [True: 0, False: 0]
  |  Branch (13828:3): [True: 3.09k, False: 0]
  ------------------
13829|  3.09k|         socket_requests_are_from_thread_ == std::this_thread::get_id());
13830|       |
13831|       |  // It is also a bug if this happens while SSL is still active
13832|       |#ifdef CPPHTTPLIB_SSL_ENABLED
13833|       |  assert(socket.ssl == nullptr);
13834|       |#endif
13835|       |
13836|  3.09k|  if (socket.sock == INVALID_SOCKET) { return; }
  ------------------
  |  |  300|  3.09k|#define INVALID_SOCKET (-1)
  ------------------
  |  Branch (13836:7): [True: 3.09k, False: 0]
  ------------------
13837|      0|  detail::close_socket(socket.sock);
13838|      0|  socket.sock = INVALID_SOCKET;
  ------------------
  |  |  300|      0|#define INVALID_SOCKET (-1)
  ------------------
13839|      0|}
_ZN7httplib10ClientImplC2ERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEi:
13679|  3.09k|    : ClientImpl(host, port, std::string(), std::string()) {}
_ZN7httplib10ClientImplC2ERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEiS9_S9_:
13684|  3.09k|    : host_(detail::escape_abstract_namespace_unix_domain(host)), port_(port),
13685|  3.09k|      client_cert_path_(client_cert_path), client_key_path_(client_key_path) {}
_ZN7httplib6detail37escape_abstract_namespace_unix_domainERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
 6357|  3.09k|inline std::string escape_abstract_namespace_unix_domain(const std::string &s) {
 6358|  3.09k|  if (s.size() > 1 && s[0] == '\0') {
  ------------------
  |  Branch (6358:7): [True: 3.09k, False: 0]
  |  Branch (6358:23): [True: 0, False: 3.09k]
  ------------------
 6359|      0|    auto ret = s;
 6360|      0|    ret[0] = '@';
 6361|      0|    return ret;
 6362|      0|  }
 6363|  3.09k|  return s;
 6364|  3.09k|}
_ZN7httplib6detail26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEEC2Ev:
 1101|  15.4k|  insertion_ordered_multimap() = default;
_ZN7httplib6detail13write_headersERNS_6StreamERKNS0_26insertion_ordered_multimapINSt3__112basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEENS0_11case_ignore8equal_toEEE:
 8171|  3.09k|inline ssize_t write_headers(Stream &strm, const Headers &headers) {
 8172|  3.09k|  ssize_t write_len = 0;
 8173|  14.1k|  for (const auto &x : headers) {
  ------------------
  |  Branch (8173:22): [True: 14.1k, False: 3.09k]
  ------------------
 8174|       |    // Skip fields with invalid names or values to prevent response splitting
 8175|       |    // via CR/LF injection, matching set_header(). The client validates request
 8176|       |    // headers up front in check_and_write_headers, but the server passes
 8177|       |    // res.headers straight to this writer, and res.headers is a public field
 8178|       |    // an application can populate directly with request-derived values.
 8179|  14.1k|    if (!fields::is_field_valid(x.first, x.second)) { continue; }
  ------------------
  |  Branch (8179:9): [True: 0, False: 14.1k]
  ------------------
 8180|       |
 8181|  14.1k|    std::string s;
 8182|  14.1k|    s = x.first;
 8183|  14.1k|    s += ": ";
 8184|  14.1k|    s += x.second;
 8185|  14.1k|    s += "\r\n";
 8186|       |
 8187|  14.1k|    auto len = strm.write(s.data(), s.size());
 8188|  14.1k|    if (len < 0) { return len; }
  ------------------
  |  Branch (8188:9): [True: 0, False: 14.1k]
  ------------------
 8189|  14.1k|    write_len += len;
 8190|  14.1k|  }
 8191|  3.09k|  auto len = strm.write("\r\n");
 8192|  3.09k|  if (len < 0) { return len; }
  ------------------
  |  Branch (8192:7): [True: 0, False: 3.09k]
  ------------------
 8193|  3.09k|  write_len += len;
 8194|  3.09k|  return write_len;
 8195|  3.09k|}
_ZNK7httplib6detail26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEE5beginEv:
 1110|  3.09k|  const_iterator begin() const { return make_citer(0, npos()); }
_ZNK7httplib6detail26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEE10make_citerEmm:
 1243|  64.7k|  const_iterator make_citer(size_type idx, size_type key_idx) const {
 1244|  64.7k|    return const_iterator(entries_.data(), idx, entries_.size(), key_idx);
 1245|  64.7k|  }
_ZN7httplib6detail26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEE10iterator_tIKNS2_4pairIS8_S8_EEEC2EPSF_mmm:
 1085|  64.7k|        : data_(data), idx_(idx), size_(size), key_idx_(key_idx) {}
_ZN7httplib6detail26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEE4nposEv:
 1004|   190k|  static size_type npos() { return static_cast<size_type>(-1); }
_ZNK7httplib6detail26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEE3endEv:
 1111|  58.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:
 1076|  47.0k|    template <typename U> bool operator!=(const iterator_t<U> &rhs) const {
 1077|  47.0k|      return idx_ != rhs.idx_;
 1078|  47.0k|    }
_ZNK7httplib6detail26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEE10iterator_tIKNS2_4pairIS8_S8_EEEdeEv:
 1032|  14.1k|    reference operator*() const { return data_[idx_]; }
_ZN7httplib6detail6fields14is_field_validERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEESA_:
 9630|  36.2k|inline bool is_field_valid(const std::string &name, const std::string &value) {
 9631|  36.2k|  return is_field_name(name) && is_field_value(value);
  ------------------
  |  Branch (9631:10): [True: 36.2k, False: 0]
  |  Branch (9631:33): [True: 36.2k, False: 0]
  ------------------
 9632|  36.2k|}
_ZN7httplib6detail6fields13is_field_nameERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE:
 9595|  49.7k|inline bool is_field_name(const std::string &s) { return is_token(s); }
_ZN7httplib6detail6fields8is_tokenERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE:
 9587|  49.7k|inline bool is_token(const std::string &s) {
 9588|  49.7k|  if (s.empty()) { return false; }
  ------------------
  |  Branch (9588:7): [True: 71, False: 49.7k]
  ------------------
 9589|   506k|  for (auto c : s) {
  ------------------
  |  Branch (9589:15): [True: 506k, False: 49.5k]
  ------------------
 9590|   506k|    if (!is_token_char(c)) { return false; }
  ------------------
  |  Branch (9590:9): [True: 137, False: 506k]
  ------------------
 9591|   506k|  }
 9592|  49.5k|  return true;
 9593|  49.7k|}
_ZN7httplib6detail6fields13is_token_charEc:
 9581|   506k|inline bool is_token_char(char c) {
 9582|   506k|  return is_ascii_alnum(c) || c == '!' || c == '#' || c == '$' || c == '%' ||
  ------------------
  |  Branch (9582:10): [True: 462k, False: 44.6k]
  |  Branch (9582:31): [True: 891, False: 43.7k]
  |  Branch (9582:43): [True: 992, False: 42.7k]
  |  Branch (9582:55): [True: 434, False: 42.2k]
  |  Branch (9582:67): [True: 328, False: 41.9k]
  ------------------
 9583|  41.9k|         c == '&' || c == '\'' || c == '*' || c == '+' || c == '-' ||
  ------------------
  |  Branch (9583:10): [True: 1.56k, False: 40.3k]
  |  Branch (9583:22): [True: 508, False: 39.8k]
  |  Branch (9583:35): [True: 1.79k, False: 38.0k]
  |  Branch (9583:47): [True: 509, False: 37.5k]
  |  Branch (9583:59): [True: 30.0k, False: 7.57k]
  ------------------
 9584|  7.57k|         c == '.' || c == '^' || c == '_' || c == '`' || c == '|' || c == '~';
  ------------------
  |  Branch (9584:10): [True: 677, False: 6.89k]
  |  Branch (9584:22): [True: 558, False: 6.33k]
  |  Branch (9584:34): [True: 3.05k, False: 3.28k]
  |  Branch (9584:46): [True: 308, False: 2.97k]
  |  Branch (9584:58): [True: 1.76k, False: 1.20k]
  |  Branch (9584:70): [True: 1.07k, False: 137]
  ------------------
 9585|   506k|}
_ZN7httplib6detail14is_ascii_alnumEc:
  568|   506k|inline bool is_ascii_alnum(char c) {
  569|   506k|  return is_ascii_digit(c) || is_ascii_alpha(c);
  ------------------
  |  Branch (569:10): [True: 9.54k, False: 497k]
  |  Branch (569:31): [True: 452k, False: 44.6k]
  ------------------
  570|   506k|}
_ZN7httplib6detail14is_ascii_digitEc:
  562|   552k|inline bool is_ascii_digit(char c) { return '0' <= c && c <= '9'; }
  ------------------
  |  Branch (562:45): [True: 509k, False: 42.4k]
  |  Branch (562:57): [True: 46.2k, False: 463k]
  ------------------
_ZN7httplib6detail14is_ascii_alphaEc:
  564|   497k|inline bool is_ascii_alpha(char c) {
  565|   497k|  return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z');
  ------------------
  |  Branch (565:11): [True: 362k, False: 134k]
  |  Branch (565:23): [True: 359k, False: 2.84k]
  |  Branch (565:37): [True: 99.4k, False: 37.8k]
  |  Branch (565:49): [True: 92.6k, False: 6.76k]
  ------------------
  566|   497k|}
_ZN7httplib6detail6fields14is_field_valueERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE:
 9628|  52.4k|inline bool is_field_value(const std::string &s) { return is_field_content(s); }
_ZN7httplib6detail6fields16is_field_contentERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE:
 9603|  52.4k|inline bool is_field_content(const std::string &s) {
 9604|  52.4k|  if (s.empty()) { return true; }
  ------------------
  |  Branch (9604:7): [True: 8.36k, False: 44.1k]
  ------------------
 9605|       |
 9606|  44.1k|  if (s.size() == 1) {
  ------------------
  |  Branch (9606:7): [True: 9.20k, False: 34.9k]
  ------------------
 9607|  9.20k|    return is_field_vchar(s[0]);
 9608|  34.9k|  } else if (s.size() == 2) {
  ------------------
  |  Branch (9608:14): [True: 387, False: 34.5k]
  ------------------
 9609|    387|    return is_field_vchar(s[0]) && is_field_vchar(s[1]);
  ------------------
  |  Branch (9609:12): [True: 386, False: 1]
  |  Branch (9609:36): [True: 386, False: 0]
  ------------------
 9610|  34.5k|  } else {
 9611|  34.5k|    size_t i = 0;
 9612|       |
 9613|  34.5k|    if (!is_field_vchar(s[i])) { return false; }
  ------------------
  |  Branch (9613:9): [True: 2, False: 34.5k]
  ------------------
 9614|  34.5k|    i++;
 9615|       |
 9616|   608k|    while (i < s.size() - 1) {
  ------------------
  |  Branch (9616:12): [True: 574k, False: 34.4k]
  ------------------
 9617|   574k|      auto c = s[i++];
 9618|   574k|      if (c == ' ' || c == '\t' || is_field_vchar(c)) {
  ------------------
  |  Branch (9618:11): [True: 19.4k, False: 554k]
  |  Branch (9618:23): [True: 1.43k, False: 553k]
  |  Branch (9618:36): [True: 553k, False: 34]
  ------------------
 9619|   574k|      } else {
 9620|     34|        return false;
 9621|     34|      }
 9622|   574k|    }
 9623|       |
 9624|  34.4k|    return is_field_vchar(s[i]);
 9625|  34.5k|  }
 9626|  44.1k|}
_ZN7httplib6detail6fields14is_field_vcharEc:
 9601|   632k|inline bool is_field_vchar(char c) { return is_vchar(c) || is_obs_text(c); }
  ------------------
  |  Branch (9601:45): [True: 565k, False: 66.5k]
  |  Branch (9601:60): [True: 66.4k, False: 55]
  ------------------
_ZN7httplib6detail6fields8is_vcharEc:
 9597|   632k|inline bool is_vchar(char c) { return c >= 33 && c <= 126; }
  ------------------
  |  Branch (9597:39): [True: 565k, False: 66.5k]
  |  Branch (9597:50): [True: 565k, False: 3]
  ------------------
_ZN7httplib6detail6fields11is_obs_textEc:
 9599|  66.5k|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:
 1035|  15.4k|    iterator_t &operator++() {
 1036|       |      // Saturating, so that advancing past the last entry of a key (which
 1037|       |      // get_multimap_value() does when asked for an out-of-range id) stays at
 1038|       |      // end() instead of running off the container.
 1039|  15.4k|      if (idx_ >= size_) { return *this; }
  ------------------
  |  Branch (1039:11): [True: 0, False: 15.4k]
  ------------------
 1040|  15.4k|      ++idx_;
 1041|  15.4k|      if (key_idx_ != npos()) {
  ------------------
  |  Branch (1041:11): [True: 1.31k, False: 14.1k]
  ------------------
 1042|  1.56k|        while (idx_ < size_ && !matches(idx_)) {
  ------------------
  |  Branch (1042:16): [True: 654, False: 915]
  |  Branch (1042:32): [True: 252, False: 402]
  ------------------
 1043|    252|          ++idx_;
 1044|    252|        }
 1045|  1.31k|      }
 1046|  15.4k|      return *this;
 1047|  15.4k|    }
_ZNK7httplib6detail26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEE10iterator_tIKNS2_4pairIS8_S8_EEE7matchesEm:
 1087|    654|    bool matches(size_type i) const {
 1088|    654|      return keys_equal(data_[i].first, data_[key_idx_].first);
 1089|    654|    }
_ZN7httplib6detail26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEE10keys_equalERKS8_SD_:
 1006|  46.8k|  static bool keys_equal(const std::string &a, const std::string &b) {
 1007|  46.8k|    return KeyEqual()(a, b);
 1008|  46.8k|  }
_ZNK7httplib6detail11case_ignore8equal_toclERKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEESB_:
  614|  46.8k|  bool operator()(const std::string &a, const std::string &b) const {
  615|  46.8k|    return equal(a, b);
  616|  46.8k|  }
_ZN7httplib6detail11case_ignore5equalERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEESA_:
  606|  48.2k|inline bool equal(const std::string &a, const std::string &b) {
  607|  48.2k|  return a.size() == b.size() &&
  ------------------
  |  Branch (607:10): [True: 8.98k, False: 39.2k]
  ------------------
  608|  8.98k|         std::equal(a.begin(), a.end(), b.begin(), [](char ca, char cb) {
  ------------------
  |  Branch (608:10): [True: 6.25k, False: 2.72k]
  ------------------
  609|  8.98k|           return to_lower(ca) == to_lower(cb);
  610|  8.98k|         });
  611|  48.2k|}
_ZZN7httplib6detail11case_ignore5equalERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEESA_ENKUlccE_clEcc:
  608|   103k|         std::equal(a.begin(), a.end(), b.begin(), [](char ca, char cb) {
  609|   103k|           return to_lower(ca) == to_lower(cb);
  610|   103k|         });
_ZN7httplib6detail11case_ignore8to_lowerEi:
  574|   402k|inline unsigned char to_lower(int c) {
  575|   402k|  const static unsigned char table[256] = {
  576|   402k|      0,   1,   2,   3,   4,   5,   6,   7,   8,   9,   10,  11,  12,  13,  14,
  577|   402k|      15,  16,  17,  18,  19,  20,  21,  22,  23,  24,  25,  26,  27,  28,  29,
  578|   402k|      30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,  43,  44,
  579|   402k|      45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,
  580|   402k|      60,  61,  62,  63,  64,  97,  98,  99,  100, 101, 102, 103, 104, 105, 106,
  581|   402k|      107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121,
  582|   402k|      122, 91,  92,  93,  94,  95,  96,  97,  98,  99,  100, 101, 102, 103, 104,
  583|   402k|      105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
  584|   402k|      120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134,
  585|   402k|      135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
  586|   402k|      150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164,
  587|   402k|      165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179,
  588|   402k|      180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 224, 225, 226,
  589|   402k|      227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241,
  590|   402k|      242, 243, 244, 245, 246, 215, 248, 249, 250, 251, 252, 253, 254, 223, 224,
  591|   402k|      225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
  592|   402k|      240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254,
  593|   402k|      255,
  594|   402k|  };
  595|   402k|  return table[(unsigned char)(char)c];
  596|   402k|}
_ZN7httplib6Stream5writeEPKc:
11106|  3.09k|inline ssize_t Stream::write(const char *ptr) {
11107|  3.09k|  return write(ptr, strlen(ptr));
11108|  3.09k|}
_ZN7httplib6detail26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS2_8equal_toIS8_EEEC2Ev:
 1101|  3.09k|  insertion_ordered_multimap() = default;
_ZN7httplib6detail26insertion_ordered_multimapINS_9FormFieldENSt3__18equal_toINS3_12basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEEEEC2Ev:
 1101|  3.09k|  insertion_ordered_multimap() = default;
_ZN7httplib6detail26insertion_ordered_multimapINS_8FormDataENSt3__18equal_toINS3_12basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEEEEC2Ev:
 1101|  3.09k|  insertion_ordered_multimap() = default;
_ZN7httplib8ResponseC2Ev:
 1751|  3.09k|  Response() = default;
_ZN7httplib8UserDataC2Ev:
 1297|  3.09k|  UserData() = default;
_ZN7httplib10ClientImpl15process_requestERNS_6StreamERNS_7RequestERNS_8ResponseEbRNS_5ErrorE:
14986|  3.09k|                                        Error &error) {
14987|       |  // Auto-add Expect: 100-continue for large bodies
14988|  3.09k|  if (CPPHTTPLIB_EXPECT_100_THRESHOLD > 0 && !req.has_header("Expect")) {
  ------------------
  |  |   82|  3.09k|#define CPPHTTPLIB_EXPECT_100_THRESHOLD 1024
  ------------------
  |  Branch (14988:7): [True: 3.09k, Folded]
  |  Branch (14988:7): [True: 3.09k, False: 0]
  |  Branch (14988:46): [True: 3.09k, False: 0]
  ------------------
14989|  3.09k|    auto body_size = req.body.empty() ? req.content_length_ : req.body.size();
  ------------------
  |  Branch (14989:22): [True: 3.09k, False: 0]
  ------------------
14990|  3.09k|    if (body_size >= CPPHTTPLIB_EXPECT_100_THRESHOLD) {
  ------------------
  |  |   82|  3.09k|#define CPPHTTPLIB_EXPECT_100_THRESHOLD 1024
  ------------------
  |  Branch (14990:9): [True: 0, False: 3.09k]
  ------------------
14991|      0|      req.set_header("Expect", "100-continue");
14992|      0|    }
14993|  3.09k|  }
14994|       |
14995|       |  // Check for Expect: 100-continue
14996|  3.09k|  auto expect_100_continue = req.get_header_value("Expect") == "100-continue";
14997|       |
14998|       |  // Send request (skip body if using Expect: 100-continue)
14999|  3.09k|  auto write_request_success =
15000|  3.09k|      write_request(strm, req, close_connection, error, expect_100_continue);
15001|       |
15002|       |#ifdef CPPHTTPLIB_SSL_ENABLED
15003|       |  if (is_ssl() && !expect_100_continue) {
15004|       |    auto is_proxy_enabled = is_proxy_enabled_for_host(host_);
15005|       |    if (!is_proxy_enabled) {
15006|       |      if (tls::is_peer_closed(socket_.ssl, socket_.sock)) {
15007|       |        error = Error::SSLPeerCouldBeClosed_;
15008|       |        output_error_log(error, &req);
15009|       |        return false;
15010|       |      }
15011|       |    }
15012|       |  }
15013|       |#endif
15014|       |
15015|       |  // Handle Expect: 100-continue.
15016|       |  //
15017|       |  // Wait for an interim/early response by attempting to read the status line
15018|       |  // under a short timeout, instead of trusting raw socket readability. Over
15019|       |  // TLS, post-handshake records (e.g. session tickets) make the socket
15020|       |  // readable without any HTTP response being available; relying on
15021|       |  // `select_read` there caused the body to be withheld forever and the
15022|       |  // request to fail with `Read` (#2458). If no status line arrives within the
15023|       |  // timeout, send the body anyway (matching curl's behavior).
15024|  3.09k|  auto status_line_read = false;
15025|  3.09k|  if (expect_100_continue && write_request_success) {
  ------------------
  |  Branch (15025:7): [True: 0, False: 3.09k]
  |  Branch (15025:30): [True: 0, False: 0]
  ------------------
15026|      0|    if (CPPHTTPLIB_EXPECT_100_TIMEOUT_MSECOND > 0) {
  ------------------
  |  |   86|      0|#define CPPHTTPLIB_EXPECT_100_TIMEOUT_MSECOND 1000
  ------------------
  |  Branch (15026:9): [True: 0, Folded]
  ------------------
15027|      0|      time_t sec = CPPHTTPLIB_EXPECT_100_TIMEOUT_MSECOND / 1000;
  ------------------
  |  |   86|      0|#define CPPHTTPLIB_EXPECT_100_TIMEOUT_MSECOND 1000
  ------------------
15028|      0|      time_t usec = (CPPHTTPLIB_EXPECT_100_TIMEOUT_MSECOND % 1000) * 1000;
  ------------------
  |  |   86|      0|#define CPPHTTPLIB_EXPECT_100_TIMEOUT_MSECOND 1000
  ------------------
15029|      0|      strm.set_read_timeout(sec, usec);
15030|      0|      status_line_read = read_response_line(strm, req, res, false);
15031|      0|      strm.set_read_timeout(read_timeout_sec_, read_timeout_usec_);
15032|      0|    }
15033|       |
15034|      0|    if (!status_line_read) {
  ------------------
  |  Branch (15034:9): [True: 0, False: 0]
  ------------------
15035|       |      // No interim response within the timeout: send the body and handle the
15036|       |      // response as usual.
15037|      0|      if (!write_request_body(strm, req, error)) { return false; }
  ------------------
  |  Branch (15037:11): [True: 0, False: 0]
  ------------------
15038|      0|      expect_100_continue = false; // Switch to normal response handling
15039|      0|    }
15040|      0|  }
15041|       |
15042|       |  // Receive response and headers
15043|       |  // When using Expect: 100-continue, don't auto-skip `100 Continue` response
15044|  3.09k|  if ((!status_line_read &&
  ------------------
  |  Branch (15044:8): [True: 3.09k, False: 0]
  ------------------
15045|  3.09k|       !read_response_line(strm, req, res, !expect_100_continue)) ||
  ------------------
  |  Branch (15045:8): [True: 432, False: 2.66k]
  ------------------
15046|  2.66k|      !detail::read_headers(strm, res.headers)) {
  ------------------
  |  Branch (15046:7): [True: 844, False: 1.82k]
  ------------------
15047|  1.27k|    if (write_request_success) { error = Error::Read; }
  ------------------
  |  Branch (15047:9): [True: 1.27k, False: 0]
  ------------------
15048|  1.27k|    output_error_log(error, &req);
15049|  1.27k|    return false;
15050|  1.27k|  }
15051|       |
15052|  1.82k|  if (!write_request_success) { return false; }
  ------------------
  |  Branch (15052:7): [True: 0, False: 1.82k]
  ------------------
15053|       |
15054|       |  // Handle Expect: 100-continue response
15055|  1.82k|  if (expect_100_continue) {
  ------------------
  |  Branch (15055:7): [True: 0, False: 1.82k]
  ------------------
15056|      0|    if (res.status == StatusCode::Continue_100) {
  ------------------
  |  Branch (15056:9): [True: 0, False: 0]
  ------------------
15057|       |      // Server accepted, send the body
15058|      0|      if (!write_request_body(strm, req, error)) { return false; }
  ------------------
  |  Branch (15058:11): [True: 0, False: 0]
  ------------------
15059|       |
15060|       |      // Read the actual response
15061|      0|      res.headers.clear();
15062|      0|      res.body.clear();
15063|      0|      if (!read_response_line(strm, req, res) ||
  ------------------
  |  Branch (15063:11): [True: 0, False: 0]
  ------------------
15064|      0|          !detail::read_headers(strm, res.headers)) {
  ------------------
  |  Branch (15064:11): [True: 0, False: 0]
  ------------------
15065|      0|        error = Error::Read;
15066|      0|        output_error_log(error, &req);
15067|      0|        return false;
15068|      0|      }
15069|      0|    }
15070|       |    // If not 100 Continue, server returned an error; proceed with that response
15071|      0|  }
15072|       |
15073|       |  // Body
15074|  1.82k|  if ((res.status != StatusCode::NoContent_204) && req.method != "HEAD" &&
  ------------------
  |  Branch (15074:7): [True: 1.80k, False: 11]
  |  Branch (15074:52): [True: 1.80k, False: 0]
  ------------------
15075|  1.80k|      req.method != "CONNECT") {
  ------------------
  |  Branch (15075:7): [True: 1.80k, False: 0]
  ------------------
15076|  1.80k|    auto redirect = 300 < res.status && res.status < 400 &&
  ------------------
  |  Branch (15076:21): [True: 579, False: 1.23k]
  |  Branch (15076:41): [True: 176, False: 403]
  ------------------
15077|    176|                    res.status != StatusCode::NotModified_304 &&
  ------------------
  |  Branch (15077:21): [True: 168, False: 8]
  ------------------
15078|    168|                    follow_location_;
  ------------------
  |  Branch (15078:21): [True: 0, False: 168]
  ------------------
15079|       |
15080|  1.80k|    if (req.response_handler && !redirect) {
  ------------------
  |  Branch (15080:9): [True: 0, False: 1.80k]
  |  Branch (15080:33): [True: 0, False: 0]
  ------------------
15081|      0|      if (!req.response_handler(res)) {
  ------------------
  |  Branch (15081:11): [True: 0, False: 0]
  ------------------
15082|      0|        error = Error::Canceled;
15083|      0|        output_error_log(error, &req);
15084|      0|        return false;
15085|      0|      }
15086|      0|    }
15087|       |
15088|  1.80k|    auto out =
15089|  1.80k|        req.content_receiver
  ------------------
  |  Branch (15089:9): [True: 0, False: 1.80k]
  ------------------
15090|  1.80k|            ? static_cast<ContentReceiverWithProgress>(
15091|      0|                  [&](const char *buf, size_t n, size_t off, size_t len) {
15092|      0|                    if (redirect) { return true; }
15093|      0|                    auto ret = req.content_receiver(buf, n, off, len);
15094|      0|                    if (!ret) {
15095|      0|                      error = Error::Canceled;
15096|      0|                      output_error_log(error, &req);
15097|      0|                    }
15098|      0|                    return ret;
15099|      0|                  })
15100|  1.80k|            : static_cast<ContentReceiverWithProgress>(
15101|  1.80k|                  [&](const char *buf, size_t n, size_t /*off*/,
15102|  1.80k|                      size_t /*len*/) {
15103|  1.80k|                    assert(res.body.size() + n <= res.body.max_size());
15104|  1.80k|                    if (payload_max_length_ > 0 &&
15105|  1.80k|                        (res.body.size() >= payload_max_length_ ||
15106|  1.80k|                         n > payload_max_length_ - res.body.size())) {
15107|  1.80k|                      return false;
15108|  1.80k|                    }
15109|  1.80k|                    res.body.append(buf, n);
15110|  1.80k|                    return true;
15111|  1.80k|                  });
15112|       |
15113|  1.80k|    auto progress = [&](size_t current, size_t total) {
15114|  1.80k|      if (!req.download_progress || redirect) { return true; }
15115|  1.80k|      auto ret = req.download_progress(current, total);
15116|  1.80k|      if (!ret) {
15117|  1.80k|        error = Error::Canceled;
15118|  1.80k|        output_error_log(error, &req);
15119|  1.80k|      }
15120|  1.80k|      return ret;
15121|  1.80k|    };
15122|       |
15123|  1.80k|    if (res.has_header("Content-Length")) {
  ------------------
  |  Branch (15123:9): [True: 602, False: 1.20k]
  ------------------
15124|    602|      if (!req.content_receiver) {
  ------------------
  |  Branch (15124:11): [True: 602, False: 0]
  ------------------
15125|    602|        auto len = res.get_header_value_u64("Content-Length");
15126|    602|        if (len > res.body.max_size()) {
  ------------------
  |  Branch (15126:13): [True: 66, False: 536]
  ------------------
15127|     66|          error = Error::Read;
15128|     66|          output_error_log(error, &req);
15129|     66|          return false;
15130|     66|        }
15131|       |        // Cap the reservation by payload_max_length_ to avoid OOM when a
15132|       |        // hostile or malformed server sends an enormous Content-Length.
15133|       |        // The actual body read below is bounded by payload_max_length_,
15134|       |        // so reserving more than that is never useful.
15135|    536|        auto reserve_len = static_cast<size_t>(len);
15136|    536|        if (payload_max_length_ > 0 && reserve_len > payload_max_length_) {
  ------------------
  |  Branch (15136:13): [True: 536, False: 0]
  |  Branch (15136:40): [True: 314, False: 222]
  ------------------
15137|    314|          reserve_len = payload_max_length_;
15138|    314|        }
15139|    536|        res.body.reserve(reserve_len);
15140|    536|      }
15141|    602|    }
15142|       |
15143|  1.74k|    if (res.status != StatusCode::NotModified_304) {
  ------------------
  |  Branch (15143:9): [True: 1.73k, False: 8]
  ------------------
15144|  1.73k|      auto content_status = 0;
15145|  1.73k|      auto max_length = (!has_payload_max_length_ && req.content_receiver)
  ------------------
  |  Branch (15145:26): [True: 1.73k, False: 0]
  |  Branch (15145:54): [True: 0, False: 1.73k]
  ------------------
15146|  1.73k|                            ? (std::numeric_limits<size_t>::max)()
15147|  1.73k|                            : payload_max_length_;
15148|  1.73k|      if (!detail::read_content(strm, res, max_length, content_status,
  ------------------
  |  Branch (15148:11): [True: 1.25k, False: 485]
  ------------------
15149|  1.73k|                                std::move(progress), std::move(out),
15150|  1.73k|                                decompress_)) {
15151|  1.25k|        if (error != Error::Canceled) {
  ------------------
  |  Branch (15151:13): [True: 1.25k, False: 0]
  ------------------
15152|       |          // Tell the caller apart from a plain read failure when the body could
15153|       |          // not be decoded because of its Content-Encoding.
15154|  1.25k|          switch (content_status) {
15155|     13|          case StatusCode::UnsupportedMediaType_415:
  ------------------
  |  Branch (15155:11): [True: 13, False: 1.23k]
  ------------------
15156|     13|            error = Error::UnsupportedContentEncoding;
15157|     13|            break;
15158|      0|          case StatusCode::InternalServerError_500:
  ------------------
  |  Branch (15158:11): [True: 0, False: 1.25k]
  ------------------
15159|      0|            error = Error::Compression;
15160|      0|            break;
15161|  1.23k|          default: error = Error::Read; break;
  ------------------
  |  Branch (15161:11): [True: 1.23k, False: 13]
  ------------------
15162|  1.25k|          }
15163|  1.25k|        }
15164|  1.25k|        output_error_log(error, &req);
15165|  1.25k|        return false;
15166|  1.25k|      }
15167|  1.73k|    }
15168|  1.74k|  }
15169|       |
15170|       |  // Log
15171|    504|  output_log(req, res);
15172|       |
15173|    504|  return true;
15174|  1.82k|}
_ZNK7httplib7Request10has_headerERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
10819|  18.5k|inline bool Request::has_header(const std::string &key) const {
10820|  18.5k|  return detail::has_header(headers, key);
10821|  18.5k|}
_ZN7httplib6detail10has_headerERKNS0_26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEEERKS8_:
 7700|  19.6k|inline bool has_header(const Headers &headers, const std::string &key) {
 7701|  19.6k|  if (is_prohibited_header_name(key)) { return false; }
  ------------------
  |  Branch (7701:7): [True: 0, False: 19.6k]
  ------------------
 7702|  19.6k|  return headers.find(key) != headers.end();
 7703|  19.6k|}
_ZN7httplib6detail25is_prohibited_header_nameERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
 7688|  24.5k|inline bool is_prohibited_header_name(const std::string &name) {
 7689|  24.5k|  using udl::operator""_t;
 7690|       |
 7691|  24.5k|  switch (str2tag(name)) {
 7692|      0|  case "REMOTE_ADDR"_t:
  ------------------
  |  Branch (7692:3): [True: 0, False: 24.5k]
  ------------------
 7693|      0|  case "REMOTE_PORT"_t:
  ------------------
  |  Branch (7693:3): [True: 0, False: 24.5k]
  ------------------
 7694|      0|  case "LOCAL_ADDR"_t:
  ------------------
  |  Branch (7694:3): [True: 0, False: 24.5k]
  ------------------
 7695|      0|  case "LOCAL_PORT"_t: return true;
  ------------------
  |  Branch (7695:3): [True: 0, False: 24.5k]
  ------------------
 7696|  24.5k|  default: return false;
  ------------------
  |  Branch (7696:3): [True: 24.5k, False: 0]
  ------------------
 7697|  24.5k|  }
 7698|  24.5k|}
_ZN7httplib6detail7str2tagERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
 7076|  24.5k|inline unsigned int str2tag(const std::string &s) {
 7077|       |  // Iterative form of str2tag_core: the recursive constexpr version is kept
 7078|       |  // for compile-time UDL evaluation of short string literals, but at runtime
 7079|       |  // we may receive arbitrarily long inputs (e.g. fuzzed Content-Type) that
 7080|       |  // would blow the stack with one frame per character.
 7081|  24.5k|  unsigned int h = 0;
 7082|   225k|  for (auto c : s) {
  ------------------
  |  Branch (7082:15): [True: 225k, False: 24.5k]
  ------------------
 7083|   225k|    h = (((std::numeric_limits<unsigned int>::max)() >> 6) & h * 33) ^
 7084|   225k|        static_cast<unsigned char>(c);
 7085|   225k|  }
 7086|  24.5k|  return h;
 7087|  24.5k|}
_ZNK7httplib6detail26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEE4findERKS8_:
 1147|  21.4k|  const_iterator find(const std::string &key) const {
 1148|  21.4k|    auto i = index_of(key);
 1149|  21.4k|    return i == npos() ? end() : make_citer(i, i);
  ------------------
  |  Branch (1149:12): [True: 20.2k, False: 1.13k]
  ------------------
 1150|  21.4k|  }
_ZNK7httplib6detail26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEE8index_ofERKS8_:
 1232|  31.2k|  size_type index_of(const std::string &key) const {
 1233|  72.0k|    for (size_type i = 0; i < entries_.size(); i++) {
  ------------------
  |  Branch (1233:27): [True: 44.9k, False: 27.0k]
  ------------------
 1234|  44.9k|      if (keys_equal(entries_[i].first, key)) { return i; }
  ------------------
  |  Branch (1234:11): [True: 4.16k, False: 40.7k]
  ------------------
 1235|  44.9k|    }
 1236|  27.0k|    return npos();
 1237|  31.2k|  }
_ZN7httplib7Request10set_headerERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEES9_:
10833|  7.96k|                                const std::string &val) {
10834|  7.96k|  detail::set_header(headers, key, val);
10835|  7.96k|}
_ZN7httplib6detail10set_headerERNS0_26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEEERKS8_SE_:
 7740|  7.96k|                       const std::string &val) {
 7741|  7.96k|  if (fields::is_field_valid(key, val)) { headers.emplace(key, val); }
  ------------------
  |  Branch (7741:7): [True: 7.96k, False: 0]
  ------------------
 7742|  7.96k|}
_ZN7httplib6detail26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEE7emplaceIJRKS8_SE_EEENSB_10iterator_tINS2_4pairIS8_S8_EEEEDpOT_:
 1130|  17.5k|  template <typename... Args> iterator emplace(Args &&...args) {
 1131|  17.5k|    entries_.emplace_back(std::forward<Args>(args)...);
 1132|  17.5k|    return make_iter(entries_.size() - 1, npos());
 1133|  17.5k|  }
_ZN7httplib6detail26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEE9make_iterEmm:
 1239|  40.0k|  iterator make_iter(size_type idx, size_type key_idx) {
 1240|  40.0k|    return iterator(entries_.data(), idx, entries_.size(), key_idx);
 1241|  40.0k|  }
_ZN7httplib6detail26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEE10iterator_tINS2_4pairIS8_S8_EEEC2EPSE_mmm:
 1085|  40.0k|        : data_(data), idx_(idx), size_(size), key_idx_(key_idx) {}
_ZNK7httplib7Request16get_header_valueERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEPKcm:
10824|  3.09k|                                             const char *def, size_t id) const {
10825|  3.09k|  return detail::get_header_value(headers, key, def, id);
10826|  3.09k|}
_ZN7httplib6detail16get_header_valueERKNS0_26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEEERKS8_PKcm:
 7707|  4.98k|                                    size_t id) {
 7708|  4.98k|  if (is_prohibited_header_name(key)) {
  ------------------
  |  Branch (7708:7): [True: 0, False: 4.98k]
  ------------------
 7709|      0|#ifndef CPPHTTPLIB_NO_EXCEPTIONS
 7710|      0|    std::string msg = "Prohibited header name '" + key + "' is specified.";
 7711|      0|    throw std::invalid_argument(msg);
 7712|       |#else
 7713|       |    return "";
 7714|       |#endif
 7715|      0|  }
 7716|       |
 7717|  4.98k|  auto rng = headers.equal_range(key);
 7718|  4.98k|  auto it = rng.first;
 7719|  4.98k|  std::advance(it, static_cast<ssize_t>(id));
 7720|  4.98k|  if (it != rng.second) { return it->second.c_str(); }
  ------------------
  |  Branch (7720:7): [True: 207, False: 4.77k]
  ------------------
 7721|  4.77k|  return def;
 7722|  4.98k|}
_ZNK7httplib6detail26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEE11equal_rangeERKS8_:
 1167|  7.83k|  equal_range(const std::string &key) const {
 1168|  7.83k|    auto i = index_of(key);
 1169|  7.83k|    return i == npos() ? std::make_pair(end(), end())
  ------------------
  |  Branch (1169:12): [True: 5.58k, False: 2.25k]
  ------------------
 1170|  7.83k|                       : std::make_pair(make_citer(i, i), end());
 1171|  7.83k|  }
_ZNK7httplib6detail26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEE10iterator_tIKNS2_4pairIS8_S8_EEEptEv:
 1033|  3.65k|    pointer operator->() const { return data_ + idx_; }
_ZN7httplib10ClientImpl13write_requestERNS_6StreamERNS_7RequestEbRNS_5ErrorEb:
14649|  3.09k|                                      bool skip_body) {
14650|       |  // Prepare additional headers
14651|  3.09k|  if (close_connection) {
  ------------------
  |  Branch (14651:7): [True: 0, False: 3.09k]
  ------------------
14652|      0|    if (!req.has_header("Connection")) {
  ------------------
  |  Branch (14652:9): [True: 0, False: 0]
  ------------------
14653|      0|      req.set_header("Connection", "close");
14654|      0|    }
14655|      0|  }
14656|       |
14657|  3.09k|  std::string ct_for_defaults;
14658|  3.09k|  if (!req.has_header("Content-Type") && !req.body.empty()) {
  ------------------
  |  Branch (14658:7): [True: 3.09k, False: 0]
  |  Branch (14658:7): [True: 0, False: 3.09k]
  |  Branch (14658:42): [True: 0, False: 3.09k]
  ------------------
14659|      0|    ct_for_defaults = "text/plain";
14660|      0|  }
14661|  3.09k|  prepare_default_headers(req, false, ct_for_defaults);
14662|       |
14663|  3.09k|  if (req.body.empty()) {
  ------------------
  |  Branch (14663:7): [True: 3.09k, False: 0]
  ------------------
14664|  3.09k|    if (req.content_provider_) {
  ------------------
  |  Branch (14664:9): [True: 0, False: 3.09k]
  ------------------
14665|      0|      if (!req.is_chunked_content_provider_) {
  ------------------
  |  Branch (14665:11): [True: 0, False: 0]
  ------------------
14666|      0|        if (!req.has_header("Content-Length")) {
  ------------------
  |  Branch (14666:13): [True: 0, False: 0]
  ------------------
14667|      0|          auto length = std::to_string(req.content_length_);
14668|      0|          req.set_header("Content-Length", length);
14669|      0|        }
14670|      0|      }
14671|  3.09k|    } else {
14672|  3.09k|      if (req.method == "POST" || req.method == "PUT" ||
  ------------------
  |  Branch (14672:11): [True: 686, False: 2.41k]
  |  Branch (14672:35): [True: 798, False: 1.61k]
  ------------------
14673|  1.77k|          req.method == "PATCH") {
  ------------------
  |  Branch (14673:11): [True: 293, False: 1.31k]
  ------------------
14674|  1.77k|        req.set_header("Content-Length", "0");
14675|  1.77k|      }
14676|  3.09k|    }
14677|  3.09k|  }
14678|       |
14679|  3.09k|  if (!basic_auth_password_.empty() || !basic_auth_username_.empty()) {
  ------------------
  |  Branch (14679:7): [True: 0, False: 3.09k]
  |  Branch (14679:40): [True: 0, False: 3.09k]
  ------------------
14680|      0|    if (!req.has_header("Authorization")) {
  ------------------
  |  Branch (14680:9): [True: 0, False: 0]
  ------------------
14681|      0|      req.headers.insert(make_basic_authentication_header(
14682|      0|          basic_auth_username_, basic_auth_password_, false));
14683|      0|    }
14684|      0|  }
14685|       |
14686|  3.09k|  if (!bearer_token_auth_token_.empty()) {
  ------------------
  |  Branch (14686:7): [True: 0, False: 3.09k]
  ------------------
14687|      0|    if (!req.has_header("Authorization")) {
  ------------------
  |  Branch (14687:9): [True: 0, False: 0]
  ------------------
14688|      0|      req.headers.insert(make_bearer_token_authentication_header(
14689|      0|          bearer_token_auth_token_, false));
14690|      0|    }
14691|      0|  }
14692|       |
14693|       |  // Proxy-Authorization is only sent when the proxy is actually used for
14694|       |  // this target — otherwise NO_PROXY-matched requests would leak proxy
14695|       |  // credentials directly to the destination server.
14696|  3.09k|  if (is_proxy_enabled_for_host(host_)) {
  ------------------
  |  Branch (14696:7): [True: 0, False: 3.09k]
  ------------------
14697|      0|    if (!proxy_basic_auth_username_.empty() &&
  ------------------
  |  Branch (14697:9): [True: 0, False: 0]
  |  Branch (14697:9): [True: 0, False: 0]
  ------------------
14698|      0|        !proxy_basic_auth_password_.empty() &&
  ------------------
  |  Branch (14698:9): [True: 0, False: 0]
  ------------------
14699|      0|        !req.has_header("Proxy-Authorization")) {
  ------------------
  |  Branch (14699:9): [True: 0, False: 0]
  ------------------
14700|      0|      req.headers.insert(make_basic_authentication_header(
14701|      0|          proxy_basic_auth_username_, proxy_basic_auth_password_, true));
14702|      0|    }
14703|      0|    if (!proxy_bearer_token_auth_token_.empty() &&
  ------------------
  |  Branch (14703:9): [True: 0, False: 0]
  |  Branch (14703:9): [True: 0, False: 0]
  ------------------
14704|      0|        !req.has_header("Proxy-Authorization")) {
  ------------------
  |  Branch (14704:9): [True: 0, False: 0]
  ------------------
14705|      0|      req.headers.insert(make_bearer_token_authentication_header(
14706|      0|          proxy_bearer_token_auth_token_, true));
14707|      0|    }
14708|      0|  }
14709|       |
14710|       |  // Request line and headers
14711|  3.09k|  {
14712|  3.09k|    detail::BufferStream bstrm;
14713|       |
14714|       |    // Extract the query from req.path. The encoding itself is delegated to
14715|       |    // `encode_request_target`; the raw query is still needed here to decide
14716|       |    // between populating `req.params` from it and falling back to building a
14717|       |    // query out of caller-supplied `req.params`.
14718|  3.09k|    auto query_pos = req.path.find('?');
14719|  3.09k|    auto query_part = query_pos == std::string::npos
  ------------------
  |  Branch (14719:23): [True: 3.09k, False: 0]
  ------------------
14720|  3.09k|                          ? std::string()
14721|  3.09k|                          : req.path.substr(query_pos + 1);
14722|       |
14723|  3.09k|    auto path_with_query =
14724|  3.09k|        detail::encode_request_target(req.path, path_encode_);
14725|       |
14726|  3.09k|    if (!query_part.empty()) {
  ------------------
  |  Branch (14726:9): [True: 0, False: 3.09k]
  ------------------
14727|       |      // The query already came in through `req.path`; still populate
14728|       |      // `req.params` for handlers/users who read them.
14729|      0|      detail::parse_query_text(query_part, req.params);
14730|  3.09k|    } else if (!req.params.empty()) {
  ------------------
  |  Branch (14730:16): [True: 0, False: 3.09k]
  ------------------
14731|       |      // No query in `req.path`; build one from `req.params` so existing
14732|       |      // callers that pass `Params` separately continue to work.
14733|      0|      path_with_query = append_query_params(path_with_query, req.params);
14734|      0|    }
14735|       |
14736|       |    // Write request line and headers
14737|  3.09k|    if (detail::write_request_line(bstrm, req.method, path_with_query) < 0) {
  ------------------
  |  Branch (14737:9): [True: 0, False: 3.09k]
  ------------------
14738|       |      // A rejected target (e.g. CR/LF smuggled in via a decoded redirect
14739|       |      // Location under set_path_encode(false)) must fail the request cleanly
14740|       |      // instead of emitting a request-line-less, header-injecting request.
14741|      0|      error = Error::Write;
14742|      0|      output_error_log(error, &req);
14743|      0|      return false;
14744|      0|    }
14745|  3.09k|    if (!detail::check_and_write_headers(bstrm, req.headers, header_writer_,
  ------------------
  |  Branch (14745:9): [True: 0, False: 3.09k]
  ------------------
14746|  3.09k|                                         error)) {
14747|      0|      output_error_log(error, &req);
14748|      0|      return false;
14749|      0|    }
14750|       |
14751|       |    // Flush buffer
14752|  3.09k|    auto &data = bstrm.get_buffer();
14753|  3.09k|    if (!detail::write_data(strm, data.data(), data.size())) {
  ------------------
  |  Branch (14753:9): [True: 0, False: 3.09k]
  ------------------
14754|      0|      error = Error::Write;
14755|      0|      output_error_log(error, &req);
14756|      0|      return false;
14757|      0|    }
14758|  3.09k|  }
14759|       |
14760|       |  // After sending request line and headers, wait briefly for an early server
14761|       |  // response (e.g. 4xx) and avoid sending a potentially large request body
14762|       |  // unnecessarily. This workaround is only enabled on Windows because Unix
14763|       |  // platforms surface write errors (EPIPE) earlier; on Windows kernel send
14764|       |  // buffering can accept large writes even when the peer already responded.
14765|       |  // Check the stream first (which covers SSL via `is_readable()`), then
14766|       |  // fall back to select on the socket. Only perform the wait for very large
14767|       |  // request bodies to avoid interfering with normal small requests and
14768|       |  // reduce side-effects. Poll briefly (up to 50ms as default) for an early
14769|       |  // response. Skip this check when using Expect: 100-continue, as the protocol
14770|       |  // handles early responses properly.
14771|       |#if defined(_WIN32)
14772|       |  if (!skip_body &&
14773|       |      req.body.size() > CPPHTTPLIB_WAIT_EARLY_SERVER_RESPONSE_THRESHOLD &&
14774|       |      req.path.size() > CPPHTTPLIB_REQUEST_URI_MAX_LENGTH) {
14775|       |    auto start = std::chrono::high_resolution_clock::now();
14776|       |
14777|       |    for (;;) {
14778|       |      // Prefer socket-level readiness to avoid SSL_pending() false-positives
14779|       |      // from SSL internals. If the underlying socket is readable, assume an
14780|       |      // early response may be present.
14781|       |      auto sock = strm.socket();
14782|       |      if (sock != INVALID_SOCKET && detail::select_read(sock, 0, 0) > 0) {
14783|       |        return false;
14784|       |      }
14785|       |
14786|       |      // Fallback to stream-level check for non-socket streams or when the
14787|       |      // socket isn't reporting readable. Avoid using `is_readable()` for
14788|       |      // SSL, since `SSL_pending()` may report buffered records that do not
14789|       |      // indicate a complete application-level response yet.
14790|       |      if (!is_ssl() && strm.is_readable()) { return false; }
14791|       |
14792|       |      auto now = std::chrono::high_resolution_clock::now();
14793|       |      auto elapsed =
14794|       |          std::chrono::duration_cast<std::chrono::milliseconds>(now - start)
14795|       |              .count();
14796|       |      if (elapsed >= CPPHTTPLIB_WAIT_EARLY_SERVER_RESPONSE_TIMEOUT_MSECOND) {
14797|       |        break;
14798|       |      }
14799|       |
14800|       |      std::this_thread::sleep_for(std::chrono::milliseconds(1));
14801|       |    }
14802|       |  }
14803|       |#endif
14804|       |
14805|       |  // Body
14806|  3.09k|  if (skip_body) { return true; }
  ------------------
  |  Branch (14806:7): [True: 0, False: 3.09k]
  ------------------
14807|       |
14808|  3.09k|  return write_request_body(strm, req, error);
14809|  3.09k|}
_ZN7httplib10ClientImpl23prepare_default_headersERNS_7RequestEbRKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEE:
13996|  3.09k|                                                const std::string &ct) {
13997|  3.09k|  (void)for_stream;
13998|  3.09k|  for (const auto &header : default_headers_) {
  ------------------
  |  Branch (13998:27): [True: 0, False: 3.09k]
  ------------------
13999|      0|    if (!r.has_header(header.first)) { r.headers.insert(header); }
  ------------------
  |  Branch (13999:9): [True: 0, False: 0]
  ------------------
14000|      0|  }
14001|       |
14002|       |  // RFC 9110 5.3 recommends sending control data such as Host first, so
14003|       |  // prepend it rather than appending it after the caller's own fields.
14004|  3.09k|  if (!r.has_header("Host")) {
  ------------------
  |  Branch (14004:7): [True: 3.09k, False: 0]
  ------------------
14005|  3.09k|    r.headers.emplace_front(
14006|  3.09k|        "Host", detail::make_default_host_header_value(host_, port_, is_ssl(),
14007|  3.09k|                                                       address_family_));
14008|  3.09k|  }
14009|       |
14010|  3.09k|  if (!r.has_header("Accept")) { r.headers.emplace("Accept", "*/*"); }
  ------------------
  |  Branch (14010:7): [True: 3.09k, False: 0]
  ------------------
14011|       |
14012|  3.09k|  if (!r.content_receiver) {
  ------------------
  |  Branch (14012:7): [True: 3.09k, False: 0]
  ------------------
14013|  3.09k|    if (!r.has_header("Accept-Encoding")) {
  ------------------
  |  Branch (14013:9): [True: 3.09k, False: 0]
  ------------------
14014|  3.09k|      std::string accept_encoding;
14015|       |#ifdef CPPHTTPLIB_BROTLI_SUPPORT
14016|       |      accept_encoding = "br";
14017|       |#endif
14018|  3.09k|#ifdef CPPHTTPLIB_ZLIB_SUPPORT
14019|  3.09k|      if (!accept_encoding.empty()) { accept_encoding += ", "; }
  ------------------
  |  Branch (14019:11): [True: 0, False: 3.09k]
  ------------------
14020|  3.09k|      accept_encoding += "gzip, deflate";
14021|  3.09k|#endif
14022|       |#ifdef CPPHTTPLIB_ZSTD_SUPPORT
14023|       |      if (!accept_encoding.empty()) { accept_encoding += ", "; }
14024|       |      accept_encoding += "zstd";
14025|       |#endif
14026|  3.09k|      r.set_header("Accept-Encoding", accept_encoding);
14027|  3.09k|    }
14028|       |
14029|  3.09k|    detail::add_default_user_agent_header(r);
14030|  3.09k|  }
14031|       |
14032|  3.09k|  if (!r.body.empty()) {
  ------------------
  |  Branch (14032:7): [True: 0, False: 3.09k]
  ------------------
14033|      0|    if (!ct.empty() && !r.has_header("Content-Type")) {
  ------------------
  |  Branch (14033:9): [True: 0, False: 0]
  |  Branch (14033:9): [True: 0, False: 0]
  |  Branch (14033:24): [True: 0, False: 0]
  ------------------
14034|      0|      r.headers.emplace("Content-Type", ct);
14035|      0|    }
14036|      0|    if (!r.has_header("Content-Length")) {
  ------------------
  |  Branch (14036:9): [True: 0, False: 0]
  ------------------
14037|      0|      r.headers.emplace("Content-Length", std::to_string(r.body.size()));
14038|      0|    }
14039|      0|  }
14040|  3.09k|}
_ZN7httplib6detail26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEE5beginEv:
 1108|  6.19k|  iterator begin() { return make_iter(0, npos()); }
_ZN7httplib6detail26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEE3endEv:
 1109|  9.39k|  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:
 1076|  23.8k|    template <typename U> bool operator!=(const iterator_t<U> &rhs) const {
 1077|  23.8k|      return idx_ != rhs.idx_;
 1078|  23.8k|    }
_ZNK7httplib6detail26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEE10iterator_tINS2_4pairIS8_S8_EEEdeEv:
 1032|  14.1k|    reference operator*() const { return data_[idx_]; }
_ZN7httplib6detail26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEE10iterator_tINS2_4pairIS8_S8_EEEppEv:
 1035|  15.6k|    iterator_t &operator++() {
 1036|       |      // Saturating, so that advancing past the last entry of a key (which
 1037|       |      // get_multimap_value() does when asked for an out-of-range id) stays at
 1038|       |      // end() instead of running off the container.
 1039|  15.6k|      if (idx_ >= size_) { return *this; }
  ------------------
  |  Branch (1039:11): [True: 0, False: 15.6k]
  ------------------
 1040|  15.6k|      ++idx_;
 1041|  15.6k|      if (key_idx_ != npos()) {
  ------------------
  |  Branch (1041:11): [True: 1.47k, False: 14.1k]
  ------------------
 1042|  1.84k|        while (idx_ < size_ && !matches(idx_)) {
  ------------------
  |  Branch (1042:16): [True: 1.23k, False: 604]
  |  Branch (1042:32): [True: 367, False: 870]
  ------------------
 1043|    367|          ++idx_;
 1044|    367|        }
 1045|  1.47k|      }
 1046|  15.6k|      return *this;
 1047|  15.6k|    }
_ZNK7httplib6detail26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEE10iterator_tINS2_4pairIS8_S8_EEE7matchesEm:
 1087|  1.23k|    bool matches(size_type i) const {
 1088|  1.23k|      return keys_equal(data_[i].first, data_[key_idx_].first);
 1089|  1.23k|    }
_ZN7httplib6detail26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEE13emplace_frontIJRA5_KcS8_EEENSB_10iterator_tINS2_4pairIS8_S8_EEEEDpOT_:
 1137|  3.09k|  template <typename... Args> iterator emplace_front(Args &&...args) {
 1138|  3.09k|    entries_.emplace(entries_.begin(), std::forward<Args>(args)...);
 1139|  3.09k|    return make_iter(0, npos());
 1140|  3.09k|  }
_ZN7httplib6detail30make_default_host_header_valueERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEibi:
11676|  3.09k|                                                  int address_family) {
11677|  3.09k|  if (address_family == AF_UNIX) { return "localhost"; }
  ------------------
  |  Branch (11677:7): [True: 0, False: 3.09k]
  ------------------
11678|  3.09k|  return make_host_and_port_string(host, port, is_ssl);
11679|  3.09k|}
_ZN7httplib6detail25make_host_and_port_stringERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEib:
11653|  3.09k|                                             bool is_ssl) {
11654|  3.09k|  auto result = prepare_host_string(host);
11655|       |
11656|       |  // Append port if not default
11657|  3.09k|  if ((!is_ssl && port == 80) || (is_ssl && port == 443)) {
  ------------------
  |  Branch (11657:8): [True: 3.09k, False: 0]
  |  Branch (11657:19): [True: 0, False: 3.09k]
  |  Branch (11657:35): [True: 0, False: 3.09k]
  |  Branch (11657:45): [True: 0, False: 0]
  ------------------
11658|      0|    ; // do nothing
11659|  3.09k|  } else {
11660|  3.09k|    result += ":" + std::to_string(port);
11661|  3.09k|  }
11662|       |
11663|  3.09k|  return result;
11664|  3.09k|}
_ZN7httplib6detail19prepare_host_stringERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
11640|  3.09k|inline std::string prepare_host_string(const std::string &host) {
11641|       |  // Enclose IPv6 address in brackets (but not if already enclosed)
11642|  3.09k|  if (host.find(':') == std::string::npos ||
  ------------------
  |  Branch (11642:7): [True: 3.09k, False: 0]
  ------------------
11643|  3.09k|      (!host.empty() && host[0] == '[')) {
  ------------------
  |  Branch (11643:8): [True: 0, False: 0]
  |  Branch (11643:25): [True: 0, False: 0]
  ------------------
11644|       |    // IPv4, hostname, or already bracketed IPv6
11645|  3.09k|    return host;
11646|  3.09k|  } else {
11647|       |    // IPv6 address without brackets
11648|      0|    return "[" + host + "]";
11649|      0|  }
11650|  3.09k|}
_ZN7httplib6detail26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEE7emplaceIJRA7_KcRA4_SD_EEENSB_10iterator_tINS2_4pairIS8_S8_EEEEDpOT_:
 1130|  3.09k|  template <typename... Args> iterator emplace(Args &&...args) {
 1131|  3.09k|    entries_.emplace_back(std::forward<Args>(args)...);
 1132|  3.09k|    return make_iter(entries_.size() - 1, npos());
 1133|  3.09k|  }
_ZN7httplib6detail29add_default_user_agent_headerERNS_7RequestE:
11681|  3.09k|inline void add_default_user_agent_header(Request &req) {
11682|  3.09k|#ifndef CPPHTTPLIB_NO_DEFAULT_USER_AGENT
11683|  3.09k|  if (!req.has_header("User-Agent")) {
  ------------------
  |  Branch (11683:7): [True: 3.09k, False: 0]
  ------------------
11684|  3.09k|    req.set_header("User-Agent",
11685|  3.09k|                   std::string("cpp-httplib/") + CPPHTTPLIB_VERSION);
  ------------------
  |  |   11|  3.09k|#define CPPHTTPLIB_VERSION "0.53.0"
  ------------------
11686|  3.09k|  }
11687|       |#else
11688|       |  (void)req;
11689|       |#endif
11690|  3.09k|}
_ZNK7httplib10ClientImpl25is_proxy_enabled_for_hostERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
13752|  3.09k|ClientImpl::is_proxy_enabled_for_host(const std::string &host) const {
13753|  3.09k|  if (proxy_host_.empty() || proxy_port_ == -1) { return false; }
  ------------------
  |  Branch (13753:7): [True: 3.09k, False: 0]
  |  Branch (13753:30): [True: 0, False: 0]
  ------------------
13754|      0|  if (no_proxy_entries_.empty()) { return true; }
  ------------------
  |  Branch (13754:7): [True: 0, False: 0]
  ------------------
13755|       |  // host_ is const so its normalized form is invariant; cache it. The
13756|       |  // cross-host path (setup_redirect_client passing next_host) re-normalizes.
13757|      0|  if (host == host_) {
  ------------------
  |  Branch (13757:7): [True: 0, False: 0]
  ------------------
13758|      0|    if (!host_normalized_valid_) {
  ------------------
  |  Branch (13758:9): [True: 0, False: 0]
  ------------------
13759|      0|      host_normalized_ = detail::normalize_target(host_);
13760|      0|      host_normalized_valid_ = true;
13761|      0|    }
13762|      0|    return !detail::host_matches_no_proxy(host_normalized_, no_proxy_entries_);
13763|      0|  }
13764|      0|  auto target = detail::normalize_target(host);
13765|      0|  return !detail::host_matches_no_proxy(target, no_proxy_entries_);
13766|      0|}
_ZN7httplib6detail12BufferStreamC2Ev:
 3526|  3.09k|  BufferStream() = default;
_ZN7httplib6detail21encode_request_targetERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEb:
 8538|  3.09k|                                         bool path_encode) {
 8539|       |  // `substr(0, npos)` yields the whole string, which is what the no-query
 8540|       |  // case needs.
 8541|  3.09k|  auto query_pos = target.find('?');
 8542|  3.09k|  auto path_part = target.substr(0, query_pos);
 8543|  3.09k|  std::string query_part;
 8544|  3.09k|  if (query_pos != std::string::npos) {
  ------------------
  |  Branch (8544:7): [True: 0, False: 3.09k]
  ------------------
 8545|      0|    query_part = target.substr(query_pos + 1);
 8546|      0|  }
 8547|       |
 8548|  3.09k|  auto result = path_encode ? encode_path(path_part) : std::move(path_part);
  ------------------
  |  Branch (8548:17): [True: 3.09k, False: 0]
  ------------------
 8549|       |
 8550|  3.09k|  if (!query_part.empty()) {
  ------------------
  |  Branch (8550:7): [True: 0, False: 3.09k]
  ------------------
 8551|       |    // When path encoding is disabled the caller has supplied an already-encoded
 8552|       |    // target and expects the exact bytes to be sent on the wire, so skip
 8553|       |    // normalization for the query too. Normalizing would decode-then-re-encode
 8554|       |    // it and corrupt pre-encoded binary payloads (e.g. turning `%20` into `+`,
 8555|       |    // which a strict RFC 3986 server decodes back as `+`, not a space).
 8556|      0|    if (path_encode) {
  ------------------
  |  Branch (8556:9): [True: 0, False: 0]
  ------------------
 8557|      0|      auto normalized = normalize_query_string(query_part);
 8558|      0|      if (!normalized.empty()) {
  ------------------
  |  Branch (8558:11): [True: 0, False: 0]
  ------------------
 8559|      0|        result += '?';
 8560|      0|        result += normalized;
 8561|      0|      }
 8562|      0|    } else {
 8563|      0|      result += '?';
 8564|      0|      result += query_part;
 8565|      0|    }
 8566|      0|  }
 8567|       |
 8568|  3.09k|  return result;
 8569|  3.09k|}
_ZN7httplib6detail11encode_pathERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
 5534|  3.09k|inline std::string encode_path(const std::string &s) {
 5535|  3.09k|  std::string result;
 5536|  3.09k|  result.reserve(s.size());
 5537|       |
 5538|  6.19k|  for (size_t i = 0; s[i]; i++) {
  ------------------
  |  Branch (5538:22): [True: 3.09k, False: 3.09k]
  ------------------
 5539|  3.09k|    switch (s[i]) {
 5540|      0|    case ' ': result += "%20"; break;
  ------------------
  |  Branch (5540:5): [True: 0, False: 3.09k]
  ------------------
 5541|      0|    case '+': result += "%2B"; break;
  ------------------
  |  Branch (5541:5): [True: 0, False: 3.09k]
  ------------------
 5542|      0|    case '\r': result += "%0D"; break;
  ------------------
  |  Branch (5542:5): [True: 0, False: 3.09k]
  ------------------
 5543|      0|    case '\n': result += "%0A"; break;
  ------------------
  |  Branch (5543:5): [True: 0, False: 3.09k]
  ------------------
 5544|      0|    case '\'': result += "%27"; break;
  ------------------
  |  Branch (5544:5): [True: 0, False: 3.09k]
  ------------------
 5545|      0|    case ',': result += "%2C"; break;
  ------------------
  |  Branch (5545:5): [True: 0, False: 3.09k]
  ------------------
 5546|       |    // case ':': result += "%3A"; break; // ok? probably...
 5547|      0|    case ';': result += "%3B"; break;
  ------------------
  |  Branch (5547:5): [True: 0, False: 3.09k]
  ------------------
 5548|  3.09k|    default:
  ------------------
  |  Branch (5548:5): [True: 3.09k, False: 0]
  ------------------
 5549|  3.09k|      auto c = static_cast<uint8_t>(s[i]);
 5550|  3.09k|      if (c >= 0x80) {
  ------------------
  |  Branch (5550:11): [True: 0, False: 3.09k]
  ------------------
 5551|      0|        result += '%';
 5552|      0|        char hex[4];
 5553|      0|        auto len = snprintf(hex, sizeof(hex) - 1, "%02X", c);
 5554|      0|        assert(len == 2);
  ------------------
  |  Branch (5554:9): [True: 0, False: 0]
  ------------------
 5555|      0|        result.append(hex, static_cast<size_t>(len));
 5556|  3.09k|      } else {
 5557|  3.09k|        result += s[i];
 5558|  3.09k|      }
 5559|  3.09k|      break;
 5560|  3.09k|    }
 5561|  3.09k|  }
 5562|       |
 5563|  3.09k|  return result;
 5564|  3.09k|}
_ZN7httplib6detail5splitEPKcS2_cNSt3__18functionIFvS2_S2_EEE:
 5762|  1.31k|                  std::function<void(const char *, const char *)> fn) {
 5763|  1.31k|  return split(b, e, d, (std::numeric_limits<size_t>::max)(), std::move(fn));
 5764|  1.31k|}
_ZN7httplib6detail5splitEPKcS2_cmNSt3__18functionIFvS2_S2_EEE:
 5767|  1.31k|                  std::function<void(const char *, const char *)> fn) {
 5768|  1.31k|  size_t i = 0;
 5769|  1.31k|  size_t beg = 0;
 5770|  1.31k|  size_t count = 1;
 5771|       |
 5772|   150k|  while (e ? (b + i < e) : (b[i] != '\0')) {
  ------------------
  |  Branch (5772:10): [True: 150k, False: 0]
  |  Branch (5772:10): [True: 149k, False: 1.31k]
  ------------------
 5773|   149k|    if (b[i] == d && count < m) {
  ------------------
  |  Branch (5773:9): [True: 17.2k, False: 132k]
  |  Branch (5773:22): [True: 17.2k, False: 0]
  ------------------
 5774|  17.2k|      auto r = trim(b, e, beg, i);
 5775|  17.2k|      if (r.first < r.second) { fn(&b[r.first], &b[r.second]); }
  ------------------
  |  Branch (5775:11): [True: 4.66k, False: 12.5k]
  ------------------
 5776|  17.2k|      beg = i + 1;
 5777|  17.2k|      count++;
 5778|  17.2k|    }
 5779|   149k|    i++;
 5780|   149k|  }
 5781|       |
 5782|  1.31k|  if (i) {
  ------------------
  |  Branch (5782:7): [True: 1.10k, False: 215]
  ------------------
 5783|  1.10k|    auto r = trim(b, e, beg, i);
 5784|  1.10k|    if (r.first < r.second) { fn(&b[r.first], &b[r.second]); }
  ------------------
  |  Branch (5784:9): [True: 962, False: 140]
  ------------------
 5785|  1.10k|  }
 5786|  1.31k|}
_ZN7httplib6detail4trimEPKcS2_mm:
 5718|  18.3k|                                      size_t right) {
 5719|  26.5k|  while (b + left < e && is_space_or_tab(b[left])) {
  ------------------
  |  Branch (5719:10): [True: 26.3k, False: 140]
  |  Branch (5719:26): [True: 8.23k, False: 18.1k]
  ------------------
 5720|  8.23k|    left++;
 5721|  8.23k|  }
 5722|  26.5k|  while (right > 0 && is_space_or_tab(b[right - 1])) {
  ------------------
  |  Branch (5722:10): [True: 26.4k, False: 110]
  |  Branch (5722:23): [True: 8.23k, False: 18.1k]
  ------------------
 5723|  8.23k|    right--;
 5724|  8.23k|  }
 5725|  18.3k|  return std::make_pair(left, right);
 5726|  18.3k|}
_ZN7httplib6detail15is_space_or_tabEc:
 5573|  77.4k|inline bool is_space_or_tab(char c) { return c == ' ' || c == '\t'; }
  ------------------
  |  Branch (5573:46): [True: 17.5k, False: 59.9k]
  |  Branch (5573:58): [True: 593, False: 59.3k]
  ------------------
_ZN7httplib6detail6is_hexEcRi:
 4924|  18.2k|inline bool is_hex(char c, int &v) {
 4925|  18.2k|  if (is_ascii_digit(c)) {
  ------------------
  |  Branch (4925:7): [True: 9.60k, False: 8.65k]
  ------------------
 4926|  9.60k|    v = c - '0';
 4927|  9.60k|    return true;
 4928|  9.60k|  } else if ('A' <= c && c <= 'F') {
  ------------------
  |  Branch (4928:14): [True: 3.80k, False: 4.84k]
  |  Branch (4928:26): [True: 946, False: 2.85k]
  ------------------
 4929|    946|    v = c - 'A' + 10;
 4930|    946|    return true;
 4931|  7.70k|  } else if ('a' <= c && c <= 'f') {
  ------------------
  |  Branch (4931:14): [True: 2.85k, False: 4.85k]
  |  Branch (4931:26): [True: 2.84k, False: 10]
  ------------------
 4932|  2.84k|    v = c - 'a' + 10;
 4933|  2.84k|    return true;
 4934|  2.84k|  }
 4935|  4.86k|  return false;
 4936|  18.2k|}
_ZNK7httplib6detail26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS2_8equal_toIS8_EEE5emptyEv:
 1115|  3.09k|  bool empty() const { return entries_.empty(); }
_ZN7httplib6detail18write_request_lineERNS_6StreamERKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEESB_:
 8147|  3.09k|                                  const std::string &path) {
 8148|       |  // A request target must not carry CR/LF (or other control octets); otherwise
 8149|       |  // a value smuggled into it splits the request line and injects headers or a
 8150|       |  // whole request. The same field-value check already guards header values in
 8151|       |  // check_and_write_headers and the request target in
 8152|       |  // perform_websocket_handshake; apply it here too.
 8153|  3.09k|  if (!fields::is_field_value(path)) { return -1; }
  ------------------
  |  Branch (8153:7): [True: 0, False: 3.09k]
  ------------------
 8154|       |
 8155|  3.09k|  std::string s = method;
 8156|  3.09k|  s += ' ';
 8157|  3.09k|  s += path;
 8158|  3.09k|  s += " HTTP/1.1\r\n";
 8159|  3.09k|  return strm.write(s.data(), s.size());
 8160|  3.09k|}
_ZN7httplib6detail23check_and_write_headersINSt3__18functionIFlRNS_6StreamERNS0_26insertion_ordered_multimapINS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEEEEEEEEbS5_SG_T_RNS_5ErrorE:
11864|  3.09k|                                    T header_writer, Error &error) {
11865|  14.1k|  for (const auto &h : headers) {
  ------------------
  |  Branch (11865:22): [True: 14.1k, False: 3.09k]
  ------------------
11866|  14.1k|    if (!detail::fields::is_field_valid(h.first, h.second)) {
  ------------------
  |  Branch (11866:9): [True: 0, False: 14.1k]
  ------------------
11867|      0|      error = Error::InvalidHeaders;
11868|      0|      return false;
11869|      0|    }
11870|  14.1k|  }
11871|  3.09k|  if (header_writer(strm, headers) <= 0) {
  ------------------
  |  Branch (11871:7): [True: 0, False: 3.09k]
  ------------------
11872|      0|    error = Error::Write;
11873|      0|    return false;
11874|      0|  }
11875|  3.09k|  return true;
11876|  3.09k|}
_ZNK7httplib6detail12BufferStream10get_bufferEv:
11540|  3.09k|inline const std::string &BufferStream::get_buffer() const { return buffer; }
_ZN7httplib6detail10write_dataERNS_6StreamEPKcm:
 8197|  3.09k|inline bool write_data(Stream &strm, const char *d, size_t l) {
 8198|  3.09k|  size_t offset = 0;
 8199|  6.19k|  while (offset < l) {
  ------------------
  |  Branch (8199:10): [True: 3.09k, False: 3.09k]
  ------------------
 8200|  3.09k|    auto length = strm.write(d + offset, l - offset);
 8201|  3.09k|    if (length < 0) { return false; }
  ------------------
  |  Branch (8201:9): [True: 0, False: 3.09k]
  ------------------
 8202|  3.09k|    offset += static_cast<size_t>(length);
 8203|  3.09k|  }
 8204|  3.09k|  return true;
 8205|  3.09k|}
_ZNK7httplib10ClientImpl18read_response_lineERNS_6StreamERKNS_7RequestERNS_8ResponseEb:
13849|  3.09k|                                           bool skip_100_continue) const {
13850|  3.09k|  std::array<char, 2048> buf{};
13851|       |
13852|  3.09k|  detail::stream_line_reader line_reader(strm, buf.data(), buf.size());
13853|       |
13854|  3.09k|  if (!line_reader.getline()) { return false; }
  ------------------
  |  Branch (13854:7): [True: 9, False: 3.08k]
  ------------------
13855|       |
13856|  3.08k|  if (!detail::parse_status_line(line_reader.ptr(), res.version, res.status,
  ------------------
  |  Branch (13856:7): [True: 231, False: 2.85k]
  ------------------
13857|  3.08k|                                 res.reason)) {
13858|    231|    return req.method == "CONNECT";
13859|    231|  }
13860|       |
13861|       |  // Ignore '100 Continue' (only when not using Expect: 100-continue explicitly)
13862|  8.39k|  while (skip_100_continue && res.status == StatusCode::Continue_100) {
  ------------------
  |  Branch (13862:10): [True: 8.39k, False: 0]
  |  Branch (13862:31): [True: 5.72k, False: 2.66k]
  ------------------
13863|  5.72k|    if (!line_reader.getline()) { return false; } // CRLF
  ------------------
  |  Branch (13863:9): [True: 52, False: 5.67k]
  ------------------
13864|  5.67k|    if (!line_reader.getline()) { return false; } // next response line
  ------------------
  |  Branch (13864:9): [True: 13, False: 5.66k]
  ------------------
13865|       |
13866|  5.66k|    if (!detail::parse_status_line(line_reader.ptr(), res.version, res.status,
  ------------------
  |  Branch (13866:9): [True: 127, False: 5.53k]
  ------------------
13867|  5.66k|                                   res.reason)) {
13868|    127|      return false;
13869|    127|    }
13870|  5.66k|  }
13871|       |
13872|  2.66k|  return true;
13873|  2.85k|}
_ZN7httplib6detail18stream_line_readerC2ERNS_6StreamEPcm:
 5826|  15.0k|    : strm_(strm), fixed_buffer_(fixed_buffer),
 5827|  15.0k|      fixed_buffer_size_(fixed_buffer_size) {}
_ZN7httplib6detail18stream_line_reader7getlineEv:
 5850|  39.5k|inline bool stream_line_reader::getline() {
 5851|  39.5k|  fixed_buffer_used_size_ = 0;
 5852|  39.5k|  growable_buffer_.clear();
 5853|       |
 5854|  39.5k|#ifndef CPPHTTPLIB_ALLOW_LF_AS_LINE_TERMINATOR
 5855|  39.5k|  char prev_byte = 0;
 5856|  39.5k|#endif
 5857|       |
 5858|  2.01M|  for (size_t i = 0;; i++) {
 5859|       |    // Fast path: whatever the stream has already buffered can be scanned for
 5860|       |    // the terminator in one pass. Asking for a byte at a time costs a virtual
 5861|       |    // call, a bounds check and a one-byte copy per character of the request.
 5862|  2.01M|    size_t buffered_size = 0;
 5863|  2.01M|    if (auto buffered = strm_.buffered_data(buffered_size)) {
  ------------------
  |  Branch (5863:14): [True: 0, False: 2.01M]
  ------------------
 5864|      0|      auto take = buffered_size;
 5865|      0|      auto terminated = false;
 5866|       |
 5867|      0|      for (size_t at = 0; at < buffered_size;) {
  ------------------
  |  Branch (5867:27): [True: 0, False: 0]
  ------------------
 5868|      0|        auto nl = static_cast<const char *>(
 5869|      0|            memchr(buffered + at, '\n', buffered_size - at));
 5870|      0|        if (!nl) { break; }
  ------------------
  |  Branch (5870:13): [True: 0, False: 0]
  ------------------
 5871|      0|        auto pos = static_cast<size_t>(nl - buffered);
 5872|       |#ifdef CPPHTTPLIB_ALLOW_LF_AS_LINE_TERMINATOR
 5873|       |        take = pos + 1;
 5874|       |        terminated = true;
 5875|       |        break;
 5876|       |#else
 5877|       |        // A bare LF does not end the line; keep looking for CRLF. The CR may
 5878|       |        // be the last byte of an earlier chunk, hence prev_byte.
 5879|      0|        if ((pos > 0 ? buffered[pos - 1] : prev_byte) == '\r') {
  ------------------
  |  Branch (5879:13): [True: 0, False: 0]
  |  Branch (5879:14): [True: 0, False: 0]
  ------------------
 5880|      0|          take = pos + 1;
 5881|      0|          terminated = true;
 5882|      0|          break;
 5883|      0|        }
 5884|      0|        at = pos + 1;
 5885|      0|#endif
 5886|      0|      }
 5887|       |
 5888|      0|      if (size() + take > CPPHTTPLIB_MAX_LINE_LENGTH) { return false; }
  ------------------
  |  |  189|      0|#define CPPHTTPLIB_MAX_LINE_LENGTH 32768
  ------------------
  |  Branch (5888:11): [True: 0, False: 0]
  ------------------
 5889|      0|#ifndef CPPHTTPLIB_ALLOW_LF_AS_LINE_TERMINATOR
 5890|      0|      prev_byte = buffered[take - 1];
 5891|      0|#endif
 5892|      0|      append(buffered, take);
 5893|      0|      strm_.consume_buffered(take);
 5894|      0|      i += take;
 5895|      0|      if (terminated) { return true; }
  ------------------
  |  Branch (5895:11): [True: 0, False: 0]
  ------------------
 5896|      0|      continue;
 5897|      0|    }
 5898|       |
 5899|  2.01M|    if (size() >= CPPHTTPLIB_MAX_LINE_LENGTH) {
  ------------------
  |  |  189|  2.01M|#define CPPHTTPLIB_MAX_LINE_LENGTH 32768
  ------------------
  |  Branch (5899:9): [True: 4, False: 2.01M]
  ------------------
 5900|       |      // Treat exceptionally long lines as an error to
 5901|       |      // prevent infinite loops/memory exhaustion
 5902|      4|      return false;
 5903|      4|    }
 5904|  2.01M|    char byte;
 5905|  2.01M|    auto n = strm_.read(&byte, 1);
 5906|       |
 5907|  2.01M|    if (n < 0) {
  ------------------
  |  Branch (5907:9): [True: 0, False: 2.01M]
  ------------------
 5908|      0|      return false;
 5909|  2.01M|    } else if (n == 0) {
  ------------------
  |  Branch (5909:16): [True: 1.36k, False: 2.01M]
  ------------------
 5910|  1.36k|      if (i == 0) {
  ------------------
  |  Branch (5910:11): [True: 478, False: 886]
  ------------------
 5911|    478|        return false;
 5912|    886|      } else {
 5913|    886|        break;
 5914|    886|      }
 5915|  1.36k|    }
 5916|       |
 5917|  2.01M|    append(byte);
 5918|       |
 5919|       |#ifdef CPPHTTPLIB_ALLOW_LF_AS_LINE_TERMINATOR
 5920|       |    if (byte == '\n') { break; }
 5921|       |#else
 5922|  2.01M|    if (prev_byte == '\r' && byte == '\n') { break; }
  ------------------
  |  Branch (5922:9): [True: 38.9k, False: 1.97M]
  |  Branch (5922:30): [True: 38.2k, False: 728]
  ------------------
 5923|  1.98M|    prev_byte = byte;
 5924|  1.98M|#endif
 5925|  1.98M|  }
 5926|       |
 5927|  39.0k|  return true;
 5928|  39.5k|}
_ZNK7httplib6detail18stream_line_reader4sizeEv:
 5837|  2.08M|inline size_t stream_line_reader::size() const {
 5838|  2.08M|  if (growable_buffer_.empty()) {
  ------------------
  |  Branch (5838:7): [True: 828k, False: 1.25M]
  ------------------
 5839|   828k|    return fixed_buffer_used_size_;
 5840|  1.25M|  } else {
 5841|  1.25M|    return growable_buffer_.size();
 5842|  1.25M|  }
 5843|  2.08M|}
_ZN7httplib6detail18stream_line_reader6appendEPKcm:
 5932|  2.01M|inline void stream_line_reader::append(const char *data, size_t size) {
 5933|       |  // Once the line has outgrown the fixed buffer everything must keep going to
 5934|       |  // the growable one, even if a later chunk would have fit. Without the
 5935|       |  // emptiness check a short append after a long one would land in the fixed
 5936|       |  // buffer, which ptr() and size() no longer look at, and be lost.
 5937|  2.01M|  if (growable_buffer_.empty() &&
  ------------------
  |  Branch (5937:7): [True: 765k, False: 1.25M]
  ------------------
 5938|   765k|      fixed_buffer_used_size_ + size < fixed_buffer_size_) {
  ------------------
  |  Branch (5938:7): [True: 764k, False: 1.02k]
  ------------------
 5939|   764k|    memcpy(fixed_buffer_ + fixed_buffer_used_size_, data, size);
 5940|   764k|    fixed_buffer_used_size_ += size;
 5941|   764k|    fixed_buffer_[fixed_buffer_used_size_] = '\0';
 5942|  1.25M|  } else {
 5943|       |    // Unlike the per-character overload, this can be the very first append of
 5944|       |    // the line, so the fixed buffer may hold nothing and carry no terminator
 5945|       |    // yet. assign() takes an explicit length and does not need one.
 5946|  1.25M|    if (growable_buffer_.empty()) {
  ------------------
  |  Branch (5946:9): [True: 1.02k, False: 1.25M]
  ------------------
 5947|  1.02k|      growable_buffer_.assign(fixed_buffer_, fixed_buffer_used_size_);
 5948|  1.02k|    }
 5949|  1.25M|    growable_buffer_.append(data, size);
 5950|  1.25M|  }
 5951|  2.01M|}
_ZN7httplib6detail18stream_line_reader6appendEc:
 5930|  2.01M|inline void stream_line_reader::append(char c) { append(&c, 1); }
_ZN7httplib6detail17parse_status_lineEPKcRNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEERiSA_:
 7801|  8.74k|                              int &status, std::string &reason) {
 7802|       |#ifdef CPPHTTPLIB_ALLOW_LF_AS_LINE_TERMINATOR
 7803|       |  thread_local const std::regex re("(HTTP/1\\.[01]) (\\d{3})(?: (.*?))?\r?\n");
 7804|       |#else
 7805|  8.74k|  thread_local const std::regex re("(HTTP/1\\.[01]) (\\d{3})(?: (.*?))?\r\n");
 7806|  8.74k|#endif
 7807|       |
 7808|  8.74k|  std::cmatch m;
 7809|  8.74k|  if (!std::regex_match(line, m, re)) { return false; }
  ------------------
  |  Branch (7809:7): [True: 358, False: 8.39k]
  ------------------
 7810|  8.39k|  version = std::string(m[1]);
 7811|  8.39k|  status = std::stoi(std::string(m[2]));
 7812|  8.39k|  reason = std::string(m[3]);
 7813|  8.39k|  return true;
 7814|  8.74k|}
_ZNK7httplib6detail18stream_line_reader3ptrEv:
 5829|  60.3k|inline const char *stream_line_reader::ptr() const {
 5830|  60.3k|  if (growable_buffer_.empty()) {
  ------------------
  |  Branch (5830:7): [True: 58.6k, False: 1.71k]
  ------------------
 5831|  58.6k|    return fixed_buffer_;
 5832|  58.6k|  } else {
 5833|  1.71k|    return growable_buffer_.data();
 5834|  1.71k|  }
 5835|  60.3k|}
_ZN7httplib10ClientImpl18write_request_bodyERNS_6StreamERNS_7RequestERNS_5ErrorE:
14812|  3.09k|                                           Error &error) {
14813|  3.09k|  if (req.body.empty()) {
  ------------------
  |  Branch (14813:7): [True: 3.09k, False: 0]
  ------------------
14814|  3.09k|    return write_content_with_provider(strm, req, error);
14815|  3.09k|  }
14816|       |
14817|      0|  if (req.upload_progress) {
  ------------------
  |  Branch (14817:7): [True: 0, False: 0]
  ------------------
14818|      0|    auto body_size = req.body.size();
14819|      0|    size_t written = 0;
14820|      0|    auto data = req.body.data();
14821|       |
14822|      0|    while (written < body_size) {
  ------------------
  |  Branch (14822:12): [True: 0, False: 0]
  ------------------
14823|      0|      size_t to_write = (std::min)(CPPHTTPLIB_SEND_BUFSIZ, body_size - written);
  ------------------
  |  |  154|      0|#define CPPHTTPLIB_SEND_BUFSIZ size_t(16384u)
  ------------------
14824|      0|      if (!detail::write_data(strm, data + written, to_write)) {
  ------------------
  |  Branch (14824:11): [True: 0, False: 0]
  ------------------
14825|      0|        error = Error::Write;
14826|      0|        output_error_log(error, &req);
14827|      0|        return false;
14828|      0|      }
14829|      0|      written += to_write;
14830|       |
14831|      0|      if (!req.upload_progress(written, body_size)) {
  ------------------
  |  Branch (14831:11): [True: 0, False: 0]
  ------------------
14832|      0|        error = Error::Canceled;
14833|      0|        output_error_log(error, &req);
14834|      0|        return false;
14835|      0|      }
14836|      0|    }
14837|      0|  } else {
14838|      0|    if (!detail::write_data(strm, req.body.data(), req.body.size())) {
  ------------------
  |  Branch (14838:9): [True: 0, False: 0]
  ------------------
14839|      0|      error = Error::Write;
14840|      0|      output_error_log(error, &req);
14841|      0|      return false;
14842|      0|    }
14843|      0|  }
14844|       |
14845|      0|  return true;
14846|      0|}
_ZNK7httplib10ClientImpl27write_content_with_providerERNS_6StreamERKNS_7RequestERNS_5ErrorE:
14628|  3.09k|                                                    Error &error) const {
14629|  3.09k|  auto is_shutting_down = []() { return false; };
14630|       |
14631|  3.09k|  if (req.is_chunked_content_provider_) {
  ------------------
  |  Branch (14631:7): [True: 0, False: 3.09k]
  ------------------
14632|      0|    auto compressor = compress_ ? detail::create_compressor().first
  ------------------
  |  Branch (14632:23): [True: 0, False: 0]
  ------------------
14633|      0|                                : std::unique_ptr<detail::compressor>();
14634|      0|    if (!compressor) {
  ------------------
  |  Branch (14634:9): [True: 0, False: 0]
  ------------------
14635|      0|      compressor = detail::make_unique<detail::nocompressor>();
14636|      0|    }
14637|       |
14638|      0|    return detail::write_content_chunked(strm, req.content_provider_,
14639|      0|                                         is_shutting_down, *compressor, error);
14640|  3.09k|  } else {
14641|  3.09k|    return detail::write_content_with_progress(
14642|  3.09k|        strm, req.content_provider_, 0, req.content_length_, is_shutting_down,
14643|  3.09k|        req.upload_progress, error);
14644|  3.09k|  }
14645|  3.09k|}
_ZN7httplib8DataSinkC2Ev:
 1403|  3.09k|  DataSink() : os(&sb_), sb_(*this) {}
_ZN7httplib8DataSink19data_sink_streambufC2ERS0_:
 1419|  3.09k|    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_:
 8213|  3.09k|                                        Error &error) {
 8214|  3.09k|  size_t end_offset = offset + length;
 8215|  3.09k|  size_t start_offset = offset;
 8216|  3.09k|  auto ok = true;
 8217|  3.09k|  DataSink data_sink;
 8218|       |
 8219|  3.09k|  data_sink.write = [&](const char *d, size_t l) -> bool {
 8220|  3.09k|    if (ok) {
 8221|  3.09k|      if (write_data(strm, d, l)) {
 8222|  3.09k|        offset += l;
 8223|       |
 8224|  3.09k|        if (upload_progress && length > 0) {
 8225|  3.09k|          size_t current_written = offset - start_offset;
 8226|  3.09k|          if (!upload_progress(current_written, length)) {
 8227|  3.09k|            ok = false;
 8228|  3.09k|            return false;
 8229|  3.09k|          }
 8230|  3.09k|        }
 8231|  3.09k|      } else {
 8232|  3.09k|        ok = false;
 8233|  3.09k|      }
 8234|  3.09k|    }
 8235|  3.09k|    return ok;
 8236|  3.09k|  };
 8237|       |
 8238|  3.09k|  data_sink.is_writable = [&]() -> bool { return strm.is_peer_alive(); };
 8239|       |
 8240|  3.09k|  while (offset < end_offset && !is_shutting_down()) {
  ------------------
  |  Branch (8240:10): [True: 0, False: 3.09k]
  |  Branch (8240:33): [True: 0, False: 0]
  ------------------
 8241|      0|    if (!strm.wait_writable() || !strm.is_peer_alive()) {
  ------------------
  |  Branch (8241:9): [True: 0, False: 0]
  |  Branch (8241:34): [True: 0, False: 0]
  ------------------
 8242|      0|      error = Error::Write;
 8243|      0|      return false;
 8244|      0|    } else if (!content_provider(offset, end_offset - offset, data_sink)) {
  ------------------
  |  Branch (8244:16): [True: 0, False: 0]
  ------------------
 8245|      0|      error = Error::Canceled;
 8246|      0|      return false;
 8247|      0|    } else if (!ok) {
  ------------------
  |  Branch (8247:16): [True: 0, False: 0]
  ------------------
 8248|      0|      error = Error::Write;
 8249|      0|      return false;
 8250|      0|    }
 8251|      0|  }
 8252|       |
 8253|  3.09k|  if (offset < end_offset) { // exited due to is_shutting_down(), not completion
  ------------------
  |  Branch (8253:7): [True: 0, False: 3.09k]
  ------------------
 8254|      0|    error = Error::Write;
 8255|      0|    return false;
 8256|      0|  }
 8257|       |
 8258|  3.09k|  error = Error::Success;
 8259|  3.09k|  return true;
 8260|  3.09k|}
_ZN7httplib6detail12read_headersERNS_6StreamERNS0_26insertion_ordered_multimapINSt3__112basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEENS0_11case_ignore8equal_toEEE:
 7744|  2.66k|inline bool read_headers(Stream &strm, Headers &headers) {
 7745|  2.66k|  const auto bufsiz = 2048;
 7746|  2.66k|  char buf[bufsiz];
 7747|  2.66k|  stream_line_reader line_reader(strm, buf, bufsiz);
 7748|       |
 7749|  2.66k|  size_t header_count = 0;
 7750|       |
 7751|  12.2k|  for (;;) {
 7752|  12.2k|    if (!line_reader.getline()) { return false; }
  ------------------
  |  Branch (7752:9): [True: 316, False: 11.9k]
  ------------------
 7753|       |
 7754|       |    // Check if the line ends with CRLF.
 7755|  11.9k|    auto line_terminator_len = 2;
 7756|  11.9k|    if (line_reader.end_with_crlf()) {
  ------------------
  |  Branch (7756:9): [True: 11.8k, False: 73]
  ------------------
 7757|       |      // Blank line indicates end of headers.
 7758|  11.8k|      if (line_reader.size() == 2) { break; }
  ------------------
  |  Branch (7758:11): [True: 1.99k, False: 9.90k]
  ------------------
 7759|  11.8k|    } else {
 7760|       |#ifdef CPPHTTPLIB_ALLOW_LF_AS_LINE_TERMINATOR
 7761|       |      // Blank line indicates end of headers.
 7762|       |      if (line_reader.size() == 1) { break; }
 7763|       |      line_terminator_len = 1;
 7764|       |#else
 7765|     73|      continue; // Skip invalid line.
 7766|     73|#endif
 7767|     73|    }
 7768|       |
 7769|  9.90k|    if (line_reader.size() > CPPHTTPLIB_HEADER_MAX_LENGTH) { return false; }
  ------------------
  |  |  114|  9.90k|#define CPPHTTPLIB_HEADER_MAX_LENGTH 8192
  ------------------
  |  Branch (7769:9): [True: 4, False: 9.90k]
  ------------------
 7770|       |
 7771|       |    // Check header count limit
 7772|  9.90k|    if (header_count >= CPPHTTPLIB_HEADER_MAX_COUNT) { return false; }
  ------------------
  |  |  118|  9.90k|#define CPPHTTPLIB_HEADER_MAX_COUNT 100
  ------------------
  |  Branch (7772:9): [True: 1, False: 9.90k]
  ------------------
 7773|       |
 7774|       |    // Exclude line terminator
 7775|  9.90k|    auto end = line_reader.ptr() + line_reader.size() - line_terminator_len;
 7776|       |
 7777|  9.90k|    if (!parse_header(line_reader.ptr(), end,
  ------------------
  |  Branch (7777:9): [True: 353, False: 9.54k]
  ------------------
 7778|  9.90k|                      [&](const std::string &key, const std::string &val) {
 7779|  9.90k|                        headers.emplace(key, val);
 7780|  9.90k|                      })) {
 7781|    353|      return false;
 7782|    353|    }
 7783|       |
 7784|  9.54k|    header_count++;
 7785|  9.54k|  }
 7786|       |
 7787|       |  // RFC 9110 Section 8.6: Reject requests with multiple Content-Length
 7788|       |  // headers that have different values to prevent request smuggling.
 7789|  1.99k|  auto cl_range = headers.equal_range("Content-Length");
 7790|  1.99k|  if (cl_range.first != cl_range.second) {
  ------------------
  |  Branch (7790:7): [True: 774, False: 1.21k]
  ------------------
 7791|    774|    const auto &first_val = cl_range.first->second;
 7792|  1.47k|    for (auto it = std::next(cl_range.first); it != cl_range.second; ++it) {
  ------------------
  |  Branch (7792:47): [True: 870, False: 604]
  ------------------
 7793|    870|      if (it->second != first_val) { return false; }
  ------------------
  |  Branch (7793:11): [True: 170, False: 700]
  ------------------
 7794|    870|    }
 7795|    774|  }
 7796|       |
 7797|  1.82k|  return true;
 7798|  1.99k|}
_ZNK7httplib6detail18stream_line_reader13end_with_crlfEv:
 5845|  11.9k|inline bool stream_line_reader::end_with_crlf() const {
 5846|  11.9k|  auto end = ptr() + size();
 5847|  11.9k|  return size() >= 2 && end[-2] == '\r' && end[-1] == '\n';
  ------------------
  |  Branch (5847:10): [True: 11.9k, False: 31]
  |  Branch (5847:25): [True: 11.9k, False: 25]
  |  Branch (5847:44): [True: 11.8k, False: 17]
  ------------------
 5848|  11.9k|}
_ZN7httplib6detail12parse_headerIZNS0_12read_headersERNS_6StreamERNS0_26insertion_ordered_multimapINSt3__112basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEENS0_11case_ignore8equal_toEEEEUlRKSB_SH_E_EEbPKcSK_T_:
 5579|  9.90k|inline bool parse_header(const char *beg, const char *end, T fn) {
 5580|       |  // Skip trailing spaces and tabs.
 5581|  10.1k|  while (beg < end && is_space_or_tab(end[-1])) {
  ------------------
  |  Branch (5581:10): [True: 10.1k, False: 14]
  |  Branch (5581:23): [True: 296, False: 9.88k]
  ------------------
 5582|    296|    end--;
 5583|    296|  }
 5584|       |
 5585|  9.90k|  auto p = beg;
 5586|   159k|  while (p < end && *p != ':') {
  ------------------
  |  Branch (5586:10): [True: 158k, False: 287]
  |  Branch (5586:21): [True: 149k, False: 9.61k]
  ------------------
 5587|   149k|    p++;
 5588|   149k|  }
 5589|       |
 5590|  9.90k|  auto name = std::string(beg, p);
 5591|  9.90k|  if (!detail::fields::is_field_name(name)) { return false; }
  ------------------
  |  Branch (5591:7): [True: 127, False: 9.77k]
  ------------------
 5592|       |
 5593|  9.77k|  if (p == end) { return false; }
  ------------------
  |  Branch (5593:7): [True: 183, False: 9.59k]
  ------------------
 5594|       |
 5595|  9.59k|  auto key_end = p;
 5596|       |
 5597|  9.59k|  if (*p++ != ':') { return false; }
  ------------------
  |  Branch (5597:7): [True: 0, False: 9.59k]
  ------------------
 5598|       |
 5599|  9.97k|  while (p < end && is_space_or_tab(*p)) {
  ------------------
  |  Branch (5599:10): [True: 3.50k, False: 6.46k]
  |  Branch (5599:21): [True: 380, False: 3.12k]
  ------------------
 5600|    380|    p++;
 5601|    380|  }
 5602|       |
 5603|  9.59k|  if (p <= end) {
  ------------------
  |  Branch (5603:7): [True: 9.59k, False: 0]
  ------------------
 5604|  9.59k|    auto key_len = key_end - beg;
 5605|  9.59k|    if (!key_len) { return false; }
  ------------------
  |  Branch (5605:9): [True: 0, False: 9.59k]
  ------------------
 5606|       |
 5607|  9.59k|    auto key = std::string(beg, key_end);
 5608|  9.59k|    auto val = std::string(p, end);
 5609|       |
 5610|  9.59k|    if (!detail::fields::is_field_value(val)) { return false; }
  ------------------
  |  Branch (5610:9): [True: 43, False: 9.54k]
  ------------------
 5611|       |
 5612|       |    // RFC 9110 §5.5: header field values are opaque octets and MUST NOT be
 5613|       |    // percent-decoded by the recipient. Applications that need to interpret a
 5614|       |    // value as a URI component should call httplib::decode_uri_component()
 5615|       |    // (or decode_path_component()) explicitly.
 5616|  9.54k|    fn(key, val);
 5617|       |
 5618|  9.54k|    return true;
 5619|  9.59k|  }
 5620|       |
 5621|      0|  return false;
 5622|  9.59k|}
_ZZN7httplib6detail12read_headersERNS_6StreamERNS0_26insertion_ordered_multimapINSt3__112basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEENS0_11case_ignore8equal_toEEEENKUlRKSA_SG_E_clESG_SG_:
 7778|  9.54k|                      [&](const std::string &key, const std::string &val) {
 7779|  9.54k|                        headers.emplace(key, val);
 7780|  9.54k|                      })) {
_ZN7httplib6detail26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEE11equal_rangeERKS8_:
 1160|  1.99k|  std::pair<iterator, iterator> equal_range(const std::string &key) {
 1161|  1.99k|    auto i = index_of(key);
 1162|  1.99k|    return i == npos() ? std::make_pair(end(), end())
  ------------------
  |  Branch (1162:12): [True: 1.21k, False: 774]
  ------------------
 1163|  1.99k|                       : std::make_pair(make_iter(i, i), end());
 1164|  1.99k|  }
_ZNK7httplib6detail26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEE10iterator_tINS2_4pairIS8_S8_EEEptEv:
 1033|  1.64k|    pointer operator->() const { return data_ + idx_; }
_ZNK7httplib10ClientImpl16output_error_logERKNS_5ErrorEPKNS_7RequestE:
14977|  2.59k|                                         const Request *req) const {
14978|  2.59k|  if (error_logger_) {
  ------------------
  |  Branch (14978:7): [True: 0, False: 2.59k]
  ------------------
14979|      0|    std::lock_guard<std::mutex> guard(logger_mutex_);
14980|      0|    error_logger_(err, req);
14981|      0|  }
14982|  2.59k|}
_ZZN7httplib10ClientImpl15process_requestERNS_6StreamERNS_7RequestERNS_8ResponseEbRNS_5ErrorEENKUlPKcmmmE0_clESA_mmm:
15102|   132k|                      size_t /*len*/) {
15103|   132k|                    assert(res.body.size() + n <= res.body.max_size());
  ------------------
  |  Branch (15103:21): [True: 132k, False: 0]
  ------------------
15104|   132k|                    if (payload_max_length_ > 0 &&
  ------------------
  |  Branch (15104:25): [True: 132k, False: 0]
  ------------------
15105|   132k|                        (res.body.size() >= payload_max_length_ ||
  ------------------
  |  Branch (15105:26): [True: 0, False: 132k]
  ------------------
15106|   132k|                         n > payload_max_length_ - res.body.size())) {
  ------------------
  |  Branch (15106:26): [True: 0, False: 132k]
  ------------------
15107|      0|                      return false;
15108|      0|                    }
15109|   132k|                    res.body.append(buf, n);
15110|   132k|                    return true;
15111|   132k|                  });
_ZNK7httplib8Response10has_headerERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
10978|  1.80k|inline bool Response::has_header(const std::string &key) const {
10979|  1.80k|  return headers.find(key) != headers.end();
10980|  1.80k|}
_ZNK7httplib8Response20get_header_value_u64ERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEmm:
10974|    602|                                             size_t id) const {
10975|    602|  return detail::get_header_value_u64(headers, key, def, id);
10976|    602|}
_ZN7httplib6detail20get_header_value_u64ERKNS0_26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEEERKS8_mm:
 3296|    602|                                   size_t id) {
 3297|    602|  auto dummy = false;
 3298|    602|  return get_header_value_u64(headers, key, def, id, dummy);
 3299|    602|}
_ZN7httplib6detail20get_header_value_u64ERKNS0_26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEEERKS8_mmRb:
 3268|  1.13k|                                   size_t id, bool &is_invalid_value) {
 3269|  1.13k|  is_invalid_value = false;
 3270|  1.13k|  auto rng = headers.equal_range(key);
 3271|  1.13k|  auto it = rng.first;
 3272|  1.13k|  std::advance(it, static_cast<ssize_t>(id));
 3273|  1.13k|  if (it != rng.second) {
  ------------------
  |  Branch (3273:7): [True: 1.13k, False: 0]
  ------------------
 3274|  1.13k|    if (is_numeric(it->second)) {
  ------------------
  |  Branch (3274:9): [True: 994, False: 139]
  ------------------
 3275|       |      // Parse at size_t width so an out-of-range Content-Length is reported
 3276|       |      // rather than silently saturated/truncated (a value above 2^32 would
 3277|       |      // otherwise wrap to a small framing length on 32-bit builds). Flag it
 3278|       |      // and return SIZE_MAX so the existing oversized-value guards reject it.
 3279|    994|      size_t val = 0;
 3280|    994|      const auto &s = it->second;
 3281|    994|      auto r = from_chars(s.data(), s.data() + s.size(), val);
 3282|    994|      if (r.ec == std::errc::result_out_of_range) {
  ------------------
  |  Branch (3282:11): [True: 63, False: 931]
  ------------------
 3283|     63|        is_invalid_value = true;
 3284|     63|        return (std::numeric_limits<size_t>::max)();
 3285|     63|      }
 3286|    931|      return val;
 3287|    994|    } else {
 3288|    139|      is_invalid_value = true;
 3289|    139|    }
 3290|  1.13k|  }
 3291|    139|  return def;
 3292|  1.13k|}
_ZN7httplib6detail10is_numericERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
 3262|  1.13k|inline bool is_numeric(const std::string &str) {
 3263|  1.13k|  return !str.empty() && std::all_of(str.cbegin(), str.cend(), is_ascii_digit);
  ------------------
  |  Branch (3263:10): [True: 1.00k, False: 128]
  |  Branch (3263:26): [True: 994, False: 11]
  ------------------
 3264|  1.13k|}
_ZN7httplib6detail10from_charsImEENS0_17from_chars_resultIT_EEPKcS6_RS3_i:
  678|    994|                                       T &value, int base = 10) {
  679|    994|  value = 0;
  680|    994|  const char *p = first;
  681|    994|  bool negative = false;
  682|       |
  683|    994|  if (p != last && *p == '-') {
  ------------------
  |  Branch (683:7): [True: 994, False: 0]
  |  Branch (683:20): [True: 0, False: 994]
  ------------------
  684|      0|    negative = true;
  685|      0|    ++p;
  686|      0|  }
  687|    994|  if (p == last) { return {first, std::errc::invalid_argument}; }
  ------------------
  |  Branch (687:7): [True: 0, False: 994]
  ------------------
  688|       |
  689|    994|  T result = 0;
  690|  14.4k|  for (; p != last; ++p) {
  ------------------
  |  Branch (690:10): [True: 13.5k, False: 931]
  ------------------
  691|  13.5k|    char c = *p;
  692|  13.5k|    int digit = -1;
  693|  13.5k|    if (is_ascii_digit(c)) {
  ------------------
  |  Branch (693:9): [True: 13.5k, False: 0]
  ------------------
  694|  13.5k|      digit = c - '0';
  695|  13.5k|    } else if ('a' <= c && c <= 'z') {
  ------------------
  |  Branch (695:16): [True: 0, False: 0]
  |  Branch (695:28): [True: 0, False: 0]
  ------------------
  696|      0|      digit = c - 'a' + 10;
  697|      0|    } else if ('A' <= c && c <= 'Z') {
  ------------------
  |  Branch (697:16): [True: 0, False: 0]
  |  Branch (697:28): [True: 0, False: 0]
  ------------------
  698|      0|      digit = c - 'A' + 10;
  699|      0|    } else {
  700|      0|      break;
  701|      0|    }
  702|       |
  703|  13.5k|    if (digit < 0 || digit >= base) { break; }
  ------------------
  |  Branch (703:9): [True: 0, False: 13.5k]
  |  Branch (703:22): [True: 0, False: 13.5k]
  ------------------
  704|  13.5k|    if (result > ((std::numeric_limits<T>::max)() - digit) / base) {
  ------------------
  |  Branch (704:9): [True: 63, False: 13.5k]
  ------------------
  705|     63|      return {p, std::errc::result_out_of_range};
  706|     63|    }
  707|  13.5k|    result = result * base + digit;
  708|  13.5k|  }
  709|       |
  710|    931|  if (p == first || (negative && p == first + 1)) {
  ------------------
  |  Branch (710:7): [True: 0, False: 931]
  |  Branch (710:22): [True: 0, False: 931]
  |  Branch (710:34): [True: 0, False: 0]
  ------------------
  711|      0|    return {first, std::errc::invalid_argument};
  712|      0|  }
  713|       |
  714|    931|  value = negative ? T(0) - result : result;
  ------------------
  |  Branch (714:11): [True: 0, False: 931]
  ------------------
  715|    931|  return {p, std::errc{}};
  716|    931|}
_ZN7httplib6detail12read_contentINS_8ResponseEEEbRNS_6StreamERT_mRiNSt3__18functionIFbmmEEENS9_IFbPKcmmmEEEb:
 8089|  1.73k|                  ContentReceiverWithProgress receiver, bool decompress) {
 8090|  1.73k|  bool exceed_payload_max_length = false;
 8091|  1.73k|  return prepare_content_receiver(
 8092|  1.73k|      x, status, std::move(receiver), decompress, payload_max_length,
 8093|  1.73k|      exceed_payload_max_length, [&](const ContentReceiverWithProgress &out) {
 8094|  1.73k|        auto ret = true;
 8095|       |        // Note: exceed_payload_max_length may also be set by the decompressor
 8096|       |        // wrapper in prepare_content_receiver when the decompressed payload
 8097|       |        // size exceeds the limit.
 8098|       |
 8099|  1.73k|        if (is_chunked_transfer_encoding(x.headers)) {
 8100|  1.73k|          auto result = read_content_chunked(strm, x, payload_max_length, out);
 8101|  1.73k|          if (result == ReadContentResult::Success) {
 8102|  1.73k|            ret = true;
 8103|  1.73k|          } else if (result == ReadContentResult::PayloadTooLarge) {
 8104|  1.73k|            exceed_payload_max_length = true;
 8105|  1.73k|            ret = false;
 8106|  1.73k|          } else {
 8107|  1.73k|            ret = false;
 8108|  1.73k|          }
 8109|  1.73k|        } else if (!has_header(x.headers, "Content-Length")) {
 8110|  1.73k|          auto result =
 8111|  1.73k|              read_content_without_length(strm, payload_max_length, out);
 8112|  1.73k|          if (result == ReadContentResult::Success) {
 8113|  1.73k|            ret = true;
 8114|  1.73k|          } else if (result == ReadContentResult::PayloadTooLarge) {
 8115|  1.73k|            exceed_payload_max_length = true;
 8116|  1.73k|            ret = false;
 8117|  1.73k|          } else {
 8118|  1.73k|            ret = false;
 8119|  1.73k|          }
 8120|  1.73k|        } else {
 8121|  1.73k|          auto is_invalid_value = false;
 8122|  1.73k|          auto len = get_header_value_u64(x.headers, "Content-Length",
 8123|  1.73k|                                          (std::numeric_limits<size_t>::max)(),
 8124|  1.73k|                                          0, is_invalid_value);
 8125|       |
 8126|  1.73k|          if (is_invalid_value) {
 8127|  1.73k|            ret = false;
 8128|  1.73k|          } else if (len > 0) {
 8129|  1.73k|            auto result = read_content_with_length(
 8130|  1.73k|                strm, len, std::move(progress), out, payload_max_length);
 8131|  1.73k|            ret = (result == ReadContentResult::Success);
 8132|  1.73k|            if (result == ReadContentResult::PayloadTooLarge) {
 8133|  1.73k|              exceed_payload_max_length = true;
 8134|  1.73k|            }
 8135|  1.73k|          }
 8136|  1.73k|        }
 8137|       |
 8138|  1.73k|        if (!ret) {
 8139|  1.73k|          status = exceed_payload_max_length ? StatusCode::PayloadTooLarge_413
 8140|  1.73k|                                             : StatusCode::BadRequest_400;
 8141|  1.73k|        }
 8142|  1.73k|        return ret;
 8143|  1.73k|      });
 8144|  1.73k|}
_ZN7httplib6detail24prepare_content_receiverINS_8ResponseEZNS0_12read_contentIS2_EEbRNS_6StreamERT_mRiNSt3__18functionIFbmmEEENSA_IFbPKcmmmEEEbEUlRKSG_E_EEbS7_S8_SG_bmRbT0_:
 8035|  1.73k|                              bool &exceed_payload_max_length, U callback) {
 8036|  1.73k|  if (decompress) {
  ------------------
  |  Branch (8036:7): [True: 1.73k, False: 0]
  ------------------
 8037|  1.73k|    std::string encoding = x.get_header_value("Content-Encoding");
 8038|  1.73k|    std::unique_ptr<decompressor> decompressor;
 8039|       |
 8040|  1.73k|    if (!encoding.empty()) {
  ------------------
  |  Branch (8040:9): [True: 203, False: 1.53k]
  ------------------
 8041|       |      // A coding we know about but were not built with is an error. An
 8042|       |      // unrecognized coding (including "identity") is left alone and the
 8043|       |      // payload is passed through as-is, since some servers misuse the header,
 8044|       |      // e.g. by sending a character set such as "Content-Encoding: UTF-8".
 8045|    203|      decompressor = detail::create_decompressor(encoding);
 8046|    203|      if (!decompressor && detail::is_known_content_encoding(encoding)) {
  ------------------
  |  Branch (8046:11): [True: 68, False: 135]
  |  Branch (8046:28): [True: 13, False: 55]
  ------------------
 8047|     13|        status = StatusCode::UnsupportedMediaType_415;
 8048|     13|        return false;
 8049|     13|      }
 8050|    203|    }
 8051|       |
 8052|  1.72k|    if (decompressor) {
  ------------------
  |  Branch (8052:9): [True: 135, False: 1.58k]
  ------------------
 8053|    135|      if (decompressor->is_valid()) {
  ------------------
  |  Branch (8053:11): [True: 135, False: 0]
  ------------------
 8054|    135|        size_t decompressed_size = 0;
 8055|    135|        ContentReceiverWithProgress out = [&](const char *buf, size_t n,
 8056|    135|                                              size_t off, size_t len) {
 8057|    135|          return decompressor->decompress(
 8058|    135|              buf, n, [&](const char *buf2, size_t n2) {
 8059|       |                // Guard against zip-bomb: check
 8060|       |                // decompressed size against limit.
 8061|    135|                if (payload_max_length > 0 &&
 8062|    135|                    (decompressed_size >= payload_max_length ||
 8063|    135|                     n2 > payload_max_length - decompressed_size)) {
 8064|    135|                  exceed_payload_max_length = true;
 8065|    135|                  return false;
 8066|    135|                }
 8067|    135|                decompressed_size += n2;
 8068|    135|                return receiver(buf2, n2, off, len);
 8069|    135|              });
 8070|    135|        };
 8071|    135|        return callback(std::move(out));
 8072|    135|      } else {
 8073|      0|        status = StatusCode::InternalServerError_500;
 8074|      0|        return false;
 8075|      0|      }
 8076|    135|    }
 8077|  1.72k|  }
 8078|       |
 8079|  1.58k|  ContentReceiverWithProgress out = [&](const char *buf, size_t n, size_t off,
 8080|  1.58k|                                        size_t len) {
 8081|  1.58k|    return receiver(buf, n, off, len);
 8082|  1.58k|  };
 8083|  1.58k|  return callback(std::move(out));
 8084|  1.73k|}
_ZNK7httplib8Response16get_header_valueERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEPKcm:
10984|  1.73k|                                              size_t id) const {
10985|  1.73k|  return detail::get_header_value(headers, key, def, id);
10986|  1.73k|}
_ZN7httplib6detail19create_decompressorERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
 7653|    203|create_decompressor(const std::string &encoding) {
 7654|    203|  std::unique_ptr<decompressor> decompressor;
 7655|       |
 7656|    203|  if (is_zlib_encoding(encoding)) {
  ------------------
  |  Branch (7656:7): [True: 135, False: 68]
  ------------------
 7657|    135|#ifdef CPPHTTPLIB_ZLIB_SUPPORT
 7658|    135|    decompressor = detail::make_unique<gzip_decompressor>();
 7659|    135|#endif
 7660|    135|  } else if (is_brotli_encoding(encoding)) {
  ------------------
  |  Branch (7660:14): [True: 2, False: 66]
  ------------------
 7661|       |#ifdef CPPHTTPLIB_BROTLI_SUPPORT
 7662|       |    decompressor = detail::make_unique<brotli_decompressor>();
 7663|       |#endif
 7664|     66|  } else if (is_zstd_encoding(encoding)) {
  ------------------
  |  Branch (7664:14): [True: 11, False: 55]
  ------------------
 7665|       |#ifdef CPPHTTPLIB_ZSTD_SUPPORT
 7666|       |    decompressor = detail::make_unique<zstd_decompressor>();
 7667|       |#endif
 7668|     11|  }
 7669|       |
 7670|    203|  return decompressor;
 7671|    203|}
_ZN7httplib6detail16is_zlib_encodingERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
 7632|    271|inline bool is_zlib_encoding(const std::string &encoding) {
 7633|    271|  return case_ignore::equal(encoding, "gzip") ||
  ------------------
  |  Branch (7633:10): [True: 19, False: 252]
  ------------------
 7634|    252|         case_ignore::equal(encoding, "deflate");
  ------------------
  |  Branch (7634:10): [True: 116, False: 136]
  ------------------
 7635|    271|}
_ZN7httplib6detail11make_uniqueINS0_17gzip_decompressorEJEEENSt3__19enable_ifIXntsr3std8is_arrayIT_EE5valueENS3_10unique_ptrIS5_NS3_14default_deleteIS5_EEEEE4typeEDpOT0_:
  546|    135|make_unique(Args &&...args) {
  547|    135|  return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
  548|    135|}
_ZN7httplib6detail17gzip_decompressorC2Ev:
 7420|    135|inline gzip_decompressor::gzip_decompressor() {
 7421|    135|  std::memset(&strm_, 0, sizeof(strm_));
 7422|    135|  strm_.zalloc = Z_NULL;
 7423|    135|  strm_.zfree = Z_NULL;
 7424|    135|  strm_.opaque = Z_NULL;
 7425|       |
 7426|       |  // 15 is the value of wbits, which should be at the maximum possible value
 7427|       |  // to ensure that any gzip stream can be decoded. The offset of 32 specifies
 7428|       |  // that the stream type should be automatically detected either gzip or
 7429|       |  // deflate.
 7430|    135|  is_valid_ = inflateInit2(&strm_, 32 + 15) == Z_OK;
 7431|    135|}
_ZN7httplib6detail18is_brotli_encodingERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
 7637|    136|inline bool is_brotli_encoding(const std::string &encoding) {
 7638|    136|  return contains_case_ignore(encoding, "br");
 7639|    136|}
_ZN7httplib6detail20contains_case_ignoreERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEPKc:
 7622|    268|inline bool contains_case_ignore(const std::string &s, const char *token) {
 7623|    268|  auto token_end = token + std::strlen(token);
 7624|    268|  return std::search(s.begin(), s.end(), token, token_end, [](char a, char b) {
 7625|    268|           return case_ignore::to_lower(a) == case_ignore::to_lower(b);
 7626|    268|         }) != s.end();
 7627|    268|}
_ZZN7httplib6detail20contains_case_ignoreERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEPKcENKUlccE_clEcc:
 7624|  97.8k|  return std::search(s.begin(), s.end(), token, token_end, [](char a, char b) {
 7625|  97.8k|           return case_ignore::to_lower(a) == case_ignore::to_lower(b);
 7626|  97.8k|         }) != s.end();
_ZN7httplib6detail16is_zstd_encodingERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
 7641|    132|inline bool is_zstd_encoding(const std::string &encoding) {
 7642|    132|  return contains_case_ignore(encoding, "zstd");
 7643|    132|}
_ZN7httplib6detail25is_known_content_encodingERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
 7647|     68|inline bool is_known_content_encoding(const std::string &encoding) {
 7648|     68|  return is_zlib_encoding(encoding) || is_brotli_encoding(encoding) ||
  ------------------
  |  Branch (7648:10): [True: 0, False: 68]
  |  Branch (7648:40): [True: 2, False: 66]
  ------------------
 7649|     66|         is_zstd_encoding(encoding);
  ------------------
  |  Branch (7649:10): [True: 11, False: 55]
  ------------------
 7650|     68|}
_ZZN7httplib6detail24prepare_content_receiverINS_8ResponseEZNS0_12read_contentIS2_EEbRNS_6StreamERT_mRiNSt3__18functionIFbmmEEENSA_IFbPKcmmmEEEbEUlRKSG_E_EEbS7_S8_SG_bmRbT0_ENKUlSE_mmmE_clESE_mmm:
 8056|  1.94k|                                              size_t off, size_t len) {
 8057|  1.94k|          return decompressor->decompress(
 8058|  1.94k|              buf, n, [&](const char *buf2, size_t n2) {
 8059|       |                // Guard against zip-bomb: check
 8060|       |                // decompressed size against limit.
 8061|  1.94k|                if (payload_max_length > 0 &&
 8062|  1.94k|                    (decompressed_size >= payload_max_length ||
 8063|  1.94k|                     n2 > payload_max_length - decompressed_size)) {
 8064|  1.94k|                  exceed_payload_max_length = true;
 8065|  1.94k|                  return false;
 8066|  1.94k|                }
 8067|  1.94k|                decompressed_size += n2;
 8068|  1.94k|                return receiver(buf2, n2, off, len);
 8069|  1.94k|              });
 8070|  1.94k|        };
_ZZZN7httplib6detail24prepare_content_receiverINS_8ResponseEZNS0_12read_contentIS2_EEbRNS_6StreamERT_mRiNSt3__18functionIFbmmEEENSA_IFbPKcmmmEEEbEUlRKSG_E_EEbS7_S8_SG_bmRbT0_ENKUlSE_mmmE_clESE_mmmENKUlSE_mE_clESE_m:
 8058|   127k|              buf, n, [&](const char *buf2, size_t n2) {
 8059|       |                // Guard against zip-bomb: check
 8060|       |                // decompressed size against limit.
 8061|   127k|                if (payload_max_length > 0 &&
  ------------------
  |  Branch (8061:21): [True: 127k, False: 0]
  ------------------
 8062|   127k|                    (decompressed_size >= payload_max_length ||
  ------------------
  |  Branch (8062:22): [True: 1, False: 127k]
  ------------------
 8063|   127k|                     n2 > payload_max_length - decompressed_size)) {
  ------------------
  |  Branch (8063:22): [True: 14, False: 127k]
  ------------------
 8064|     15|                  exceed_payload_max_length = true;
 8065|     15|                  return false;
 8066|     15|                }
 8067|   127k|                decompressed_size += n2;
 8068|   127k|                return receiver(buf2, n2, off, len);
 8069|   127k|              });
_ZZN7httplib6detail12read_contentINS_8ResponseEEEbRNS_6StreamERT_mRiNSt3__18functionIFbmmEEENS9_IFbPKcmmmEEEbENKUlRKSF_E_clESH_:
 8093|  1.72k|      exceed_payload_max_length, [&](const ContentReceiverWithProgress &out) {
 8094|  1.72k|        auto ret = true;
 8095|       |        // Note: exceed_payload_max_length may also be set by the decompressor
 8096|       |        // wrapper in prepare_content_receiver when the decompressed payload
 8097|       |        // size exceeds the limit.
 8098|       |
 8099|  1.72k|        if (is_chunked_transfer_encoding(x.headers)) {
  ------------------
  |  Branch (8099:13): [True: 685, False: 1.03k]
  ------------------
 8100|    685|          auto result = read_content_chunked(strm, x, payload_max_length, out);
 8101|    685|          if (result == ReadContentResult::Success) {
  ------------------
  |  Branch (8101:15): [True: 1, False: 684]
  ------------------
 8102|      1|            ret = true;
 8103|    684|          } else if (result == ReadContentResult::PayloadTooLarge) {
  ------------------
  |  Branch (8103:22): [True: 0, False: 684]
  ------------------
 8104|      0|            exceed_payload_max_length = true;
 8105|      0|            ret = false;
 8106|    684|          } else {
 8107|    684|            ret = false;
 8108|    684|          }
 8109|  1.03k|        } else if (!has_header(x.headers, "Content-Length")) {
  ------------------
  |  Branch (8109:20): [True: 506, False: 531]
  ------------------
 8110|    506|          auto result =
 8111|    506|              read_content_without_length(strm, payload_max_length, out);
 8112|    506|          if (result == ReadContentResult::Success) {
  ------------------
  |  Branch (8112:15): [True: 475, False: 31]
  ------------------
 8113|    475|            ret = true;
 8114|    475|          } else if (result == ReadContentResult::PayloadTooLarge) {
  ------------------
  |  Branch (8114:22): [True: 0, False: 31]
  ------------------
 8115|      0|            exceed_payload_max_length = true;
 8116|      0|            ret = false;
 8117|     31|          } else {
 8118|     31|            ret = false;
 8119|     31|          }
 8120|    531|        } else {
 8121|    531|          auto is_invalid_value = false;
 8122|    531|          auto len = get_header_value_u64(x.headers, "Content-Length",
 8123|    531|                                          (std::numeric_limits<size_t>::max)(),
 8124|    531|                                          0, is_invalid_value);
 8125|       |
 8126|    531|          if (is_invalid_value) {
  ------------------
  |  Branch (8126:15): [True: 68, False: 463]
  ------------------
 8127|     68|            ret = false;
 8128|    463|          } else if (len > 0) {
  ------------------
  |  Branch (8128:22): [True: 457, False: 6]
  ------------------
 8129|    457|            auto result = read_content_with_length(
 8130|    457|                strm, len, std::move(progress), out, payload_max_length);
 8131|    457|            ret = (result == ReadContentResult::Success);
 8132|    457|            if (result == ReadContentResult::PayloadTooLarge) {
  ------------------
  |  Branch (8132:17): [True: 0, False: 457]
  ------------------
 8133|      0|              exceed_payload_max_length = true;
 8134|      0|            }
 8135|    457|          }
 8136|    531|        }
 8137|       |
 8138|  1.72k|        if (!ret) {
  ------------------
  |  Branch (8138:13): [True: 1.23k, False: 485]
  ------------------
 8139|  1.23k|          status = exceed_payload_max_length ? StatusCode::PayloadTooLarge_413
  ------------------
  |  Branch (8139:20): [True: 15, False: 1.22k]
  ------------------
 8140|  1.23k|                                             : StatusCode::BadRequest_400;
 8141|  1.23k|        }
 8142|  1.72k|        return ret;
 8143|  1.72k|      });
_ZN7httplib6detail28is_chunked_transfer_encodingERKNS0_26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEEE:
 7999|  1.72k|inline bool is_chunked_transfer_encoding(const Headers &headers) {
 8000|       |  // RFC 9112 6.1: a message is framed with the chunked coding when "chunked"
 8001|       |  // is the final transfer coding. A single field value may list several
 8002|       |  // codings ("gzip, chunked"), and RFC 9110 5.3 lets that list be split across
 8003|       |  // several Transfer-Encoding lines, which combine into one comma-separated
 8004|       |  // list in the order the lines were received. Headers preserves that order,
 8005|       |  // so the final coding is the last token of the last line. Match it
 8006|       |  // case-insensitively rather than comparing the whole value against
 8007|       |  // "chunked".
 8008|       |  //
 8009|       |  // Security: reading a chunked message as unframed leaves its body in the
 8010|       |  // socket, where a keep-alive connection parses it as a smuggled request.
 8011|       |  // Server::process_request() answers 400 and closes when the final coding is
 8012|       |  // not chunked, so a request whose framing cannot be determined never
 8013|       |  // reaches the "no body" path.
 8014|  1.72k|  auto rng = headers.equal_range("Transfer-Encoding");
 8015|  1.72k|  if (rng.first == rng.second) { return false; }
  ------------------
  |  Branch (8015:7): [True: 807, False: 915]
  ------------------
 8016|       |
 8017|       |  // Cleared per line, so a trailing line carrying no coding at all leaves the
 8018|       |  // combined list ending in nothing rather than inheriting the line before it.
 8019|    915|  std::string last_coding;
 8020|       |
 8021|  2.23k|  for (auto it = rng.first; it != rng.second; ++it) {
  ------------------
  |  Branch (8021:29): [True: 1.31k, False: 915]
  ------------------
 8022|  1.31k|    const auto &value = it->second;
 8023|  1.31k|    last_coding.clear();
 8024|  1.31k|    split(value.data(), value.data() + value.size(), ',',
 8025|  1.31k|          [&](const char *b, const char *e) { last_coding.assign(b, e); });
 8026|  1.31k|  }
 8027|       |
 8028|    915|  return case_ignore::equal(last_coding, "chunked");
 8029|  1.72k|}
_ZNK7httplib6detail26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEE10iterator_tIKNS2_4pairIS8_S8_EEEeqISF_EEbRKNSC_IT_EE:
 1072|  1.72k|    template <typename U> bool operator==(const iterator_t<U> &rhs) const {
 1073|  1.72k|      return idx_ == rhs.idx_;
 1074|  1.72k|    }
_ZZN7httplib6detail28is_chunked_transfer_encodingERKNS0_26insertion_ordered_multimapINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS0_11case_ignore8equal_toEEEENKUlPKcSF_E_clESF_SF_:
 8025|  5.63k|          [&](const char *b, const char *e) { last_coding.assign(b, e); });
_ZN7httplib6detail20read_content_chunkedINS_8ResponseEEENS0_17ReadContentResultERNS_6StreamERT_mNSt3__18functionIFbPKcmmmEEE:
 7967|    685|                                              ContentReceiverWithProgress out) {
 7968|    685|  detail::ChunkedDecoder dec(strm);
 7969|       |
 7970|    685|  char buf[CPPHTTPLIB_RECV_BUFSIZ];
 7971|    685|  size_t total_len = 0;
 7972|       |
 7973|  5.41k|  for (;;) {
 7974|  5.41k|    size_t chunk_offset = 0;
 7975|  5.41k|    size_t chunk_total = 0;
 7976|  5.41k|    auto n = dec.read_payload(buf, sizeof(buf), chunk_offset, chunk_total);
 7977|  5.41k|    if (n < 0) { return ReadContentResult::Error; }
  ------------------
  |  Branch (7977:9): [True: 513, False: 4.90k]
  ------------------
 7978|       |
 7979|  4.90k|    if (n == 0) {
  ------------------
  |  Branch (7979:9): [True: 170, False: 4.73k]
  ------------------
 7980|    170|      if (!dec.parse_trailers_into(x.trailers, x.headers)) {
  ------------------
  |  Branch (7980:11): [True: 169, False: 1]
  ------------------
 7981|    169|        return ReadContentResult::Error;
 7982|    169|      }
 7983|      1|      return ReadContentResult::Success;
 7984|    170|    }
 7985|       |
 7986|  4.73k|    if (total_len > payload_max_length ||
  ------------------
  |  Branch (7986:9): [True: 0, False: 4.73k]
  ------------------
 7987|  4.73k|        payload_max_length - total_len < static_cast<size_t>(n)) {
  ------------------
  |  Branch (7987:9): [True: 0, False: 4.73k]
  ------------------
 7988|      0|      return ReadContentResult::PayloadTooLarge;
 7989|      0|    }
 7990|       |
 7991|  4.73k|    if (!out(buf, static_cast<size_t>(n), chunk_offset, chunk_total)) {
  ------------------
  |  Branch (7991:9): [True: 2, False: 4.72k]
  ------------------
 7992|      2|      return ReadContentResult::Error;
 7993|      2|    }
 7994|       |
 7995|  4.72k|    total_len += static_cast<size_t>(n);
 7996|  4.72k|  }
 7997|    685|}
_ZN7httplib6detail14ChunkedDecoderC2ERNS_6StreamE:
14283|    685|inline ChunkedDecoder::ChunkedDecoder(Stream &s) : strm(s) {}
_ZN7httplib6detail14ChunkedDecoder12read_payloadEPcmRmS3_:
14287|  5.41k|                                            size_t &out_chunk_total) {
14288|  5.41k|  if (finished) { return 0; }
  ------------------
  |  Branch (14288:7): [True: 0, False: 5.41k]
  ------------------
14289|       |
14290|  5.41k|  if (chunk_remaining == 0) {
  ------------------
  |  Branch (14290:7): [True: 4.89k, False: 515]
  ------------------
14291|  4.89k|    stream_line_reader lr(strm, line_buf, sizeof(line_buf));
14292|  4.89k|    if (!lr.getline()) { return -1; }
  ------------------
  |  Branch (14292:9): [True: 23, False: 4.87k]
  ------------------
14293|       |
14294|       |    // RFC 9112 §7.1: chunk-size = 1*HEXDIG
14295|  4.87k|    const char *p = lr.ptr();
14296|  4.87k|    int v = 0;
14297|  4.87k|    if (!is_hex(*p, v)) { return -1; }
  ------------------
  |  Branch (14297:9): [True: 31, False: 4.84k]
  ------------------
14298|       |
14299|  4.84k|    size_t chunk_len = 0;
14300|  4.84k|    constexpr size_t chunk_len_max = (std::numeric_limits<size_t>::max)();
14301|  13.3k|    for (; is_hex(*p, v); ++p) {
  ------------------
  |  Branch (14301:12): [True: 8.54k, False: 4.83k]
  ------------------
14302|  8.54k|      if (chunk_len > (chunk_len_max >> 4)) { return -1; }
  ------------------
  |  Branch (14302:11): [True: 8, False: 8.53k]
  ------------------
14303|  8.53k|      chunk_len = (chunk_len << 4) | static_cast<size_t>(v);
14304|  8.53k|    }
14305|       |
14306|  5.09k|    while (is_space_or_tab(*p)) {
  ------------------
  |  Branch (14306:12): [True: 259, False: 4.83k]
  ------------------
14307|    259|      ++p;
14308|    259|    }
14309|  4.83k|    if (*p != '\0' && *p != ';' && *p != '\r' && *p != '\n') { return -1; }
  ------------------
  |  Branch (14309:9): [True: 3.42k, False: 1.41k]
  |  Branch (14309:23): [True: 3.16k, False: 251]
  |  Branch (14309:36): [True: 252, False: 2.91k]
  |  Branch (14309:50): [True: 37, False: 215]
  ------------------
14310|       |
14311|  4.79k|    if (chunk_len == 0) {
  ------------------
  |  Branch (14311:9): [True: 170, False: 4.62k]
  ------------------
14312|    170|      chunk_remaining = 0;
14313|    170|      finished = true;
14314|    170|      out_chunk_offset = 0;
14315|    170|      out_chunk_total = 0;
14316|    170|      return 0;
14317|    170|    }
14318|       |
14319|  4.62k|    chunk_remaining = chunk_len;
14320|  4.62k|    last_chunk_total = chunk_remaining;
14321|  4.62k|    last_chunk_offset = 0;
14322|  4.62k|  }
14323|       |
14324|  5.14k|  auto to_read = (std::min)(chunk_remaining, len);
14325|  5.14k|  auto n = strm.read(buf, to_read);
14326|  5.14k|  if (n <= 0) { return -1; }
  ------------------
  |  Branch (14326:7): [True: 386, False: 4.75k]
  ------------------
14327|       |
14328|  4.75k|  auto offset_before = last_chunk_offset;
14329|  4.75k|  last_chunk_offset += static_cast<size_t>(n);
14330|  4.75k|  chunk_remaining -= static_cast<size_t>(n);
14331|       |
14332|  4.75k|  out_chunk_offset = offset_before;
14333|  4.75k|  out_chunk_total = last_chunk_total;
14334|       |
14335|  4.75k|  if (chunk_remaining == 0) {
  ------------------
  |  Branch (14335:7): [True: 4.24k, False: 517]
  ------------------
14336|  4.24k|    stream_line_reader lr(strm, line_buf, sizeof(line_buf));
14337|  4.24k|    if (!lr.getline()) { return -1; }
  ------------------
  |  Branch (14337:9): [True: 7, False: 4.23k]
  ------------------
14338|  4.23k|    if (std::strcmp(lr.ptr(), "\r\n") != 0) { return -1; }
  ------------------
  |  Branch (14338:9): [True: 21, False: 4.21k]
  ------------------
14339|  4.23k|  }
14340|       |
14341|  4.73k|  return n;
14342|  4.75k|}
_ZN7httplib6detail14ChunkedDecoder19parse_trailers_intoERNS0_26insertion_ordered_multimapINSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEENS0_11case_ignore8equal_toEEERKSC_:
14345|    170|                                                const Headers &src_headers) {
14346|    170|  stream_line_reader lr(strm, line_buf, sizeof(line_buf));
14347|    170|  if (!lr.getline()) { return false; }
  ------------------
  |  Branch (14347:7): [True: 19, False: 151]
  ------------------
14348|    151|  return parse_trailers(lr, dest, src_headers);
14349|    170|}
_ZN7httplib6detail14parse_trailersERNS0_18stream_line_readerERNS0_26insertion_ordered_multimapINSt3__112basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEENS0_11case_ignore8equal_toEEERKSD_:
 5625|    151|                           const Headers &src_headers) {
 5626|       |  // NOTE: In RFC 9112, '7.1 Chunked Transfer Coding' mentions "The chunked
 5627|       |  // transfer coding is complete when a chunk with a chunk-size of zero is
 5628|       |  // received, possibly followed by a trailer section, and finally terminated by
 5629|       |  // an empty line". https://www.rfc-editor.org/rfc/rfc9112.html#section-7.1
 5630|       |  //
 5631|       |  // In '7.1.3. Decoding Chunked', however, the pseudo-code in the section
 5632|       |  // doesn't care for the existence of the final CRLF. In other words, it seems
 5633|       |  // to be ok whether the final CRLF exists or not in the chunked data.
 5634|       |  // https://www.rfc-editor.org/rfc/rfc9112.html#section-7.1.3
 5635|       |  //
 5636|       |  // According to the reference code in RFC 9112, cpp-httplib now allows
 5637|       |  // chunked transfer coding data without the final CRLF.
 5638|       |
 5639|       |  // RFC 7230 Section 4.1.2 - Headers prohibited in trailers
 5640|    151|  thread_local case_ignore::unordered_set<std::string> prohibited_trailers = {
 5641|    151|      "transfer-encoding",
 5642|    151|      "content-length",
 5643|    151|      "host",
 5644|    151|      "authorization",
 5645|    151|      "www-authenticate",
 5646|    151|      "proxy-authenticate",
 5647|    151|      "proxy-authorization",
 5648|    151|      "cookie",
 5649|    151|      "set-cookie",
 5650|    151|      "cache-control",
 5651|    151|      "expect",
 5652|    151|      "max-forwards",
 5653|    151|      "pragma",
 5654|    151|      "range",
 5655|    151|      "te",
 5656|    151|      "age",
 5657|    151|      "expires",
 5658|    151|      "date",
 5659|    151|      "location",
 5660|    151|      "retry-after",
 5661|    151|      "vary",
 5662|    151|      "warning",
 5663|    151|      "content-encoding",
 5664|    151|      "content-type",
 5665|    151|      "content-range",
 5666|    151|      "trailer"};
 5667|       |
 5668|    151|  case_ignore::unordered_set<std::string> declared_trailers;
 5669|    151|  auto trailer_header = get_header_value(src_headers, "Trailer", "", 0);
 5670|    151|  if (trailer_header && std::strlen(trailer_header)) {
  ------------------
  |  Branch (5670:7): [True: 151, False: 0]
  |  Branch (5670:25): [True: 0, False: 151]
  ------------------
 5671|      0|    auto len = std::strlen(trailer_header);
 5672|      0|    split(trailer_header, trailer_header + len, ',',
 5673|      0|          [&](const char *b, const char *e) {
 5674|      0|            const char *kbeg = b;
 5675|      0|            const char *kend = e;
 5676|      0|            while (kbeg < kend && (*kbeg == ' ' || *kbeg == '\t')) {
 5677|      0|              ++kbeg;
 5678|      0|            }
 5679|      0|            while (kend > kbeg && (kend[-1] == ' ' || kend[-1] == '\t')) {
 5680|      0|              --kend;
 5681|      0|            }
 5682|      0|            std::string key(kbeg, static_cast<size_t>(kend - kbeg));
 5683|      0|            if (!key.empty() &&
 5684|      0|                prohibited_trailers.find(key) == prohibited_trailers.end()) {
 5685|      0|              declared_trailers.insert(key);
 5686|      0|            }
 5687|      0|          });
 5688|      0|  }
 5689|       |
 5690|    151|  size_t trailer_header_count = 0;
 5691|  3.59k|  while (strcmp(line_reader.ptr(), "\r\n") != 0) {
  ------------------
  |  Branch (5691:10): [True: 3.59k, False: 1]
  ------------------
 5692|  3.59k|    if (line_reader.size() > CPPHTTPLIB_HEADER_MAX_LENGTH) { return false; }
  ------------------
  |  |  114|  3.59k|#define CPPHTTPLIB_HEADER_MAX_LENGTH 8192
  ------------------
  |  Branch (5692:9): [True: 2, False: 3.59k]
  ------------------
 5693|  3.59k|    if (trailer_header_count >= CPPHTTPLIB_HEADER_MAX_COUNT) { return false; }
  ------------------
  |  |  118|  3.59k|#define CPPHTTPLIB_HEADER_MAX_COUNT 100
  ------------------
  |  Branch (5693:9): [True: 0, False: 3.59k]
  ------------------
 5694|       |
 5695|  3.59k|    constexpr auto line_terminator_len = 2;
 5696|  3.59k|    auto line_beg = line_reader.ptr();
 5697|  3.59k|    auto line_end =
 5698|  3.59k|        line_reader.ptr() + line_reader.size() - line_terminator_len;
 5699|       |
 5700|  3.59k|    if (!parse_header(line_beg, line_end,
  ------------------
  |  Branch (5700:9): [True: 105, False: 3.48k]
  ------------------
 5701|  3.59k|                      [&](const std::string &key, const std::string &val) {
 5702|  3.59k|                        if (declared_trailers.find(key) !=
 5703|  3.59k|                            declared_trailers.end()) {
 5704|  3.59k|                          dest.emplace(key, val);
 5705|  3.59k|                          trailer_header_count++;
 5706|  3.59k|                        }
 5707|  3.59k|                      })) {
 5708|    105|      return false;
 5709|    105|    }
 5710|       |
 5711|  3.48k|    if (!line_reader.getline()) { return false; }
  ------------------
  |  Branch (5711:9): [True: 43, False: 3.44k]
  ------------------
 5712|  3.48k|  }
 5713|       |
 5714|      1|  return true;
 5715|    151|}
_ZNK7httplib6detail11case_ignore4hashclERKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEE:
  620|     26|  size_t operator()(const std::string &key) const {
  621|     26|    return hash_core(key.data(), key.size(), 0);
  622|     26|  }
_ZNK7httplib6detail11case_ignore4hash9hash_coreEPKcmm:
  624|    279|  size_t hash_core(const char *s, size_t l, size_t h) const {
  625|    279|    return (l == 0) ? h
  ------------------
  |  Branch (625:12): [True: 26, False: 253]
  ------------------
  626|    279|                    : hash_core(s + 1, l - 1,
  627|       |                                // Unsets the 6 high bits of h, therefore no
  628|       |                                // overflow happens
  629|    253|                                (((std::numeric_limits<size_t>::max)() >> 6) &
  630|    253|                                 h * 33) ^
  631|    253|                                    static_cast<unsigned char>(to_lower(*s)));
  632|    279|  }
_ZN7httplib6detail12parse_headerIZNS0_14parse_trailersERNS0_18stream_line_readerERNS0_26insertion_ordered_multimapINSt3__112basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEENS0_11case_ignore8equal_toEEERKSE_EUlRKSB_SJ_E_EEbPKcSM_T_:
 5579|  3.59k|inline bool parse_header(const char *beg, const char *end, T fn) {
 5580|       |  // Skip trailing spaces and tabs.
 5581|  3.82k|  while (beg < end && is_space_or_tab(end[-1])) {
  ------------------
  |  Branch (5581:10): [True: 3.77k, False: 43]
  |  Branch (5581:23): [True: 231, False: 3.54k]
  ------------------
 5582|    231|    end--;
 5583|    231|  }
 5584|       |
 5585|  3.59k|  auto p = beg;
 5586|  92.0k|  while (p < end && *p != ':') {
  ------------------
  |  Branch (5586:10): [True: 91.9k, False: 84]
  |  Branch (5586:21): [True: 88.4k, False: 3.50k]
  ------------------
 5587|  88.4k|    p++;
 5588|  88.4k|  }
 5589|       |
 5590|  3.59k|  auto name = std::string(beg, p);
 5591|  3.59k|  if (!detail::fields::is_field_name(name)) { return false; }
  ------------------
  |  Branch (5591:7): [True: 81, False: 3.50k]
  ------------------
 5592|       |
 5593|  3.50k|  if (p == end) { return false; }
  ------------------
  |  Branch (5593:7): [True: 12, False: 3.49k]
  ------------------
 5594|       |
 5595|  3.49k|  auto key_end = p;
 5596|       |
 5597|  3.49k|  if (*p++ != ':') { return false; }
  ------------------
  |  Branch (5597:7): [True: 0, False: 3.49k]
  ------------------
 5598|       |
 5599|  3.99k|  while (p < end && is_space_or_tab(*p)) {
  ------------------
  |  Branch (5599:10): [True: 2.08k, False: 1.90k]
  |  Branch (5599:21): [True: 498, False: 1.59k]
  ------------------
 5600|    498|    p++;
 5601|    498|  }
 5602|       |
 5603|  3.49k|  if (p <= end) {
  ------------------
  |  Branch (5603:7): [True: 3.49k, False: 0]
  ------------------
 5604|  3.49k|    auto key_len = key_end - beg;
 5605|  3.49k|    if (!key_len) { return false; }
  ------------------
  |  Branch (5605:9): [True: 0, False: 3.49k]
  ------------------
 5606|       |
 5607|  3.49k|    auto key = std::string(beg, key_end);
 5608|  3.49k|    auto val = std::string(p, end);
 5609|       |
 5610|  3.49k|    if (!detail::fields::is_field_value(val)) { return false; }
  ------------------
  |  Branch (5610:9): [True: 12, False: 3.48k]
  ------------------
 5611|       |
 5612|       |    // RFC 9110 §5.5: header field values are opaque octets and MUST NOT be
 5613|       |    // percent-decoded by the recipient. Applications that need to interpret a
 5614|       |    // value as a URI component should call httplib::decode_uri_component()
 5615|       |    // (or decode_path_component()) explicitly.
 5616|  3.48k|    fn(key, val);
 5617|       |
 5618|  3.48k|    return true;
 5619|  3.49k|  }
 5620|       |
 5621|      0|  return false;
 5622|  3.49k|}
_ZZN7httplib6detail14parse_trailersERNS0_18stream_line_readerERNS0_26insertion_ordered_multimapINSt3__112basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEENS0_11case_ignore8equal_toEEERKSD_ENKUlRKSA_SI_E_clESI_SI_:
 5701|  3.48k|                      [&](const std::string &key, const std::string &val) {
 5702|  3.48k|                        if (declared_trailers.find(key) !=
  ------------------
  |  Branch (5702:29): [True: 0, False: 3.48k]
  ------------------
 5703|  3.48k|                            declared_trailers.end()) {
 5704|      0|                          dest.emplace(key, val);
 5705|      0|                          trailer_header_count++;
 5706|      0|                        }
 5707|  3.48k|                      })) {
_ZN7httplib6detail27read_content_without_lengthERNS_6StreamEmNSt3__18functionIFbPKcmmmEEE:
 7941|    506|                            ContentReceiverWithProgress out) {
 7942|    506|  char buf[CPPHTTPLIB_RECV_BUFSIZ];
 7943|    506|  size_t r = 0;
 7944|  1.78k|  for (;;) {
 7945|  1.78k|    auto n = strm.read(buf, CPPHTTPLIB_RECV_BUFSIZ);
  ------------------
  |  |  150|  1.78k|#define CPPHTTPLIB_RECV_BUFSIZ size_t(16384u)
  ------------------
 7946|  1.78k|    if (n == 0) { return ReadContentResult::Success; }
  ------------------
  |  Branch (7946:9): [True: 475, False: 1.31k]
  ------------------
 7947|  1.31k|    if (n < 0) { return ReadContentResult::Error; }
  ------------------
  |  Branch (7947:9): [True: 0, False: 1.31k]
  ------------------
 7948|       |
 7949|       |    // Check if adding this data would exceed the payload limit
 7950|  1.31k|    if (r > payload_max_length ||
  ------------------
  |  Branch (7950:9): [True: 0, False: 1.31k]
  ------------------
 7951|  1.31k|        payload_max_length - r < static_cast<size_t>(n)) {
  ------------------
  |  Branch (7951:9): [True: 0, False: 1.31k]
  ------------------
 7952|      0|      return ReadContentResult::PayloadTooLarge;
 7953|      0|    }
 7954|       |
 7955|  1.31k|    if (!out(buf, static_cast<size_t>(n), r, 0)) {
  ------------------
  |  Branch (7955:9): [True: 31, False: 1.28k]
  ------------------
 7956|     31|      return ReadContentResult::Error;
 7957|     31|    }
 7958|  1.28k|    r += static_cast<size_t>(n);
 7959|  1.28k|  }
 7960|       |
 7961|      0|  return ReadContentResult::Success;
 7962|    506|}
_ZN7httplib6detail24read_content_with_lengthERNS_6StreamEmNSt3__18functionIFbmmEEENS4_IFbPKcmmmEEEm:
 7901|    457|    size_t payload_max_length = (std::numeric_limits<size_t>::max)()) {
 7902|    457|  char buf[CPPHTTPLIB_RECV_BUFSIZ];
 7903|       |
 7904|    457|  detail::BodyReader br;
 7905|    457|  br.stream = &strm;
 7906|    457|  br.has_content_length = true;
 7907|    457|  br.content_length = len;
 7908|    457|  br.payload_max_length = payload_max_length;
 7909|    457|  br.chunked = false;
 7910|    457|  br.bytes_read = 0;
 7911|    457|  br.last_error = Error::Success;
 7912|       |
 7913|    457|  size_t r = 0;
 7914|    996|  while (r < len) {
  ------------------
  |  Branch (7914:10): [True: 993, False: 3]
  ------------------
 7915|    993|    auto read_len = static_cast<size_t>(len - r);
 7916|    993|    auto to_read = (std::min)(read_len, CPPHTTPLIB_RECV_BUFSIZ);
  ------------------
  |  |  150|    993|#define CPPHTTPLIB_RECV_BUFSIZ size_t(16384u)
  ------------------
 7917|    993|    auto n = detail::read_body_content(&strm, br, buf, to_read);
 7918|    993|    if (n <= 0) {
  ------------------
  |  Branch (7918:9): [True: 452, False: 541]
  ------------------
 7919|       |      // Check if it was a payload size error
 7920|    452|      if (br.last_error == Error::ExceedMaxPayloadSize) {
  ------------------
  |  Branch (7920:11): [True: 0, False: 452]
  ------------------
 7921|      0|        return ReadContentResult::PayloadTooLarge;
 7922|      0|      }
 7923|    452|      return ReadContentResult::Error;
 7924|    452|    }
 7925|       |
 7926|    541|    if (!out(buf, static_cast<size_t>(n), r, len)) {
  ------------------
  |  Branch (7926:9): [True: 2, False: 539]
  ------------------
 7927|      2|      return ReadContentResult::Error;
 7928|      2|    }
 7929|    539|    r += static_cast<size_t>(n);
 7930|       |
 7931|    539|    if (progress) {
  ------------------
  |  Branch (7931:9): [True: 539, False: 0]
  ------------------
 7932|    539|      if (!progress(r, len)) { return ReadContentResult::Error; }
  ------------------
  |  Branch (7932:11): [True: 0, False: 539]
  ------------------
 7933|    539|    }
 7934|    539|  }
 7935|       |
 7936|      3|  return ReadContentResult::Success;
 7937|    457|}
_ZN7httplib6detail17read_body_contentEPNS_6StreamERNS0_10BodyReaderEPcm:
 2445|    993|                                 size_t len) {
 2446|    993|  (void)stream;
 2447|    993|  return br.read(buf, len);
 2448|    993|}
_ZN7httplib6detail10BodyReader4readEPcm:
11115|    993|inline ssize_t detail::BodyReader::read(char *buf, size_t len) {
11116|    993|  if (!stream) {
  ------------------
  |  Branch (11116:7): [True: 0, False: 993]
  ------------------
11117|      0|    last_error = Error::Connection;
11118|      0|    return -1;
11119|      0|  }
11120|    993|  if (eof) { return 0; }
  ------------------
  |  Branch (11120:7): [True: 0, False: 993]
  ------------------
11121|       |
11122|    993|  if (!chunked) {
  ------------------
  |  Branch (11122:7): [True: 993, False: 0]
  ------------------
11123|       |    // Content-Length based reading
11124|    993|    if (has_content_length && bytes_read >= content_length) {
  ------------------
  |  Branch (11124:9): [True: 993, False: 0]
  |  Branch (11124:31): [True: 0, False: 993]
  ------------------
11125|      0|      eof = true;
11126|      0|      return 0;
11127|      0|    }
11128|       |
11129|    993|    auto to_read = len;
11130|    993|    if (has_content_length) {
  ------------------
  |  Branch (11130:9): [True: 993, False: 0]
  ------------------
11131|    993|      auto remaining = content_length - bytes_read;
11132|    993|      to_read = (std::min)(len, remaining);
11133|    993|    }
11134|    993|    auto n = stream->read(buf, to_read);
11135|       |
11136|    993|    if (n < 0) {
  ------------------
  |  Branch (11136:9): [True: 0, False: 993]
  ------------------
11137|      0|      last_error = stream->get_error();
11138|      0|      if (last_error == Error::Success) { last_error = Error::Read; }
  ------------------
  |  Branch (11138:11): [True: 0, False: 0]
  ------------------
11139|      0|      eof = true;
11140|      0|      return n;
11141|      0|    }
11142|    993|    if (n == 0) {
  ------------------
  |  Branch (11142:9): [True: 452, False: 541]
  ------------------
11143|       |      // Unexpected EOF before content_length
11144|    452|      last_error = stream->get_error();
11145|    452|      if (last_error == Error::Success) { last_error = Error::Read; }
  ------------------
  |  Branch (11145:11): [True: 452, False: 0]
  ------------------
11146|    452|      eof = true;
11147|    452|      return 0;
11148|    452|    }
11149|       |
11150|    541|    bytes_read += static_cast<size_t>(n);
11151|    541|    if (has_content_length && bytes_read >= content_length) { eof = true; }
  ------------------
  |  Branch (11151:9): [True: 541, False: 0]
  |  Branch (11151:31): [True: 3, False: 538]
  ------------------
11152|    541|    if (payload_max_length > 0 && bytes_read > payload_max_length) {
  ------------------
  |  Branch (11152:9): [True: 541, False: 0]
  |  Branch (11152:35): [True: 0, False: 541]
  ------------------
11153|      0|      last_error = Error::ExceedMaxPayloadSize;
11154|      0|      eof = true;
11155|      0|      return -1;
11156|      0|    }
11157|    541|    return n;
11158|    541|  }
11159|       |
11160|       |  // Chunked transfer encoding: delegate to shared decoder instance.
11161|      0|  if (!chunked_decoder) { chunked_decoder.reset(new ChunkedDecoder(*stream)); }
  ------------------
  |  Branch (11161:7): [True: 0, False: 0]
  ------------------
11162|       |
11163|      0|  size_t chunk_offset = 0;
11164|      0|  size_t chunk_total = 0;
11165|      0|  auto n = chunked_decoder->read_payload(buf, len, chunk_offset, chunk_total);
11166|      0|  if (n < 0) {
  ------------------
  |  Branch (11166:7): [True: 0, False: 0]
  ------------------
11167|      0|    last_error = stream->get_error();
11168|      0|    if (last_error == Error::Success) { last_error = Error::Read; }
  ------------------
  |  Branch (11168:9): [True: 0, False: 0]
  ------------------
11169|      0|    eof = true;
11170|      0|    return n;
11171|      0|  }
11172|       |
11173|      0|  if (n == 0) {
  ------------------
  |  Branch (11173:7): [True: 0, False: 0]
  ------------------
11174|       |    // Final chunk observed. Leave trailer parsing to the caller (StreamHandle).
11175|      0|    eof = true;
11176|      0|    return 0;
11177|      0|  }
11178|       |
11179|      0|  bytes_read += static_cast<size_t>(n);
11180|      0|  if (payload_max_length > 0 && bytes_read > payload_max_length) {
  ------------------
  |  Branch (11180:7): [True: 0, False: 0]
  |  Branch (11180:33): [True: 0, False: 0]
  ------------------
11181|      0|    last_error = Error::ExceedMaxPayloadSize;
11182|      0|    eof = true;
11183|      0|    return -1;
11184|      0|  }
11185|      0|  return n;
11186|      0|}
_ZNK7httplib6Stream9get_errorEv:
 1855|    452|  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:
 8080|  4.63k|                                        size_t len) {
 8081|  4.63k|    return receiver(buf, n, off, len);
 8082|  4.63k|  };
_ZZN7httplib10ClientImpl15process_requestERNS_6StreamERNS_7RequestERNS_8ResponseEbRNS_5ErrorEENKUlmmE_clEmm:
15113|    539|    auto progress = [&](size_t current, size_t total) {
15114|    539|      if (!req.download_progress || redirect) { return true; }
  ------------------
  |  Branch (15114:11): [True: 539, False: 0]
  |  Branch (15114:37): [True: 0, False: 0]
  ------------------
15115|      0|      auto ret = req.download_progress(current, total);
15116|      0|      if (!ret) {
  ------------------
  |  Branch (15116:11): [True: 0, False: 0]
  ------------------
15117|      0|        error = Error::Canceled;
15118|      0|        output_error_log(error, &req);
15119|      0|      }
15120|      0|      return ret;
15121|    539|    };
_ZNK7httplib10ClientImpl10output_logERKNS_7RequestERKNS_8ResponseE:
14969|    504|                                   const Response &res) const {
14970|    504|  if (logger_) {
  ------------------
  |  Branch (14970:7): [True: 0, False: 504]
  ------------------
14971|      0|    std::lock_guard<std::mutex> guard(logger_mutex_);
14972|      0|    logger_(req, res);
14973|      0|  }
14974|    504|}
_ZN7httplib8ResponseD2Ev:
 1756|  3.09k|  ~Response() {
 1757|  3.09k|    if (content_provider_resource_releaser_) {
  ------------------
  |  Branch (1757:9): [True: 0, False: 3.09k]
  ------------------
 1758|      0|      content_provider_resource_releaser_(content_provider_success_);
 1759|      0|    }
 1760|  3.09k|  }
_ZNK7httplib6detail17gzip_decompressor8is_validEv:
 7435|    135|inline bool gzip_decompressor::is_valid() const { return is_valid_; }
_ZN7httplib6detail17gzip_decompressor10decompressEPKcmNSt3__18functionIFbS3_mEEE:
 7438|  1.94k|                                          Callback callback) {
 7439|  1.94k|  assert(is_valid_);
  ------------------
  |  Branch (7439:3): [True: 1.94k, False: 0]
  ------------------
 7440|       |
 7441|  1.94k|  auto ret = Z_OK;
 7442|       |
 7443|  1.94k|  do {
 7444|  1.94k|    constexpr size_t max_avail_in =
 7445|  1.94k|        (std::numeric_limits<decltype(strm_.avail_in)>::max)();
 7446|       |
 7447|  1.94k|    strm_.avail_in = static_cast<decltype(strm_.avail_in)>(
 7448|  1.94k|        (std::min)(data_length, max_avail_in));
 7449|  1.94k|    strm_.next_in = const_cast<Bytef *>(reinterpret_cast<const Bytef *>(data));
 7450|       |
 7451|  1.94k|    data_length -= strm_.avail_in;
 7452|  1.94k|    data += strm_.avail_in;
 7453|       |
 7454|  1.94k|    std::array<char, CPPHTTPLIB_COMPRESSION_BUFSIZ> buff{};
 7455|   129k|    while (strm_.avail_in > 0 && ret == Z_OK) {
  ------------------
  |  Branch (7455:12): [True: 127k, False: 1.64k]
  |  Branch (7455:34): [True: 127k, False: 259]
  ------------------
 7456|   127k|      strm_.avail_out = static_cast<uInt>(buff.size());
 7457|   127k|      strm_.next_out = reinterpret_cast<Bytef *>(buff.data());
 7458|       |
 7459|   127k|      ret = inflate(&strm_, Z_NO_FLUSH);
 7460|       |
 7461|   127k|      assert(ret != Z_STREAM_ERROR);
  ------------------
  |  Branch (7461:7): [True: 127k, False: 0]
  ------------------
 7462|   127k|      switch (ret) {
  ------------------
  |  Branch (7462:15): [True: 20, False: 127k]
  ------------------
 7463|      1|      case Z_NEED_DICT:
  ------------------
  |  Branch (7463:7): [True: 1, False: 127k]
  ------------------
 7464|     20|      case Z_DATA_ERROR:
  ------------------
  |  Branch (7464:7): [True: 19, False: 127k]
  ------------------
 7465|     20|      case Z_MEM_ERROR: inflateEnd(&strm_); return false;
  ------------------
  |  Branch (7465:7): [True: 0, False: 127k]
  ------------------
 7466|   127k|      }
 7467|       |
 7468|   127k|      if (!callback(buff.data(), buff.size() - strm_.avail_out)) {
  ------------------
  |  Branch (7468:11): [True: 15, False: 127k]
  ------------------
 7469|     15|        return false;
 7470|     15|      }
 7471|   127k|    }
 7472|       |
 7473|  1.90k|    if (ret != Z_OK && ret != Z_STREAM_END) { return false; }
  ------------------
  |  Branch (7473:9): [True: 259, False: 1.64k]
  |  Branch (7473:24): [True: 0, False: 259]
  ------------------
 7474|       |
 7475|  1.90k|  } while (data_length > 0);
  ------------------
  |  Branch (7475:12): [True: 0, False: 1.90k]
  ------------------
 7476|       |
 7477|  1.90k|  return true;
 7478|  1.94k|}
_ZN7httplib6detail12BufferStreamD2Ev:
 3527|  3.09k|  ~BufferStream() override = default;
_ZN7httplib6detail12BufferStream5writeEPKcm:
11525|  20.3k|inline ssize_t BufferStream::write(const char *ptr, size_t size) {
11526|  20.3k|  buffer.append(ptr, size);
11527|  20.3k|  return static_cast<ssize_t>(size);
11528|  20.3k|}
_ZNK7httplib6Stream13buffered_dataERm:
 1844|  2.01M|  virtual const char *buffered_data(size_t &size) const {
 1845|  2.01M|    size = 0;
 1846|  2.01M|    return nullptr;
 1847|  2.01M|  }
_ZNK7httplib10ClientImpl6is_sslEv:
15229|  3.09k|inline bool ClientImpl::is_ssl() const { return false; }

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

