Merge pull request #2394 from nghttp2/refine-output-iterator

Refine output iterator requirements
This commit is contained in:
Tatsuhiro Tsujikawa
2025-05-20 22:38:37 +09:00
committed by GitHub
2 changed files with 19 additions and 4 deletions

View File

@@ -49,6 +49,7 @@ constexpr char B64_CHARS[] = {
constexpr size_t encode_length(size_t n) { return (n + 2) / 3 * 4; } constexpr size_t encode_length(size_t n) { return (n + 2) / 3 * 4; }
template <std::input_iterator I, std::weakly_incrementable O> template <std::input_iterator I, std::weakly_incrementable O>
requires(std::indirectly_writable<O, char>)
O encode(I first, I last, O result) { O encode(I first, I last, O result) {
auto len = std::ranges::distance(first, last); auto len = std::ranges::distance(first, last);
if (len == 0) { if (len == 0) {
@@ -96,6 +97,7 @@ O encode(I first, I last, O result) {
} }
template <std::ranges::input_range R, std::weakly_incrementable O> template <std::ranges::input_range R, std::weakly_incrementable O>
requires(std::indirectly_writable<O, char>)
O encode(R &&r, O result) { O encode(R &&r, O result) {
return encode(std::ranges::begin(r), std::ranges::end(r), std::move(result)); return encode(std::ranges::begin(r), std::ranges::end(r), std::move(result));
} }
@@ -115,6 +117,7 @@ template <std::ranges::input_range R> std::string encode(R &&r) {
} }
template <std::input_iterator I, std::weakly_incrementable O> template <std::input_iterator I, std::weakly_incrementable O>
requires(std::indirectly_writable<O, uint8_t>)
O decode(I first, I last, O result) { O decode(I first, I last, O result) {
static constexpr int INDEX_TABLE[] = { static constexpr int INDEX_TABLE[] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,

View File

@@ -172,6 +172,7 @@ constexpr uint32_t hex_to_uint(char c) noexcept {
} }
template <std::input_iterator I, std::weakly_incrementable O> template <std::input_iterator I, std::weakly_incrementable O>
requires(std::indirectly_copyable<I, O>)
constexpr O percent_decode(I first, I last, O result) { constexpr O percent_decode(I first, I last, O result) {
for (; first != last; ++first) { for (; first != last; ++first) {
if (*first != '%') { if (*first != '%') {
@@ -233,6 +234,7 @@ StringRef percent_decode(BlockAllocator &balloc, R &&r) {
// Percent encode a range [|first|, |last|) if a character is not in // Percent encode a range [|first|, |last|) if a character is not in
// token or '%'. // token or '%'.
template <std::input_iterator I, std::weakly_incrementable O> template <std::input_iterator I, std::weakly_incrementable O>
requires(std::indirectly_copyable<I, O>)
constexpr O percent_encode_token(I first, I last, O result) noexcept { constexpr O percent_encode_token(I first, I last, O result) noexcept {
for (; first != last; ++first) { for (; first != last; ++first) {
uint8_t c = *first; uint8_t c = *first;
@@ -251,6 +253,7 @@ constexpr O percent_encode_token(I first, I last, O result) noexcept {
} }
template <std::ranges::input_range R, std::weakly_incrementable O> template <std::ranges::input_range R, std::weakly_incrementable O>
requires(std::indirectly_copyable<std::ranges::iterator_t<R>, O>)
constexpr O percent_encode_token(R &&r, O result) { constexpr O percent_encode_token(R &&r, O result) {
return percent_encode_token(std::ranges::begin(r), std::ranges::end(r), return percent_encode_token(std::ranges::begin(r), std::ranges::end(r),
std::move(result)); std::move(result));
@@ -281,6 +284,7 @@ constexpr size_t percent_encode_tokenlen(R &&r) noexcept {
// element past the last element stored. Currently, this function // element past the last element stored. Currently, this function
// just replace '"' with '\"'. // just replace '"' with '\"'.
template <std::input_iterator I, std::weakly_incrementable O> template <std::input_iterator I, std::weakly_incrementable O>
requires(std::indirectly_copyable<I, O>)
constexpr O quote_string(I first, I last, O result) noexcept { constexpr O quote_string(I first, I last, O result) noexcept {
for (; first != last; ++first) { for (; first != last; ++first) {
if (*first == '"') { if (*first == '"') {
@@ -295,6 +299,7 @@ constexpr O quote_string(I first, I last, O result) noexcept {
} }
template <std::ranges::input_range R, std::weakly_incrementable O> template <std::ranges::input_range R, std::weakly_incrementable O>
requires(std::indirectly_copyable<std::ranges::iterator_t<R>, O>)
constexpr O quote_string(R &&r, O result) { constexpr O quote_string(R &&r, O result) {
return quote_string(std::ranges::begin(r), std::ranges::end(r), return quote_string(std::ranges::begin(r), std::ranges::end(r),
std::move(result)); std::move(result));
@@ -339,7 +344,8 @@ static constexpr char LOWER_XDIGITS[] = "0123456789abcdef";
// result in another range, beginning at |result|. It returns an // result in another range, beginning at |result|. It returns an
// output iterator to the element past the last element stored. // output iterator to the element past the last element stored.
template <std::input_iterator I, std::weakly_incrementable O> template <std::input_iterator I, std::weakly_incrementable O>
requires(sizeof(std::iter_value_t<I>) == sizeof(uint8_t)) requires(std::indirectly_writable<O, char> &&
sizeof(std::iter_value_t<I>) == sizeof(uint8_t))
constexpr O format_hex(I first, I last, O result) noexcept { constexpr O format_hex(I first, I last, O result) noexcept {
for (; first != last; ++first) { for (; first != last; ++first) {
uint8_t c = *first; uint8_t c = *first;
@@ -354,7 +360,8 @@ constexpr O format_hex(I first, I last, O result) noexcept {
// beginning at |result|. It returns an output iterator to the // beginning at |result|. It returns an output iterator to the
// element past the last element stored. // element past the last element stored.
template <std::ranges::input_range R, std::weakly_incrementable O> template <std::ranges::input_range R, std::weakly_incrementable O>
requires(sizeof(std::ranges::range_value_t<R>) == sizeof(uint8_t)) requires(std::indirectly_writable<O, char> &&
sizeof(std::ranges::range_value_t<R>) == sizeof(uint8_t))
constexpr O format_hex(R &&r, O result) noexcept { constexpr O format_hex(R &&r, O result) noexcept {
return format_hex(std::ranges::begin(r), std::ranges::end(r), return format_hex(std::ranges::begin(r), std::ranges::end(r),
std::move(result)); std::move(result));
@@ -393,10 +400,11 @@ constexpr std::string format_hex(R &&r) {
// stored. This function assumes a range [|first|, |last|) is hex // stored. This function assumes a range [|first|, |last|) is hex
// string, that is is_hex_string(|first|, |last|) == true. // string, that is is_hex_string(|first|, |last|) == true.
template <std::input_iterator I, std::weakly_incrementable O> template <std::input_iterator I, std::weakly_incrementable O>
requires(std::indirectly_writable<O, uint8_t>)
constexpr O decode_hex(I first, I last, O result) { constexpr O decode_hex(I first, I last, O result) {
for (; first != last; first = std::ranges::next(first, 2)) { for (; first != last; first = std::ranges::next(first, 2)) {
*result++ = *result++ = static_cast<uint8_t>((hex_to_uint(*first) << 4) |
(hex_to_uint(*first) << 4) | hex_to_uint(*std::ranges::next(first, 1)); hex_to_uint(*std::ranges::next(first, 1)));
} }
return result; return result;
@@ -407,6 +415,7 @@ constexpr O decode_hex(I first, I last, O result) {
// element past the last element stored. This function assumes |r| is // element past the last element stored. This function assumes |r| is
// hex string, that is is_hex_string(r) == true. // hex string, that is is_hex_string(r) == true.
template <std::ranges::input_range R, std::weakly_incrementable O> template <std::ranges::input_range R, std::weakly_incrementable O>
requires(std::indirectly_writable<O, uint8_t>)
constexpr O decode_hex(R &&r, O result) { constexpr O decode_hex(R &&r, O result) {
return decode_hex(std::ranges::begin(r), std::ranges::end(r), return decode_hex(std::ranges::begin(r), std::ranges::end(r),
std::move(result)); std::move(result));
@@ -554,6 +563,7 @@ constexpr bool streq(R1 &&a, R2 &&b) {
// returns an output iterator to the element past the last element // returns an output iterator to the element past the last element
// stored. // stored.
template <std::input_iterator I, std::weakly_incrementable O> template <std::input_iterator I, std::weakly_incrementable O>
requires(std::indirectly_copyable<I, O>)
constexpr O tolower(I first, I last, O result) { constexpr O tolower(I first, I last, O result) {
return std::ranges::transform(std::move(first), std::move(last), return std::ranges::transform(std::move(first), std::move(last),
std::move(result), lowcase) std::move(result), lowcase)
@@ -564,6 +574,7 @@ constexpr O tolower(I first, I last, O result) {
// result in another range, beginning at |result|. It returns an // result in another range, beginning at |result|. It returns an
// output iterator to the element past the last element stored. // output iterator to the element past the last element stored.
template <std::ranges::input_range R, std::weakly_incrementable O> template <std::ranges::input_range R, std::weakly_incrementable O>
requires(std::indirectly_copyable<std::ranges::iterator_t<R>, O>)
constexpr O tolower(R &&r, O result) { constexpr O tolower(R &&r, O result) {
return std::ranges::transform(std::forward<R>(r), std::move(result), lowcase) return std::ranges::transform(std::forward<R>(r), std::move(result), lowcase)
.out; .out;
@@ -595,6 +606,7 @@ template <std::integral T> constexpr std::string utos(T n) {
} }
template <std::integral T, std::weakly_incrementable O> template <std::integral T, std::weakly_incrementable O>
requires(std::indirectly_writable<O, char>)
constexpr O utos(T n, O result) { constexpr O utos(T n, O result) {
if (n == 0) { if (n == 0) {
*result++ = '0'; *result++ = '0';