Skip to content

Commit

Permalink
set_impl uses raii helper
Browse files Browse the repository at this point in the history
  • Loading branch information
cmazakas committed Mar 7, 2024
1 parent e5b8c16 commit 3fa86e3
Show file tree
Hide file tree
Showing 6 changed files with 139 additions and 77 deletions.
6 changes: 6 additions & 0 deletions include/boost/http_proto/fields_base.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
namespace boost {
namespace http_proto {

namespace detail {
struct prefix_op;
} // detail

/** Mixin for modifiable HTTP fields
@par Iterators
Expand All @@ -32,6 +36,8 @@ class BOOST_SYMBOL_VISIBLE
fields_base
: public virtual fields_view_base
{
friend struct detail::prefix_op;

detail::header h_;

class op_t;
Expand Down
7 changes: 4 additions & 3 deletions include/boost/http_proto/message_base.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//
// Copyright (c) 2021 Vinnie Falco ([email protected])
// Copyright (c) 2024 Christian Mazakas
//
// 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)
Expand All @@ -11,9 +12,12 @@
#define BOOST_HTTP_PROTO_MESSAGE_BASE_HPP

#include <boost/http_proto/detail/config.hpp>
#include <boost/http_proto/detail/header.hpp>
#include <boost/http_proto/fields_base.hpp>
#include <boost/http_proto/message_view_base.hpp>
#include <boost/http_proto/detail/except.hpp>
#include <boost/core/detail/string_view.hpp>
#include <boost/core/span.hpp>

namespace boost {
namespace http_proto {
Expand Down Expand Up @@ -93,9 +97,6 @@ class BOOST_SYMBOL_VISIBLE
BOOST_HTTP_PROTO_DECL
void
set_keep_alive(bool value);

private:
char* set_prefix_impl(std::size_t);
};

} // http_proto
Expand Down
111 changes: 111 additions & 0 deletions src/detail/header.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
//
// Copyright (c) 2024 Christian Mazakas
//
// 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_SRC_DETAIL_HEADER_HPP
#define BOOST_HTTP_PROTO_SRC_DETAIL_HEADER_HPP

#include <boost/http_proto/message_base.hpp>
#include <boost/http_proto/detail/header.hpp>
#include <boost/core/span.hpp>
#include <cstddef>

namespace boost {
namespace http_proto {
namespace detail {

struct prefix_op {
message_base& mb_;
span<char> prefix_;
char* buf_ = nullptr;
std::size_t n_ = 0;

prefix_op(
message_base& mb,
std::size_t n)
: mb_{mb}
, n_{n}
{
auto& h = mb_.h_;
if( h.buf && n <= h.prefix )
{
prefix_ = {h.buf, n};
return;
}

// allocate or grow
if( n > h.prefix &&
static_cast<std::size_t>(
n - h.prefix) >
static_cast<std::size_t>(
max_offset - h.size))
detail::throw_length_error();

auto n0 = detail::header::bytes_needed(
n + h.size - h.prefix,
h.count);

auto p = new char[n0];
if( h.buf != nullptr )
{
std::memcpy(
p + n,
h.buf + h.prefix,
h.size - h.prefix);

h.copy_table(p + n0);
}
else
{
std::memcpy(
p + n,
h.cbuf + h.prefix,
h.size - h.prefix);
}

prefix_ = {p, n};
buf_ = h.buf;

h.buf = p;
h.cbuf = p;
h.size = static_cast<
offset_type>(h.size +
n - h.prefix);
h.prefix = static_cast<
offset_type>(n);
h.cap = n0;
}

prefix_op(prefix_op&&) = delete;
prefix_op(prefix_op const&) = delete;

~prefix_op()
{
auto& h = mb_.h_;
if( n_ < h.prefix )
{
std::memmove(
h.buf + n_,
h.buf + h.prefix,
h.size - h.prefix);

h.size = static_cast<
offset_type>(h.size -
h.prefix + n_);
h.prefix = static_cast<
offset_type>(n_);
}
delete[] buf_;
}
};

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

#endif // BOOST_HTTP_PROTO_SRC_DETAIL_HEADER_HPP
65 changes: 1 addition & 64 deletions src/message_base.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//
// Copyright (c) 2021 Vinnie Falco ([email protected])
// Copyright (c) 2024 Christian Mazakas
//
// 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)
Expand Down Expand Up @@ -185,69 +186,5 @@ set_keep_alive(bool value)
}
}

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

char*
message_base::
set_prefix_impl(
std::size_t n)
{
if( n > h_.prefix ||
h_.buf == nullptr)
{
// allocate or grow
if( n > h_.prefix &&
static_cast<std::size_t>(
n - h_.prefix) >
static_cast<std::size_t>(
max_offset - h_.size))
detail::throw_length_error();

auto n0 = detail::header::bytes_needed(
n + h_.size - h_.prefix,
h_.count);
auto buf = new char[n0];
if(h_.buf != nullptr)
{
std::memcpy(
buf + n,
h_.buf + h_.prefix,
h_.size - h_.prefix);
detail::header::table ft(
h_.buf + h_.cap);
h_.copy_table(buf + n0);
delete[] h_.buf;
}
else
{
std::memcpy(
buf + n,
h_.cbuf + h_.prefix,
h_.size - h_.prefix);
}
h_.buf = buf;
h_.cbuf = buf;
h_.size = static_cast<
offset_type>(h_.size +
n - h_.prefix);
h_.prefix = static_cast<
offset_type>(n);
h_.cap = n0;
return h_.buf;
}

// shrink
std::memmove(
h_.buf + n,
h_.buf + h_.prefix,
h_.size - h_.prefix);
h_.size = static_cast<
offset_type>(h_.size -
h_.prefix + n);
h_.prefix = static_cast<
offset_type>(n);
return h_.buf;
}

} // http_proto
} // boost
21 changes: 12 additions & 9 deletions src/request.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,12 @@

#include <boost/http_proto/request.hpp>
#include <boost/http_proto/request_view.hpp>
#include "detail/copied_strings.hpp"

#include <cstring>
#include <utility>

#include "detail/header.hpp"

namespace boost {
namespace http_proto {

Expand Down Expand Up @@ -145,25 +148,25 @@ set_impl(
core::string_view t,
http_proto::version v)
{
detail::copied_strings cs(
this->buffer());
ms = cs.maybe_copy(ms);
t = cs.maybe_copy(t);

auto const vs =
to_string(v);
auto const n =
// method SP
ms.size() + 1 +
// request-target SP
t.size() + 1 +
// HTTP-version CRLF
vs.size() + 2;
auto dest = set_prefix_impl(n);
std::memcpy(

detail::prefix_op op(*this, n);
auto dest = op.prefix_.data();
std::memmove(
dest,
ms.data(),
ms.size());
dest += ms.size();
*dest++ = ' ';
std::memcpy(
std::memmove(
dest,
t.data(),
t.size());
Expand Down
6 changes: 5 additions & 1 deletion src/response.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

#include <utility>

#include "detail/header.hpp"

namespace boost {
namespace http_proto {

Expand Down Expand Up @@ -109,7 +111,9 @@ set_impl(
3 + 1 +
rs.size() +
2;
auto dest = set_prefix_impl(n);

detail::prefix_op op(*this, n);
auto dest = op.prefix_.data();

h_.version = v;
vs.copy(dest, vs.size());
Expand Down

0 comments on commit 3fa86e3

Please sign in to comment.