_ZN7httplib6detail17gzip_decompressorD2Ev:
 6779|     86|inline gzip_decompressor::~gzip_decompressor() { inflateEnd(&strm_); }
_ZN7httplib10ClientImplD2Ev:
12479|  1.96k|inline ClientImpl::~ClientImpl() {
12480|       |  // Wait until all the requests in flight are handled.
12481|  1.96k|  size_t retry_count = 10;
12482|  1.96k|  while (retry_count-- > 0) {
  ------------------
  |  Branch (12482:10): [True: 1.96k, False: 0]
  ------------------
12483|  1.96k|    {
12484|  1.96k|      std::lock_guard<std::mutex> guard(socket_mutex_);
12485|  1.96k|      if (socket_requests_in_flight_ == 0) { break; }
  ------------------
  |  Branch (12485:11): [True: 1.96k, False: 0]
  ------------------
12486|  1.96k|    }
12487|      0|    std::this_thread::sleep_for(std::chrono::milliseconds{1});
12488|      0|  }
12489|       |
12490|  1.96k|  std::lock_guard<std::mutex> guard(socket_mutex_);
12491|  1.96k|  shutdown_socket(socket_);
12492|  1.96k|  close_socket(socket_);
12493|  1.96k|}
_ZN7httplib6detail12decompressorD2Ev:
 3117|     86|  virtual ~decompressor() = default;
_ZN7httplib6StreamD2Ev:
 1445|  3.92k|  virtual ~Stream() = default;
_ZNK7httplib10ClientImpl15shutdown_socketERNS0_6SocketE:
12607|  1.96k|inline void ClientImpl::shutdown_socket(Socket &socket) const {
12608|  1.96k|  if (socket.sock == INVALID_SOCKET) { return; }
  ------------------
  |  |  300|  1.96k|#define INVALID_SOCKET (-1)
  ------------------
  |  Branch (12608:7): [True: 1.96k, False: 0]
  ------------------
12609|      0|  detail::shutdown_socket(socket.sock);
12610|      0|}
_ZN7httplib10ClientImpl12close_socketERNS0_6SocketE:
12612|  1.96k|inline void ClientImpl::close_socket(Socket &socket) {
12613|       |  // If there are requests in flight in another thread, usually closing
12614|       |  // the socket will be fine and they will simply receive an error when
12615|       |  // using the closed socket, but it is still a bug since rarely the OS
12616|       |  // may reassign the socket id to be used for a new socket, and then
12617|       |  // suddenly they will be operating on a live socket that is different
12618|       |  // than the one they intended!
12619|  1.96k|  assert(socket_requests_in_flight_ == 0 ||
  ------------------
  |  Branch (12619:3): [True: 1.96k, False: 0]
  |  Branch (12619:3): [True: 0, False: 0]
  |  Branch (12619:3): [True: 1.96k, False: 0]
  ------------------
12620|  1.96k|         socket_requests_are_from_thread_ == std::this_thread::get_id());
12621|       |
12622|       |  // It is also a bug if this happens while SSL is still active
12623|       |#ifdef CPPHTTPLIB_SSL_ENABLED
12624|       |  assert(socket.ssl == nullptr);
12625|       |#endif
12626|       |
12627|  1.96k|  if (socket.sock == INVALID_SOCKET) { return; }
  ------------------
  |  |  300|  1.96k|#define INVALID_SOCKET (-1)
  ------------------
  |  Branch (12627:7): [True: 1.96k, False: 0]
  ------------------
12628|      0|  detail::close_socket(socket.sock);
12629|      0|  socket.sock = INVALID_SOCKET;
  ------------------
  |  |  300|      0|#define INVALID_SOCKET (-1)
  ------------------
12630|      0|}
_ZN7httplib10ClientImplC2ERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEi:
12471|  1.96k|    : ClientImpl(host, port, std::string(), std::string()) {}
_ZN7httplib10ClientImplC2ERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEiS9_S9_:
12476|  1.96k|    : host_(detail::escape_abstract_namespace_unix_domain(host)), port_(port),
12477|  1.96k|      client_cert_path_(client_cert_path), client_key_path_(client_key_path) {}
_ZN7httplib6detail37escape_abstract_namespace_unix_domainERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
 5703|  1.96k|inline std::string escape_abstract_namespace_unix_domain(const std::string &s) {
 5704|  1.96k|  if (s.size() > 1 && s[0] == '\0') {
  ------------------
  |  Branch (5704:7): [True: 1.96k, False: 0]
  |  Branch (5704:23): [True: 0, False: 1.96k]
  ------------------
 5705|      0|    auto ret = s;
 5706|      0|    ret[0] = '@';
 5707|      0|    return ret;
 5708|      0|  }
 5709|  1.96k|  return s;
 5710|  1.96k|}
_ZN7httplib6detail13write_headersERNS_6StreamERKNSt3__118unordered_multimapINS3_12basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEESA_NS0_11case_ignore4hashENSB_8equal_toENS8_INS3_4pairIKSA_SA_EEEEEE:
 7401|  1.96k|inline ssize_t write_headers(Stream &strm, const Headers &headers) {
 7402|  1.96k|  ssize_t write_len = 0;
 7403|  9.16k|  for (const auto &x : headers) {
  ------------------
  |  Branch (7403:22): [True: 9.16k, False: 1.96k]
  ------------------
 7404|  9.16k|    std::string s;
 7405|  9.16k|    s = x.first;
 7406|  9.16k|    s += ": ";
 7407|  9.16k|    s += x.second;
 7408|  9.16k|    s += "\r\n";
 7409|       |
 7410|  9.16k|    auto len = strm.write(s.data(), s.size());
 7411|  9.16k|    if (len < 0) { return len; }
  ------------------
  |  Branch (7411:9): [True: 0, False: 9.16k]
  ------------------
 7412|  9.16k|    write_len += len;
 7413|  9.16k|  }
 7414|  1.96k|  auto len = strm.write("\r\n");
 7415|  1.96k|  if (len < 0) { return len; }
  ------------------
  |  Branch (7415:7): [True: 0, False: 1.96k]
  ------------------
 7416|  1.96k|  write_len += len;
 7417|  1.96k|  return write_len;
 7418|  1.96k|}
_ZN7httplib6Stream5writeEPKc:
10005|  1.96k|inline ssize_t Stream::write(const char *ptr) {
10006|  1.96k|  return write(ptr, strlen(ptr));
10007|  1.96k|}
_ZN7httplib8ResponseC2Ev:
 1378|  1.96k|  Response() = default;
_ZN7httplib8UserDataC2Ev:
  931|  1.96k|  UserData() = default;
_ZN7httplib10ClientImpl15process_requestERNS_6StreamERNS_7RequestERNS_8ResponseEbRNS_5ErrorE:
13784|  1.96k|                                        Error &error) {
13785|       |  // Auto-add Expect: 100-continue for large bodies
13786|  1.96k|  if (CPPHTTPLIB_EXPECT_100_THRESHOLD > 0 && !req.has_header("Expect")) {
  ------------------
  |  |   82|  1.96k|#define CPPHTTPLIB_EXPECT_100_THRESHOLD 1024
  ------------------
  |  Branch (13786:7): [True: 1.96k, Folded]
  |  Branch (13786:7): [True: 1.96k, False: 0]
  |  Branch (13786:46): [True: 1.96k, False: 0]
  ------------------
13787|  1.96k|    auto body_size = req.body.empty() ? req.content_length_ : req.body.size();
  ------------------
  |  Branch (13787:22): [True: 1.96k, False: 0]
  ------------------
13788|  1.96k|    if (body_size >= CPPHTTPLIB_EXPECT_100_THRESHOLD) {
  ------------------
  |  |   82|  1.96k|#define CPPHTTPLIB_EXPECT_100_THRESHOLD 1024
  ------------------
  |  Branch (13788:9): [True: 0, False: 1.96k]
  ------------------
13789|      0|      req.set_header("Expect", "100-continue");
13790|      0|    }
13791|  1.96k|  }
13792|       |
13793|       |  // Check for Expect: 100-continue
13794|  1.96k|  auto expect_100_continue = req.get_header_value("Expect") == "100-continue";
13795|       |
13796|       |  // Send request (skip body if using Expect: 100-continue)
13797|  1.96k|  auto write_request_success =
13798|  1.96k|      write_request(strm, req, close_connection, error, expect_100_continue);
13799|       |
13800|       |#ifdef CPPHTTPLIB_SSL_ENABLED
13801|       |  if (is_ssl() && !expect_100_continue) {
13802|       |    auto is_proxy_enabled = is_proxy_enabled_for_host(host_);
13803|       |    if (!is_proxy_enabled) {
13804|       |      if (tls::is_peer_closed(socket_.ssl, socket_.sock)) {
13805|       |        error = Error::SSLPeerCouldBeClosed_;
13806|       |        output_error_log(error, &req);
13807|       |        return false;
13808|       |      }
13809|       |    }
13810|       |  }
13811|       |#endif
13812|       |
13813|       |  // Handle Expect: 100-continue.
13814|       |  //
13815|       |  // Wait for an interim/early response by attempting to read the status line
13816|       |  // under a short timeout, instead of trusting raw socket readability. Over
13817|       |  // TLS, post-handshake records (e.g. session tickets) make the socket
13818|       |  // readable without any HTTP response being available; relying on
13819|       |  // `select_read` there caused the body to be withheld forever and the
13820|       |  // request to fail with `Read` (#2458). If no status line arrives within the
13821|       |  // timeout, send the body anyway (matching curl's behavior).
13822|  1.96k|  auto status_line_read = false;
13823|  1.96k|  if (expect_100_continue && write_request_success) {
  ------------------
  |  Branch (13823:7): [True: 0, False: 1.96k]
  |  Branch (13823:30): [True: 0, False: 0]
  ------------------
13824|      0|    if (CPPHTTPLIB_EXPECT_100_TIMEOUT_MSECOND > 0) {
  ------------------
  |  |   86|      0|#define CPPHTTPLIB_EXPECT_100_TIMEOUT_MSECOND 1000
  ------------------
  |  Branch (13824:9): [True: 0, Folded]
  ------------------
13825|      0|      time_t sec = CPPHTTPLIB_EXPECT_100_TIMEOUT_MSECOND / 1000;
  ------------------
  |  |   86|      0|#define CPPHTTPLIB_EXPECT_100_TIMEOUT_MSECOND 1000
  ------------------
13826|      0|      time_t usec = (CPPHTTPLIB_EXPECT_100_TIMEOUT_MSECOND % 1000) * 1000;
  ------------------
  |  |   86|      0|#define CPPHTTPLIB_EXPECT_100_TIMEOUT_MSECOND 1000
  ------------------
13827|      0|      strm.set_read_timeout(sec, usec);
13828|      0|      status_line_read = read_response_line(strm, req, res, false);
13829|      0|      strm.set_read_timeout(read_timeout_sec_, read_timeout_usec_);
13830|      0|    }
13831|       |
13832|      0|    if (!status_line_read) {
  ------------------
  |  Branch (13832:9): [True: 0, False: 0]
  ------------------
13833|       |      // No interim response within the timeout: send the body and handle the
13834|       |      // response as usual.
13835|      0|      if (!write_request_body(strm, req, error)) { return false; }
  ------------------
  |  Branch (13835:11): [True: 0, False: 0]
  ------------------
13836|      0|      expect_100_continue = false; // Switch to normal response handling
13837|      0|    }
13838|      0|  }
13839|       |
13840|       |  // Receive response and headers
13841|       |  // When using Expect: 100-continue, don't auto-skip `100 Continue` response
13842|  1.96k|  if ((!status_line_read &&
  ------------------
  |  Branch (13842:8): [True: 1.96k, False: 0]
  ------------------
13843|  1.96k|       !read_response_line(strm, req, res, !expect_100_continue)) ||
  ------------------
  |  Branch (13843:8): [True: 323, False: 1.64k]
  ------------------
13844|  1.64k|      !detail::read_headers(strm, res.headers)) {
  ------------------
  |  Branch (13844:7): [True: 1.05k, False: 586]
  ------------------
13845|  1.37k|    if (write_request_success) { error = Error::Read; }
  ------------------
  |  Branch (13845:9): [True: 1.37k, False: 0]
  ------------------
13846|  1.37k|    output_error_log(error, &req);
13847|  1.37k|    return false;
13848|  1.37k|  }
13849|       |
13850|    586|  if (!write_request_success) { return false; }
  ------------------
  |  Branch (13850:7): [True: 0, False: 586]
  ------------------
13851|       |
13852|       |  // Handle Expect: 100-continue response
13853|    586|  if (expect_100_continue) {
  ------------------
  |  Branch (13853:7): [True: 0, False: 586]
  ------------------
13854|      0|    if (res.status == StatusCode::Continue_100) {
  ------------------
  |  Branch (13854:9): [True: 0, False: 0]
  ------------------
13855|       |      // Server accepted, send the body
13856|      0|      if (!write_request_body(strm, req, error)) { return false; }
  ------------------
  |  Branch (13856:11): [True: 0, False: 0]
  ------------------
13857|       |
13858|       |      // Read the actual response
13859|      0|      res.headers.clear();
13860|      0|      res.body.clear();
13861|      0|      if (!read_response_line(strm, req, res) ||
  ------------------
  |  Branch (13861:11): [True: 0, False: 0]
  ------------------
13862|      0|          !detail::read_headers(strm, res.headers)) {
  ------------------
  |  Branch (13862:11): [True: 0, False: 0]
  ------------------
13863|      0|        error = Error::Read;
13864|      0|        output_error_log(error, &req);
13865|      0|        return false;
13866|      0|      }
13867|      0|    }
13868|       |    // If not 100 Continue, server returned an error; proceed with that response
13869|      0|  }
13870|       |
13871|       |  // Body
13872|    586|  if ((res.status != StatusCode::NoContent_204) && req.method != "HEAD" &&
  ------------------
  |  Branch (13872:7): [True: 583, False: 3]
  |  Branch (13872:52): [True: 583, False: 0]
  ------------------
13873|    583|      req.method != "CONNECT") {
  ------------------
  |  Branch (13873:7): [True: 583, False: 0]
  ------------------
13874|    583|    auto redirect = 300 < res.status && res.status < 400 &&
  ------------------
  |  Branch (13874:21): [True: 199, False: 384]
  |  Branch (13874:41): [True: 26, False: 173]
  ------------------
13875|     26|                    res.status != StatusCode::NotModified_304 &&
  ------------------
  |  Branch (13875:21): [True: 25, False: 1]
  ------------------
13876|     25|                    follow_location_;
  ------------------
  |  Branch (13876:21): [True: 0, False: 25]
  ------------------
13877|       |
13878|    583|    if (req.response_handler && !redirect) {
  ------------------
  |  Branch (13878:9): [True: 0, False: 583]
  |  Branch (13878:33): [True: 0, False: 0]
  ------------------
13879|      0|      if (!req.response_handler(res)) {
  ------------------
  |  Branch (13879:11): [True: 0, False: 0]
  ------------------
13880|      0|        error = Error::Canceled;
13881|      0|        output_error_log(error, &req);
13882|      0|        return false;
13883|      0|      }
13884|      0|    }
13885|       |
13886|    583|    auto out =
13887|    583|        req.content_receiver
  ------------------
  |  Branch (13887:9): [True: 0, False: 583]
  ------------------
13888|    583|            ? static_cast<ContentReceiverWithProgress>(
13889|      0|                  [&](const char *buf, size_t n, size_t off, size_t len) {
13890|      0|                    if (redirect) { return true; }
13891|      0|                    auto ret = req.content_receiver(buf, n, off, len);
13892|      0|                    if (!ret) {
13893|      0|                      error = Error::Canceled;
13894|      0|                      output_error_log(error, &req);
13895|      0|                    }
13896|      0|                    return ret;
13897|      0|                  })
13898|    583|            : static_cast<ContentReceiverWithProgress>(
13899|    583|                  [&](const char *buf, size_t n, size_t /*off*/,
13900|    583|                      size_t /*len*/) {
13901|    583|                    assert(res.body.size() + n <= res.body.max_size());
13902|    583|                    if (payload_max_length_ > 0 &&
13903|    583|                        (res.body.size() >= payload_max_length_ ||
13904|    583|                         n > payload_max_length_ - res.body.size())) {
13905|    583|                      return false;
13906|    583|                    }
13907|    583|                    res.body.append(buf, n);
13908|    583|                    return true;
13909|    583|                  });
13910|       |
13911|    583|    auto progress = [&](size_t current, size_t total) {
13912|    583|      if (!req.download_progress || redirect) { return true; }
13913|    583|      auto ret = req.download_progress(current, total);
13914|    583|      if (!ret) {
13915|    583|        error = Error::Canceled;
13916|    583|        output_error_log(error, &req);
13917|    583|      }
13918|    583|      return ret;
13919|    583|    };
13920|       |
13921|    583|    if (res.has_header("Content-Length")) {
  ------------------
  |  Branch (13921:9): [True: 18, False: 565]
  ------------------
13922|     18|      if (!req.content_receiver) {
  ------------------
  |  Branch (13922:11): [True: 18, False: 0]
  ------------------
13923|     18|        auto len = res.get_header_value_u64("Content-Length");
13924|     18|        if (len > res.body.max_size()) {
  ------------------
  |  Branch (13924:13): [True: 1, False: 17]
  ------------------
13925|      1|          error = Error::Read;
13926|      1|          output_error_log(error, &req);
13927|      1|          return false;
13928|      1|        }
13929|       |        // Cap the reservation by payload_max_length_ to avoid OOM when a
13930|       |        // hostile or malformed server sends an enormous Content-Length.
13931|       |        // The actual body read below is bounded by payload_max_length_,
13932|       |        // so reserving more than that is never useful.
13933|     17|        auto reserve_len = static_cast<size_t>(len);
13934|     17|        if (payload_max_length_ > 0 && reserve_len > payload_max_length_) {
  ------------------
  |  Branch (13934:13): [True: 17, False: 0]
  |  Branch (13934:40): [True: 0, False: 17]
  ------------------
13935|      0|          reserve_len = payload_max_length_;
13936|      0|        }
13937|     17|        res.body.reserve(reserve_len);
13938|     17|      }
13939|     18|    }
13940|       |
13941|    582|    if (res.status != StatusCode::NotModified_304) {
  ------------------
  |  Branch (13941:9): [True: 581, False: 1]
  ------------------
13942|    581|      int dummy_status;
13943|    581|      auto max_length = (!has_payload_max_length_ && req.content_receiver)
  ------------------
  |  Branch (13943:26): [True: 581, False: 0]
  |  Branch (13943:54): [True: 0, False: 581]
  ------------------
13944|    581|                            ? (std::numeric_limits<size_t>::max)()
13945|    581|                            : payload_max_length_;
13946|    581|      if (!detail::read_content(strm, res, max_length, dummy_status,
  ------------------
  |  Branch (13946:11): [True: 227, False: 354]
  ------------------
13947|    581|                                std::move(progress), std::move(out),
13948|    581|                                decompress_)) {
13949|    227|        if (error != Error::Canceled) { error = Error::Read; }
  ------------------
  |  Branch (13949:13): [True: 227, False: 0]
  ------------------
13950|    227|        output_error_log(error, &req);
13951|    227|        return false;
13952|    227|      }
13953|    581|    }
13954|    582|  }
13955|       |
13956|       |  // Log
13957|    358|  output_log(req, res);
13958|       |
13959|    358|  return true;
13960|    586|}
_ZNK7httplib7Request10has_headerERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
 9754|  11.7k|inline bool Request::has_header(const std::string &key) const {
 9755|  11.7k|  return detail::has_header(headers, key);
 9756|  11.7k|}
