Skip to content

Commit 6d19ac8

Browse files
committed
Migrate to capy post-cppalliance#262 buffer API
cppalliance/capy#262 removes the slice CPO machinery (`capy::prefix`, `capy::sans_prefix`, `capy::remove_prefix`, `capy::remove_suffix`, `capy::keep_prefix`, `capy::slice_of<>`) and the `capy::const_buffer_pair` / `capy::mutable_buffer_pair` aliases. boost::http migrates to the replacements: - `capy::const_buffer_pair` / `capy::mutable_buffer_pair` --> `std::array<capy::const_buffer, 2>` / `std::array<capy::mutable_buffer, 2>`. - `capy::prefix(seq, n)` returning a 2-element buffer pair --> local helper `prefix_pair(seq, n)` in `src/parser.cpp` that constructs the trimmed array directly. Retained for the call sites that consume the result as a std::array (i.e. assigning to a parser member or passing to `filter::process`). - For one parser site where the result is consumed by `capy::buffer_copy`, the migration uses `capy::buffer_slice` directly: `auto chunk = capy::buffer_slice(cb0_.data(), 0, n);` then `buffer_copy(target, chunk.data())`. Demonstrates the by-value buffer_slice's idiomatic use; the slice owns its buffer-sequence copy and works with the prvalue `cb0_.data()`. - `capy::remove_prefix(pair, n)` / `capy::remove_suffix(pair, n)` on 2-element buffer pairs --> local helpers `trim_prefix_pair` / `trim_suffix_pair` in `src/serializer.cpp`. Retained for `out_prepare()`'s in-place std::array trim. - `capy::remove_prefix(buf, n)` on a single buffer --> `buf += n` (member operator already provided by capy). - `capy::sans_prefix(seq, n)` --> `capy::buffer_slice(seq, n)` (returns a Slice exposing the buffer sequence via `.data()`). In iterative consumption loops, advance an existing slice in place via `slice.remove_prefix(n)`. - `filter::process` now takes `boost::span<const capy::mutable_buffer>` and `std::array<capy::const_buffer, 2>` directly, and drives the loop using `capy::buffer_slice` internally. - Test serializer.cpp's `read_some` builds a slice in one expression via `capy::buffer_slice(sr.prepare().value(), 0, 256)` and iterates `.data()`. Since capy's buffer_slice captures its underlying buffer sequence by value, the prvalue `sr.prepare() .value()` is safe — the slice owns its own copy. Coordinated with capy PR cppalliance/capy#262. Merge order: this PR lands before cppalliance#262 (so http remains buildable against capy's \`develop\` during the brief window).
1 parent 5cd36d3 commit 6d19ac8

8 files changed

Lines changed: 137 additions & 48 deletions

File tree

include/boost/http/parser.hpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,15 @@
1717
#include <boost/http/error.hpp>
1818

1919
#include <boost/capy/buffers/buffer_copy.hpp>
20-
#include <boost/capy/buffers/buffer_pair.hpp>
21-
#include <boost/capy/buffers/slice.hpp>
20+
#include <boost/capy/buffers/buffer_slice.hpp>
2221
#include <boost/capy/concept/read_stream.hpp>
2322
#include <boost/capy/concept/write_sink.hpp>
2423
#include <boost/capy/cond.hpp>
2524
#include <boost/capy/error.hpp>
2625
#include <boost/capy/io_task.hpp>
2726
#include <boost/core/span.hpp>
2827

28+
#include <array>
2929
#include <cstddef>
3030
#include <cstdint>
3131
#include <memory>
@@ -526,7 +526,7 @@ read(Stream& stream, MB buffers)
526526
co_return {{}, 0};
527527

528528
std::size_t total = 0;
529-
auto dest = capy::sans_prefix(buffers, 0);
529+
auto dest = capy::buffer_slice(buffers);
530530

