Rewrite util::utos functions

This commit is contained in:
Tatsuhiro Tsujikawa
2025-05-19 18:33:42 +09:00
parent 3bca3282f1
commit 2f02abfe7a
7 changed files with 63 additions and 40 deletions

View File

@@ -1058,16 +1058,16 @@ void Client::on_stream_close(int32_t stream_id, bool success, bool final) {
std::array<uint8_t, 256> buf;
auto p = std::begin(buf);
p = util::utos(p, start.count());
p = util::utos(start.count(), p);
*p++ = '\t';
if (success) {
p = util::utos(p, req_stat->status);
p = util::utos(req_stat->status, p);
} else {
*p++ = '-';
*p++ = '1';
}
*p++ = '\t';
p = util::utos(p, delta.count());
p = util::utos(delta.count(), p);
*p++ = '\n';
auto nwrite = static_cast<size_t>(std::distance(std::begin(buf), p));

View File

@@ -1586,7 +1586,7 @@ int construct_push_component(BlockAllocator &balloc, StringRef &scheme,
p = std::ranges::copy(auth, p).out;
if (port_exists) {
*p++ = ':';
p = util::utos(p, u.port);
p = util::utos(u.port, p);
}
*p = '\0';

View File

@@ -130,7 +130,7 @@ int APIDownstreamConnection::send_reply(unsigned int http_status,
p = std::ranges::copy(M1, p).out;
p = std::ranges::copy(api_status_str, p).out;
p = std::ranges::copy(M2, p).out;
p = util::utos(p, http_status);
p = util::utos(http_status, p);
p = std::ranges::copy(data, p).out;
p = std::ranges::copy(M3, p).out;

View File

@@ -280,7 +280,7 @@ void rewrite_request_host_path_from_uri(BlockAllocator &balloc, Request &req,
if (u.field_set & (1 << URLPARSE_PORT)) {
*p++ = ':';
p = util::utos(p, u.port);
p = util::utos(u.port, p);
}
*p = '\0';
@@ -1072,9 +1072,8 @@ void HttpsUpstream::error_reply(unsigned int status_code) {
output->append(get_config()->http.server_name);
output->append("\r\nContent-Length: ");
std::array<char, NGHTTP2_MAX_UINT64_DIGITS> intbuf;
output->append(
StringRef{std::ranges::begin(intbuf),
util::utos(std::ranges::begin(intbuf), html.size())});
output->append(std::ranges::begin(intbuf),
util::utos(html.size(), std::ranges::begin(intbuf)));
output->append("\r\nDate: ");
auto lgconf = log_config();
lgconf->update_tstamp(std::chrono::system_clock::now());

View File

@@ -416,7 +416,7 @@ template <std::integral T> std::span<char> copy(T n, std::span<char> dest) {
return dest.first(0);
}
return {util::utos(std::ranges::begin(dest), n), std::ranges::end(dest)};
return {util::utos(n, std::ranges::begin(dest)), std::ranges::end(dest)};
}
} // namespace

View File

@@ -532,49 +532,64 @@ constexpr O tolower(R &&r, O result) {
// Returns string representation of |n| with 2 fractional digits.
std::string dtos(double n);
template <typename T> std::string utos(T n) {
std::string res;
template <std::integral T> constexpr std::string utos(T n) {
using namespace std::literals;
if (n == 0) {
res = "0";
return res;
return "0"s;
}
size_t nlen = 0;
for (auto t = n; t; t /= 10, ++nlen)
;
std::string res;
res.resize(nlen);
for (; n; n /= 10) {
res[--nlen] = (n % 10) + '0';
}
return res;
}
template <typename T, typename OutputIt> OutputIt utos(OutputIt dst, T n) {
template <std::integral T, std::weakly_incrementable O>
constexpr O utos(T n, O result) {
if (n == 0) {
*dst++ = '0';
return dst;
*result++ = '0';
return result;
}
size_t nlen = 0;
for (auto t = n; t; t /= 10, ++nlen)
;
auto p = dst + nlen;
auto res = p;
result = std::ranges::next(result, nlen);
auto p = result;
for (; n; n /= 10) {
*--p = (n % 10) + '0';
}
return res;
return result;
}
template <typename T>
template <std::integral T>
StringRef make_string_ref_uint(BlockAllocator &balloc, T n) {
auto iov = make_byte_ref(balloc, NGHTTP2_MAX_UINT64_DIGITS + 1);
auto p = std::begin(iov);
p = util::utos(p, n);
auto p = std::ranges::begin(iov);
p = util::utos(n, p);
*p = '\0';
return as_string_ref(std::begin(iov), p);
return as_string_ref(std::ranges::begin(iov), p);
}
template <typename T> std::string utos_unit(T n) {
char u = 0;
template <std::integral T> constexpr std::string utos_unit(T n) {
char u;
if (n >= (1 << 30)) {
u = 'G';
n /= (1 << 30);
@@ -584,17 +599,18 @@ template <typename T> std::string utos_unit(T n) {
} else if (n >= (1 << 10)) {
u = 'K';
n /= (1 << 10);
}
if (u == 0) {
} else {
return utos(n);
}
return utos(n) + u;
}
// Like utos_unit(), but 2 digits fraction part is followed.
template <typename T> std::string utos_funit(T n) {
char u = 0;
int b = 0;
template <std::integral T> constexpr std::string utos_funit(T n) {
char u;
int b;
if (n >= (1 << 30)) {
u = 'G';
b = 30;
@@ -604,28 +620,36 @@ template <typename T> std::string utos_funit(T n) {
} else if (n >= (1 << 10)) {
u = 'K';
b = 10;
}
if (b == 0) {
} else {
return utos(n);
}
return dtos(static_cast<double>(n) / (1 << b)) + u;
}
template <typename T> std::string utox(T n) {
std::string res;
template <std::integral T> constexpr std::string utox(T n) {
using namespace std::literals;
if (n == 0) {
res = "0";
return res;
return "0"s;
}
int i = 0;
T t = n;
for (; t; t /= 16, ++i)
;
std::string res;
res.resize(i);
--i;
for (; n; --i, n /= 16) {
res[i] = UPPER_XDIGITS[(n & 0x0f)];
}
return res;
}

View File

@@ -336,11 +336,11 @@ void test_util_ipv6_numeric_addr(void) {
void test_util_utos(void) {
uint8_t buf[32];
assert_stdstring_equal("0", (std::string{buf, util::utos(buf, 0)}));
assert_stdstring_equal("123", (std::string{buf, util::utos(buf, 123)}));
assert_stdstring_equal("0", (std::string{buf, util::utos(0, buf)}));
assert_stdstring_equal("123", (std::string{buf, util::utos(123, buf)}));
assert_stdstring_equal(
"18446744073709551615",
(std::string{buf, util::utos(buf, 18446744073709551615ULL)}));
(std::string{buf, util::utos(18446744073709551615ULL, buf)}));
}
void test_util_make_string_ref_uint(void) {