_ZN7httplib6detail10has_headerERKNSt3__118unordered_multimapINS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEES8_NS0_11case_ignore4hashENS9_8equal_toENS6_INS1_4pairIKS8_S8_EEEEEERSD_:
 7016|  12.1k|inline bool has_header(const Headers &headers, const std::string &key) {
 7017|  12.1k|  if (is_prohibited_header_name(key)) { return false; }
  ------------------
  |  Branch (7017:7): [True: 0, False: 12.1k]
  ------------------
 7018|  12.1k|  return headers.find(key) != headers.end();
 7019|  12.1k|}
_ZN7httplib6detail25is_prohibited_header_nameERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
 7004|  15.2k|inline bool is_prohibited_header_name(const std::string &name) {
 7005|  15.2k|  using udl::operator""_t;
 7006|       |
 7007|  15.2k|  switch (str2tag(name)) {
 7008|      0|  case "REMOTE_ADDR"_t:
  ------------------
  |  Branch (7008:3): [True: 0, False: 15.2k]
  ------------------
 7009|      0|  case "REMOTE_PORT"_t:
  ------------------
  |  Branch (7009:3): [True: 0, False: 15.2k]
  ------------------
 7010|      0|  case "LOCAL_ADDR"_t:
  ------------------
  |  Branch (7010:3): [True: 0, False: 15.2k]
  ------------------
 7011|      0|  case "LOCAL_PORT"_t: return true;
  ------------------
  |  Branch (7011:3): [True: 0, False: 15.2k]
  ------------------
 7012|  15.2k|  default: return false;
  ------------------
  |  Branch (7012:3): [True: 15.2k, False: 0]
  ------------------
 7013|  15.2k|  }
 7014|  15.2k|}
_ZN7httplib6detail7str2tagERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
 6422|  15.2k|inline unsigned int str2tag(const std::string &s) {
 6423|       |  // Iterative form of str2tag_core: the recursive constexpr version is kept
 6424|       |  // for compile-time UDL evaluation of short string literals, but at runtime
 6425|       |  // we may receive arbitrarily long inputs (e.g. fuzzed Content-Type) that
 6426|       |  // would blow the stack with one frame per character.
 6427|  15.2k|  unsigned int h = 0;
 6428|   138k|  for (auto c : s) {
  ------------------
  |  Branch (6428:15): [True: 138k, False: 15.2k]
  ------------------
 6429|   138k|    h = (((std::numeric_limits<unsigned int>::max)() >> 6) & h * 33) ^
 6430|   138k|        static_cast<unsigned char>(c);
 6431|   138k|  }
 6432|  15.2k|  return h;
 6433|  15.2k|}
_ZNK7httplib6detail11case_ignore4hashclERKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEE:
  591|  44.7k|  size_t operator()(const std::string &key) const {
  592|  44.7k|    return hash_core(key.data(), key.size(), 0);
  593|  44.7k|  }
_ZNK7httplib6detail11case_ignore4hash9hash_coreEPKcmm:
  595|   726k|  size_t hash_core(const char *s, size_t l, size_t h) const {
  596|   726k|    return (l == 0) ? h
  ------------------
  |  Branch (596:12): [True: 44.7k, False: 682k]
  ------------------
  597|   726k|                    : hash_core(s + 1, l - 1,
  598|       |                                // Unsets the 6 high bits of h, therefore no
  599|       |                                // overflow happens
  600|   682k|                                (((std::numeric_limits<size_t>::max)() >> 6) &
  601|   682k|                                 h * 33) ^
  602|   682k|                                    static_cast<unsigned char>(to_lower(*s)));
  603|   726k|  }
_ZN7httplib6detail11case_ignore8to_lowerEi:
  545|  1.50M|inline unsigned char to_lower(int c) {
  546|  1.50M|  const static unsigned char table[256] = {
  547|  1.50M|      0,   1,   2,   3,   4,   5,   6,   7,   8,   9,   10,  11,  12,  13,  14,
  548|  1.50M|      15,  16,  17,  18,  19,  20,  21,  22,  23,  24,  25,  26,  27,  28,  29,
  549|  1.50M|      30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,  43,  44,
  550|  1.50M|      45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,
  551|  1.50M|      60,  61,  62,  63,  64,  97,  98,  99,  100, 101, 102, 103, 104, 105, 106,
  552|  1.50M|      107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121,
  553|  1.50M|      122, 91,  92,  93,  94,  95,  96,  97,  98,  99,  100, 101, 102, 103, 104,
  554|  1.50M|      105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
  555|  1.50M|      120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134,
  556|  1.50M|      135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
  557|  1.50M|      150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164,
  558|  1.50M|      165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179,
  559|  1.50M|      180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 224, 225, 226,
  560|  1.50M|      227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241,
  561|  1.50M|      242, 243, 244, 245, 246, 215, 248, 249, 250, 251, 252, 253, 254, 223, 224,
  562|  1.50M|      225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
  563|  1.50M|      240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254,
  564|  1.50M|      255,
  565|  1.50M|  };
  566|  1.50M|  return table[(unsigned char)(char)c];
  567|  1.50M|}
_ZNK7httplib6detail11case_ignore8equal_toclERKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEESB_:
  585|  92.1k|  bool operator()(const std::string &a, const std::string &b) const {
  586|  92.1k|    return equal(a, b);
  587|  92.1k|  }
_ZN7httplib6detail11case_ignore5equalERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEESA_:
  577|  92.5k|inline bool equal(const std::string &a, const std::string &b) {
  578|  92.5k|  return a.size() == b.size() &&
  ------------------
  |  Branch (578:10): [True: 91.9k, False: 664]
  ------------------
  579|  91.9k|         std::equal(a.begin(), a.end(), b.begin(), [](char ca, char cb) {
  ------------------
  |  Branch (579:10): [True: 91.7k, False: 155]
  ------------------
  580|  91.9k|           return to_lower(ca) == to_lower(cb);
  581|  91.9k|         });
  582|  92.5k|}
_ZZN7httplib6detail11case_ignore5equalERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEESA_ENKUlccE_clEcc:
  579|   412k|         std::equal(a.begin(), a.end(), b.begin(), [](char ca, char cb) {
  580|   412k|           return to_lower(ca) == to_lower(cb);
  581|   412k|         });
_ZN7httplib7Request10set_headerERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEES9_:
 9768|  5.24k|                                const std::string &val) {
 9769|  5.24k|  detail::set_header(headers, key, val);
 9770|  5.24k|}
_ZN7httplib6detail10set_headerERNSt3__118unordered_multimapINS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEES8_NS0_11case_ignore4hashENS9_8equal_toENS6_INS1_4pairIKS8_S8_EEEEEERSD_SI_:
 7057|  5.24k|                       const std::string &val) {
 7058|  5.24k|  if (fields::is_field_name(key) && fields::is_field_value(val)) {
  ------------------
  |  Branch (7058:7): [True: 5.24k, False: 0]
  |  Branch (7058:37): [True: 5.24k, False: 0]
  ------------------
 7059|  5.24k|    headers.emplace(key, val);
 7060|  5.24k|  }
 7061|  5.24k|}
_ZN7httplib6detail6fields13is_field_nameERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE:
 8727|  23.9k|inline bool is_field_name(const std::string &s) { return is_token(s); }
_ZN7httplib6detail6fields8is_tokenERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE:
 8719|  23.9k|inline bool is_token(const std::string &s) {
 8720|  23.9k|  if (s.empty()) { return false; }
  ------------------
  |  Branch (8720:7): [True: 13, False: 23.9k]
  ------------------
 8721|   379k|  for (auto c : s) {
  ------------------
  |  Branch (8721:15): [True: 379k, False: 23.7k]
  ------------------
 8722|   379k|    if (!is_token_char(c)) { return false; }
  ------------------
  |  Branch (8722:9): [True: 176, False: 379k]
  ------------------
 8723|   379k|  }
 8724|  23.7k|  return true;
 8725|  23.9k|}
_ZN7httplib6detail6fields13is_token_charEc:
 8713|   379k|inline bool is_token_char(char c) {
 8714|   379k|  return std::isalnum(c) || c == '!' || c == '#' || c == '$' || c == '%' ||
  ------------------
  |  Branch (8714:10): [True: 331k, False: 48.6k]
  |  Branch (8714:29): [True: 868, False: 47.8k]
  |  Branch (8714:41): [True: 2.47k, False: 45.3k]
  |  Branch (8714:53): [True: 484, False: 44.8k]
  |  Branch (8714:65): [True: 1.98k, False: 42.8k]
  ------------------
 8715|  42.8k|         c == '&' || c == '\'' || c == '*' || c == '+' || c == '-' ||
  ------------------
  |  Branch (8715:10): [True: 578, False: 42.2k]
  |  Branch (8715:22): [True: 2.27k, False: 40.0k]
  |  Branch (8715:35): [True: 14.6k, False: 25.3k]
  |  Branch (8715:47): [True: 5.34k, False: 20.0k]
  |  Branch (8715:59): [True: 13.4k, False: 6.52k]
  ------------------
 8716|  6.52k|         c == '.' || c == '^' || c == '_' || c == '`' || c == '|' || c == '~';
  ------------------
  |  Branch (8716:10): [True: 870, False: 5.65k]
  |  Branch (8716:22): [True: 2.40k, False: 3.24k]
  |  Branch (8716:34): [True: 421, False: 2.82k]
  |  Branch (8716:46): [True: 1.03k, False: 1.79k]
  |  Branch (8716:58): [True: 633, False: 1.16k]
  |  Branch (8716:70): [True: 986, False: 176]
  ------------------
 8717|   379k|}
_ZN7httplib6detail6fields14is_field_valueERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE:
 8760|  23.6k|inline bool is_field_value(const std::string &s) { return is_field_content(s); }
_ZN7httplib6detail6fields16is_field_contentERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE:
 8735|  23.6k|inline bool is_field_content(const std::string &s) {
 8736|  23.6k|  if (s.empty()) { return true; }
  ------------------
  |  Branch (8736:7): [True: 825, False: 22.7k]
  ------------------
 8737|       |
 8738|  22.7k|  if (s.size() == 1) {
  ------------------
  |  Branch (8738:7): [True: 3.23k, False: 19.5k]
  ------------------
 8739|  3.23k|    return is_field_vchar(s[0]);
 8740|  19.5k|  } else if (s.size() == 2) {
  ------------------
  |  Branch (8740:14): [True: 1.36k, False: 18.1k]
  ------------------
 8741|  1.36k|    return is_field_vchar(s[0]) && is_field_vchar(s[1]);
  ------------------
  |  Branch (8741:12): [True: 1.35k, False: 4]
  |  Branch (8741:36): [True: 1.35k, False: 1]
  ------------------
 8742|  18.1k|  } else {
 8743|  18.1k|    size_t i = 0;
 8744|       |
 8745|  18.1k|    if (!is_field_vchar(s[i])) { return false; }
  ------------------
  |  Branch (8745:9): [True: 1, False: 18.1k]
  ------------------
 8746|  18.1k|    i++;
 8747|       |
 8748|   744k|    while (i < s.size() - 1) {
  ------------------
  |  Branch (8748:12): [True: 726k, False: 18.1k]
  ------------------
 8749|   726k|      auto c = s[i++];
 8750|   726k|      if (c == ' ' || c == '\t' || is_field_vchar(c)) {
  ------------------
  |  Branch (8750:11): [True: 9.96k, False: 716k]
  |  Branch (8750:23): [True: 1.25k, False: 715k]
  |  Branch (8750:36): [True: 715k, False: 64]
  ------------------
 8751|   726k|      } else {
 8752|     64|        return false;
 8753|     64|      }
 8754|   726k|    }
 8755|       |
 8756|  18.1k|    return is_field_vchar(s[i]);
 8757|  18.1k|  }
 8758|  22.7k|}
_ZN7httplib6detail6fields14is_field_vcharEc:
 8733|   757k|inline bool is_field_vchar(char c) { return is_vchar(c) || is_obs_text(c); }
  ------------------
  |  Branch (8733:45): [True: 558k, False: 199k]
  |  Branch (8733:60): [True: 199k, False: 78]
  ------------------
_ZN7httplib6detail6fields8is_vcharEc:
 8729|   757k|inline bool is_vchar(char c) { return c >= 33 && c <= 126; }
  ------------------
  |  Branch (8729:39): [True: 558k, False: 199k]
  |  Branch (8729:50): [True: 558k, False: 2]
  ------------------
