mirror of
https://github.com/nghttp2/nghttp2.git
synced 2025-12-06 18:18:52 +08:00
Merge pull request #2388 from nghttp2/rewrite-quote_string
Rewrite util::quote_string
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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++ = '"';
|
||||
|
||||
29
src/util.cc
29
src/util.cc
@@ -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) {
|
||||
|
||||
62
src/util.h
62
src/util.h
@@ -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";
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user