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; std::array<uint8_t, 256> buf;
auto p = std::begin(buf); auto p = std::begin(buf);
p = util::utos(p, start.count()); p = util::utos(start.count(), p);
*p++ = '\t'; *p++ = '\t';
if (success) { if (success) {
p = util::utos(p, req_stat->status); p = util::utos(req_stat->status, p);
} else { } else {
*p++ = '-'; *p++ = '-';
*p++ = '1'; *p++ = '1';
} }
*p++ = '\t'; *p++ = '\t';
p = util::utos(p, delta.count()); p = util::utos(delta.count(), p);
*p++ = '\n'; *p++ = '\n';
auto nwrite = static_cast<size_t>(std::distance(std::begin(buf), p)); 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; p = std::ranges::copy(auth, p).out;
if (port_exists) { if (port_exists) {
*p++ = ':'; *p++ = ':';
p = util::utos(p, u.port); p = util::utos(u.port, p);
} }
*p = '\0'; *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(M1, p).out;
p = std::ranges::copy(api_status_str, p).out; p = std::ranges::copy(api_status_str, p).out;
p = std::ranges::copy(M2, 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(data, p).out;
p = std::ranges::copy(M3, 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)) { if (u.field_set & (1 << URLPARSE_PORT)) {
*p++ = ':'; *p++ = ':';
p = util::utos(p, u.port); p = util::utos(u.port, p);
} }
*p = '\0'; *p = '\0';
@@ -1072,9 +1072,8 @@ void HttpsUpstream::error_reply(unsigned int status_code) {
output->append(get_config()->http.server_name); output->append(get_config()->http.server_name);
output->append("\r\nContent-Length: "); output->append("\r\nContent-Length: ");
std::array<char, NGHTTP2_MAX_UINT64_DIGITS> intbuf; std::array<char, NGHTTP2_MAX_UINT64_DIGITS> intbuf;
output->append( output->append(std::ranges::begin(intbuf),
StringRef{std::ranges::begin(intbuf), util::utos(html.size(), std::ranges::begin(intbuf)));
util::utos(std::ranges::begin(intbuf), html.size())});
output->append("\r\nDate: "); output->append("\r\nDate: ");
auto lgconf = log_config(); auto lgconf = log_config();
lgconf->update_tstamp(std::chrono::system_clock::now()); 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 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 } // namespace

View File

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

View File

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