_ZN7httplib6detail6fields11is_obs_textEc:
 8731|   199k|inline bool is_obs_text(char c) { return 128 <= static_cast<unsigned char>(c); }
_ZNK7httplib7Request16get_header_valueERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEPKcm:
 9759|  1.96k|                                             const char *def, size_t id) const {
 9760|  1.96k|  return detail::get_header_value(headers, key, def, id);
 9761|  1.96k|}
_ZN7httplib6detail16get_header_valueERKNSt3__118unordered_multimapINS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEES8_NS0_11case_ignore4hashENS9_8equal_toENS6_INS1_4pairIKS8_S8_EEEEEERSD_PKcm:
 7023|  3.01k|                                    size_t id) {
 7024|  3.01k|  if (is_prohibited_header_name(key)) {
  ------------------
  |  Branch (7024:7): [True: 0, False: 3.01k]
  ------------------
 7025|      0|#ifndef CPPHTTPLIB_NO_EXCEPTIONS
 7026|      0|    std::string msg = "Prohibited header name '" + key + "' is specified.";
 7027|      0|    throw std::invalid_argument(msg);
 7028|       |#else
 7029|       |    return "";
 7030|       |#endif
 7031|      0|  }
 7032|       |
 7033|  3.01k|  auto rng = headers.equal_range(key);
 7034|  3.01k|  auto it = rng.first;
 7035|  3.01k|  std::advance(it, static_cast<ssize_t>(id));
 7036|  3.01k|  if (it != rng.second) { return it->second.c_str(); }
  ------------------
  |  Branch (7036:7): [True: 268, False: 2.75k]
  ------------------
 7037|  2.75k|  return def;
 7038|  3.01k|}
_ZN7httplib10ClientImpl13write_requestERNS_6StreamERNS_7RequestEbRNS_5ErrorEb:
13437|  1.96k|                                      bool skip_body) {
13438|       |  // Prepare additional headers
13439|  1.96k|  if (close_connection) {
  ------------------
  |  Branch (13439:7): [True: 0, False: 1.96k]
  ------------------
13440|      0|    if (!req.has_header("Connection")) {
  ------------------
  |  Branch (13440:9): [True: 0, False: 0]
  ------------------
13441|      0|      req.set_header("Connection", "close");
13442|      0|    }
13443|      0|  }
13444|       |
13445|  1.96k|  std::string ct_for_defaults;
13446|  1.96k|  if (!req.has_header("Content-Type") && !req.body.empty()) {
  ------------------
  |  Branch (13446:7): [True: 1.96k, False: 0]
  |  Branch (13446:7): [True: 0, False: 1.96k]
  |  Branch (13446:42): [True: 0, False: 1.96k]
  ------------------
13447|      0|    ct_for_defaults = "text/plain";
13448|      0|  }
13449|  1.96k|  prepare_default_headers(req, false, ct_for_defaults);
13450|       |
13451|  1.96k|  if (req.body.empty()) {
  ------------------
  |  Branch (13451:7): [True: 1.96k, False: 0]
  ------------------
13452|  1.96k|    if (req.content_provider_) {
  ------------------
  |  Branch (13452:9): [True: 0, False: 1.96k]
  ------------------
13453|      0|      if (!req.is_chunked_content_provider_) {
  ------------------
  |  Branch (13453:11): [True: 0, False: 0]
  ------------------
13454|      0|        if (!req.has_header("Content-Length")) {
  ------------------
  |  Branch (13454:13): [True: 0, False: 0]
  ------------------
13455|      0|          auto length = std::to_string(req.content_length_);
13456|      0|          req.set_header("Content-Length", length);
13457|      0|        }
13458|      0|      }
13459|  1.96k|    } else {
13460|  1.96k|      if (req.method == "POST" || req.method == "PUT" ||
  ------------------
  |  Branch (13460:11): [True: 564, False: 1.40k]
  |  Branch (13460:35): [True: 551, False: 849]
  ------------------
13461|  1.31k|          req.method == "PATCH") {
  ------------------
  |  Branch (13461:11): [True: 198, False: 651]
  ------------------
13462|  1.31k|        req.set_header("Content-Length", "0");
13463|  1.31k|      }
13464|  1.96k|    }
13465|  1.96k|  }
13466|       |
13467|  1.96k|  if (!basic_auth_password_.empty() || !basic_auth_username_.empty()) {
  ------------------
  |  Branch (13467:7): [True: 0, False: 1.96k]
  |  Branch (13467:40): [True: 0, False: 1.96k]
  ------------------
13468|      0|    if (!req.has_header("Authorization")) {
  ------------------
  |  Branch (13468:9): [True: 0, False: 0]
  ------------------
13469|      0|      req.headers.insert(make_basic_authentication_header(
13470|      0|          basic_auth_username_, basic_auth_password_, false));
13471|      0|    }
13472|      0|  }
13473|       |
13474|  1.96k|  if (!bearer_token_auth_token_.empty()) {
  ------------------
  |  Branch (13474:7): [True: 0, False: 1.96k]
  ------------------
13475|      0|    if (!req.has_header("Authorization")) {
  ------------------
  |  Branch (13475:9): [True: 0, False: 0]
  ------------------
13476|      0|      req.headers.insert(make_bearer_token_authentication_header(
13477|      0|          bearer_token_auth_token_, false));
13478|      0|    }
13479|      0|  }
13480|       |
13481|       |  // Proxy-Authorization is only sent when the proxy is actually used for
13482|       |  // this target — otherwise NO_PROXY-matched requests would leak proxy
13483|       |  // credentials directly to the destination server.
13484|  1.96k|  if (is_proxy_enabled_for_host(host_)) {
  ------------------
  |  Branch (13484:7): [True: 0, False: 1.96k]
  ------------------
13485|      0|    if (!proxy_basic_auth_username_.empty() &&
  ------------------
  |  Branch (13485:9): [True: 0, False: 0]
  |  Branch (13485:9): [True: 0, False: 0]
  ------------------
13486|      0|        !proxy_basic_auth_password_.empty() &&
  ------------------
  |  Branch (13486:9): [True: 0, False: 0]
  ------------------
13487|      0|        !req.has_header("Proxy-Authorization")) {
  ------------------
  |  Branch (13487:9): [True: 0, False: 0]
  ------------------
13488|      0|      req.headers.insert(make_basic_authentication_header(
13489|      0|          proxy_basic_auth_username_, proxy_basic_auth_password_, true));
13490|      0|    }
13491|      0|    if (!proxy_bearer_token_auth_token_.empty() &&
  ------------------
  |  Branch (13491:9): [True: 0, False: 0]
  |  Branch (13491:9): [True: 0, False: 0]
  ------------------
13492|      0|        !req.has_header("Proxy-Authorization")) {
  ------------------
  |  Branch (13492:9): [True: 0, False: 0]
  ------------------
13493|      0|      req.headers.insert(make_bearer_token_authentication_header(
13494|      0|          proxy_bearer_token_auth_token_, true));
13495|      0|    }
13496|      0|  }
13497|       |
13498|       |  // Request line and headers
13499|  1.96k|  {
13500|  1.96k|    detail::BufferStream bstrm;
13501|       |
13502|       |    // Extract path and query from req.path
13503|  1.96k|    std::string path_part, query_part;
13504|  1.96k|    auto query_pos = req.path.find('?');
13505|  1.96k|    if (query_pos != std::string::npos) {
  ------------------
  |  Branch (13505:9): [True: 0, False: 1.96k]
  ------------------
13506|      0|      path_part = req.path.substr(0, query_pos);
13507|      0|      query_part = req.path.substr(query_pos + 1);
13508|  1.96k|    } else {
13509|  1.96k|      path_part = req.path;
13510|  1.96k|      query_part = "";
13511|  1.96k|    }
13512|       |
13513|       |    // Encode path part. If the original `req.path` already contained a
13514|       |    // query component, preserve its raw query string (including parameter
13515|       |    // order) instead of reparsing and reassembling it which may reorder
13516|       |    // parameters due to container ordering (e.g. `Params` uses
13517|       |    // `std::multimap`). When there is no query in `req.path`, fall back to
13518|       |    // building a query from `req.params` so existing callers that pass
13519|       |    // `Params` continue to work.
13520|  1.96k|    auto path_with_query =
13521|  1.96k|        path_encode_ ? detail::encode_path(path_part) : path_part;
  ------------------
  |  Branch (13521:9): [True: 1.96k, False: 0]
  ------------------
13522|       |
13523|  1.96k|    if (!query_part.empty()) {
  ------------------
  |  Branch (13523:9): [True: 0, False: 1.96k]
  ------------------
13524|       |      // Normalize the query string (decode then re-encode) while preserving
13525|       |      // the original parameter order.
13526|      0|      auto normalized = detail::normalize_query_string(query_part);
13527|      0|      if (!normalized.empty()) { path_with_query += '?' + normalized; }
  ------------------
  |  Branch (13527:11): [True: 0, False: 0]
  ------------------
13528|       |
13529|       |      // Still populate req.params for handlers/users who read them.
13530|      0|      detail::parse_query_text(query_part, req.params);
13531|  1.96k|    } else {
13532|       |      // No query in path; parse any query_part (empty) and append params
13533|       |      // from `req.params` when present (preserves prior behavior for
13534|       |      // callers who provide Params separately).
13535|  1.96k|      detail::parse_query_text(query_part, req.params);
13536|  1.96k|      if (!req.params.empty()) {
  ------------------
  |  Branch (13536:11): [True: 0, False: 1.96k]
  ------------------
13537|      0|        path_with_query = append_query_params(path_with_query, req.params);
13538|      0|      }
13539|  1.96k|    }
13540|       |
13541|       |    // Write request line and headers
13542|  1.96k|    detail::write_request_line(bstrm, req.method, path_with_query);
13543|  1.96k|    if (!detail::check_and_write_headers(bstrm, req.headers, header_writer_,
  ------------------
  |  Branch (13543:9): [True: 0, False: 1.96k]
  ------------------
13544|  1.96k|                                         error)) {
13545|      0|      output_error_log(error, &req);
13546|      0|      return false;
13547|      0|    }
13548|       |
13549|       |    // Flush buffer
13550|  1.96k|    auto &data = bstrm.get_buffer();
13551|  1.96k|    if (!detail::write_data(strm, data.data(), data.size())) {
  ------------------
  |  Branch (13551:9): [True: 0, False: 1.96k]
  ------------------
13552|      0|      error = Error::Write;
13553|      0|      output_error_log(error, &req);
13554|      0|      return false;
13555|      0|    }
13556|  1.96k|  }
13557|       |
13558|       |  // After sending request line and headers, wait briefly for an early server
13559|       |  // response (e.g. 4xx) and avoid sending a potentially large request body
13560|       |  // unnecessarily. This workaround is only enabled on Windows because Unix
13561|       |  // platforms surface write errors (EPIPE) earlier; on Windows kernel send
13562|       |  // buffering can accept large writes even when the peer already responded.
13563|       |  // Check the stream first (which covers SSL via `is_readable()`), then
13564|       |  // fall back to select on the socket. Only perform the wait for very large
13565|       |  // request bodies to avoid interfering with normal small requests and
13566|       |  // reduce side-effects. Poll briefly (up to 50ms as default) for an early
13567|       |  // response. Skip this check when using Expect: 100-continue, as the protocol
13568|       |  // handles early responses properly.
13569|       |#if defined(_WIN32)
13570|       |  if (!skip_body &&
13571|       |      req.body.size() > CPPHTTPLIB_WAIT_EARLY_SERVER_RESPONSE_THRESHOLD &&
13572|       |      req.path.size() > CPPHTTPLIB_REQUEST_URI_MAX_LENGTH) {
13573|       |    auto start = std::chrono::high_resolution_clock::now();
13574|       |
13575|       |    for (;;) {
13576|       |      // Prefer socket-level readiness to avoid SSL_pending() false-positives
13577|       |      // from SSL internals. If the underlying socket is readable, assume an
13578|       |      // early response may be present.
13579|       |      auto sock = strm.socket();
13580|       |      if (sock != INVALID_SOCKET && detail::select_read(sock, 0, 0) > 0) {
13581|       |        return false;
13582|       |      }
13583|       |
13584|       |      // Fallback to stream-level check for non-socket streams or when the
13585|       |      // socket isn't reporting readable. Avoid using `is_readable()` for
13586|       |      // SSL, since `SSL_pending()` may report buffered records that do not
13587|       |      // indicate a complete application-level response yet.
13588|       |      if (!is_ssl() && strm.is_readable()) { return false; }
13589|       |
13590|       |      auto now = std::chrono::high_resolution_clock::now();
13591|       |      auto elapsed =
13592|       |          std::chrono::duration_cast<std::chrono::milliseconds>(now - start)
13593|       |              .count();
13594|       |      if (elapsed >= CPPHTTPLIB_WAIT_EARLY_SERVER_RESPONSE_TIMEOUT_MSECOND) {
13595|       |        break;
13596|       |      }
13597|       |
13598|       |      std::this_thread::sleep_for(std::chrono::milliseconds(1));
13599|       |    }
13600|       |  }
13601|       |#endif
13602|       |
13603|       |  // Body
13604|  1.96k|  if (skip_body) { return true; }
  ------------------
  |  Branch (13604:7): [True: 0, False: 1.96k]
  ------------------
13605|       |
13606|  1.96k|  return write_request_body(strm, req, error);
13607|  1.96k|}
_ZN7httplib10ClientImpl23prepare_default_headersERNS_7RequestEbRKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEE:
12796|  1.96k|                                                const std::string &ct) {
12797|  1.96k|  (void)for_stream;
12798|  1.96k|  for (const auto &header : default_headers_) {
  ------------------
  |  Branch (12798:27): [True: 0, False: 1.96k]
  ------------------
12799|      0|    if (!r.has_header(header.first)) { r.headers.insert(header); }
  ------------------
  |  Branch (12799:9): [True: 0, False: 0]
  ------------------
12800|      0|  }
12801|       |
12802|  1.96k|  if (!r.has_header("Host")) {
  ------------------
  |  Branch (12802:7): [True: 1.96k, False: 0]
  ------------------
12803|  1.96k|    if (address_family_ == AF_UNIX) {
  ------------------
  |  Branch (12803:9): [True: 0, False: 1.96k]
  ------------------
12804|      0|      r.headers.emplace("Host", "localhost");
12805|  1.96k|    } else {
12806|  1.96k|      r.headers.emplace(
12807|  1.96k|          "Host", detail::make_host_and_port_string(host_, port_, is_ssl()));
12808|  1.96k|    }
12809|  1.96k|  }
12810|       |
12811|  1.96k|  if (!r.has_header("Accept")) { r.headers.emplace("Accept", "*/*"); }
  ------------------
  |  Branch (12811:7): [True: 1.96k, False: 0]
  ------------------
12812|       |
12813|  1.96k|  if (!r.content_receiver) {
  ------------------
  |  Branch (12813:7): [True: 1.96k, False: 0]
  ------------------
12814|  1.96k|    if (!r.has_header("Accept-Encoding")) {
  ------------------
  |  Branch (12814:9): [True: 1.96k, False: 0]
  ------------------
12815|  1.96k|      std::string accept_encoding;
12816|       |#ifdef CPPHTTPLIB_BROTLI_SUPPORT
12817|       |      accept_encoding = "br";
12818|       |#endif
12819|  1.96k|#ifdef CPPHTTPLIB_ZLIB_SUPPORT
12820|  1.96k|      if (!accept_encoding.empty()) { accept_encoding += ", "; }
  ------------------
  |  Branch (12820:11): [True: 0, False: 1.96k]
  ------------------
12821|  1.96k|      accept_encoding += "gzip, deflate";
12822|  1.96k|#endif
12823|       |#ifdef CPPHTTPLIB_ZSTD_SUPPORT
12824|       |      if (!accept_encoding.empty()) { accept_encoding += ", "; }
12825|       |      accept_encoding += "zstd";
12826|       |#endif
12827|  1.96k|      r.set_header("Accept-Encoding", accept_encoding);
12828|  1.96k|    }
12829|       |
12830|  1.96k|#ifndef CPPHTTPLIB_NO_DEFAULT_USER_AGENT
12831|  1.96k|    if (!r.has_header("User-Agent")) {
  ------------------
  |  Branch (12831:9): [True: 1.96k, False: 0]
  ------------------
12832|  1.96k|      auto agent = std::string("cpp-httplib/") + CPPHTTPLIB_VERSION;
  ------------------
  |  |   11|  1.96k|#define CPPHTTPLIB_VERSION "0.46.0"
  ------------------
12833|  1.96k|      r.set_header("User-Agent", agent);
12834|  1.96k|    }
12835|  1.96k|#endif
12836|  1.96k|  }
12837|       |
12838|  1.96k|  if (!r.body.empty()) {
  ------------------
  |  Branch (12838:7): [True: 0, False: 1.96k]
  ------------------
12839|      0|    if (!ct.empty() && !r.has_header("Content-Type")) {
  ------------------
  |  Branch (12839:9): [True: 0, False: 0]
  |  Branch (12839:9): [True: 0, False: 0]
  |  Branch (12839:24): [True: 0, False: 0]
  ------------------
12840|      0|      r.headers.emplace("Content-Type", ct);
12841|      0|    }
12842|      0|    if (!r.has_header("Content-Length")) {
  ------------------
  |  Branch (12842:9): [True: 0, False: 0]
  ------------------
12843|      0|      r.headers.emplace("Content-Length", std::to_string(r.body.size()));
12844|      0|    }
12845|      0|  }
12846|  1.96k|}
_ZN7httplib6detail25make_host_and_port_stringERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEib:
10532|  1.96k|                                             bool is_ssl) {
10533|  1.96k|  auto result = prepare_host_string(host);
10534|       |
10535|       |  // Append port if not default
10536|  1.96k|  if ((!is_ssl && port == 80) || (is_ssl && port == 443)) {
  ------------------
  |  Branch (10536:8): [True: 1.96k, False: 0]
  |  Branch (10536:19): [True: 0, False: 1.96k]
  |  Branch (10536:35): [True: 0, False: 1.96k]
  |  Branch (10536:45): [True: 0, False: 0]
  ------------------
10537|      0|    ; // do nothing
10538|  1.96k|  } else {
10539|  1.96k|    result += ":" + std::to_string(port);
10540|  1.96k|  }
10541|       |
10542|  1.96k|  return result;
10543|  1.96k|}
_ZN7httplib6detail19prepare_host_stringERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
10519|  1.96k|inline std::string prepare_host_string(const std::string &host) {
10520|       |  // Enclose IPv6 address in brackets (but not if already enclosed)
10521|  1.96k|  if (host.find(':') == std::string::npos ||
  ------------------
  |  Branch (10521:7): [True: 1.96k, False: 0]
  ------------------
10522|  1.96k|      (!host.empty() && host[0] == '[')) {
  ------------------
  |  Branch (10522:8): [True: 0, False: 0]
  |  Branch (10522:25): [True: 0, False: 0]
  ------------------
10523|       |    // IPv4, hostname, or already bracketed IPv6
10524|  1.96k|    return host;
10525|  1.96k|  } else {
10526|       |    // IPv6 address without brackets
10527|      0|    return "[" + host + "]";
10528|      0|  }
10529|  1.96k|}
_ZNK7httplib10ClientImpl25is_proxy_enabled_for_hostERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
12543|  1.96k|ClientImpl::is_proxy_enabled_for_host(const std::string &host) const {
12544|  1.96k|  if (proxy_host_.empty() || proxy_port_ == -1) { return false; }
  ------------------
  |  Branch (12544:7): [True: 1.96k, False: 0]
  |  Branch (12544:30): [True: 0, False: 0]
  ------------------
12545|      0|  if (no_proxy_entries_.empty()) { return true; }
  ------------------
  |  Branch (12545:7): [True: 0, False: 0]
  ------------------
12546|       |  // host_ is const so its normalized form is invariant; cache it. The
12547|       |  // cross-host path (setup_redirect_client passing next_host) re-normalizes.
12548|      0|  if (host == host_) {
  ------------------
  |  Branch (12548:7): [True: 0, False: 0]
  ------------------
12549|      0|    if (!host_normalized_valid_) {
  ------------------
  |  Branch (12549:9): [True: 0, False: 0]
  ------------------
12550|      0|      host_normalized_ = detail::normalize_target(host_);
12551|      0|      host_normalized_valid_ = true;
12552|      0|    }
12553|      0|    return !detail::host_matches_no_proxy(host_normalized_, no_proxy_entries_);
12554|      0|  }
12555|      0|  auto target = detail::normalize_target(host);
12556|      0|  return !detail::host_matches_no_proxy(target, no_proxy_entries_);
12557|      0|}
_ZN7httplib6detail12BufferStreamC2Ev:
 3086|  1.96k|  BufferStream() = default;
