Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions include/boost/http_proto/detail/managed.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
//
// Copyright (c) 2025 Mohammad Nejati
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// Official repository: https://github.com/cppalliance/http_proto
//

#ifndef BOOST_HTTP_PROTO_DETAIL_MANAGED_HPP
#define BOOST_HTTP_PROTO_DETAIL_MANAGED_HPP

namespace boost {
namespace http_proto {
namespace detail {

template<typename T, T Default>
class managed
{
T value_ = Default;

public:
managed() = default;

managed(T s) noexcept
: value_(s)
{
}

managed(managed&& other) noexcept
: value_(other.value_)
{
other.value_ = Default;
}

managed&
operator=(managed&& other) noexcept
{
value_ = other.value_;
other.value_ = Default;
return *this;
}

operator T() const noexcept
{
return value_;
}
};

} // detail
} // http_proto
} // boost

#endif
37 changes: 15 additions & 22 deletions include/boost/http_proto/impl/parser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@
namespace boost {
namespace http_proto {

//------------------------------------------------

template<class ElasticBuffer>
typename std::enable_if<
! detail::is_reference_wrapper<
Expand All @@ -44,21 +42,20 @@ set_body(
buffers::is_dynamic_buffer<ElasticBuffer>::value,
"Type requirements not met.");

// body must not be set already
if(how_ != how::in_place)
// body must not already be set
if(is_body_set())
detail::throw_logic_error();

// headers must be complete
if(! got_header())
detail::throw_logic_error();

auto& dyn = ws_.emplace<
auto& dyn = ws().emplace<
buffers::any_dynamic_buffer_impl<typename
std::decay<ElasticBuffer>::type,
buffers_N>>(std::forward<ElasticBuffer>(eb));
eb_ = &dyn;
how_ = how::elastic;
on_set_body();

set_body_impl(dyn);
}

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

// body must not be set already
if(how_ != how::in_place)
// body must not already be set
if(is_body_set())
detail::throw_logic_error();

// headers must be complete
if(! got_header())
detail::throw_logic_error();

auto& dyn = ws_.emplace<
auto& dyn = ws().emplace<
buffers::any_dynamic_buffer_impl<typename
std::decay<ElasticBuffer>::type&,
buffers_N>>(eb);
eb_ = &dyn;
how_ = how::elastic;
on_set_body();
}

//------------------------------------------------
set_body_impl(dyn);
}

