Merge pull request #2388 from nghttp2/rewrite-quote_string

Rewrite util::quote_string
This commit is contained in:
Tatsuhiro Tsujikawa
2025-05-19 19:07:03 +09:00
committed by GitHub
5 changed files with 57 additions and 47 deletions

View File

@@ -208,10 +208,11 @@ StringRef make_string_ref(BlockAllocator &alloc, I first, I last) {
return StringRef{dst, p};
}
// Makes a copy of |src|. The resulting string will be
// Makes a copy of |r| as StringRef. The resulting string will be
// NULL-terminated.
inline StringRef make_string_ref(BlockAllocator &alloc, const StringRef &src) {
return make_string_ref(alloc, std::ranges::begin(src), std::ranges::end(src));
template <std::ranges::input_range R>
StringRef make_string_ref(BlockAllocator &alloc, R &&r) {
return make_string_ref(alloc, std::ranges::begin(r), std::ranges::end(r));
}
// private function used in concat_string_ref. this is the base

View File

@@ -246,7 +246,7 @@ StringRef create_altsvc_header_value(BlockAllocator &balloc,
for (auto &altsvc : altsvcs) {
p = util::percent_encode_token(altsvc.protocol_id, p);
p = std::ranges::copy("=\""sv, p).out;
p = util::quote_string(p, altsvc.host);
p = util::quote_string(altsvc.host, p);
*p++ = ':';
p = std::ranges::copy(altsvc.service, p).out;
*p++ = '"';

View File

@@ -150,35 +150,6 @@ bool in_attr_char(char c) {
return util::in_token(c);
}
StringRef quote_string(BlockAllocator &balloc, const StringRef &target) {
auto cnt = std::count(std::begin(target), std::end(target), '"');
if (cnt == 0) {
return make_string_ref(balloc, target);
}
auto iov = make_byte_ref(balloc, target.size() + cnt + 1);
auto p = quote_string(std::begin(iov), target);
*p = '\0';
return as_string_ref(std::begin(iov), p);
}
size_t quote_stringlen(const StringRef &target) {
size_t n = 0;
for (auto c : target) {
if (c == '"') {
n += 2;
} else {
++n;
}
}
return n;
}
namespace {
template <typename Iterator>
Iterator cpydig(Iterator d, uint32_t n, size_t len) {

View File

@@ -259,28 +259,62 @@ constexpr size_t percent_encode_tokenlen(R &&r) noexcept {
return n;
}
// Returns quotedString version of |target|. Currently, this function
// Quote a range [|first|, |last|) and stores the result in another
// range, beginning at |result|. It returns an output iterator to the
// element past the last element stored. Currently, this function
// just replace '"' with '\"'.
StringRef quote_string(BlockAllocator &balloc, const StringRef &target);
template <typename OutputIt>
OutputIt quote_string(OutputIt it, const StringRef &target) {
for (auto c : target) {
if (c == '"') {
*it++ = '\\';
*it++ = '"';
template <std::input_iterator I, std::weakly_incrementable O>
constexpr O quote_string(I first, I last, O result) noexcept {
for (; first != last; ++first) {
if (*first == '"') {
*result++ = '\\';
*result++ = '"';
} else {
*it++ = c;
*result++ = *first;
}
}
return it;
return result;
}
template <std::ranges::input_range R, std::weakly_incrementable O>
constexpr O quote_string(R &&r, O result) {
return quote_string(std::ranges::begin(r), std::ranges::end(r),
std::move(result));
}
template <std::ranges::input_range R>
StringRef quote_string(BlockAllocator &balloc, R &&r) {
auto cnt = std::ranges::count(r, '"');
if (cnt == 0) {
return make_string_ref(balloc, std::forward<R>(r));
}
auto iov = make_byte_ref(balloc, std::ranges::distance(r) + cnt + 1);
auto p = quote_string(std::forward<R>(r), std::ranges::begin(iov));
*p = '\0';
return as_string_ref(std::ranges::begin(iov), p);
}
// Returns the number of bytes written by quote_string with the same
// |target| parameter. The return value does not include a terminal
// NUL byte.
size_t quote_stringlen(const StringRef &target);
// |r| parameter. The return value does not include a terminal NUL
// byte.
template <std::ranges::input_range R> constexpr size_t quote_stringlen(R &&r) {
size_t n = 0;
for (auto c : r) {
if (c == '"') {
n += 2;
} else {
++n;
}
}
return n;
}
static constexpr char LOWER_XDIGITS[] = "0123456789abcdef";

View File

@@ -246,6 +246,10 @@ void test_util_quote_string(void) {
assert_stdsv_equal(""sv, util::quote_string(balloc, ""_sr));
assert_stdsv_equal("\\\"alpha\\\""sv,
util::quote_string(balloc, "\"alpha\""_sr));
assert_size("\\\"alpha\\\""sv.size(), ==,
util::quote_stringlen("\"alpha\""_sr));
assert_size(0, ==, util::quote_stringlen(""_sr));
}
void test_util_utox(void) {