_ZN7httplib6detail11encode_pathERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
 4984|  1.96k|inline std::string encode_path(const std::string &s) {
 4985|  1.96k|  std::string result;
 4986|  1.96k|  result.reserve(s.size());
 4987|       |
 4988|  3.92k|  for (size_t i = 0; s[i]; i++) {
  ------------------
  |  Branch (4988:22): [True: 1.96k, False: 1.96k]
  ------------------
 4989|  1.96k|    switch (s[i]) {
 4990|      0|    case ' ': result += "%20"; break;
  ------------------
  |  Branch (4990:5): [True: 0, False: 1.96k]
  ------------------
 4991|      0|    case '+': result += "%2B"; break;
  ------------------
  |  Branch (4991:5): [True: 0, False: 1.96k]
  ------------------
 4992|      0|    case '\r': result += "%0D"; break;
  ------------------
  |  Branch (4992:5): [True: 0, False: 1.96k]
  ------------------
 4993|      0|    case '\n': result += "%0A"; break;
  ------------------
  |  Branch (4993:5): [True: 0, False: 1.96k]
  ------------------
 4994|      0|    case '\'': result += "%27"; break;
  ------------------
  |  Branch (4994:5): [True: 0, False: 1.96k]
  ------------------
 4995|      0|    case ',': result += "%2C"; break;
  ------------------
  |  Branch (4995:5): [True: 0, False: 1.96k]
  ------------------
 4996|       |    // case ':': result += "%3A"; break; // ok? probably...
 4997|      0|    case ';': result += "%3B"; break;
  ------------------
  |  Branch (4997:5): [True: 0, False: 1.96k]
  ------------------
 4998|  1.96k|    default:
  ------------------
  |  Branch (4998:5): [True: 1.96k, False: 0]
  ------------------
 4999|  1.96k|      auto c = static_cast<uint8_t>(s[i]);
 5000|  1.96k|      if (c >= 0x80) {
  ------------------
  |  Branch (5000:11): [True: 0, False: 1.96k]
  ------------------
 5001|      0|        result += '%';
 5002|      0|        char hex[4];
 5003|      0|        auto len = snprintf(hex, sizeof(hex) - 1, "%02X", c);
 5004|      0|        assert(len == 2);
  ------------------
  |  Branch (5004:9): [True: 0, False: 0]
  ------------------
 5005|      0|        result.append(hex, static_cast<size_t>(len));
 5006|  1.96k|      } else {
 5007|  1.96k|        result += s[i];
 5008|  1.96k|      }
 5009|  1.96k|      break;
 5010|  1.96k|    }
 5011|  1.96k|  }
 5012|       |
 5013|  1.96k|  return result;
 5014|  1.96k|}
_ZN7httplib6detail5splitEPKcS2_cNSt3__18functionIFvS2_S2_EEE:
 5212|  1.96k|                  std::function<void(const char *, const char *)> fn) {
 5213|  1.96k|  return split(b, e, d, (std::numeric_limits<size_t>::max)(), std::move(fn));
 5214|  1.96k|}
_ZN7httplib6detail5splitEPKcS2_cmNSt3__18functionIFvS2_S2_EEE:
 5217|  1.96k|                  std::function<void(const char *, const char *)> fn) {
 5218|  1.96k|  size_t i = 0;
 5219|  1.96k|  size_t beg = 0;
 5220|  1.96k|  size_t count = 1;
 5221|       |
 5222|  1.96k|  while (e ? (b + i < e) : (b[i] != '\0')) {
  ------------------
  |  Branch (5222:10): [True: 1.96k, False: 0]
  |  Branch (5222:10): [True: 0, False: 1.96k]
  ------------------
 5223|      0|    if (b[i] == d && count < m) {
  ------------------
  |  Branch (5223:9): [True: 0, False: 0]
  |  Branch (5223:22): [True: 0, False: 0]
  ------------------
 5224|      0|      auto r = trim(b, e, beg, i);
 5225|      0|      if (r.first < r.second) { fn(&b[r.first], &b[r.second]); }
  ------------------
  |  Branch (5225:11): [True: 0, False: 0]
  ------------------
 5226|      0|      beg = i + 1;
 5227|      0|      count++;
 5228|      0|    }
 5229|      0|    i++;
 5230|      0|  }
 5231|       |
 5232|  1.96k|  if (i) {
  ------------------
  |  Branch (5232:7): [True: 0, False: 1.96k]
  ------------------
 5233|      0|    auto r = trim(b, e, beg, i);
 5234|      0|    if (r.first < r.second) { fn(&b[r.first], &b[r.second]); }
  ------------------
  |  Branch (5234:9): [True: 0, False: 0]
  ------------------
 5235|      0|  }
 5236|  1.96k|}
_ZN7httplib6detail15is_space_or_tabEc:
 5023|  19.1k|inline bool is_space_or_tab(char c) { return c == ' ' || c == '\t'; }
  ------------------
  |  Branch (5023:46): [True: 945, False: 18.1k]
  |  Branch (5023:58): [True: 208, False: 17.9k]
  ------------------
_ZN7httplib6detail16parse_query_textERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEERNS1_8multimapIS7_S7_NS1_4lessIS7_EENS5_INS1_4pairIS8_S7_EEEEEE:
 7712|  1.96k|inline void parse_query_text(const std::string &s, Params &params) {
 7713|  1.96k|  parse_query_text(s.data(), s.size(), params);
 7714|  1.96k|}
_ZN7httplib6detail16parse_query_textEPKcmRNSt3__18multimapINS3_12basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEESA_NS3_4lessISA_EENS8_INS3_4pairIKSA_SA_EEEEEE:
 7690|  1.96k|                             Params &params) {
 7691|  1.96k|  std::set<std::string> cache;
 7692|  1.96k|  split(data, data + size, '&', [&](const char *b, const char *e) {
 7693|  1.96k|    std::string kv(b, e);
 7694|  1.96k|    if (cache.find(kv) != cache.end()) { return; }
 7695|  1.96k|    cache.insert(std::move(kv));
 7696|       |
 7697|  1.96k|    std::string key;
 7698|  1.96k|    std::string val;
 7699|  1.96k|    divide(b, static_cast<std::size_t>(e - b), '=',
 7700|  1.96k|           [&](const char *lhs_data, std::size_t lhs_size, const char *rhs_data,
 7701|  1.96k|               std::size_t rhs_size) {
 7702|  1.96k|             key.assign(lhs_data, lhs_size);
 7703|  1.96k|             val.assign(rhs_data, rhs_size);
 7704|  1.96k|           });
 7705|       |
 7706|  1.96k|    if (!key.empty()) {
 7707|  1.96k|      params.emplace(decode_query_component(key), decode_query_component(val));
 7708|  1.96k|    }
 7709|  1.96k|  });
 7710|  1.96k|}
_ZN7httplib6detail18write_request_lineERNS_6StreamERKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEESB_:
 7384|  1.96k|                                  const std::string &path) {
 7385|  1.96k|  std::string s = method;
 7386|  1.96k|  s += ' ';
 7387|  1.96k|  s += path;
 7388|  1.96k|  s += " HTTP/1.1\r\n";
 7389|  1.96k|  return strm.write(s.data(), s.size());
 7390|  1.96k|}
_ZN7httplib6detail23check_and_write_headersINSt3__18functionIFlRNS_6StreamERNS2_18unordered_multimapINS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEESC_NS0_11case_ignore4hashENSD_8equal_toENSA_INS2_4pairIKSC_SC_EEEEEEEEEEEbS5_SL_T_RNS_5ErrorE:
10723|  1.96k|                                    T header_writer, Error &error) {
10724|  9.16k|  for (const auto &h : headers) {
  ------------------
  |  Branch (10724:22): [True: 9.16k, False: 1.96k]
  ------------------
10725|  9.16k|    if (!detail::fields::is_field_name(h.first) ||
  ------------------
  |  Branch (10725:9): [True: 0, False: 9.16k]
  ------------------
10726|  9.16k|        !detail::fields::is_field_value(h.second)) {
  ------------------
  |  Branch (10726:9): [True: 0, False: 9.16k]
  ------------------
10727|      0|      error = Error::InvalidHeaders;
10728|      0|      return false;
10729|      0|    }
10730|  9.16k|  }
10731|  1.96k|  if (header_writer(strm, headers) <= 0) {
  ------------------
  |  Branch (10731:7): [True: 0, False: 1.96k]
  ------------------
10732|      0|    error = Error::Write;
10733|      0|    return false;
10734|      0|  }
10735|  1.96k|  return true;
10736|  1.96k|}
_ZNK7httplib6detail12BufferStream10get_bufferEv:
10419|  1.96k|inline const std::string &BufferStream::get_buffer() const { return buffer; }
_ZN7httplib6detail10write_dataERNS_6StreamEPKcm:
 7420|  1.96k|inline bool write_data(Stream &strm, const char *d, size_t l) {
 7421|  1.96k|  size_t offset = 0;
 7422|  3.92k|  while (offset < l) {
  ------------------
  |  Branch (7422:10): [True: 1.96k, False: 1.96k]
  ------------------
 7423|  1.96k|    auto length = strm.write(d + offset, l - offset);
 7424|  1.96k|    if (length < 0) { return false; }
  ------------------
  |  Branch (7424:9): [True: 0, False: 1.96k]
  ------------------
 7425|  1.96k|    offset += static_cast<size_t>(length);
 7426|  1.96k|  }
 7427|  1.96k|  return true;
 7428|  1.96k|}
_ZNK7httplib10ClientImpl18read_response_lineERNS_6StreamERKNS_7RequestERNS_8ResponseEb:
12640|  1.96k|                                           bool skip_100_continue) const {
12641|  1.96k|  std::array<char, 2048> buf{};
12642|       |
12643|  1.96k|  detail::stream_line_reader line_reader(strm, buf.data(), buf.size());
12644|       |
12645|  1.96k|  if (!line_reader.getline()) { return false; }
  ------------------
  |  Branch (12645:7): [True: 7, False: 1.95k]
  ------------------
12646|       |
12647|       |#ifdef CPPHTTPLIB_ALLOW_LF_AS_LINE_TERMINATOR
12648|       |  thread_local const std::regex re("(HTTP/1\\.[01]) (\\d{3})(?: (.*?))?\r?\n");
12649|       |#else
12650|  1.95k|  thread_local const std::regex re("(HTTP/1\\.[01]) (\\d{3})(?: (.*?))?\r\n");
12651|  1.95k|#endif
12652|       |
12653|  1.95k|  std::cmatch m;
12654|  1.95k|  if (!std::regex_match(line_reader.ptr(), m, re)) {
  ------------------
  |  Branch (12654:7): [True: 210, False: 1.74k]
  ------------------
12655|    210|    return req.method == "CONNECT";
12656|    210|  }
12657|  1.74k|  res.version = std::string(m[1]);
12658|  1.74k|  res.status = std::stoi(std::string(m[2]));
12659|  1.74k|  res.reason = std::string(m[3]);
12660|       |
12661|       |  // Ignore '100 Continue' (only when not using Expect: 100-continue explicitly)
12662|  6.68k|  while (skip_100_continue && res.status == StatusCode::Continue_100) {
  ------------------
  |  Branch (12662:10): [True: 6.68k, False: 0]
  |  Branch (12662:31): [True: 5.04k, False: 1.64k]
  ------------------
12663|  5.04k|    if (!line_reader.getline()) { return false; } // CRLF
  ------------------
  |  Branch (12663:9): [True: 7, False: 5.04k]
  ------------------
12664|  5.04k|    if (!line_reader.getline()) { return false; } // next response line
  ------------------
  |  Branch (12664:9): [True: 12, False: 5.02k]
  ------------------
12665|       |
12666|  5.02k|    if (!std::regex_match(line_reader.ptr(), m, re)) { return false; }
  ------------------
  |  Branch (12666:9): [True: 87, False: 4.94k]
  ------------------
12667|  4.94k|    res.version = std::string(m[1]);
12668|  4.94k|    res.status = std::stoi(std::string(m[2]));
12669|  4.94k|    res.reason = std::string(m[3]);
12670|  4.94k|  }
12671|       |
12672|  1.64k|  return true;
12673|  1.74k|}
_ZN7httplib6detail18stream_line_readerC2ERNS_6StreamEPcm:
 5276|  3.69k|    : strm_(strm), fixed_buffer_(fixed_buffer),
 5277|  3.69k|      fixed_buffer_size_(fixed_buffer_size) {}