template<
class Sink,
Expand All @@ -99,19 +93,18 @@ Sink&
parser::
set_body(Args&&... args)
{
// body must not be set already
if(how_ != how::in_place)
// body must not already be set
if(is_body_set())
detail::throw_logic_error();

// headers must be complete
if(! got_header())
detail::throw_logic_error();

auto& s = ws_.emplace<Sink>(
auto& s = ws().emplace<Sink>(
std::forward<Args>(args)...);
sink_ = &s;
how_ = how::sink;
on_set_body();

set_body_impl(s);
return s;
}

Expand Down
118 changes: 23 additions & 95 deletions include/boost/http_proto/parser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,14 @@
#include <boost/http_proto/detail/header.hpp>
#include <boost/http_proto/detail/type_traits.hpp>
#include <boost/http_proto/detail/workspace.hpp>
#include <boost/http_proto/error.hpp>
#include <boost/http_proto/header_limits.hpp>
#include <boost/http_proto/sink.hpp>

#include <boost/buffers/any_dynamic_buffer.hpp>
#include <boost/buffers/circular_buffer.hpp>
#include <boost/buffers/flat_buffer.hpp>
#include <boost/buffers/mutable_buffer_pair.hpp>
#include <boost/buffers/mutable_buffer_span.hpp>
#include <boost/buffers/type_traits.hpp>
#include <boost/rts/context_fwd.hpp>
#include <boost/url/grammar/error.hpp>

#include <cstddef>
#include <cstdint>
Expand All @@ -37,10 +33,6 @@ namespace http_proto {
// Forward declaration
class request_parser;
class response_parser;
namespace detail {
class parser_service;
class filter;
} // detail

/** A parser for HTTP/1 messages.

Expand Down Expand Up @@ -92,30 +84,6 @@ class parser
using const_buffers_type =
buffers::const_buffer_span;

//--------------------------------------------
//
// Special Members
//
//--------------------------------------------

/** Constructor (deleted)
*/
// TODO
parser(parser&&) = delete;

/** Assignment (deleted)
*/
// TODO
parser& operator=(parser&&) = delete;

/** Destructor.

Any views or buffers obtained from this
parser become invalid.
*/
BOOST_HTTP_PROTO_DECL
~parser();

//--------------------------------------------
//
// Observers
Expand Down Expand Up @@ -643,87 +611,47 @@ class parser
private:
friend class request_parser;
friend class response_parser;
class impl;

BOOST_HTTP_PROTO_DECL
parser(
const rts::context&,
detail::kind);

BOOST_HTTP_PROTO_DECL
void
start_impl(bool);
parser(parser&& other) noexcept;

BOOST_HTTP_PROTO_DECL
void
on_set_body() noexcept;
parser& operator=(parser&& other) noexcept;

std::size_t
apply_filter(
system::error_code&,
std::size_t,
bool);
BOOST_HTTP_PROTO_DECL
~parser();

BOOST_HTTP_PROTO_DECL
void
start_impl(bool);

detail::header const*
safe_get_header() const;

BOOST_HTTP_PROTO_DECL
detail::workspace&
ws() noexcept;

BOOST_HTTP_PROTO_DECL
bool
is_plain() const noexcept;
is_body_set() const noexcept;

std::uint64_t
body_limit_remain() const noexcept;
BOOST_HTTP_PROTO_DECL
void
set_body_impl(buffers::any_dynamic_buffer&) noexcept;

static constexpr unsigned buffers_N = 8;
BOOST_HTTP_PROTO_DECL
void
set_body_impl(sink&) noexcept;

enum class state
{
reset,
start,
header,
header_done,
body,
set_body,
complete_in_place,
complete
};

enum class how
{
in_place,
sink,
elastic,
};

const rts::context& ctx_;
detail::parser_service& svc_;

detail::workspace ws_;
detail::header h_;
std::uint64_t body_limit_;
std::uint64_t body_total_;
std::uint64_t payload_remain_;
std::uint64_t chunk_remain_;
std::size_t body_avail_;
std::size_t nprepare_;

buffers::flat_buffer fb_;
buffers::circular_buffer cb0_;
buffers::circular_buffer cb1_;

buffers::mutable_buffer_pair mbp_;
buffers::const_buffer_pair cbp_;

detail::filter* filter_;
buffers::any_dynamic_buffer* eb_;
sink* sink_;

state st_;
how how_;
bool got_header_;
bool got_eof_;
bool head_response_;
bool needs_chunk_close_;
bool trailer_headers_;
bool chunked_body_ended;
static constexpr unsigned buffers_N = 8;
impl* impl_;
};

//------------------------------------------------
Expand Down
50 changes: 49 additions & 1 deletion include/boost/http_proto/request_parser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,55 @@ class request_parser
explicit
request_parser(const rts::context& ctx);

/// @copydoc parser
/** Constructor.

The states of `other` are transferred
to the newly constructed object,
including the allocated buffer.
After construction, the only valid
operations on the moved-from object
are destruction and assignment.

Buffer sequences previously obtained
using @ref prepare or @ref pull_body
remain valid.

@par Complexity
Constant.

@param other The parser to move from.
*/
request_parser(
request_parser&& other) noexcept = default;

/** Assignment.

The states of `other` are transferred to
`this`, including the allocated buffer.
The previous states of `this` are
destroyed. After assignment, the only
valid operations on the moved-from object
are destruction and assignment.

Buffer sequences previously obtained
using @ref prepare or @ref pull_body
remain valid.

@par Complexity
Constant.

@return A reference to this object.

@param other The parser to assign from.
*/
request_parser& operator=(
request_parser&& other) noexcept = default;

/** Destructor.

Any views or buffers obtained from this
parser become invalid.
*/
~request_parser() = default;

/** Return a read-only view to the parsed request headers.
Expand Down
Loading
Loading