00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #ifndef ASIO_BASIC_STREAMBUF_HPP
00012 #define ASIO_BASIC_STREAMBUF_HPP
00013
00014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
00015 # pragma once
00016 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
00017
00018 #include "asio/detail/push_options.hpp"
00019
00020 #include "asio/detail/push_options.hpp"
00021 #include <algorithm>
00022 #include <limits>
00023 #include <memory>
00024 #include <stdexcept>
00025 #include <streambuf>
00026 #include <vector>
00027 #include "asio/detail/pop_options.hpp"
00028
00029 #include "asio/buffer.hpp"
00030 #include "asio/detail/noncopyable.hpp"
00031
00032 namespace asio {
00033
00035 template <typename Allocator = std::allocator<char> >
00036 class basic_streambuf
00037 : public std::streambuf,
00038 private noncopyable
00039 {
00040 public:
00041 #if defined(GENERATING_DOCUMENTATION)
00043 typedef implementation_defined const_buffers_type;
00044
00046 typedef implementation_defined mutable_buffers_type;
00047 #else
00048 typedef asio::const_buffers_1 const_buffers_type;
00049 typedef asio::mutable_buffers_1 mutable_buffers_type;
00050 #endif
00051
00053 explicit basic_streambuf(
00054 std::size_t max_size = (std::numeric_limits<std::size_t>::max)(),
00055 const Allocator& allocator = Allocator())
00056 : max_size_(max_size),
00057 buffer_(allocator)
00058 {
00059 std::size_t pend = (std::min<std::size_t>)(max_size_, buffer_delta);
00060 buffer_.resize((std::max<std::size_t>)(pend, 1));
00061 setg(&buffer_[0], &buffer_[0], &buffer_[0]);
00062 setp(&buffer_[0], &buffer_[0] + pend);
00063 }
00064
00066 std::size_t size() const
00067 {
00068 return pptr() - gptr();
00069 }
00070
00072 std::size_t max_size() const
00073 {
00074 return max_size_;
00075 }
00076
00078 const_buffers_type data() const
00079 {
00080 return asio::buffer(asio::const_buffer(gptr(),
00081 (pptr() - gptr()) * sizeof(char_type)));
00082 }
00083
00085 mutable_buffers_type prepare(std::size_t size)
00086 {
00087 reserve(size);
00088 return asio::buffer(asio::mutable_buffer(
00089 pptr(), size * sizeof(char_type)));
00090 }
00091
00093 void commit(std::size_t n)
00094 {
00095 if (pptr() + n > epptr())
00096 n = epptr() - pptr();
00097 pbump(static_cast<int>(n));
00098 }
00099
00101 void consume(std::size_t n)
00102 {
00103 while (n > 0)
00104 {
00105 sbumpc();
00106 --n;
00107 }
00108 }
00109
00110 protected:
00111 enum { buffer_delta = 128 };
00112
00113 int_type underflow()
00114 {
00115 if (gptr() < pptr())
00116 {
00117 setg(&buffer_[0], gptr(), pptr());
00118 return traits_type::to_int_type(*gptr());
00119 }
00120 else
00121 {
00122 return traits_type::eof();
00123 }
00124 }
00125
00126 int_type overflow(int_type c)
00127 {
00128 if (!traits_type::eq_int_type(c, traits_type::eof()))
00129 {
00130 if (pptr() == epptr())
00131 {
00132 std::size_t buffer_size = pptr() - gptr();
00133 if (buffer_size < max_size_ && max_size_ - buffer_size < buffer_delta)
00134 {
00135 reserve(max_size_ - buffer_size);
00136 }
00137 else
00138 {
00139 reserve(buffer_delta);
00140 }
00141 }
00142
00143 *pptr() = traits_type::to_char_type(c);
00144 pbump(1);
00145 return c;
00146 }
00147
00148 return traits_type::not_eof(c);
00149 }
00150
00151 void reserve(std::size_t n)
00152 {
00153
00154 std::size_t gnext = gptr() - &buffer_[0];
00155 std::size_t gend = egptr() - &buffer_[0];
00156 std::size_t pnext = pptr() - &buffer_[0];
00157 std::size_t pend = epptr() - &buffer_[0];
00158
00159
00160 if (n <= pend - pnext)
00161 {
00162 return;
00163 }
00164
00165
00166 if (gnext > 0)
00167 {
00168 std::rotate(&buffer_[0], &buffer_[0] + gnext, &buffer_[0] + pend);
00169 gend -= gnext;
00170 pnext -= gnext;
00171 }
00172
00173
00174 if (n > pend - pnext)
00175 {
00176 if (n <= max_size_ && pnext <= max_size_ - n)
00177 {
00178 buffer_.resize((std::max<std::size_t>)(pnext + n, 1));
00179 }
00180 else
00181 {
00182 throw std::length_error("asio::streambuf too long");
00183 }
00184 }
00185
00186
00187 setg(&buffer_[0], &buffer_[0], &buffer_[0] + gend);
00188 setp(&buffer_[0] + pnext, &buffer_[0] + pnext + n);
00189 }
00190
00191 private:
00192 std::size_t max_size_;
00193 std::vector<char_type, Allocator> buffer_;
00194 };
00195
00196 }
00197
00198 #include "asio/detail/pop_options.hpp"
00199
00200 #endif // ASIO_BASIC_STREAMBUF_HPP