_ZN7httplib6detail18stream_line_reader7getlineEv:
 5300|  23.4k|inline bool stream_line_reader::getline() {
 5301|  23.4k|  fixed_buffer_used_size_ = 0;
 5302|  23.4k|  growable_buffer_.clear();
 5303|       |
 5304|  23.4k|#ifndef CPPHTTPLIB_ALLOW_LF_AS_LINE_TERMINATOR
 5305|  23.4k|  char prev_byte = 0;
 5306|  23.4k|#endif
 5307|       |
 5308|  2.12M|  for (size_t i = 0;; i++) {
 5309|  2.12M|    if (size() >= CPPHTTPLIB_MAX_LINE_LENGTH) {
  ------------------
  |  |  189|  2.12M|#define CPPHTTPLIB_MAX_LINE_LENGTH 32768
  ------------------
  |  Branch (5309:9): [True: 3, False: 2.12M]
  ------------------
 5310|       |      // Treat exceptionally long lines as an error to
 5311|       |      // prevent infinite loops/memory exhaustion
 5312|      3|      return false;
 5313|      3|    }
 5314|  2.12M|    char byte;
 5315|  2.12M|    auto n = strm_.read(&byte, 1);
 5316|       |
 5317|  2.12M|    if (n < 0) {
  ------------------
  |  Branch (5317:9): [True: 0, False: 2.12M]
  ------------------
 5318|      0|      return false;
 5319|  2.12M|    } else if (n == 0) {
  ------------------
  |  Branch (5319:16): [True: 1.50k, False: 2.12M]
  ------------------
 5320|  1.50k|      if (i == 0) {
  ------------------
  |  Branch (5320:11): [True: 679, False: 823]
  ------------------
 5321|    679|        return false;
 5322|    823|      } else {
 5323|    823|        break;
 5324|    823|      }
 5325|  1.50k|    }
 5326|       |
 5327|  2.12M|    append(byte);
 5328|       |
 5329|       |#ifdef CPPHTTPLIB_ALLOW_LF_AS_LINE_TERMINATOR
 5330|       |    if (byte == '\n') { break; }
 5331|       |#else
 5332|  2.12M|    if (prev_byte == '\r' && byte == '\n') { break; }
  ------------------
  |  Branch (5332:9): [True: 55.2k, False: 2.07M]
  |  Branch (5332:30): [True: 21.9k, False: 33.2k]
  ------------------
 5333|  2.10M|    prev_byte = byte;
 5334|  2.10M|#endif
 5335|  2.10M|  }
 5336|       |
 5337|  22.7k|  return true;
 5338|  23.4k|}
_ZNK7httplib6detail18stream_line_reader4sizeEv:
 5287|  2.17M|inline size_t stream_line_reader::size() const {
 5288|  2.17M|  if (growable_buffer_.empty()) {
  ------------------
  |  Branch (5288:7): [True: 1.36M, False: 807k]
  ------------------
 5289|  1.36M|    return fixed_buffer_used_size_;
 5290|  1.36M|  } else {
 5291|   807k|    return growable_buffer_.size();
 5292|   807k|  }
 5293|  2.17M|}
_ZN7httplib6detail18stream_line_reader6appendEc:
 5340|  2.12M|inline void stream_line_reader::append(char c) {
 5341|  2.12M|  if (fixed_buffer_used_size_ < fixed_buffer_size_ - 1) {
  ------------------
  |  Branch (5341:7): [True: 1.31M, False: 806k]
  ------------------
 5342|  1.31M|    fixed_buffer_[fixed_buffer_used_size_++] = c;
 5343|  1.31M|    fixed_buffer_[fixed_buffer_used_size_] = '\0';
 5344|  1.31M|  } else {
 5345|   806k|    if (growable_buffer_.empty()) {
  ------------------
  |  Branch (5345:9): [True: 266, False: 806k]
  ------------------
 5346|    266|      assert(fixed_buffer_[fixed_buffer_used_size_] == '\0');
  ------------------
  |  Branch (5346:7): [True: 266, False: 0]
  ------------------
 5347|    266|      growable_buffer_.assign(fixed_buffer_, fixed_buffer_used_size_);
 5348|    266|    }
 5349|   806k|    growable_buffer_ += c;
 5350|   806k|  }
 5351|  2.12M|}
_ZNK7httplib6detail18stream_line_reader3ptrEv:
 5279|  36.7k|inline const char *stream_line_reader::ptr() const {
 5280|  36.7k|  if (growable_buffer_.empty()) {
  ------------------
  |  Branch (5280:7): [True: 36.1k, False: 588]
  ------------------
 5281|  36.1k|    return fixed_buffer_;
 5282|  36.1k|  } else {
 5283|    588|    return growable_buffer_.data();
 5284|    588|  }
 5285|  36.7k|}
_ZN7httplib10ClientImpl18write_request_bodyERNS_6StreamERNS_7RequestERNS_5ErrorE:
13610|  1.96k|                                           Error &error) {
13611|  1.96k|  if (req.body.empty()) {
  ------------------
  |  Branch (13611:7): [True: 1.96k, False: 0]
  ------------------
13612|  1.96k|    return write_content_with_provider(strm, req, error);
13613|  1.96k|  }
13614|       |
13615|      0|  if (req.upload_progress) {
  ------------------
  |  Branch (13615:7): [True: 0, False: 0]
  ------------------
13616|      0|    auto body_size = req.body.size();
13617|      0|    size_t written = 0;
13618|      0|    auto data = req.body.data();
13619|       |
13620|      0|    while (written < body_size) {
  ------------------
  |  Branch (13620:12): [True: 0, False: 0]
  ------------------
13621|      0|      size_t to_write = (std::min)(CPPHTTPLIB_SEND_BUFSIZ, body_size - written);
  ------------------
  |  |  154|      0|#define CPPHTTPLIB_SEND_BUFSIZ size_t(16384u)
  ------------------
13622|      0|      if (!detail::write_data(strm, data + written, to_write)) {
  ------------------
  |  Branch (13622:11): [True: 0, False: 0]
  ------------------
13623|      0|        error = Error::Write;
13624|      0|        output_error_log(error, &req);
13625|      0|        return false;
13626|      0|      }
13627|      0|      written += to_write;
13628|       |
13629|      0|      if (!req.upload_progress(written, body_size)) {
  ------------------
  |  Branch (13629:11): [True: 0, False: 0]
  ------------------
13630|      0|        error = Error::Canceled;
13631|      0|        output_error_log(error, &req);
13632|      0|        return false;
13633|      0|      }
13634|      0|    }
13635|      0|  } else {
13636|      0|    if (!detail::write_data(strm, req.body.data(), req.body.size())) {
  ------------------
  |  Branch (13636:9): [True: 0, False: 0]
  ------------------
13637|      0|      error = Error::Write;
13638|      0|      output_error_log(error, &req);
13639|      0|      return false;
13640|      0|    }
13641|      0|  }
13642|       |
13643|      0|  return true;
13644|      0|}
_ZNK7httplib10ClientImpl27write_content_with_providerERNS_6StreamERKNS_7RequestERNS_5ErrorE:
13416|  1.96k|                                                    Error &error) const {
13417|  1.96k|  auto is_shutting_down = []() { return false; };
13418|       |
13419|  1.96k|  if (req.is_chunked_content_provider_) {
  ------------------
  |  Branch (13419:7): [True: 0, False: 1.96k]
  ------------------
13420|      0|    auto compressor = compress_ ? detail::create_compressor().first
  ------------------
  |  Branch (13420:23): [True: 0, False: 0]
  ------------------
13421|      0|                                : std::unique_ptr<detail::compressor>();
13422|      0|    if (!compressor) {
  ------------------
  |  Branch (13422:9): [True: 0, False: 0]
  ------------------
13423|      0|      compressor = detail::make_unique<detail::nocompressor>();
13424|      0|    }
13425|       |
13426|      0|    return detail::write_content_chunked(strm, req.content_provider_,
13427|      0|                                         is_shutting_down, *compressor, error);
13428|  1.96k|  } else {
13429|  1.96k|    return detail::write_content_with_progress(
13430|  1.96k|        strm, req.content_provider_, 0, req.content_length_, is_shutting_down,
13431|  1.96k|        req.upload_progress, error);
13432|  1.96k|  }
13433|  1.96k|}
_ZN7httplib8DataSinkC2Ev:
 1030|  1.96k|  DataSink() : os(&sb_), sb_(*this) {}
_ZN7httplib8DataSink19data_sink_streambufC2ERS0_:
 1046|  1.96k|    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_:
 7436|  1.96k|                                        Error &error) {
 7437|  1.96k|  size_t end_offset = offset + length;
 7438|  1.96k|  size_t start_offset = offset;
 7439|  1.96k|  auto ok = true;
 7440|  1.96k|  DataSink data_sink;
 7441|       |
 7442|  1.96k|  data_sink.write = [&](const char *d, size_t l) -> bool {
 7443|  1.96k|    if (ok) {
 7444|  1.96k|      if (write_data(strm, d, l)) {
 7445|  1.96k|        offset += l;
 7446|       |
 7447|  1.96k|        if (upload_progress && length > 0) {
 7448|  1.96k|          size_t current_written = offset - start_offset;
 7449|  1.96k|          if (!upload_progress(current_written, length)) {
 7450|  1.96k|            ok = false;
 7451|  1.96k|            return false;
 7452|  1.96k|          }
 7453|  1.96k|        }
 7454|  1.96k|      } else {
 7455|  1.96k|        ok = false;
 7456|  1.96k|      }
 7457|  1.96k|    }
 7458|  1.96k|    return ok;
 7459|  1.96k|  };
 7460|       |
 7461|  1.96k|  data_sink.is_writable = [&]() -> bool { return strm.is_peer_alive(); };
 7462|       |
 7463|  1.96k|  while (offset < end_offset && !is_shutting_down()) {
  ------------------
  |  Branch (7463:10): [True: 0, False: 1.96k]
  |  Branch (7463:33): [True: 0, False: 0]
  ------------------
 7464|      0|    if (!strm.wait_writable() || !strm.is_peer_alive()) {
  ------------------
  |  Branch (7464:9): [True: 0, False: 0]
  |  Branch (7464:34): [True: 0, False: 0]
  ------------------
 7465|      0|      error = Error::Write;
 7466|      0|      return false;
 7467|      0|    } else if (!content_provider(offset, end_offset - offset, data_sink)) {
  ------------------
  |  Branch (7467:16): [True: 0, False: 0]
  ------------------
 7468|      0|      error = Error::Canceled;
 7469|      0|      return false;
 7470|      0|    } else if (!ok) {
  ------------------
  |  Branch (7470:16): [True: 0, False: 0]
  ------------------
 7471|      0|      error = Error::Write;
 7472|      0|      return false;
 7473|      0|    }
 7474|      0|  }
 7475|       |
 7476|  1.96k|  if (offset < end_offset) { // exited due to is_shutting_down(), not completion
  ------------------
  |  Branch (7476:7): [True: 0, False: 1.96k]
  ------------------
 7477|      0|    error = Error::Write;
 7478|      0|    return false;
 7479|      0|  }
 7480|       |
 7481|  1.96k|  error = Error::Success;
 7482|  1.96k|  return true;
 7483|  1.96k|}
_ZN7httplib6detail12read_headersERNS_6StreamERNSt3__118unordered_multimapINS3_12basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEESA_NS0_11case_ignore4hashENSB_8equal_toENS8_INS3_4pairIKSA_SA_EEEEEE:
 7063|  1.64k|inline bool read_headers(Stream &strm, Headers &headers) {
 7064|  1.64k|  const auto bufsiz = 2048;
 7065|  1.64k|  char buf[bufsiz];
 7066|  1.64k|  stream_line_reader line_reader(strm, buf, bufsiz);
 7067|       |
 7068|  1.64k|  size_t header_count = 0;
 7069|       |
 7070|  11.3k|  for (;;) {
 7071|  11.3k|    if (!line_reader.getline()) { return false; }
  ------------------
  |  Branch (7071:9): [True: 655, False: 10.6k]
  ------------------
 7072|       |
 7073|       |    // Check if the line ends with CRLF.
 7074|  10.6k|    auto line_terminator_len = 2;
 7075|  10.6k|    if (line_reader.end_with_crlf()) {
  ------------------
  |  Branch (7075:9): [True: 10.1k, False: 542]
  ------------------
 7076|       |      // Blank line indicates end of headers.
 7077|  10.1k|      if (line_reader.size() == 2) { break; }
  ------------------
  |  Branch (7077:11): [True: 592, False: 9.51k]
  ------------------
 7078|  10.1k|    } else {
 7079|       |#ifdef CPPHTTPLIB_ALLOW_LF_AS_LINE_TERMINATOR
 7080|       |      // Blank line indicates end of headers.
 7081|       |      if (line_reader.size() == 1) { break; }
 7082|       |      line_terminator_len = 1;
 7083|       |#else
 7084|    542|      continue; // Skip invalid line.
 7085|    542|#endif
 7086|    542|    }
 7087|       |
 7088|  9.51k|    if (line_reader.size() > CPPHTTPLIB_HEADER_MAX_LENGTH) { return false; }
  ------------------
  |  |  114|  9.51k|#define CPPHTTPLIB_HEADER_MAX_LENGTH 8192
  ------------------
  |  Branch (7088:9): [True: 3, False: 9.51k]
  ------------------
 7089|       |
 7090|       |    // Check header count limit
 7091|  9.51k|    if (header_count >= CPPHTTPLIB_HEADER_MAX_COUNT) { return false; }
  ------------------
  |  |  118|  9.51k|#define CPPHTTPLIB_HEADER_MAX_COUNT 100
  ------------------
  |  Branch (7091:9): [True: 8, False: 9.50k]
  ------------------
 7092|       |
 7093|       |    // Exclude line terminator
 7094|  9.50k|    auto end = line_reader.ptr() + line_reader.size() - line_terminator_len;
 7095|       |
 7096|  9.50k|    if (!parse_header(line_reader.ptr(), end,
  ------------------
  |  Branch (7096:9): [True: 383, False: 9.12k]
  ------------------
 7097|  9.50k|                      [&](const std::string &key, const std::string &val) {
 7098|  9.50k|                        headers.emplace(key, val);
 7099|  9.50k|                      })) {
 7100|    383|      return false;
 7101|    383|    }
 7102|       |
 7103|  9.12k|    header_count++;
 7104|  9.12k|  }
 7105|       |
 7106|       |  // RFC 9110 Section 8.6: Reject requests with multiple Content-Length
 7107|       |  // headers that have different values to prevent request smuggling.
 7108|    592|  auto cl_range = headers.equal_range("Content-Length");
 7109|    592|  if (cl_range.first != cl_range.second) {
  ------------------
  |  Branch (7109:7): [True: 24, False: 568]
  ------------------
 7110|     24|    const auto &first_val = cl_range.first->second;
 7111|     51|    for (auto it = std::next(cl_range.first); it != cl_range.second; ++it) {
  ------------------
  |  Branch (7111:47): [True: 33, False: 18]
  ------------------
 7112|     33|      if (it->second != first_val) { return false; }
  ------------------
  |  Branch (7112:11): [True: 6, False: 27]
  ------------------
 7113|     33|    }
 7114|     24|  }
 7115|       |
 7116|    586|  return true;
 7117|    592|}
