5
// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
7
// Distributed under the Boost Software License, Version 1.0. (See accompanying
8
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
11
#ifndef ASIO_BASIC_STREAMBUF_HPP
12
#define ASIO_BASIC_STREAMBUF_HPP
14
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
16
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
18
#include "asio/detail/push_options.hpp"
20
#include "asio/detail/push_options.hpp"
27
#include "asio/detail/pop_options.hpp"
29
#include "asio/buffer.hpp"
30
#include "asio/detail/noncopyable.hpp"
34
/// Automatically resizable buffer class based on std::streambuf.
35
template <typename Allocator = std::allocator<char> >
37
: public std::streambuf,
41
#if defined(GENERATING_DOCUMENTATION)
42
/// The type used to represent the get area as a list of buffers.
43
typedef implementation_defined const_buffers_type;
45
/// The type used to represent the put area as a list of buffers.
46
typedef implementation_defined mutable_buffers_type;
48
typedef asio::const_buffers_1 const_buffers_type;
49
typedef asio::mutable_buffers_1 mutable_buffers_type;
52
/// Construct a buffer with a specified maximum size.
53
explicit basic_streambuf(
54
std::size_t max_size = (std::numeric_limits<std::size_t>::max)(),
55
const Allocator& allocator = Allocator())
56
: max_size_(max_size),
59
std::size_t pend = (std::min<std::size_t>)(max_size_, buffer_delta);
60
buffer_.resize((std::max<std::size_t>)(pend, 1));
61
setg(&buffer_[0], &buffer_[0], &buffer_[0]);
62
setp(&buffer_[0], &buffer_[0] + pend);
65
/// Return the size of the get area in characters.
66
std::size_t size() const
68
return pptr() - gptr();
71
/// Return the maximum size of the buffer.
72
std::size_t max_size() const
77
/// Get a list of buffers that represents the get area.
78
const_buffers_type data() const
80
return asio::buffer(asio::const_buffer(gptr(),
81
(pptr() - gptr()) * sizeof(char_type)));
84
/// Get a list of buffers that represents the put area, with the given size.
85
mutable_buffers_type prepare(std::size_t size)
88
return asio::buffer(asio::mutable_buffer(
89
pptr(), size * sizeof(char_type)));
92
/// Move the start of the put area by the specified number of characters.
93
void commit(std::size_t n)
95
if (pptr() + n > epptr())
97
pbump(static_cast<int>(n));
100
/// Move the start of the get area by the specified number of characters.
101
void consume(std::size_t n)
111
enum { buffer_delta = 128 };
117
setg(&buffer_[0], gptr(), pptr());
118
return traits_type::to_int_type(*gptr());
122
return traits_type::eof();
126
int_type overflow(int_type c)
128
if (!traits_type::eq_int_type(c, traits_type::eof()))
130
if (pptr() == epptr())
132
std::size_t buffer_size = pptr() - gptr();
133
if (buffer_size < max_size_ && max_size_ - buffer_size < buffer_delta)
135
reserve(max_size_ - buffer_size);
139
reserve(buffer_delta);
143
*pptr() = traits_type::to_char_type(c);
148
return traits_type::not_eof(c);
151
void reserve(std::size_t n)
153
// Get current stream positions as offsets.
154
std::size_t gnext = gptr() - &buffer_[0];
155
std::size_t gend = egptr() - &buffer_[0];
156
std::size_t pnext = pptr() - &buffer_[0];
157
std::size_t pend = epptr() - &buffer_[0];
159
// Check if there is already enough space in the put area.
160
if (n <= pend - pnext)
165
// Shift existing contents of get area to start of buffer.
168
std::rotate(&buffer_[0], &buffer_[0] + gnext, &buffer_[0] + pend);
173
// Ensure buffer is large enough to hold at least the specified size.
174
if (n > pend - pnext)
176
if (n <= max_size_ && pnext <= max_size_ - n)
178
buffer_.resize((std::max<std::size_t>)(pnext + n, 1));
182
throw std::length_error("asio::streambuf too long");
186
// Update stream positions.
187
setg(&buffer_[0], &buffer_[0], &buffer_[0] + gend);
188
setp(&buffer_[0] + pnext, &buffer_[0] + pnext + n);
192
std::size_t max_size_;
193
std::vector<char_type, Allocator> buffer_;
198
#include "asio/detail/pop_options.hpp"
200
#endif // ASIO_BASIC_STREAMBUF_HPP