Merge pull request #2435 from nghttp2/refactor-capitalize

Refactor http2::capitalize
This commit is contained in:
Tatsuhiro Tsujikawa
2025-05-27 19:40:15 +09:00
committed by GitHub
3 changed files with 142 additions and 7 deletions

View File

@@ -249,15 +249,58 @@ StringRef stringify_status(BlockAllocator &balloc, unsigned int status_code) {
}
}
void capitalize(DefaultMemchunks *buf, const StringRef &s) {
buf->append(util::upcase(s[0]));
for (size_t i = 1; i < s.size(); ++i) {
if (s[i - 1] == '-') {
buf->append(util::upcase(s[i]));
} else {
buf->append(s[i]);
struct Capitalizer {
template <std::weakly_incrementable O>
requires(std::indirectly_writable<O, char>)
constexpr O operator()(const StringRef &s, O result) noexcept {
*result++ = util::upcase(s[0]);
for (size_t i = 1; i < s.size(); ++i) {
if (s[i - 1] == '-') {
*result++ = util::upcase(s[i]);
} else {
*result++ = s[i];
}
}
return result;
}
};
namespace {
void capitalize_long(DefaultMemchunks *buf, const StringRef &s) {
buf->append(util::upcase(s[0]));
auto it = s.begin() + 1;
for (; it != s.end();) {
auto p = std::ranges::find(it, s.end(), '-');
p = std::ranges::find_if(p, s.end(), [](auto c) { return c != '-'; });
buf->append(it, p);
if (p == s.end()) {
return;
}
buf->append(util::upcase(*p));
it = p + 1;
}
}
} // namespace
void capitalize(DefaultMemchunks *buf, const StringRef &s) {
assert(!s.empty());
constexpr size_t max_namelen = 32;
if (s.size() > max_namelen) {
capitalize_long(buf, s);
return;
}
buf->append(s.size(), std::bind_front(Capitalizer{}, s));
}
bool lws(const char *value) {

View File

@@ -65,6 +65,7 @@ const MunitTest tests[]{
munit_void_test(test_http2_construct_push_component),
munit_void_test(test_http2_contains_trailers),
munit_void_test(test_http2_check_transfer_encoding),
munit_void_test(test_http2_capitalize),
munit_test_end(),
};
} // namespace
@@ -1187,4 +1188,94 @@ void test_http2_check_transfer_encoding(void) {
assert_false(http2::check_transfer_encoding(R"(chunked;foo="bar",,gzip)"_sr));
}
void test_http2_capitalize(void) {
MemchunkPool pool;
DefaultMemchunks m{&pool};
iovec iov;
{
http2::capitalize(&m, "content-length"_sr);
auto iovcnt = m.riovec(&iov, 1);
assert_int(1, ==, iovcnt);
assert_stdsv_equal(
"Content-Length"sv,
(std::string_view{static_cast<const char *>(iov.iov_base), iov.iov_len}));
m.reset();
}
{
http2::capitalize(&m, "altsvc"_sr);
auto iovcnt = m.riovec(&iov, 1);
assert_int(1, ==, iovcnt);
assert_stdsv_equal(
"Altsvc"sv,
(std::string_view{static_cast<const char *>(iov.iov_base), iov.iov_len}));
m.reset();
}
{
http2::capitalize(&m, "altsvc-"_sr);
auto iovcnt = m.riovec(&iov, 1);
assert_int(1, ==, iovcnt);
assert_stdsv_equal(
"Altsvc-"sv,
(std::string_view{static_cast<const char *>(iov.iov_base), iov.iov_len}));
m.reset();
}
{
http2::capitalize(&m, "alt--svc"_sr);
auto iovcnt = m.riovec(&iov, 1);
assert_int(1, ==, iovcnt);
assert_stdsv_equal(
"Alt--Svc"sv,
(std::string_view{static_cast<const char *>(iov.iov_base), iov.iov_len}));
m.reset();
}
{
http2::capitalize(&m, "sec-websocket----------------key"_sr);
auto iovcnt = m.riovec(&iov, 1);
assert_int(1, ==, iovcnt);
assert_stdsv_equal(
"Sec-Websocket----------------Key"sv,
(std::string_view{static_cast<const char *>(iov.iov_base), iov.iov_len}));
m.reset();
}
{
http2::capitalize(&m, "content--------------------length"_sr);
auto iovcnt = m.riovec(&iov, 1);
assert_int(1, ==, iovcnt);
assert_stdsv_equal(
"Content--------------------Length"sv,
(std::string_view{static_cast<const char *>(iov.iov_base), iov.iov_len}));
m.reset();
}
{
http2::capitalize(&m, "content--------------------length-"_sr);
auto iovcnt = m.riovec(&iov, 1);
assert_int(1, ==, iovcnt);
assert_stdsv_equal(
"Content--------------------Length-"sv,
(std::string_view{static_cast<const char *>(iov.iov_base), iov.iov_len}));
m.reset();
}
}
} // namespace shrpx

View File

@@ -54,6 +54,7 @@ munit_void_test_decl(test_http2_get_pure_path_component)
munit_void_test_decl(test_http2_construct_push_component)
munit_void_test_decl(test_http2_contains_trailers)
munit_void_test_decl(test_http2_check_transfer_encoding)
munit_void_test_decl(test_http2_capitalize)
} // namespace shrpx