531531
for(;;)
532532
{
@@ -538,12 +538,12 @@ read(Stream& stream, MB buffers)
538538
auto body_data = pull_body();
539539
if(capy::buffer_size(body_data) > 0)
540540
{
541-
std::size_t copied = capy::buffer_copy(dest, body_data);
541+
std::size_t copied = capy::buffer_copy(dest.data(), body_data);
542542
consume_body(copied);
543543
total += copied;
544-
dest = capy::sans_prefix(dest, copied);
544+
dest.remove_prefix(copied);
545545

546-
if(capy::buffer_empty(dest))
546+
if(capy::buffer_empty(dest.data()))
547547
co_return {{}, total};
548548
}
549549

include/boost/http/serializer.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,13 @@
1616
#include <boost/http/error.hpp>
1717

1818
#include <boost/capy/buffers.hpp>
19-
#include <boost/capy/buffers/buffer_pair.hpp>
2019
#include <boost/capy/concept/buffer_sink.hpp>
2120
#include <boost/capy/concept/write_stream.hpp>
2221
#include <boost/capy/io_task.hpp>
2322
#include <boost/core/span.hpp>
2423
#include <boost/system/result.hpp>
2524

25+
#include <array>
2626
#include <cstddef>
2727
#include <cstring>
2828
#include <type_traits>
@@ -82,7 +82,7 @@ class serializer
8282
of mutable buffers for streaming.
8383
*/
8484
using mutable_buffers_type =
85-
capy::mutable_buffer_pair;
85+
std::array<capy::mutable_buffer, 2>;
8686

8787
/** The type used to represent a sequence of
8888
constant buffers that refers to the output

src/detail/array_of_const_buffers.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@
1212

1313
#include <boost/http/detail/except.hpp>
1414

15-
#include <boost/capy/buffers/slice.hpp>
16-
1715
namespace boost {
1816
namespace http {
1917
namespace detail {
@@ -38,7 +36,7 @@ consume(std::size_t n)
3836
auto* p = base_ + pos_;
3937
if(n < p->size())
4038
{
41-
capy::remove_prefix(*p, n);
39+
*p += n;
4240
return;
4341
}
4442
n -= p->size();

src/detail/filter.cpp

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,36 +10,57 @@
1010

1111
#include "src/detail/filter.hpp"
1212

13+
#include <boost/capy/buffers/buffer_slice.hpp>
1314
#include <boost/capy/buffers/front.hpp>
1415

1516
namespace boost {
1617
namespace http {
1718
namespace detail {
1819

20+
namespace {
21+
22+
// Returns true if the slice's current data view contains at most one
23+
// non-empty buffer (i.e., we are processing the last logical chunk).
24+
template<class Slice>
25+
bool single_or_empty(Slice const& s)
26+
{
27+
auto d = s.data();
28+
auto it = d.begin();
29+
auto const end_it = d.end();
30+
if(it == end_it)
31+
return true;
32+
++it;
33+
return it == end_it;
34+
}
35+
36+
} // anonymous
37+
1938
auto
2039
filter::
2140
process(
22-
capy::slice_of<
23-
boost::span<const capy::mutable_buffer>> out,
24-
capy::const_buffer_pair in,
41+
boost::span<const capy::mutable_buffer> out_seq,
42+
std::array<capy::const_buffer, 2> in_seq,
2543
bool more) -> results
2644
{
45+
auto out = capy::buffer_slice(out_seq);
46+
auto in = capy::buffer_slice(in_seq);
47+
2748
results rv;
2849
bool p_more = true;
2950
for(;;)
3051
{
31-
if(!more && p_more && in[1].size() == 0)
52+
if(!more && p_more && single_or_empty(in))
3253
{
33-
if(capy::buffer_size(out) < min_out_buffer())
54+
if(capy::buffer_size(out.data()) < min_out_buffer())
3455
{
3556
rv.out_short = true;
3657
return rv;
3758
}
3859
p_more = false;
3960
}
4061

41-
auto ob = capy::front(out);
42-
auto ib = capy::front(in);
62+
auto ob = capy::front(out.data());
63+
auto ib = capy::front(in.data());
4364
auto rs = do_process(ob, ib, p_more);
4465

4566
rv.in_bytes += rs.in_bytes;
@@ -57,13 +78,13 @@ process(
5778
return rv;
5879
}
5980

60-
capy::remove_prefix(out, rs.out_bytes);
61-
capy::remove_prefix(in, rs.in_bytes);
81+
out.remove_prefix(rs.out_bytes);
82+
in.remove_prefix(rs.in_bytes);
6283

63-
if(capy::buffer_empty(out))
84+
if(capy::buffer_size(out.data()) == 0)
6485
return rv;
6586

66-
if(capy::buffer_empty(in) && rs.out_bytes < ob.size())
87+
if(capy::buffer_size(in.data()) == 0 && rs.out_bytes < ob.size())
6788
return rv;
6889
}
6990
}

src/detail/filter.hpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,12 @@
1111
#ifndef BOOST_HTTP_DETAIL_FILTER_HPP
1212
#define BOOST_HTTP_DETAIL_FILTER_HPP
1313

14-
#include <boost/capy/buffers/buffer_pair.hpp>
15-
#include <boost/capy/buffers/slice.hpp>
14+
#include <boost/capy/buffers.hpp>
1615
#include <boost/core/span.hpp>
1716
#include <boost/system/error_code.hpp>
1817

18+
#include <array>
19+
1920
namespace boost {
2021
namespace http {
2122
namespace detail {
@@ -65,9 +66,8 @@ class filter
6566

6667
results
6768
process(
68-
capy::slice_of<
69-
boost::span<const capy::mutable_buffer>> out,
70-
capy::const_buffer_pair in,
69+
boost::span<const capy::mutable_buffer> out,
70+
std::array<capy::const_buffer, 2> in,
7171
bool more);
7272

7373
protected:

src/parser.cpp

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
#include <boost/capy/buffers/buffer_copy.hpp>
2121
#include <boost/capy/buffers/flat_dynamic_buffer.hpp>
2222
#include <boost/capy/buffers/front.hpp>
23-
#include <boost/capy/buffers/slice.hpp>
23+
#include <boost/capy/buffers/buffer_slice.hpp>
2424
#include <boost/capy/ex/system_context.hpp>
2525
#include <boost/http/brotli/decode.hpp>
2626
#include <boost/http/zlib/error.hpp>
@@ -33,6 +33,7 @@
3333
#include "src/detail/buffer_utils.hpp"
3434
#include "src/detail/zlib_filter_base.hpp"
3535

36+
#include <array>
3637
#include <memory>
3738

3839
namespace boost {
@@ -123,6 +124,30 @@ Buffer Usage
123124

124125
namespace {
125126

127+
// Construct a 2-element const_buffer pair representing the first
128+
// `n` bytes of `src`. Replaces the pre-#262 `capy::prefix(src, n)`
129+
// idiom which yielded a slice convertible to std::array.
130+
inline std::array<capy::const_buffer, 2>
131+
prefix_pair(
132+
std::array<capy::const_buffer, 2> const& src,
133+
std::size_t n) noexcept
134+
{
135+
std::array<capy::const_buffer, 2> result{};
136+
if(n <= src[0].size())
137+
{
138+
result[0] = capy::const_buffer(src[0].data(), n);
139+
}
140+
else
141+
{
142+
result[0] = src[0];
143+
std::size_t remaining = n - src[0].size();
144+
if(remaining > src[1].size())
145+
remaining = src[1].size();
146+
result[1] = capy::const_buffer(src[1].data(), remaining);
147+
}
148+
return result;
149+
}
150+
126151
class chained_sequence
127152
{
128153
char const* pos_;
@@ -131,7 +156,7 @@ class chained_sequence
131156
char const* end_b_;
132157

133158
public:
134-
chained_sequence(capy::const_buffer_pair const& cbp)
159+
chained_sequence(std::array<capy::const_buffer, 2> const& cbp)
135160
: pos_(static_cast<char const*>(cbp[0].data()))
136161
, end_(pos_ + cbp[0].size())
137162
, begin_b_(static_cast<char const*>(cbp[1].data()))
@@ -440,8 +465,8 @@ class parser::impl
440465
capy::circular_dynamic_buffer cb0_;
441466
capy::circular_dynamic_buffer cb1_;
442467

443-
capy::mutable_buffer_pair mbp_;
444-
capy::const_buffer_pair cbp_;
468+
std::array<capy::mutable_buffer, 2> mbp_;
469+
std::array<capy::const_buffer, 2> cbp_;
445470

446471
std::unique_ptr<detail::filter> filter_;
447472

@@ -1113,8 +1138,9 @@ class parser::impl
11131138
{
11141139
const std::size_t chunk_avail =
11151140
clamp(chunk_remain_, cb0_.size());
1116-
const auto chunk =
1117-
capy::prefix(cb0_.data(), chunk_avail);
1141+
auto cb0_data = cb0_.data();
1142+
auto chunk = capy::buffer_slice(
1143+
cb0_data, 0, chunk_avail);
11181144

11191145
if(body_limit_remain() < chunk_avail)
11201146
{
@@ -1127,7 +1153,7 @@ class parser::impl
11271153
// in_place style
11281154
auto copied = capy::buffer_copy(
11291155
cb1_.prepare(cb1_.capacity()),
1130-
chunk);
1156+
chunk.data());
11311157
chunk_remain_ -= copied;
11321158
body_avail_ += copied;
11331159
body_total_ += copied;
@@ -1243,7 +1269,7 @@ class parser::impl
12431269
return {};
12441270
case state::body:
12451271
case state::complete:
1246-
cbp_ = capy::prefix(
1272+
cbp_ = prefix_pair(
12471273
(is_plain() ? cb0_ : cb1_).data(),
12481274
body_avail_);
12491275
return detail::make_span(cbp_);
@@ -1342,7 +1368,7 @@ class parser::impl
13421368

13431369
return filter_->process(
13441370
detail::make_span(cb1_.prepare(n)),
1345-
capy::prefix(cb0_.data(), payload_avail),
1371+
prefix_pair(cb0_.data(), payload_avail),
13461372
more);
13471373
}();
13481374

src/serializer.cpp

Lines changed: 51 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include <boost/http/zlib/error.hpp>
3232
#include <boost/http/zlib/flush.hpp>
3333

34+
#include <array>
3435
#include <memory>
3536
#include <stddef.h>
3637

@@ -39,6 +40,51 @@ namespace http {
3940

4041
namespace {
4142

43+
// Trim n bytes from the front of a 2-element buffer pair, in place.
44+
// Replaces the pre-#262 `capy::remove_prefix(pair, n)` idiom on a
45+
// 2-element buffer sequence.
46+
template<class Buf>
47+
inline void
48+
trim_prefix_pair(std::array<Buf, 2>& a, std::size_t n) noexcept
49+
{
50+
if(n >= a[0].size())
51+
{
52+
n -= a[0].size();
53+
a[0] = Buf();
54+
if(n >= a[1].size())
55+
a[1] = Buf();
56+
else
57+
a[1] = Buf(
58+
static_cast<char*>(const_cast<void*>(
59+
static_cast<void const*>(a[1].data()))) + n,
60+
a[1].size() - n);
61+
}
62+
else
63+
{
64+
a[0] += n;
65+
}
66+
}
67+
68+
// Trim n bytes from the back of a 2-element buffer pair, in place.
69+
template<class Buf>
70+
inline void
71+
trim_suffix_pair(std::array<Buf, 2>& a, std::size_t n) noexcept
72+
{
73+
if(n >= a[1].size())
74+
{
75+
n -= a[1].size();
76+
a[1] = Buf();
77+
if(n >= a[0].size())
78+
a[0] = Buf();
79+
else
80+
a[0] = Buf(a[0].data(), a[0].size() - n);
81+
}
82+
else
83+
{
84+
a[1] = Buf(a[1].data(), a[1].size() - n);
85+
}
86+
}
87+
4288
const
4389
capy::const_buffer
4490
crlf_and_final_chunk = {"\r\n0\r\n\r\n", 7};
@@ -64,7 +110,7 @@ chunk_header_len(
64110

65111
void
66112
write_chunk_header(
67-
const capy::mutable_buffer_pair& mbs,
113+
const std::array<capy::mutable_buffer, 2>& mbs,
68114
std::size_t size) noexcept
69115
{
70116
static constexpr char hexdig[] =
@@ -584,7 +630,7 @@ class serializer::impl
584630
return out_capacity();
585631
}
586632

587-
capy::mutable_buffer_pair
633+
std::array<capy::mutable_buffer, 2>
588634
stream_prepare()
589635
{
590636
if(state_ == state::start)
@@ -667,15 +713,15 @@ class serializer::impl
667713
detail::throw_length_error();
668714
}
669715

670-
capy::mutable_buffer_pair
716+
std::array<capy::mutable_buffer, 2>
671717
out_prepare() noexcept
672718
{
673719
auto mbp = out_.prepare(out_.capacity());
674720
if(is_chunked_)
675721
{
676-
capy::remove_prefix(
722+
trim_prefix_pair(
677723
mbp, chunk_header_len_);
678-
capy::remove_suffix(
724+
trim_suffix_pair(
679725
mbp, crlf_and_final_chunk.size());
680726
}
681727
return mbp;

0 commit comments

Comments
 (0)