_ZNK7httplib6detail18stream_line_reader13end_with_crlfEv:
 5295|  10.6k|inline bool stream_line_reader::end_with_crlf() const {
 5296|  10.6k|  auto end = ptr() + size();
 5297|  10.6k|  return size() >= 2 && end[-2] == '\r' && end[-1] == '\n';
  ------------------
  |  Branch (5297:10): [True: 10.5k, False: 118]
  |  Branch (5297:25): [True: 10.1k, False: 402]
  |  Branch (5297:44): [True: 10.1k, False: 22]
  ------------------
 5298|  10.6k|}
_ZN7httplib6detail12parse_headerIZNS0_12read_headersERNS_6StreamERNSt3__118unordered_multimapINS4_12basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEESB_NS0_11case_ignore4hashENSC_8equal_toENS9_INS4_4pairIKSB_SB_EEEEEEEUlRSG_SL_E_EEbPKcSO_T_:
 5029|  9.50k|inline bool parse_header(const char *beg, const char *end, T fn) {
 5030|       |  // Skip trailing spaces and tabs.
 5031|  9.87k|  while (beg < end && is_space_or_tab(end[-1])) {
  ------------------
  |  Branch (5031:10): [True: 9.86k, False: 10]
  |  Branch (5031:23): [True: 365, False: 9.49k]
  ------------------
 5032|    365|    end--;
 5033|    365|  }
 5034|       |
 5035|  9.50k|  auto p = beg;
 5036|   306k|  while (p < end && *p != ':') {
  ------------------
  |  Branch (5036:10): [True: 305k, False: 272]
  |  Branch (5036:21): [True: 296k, False: 9.23k]
  ------------------
 5037|   296k|    p++;
 5038|   296k|  }
 5039|       |
 5040|  9.50k|  auto name = std::string(beg, p);
 5041|  9.50k|  if (!detail::fields::is_field_name(name)) { return false; }
  ------------------
  |  Branch (5041:7): [True: 189, False: 9.31k]
  ------------------
 5042|       |
 5043|  9.31k|  if (p == end) { return false; }
  ------------------
  |  Branch (5043:7): [True: 116, False: 9.20k]
  ------------------
 5044|       |
 5045|  9.20k|  auto key_end = p;
 5046|       |
 5047|  9.20k|  if (*p++ != ':') { return false; }
  ------------------
  |  Branch (5047:7): [True: 0, False: 9.20k]
  ------------------
 5048|       |
 5049|  9.99k|  while (p < end && is_space_or_tab(*p)) {
  ------------------
  |  Branch (5049:10): [True: 9.16k, False: 825]
  |  Branch (5049:21): [True: 788, False: 8.37k]
  ------------------
 5050|    788|    p++;
 5051|    788|  }
 5052|       |
 5053|  9.20k|  if (p <= end) {
  ------------------
  |  Branch (5053:7): [True: 9.20k, False: 0]
  ------------------
 5054|  9.20k|    auto key_len = key_end - beg;
 5055|  9.20k|    if (!key_len) { return false; }
  ------------------
  |  Branch (5055:9): [True: 0, False: 9.20k]
  ------------------
 5056|       |
 5057|  9.20k|    auto key = std::string(beg, key_end);
 5058|  9.20k|    auto val = std::string(p, end);
 5059|       |
 5060|  9.20k|    if (!detail::fields::is_field_value(val)) { return false; }
  ------------------
  |  Branch (5060:9): [True: 78, False: 9.12k]
  ------------------
 5061|       |
 5062|       |    // RFC 9110 §5.5: header field values are opaque octets and MUST NOT be
 5063|       |    // percent-decoded by the recipient. Applications that need to interpret a
 5064|       |    // value as a URI component should call httplib::decode_uri_component()
 5065|       |    // (or decode_path_component()) explicitly.
 5066|  9.12k|    fn(key, val);
 5067|       |
 5068|  9.12k|    return true;
 5069|  9.20k|  }
 5070|       |
 5071|      0|  return false;
 5072|  9.20k|}
_ZZN7httplib6detail12read_headersERNS_6StreamERNSt3__118unordered_multimapINS3_12basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEESA_NS0_11case_ignore4hashENSB_8equal_toENS8_INS3_4pairIKSA_SA_EEEEEEENKUlRSF_SK_E_clESK_SK_:
 7097|  9.12k|                      [&](const std::string &key, const std::string &val) {
 7098|  9.12k|                        headers.emplace(key, val);
 7099|  9.12k|                      })) {
_ZNK7httplib10ClientImpl16output_error_logERKNS_5ErrorEPKNS_7RequestE:
13775|  1.60k|                                         const Request *req) const {
13776|  1.60k|  if (error_logger_) {
  ------------------
  |  Branch (13776:7): [True: 0, False: 1.60k]
  ------------------
13777|      0|    std::lock_guard<std::mutex> guard(logger_mutex_);
13778|      0|    error_logger_(err, req);
13779|      0|  }
13780|  1.60k|}
_ZZN7httplib10ClientImpl15process_requestERNS_6StreamERNS_7RequestERNS_8ResponseEbRNS_5ErrorEENKUlPKcmmmE0_clESA_mmm:
13900|  52.0k|                      size_t /*len*/) {
13901|  52.0k|                    assert(res.body.size() + n <= res.body.max_size());
  ------------------
  |  Branch (13901:21): [True: 52.0k, False: 0]
  ------------------
13902|  52.0k|                    if (payload_max_length_ > 0 &&
  ------------------
  |  Branch (13902:25): [True: 52.0k, False: 0]
  ------------------
13903|  52.0k|                        (res.body.size() >= payload_max_length_ ||
  ------------------
  |  Branch (13903:26): [True: 0, False: 52.0k]
  ------------------
13904|  52.0k|                         n > payload_max_length_ - res.body.size())) {
  ------------------
  |  Branch (13904:26): [True: 0, False: 52.0k]
  ------------------
13905|      0|                      return false;
13906|      0|                    }
13907|  52.0k|                    res.body.append(buf, n);
13908|  52.0k|                    return true;
13909|  52.0k|                  });
_ZNK7httplib8Response10has_headerERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
 9875|    583|inline bool Response::has_header(const std::string &key) const {
 9876|    583|  return headers.find(key) != headers.end();
 9877|    583|}
_ZNK7httplib8Response20get_header_value_u64ERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEmm:
 9871|     18|                                             size_t id) const {
 9872|     18|  return detail::get_header_value_u64(headers, key, def, id);
 9873|     18|}
_ZN7httplib6detail20get_header_value_u64ERKNSt3__118unordered_multimapINS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEES8_NS0_11case_ignore4hashENS9_8equal_toENS6_INS1_4pairIKS8_S8_EEEEEERSD_mm:
 2860|     18|                                   size_t id) {
 2861|     18|  auto dummy = false;
 2862|     18|  return get_header_value_u64(headers, key, def, id, dummy);
 2863|     18|}
_ZN7httplib6detail20get_header_value_u64ERKNSt3__118unordered_multimapINS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEES8_NS0_11case_ignore4hashENS9_8equal_toENS6_INS1_4pairIKS8_S8_EEEEEERSD_mmRb:
 2843|     26|                                   size_t id, bool &is_invalid_value) {
 2844|     26|  is_invalid_value = false;
 2845|     26|  auto rng = headers.equal_range(key);
 2846|     26|  auto it = rng.first;
 2847|     26|  std::advance(it, static_cast<ssize_t>(id));
 2848|     26|  if (it != rng.second) {
  ------------------
  |  Branch (2848:7): [True: 26, False: 0]
  ------------------
 2849|     26|    if (is_numeric(it->second)) {
  ------------------
  |  Branch (2849:9): [True: 6, False: 20]
  ------------------
 2850|      6|      return static_cast<size_t>(std::strtoull(it->second.data(), nullptr, 10));
 2851|     20|    } else {
 2852|     20|      is_invalid_value = true;
 2853|     20|    }
 2854|     26|  }
 2855|     20|  return def;
 2856|     26|}
_ZN7httplib6detail10is_numericERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
 2835|     26|inline bool is_numeric(const std::string &str) {
 2836|     26|  return !str.empty() &&
  ------------------
  |  Branch (2836:10): [True: 24, False: 2]
  ------------------
 2837|     24|         std::all_of(str.cbegin(), str.cend(),
  ------------------
  |  Branch (2837:10): [True: 6, False: 18]
  ------------------
 2838|     24|                     [](unsigned char c) { return std::isdigit(c); });
 2839|     26|}
_ZZN7httplib6detail10is_numericERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEENKUlhE_clEh:
 2838|    606|                     [](unsigned char c) { return std::isdigit(c); });
_ZN7httplib6detail12read_contentINS_8ResponseEEEbRNS_6StreamERT_mRiNSt3__18functionIFbmmEEENS9_IFbPKcmmmEEEb:
 7326|    581|                  ContentReceiverWithProgress receiver, bool decompress) {
 7327|    581|  bool exceed_payload_max_length = false;
 7328|    581|  return prepare_content_receiver(
 7329|    581|      x, status, std::move(receiver), decompress, payload_max_length,
 7330|    581|      exceed_payload_max_length, [&](const ContentReceiverWithProgress &out) {
 7331|    581|        auto ret = true;
 7332|       |        // Note: exceed_payload_max_length may also be set by the decompressor
 7333|       |        // wrapper in prepare_content_receiver when the decompressed payload
 7334|       |        // size exceeds the limit.
 7335|       |
 7336|    581|        if (is_chunked_transfer_encoding(x.headers)) {
 7337|    581|          auto result = read_content_chunked(strm, x, payload_max_length, out);
 7338|    581|          if (result == ReadContentResult::Success) {
 7339|    581|            ret = true;
 7340|    581|          } else if (result == ReadContentResult::PayloadTooLarge) {
 7341|    581|            exceed_payload_max_length = true;
 7342|    581|            ret = false;
 7343|    581|          } else {
 7344|    581|            ret = false;
 7345|    581|          }
 7346|    581|        } else if (!has_header(x.headers, "Content-Length")) {
 7347|    581|          auto result =
 7348|    581|              read_content_without_length(strm, payload_max_length, out);
 7349|    581|          if (result == ReadContentResult::Success) {
 7350|    581|            ret = true;
 7351|    581|          } else if (result == ReadContentResult::PayloadTooLarge) {
 7352|    581|            exceed_payload_max_length = true;
 7353|    581|            ret = false;
 7354|    581|          } else {
 7355|    581|            ret = false;
 7356|    581|          }
 7357|    581|        } else {
 7358|    581|          auto is_invalid_value = false;
 7359|    581|          auto len = get_header_value_u64(x.headers, "Content-Length",
 7360|    581|                                          (std::numeric_limits<size_t>::max)(),
 7361|    581|                                          0, is_invalid_value);
 7362|       |
 7363|    581|          if (is_invalid_value) {
 7364|    581|            ret = false;
 7365|    581|          } else if (len > 0) {
 7366|    581|            auto result = read_content_with_length(
 7367|    581|                strm, len, std::move(progress), out, payload_max_length);
 7368|    581|            ret = (result == ReadContentResult::Success);
 7369|    581|            if (result == ReadContentResult::PayloadTooLarge) {
 7370|    581|              exceed_payload_max_length = true;
 7371|    581|            }
 7372|    581|          }
 7373|    581|        }
 7374|       |
 7375|    581|        if (!ret) {
 7376|    581|          status = exceed_payload_max_length ? StatusCode::PayloadTooLarge_413
 7377|    581|                                             : StatusCode::BadRequest_400;
 7378|    581|        }
 7379|    581|        return ret;
 7380|    581|      });
 7381|    581|}
_ZN7httplib6detail24prepare_content_receiverINS_8ResponseEZNS0_12read_contentIS2_EEbRNS_6StreamERT_mRiNSt3__18functionIFbmmEEENSA_IFbPKcmmmEEEbEUlRKSG_E_EEbS7_S8_SG_bmRbT0_:
 7275|    581|                              bool &exceed_payload_max_length, U callback) {
 7276|    581|  if (decompress) {
  ------------------
  |  Branch (7276:7): [True: 581, False: 0]
  ------------------
 7277|    581|    std::string encoding = x.get_header_value("Content-Encoding");
 7278|    581|    std::unique_ptr<decompressor> decompressor;
 7279|       |
 7280|    581|    if (!encoding.empty()) {
  ------------------
  |  Branch (7280:9): [True: 193, False: 388]
  ------------------
 7281|    193|      decompressor = detail::create_decompressor(encoding);
 7282|    193|      if (!decompressor) {
  ------------------
  |  Branch (7282:11): [True: 107, False: 86]
  ------------------
 7283|       |        // Unsupported encoding or no support compiled in
 7284|    107|        status = StatusCode::UnsupportedMediaType_415;
 7285|    107|        return false;
 7286|    107|      }
 7287|    193|    }
 7288|       |
 7289|    474|    if (decompressor) {
  ------------------
  |  Branch (7289:9): [True: 86, False: 388]
  ------------------
 7290|     86|      if (decompressor->is_valid()) {
  ------------------
  |  Branch (7290:11): [True: 86, False: 0]
  ------------------
 7291|     86|        size_t decompressed_size = 0;
 7292|     86|        ContentReceiverWithProgress out = [&](const char *buf, size_t n,
 7293|     86|                                              size_t off, size_t len) {
 7294|     86|          return decompressor->decompress(
 7295|     86|              buf, n, [&](const char *buf2, size_t n2) {
 7296|       |                // Guard against zip-bomb: check
 7297|       |                // decompressed size against limit.
 7298|     86|                if (payload_max_length > 0 &&
 7299|     86|                    (decompressed_size >= payload_max_length ||
 7300|     86|                     n2 > payload_max_length - decompressed_size)) {
 7301|     86|                  exceed_payload_max_length = true;
 7302|     86|                  return false;
 7303|     86|                }
 7304|     86|                decompressed_size += n2;
 7305|     86|                return receiver(buf2, n2, off, len);
 7306|     86|              });
 7307|     86|        };
 7308|     86|        return callback(std::move(out));
 7309|     86|      } else {
 7310|      0|        status = StatusCode::InternalServerError_500;
 7311|      0|        return false;
 7312|      0|      }
 7313|     86|    }
 7314|    474|  }
 7315|       |
 7316|    388|  ContentReceiverWithProgress out = [&](const char *buf, size_t n, size_t off,
 7317|    388|                                        size_t len) {
 7318|    388|    return receiver(buf, n, off, len);
 7319|    388|  };
 7320|    388|  return callback(std::move(out));
 7321|    581|}
_ZNK7httplib8Response16get_header_valueERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEPKcm:
 9881|    581|                                              size_t id) const {
 9882|    581|  return detail::get_header_value(headers, key, def, id);
 9883|    581|}
