diff --git a/httplib.h b/httplib.h index 108f91f..0baed49 100644 --- a/httplib.h +++ b/httplib.h @@ -257,7 +257,7 @@ namespace detail { template typename std::enable_if::value, std::unique_ptr>::type -make_unique(Args &&...args) { +make_unique(Args &&... args) { return std::unique_ptr(new T(std::forward(args)...)); } @@ -490,7 +490,7 @@ public: virtual socket_t socket() const = 0; template - ssize_t write_format(const char *fmt, const Args &...args); + ssize_t write_format(const char *fmt, const Args &... args); ssize_t write(const char *ptr); ssize_t write(const std::string &s); }; @@ -1466,6 +1466,153 @@ private: }; #endif +/* + * Implementation of template methods. + */ + +namespace detail { + +template +inline void duration_to_sec_and_usec(const T &duration, U callback) { + auto sec = std::chrono::duration_cast(duration).count(); + auto usec = std::chrono::duration_cast( + duration - std::chrono::seconds(sec)) + .count(); + callback(sec, usec); +} + +template +inline T get_header_value(const Headers & /*headers*/, const char * /*key*/, + size_t /*id*/ = 0, uint64_t /*def*/ = 0) {} + +template <> +inline uint64_t get_header_value(const Headers &headers, + const char *key, size_t id, + uint64_t def) { + auto rng = headers.equal_range(key); + auto it = rng.first; + std::advance(it, static_cast(id)); + if (it != rng.second) { + return std::strtoull(it->second.data(), nullptr, 10); + } + return def; +} + +} // namespace detail + +template +inline T Request::get_header_value(const char *key, size_t id) const { + return detail::get_header_value(headers, key, id, 0); +} + +template +inline T Response::get_header_value(const char *key, size_t id) const { + return detail::get_header_value(headers, key, id, 0); +} + +template +inline ssize_t Stream::write_format(const char *fmt, const Args &... args) { + const auto bufsiz = 2048; + std::array buf; + +#if defined(_MSC_VER) && _MSC_VER < 1900 + auto sn = _snprintf_s(buf.data(), bufsiz - 1, buf.size() - 1, fmt, args...); +#else + auto sn = snprintf(buf.data(), buf.size() - 1, fmt, args...); +#endif + if (sn <= 0) { return sn; } + + auto n = static_cast(sn); + + if (n >= buf.size() - 1) { + std::vector glowable_buf(buf.size()); + + while (n >= glowable_buf.size() - 1) { + glowable_buf.resize(glowable_buf.size() * 2); +#if defined(_MSC_VER) && _MSC_VER < 1900 + n = static_cast(_snprintf_s(&glowable_buf[0], glowable_buf.size(), + glowable_buf.size() - 1, fmt, + args...)); +#else + n = static_cast( + snprintf(&glowable_buf[0], glowable_buf.size() - 1, fmt, args...)); +#endif + } + return write(&glowable_buf[0], n); + } else { + return write(buf.data(), n); + } +} + +template +inline Server & +Server::set_read_timeout(const std::chrono::duration &duration) { + detail::duration_to_sec_and_usec( + duration, [&](time_t sec, time_t usec) { set_read_timeout(sec, usec); }); + return *this; +} + +template +inline Server & +Server::set_write_timeout(const std::chrono::duration &duration) { + detail::duration_to_sec_and_usec( + duration, [&](time_t sec, time_t usec) { set_write_timeout(sec, usec); }); + return *this; +} + +template +inline Server & +Server::set_idle_interval(const std::chrono::duration &duration) { + detail::duration_to_sec_and_usec( + duration, [&](time_t sec, time_t usec) { set_idle_interval(sec, usec); }); + return *this; +} + +template +inline T Result::get_request_header_value(const char *key, size_t id) const { + return detail::get_header_value(request_headers_, key, id, 0); +} + +template +inline void ClientImpl::set_connection_timeout( + const std::chrono::duration &duration) { + detail::duration_to_sec_and_usec(duration, [&](time_t sec, time_t usec) { + set_connection_timeout(sec, usec); + }); +} + +template +inline void ClientImpl::set_read_timeout( + const std::chrono::duration &duration) { + detail::duration_to_sec_and_usec( + duration, [&](time_t sec, time_t usec) { set_read_timeout(sec, usec); }); +} + +template +inline void ClientImpl::set_write_timeout( + const std::chrono::duration &duration) { + detail::duration_to_sec_and_usec( + duration, [&](time_t sec, time_t usec) { set_write_timeout(sec, usec); }); +} + +template +inline void Client::set_connection_timeout( + const std::chrono::duration &duration) { + cli_->set_connection_timeout(duration); +} + +template +inline void +Client::set_read_timeout(const std::chrono::duration &duration) { + cli_->set_read_timeout(duration); +} + +template +inline void +Client::set_write_timeout(const std::chrono::duration &duration) { + cli_->set_write_timeout(duration); +} + // ---------------------------------------------------------------------------- /* @@ -2798,23 +2945,6 @@ inline const char *get_header_value(const Headers &headers, const char *key, return def; } -template -inline T get_header_value(const Headers & /*headers*/, const char * /*key*/, - size_t /*id*/ = 0, uint64_t /*def*/ = 0) {} - -template <> -inline uint64_t get_header_value(const Headers &headers, - const char *key, size_t id, - uint64_t def) { - auto rng = headers.equal_range(key); - auto it = rng.first; - std::advance(it, static_cast(id)); - if (it != rng.second) { - return std::strtoull(it->second.data(), nullptr, 10); - } - return def; -} - template inline bool parse_header(const char *beg, const char *end, T fn) { // Skip trailing spaces and tabs. @@ -3827,9 +3957,9 @@ inline std::pair make_digest_authentication_header( string response; { - auto H = algo == "SHA-256" ? detail::SHA_256 - : algo == "SHA-512" ? detail::SHA_512 - : detail::MD5; + auto H = algo == "SHA-256" + ? detail::SHA_256 + : algo == "SHA-512" ? detail::SHA_512 : detail::MD5; auto A1 = username + ":" + auth.at("realm") + ":" + password; @@ -3912,15 +4042,6 @@ private: ContentProviderWithoutLength content_provider_; }; -template -inline void duration_to_sec_and_usec(const T &duration, U callback) { - auto sec = std::chrono::duration_cast(duration).count(); - auto usec = std::chrono::duration_cast( - duration - std::chrono::seconds(sec)) - .count(); - callback(sec, usec); -} - } // namespace detail // Header utilities @@ -3963,11 +4084,6 @@ inline std::string Request::get_header_value(const char *key, size_t id) const { return detail::get_header_value(headers, key, id, ""); } -template -inline T Request::get_header_value(const char *key, size_t id) const { - return detail::get_header_value(headers, key, id, 0); -} - inline size_t Request::get_header_value_count(const char *key) const { auto r = headers.equal_range(key); return static_cast(std::distance(r.first, r.second)); @@ -4027,11 +4143,6 @@ inline std::string Response::get_header_value(const char *key, return detail::get_header_value(headers, key, id, ""); } -template -inline T Response::get_header_value(const char *key, size_t id) const { - return detail::get_header_value(headers, key, id, 0); -} - inline size_t Response::get_header_value_count(const char *key) const { auto r = headers.equal_range(key); return static_cast(std::distance(r.first, r.second)); @@ -4119,11 +4230,6 @@ inline std::string Result::get_request_header_value(const char *key, return detail::get_header_value(request_headers_, key, id, ""); } -template -inline T Result::get_request_header_value(const char *key, size_t id) const { - return detail::get_header_value(request_headers_, key, id, 0); -} - inline size_t Result::get_request_header_value_count(const char *key) const { auto r = request_headers_.equal_range(key); return static_cast(std::distance(r.first, r.second)); @@ -4138,40 +4244,6 @@ inline ssize_t Stream::write(const std::string &s) { return write(s.data(), s.size()); } -template -inline ssize_t Stream::write_format(const char *fmt, const Args &...args) { - const auto bufsiz = 2048; - std::array buf; - -#if defined(_MSC_VER) && _MSC_VER < 1900 - auto sn = _snprintf_s(buf.data(), bufsiz - 1, buf.size() - 1, fmt, args...); -#else - auto sn = snprintf(buf.data(), buf.size() - 1, fmt, args...); -#endif - if (sn <= 0) { return sn; } - - auto n = static_cast(sn); - - if (n >= buf.size() - 1) { - std::vector glowable_buf(buf.size()); - - while (n >= glowable_buf.size() - 1) { - glowable_buf.resize(glowable_buf.size() * 2); -#if defined(_MSC_VER) && _MSC_VER < 1900 - n = static_cast(_snprintf_s(&glowable_buf[0], glowable_buf.size(), - glowable_buf.size() - 1, fmt, - args...)); -#else - n = static_cast( - snprintf(&glowable_buf[0], glowable_buf.size() - 1, fmt, args...)); -#endif - } - return write(&glowable_buf[0], n); - } else { - return write(buf.data(), n); - } -} - namespace detail { // Socket stream implementation @@ -4449,42 +4521,18 @@ inline Server &Server::set_read_timeout(time_t sec, time_t usec) { return *this; } -template -inline Server & -Server::set_read_timeout(const std::chrono::duration &duration) { - detail::duration_to_sec_and_usec( - duration, [&](time_t sec, time_t usec) { set_read_timeout(sec, usec); }); - return *this; -} - inline Server &Server::set_write_timeout(time_t sec, time_t usec) { write_timeout_sec_ = sec; write_timeout_usec_ = usec; return *this; } -template -inline Server & -Server::set_write_timeout(const std::chrono::duration &duration) { - detail::duration_to_sec_and_usec( - duration, [&](time_t sec, time_t usec) { set_write_timeout(sec, usec); }); - return *this; -} - inline Server &Server::set_idle_interval(time_t sec, time_t usec) { idle_interval_sec_ = sec; idle_interval_usec_ = usec; return *this; } -template -inline Server & -Server::set_idle_interval(const std::chrono::duration &duration) { - detail::duration_to_sec_and_usec( - duration, [&](time_t sec, time_t usec) { set_idle_interval(sec, usec); }); - return *this; -} - inline Server &Server::set_payload_max_length(size_t length) { payload_max_length_ = length; return *this; @@ -5642,9 +5690,7 @@ inline bool ClientImpl::redirect(Request &req, Response &res, Error &error) { #ifdef CPPHTTPLIB_OPENSSL_SUPPORT SSLClient cli(next_host.c_str(), next_port); cli.copy_settings(*this); - if (ca_cert_store_) { - cli.set_ca_cert_store(ca_cert_store_); - } + if (ca_cert_store_) { cli.set_ca_cert_store(ca_cert_store_); } return detail::redirect(cli, req, res, next_path, location, error); #else return false; @@ -6453,38 +6499,16 @@ inline void ClientImpl::set_connection_timeout(time_t sec, time_t usec) { connection_timeout_usec_ = usec; } -template -inline void ClientImpl::set_connection_timeout( - const std::chrono::duration &duration) { - detail::duration_to_sec_and_usec(duration, [&](time_t sec, time_t usec) { - set_connection_timeout(sec, usec); - }); -} - inline void ClientImpl::set_read_timeout(time_t sec, time_t usec) { read_timeout_sec_ = sec; read_timeout_usec_ = usec; } -template -inline void ClientImpl::set_read_timeout( - const std::chrono::duration &duration) { - detail::duration_to_sec_and_usec( - duration, [&](time_t sec, time_t usec) { set_read_timeout(sec, usec); }); -} - inline void ClientImpl::set_write_timeout(time_t sec, time_t usec) { write_timeout_sec_ = sec; write_timeout_usec_ = usec; } -template -inline void ClientImpl::set_write_timeout( - const std::chrono::duration &duration) { - detail::duration_to_sec_and_usec( - duration, [&](time_t sec, time_t usec) { set_write_timeout(sec, usec); }); -} - inline void ClientImpl::set_basic_auth(const char *username, const char *password) { basic_auth_username_ = username; @@ -6554,7 +6578,7 @@ inline void ClientImpl::set_proxy_digest_auth(const char *username, #ifdef CPPHTTPLIB_OPENSSL_SUPPORT inline void ClientImpl::set_ca_cert_path(const char *ca_cert_file_path, - const char *ca_cert_dir_path) { + const char *ca_cert_dir_path) { if (ca_cert_file_path) { ca_cert_file_path_ = ca_cert_file_path; } if (ca_cert_dir_path) { ca_cert_dir_path_ = ca_cert_dir_path; } } @@ -7616,32 +7640,14 @@ inline void Client::set_connection_timeout(time_t sec, time_t usec) { cli_->set_connection_timeout(sec, usec); } -template -inline void Client::set_connection_timeout( - const std::chrono::duration &duration) { - cli_->set_connection_timeout(duration); -} - inline void Client::set_read_timeout(time_t sec, time_t usec) { cli_->set_read_timeout(sec, usec); } -template -inline void -Client::set_read_timeout(const std::chrono::duration &duration) { - cli_->set_read_timeout(duration); -} - inline void Client::set_write_timeout(time_t sec, time_t usec) { cli_->set_write_timeout(sec, usec); } -template -inline void -Client::set_write_timeout(const std::chrono::duration &duration) { - cli_->set_write_timeout(duration); -} - inline void Client::set_basic_auth(const char *username, const char *password) { cli_->set_basic_auth(username, password); }