summaryrefslogtreecommitdiffstats
path: root/src/util.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/util.cc')
-rw-r--r--src/util.cc250
1 files changed, 116 insertions, 134 deletions
diff --git a/src/util.cc b/src/util.cc
index 47151b2..e6c4214 100644
--- a/src/util.cc
+++ b/src/util.cc
@@ -191,11 +191,11 @@ bool in_attr_char(char c) {
StringRef percent_encode_token(BlockAllocator &balloc,
const StringRef &target) {
auto iov = make_byte_ref(balloc, target.size() * 3 + 1);
- auto p = percent_encode_token(iov.base, target);
+ auto p = percent_encode_token(std::begin(iov), target);
*p = '\0';
- return StringRef{iov.base, p};
+ return StringRef{std::span{std::begin(iov), p}};
}
size_t percent_encode_tokenlen(const StringRef &target) {
@@ -237,11 +237,11 @@ StringRef quote_string(BlockAllocator &balloc, const StringRef &target) {
}
auto iov = make_byte_ref(balloc, target.size() + cnt + 1);
- auto p = quote_string(iov.base, target);
+ auto p = quote_string(std::begin(iov), target);
*p = '\0';
- return StringRef{iov.base, p};
+ return StringRef{std::span{std::begin(iov), p}};
}
size_t quote_stringlen(const StringRef &target) {
@@ -465,13 +465,13 @@ time_t parse_http_date(const StringRef &s) {
tm tm{};
#ifdef _WIN32
// there is no strptime - use std::get_time
- std::stringstream sstr(s.str());
+ std::stringstream sstr(s.data());
sstr >> std::get_time(&tm, "%a, %d %b %Y %H:%M:%S GMT");
if (sstr.fail()) {
return 0;
}
#else // !_WIN32
- char *r = strptime(s.c_str(), "%a, %d %b %Y %H:%M:%S GMT", &tm);
+ char *r = strptime(s.data(), "%a, %d %b %Y %H:%M:%S GMT", &tm);
if (r == 0) {
return 0;
}
@@ -481,7 +481,7 @@ time_t parse_http_date(const StringRef &s) {
time_t parse_openssl_asn1_time_print(const StringRef &s) {
tm tm{};
- auto r = strptime(s.c_str(), "%b %d %H:%M:%S %Y GMT", &tm);
+ auto r = strptime(s.data(), "%b %d %H:%M:%S %Y GMT", &tm);
if (r == nullptr) {
return 0;
}
@@ -496,32 +496,22 @@ char upcase(char c) {
}
}
-std::string format_hex(const unsigned char *s, size_t len) {
+std::string format_hex(std::span<const uint8_t> s) {
std::string res;
- res.resize(len * 2);
+ res.resize(s.size() * 2);
- for (size_t i = 0; i < len; ++i) {
- unsigned char c = s[i];
+ format_hex(std::begin(res), s);
- res[i * 2] = LOWER_XDIGITS[c >> 4];
- res[i * 2 + 1] = LOWER_XDIGITS[c & 0x0f];
- }
return res;
}
-StringRef format_hex(BlockAllocator &balloc, const StringRef &s) {
+StringRef format_hex(BlockAllocator &balloc, std::span<const uint8_t> s) {
auto iov = make_byte_ref(balloc, s.size() * 2 + 1);
- auto p = iov.base;
-
- for (auto cc : s) {
- uint8_t c = cc;
- *p++ = LOWER_XDIGITS[c >> 4];
- *p++ = LOWER_XDIGITS[c & 0xf];
- }
+ auto p = format_hex(std::begin(iov), s);
*p = '\0';
- return StringRef{iov.base, p};
+ return StringRef{std::span{std::begin(iov), p}};
}
void to_token68(std::string &base64str) {
@@ -544,19 +534,18 @@ StringRef to_base64(BlockAllocator &balloc, const StringRef &token68str) {
// At most 3 padding '='
auto len = token68str.size() + 3;
auto iov = make_byte_ref(balloc, len + 1);
- auto p = iov.base;
-
- p = std::transform(std::begin(token68str), std::end(token68str), p,
- [](char c) {
- switch (c) {
- case '-':
- return '+';
- case '_':
- return '/';
- default:
- return c;
- }
- });
+
+ auto p = std::transform(std::begin(token68str), std::end(token68str),
+ std::begin(iov), [](char c) {
+ switch (c) {
+ case '-':
+ return '+';
+ case '_':
+ return '/';
+ default:
+ return c;
+ }
+ });
auto rem = token68str.size() & 0x3;
if (rem) {
@@ -565,7 +554,7 @@ StringRef to_base64(BlockAllocator &balloc, const StringRef &token68str) {
*p = '\0';
- return StringRef{iov.base, p};
+ return StringRef{std::span{std::begin(iov), p}};
}
namespace {
@@ -878,7 +867,7 @@ bool check_path(const std::string &path) {
path.find('\\') == std::string::npos &&
path.find("/../") == std::string::npos &&
path.find("/./") == std::string::npos &&
- !util::ends_with_l(path, "/..") && !util::ends_with_l(path, "/.");
+ !util::ends_with(path, "/.."_sr) && !util::ends_with(path, "/."_sr);
}
int64_t to_time64(const timeval &tv) {
@@ -886,8 +875,8 @@ int64_t to_time64(const timeval &tv) {
}
bool check_h2_is_selected(const StringRef &proto) {
- return streq(NGHTTP2_H2, proto) || streq(NGHTTP2_H2_16, proto) ||
- streq(NGHTTP2_H2_14, proto);
+ return NGHTTP2_H2 == proto || NGHTTP2_H2_16 == proto ||
+ NGHTTP2_H2_14 == proto;
}
namespace {
@@ -1148,58 +1137,63 @@ bool ipv6_numeric_addr(const char *host) {
}
namespace {
-std::pair<int64_t, size_t> parse_uint_digits(const void *ss, size_t len) {
- const uint8_t *s = static_cast<const uint8_t *>(ss);
- int64_t n = 0;
- size_t i;
- if (len == 0) {
- return {-1, 0};
+std::optional<std::pair<int64_t, StringRef>>
+parse_uint_digits(const StringRef &s) {
+ if (s.empty()) {
+ return {};
}
+
constexpr int64_t max = std::numeric_limits<int64_t>::max();
- for (i = 0; i < len; ++i) {
- if ('0' <= s[i] && s[i] <= '9') {
- if (n > max / 10) {
- return {-1, 0};
- }
- n *= 10;
- if (n > max - (s[i] - '0')) {
- return {-1, 0};
- }
- n += s[i] - '0';
- continue;
+
+ int64_t n = 0;
+ size_t i = 0;
+
+ for (auto c : s) {
+ if ('0' > c || c > '9') {
+ break;
}
- break;
+
+ if (n > max / 10) {
+ return {};
+ }
+
+ n *= 10;
+
+ if (n > max - (c - '0')) {
+ return {};
+ }
+
+ n += c - '0';
+
+ ++i;
}
+
if (i == 0) {
- return {-1, 0};
+ return {};
}
- return {n, i};
+
+ return std::pair{n, s.substr(i)};
}
} // namespace
-int64_t parse_uint_with_unit(const char *s) {
- return parse_uint_with_unit(reinterpret_cast<const uint8_t *>(s), strlen(s));
-}
+std::optional<int64_t> parse_uint_with_unit(const StringRef &s) {
+ auto r = parse_uint_digits(s);
+ if (!r) {
+ return {};
+ }
-int64_t parse_uint_with_unit(const StringRef &s) {
- return parse_uint_with_unit(s.byte(), s.size());
-}
+ auto [n, rest] = *r;
-int64_t parse_uint_with_unit(const uint8_t *s, size_t len) {
- int64_t n;
- size_t i;
- std::tie(n, i) = parse_uint_digits(s, len);
- if (n == -1) {
- return -1;
- }
- if (i == len) {
+ if (rest.empty()) {
return n;
}
- if (i + 1 != len) {
- return -1;
+
+ if (rest.size() != 1) {
+ return {};
}
+
int mul = 1;
- switch (s[i]) {
+ switch (rest[0]) {
case 'K':
case 'k':
mul = 1 << 10;
@@ -1213,94 +1207,81 @@ int64_t parse_uint_with_unit(const uint8_t *s, size_t len) {
mul = 1 << 30;
break;
default:
- return -1;
+ return {};
}
+
constexpr int64_t max = std::numeric_limits<int64_t>::max();
if (n > max / mul) {
- return -1;
+ return {};
}
- return n * mul;
-}
-int64_t parse_uint(const char *s) {
- return parse_uint(reinterpret_cast<const uint8_t *>(s), strlen(s));
-}
-
-int64_t parse_uint(const std::string &s) {
- return parse_uint(reinterpret_cast<const uint8_t *>(s.c_str()), s.size());
-}
-
-int64_t parse_uint(const StringRef &s) {
- return parse_uint(s.byte(), s.size());
+ return n * mul;
}
-int64_t parse_uint(const uint8_t *s, size_t len) {
- int64_t n;
- size_t i;
- std::tie(n, i) = parse_uint_digits(s, len);
- if (n == -1 || i != len) {
- return -1;
+std::optional<int64_t> parse_uint(const StringRef &s) {
+ auto r = parse_uint_digits(s);
+ if (!r || !(*r).second.empty()) {
+ return {};
}
- return n;
-}
-
-double parse_duration_with_unit(const char *s) {
- return parse_duration_with_unit(reinterpret_cast<const uint8_t *>(s),
- strlen(s));
-}
-double parse_duration_with_unit(const StringRef &s) {
- return parse_duration_with_unit(s.byte(), s.size());
+ return (*r).first;
}
-double parse_duration_with_unit(const uint8_t *s, size_t len) {
+std::optional<double> parse_duration_with_unit(const StringRef &s) {
constexpr auto max = std::numeric_limits<int64_t>::max();
- int64_t n;
- size_t i;
- std::tie(n, i) = parse_uint_digits(s, len);
- if (n == -1) {
- goto fail;
+ auto r = parse_uint_digits(s);
+ if (!r) {
+ return {};
}
- if (i == len) {
+
+ auto [n, rest] = *r;
+
+ if (rest.empty()) {
return static_cast<double>(n);
}
- switch (s[i]) {
+
+ switch (rest[0]) {
case 'S':
case 's':
// seconds
- if (i + 1 != len) {
- goto fail;
+ if (rest.size() != 1) {
+ return {};
}
+
return static_cast<double>(n);
case 'M':
case 'm':
- if (i + 1 == len) {
+ if (rest.size() == 1) {
// minutes
if (n > max / 60) {
- goto fail;
+ return {};
}
+
return static_cast<double>(n) * 60;
}
- if (i + 2 != len || (s[i + 1] != 's' && s[i + 1] != 'S')) {
- goto fail;
+ if (rest.size() != 2 || (rest[1] != 's' && rest[1] != 'S')) {
+ return {};
}
+
// milliseconds
return static_cast<double>(n) / 1000.;
case 'H':
case 'h':
// hours
- if (i + 1 != len) {
- goto fail;
+ if (rest.size() != 1) {
+ return {};
}
+
if (n > max / 3600) {
- goto fail;
+ return {};
}
+
return static_cast<double>(n) * 3600;
+ default:
+ return {};
}
-fail:
- return std::numeric_limits<double>::infinity();
}
std::string duration_str(double t) {
@@ -1362,13 +1343,13 @@ std::string dtos(double n) {
StringRef make_http_hostport(BlockAllocator &balloc, const StringRef &host,
uint16_t port) {
auto iov = make_byte_ref(balloc, host.size() + 2 + 1 + 5 + 1);
- return make_http_hostport(iov.base, host, port);
+ return make_http_hostport(std::begin(iov), host, port);
}
StringRef make_hostport(BlockAllocator &balloc, const StringRef &host,
uint16_t port) {
auto iov = make_byte_ref(balloc, host.size() + 2 + 1 + 5 + 1);
- return make_hostport(iov.base, host, port);
+ return make_hostport(std::begin(iov), host, port);
}
namespace {
@@ -1611,7 +1592,7 @@ int read_mime_types(std::map<std::string, std::string> &res,
StringRef percent_decode(BlockAllocator &balloc, const StringRef &src) {
auto iov = make_byte_ref(balloc, src.size() * 3 + 1);
- auto p = iov.base;
+ auto p = std::begin(iov);
for (auto first = std::begin(src); first != std::end(src); ++first) {
if (*first != '%') {
*p++ = *first;
@@ -1628,7 +1609,7 @@ StringRef percent_decode(BlockAllocator &balloc, const StringRef &src) {
*p++ = *first;
}
*p = '\0';
- return StringRef{iov.base, p};
+ return StringRef{std::span{std::begin(iov), p}};
}
// Returns x**y
@@ -1669,7 +1650,7 @@ int message_digest(uint8_t *res, const EVP_MD *meth, const StringRef &s) {
return -1;
}
- rv = EVP_DigestUpdate(ctx, s.c_str(), s.size());
+ rv = EVP_DigestUpdate(ctx, s.data(), s.size());
if (rv != 1) {
return -1;
}
@@ -1707,11 +1688,12 @@ bool is_hex_string(const StringRef &s) {
return true;
}
-StringRef decode_hex(BlockAllocator &balloc, const StringRef &s) {
+std::span<const uint8_t> decode_hex(BlockAllocator &balloc,
+ const StringRef &s) {
auto iov = make_byte_ref(balloc, s.size() + 1);
- auto p = decode_hex(iov.base, s);
+ auto p = decode_hex(std::begin(iov), s);
*p = '\0';
- return StringRef{iov.base, p};
+ return {std::begin(iov), p};
}
StringRef extract_host(const StringRef &hostport) {
@@ -1824,7 +1806,7 @@ StringRef rstrip(BlockAllocator &balloc, const StringRef &s) {
return s;
}
- return make_string_ref(balloc, StringRef{s.c_str(), s.size() - len});
+ return make_string_ref(balloc, StringRef{s.data(), s.size() - len});
}
#ifdef ENABLE_HTTP3