_ZN7httplib6detail19create_decompressorERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
 6969|    193|create_decompressor(const std::string &encoding) {
 6970|    193|  std::unique_ptr<decompressor> decompressor;
 6971|       |
 6972|    193|  if (encoding == "gzip" || encoding == "deflate") {
  ------------------
  |  Branch (6972:7): [True: 16, False: 177]
  |  Branch (6972:29): [True: 70, False: 107]
  ------------------
 6973|     86|#ifdef CPPHTTPLIB_ZLIB_SUPPORT
 6974|     86|    decompressor = detail::make_unique<gzip_decompressor>();
 6975|     86|#endif
 6976|    107|  } else if (encoding.find("br") != std::string::npos) {
  ------------------
  |  Branch (6976:14): [True: 10, False: 97]
  ------------------
 6977|       |#ifdef CPPHTTPLIB_BROTLI_SUPPORT
 6978|       |    decompressor = detail::make_unique<brotli_decompressor>();
 6979|       |#endif
 6980|     97|  } else if (encoding == "zstd" || encoding.find("zstd") != std::string::npos) {
  ------------------
  |  Branch (6980:14): [True: 0, False: 97]
  |  Branch (6980:36): [True: 11, False: 86]
  ------------------
 6981|       |#ifdef CPPHTTPLIB_ZSTD_SUPPORT
 6982|       |    decompressor = detail::make_unique<zstd_decompressor>();
 6983|       |#endif
 6984|     11|  }
 6985|       |
 6986|    193|  return decompressor;
 6987|    193|}
_ZN7httplib6detail11make_uniqueINS0_17gzip_decompressorEJEEENSt3__19enable_ifIXntsr3std8is_arrayIT_EE5valueENS3_10unique_ptrIS5_NS3_14default_deleteIS5_EEEEE4typeEDpOT0_:
  532|     86|make_unique(Args &&...args) {
  533|     86|  return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
  534|     86|}
_ZN7httplib6detail17gzip_decompressorC2Ev:
 6766|     86|inline gzip_decompressor::gzip_decompressor() {
 6767|     86|  std::memset(&strm_, 0, sizeof(strm_));
 6768|     86|  strm_.zalloc = Z_NULL;
 6769|     86|  strm_.zfree = Z_NULL;
 6770|     86|  strm_.opaque = Z_NULL;
 6771|       |
 6772|       |  // 15 is the value of wbits, which should be at the maximum possible value
 6773|       |  // to ensure that any gzip stream can be decoded. The offset of 32 specifies
 6774|       |  // that the stream type should be automatically detected either gzip or
 6775|       |  // deflate.
 6776|     86|  is_valid_ = inflateInit2(&strm_, 32 + 15) == Z_OK;
 6777|     86|}
_ZZN7httplib6detail24prepare_content_receiverINS_8ResponseEZNS0_12read_contentIS2_EEbRNS_6StreamERT_mRiNSt3__18functionIFbmmEEENSA_IFbPKcmmmEEEbEUlRKSG_E_EEbS7_S8_SG_bmRbT0_ENKUlSE_mmmE_clESE_mmm:
 7293|    725|                                              size_t off, size_t len) {
 7294|    725|          return decompressor->decompress(
 7295|    725|              buf, n, [&](const char *buf2, size_t n2) {
 7296|       |                // Guard against zip-bomb: check
 7297|       |                // decompressed size against limit.
 7298|    725|                if (payload_max_length > 0 &&
 7299|    725|                    (decompressed_size >= payload_max_length ||
 7300|    725|                     n2 > payload_max_length - decompressed_size)) {
 7301|    725|                  exceed_payload_max_length = true;
 7302|    725|                  return false;
 7303|    725|                }
 7304|    725|                decompressed_size += n2;
 7305|    725|                return receiver(buf2, n2, off, len);
 7306|    725|              });
 7307|    725|        };
_ZZZN7httplib6detail24prepare_content_receiverINS_8ResponseEZNS0_12read_contentIS2_EEbRNS_6StreamERT_mRiNSt3__18functionIFbmmEEENSA_IFbPKcmmmEEEbEUlRKSG_E_EEbS7_S8_SG_bmRbT0_ENKUlSE_mmmE_clESE_mmmENKUlSE_mE_clESE_m:
 7295|  51.6k|              buf, n, [&](const char *buf2, size_t n2) {
 7296|       |                // Guard against zip-bomb: check
 7297|       |                // decompressed size against limit.
 7298|  51.6k|                if (payload_max_length > 0 &&
  ------------------
  |  Branch (7298:21): [True: 51.6k, False: 0]
  ------------------
 7299|  51.6k|                    (decompressed_size >= payload_max_length ||
  ------------------
  |  Branch (7299:22): [True: 0, False: 51.6k]
  ------------------
 7300|  51.6k|                     n2 > payload_max_length - decompressed_size)) {
  ------------------
  |  Branch (7300:22): [True: 4, False: 51.6k]
  ------------------
 7301|      4|                  exceed_payload_max_length = true;
 7302|      4|                  return false;
 7303|      4|                }
 7304|  51.6k|                decompressed_size += n2;
 7305|  51.6k|                return receiver(buf2, n2, off, len);
 7306|  51.6k|              });
_ZZN7httplib6detail12read_contentINS_8ResponseEEEbRNS_6StreamERT_mRiNSt3__18functionIFbmmEEENS9_IFbPKcmmmEEEbENKUlRKSF_E_clESH_:
 7330|    474|      exceed_payload_max_length, [&](const ContentReceiverWithProgress &out) {
 7331|    474|        auto ret = true;
 7332|       |        // Note: exceed_payload_max_length may also be set by the decompressor
 7333|       |        // wrapper in prepare_content_receiver when the decompressed payload
 7334|       |        // size exceeds the limit.
 7335|       |
 7336|    474|        if (is_chunked_transfer_encoding(x.headers)) {
  ------------------
  |  Branch (7336:13): [True: 73, False: 401]
  ------------------
 7337|     73|          auto result = read_content_chunked(strm, x, payload_max_length, out);
 7338|     73|          if (result == ReadContentResult::Success) {
  ------------------
  |  Branch (7338:15): [True: 0, False: 73]
  ------------------
 7339|      0|            ret = true;
 7340|     73|          } else if (result == ReadContentResult::PayloadTooLarge) {
  ------------------
  |  Branch (7340:22): [True: 0, False: 73]
  ------------------
 7341|      0|            exceed_payload_max_length = true;
 7342|      0|            ret = false;
 7343|     73|          } else {
 7344|     73|            ret = false;
 7345|     73|          }
 7346|    401|        } else if (!has_header(x.headers, "Content-Length")) {
  ------------------
  |  Branch (7346:20): [True: 393, False: 8]
  ------------------
 7347|    393|          auto result =
 7348|    393|              read_content_without_length(strm, payload_max_length, out);
 7349|    393|          if (result == ReadContentResult::Success) {
  ------------------
  |  Branch (7349:15): [True: 353, False: 40]
  ------------------
 7350|    353|            ret = true;
 7351|    353|          } else if (result == ReadContentResult::PayloadTooLarge) {
  ------------------
  |  Branch (7351:22): [True: 0, False: 40]
  ------------------
 7352|      0|            exceed_payload_max_length = true;
 7353|      0|            ret = false;
 7354|     40|          } else {
 7355|     40|            ret = false;
 7356|     40|          }
 7357|    393|        } else {
 7358|      8|          auto is_invalid_value = false;
 7359|      8|          auto len = get_header_value_u64(x.headers, "Content-Length",
 7360|      8|                                          (std::numeric_limits<size_t>::max)(),
 7361|      8|                                          0, is_invalid_value);
 7362|       |
 7363|      8|          if (is_invalid_value) {
  ------------------
  |  Branch (7363:15): [True: 6, False: 2]
  ------------------
 7364|      6|            ret = false;
 7365|      6|          } else if (len > 0) {
  ------------------
  |  Branch (7365:22): [True: 2, False: 0]
  ------------------
 7366|      2|            auto result = read_content_with_length(
 7367|      2|                strm, len, std::move(progress), out, payload_max_length);
 7368|      2|            ret = (result == ReadContentResult::Success);
 7369|      2|            if (result == ReadContentResult::PayloadTooLarge) {
  ------------------
  |  Branch (7369:17): [True: 0, False: 2]
  ------------------
 7370|      0|              exceed_payload_max_length = true;
 7371|      0|            }
 7372|      2|          }
 7373|      8|        }
 7374|       |
 7375|    474|        if (!ret) {
  ------------------
  |  Branch (7375:13): [True: 120, False: 354]
  ------------------
 7376|    120|          status = exceed_payload_max_length ? StatusCode::PayloadTooLarge_413
  ------------------
  |  Branch (7376:20): [True: 4, False: 116]
  ------------------
 7377|    120|                                             : StatusCode::BadRequest_400;
 7378|    120|        }
 7379|    474|        return ret;
 7380|    474|      });
_ZN7httplib6detail28is_chunked_transfer_encodingERKNSt3__118unordered_multimapINS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEES8_NS0_11case_ignore4hashENS9_8equal_toENS6_INS1_4pairIKS8_S8_EEEEEE:
 7266|    474|inline bool is_chunked_transfer_encoding(const Headers &headers) {
 7267|    474|  return case_ignore::equal(
 7268|    474|      get_header_value(headers, "Transfer-Encoding", "", 0), "chunked");
 7269|    474|}
_ZN7httplib6detail20read_content_chunkedINS_8ResponseEEENS0_17ReadContentResultERNS_6StreamERT_mNSt3__18functionIFbPKcmmmEEE:
 7234|     73|                                              ContentReceiverWithProgress out) {
 7235|     73|  detail::ChunkedDecoder dec(strm);
 7236|       |
 7237|     73|  char buf[CPPHTTPLIB_RECV_BUFSIZ];
 7238|     73|  size_t total_len = 0;
 7239|       |
 7240|     83|  for (;;) {
 7241|     83|    size_t chunk_offset = 0;
 7242|     83|    size_t chunk_total = 0;
 7243|     83|    auto n = dec.read_payload(buf, sizeof(buf), chunk_offset, chunk_total);
 7244|     83|    if (n < 0) { return ReadContentResult::Error; }
  ------------------
  |  Branch (7244:9): [True: 73, False: 10]
  ------------------
 7245|       |
 7246|     10|    if (n == 0) {
  ------------------
  |  Branch (7246:9): [True: 0, False: 10]
  ------------------
 7247|      0|      if (!dec.parse_trailers_into(x.trailers, x.headers)) {
  ------------------
  |  Branch (7247:11): [True: 0, False: 0]
  ------------------
 7248|      0|        return ReadContentResult::Error;
 7249|      0|      }
 7250|      0|      return ReadContentResult::Success;
 7251|      0|    }
 7252|       |
 7253|     10|    if (total_len > payload_max_length ||
  ------------------
  |  Branch (7253:9): [True: 0, False: 10]
  ------------------
 7254|     10|        payload_max_length - total_len < static_cast<size_t>(n)) {
  ------------------
  |  Branch (7254:9): [True: 0, False: 10]
  ------------------
 7255|      0|      return ReadContentResult::PayloadTooLarge;
 7256|      0|    }
 7257|       |
 7258|     10|    if (!out(buf, static_cast<size_t>(n), chunk_offset, chunk_total)) {
  ------------------
  |  Branch (7258:9): [True: 0, False: 10]
  ------------------
 7259|      0|      return ReadContentResult::Error;
 7260|      0|    }
 7261|       |
 7262|     10|    total_len += static_cast<size_t>(n);
 7263|     10|  }
 7264|     73|}
_ZN7httplib6detail14ChunkedDecoderC2ERNS_6StreamE:
13072|     73|inline ChunkedDecoder::ChunkedDecoder(Stream &s) : strm(s) {}
_ZN7httplib6detail14ChunkedDecoder12read_payloadEPcmRmS3_:
13076|     83|                                            size_t &out_chunk_total) {
13077|     83|  if (finished) { return 0; }
  ------------------
  |  Branch (13077:7): [True: 0, False: 83]
  ------------------
13078|       |
13079|     83|  if (chunk_remaining == 0) {
  ------------------
  |  Branch (13079:7): [True: 80, False: 3]
  ------------------
13080|     80|    stream_line_reader lr(strm, line_buf, sizeof(line_buf));
13081|     80|    if (!lr.getline()) { return -1; }
  ------------------
  |  Branch (13081:9): [True: 1, False: 79]
  ------------------
13082|       |
13083|       |    // RFC 9112 §7.1: chunk-size = 1*HEXDIG
13084|     79|    const char *p = lr.ptr();
13085|     79|    int v = 0;
13086|     79|    if (!is_hex(*p, v)) { return -1; }
  ------------------
  |  Branch (13086:9): [True: 7, False: 72]
  ------------------
13087|       |
13088|     72|    size_t chunk_len = 0;
13089|     72|    constexpr size_t chunk_len_max = (std::numeric_limits<size_t>::max)();
13090|    209|    for (; is_hex(*p, v); ++p) {
  ------------------
  |  Branch (13090:12): [True: 138, False: 71]
  ------------------
13091|    138|      if (chunk_len > (chunk_len_max >> 4)) { return -1; }
  ------------------
  |  Branch (13091:11): [True: 1, False: 137]
  ------------------
13092|    137|      chunk_len = (chunk_len << 4) | static_cast<size_t>(v);
13093|    137|    }
13094|       |
13095|     71|    while (is_space_or_tab(*p)) {
  ------------------
  |  Branch (13095:12): [True: 0, False: 71]
  ------------------
13096|      0|      ++p;
13097|      0|    }
13098|     71|    if (*p != '\0' && *p != ';' && *p != '\r' && *p != '\n') { return -1; }
  ------------------
  |  Branch (13098:9): [True: 70, False: 1]
  |  Branch (13098:23): [True: 70, False: 0]
  |  Branch (13098:36): [True: 70, False: 0]
  |  Branch (13098:50): [True: 61, False: 9]
  ------------------
13099|       |
13100|     10|    if (chunk_len == 0) {
  ------------------
  |  Branch (13100:9): [True: 0, False: 10]
  ------------------
13101|      0|      chunk_remaining = 0;
13102|      0|      finished = true;
13103|      0|      out_chunk_offset = 0;
13104|      0|      out_chunk_total = 0;
13105|      0|      return 0;
13106|      0|    }
13107|       |
13108|     10|    chunk_remaining = chunk_len;
13109|     10|    last_chunk_total = chunk_remaining;
13110|     10|    last_chunk_offset = 0;
13111|     10|  }
13112|       |
13113|     13|  auto to_read = (std::min)(chunk_remaining, len);
13114|     13|  auto n = strm.read(buf, to_read);
13115|     13|  if (n <= 0) { return -1; }
  ------------------
  |  Branch (13115:7): [True: 2, False: 11]
  ------------------
13116|       |
13117|     11|  auto offset_before = last_chunk_offset;
13118|     11|  last_chunk_offset += static_cast<size_t>(n);
13119|     11|  chunk_remaining -= static_cast<size_t>(n);
13120|       |
13121|     11|  out_chunk_offset = offset_before;
13122|     11|  out_chunk_total = last_chunk_total;
13123|       |
13124|     11|  if (chunk_remaining == 0) {
  ------------------
  |  Branch (13124:7): [True: 8, False: 3]
  ------------------
13125|      8|    stream_line_reader lr(strm, line_buf, sizeof(line_buf));
13126|      8|    if (!lr.getline()) { return -1; }
  ------------------
  |  Branch (13126:9): [True: 0, False: 8]
  ------------------
13127|      8|    if (std::strcmp(lr.ptr(), "\r\n") != 0) { return -1; }
  ------------------
  |  Branch (13127:9): [True: 1, False: 7]
  ------------------
13128|      8|  }
13129|       |
13130|     10|  return n;
13131|     11|}
_ZN7httplib6detail6is_hexEcRi:
 4378|    288|inline bool is_hex(char c, int &v) {
 4379|    288|  if (isdigit(c)) {
  ------------------
  |  Branch (4379:7): [True: 157, False: 131]
  ------------------
 4380|    157|    v = c - '0';
 4381|    157|    return true;
 4382|    157|  } else if ('A' <= c && c <= 'F') {
  ------------------
  |  Branch (4382:14): [True: 56, False: 75]
  |  Branch (4382:26): [True: 0, False: 56]
  ------------------
 4383|      0|    v = c - 'A' + 10;
 4384|      0|    return true;
 4385|    131|  } else if ('a' <= c && c <= 'f') {
  ------------------
  |  Branch (4385:14): [True: 55, False: 76]
  |  Branch (4385:26): [True: 53, False: 2]
  ------------------
 4386|     53|    v = c - 'a' + 10;
 4387|     53|    return true;
 4388|     53|  }
 4389|     78|  return false;
 4390|    288|}
