Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

parser: gzip/deflate support #110

Merged
merged 9 commits into from
Oct 9, 2024
Merged
45 changes: 0 additions & 45 deletions src/detail/filter.cpp

This file was deleted.

31 changes: 5 additions & 26 deletions src/detail/filter.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//
// Copyright (c) 2023 Vinnie Falco ([email protected])
// Copyright (c) 2024 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)
Expand Down Expand Up @@ -108,19 +109,6 @@ class BOOST_HTTP_PROTO_DECL
buffers::const_buffer in,
bool more) = 0;

/** Called to process the filter.

@par Preconditions
@ref init was called once before any
calls to `process`.
*/
virtual
results
on_process(
buffers::mutable_buffer_span out,
buffers::const_buffer_span in,
bool more);

private:
results
process_impl(
Expand All @@ -131,22 +119,13 @@ class BOOST_HTTP_PROTO_DECL
return on_process(out, in, more);
}

results
process_impl(
buffers::mutable_buffer_span const& out,
buffers::const_buffer_span const& in,
bool more)
{
return on_process(out, in, more);
}

template<
class MutableBuffers,
class ConstBuffers>
class MutableBufferSequence,
class ConstBufferSequence>
results
process_impl(
MutableBuffers const& out,
ConstBuffers const& in,
MutableBufferSequence const& out,
ConstBufferSequence const& in,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do Asio-style buffer sequences work when passed to this?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, except here we are using buffers::begin and buffers::end. By the way, the filter is an implementation detail, so a user-passed buffer sequence would never encounter it directly.

bool more);
};

Expand Down
108 changes: 39 additions & 69 deletions src/detail/impl/filter.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//
// Copyright (c) 2023 Vinnie Falco ([email protected])
// Copyright (c) 2024 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)
Expand All @@ -10,92 +11,61 @@
#ifndef BOOST_HTTP_PROTO_DETAIL_IMPL_FILTER_HPP
#define BOOST_HTTP_PROTO_DETAIL_IMPL_FILTER_HPP

#include <boost/http_proto/detail/except.hpp>
#include <boost/buffers/range.hpp>
#include <boost/buffers/type_traits.hpp>
#include <boost/core/ignore_unused.hpp>
#include <boost/buffers/algorithm.hpp>

namespace boost {
namespace http_proto {
namespace detail {

template<
class T,
std::size_t N>
class filter::unrolled
class MutableBufferSequence,
class ConstBufferSequence>
auto
filter::
process_impl(
MutableBufferSequence const& out,
ConstBufferSequence const& in,
bool more) ->
results
{
using value_type = typename
std::conditional<
buffers::is_mutable_buffer_sequence<T>::value,
buffers::mutable_buffer,
buffers::const_buffer
>::type;
results rv;
auto it_o = buffers::begin(out);
auto it_i = buffers::begin(in);

using span_type = typename
std::conditional<
buffers::is_mutable_buffer_sequence<T>::value,
buffers::mutable_buffer_span,
buffers::const_buffer_span
>::type;
if(it_o == buffers::end(out) || it_i == buffers::end(in))
return rv;

using iter_type = decltype(
begin(std::declval<T const&>()));
auto ob = *it_o;
auto ib = *it_i;
for(;;)
{
results rs = process_impl(ob, ib, more);

using end_type = decltype(
end(std::declval<T const&>()));
rv.out_bytes += rs.out_bytes;
rv.in_bytes += rs.in_bytes;
rv.ec = rs.ec;
rv.finished = rs.finished;

value_type b_[N];
iter_type it_;
end_type end_;
std::size_t n_;
if(rv.finished || rv.ec)
return rv;

public:
explicit
unrolled(
T const& t) noexcept
: it_(begin(t))
, end_(end(t))
{
}
ob = buffers::sans_prefix(ob, rs.out_bytes);
ib = buffers::sans_prefix(ib, rs.in_bytes);

bool
empty() const noexcept
{
return n_ == 0;
}
if(ob.size() == 0)
{
if(++it_o == buffers::end(out))
return rv;
ob = *it_o;
}

span_type
increment()
{
n_ = 0;
while(n_ < N)
if(ib.size() == 0)
{
if(it_ == end_)
break;
b_[n_++] = *it_++;
if(++it_i == buffers::end(in))
return rv;
ib = *it_i;
}
return span_type(&b_[0], n_);
}
};

template<
class MutableBuffers,
class ConstBuffers>
auto
filter::
process_impl(
MutableBuffers const& out,
ConstBuffers const& in,
bool more) ->
results
{
boost::ignore_unused(more);
results rv;
constexpr int N = 16;
unrolled<ConstBuffers, N> u0(in);
unrolled<MutableBuffers, N> u1(out);

return rv;
}

} // detail
Expand Down
6 changes: 4 additions & 2 deletions src/serializer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,12 @@ class deflator_filter

if(in.size() == 0)
{
// TODO: is this necessary?
if(results.out_bytes == 0)
{
flush = zlib::flush::sync;
// TODO: Is flush::block the right choice?
// We might need a filter::flush() interface
// so that the caller can decide when to flush.
flush = zlib::flush::block;
continue;
}
return results;
Expand Down