Skip to content

Commit a7de094

Browse files
committed
parser is move constructible and move assignable
1 parent 7f401cf commit a7de094

13 files changed

Lines changed: 1560 additions & 1220 deletions

File tree

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
//
2+
// Copyright (c) 2025 Mohammad Nejati
3+
//
4+
// Distributed under the Boost Software License, Version 1.0. (See accompanying
5+
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6+
//
7+
// Official repository: https://github.com/cppalliance/http_proto
8+
//
9+
10+
#ifndef BOOST_HTTP_PROTO_DETAIL_MANAGED_HPP
11+
#define BOOST_HTTP_PROTO_DETAIL_MANAGED_HPP
12+
13+
namespace boost {
14+
namespace http_proto {
15+
namespace detail {
16+
17+
template<typename T, T Default>
18+
class managed
19+
{
20+
T value_ = Default;
21+
22+
public:
23+
managed() = default;
24+
25+
managed(T s) noexcept
26+
: value_(s)
27+
{
28+
}
29+
30+
managed(managed&& other) noexcept
31+
: value_(other.value_)
32+
{
33+
other.value_ = Default;
34+
}
35+
36+
managed&
37+
operator=(managed&& other) noexcept
38+
{
39+
value_ = other.value_;
40+
other.value_ = Default;
41+
return *this;
42+
}
43+
44+
operator T() const noexcept
45+
{
46+
return value_;
47+
}
48+
};
49+
50+
} // detail
51+
} // http_proto
52+
} // boost
53+
54+
#endif

include/boost/http_proto/impl/parser.hpp

Lines changed: 15 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@
2121
namespace boost {
2222
namespace http_proto {
2323

24-
//------------------------------------------------
25-
2624
template<class ElasticBuffer>
2725
typename std::enable_if<
2826
! detail::is_reference_wrapper<
@@ -44,21 +42,20 @@ set_body(
4442
buffers::is_dynamic_buffer<ElasticBuffer>::value,
4543
"Type requirements not met.");
4644

47-
// body must not be set already
48-
if(how_ != how::in_place)
45+
// body must not already be set
46+
if(is_body_set())
4947
detail::throw_logic_error();
5048

5149
// headers must be complete
5250
if(! got_header())
5351
detail::throw_logic_error();
5452

55-
auto& dyn = ws_.emplace<
53+
auto& dyn = ws().emplace<
5654
buffers::any_dynamic_buffer_impl<typename
5755
std::decay<ElasticBuffer>::type,
5856
buffers_N>>(std::forward<ElasticBuffer>(eb));
59-
eb_ = &dyn;
60-
how_ = how::elastic;
61-
on_set_body();
57+
58+
set_body_impl(dyn);
6259
}
6360

6461
template<class ElasticBuffer>
@@ -72,24 +69,21 @@ set_body(
7269
buffers::is_dynamic_buffer<ElasticBuffer>::value,
7370
"Type requirements not met.");
7471

75-
// body must not be set already
76-
if(how_ != how::in_place)
72+
// body must not already be set
73+
if(is_body_set())
7774
detail::throw_logic_error();
7875

7976
// headers must be complete
8077
if(! got_header())
8178
detail::throw_logic_error();
8279

83-
auto& dyn = ws_.emplace<
80+
auto& dyn = ws().emplace<
8481
buffers::any_dynamic_buffer_impl<typename
8582
std::decay<ElasticBuffer>::type&,
8683
buffers_N>>(eb);
87-
eb_ = &dyn;
88-
how_ = how::elastic;
89-
on_set_body();
90-
}
9184

92-
//------------------------------------------------
85+
set_body_impl(dyn);
86+
}
9387