_ZN7httplib6detail27read_content_without_lengthERNS_6StreamEmNSt3__18functionIFbPKcmmmEEE:
 7208|    393|                            ContentReceiverWithProgress out) {
 7209|    393|  char buf[CPPHTTPLIB_RECV_BUFSIZ];
 7210|    393|  size_t r = 0;
 7211|  1.41k|  for (;;) {
 7212|  1.41k|    auto n = strm.read(buf, CPPHTTPLIB_RECV_BUFSIZ);
  ------------------
  |  |  150|  1.41k|#define CPPHTTPLIB_RECV_BUFSIZ size_t(16384u)
  ------------------
 7213|  1.41k|    if (n == 0) { return ReadContentResult::Success; }
  ------------------
  |  Branch (7213:9): [True: 353, False: 1.05k]
  ------------------
 7214|  1.05k|    if (n < 0) { return ReadContentResult::Error; }
  ------------------
  |  Branch (7214:9): [True: 0, False: 1.05k]
  ------------------
 7215|       |
 7216|       |    // Check if adding this data would exceed the payload limit
 7217|  1.05k|    if (r > payload_max_length ||
  ------------------
  |  Branch (7217:9): [True: 0, False: 1.05k]
  ------------------
 7218|  1.05k|        payload_max_length - r < static_cast<size_t>(n)) {
  ------------------
  |  Branch (7218:9): [True: 0, False: 1.05k]
  ------------------
 7219|      0|      return ReadContentResult::PayloadTooLarge;
 7220|      0|    }
 7221|       |
 7222|  1.05k|    if (!out(buf, static_cast<size_t>(n), r, 0)) {
  ------------------
  |  Branch (7222:9): [True: 40, False: 1.01k]
  ------------------
 7223|     40|      return ReadContentResult::Error;
 7224|     40|    }
 7225|  1.01k|    r += static_cast<size_t>(n);
 7226|  1.01k|  }
 7227|       |
 7228|      0|  return ReadContentResult::Success;
 7229|    393|}
_ZN7httplib6detail24read_content_with_lengthERNS_6StreamEmNSt3__18functionIFbmmEEENS4_IFbPKcmmmEEEm:
 7168|      2|    size_t payload_max_length = (std::numeric_limits<size_t>::max)()) {
 7169|      2|  char buf[CPPHTTPLIB_RECV_BUFSIZ];
 7170|       |
 7171|      2|  detail::BodyReader br;
 7172|      2|  br.stream = &strm;
 7173|      2|  br.has_content_length = true;
 7174|      2|  br.content_length = len;
 7175|      2|  br.payload_max_length = payload_max_length;
 7176|      2|  br.chunked = false;
 7177|      2|  br.bytes_read = 0;
 7178|      2|  br.last_error = Error::Success;
 7179|       |
 7180|      2|  size_t r = 0;
 7181|      3|  while (r < len) {
  ------------------
  |  Branch (7181:10): [True: 2, False: 1]
  ------------------
 7182|      2|    auto read_len = static_cast<size_t>(len - r);
 7183|      2|    auto to_read = (std::min)(read_len, CPPHTTPLIB_RECV_BUFSIZ);
  ------------------
  |  |  150|      2|#define CPPHTTPLIB_RECV_BUFSIZ size_t(16384u)
  ------------------
 7184|      2|    auto n = detail::read_body_content(&strm, br, buf, to_read);
 7185|      2|    if (n <= 0) {
  ------------------
  |  Branch (7185:9): [True: 0, False: 2]
  ------------------
 7186|       |      // Check if it was a payload size error
 7187|      0|      if (br.last_error == Error::ExceedMaxPayloadSize) {
  ------------------
  |  Branch (7187:11): [True: 0, False: 0]
  ------------------
 7188|      0|        return ReadContentResult::PayloadTooLarge;
 7189|      0|      }
 7190|      0|      return ReadContentResult::Error;
 7191|      0|    }
 7192|       |
 7193|      2|    if (!out(buf, static_cast<size_t>(n), r, len)) {
  ------------------
  |  Branch (7193:9): [True: 1, False: 1]
  ------------------
 7194|      1|      return ReadContentResult::Error;
 7195|      1|    }
 7196|      1|    r += static_cast<size_t>(n);
 7197|       |
 7198|      1|    if (progress) {
  ------------------
  |  Branch (7198:9): [True: 1, False: 0]
  ------------------
 7199|      1|      if (!progress(r, len)) { return ReadContentResult::Error; }
  ------------------
  |  Branch (7199:11): [True: 0, False: 1]
  ------------------
 7200|      1|    }
 7201|      1|  }
 7202|       |
 7203|      1|  return ReadContentResult::Success;
 7204|      2|}
_ZN7httplib6detail17read_body_contentEPNS_6StreamERNS0_10BodyReaderEPcm:
 2020|      2|                                 size_t len) {
 2021|      2|  (void)stream;
 2022|      2|  return br.read(buf, len);
 2023|      2|}
_ZN7httplib6detail10BodyReader4readEPcm:
10014|      2|inline ssize_t detail::BodyReader::read(char *buf, size_t len) {
10015|      2|  if (!stream) {
  ------------------
  |  Branch (10015:7): [True: 0, False: 2]
  ------------------
10016|      0|    last_error = Error::Connection;
10017|      0|    return -1;
10018|      0|  }
10019|      2|  if (eof) { return 0; }
  ------------------
  |  Branch (10019:7): [True: 0, False: 2]
  ------------------
10020|       |
10021|      2|  if (!chunked) {
  ------------------
  |  Branch (10021:7): [True: 2, False: 0]
  ------------------
10022|       |    // Content-Length based reading
10023|      2|    if (has_content_length && bytes_read >= content_length) {
  ------------------
  |  Branch (10023:9): [True: 2, False: 0]
  |  Branch (10023:31): [True: 0, False: 2]
  ------------------
10024|      0|      eof = true;
10025|      0|      return 0;
10026|      0|    }
10027|       |
10028|      2|    auto to_read = len;
10029|      2|    if (has_content_length) {
  ------------------
  |  Branch (10029:9): [True: 2, False: 0]
  ------------------
10030|      2|      auto remaining = content_length - bytes_read;
10031|      2|      to_read = (std::min)(len, remaining);
10032|      2|    }
10033|      2|    auto n = stream->read(buf, to_read);
10034|       |
10035|      2|    if (n < 0) {
  ------------------
  |  Branch (10035:9): [True: 0, False: 2]
  ------------------
10036|      0|      last_error = stream->get_error();
10037|      0|      if (last_error == Error::Success) { last_error = Error::Read; }
  ------------------
  |  Branch (10037:11): [True: 0, False: 0]
  ------------------
10038|      0|      eof = true;
10039|      0|      return n;
10040|      0|    }
10041|      2|    if (n == 0) {
  ------------------
  |  Branch (10041:9): [True: 0, False: 2]
  ------------------
10042|       |      // Unexpected EOF before content_length
10043|      0|      last_error = stream->get_error();
10044|      0|      if (last_error == Error::Success) { last_error = Error::Read; }
  ------------------
  |  Branch (10044:11): [True: 0, False: 0]
  ------------------
10045|      0|      eof = true;
10046|      0|      return 0;
10047|      0|    }
10048|       |
10049|      2|    bytes_read += static_cast<size_t>(n);
10050|      2|    if (has_content_length && bytes_read >= content_length) { eof = true; }
  ------------------
  |  Branch (10050:9): [True: 2, False: 0]
  |  Branch (10050:31): [True: 1, False: 1]
  ------------------
10051|      2|    if (payload_max_length > 0 && bytes_read > payload_max_length) {
  ------------------
  |  Branch (10051:9): [True: 2, False: 0]
  |  Branch (10051:35): [True: 0, False: 2]
  ------------------
10052|      0|      last_error = Error::ExceedMaxPayloadSize;
10053|      0|      eof = true;
10054|      0|      return -1;
10055|      0|    }
10056|      2|    return n;
10057|      2|  }
10058|       |
10059|       |  // Chunked transfer encoding: delegate to shared decoder instance.
10060|      0|  if (!chunked_decoder) { chunked_decoder.reset(new ChunkedDecoder(*stream)); }
  ------------------
  |  Branch (10060:7): [True: 0, False: 0]
  ------------------
10061|       |
10062|      0|  size_t chunk_offset = 0;
10063|      0|  size_t chunk_total = 0;
10064|      0|  auto n = chunked_decoder->read_payload(buf, len, chunk_offset, chunk_total);
10065|      0|  if (n < 0) {
  ------------------
  |  Branch (10065:7): [True: 0, False: 0]
  ------------------
10066|      0|    last_error = stream->get_error();
10067|      0|    if (last_error == Error::Success) { last_error = Error::Read; }
  ------------------
  |  Branch (10067:9): [True: 0, False: 0]
  ------------------
10068|      0|    eof = true;
10069|      0|    return n;
10070|      0|  }
10071|       |
10072|      0|  if (n == 0) {
  ------------------
  |  Branch (10072:7): [True: 0, False: 0]
  ------------------
10073|       |    // Final chunk observed. Leave trailer parsing to the caller (StreamHandle).
10074|      0|    eof = true;
10075|      0|    return 0;
10076|      0|  }
10077|       |
10078|      0|  bytes_read += static_cast<size_t>(n);
10079|      0|  if (payload_max_length > 0 && bytes_read > payload_max_length) {
  ------------------
  |  Branch (10079:7): [True: 0, False: 0]
  |  Branch (10079:33): [True: 0, False: 0]
  ------------------
10080|      0|    last_error = Error::ExceedMaxPayloadSize;
10081|      0|    eof = true;
10082|      0|    return -1;
10083|      0|  }
10084|      0|  return n;
10085|      0|}
_ZZN7httplib6detail24prepare_content_receiverINS_8ResponseEZNS0_12read_contentIS2_EEbRNS_6StreamERT_mRiNSt3__18functionIFbmmEEENSA_IFbPKcmmmEEEbEUlRKSG_E_EEbS7_S8_SG_bmRbT0_ENKUlSE_mmmE0_clESE_mmm:
 7317|    345|                                        size_t len) {
 7318|    345|    return receiver(buf, n, off, len);
 7319|    345|  };
_ZZN7httplib10ClientImpl15process_requestERNS_6StreamERNS_7RequestERNS_8ResponseEbRNS_5ErrorEENKUlmmE_clEmm:
13911|      1|    auto progress = [&](size_t current, size_t total) {
13912|      1|      if (!req.download_progress || redirect) { return true; }
  ------------------
  |  Branch (13912:11): [True: 1, False: 0]
  |  Branch (13912:37): [True: 0, False: 0]
  ------------------
13913|      0|      auto ret = req.download_progress(current, total);
13914|      0|      if (!ret) {
  ------------------
  |  Branch (13914:11): [True: 0, False: 0]
  ------------------
13915|      0|        error = Error::Canceled;
13916|      0|        output_error_log(error, &req);
13917|      0|      }
13918|      0|      return ret;
13919|      1|    };
_ZNK7httplib10ClientImpl10output_logERKNS_7RequestERKNS_8ResponseE:
13767|    358|                                   const Response &res) const {
13768|    358|  if (logger_) {
  ------------------
  |  Branch (13768:7): [True: 0, False: 358]
  ------------------
13769|      0|    std::lock_guard<std::mutex> guard(logger_mutex_);
13770|      0|    logger_(req, res);
13771|      0|  }
13772|    358|}
_ZN7httplib8ResponseD2Ev:
 1383|  1.96k|  ~Response() {
 1384|  1.96k|    if (content_provider_resource_releaser_) {
  ------------------
  |  Branch (1384:9): [True: 0, False: 1.96k]
  ------------------
 1385|      0|      content_provider_resource_releaser_(content_provider_success_);
 1386|      0|    }
 1387|  1.96k|  }
_ZNK7httplib6detail17gzip_decompressor8is_validEv:
 6781|     86|inline bool gzip_decompressor::is_valid() const { return is_valid_; }
_ZN7httplib6detail17gzip_decompressor10decompressEPKcmNSt3__18functionIFbS3_mEEE:
 6784|    725|                                          Callback callback) {
 6785|    725|  assert(is_valid_);
  ------------------
  |  Branch (6785:3): [True: 725, False: 0]
  ------------------
 6786|       |
 6787|    725|  auto ret = Z_OK;
 6788|       |
 6789|    725|  do {
 6790|    725|    constexpr size_t max_avail_in =
 6791|    725|        (std::numeric_limits<decltype(strm_.avail_in)>::max)();
 6792|       |
 6793|    725|    strm_.avail_in = static_cast<decltype(strm_.avail_in)>(
 6794|    725|        (std::min)(data_length, max_avail_in));
 6795|    725|    strm_.next_in = const_cast<Bytef *>(reinterpret_cast<const Bytef *>(data));
 6796|       |
 6797|    725|    data_length -= strm_.avail_in;
 6798|    725|    data += strm_.avail_in;
 6799|       |
 6800|    725|    std::array<char, CPPHTTPLIB_COMPRESSION_BUFSIZ> buff{};
 6801|  52.4k|    while (strm_.avail_in > 0 && ret == Z_OK) {
  ------------------
  |  Branch (6801:12): [True: 51.7k, False: 618]
  |  Branch (6801:34): [True: 51.7k, False: 66]
  ------------------
 6802|  51.7k|      strm_.avail_out = static_cast<uInt>(buff.size());
 6803|  51.7k|      strm_.next_out = reinterpret_cast<Bytef *>(buff.data());
 6804|       |
 6805|  51.7k|      ret = inflate(&strm_, Z_NO_FLUSH);
 6806|       |
 6807|  51.7k|      assert(ret != Z_STREAM_ERROR);
  ------------------
  |  Branch (6807:7): [True: 51.7k, False: 0]
  ------------------
 6808|  51.7k|      switch (ret) {
  ------------------
  |  Branch (6808:15): [True: 37, False: 51.6k]
  ------------------
 6809|      2|      case Z_NEED_DICT:
  ------------------
  |  Branch (6809:7): [True: 2, False: 51.7k]
  ------------------
 6810|     37|      case Z_DATA_ERROR:
  ------------------
  |  Branch (6810:7): [True: 35, False: 51.6k]
  ------------------
 6811|     37|      case Z_MEM_ERROR: inflateEnd(&strm_); return false;
  ------------------
  |  Branch (6811:7): [True: 0, False: 51.7k]
  ------------------
 6812|  51.7k|      }
 6813|       |
 6814|  51.6k|      if (!callback(buff.data(), buff.size() - strm_.avail_out)) {
  ------------------
  |  Branch (6814:11): [True: 4, False: 51.6k]
  ------------------
 6815|      4|        return false;
 6816|      4|      }
 6817|  51.6k|    }
 6818|       |
 6819|    684|    if (ret != Z_OK && ret != Z_STREAM_END) { return false; }
  ------------------
  |  Branch (6819:9): [True: 66, False: 618]
  |  Branch (6819:24): [True: 0, False: 66]
  ------------------
 6820|       |
 6821|    684|  } while (data_length > 0);
  ------------------
  |  Branch (6821:12): [True: 0, False: 684]
  ------------------
 6822|       |
 6823|    684|  return true;
 6824|    725|}
_ZN7httplib6detail12BufferStreamD2Ev:
 3087|  1.96k|  ~BufferStream() override = default;
_ZN7httplib6detail12BufferStream5writeEPKcm:
10404|  13.0k|inline ssize_t BufferStream::write(const char *ptr, size_t size) {
10405|  13.0k|  buffer.append(ptr, size);
10406|  13.0k|  return static_cast<ssize_t>(size);
10407|  13.0k|}
_ZNK7httplib10ClientImpl6is_sslEv:
14015|  1.96k|inline bool ClientImpl::is_ssl() const { return false; }

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

