Initial Commit
This commit is contained in:
405
include/asio/detail/consuming_buffers.hpp
Normal file
405
include/asio/detail/consuming_buffers.hpp
Normal file
@@ -0,0 +1,405 @@
|
||||
//
|
||||
// detail/consuming_buffers.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2025 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
|
||||
#ifndef ASIO_DETAIL_CONSUMING_BUFFERS_HPP
|
||||
#define ASIO_DETAIL_CONSUMING_BUFFERS_HPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
#include <cstddef>
|
||||
#include "asio/buffer.hpp"
|
||||
#include "asio/detail/buffer_sequence_adapter.hpp"
|
||||
#include "asio/detail/limits.hpp"
|
||||
#include "asio/registered_buffer.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
// Helper template to determine the maximum number of prepared buffers.
|
||||
template <typename Buffers>
|
||||
struct prepared_buffers_max
|
||||
{
|
||||
enum { value = buffer_sequence_adapter_base::max_buffers };
|
||||
};
|
||||
|
||||
template <typename Elem, std::size_t N>
|
||||
struct prepared_buffers_max<boost::array<Elem, N>>
|
||||
{
|
||||
enum { value = N };
|
||||
};
|
||||
|
||||
template <typename Elem, std::size_t N>
|
||||
struct prepared_buffers_max<std::array<Elem, N>>
|
||||
{
|
||||
enum { value = N };
|
||||
};
|
||||
|
||||
// A buffer sequence used to represent a subsequence of the buffers.
|
||||
template <typename Buffer, std::size_t MaxBuffers>
|
||||
struct prepared_buffers
|
||||
{
|
||||
typedef Buffer value_type;
|
||||
typedef const Buffer* const_iterator;
|
||||
|
||||
enum { max_buffers = MaxBuffers < 16 ? MaxBuffers : 16 };
|
||||
|
||||
prepared_buffers() : count(0) {}
|
||||
const_iterator begin() const { return elems; }
|
||||
const_iterator end() const { return elems + count; }
|
||||
|
||||
Buffer elems[max_buffers];
|
||||
std::size_t count;
|
||||
};
|
||||
|
||||
// A proxy for a sub-range in a list of buffers.
|
||||
template <typename Buffer, typename Buffers, typename Buffer_Iterator>
|
||||
class consuming_buffers
|
||||
{
|
||||
public:
|
||||
typedef prepared_buffers<Buffer, prepared_buffers_max<Buffers>::value>
|
||||
prepared_buffers_type;
|
||||
|
||||
// Construct to represent the entire list of buffers.
|
||||
explicit consuming_buffers(const Buffers& buffers)
|
||||
: buffers_(buffers),
|
||||
total_consumed_(0),
|
||||
next_elem_(0),
|
||||
next_elem_offset_(0)
|
||||
{
|
||||
using asio::buffer_size;
|
||||
total_size_ = buffer_size(buffers);
|
||||
}
|
||||
|
||||
// Determine if we are at the end of the buffers.
|
||||
bool empty() const
|
||||
{
|
||||
return total_consumed_ >= total_size_;
|
||||
}
|
||||
|
||||
// Get the buffer for a single transfer, with a size.
|
||||
prepared_buffers_type prepare(std::size_t max_size)
|
||||
{
|
||||
prepared_buffers_type result;
|
||||
|
||||
Buffer_Iterator next = asio::buffer_sequence_begin(buffers_);
|
||||
Buffer_Iterator end = asio::buffer_sequence_end(buffers_);
|
||||
|
||||
std::advance(next, next_elem_);
|
||||
std::size_t elem_offset = next_elem_offset_;
|
||||
while (next != end && max_size > 0 && (result.count) < result.max_buffers)
|
||||
{
|
||||
Buffer next_buf = Buffer(*next) + elem_offset;
|
||||
result.elems[result.count] = asio::buffer(next_buf, max_size);
|
||||
max_size -= result.elems[result.count].size();
|
||||
elem_offset = 0;
|
||||
if (result.elems[result.count].size() > 0)
|
||||
++result.count;
|
||||
++next;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Consume the specified number of bytes from the buffers.
|
||||
void consume(std::size_t size)
|
||||
{
|
||||
total_consumed_ += size;
|
||||
|
||||
Buffer_Iterator next = asio::buffer_sequence_begin(buffers_);
|
||||
Buffer_Iterator end = asio::buffer_sequence_end(buffers_);
|
||||
|
||||
std::advance(next, next_elem_);
|
||||
while (next != end && size > 0)
|
||||
{
|
||||
Buffer next_buf = Buffer(*next) + next_elem_offset_;
|
||||
if (size < next_buf.size())
|
||||
{
|
||||
next_elem_offset_ += size;
|
||||
size = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
size -= next_buf.size();
|
||||
next_elem_offset_ = 0;
|
||||
++next_elem_;
|
||||
++next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get the total number of bytes consumed from the buffers.
|
||||
std::size_t total_consumed() const
|
||||
{
|
||||
return total_consumed_;
|
||||
}
|
||||
|
||||
private:
|
||||
Buffers buffers_;
|
||||
std::size_t total_size_;
|
||||
std::size_t total_consumed_;
|
||||
std::size_t next_elem_;
|
||||
std::size_t next_elem_offset_;
|
||||
};
|
||||
|
||||
// Base class of all consuming_buffers specialisations for single buffers.
|
||||
template <typename Buffer>
|
||||
class consuming_single_buffer
|
||||
{
|
||||
public:
|
||||
// Construct to represent the entire list of buffers.
|
||||
template <typename Buffer1>
|
||||
explicit consuming_single_buffer(const Buffer1& buffer)
|
||||
: buffer_(buffer),
|
||||
total_consumed_(0)
|
||||
{
|
||||
}
|
||||
|
||||
// Determine if we are at the end of the buffers.
|
||||
bool empty() const
|
||||
{
|
||||
return total_consumed_ >= buffer_.size();
|
||||
}
|
||||
|
||||
// Get the buffer for a single transfer, with a size.
|
||||
Buffer prepare(std::size_t max_size)
|
||||
{
|
||||
return asio::buffer(buffer_ + total_consumed_, max_size);
|
||||
}
|
||||
|
||||
// Consume the specified number of bytes from the buffers.
|
||||
void consume(std::size_t size)
|
||||
{
|
||||
total_consumed_ += size;
|
||||
}
|
||||
|
||||
// Get the total number of bytes consumed from the buffers.
|
||||
std::size_t total_consumed() const
|
||||
{
|
||||
return total_consumed_;
|
||||
}
|
||||
|
||||
private:
|
||||
Buffer buffer_;
|
||||
std::size_t total_consumed_;
|
||||
};
|
||||
|
||||
template <>
|
||||
class consuming_buffers<mutable_buffer, mutable_buffer, const mutable_buffer*>
|
||||
: public consuming_single_buffer<mutable_buffer>
|
||||
{
|
||||
public:
|
||||
explicit consuming_buffers(const mutable_buffer& buffer)
|
||||
: consuming_single_buffer<mutable_buffer>(buffer)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
class consuming_buffers<const_buffer, mutable_buffer, const mutable_buffer*>
|
||||
: public consuming_single_buffer<const_buffer>
|
||||
{
|
||||
public:
|
||||
explicit consuming_buffers(const mutable_buffer& buffer)
|
||||
: consuming_single_buffer<const_buffer>(buffer)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
class consuming_buffers<const_buffer, const_buffer, const const_buffer*>
|
||||
: public consuming_single_buffer<const_buffer>
|
||||
{
|
||||
public:
|
||||
explicit consuming_buffers(const const_buffer& buffer)
|
||||
: consuming_single_buffer<const_buffer>(buffer)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
class consuming_buffers<mutable_buffer,
|
||||
mutable_registered_buffer, const mutable_buffer*>
|
||||
: public consuming_single_buffer<mutable_registered_buffer>
|
||||
{
|
||||
public:
|
||||
explicit consuming_buffers(const mutable_registered_buffer& buffer)
|
||||
: consuming_single_buffer<mutable_registered_buffer>(buffer)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
class consuming_buffers<const_buffer,
|
||||
mutable_registered_buffer, const mutable_buffer*>
|
||||
: public consuming_single_buffer<mutable_registered_buffer>
|
||||
{
|
||||
public:
|
||||
explicit consuming_buffers(const mutable_registered_buffer& buffer)
|
||||
: consuming_single_buffer<mutable_registered_buffer>(buffer)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
class consuming_buffers<const_buffer,
|
||||
const_registered_buffer, const const_buffer*>
|
||||
: public consuming_single_buffer<const_registered_buffer>
|
||||
{
|
||||
public:
|
||||
explicit consuming_buffers(const const_registered_buffer& buffer)
|
||||
: consuming_single_buffer<const_registered_buffer>(buffer)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Buffer, typename Elem>
|
||||
class consuming_buffers<Buffer, boost::array<Elem, 2>,
|
||||
typename boost::array<Elem, 2>::const_iterator>
|
||||
{
|
||||
public:
|
||||
// Construct to represent the entire list of buffers.
|
||||
explicit consuming_buffers(const boost::array<Elem, 2>& buffers)
|
||||
: buffers_(buffers),
|
||||
total_consumed_(0)
|
||||
{
|
||||
}
|
||||
|
||||
// Determine if we are at the end of the buffers.
|
||||
bool empty() const
|
||||
{
|
||||
return total_consumed_ >=
|
||||
Buffer(buffers_[0]).size() + Buffer(buffers_[1]).size();
|
||||
}
|
||||
|
||||
// Get the buffer for a single transfer, with a size.
|
||||
boost::array<Buffer, 2> prepare(std::size_t max_size)
|
||||
{
|
||||
boost::array<Buffer, 2> result = {{
|
||||
Buffer(buffers_[0]), Buffer(buffers_[1]) }};
|
||||
std::size_t buffer0_size = result[0].size();
|
||||
result[0] = asio::buffer(result[0] + total_consumed_, max_size);
|
||||
result[1] = asio::buffer(
|
||||
result[1] + (total_consumed_ < buffer0_size
|
||||
? 0 : total_consumed_ - buffer0_size),
|
||||
max_size - result[0].size());
|
||||
return result;
|
||||
}
|
||||
|
||||
// Consume the specified number of bytes from the buffers.
|
||||
void consume(std::size_t size)
|
||||
{
|
||||
total_consumed_ += size;
|
||||
}
|
||||
|
||||
// Get the total number of bytes consumed from the buffers.
|
||||
std::size_t total_consumed() const
|
||||
{
|
||||
return total_consumed_;
|
||||
}
|
||||
|
||||
private:
|
||||
boost::array<Elem, 2> buffers_;
|
||||
std::size_t total_consumed_;
|
||||
};
|
||||
|
||||
template <typename Buffer, typename Elem>
|
||||
class consuming_buffers<Buffer, std::array<Elem, 2>,
|
||||
typename std::array<Elem, 2>::const_iterator>
|
||||
{
|
||||
public:
|
||||
// Construct to represent the entire list of buffers.
|
||||
explicit consuming_buffers(const std::array<Elem, 2>& buffers)
|
||||
: buffers_(buffers),
|
||||
total_consumed_(0)
|
||||
{
|
||||
}
|
||||
|
||||
// Determine if we are at the end of the buffers.
|
||||
bool empty() const
|
||||
{
|
||||
return total_consumed_ >=
|
||||
Buffer(buffers_[0]).size() + Buffer(buffers_[1]).size();
|
||||
}
|
||||
|
||||
// Get the buffer for a single transfer, with a size.
|
||||
std::array<Buffer, 2> prepare(std::size_t max_size)
|
||||
{
|
||||
std::array<Buffer, 2> result = {{
|
||||
Buffer(buffers_[0]), Buffer(buffers_[1]) }};
|
||||
std::size_t buffer0_size = result[0].size();
|
||||
result[0] = asio::buffer(result[0] + total_consumed_, max_size);
|
||||
result[1] = asio::buffer(
|
||||
result[1] + (total_consumed_ < buffer0_size
|
||||
? 0 : total_consumed_ - buffer0_size),
|
||||
max_size - result[0].size());
|
||||
return result;
|
||||
}
|
||||
|
||||
// Consume the specified number of bytes from the buffers.
|
||||
void consume(std::size_t size)
|
||||
{
|
||||
total_consumed_ += size;
|
||||
}
|
||||
|
||||
// Get the total number of bytes consumed from the buffers.
|
||||
std::size_t total_consumed() const
|
||||
{
|
||||
return total_consumed_;
|
||||
}
|
||||
|
||||
private:
|
||||
std::array<Elem, 2> buffers_;
|
||||
std::size_t total_consumed_;
|
||||
};
|
||||
|
||||
// Specialisation for null_buffers to ensure that the null_buffers type is
|
||||
// always passed through to the underlying read or write operation.
|
||||
template <typename Buffer>
|
||||
class consuming_buffers<Buffer, null_buffers, const mutable_buffer*>
|
||||
: public asio::null_buffers
|
||||
{
|
||||
public:
|
||||
consuming_buffers(const null_buffers&)
|
||||
{
|
||||
// No-op.
|
||||
}
|
||||
|
||||
bool empty()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
null_buffers prepare(std::size_t)
|
||||
{
|
||||
return null_buffers();
|
||||
}
|
||||
|
||||
void consume(std::size_t)
|
||||
{
|
||||
// No-op.
|
||||
}
|
||||
|
||||
std::size_t total_consumed() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // ASIO_DETAIL_CONSUMING_BUFFERS_HPP
|
||||
Reference in New Issue
Block a user