9488
template<
9589
class Sink,
@@ -99,19 +93,18 @@ Sink&
9993
parser::
10094
set_body(Args&&... args)
10195
{
102-
// body must not be set already
103-
if(how_ != how::in_place)
96+
// body must not already be set
97+
if(is_body_set())
10498
detail::throw_logic_error();
10599

106100
// headers must be complete
107101
if(! got_header())
108102
detail::throw_logic_error();
109103

110-
auto& s = ws_.emplace<Sink>(
104+
auto& s = ws().emplace<Sink>(
111105
std::forward<Args>(args)...);
112-
sink_ = &s;
113-
how_ = how::sink;
114-
on_set_body();
106+
107+
set_body_impl(s);
115108
return s;
116109
}
117110

include/boost/http_proto/parser.hpp

Lines changed: 23 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,14 @@
1515
#include <boost/http_proto/detail/header.hpp>
1616
#include <boost/http_proto/detail/type_traits.hpp>
1717
#include <boost/http_proto/detail/workspace.hpp>
18-
#include <boost/http_proto/error.hpp>
1918
#include <boost/http_proto/header_limits.hpp>
2019
#include <boost/http_proto/sink.hpp>
2120

2221
#include <boost/buffers/any_dynamic_buffer.hpp>
23-
#include <boost/buffers/circular_buffer.hpp>
24-
#include <boost/buffers/flat_buffer.hpp>
2522
#include <boost/buffers/mutable_buffer_pair.hpp>
2623
#include <boost/buffers/mutable_buffer_span.hpp>
2724
#include <boost/buffers/type_traits.hpp>
2825
#include <boost/rts/context_fwd.hpp>
29-
#include <boost/url/grammar/error.hpp>
3026

3127
#include <cstddef>
3228
#include <cstdint>
@@ -37,10 +33,6 @@ namespace http_proto {
3733
// Forward declaration
3834
class request_parser;
3935
class response_parser;
40-
namespace detail {
41-
class parser_service;
42-
class filter;
43-
} // detail
4436

4537
/** A parser for HTTP/1 messages.
4638
@@ -92,30 +84,6 @@ class parser
9284
using const_buffers_type =
9385
buffers::const_buffer_span;
9486

95-
//--------------------------------------------
96-
//
97-
// Special Members
98-
//
99-
//--------------------------------------------
100-
101-
/** Constructor (deleted)
102-
*/
103-
// TODO
104-
parser(parser&&) = delete;
105-
106-
/** Assignment (deleted)
107-
*/
108-
// TODO
109-
parser& operator=(parser&&) = delete;
110-
111-
/** Destructor.
112-
113-
Any views or buffers obtained from this
114-
parser become invalid.
115-
*/
116-
BOOST_HTTP_PROTO_DECL
117-
~parser();
118-
11987
//--------------------------------------------
12088
//
12189
// Observers
@@ -643,87 +611,47 @@ class parser
643611
private:
644612
friend class request_parser;
645613
friend class response_parser;
614+
class impl;
646615

647616
BOOST_HTTP_PROTO_DECL
648617
parser(
649618
const rts::context&,
650619
detail::kind);
651620

652621
BOOST_HTTP_PROTO_DECL
653-
void
654-
start_impl(bool);
622+
parser(parser&& other) noexcept;
655623

656624
BOOST_HTTP_PROTO_DECL
657-
void
658-
on_set_body() noexcept;
625+
parser& operator=(parser&& other) noexcept;
659626

660-
std::size_t
661-
apply_filter(
662-
system::error_code&,
663-
std::size_t,
664-
bool);
627+
BOOST_HTTP_PROTO_DECL
628+
~parser();
629+
630+
BOOST_HTTP_PROTO_DECL
631+
void
632+
start_impl(bool);
665633

666634
detail::header const*
667635
safe_get_header() const;
668636

637+
BOOST_HTTP_PROTO_DECL
638+
detail::workspace&
639+
ws() noexcept;
640+
641+
BOOST_HTTP_PROTO_DECL
669642
bool
670-
is_plain() const noexcept;
643+
is_body_set() const noexcept;
671644

672-
std::uint64_t
673-
body_limit_remain() const noexcept;
645+
BOOST_HTTP_PROTO_DECL
646+
void
647+
set_body_impl(buffers::any_dynamic_buffer&) noexcept;
674648

675-
static constexpr unsigned buffers_N = 8;
649+
BOOST_HTTP_PROTO_DECL
650+
void
651+
set_body_impl(sink&) noexcept;
676652

677-
enum class state
678-
{
679-
reset,
680-
start,
681-
header,
682-
header_done,
683-
body,
684-
set_body,
685-
complete_in_place,
686-
complete
687-
};
688-
689-
enum class how
690-
{
691-
in_place,
692-
sink,
693-
elastic,
694-
};
695-
696-
const rts::context& ctx_;
697-
detail::parser_service& svc_;
698-
699-
detail::workspace ws_;
700-
detail::header h_;
701-
std::uint64_t body_limit_;
702-
std::uint64_t body_total_;
703-
std::uint64_t payload_remain_;
704-
std::uint64_t chunk_remain_;
705-
std::size_t body_avail_;
706-
std::size_t nprepare_;
707-
708-
buffers::flat_buffer fb_;
709-
buffers::circular_buffer cb0_;
710-
buffers::circular_buffer cb1_;
711-
712-
buffers::mutable_buffer_pair mbp_;
713-
buffers::const_buffer_pair cbp_;
714-
715-
detail::filter* filter_;
716-
buffers::any_dynamic_buffer* eb_;
717-
sink* sink_;
718-
719-
state st_;
720-
how how_;
721-
bool got_header_;
722-
bool got_eof_;
723-
bool head_response_;
724-
bool needs_chunk_close_;
725-
bool trailer_headers_;
726-
bool chunked_body_ended;
653+
static constexpr unsigned buffers_N = 8;
654+
impl* impl_;
727655
};
728656

729657
//------------------------------------------------

include/boost/http_proto/request_parser.hpp

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,55 @@ class request_parser
8686
explicit
8787
request_parser(const rts::context& ctx);
8888

89-
/// @copydoc parser
89+
/** Constructor.
90+
91+
The states of `other` are transferred
92+
to the newly constructed object,
93+
including the allocated buffer.
94+
After construction, the only valid
95+
operations on the moved-from object
96+
are destruction and assignment.
97+
98+
Buffer sequences previously obtained
99+
using @ref prepare or @ref pull_body
100+
remain valid.
101+
102+
@par Complexity
103+
Constant.
104+
105+
@param other The parser to move from.
106+
*/
107+
request_parser(
108+
request_parser&& other) noexcept = default;
109+
110+
/** Assignment.
111+
112+
The states of `other` are transferred to
113+
`this`, including the allocated buffer.
114+
The previous states of `this` are
115+
destroyed. After assignment, the only
116+
valid operations on the moved-from object
117+
are destruction and assignment.
118+
119+
Buffer sequences previously obtained
120+
using @ref prepare or @ref pull_body
121+
remain valid.
122+
123+
@par Complexity
124+
Constant.
125+
126+
@return A reference to this object.
127+
128+
@param other The parser to assign from.
129+
*/
130+
request_parser& operator=(
131+
request_parser&& other) noexcept = default;
132+
133+
/** Destructor.
134+
135+
Any views or buffers obtained from this
136+
parser become invalid.
137+
*/
90138
~request_parser() = default;
91139

92140
/** Return a read-only view to the parsed request headers.

0 commit comments

Comments
 (0)