00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #ifndef ASIO_BUFFERED_READ_STREAM_HPP
00012 #define ASIO_BUFFERED_READ_STREAM_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 <cstddef>
00022 #include <cstring>
00023 #include <boost/config.hpp>
00024 #include <boost/type_traits.hpp>
00025 #include "asio/detail/pop_options.hpp"
00026
00027 #include "asio/buffered_read_stream_fwd.hpp"
00028 #include "asio/buffer.hpp"
00029 #include "asio/error.hpp"
00030 #include "asio/io_service.hpp"
00031 #include "asio/detail/bind_handler.hpp"
00032 #include "asio/detail/buffer_resize_guard.hpp"
00033 #include "asio/detail/buffered_stream_storage.hpp"
00034 #include "asio/detail/noncopyable.hpp"
00035
00036 namespace asio {
00037
00039
00050 template <typename Stream>
00051 class buffered_read_stream
00052 : private noncopyable
00053 {
00054 public:
00056 typedef typename boost::remove_reference<Stream>::type next_layer_type;
00057
00059 typedef typename next_layer_type::lowest_layer_type lowest_layer_type;
00060
00061 #if defined(GENERATING_DOCUMENTATION)
00063 static const std::size_t default_buffer_size = implementation_defined;
00064 #else
00065 BOOST_STATIC_CONSTANT(std::size_t, default_buffer_size = 1024);
00066 #endif
00067
00069 template <typename Arg>
00070 explicit buffered_read_stream(Arg& a)
00071 : next_layer_(a),
00072 storage_(default_buffer_size)
00073 {
00074 }
00075
00077 template <typename Arg>
00078 buffered_read_stream(Arg& a, std::size_t buffer_size)
00079 : next_layer_(a),
00080 storage_(buffer_size)
00081 {
00082 }
00083
00085 next_layer_type& next_layer()
00086 {
00087 return next_layer_;
00088 }
00089
00091 lowest_layer_type& lowest_layer()
00092 {
00093 return next_layer_.lowest_layer();
00094 }
00095
00097 asio::io_service& io_service()
00098 {
00099 return next_layer_.io_service();
00100 }
00101
00103 void close()
00104 {
00105 next_layer_.close();
00106 }
00107
00109 asio::error_code close(asio::error_code& ec)
00110 {
00111 return next_layer_.close(ec);
00112 }
00113
00116 template <typename ConstBufferSequence>
00117 std::size_t write_some(const ConstBufferSequence& buffers)
00118 {
00119 return next_layer_.write_some(buffers);
00120 }
00121
00124 template <typename ConstBufferSequence>
00125 std::size_t write_some(const ConstBufferSequence& buffers,
00126 asio::error_code& ec)
00127 {
00128 return next_layer_.write_some(buffers, ec);
00129 }
00130
00133 template <typename ConstBufferSequence, typename WriteHandler>
00134 void async_write_some(const ConstBufferSequence& buffers,
00135 WriteHandler handler)
00136 {
00137 next_layer_.async_write_some(buffers, handler);
00138 }
00139
00142 std::size_t fill()
00143 {
00144 detail::buffer_resize_guard<detail::buffered_stream_storage>
00145 resize_guard(storage_);
00146 std::size_t previous_size = storage_.size();
00147 storage_.resize(storage_.capacity());
00148 storage_.resize(previous_size + next_layer_.read_some(buffer(
00149 storage_.data() + previous_size,
00150 storage_.size() - previous_size)));
00151 resize_guard.commit();
00152 return storage_.size() - previous_size;
00153 }
00154
00157 std::size_t fill(asio::error_code& ec)
00158 {
00159 detail::buffer_resize_guard<detail::buffered_stream_storage>
00160 resize_guard(storage_);
00161 std::size_t previous_size = storage_.size();
00162 storage_.resize(storage_.capacity());
00163 storage_.resize(previous_size + next_layer_.read_some(buffer(
00164 storage_.data() + previous_size,
00165 storage_.size() - previous_size),
00166 ec));
00167 resize_guard.commit();
00168 return storage_.size() - previous_size;
00169 }
00170
00171 template <typename ReadHandler>
00172 class fill_handler
00173 {
00174 public:
00175 fill_handler(asio::io_service& io_service,
00176 detail::buffered_stream_storage& storage,
00177 std::size_t previous_size, ReadHandler handler)
00178 : io_service_(io_service),
00179 storage_(storage),
00180 previous_size_(previous_size),
00181 handler_(handler)
00182 {
00183 }
00184
00185 void operator()(const asio::error_code& ec,
00186 std::size_t bytes_transferred)
00187 {
00188 storage_.resize(previous_size_ + bytes_transferred);
00189 io_service_.dispatch(detail::bind_handler(
00190 handler_, ec, bytes_transferred));
00191 }
00192
00193 private:
00194 asio::io_service& io_service_;
00195 detail::buffered_stream_storage& storage_;
00196 std::size_t previous_size_;
00197 ReadHandler handler_;
00198 };
00199
00201 template <typename ReadHandler>
00202 void async_fill(ReadHandler handler)
00203 {
00204 std::size_t previous_size = storage_.size();
00205 storage_.resize(storage_.capacity());
00206 next_layer_.async_read_some(
00207 buffer(
00208 storage_.data() + previous_size,
00209 storage_.size() - previous_size),
00210 fill_handler<ReadHandler>(io_service(),
00211 storage_, previous_size, handler));
00212 }
00213
00216 template <typename MutableBufferSequence>
00217 std::size_t read_some(const MutableBufferSequence& buffers)
00218 {
00219 if (storage_.empty())
00220 fill();
00221 return copy(buffers);
00222 }
00223
00226 template <typename MutableBufferSequence>
00227 std::size_t read_some(const MutableBufferSequence& buffers,
00228 asio::error_code& ec)
00229 {
00230 ec = asio::error_code();
00231 if (storage_.empty() && !fill(ec))
00232 return 0;
00233 return copy(buffers);
00234 }
00235
00236 template <typename MutableBufferSequence, typename ReadHandler>
00237 class read_some_handler
00238 {
00239 public:
00240 read_some_handler(asio::io_service& io_service,
00241 detail::buffered_stream_storage& storage,
00242 const MutableBufferSequence& buffers, ReadHandler handler)
00243 : io_service_(io_service),
00244 storage_(storage),
00245 buffers_(buffers),
00246 handler_(handler)
00247 {
00248 }
00249
00250 void operator()(const asio::error_code& ec, std::size_t)
00251 {
00252 if (ec || storage_.empty())
00253 {
00254 std::size_t length = 0;
00255 io_service_.dispatch(detail::bind_handler(handler_, ec, length));
00256 }
00257 else
00258 {
00259 using namespace std;
00260
00261 std::size_t bytes_avail = storage_.size();
00262 std::size_t bytes_copied = 0;
00263
00264 typename MutableBufferSequence::const_iterator iter = buffers_.begin();
00265 typename MutableBufferSequence::const_iterator end = buffers_.end();
00266 for (; iter != end && bytes_avail > 0; ++iter)
00267 {
00268 std::size_t max_length = buffer_size(*iter);
00269 std::size_t length = (max_length < bytes_avail)
00270 ? max_length : bytes_avail;
00271 memcpy(buffer_cast<void*>(*iter),
00272 storage_.data() + bytes_copied, length);
00273 bytes_copied += length;
00274 bytes_avail -= length;
00275 }
00276
00277 storage_.consume(bytes_copied);
00278 io_service_.dispatch(detail::bind_handler(handler_, ec, bytes_copied));
00279 }
00280 }
00281
00282 private:
00283 asio::io_service& io_service_;
00284 detail::buffered_stream_storage& storage_;
00285 MutableBufferSequence buffers_;
00286 ReadHandler handler_;
00287 };
00288
00291 template <typename MutableBufferSequence, typename ReadHandler>
00292 void async_read_some(const MutableBufferSequence& buffers,
00293 ReadHandler handler)
00294 {
00295 if (storage_.empty())
00296 {
00297 async_fill(read_some_handler<MutableBufferSequence, ReadHandler>(
00298 io_service(), storage_, buffers, handler));
00299 }
00300 else
00301 {
00302 std::size_t length = copy(buffers);
00303 io_service().post(detail::bind_handler(
00304 handler, asio::error_code(), length));
00305 }
00306 }
00307
00310 template <typename MutableBufferSequence>
00311 std::size_t peek(const MutableBufferSequence& buffers)
00312 {
00313 if (storage_.empty())
00314 fill();
00315 return peek_copy(buffers);
00316 }
00317
00320 template <typename MutableBufferSequence>
00321 std::size_t peek(const MutableBufferSequence& buffers,
00322 asio::error_code& ec)
00323 {
00324 ec = asio::error_code();
00325 if (storage_.empty() && !fill(ec))
00326 return 0;
00327 return peek_copy(buffers);
00328 }
00329
00331 std::size_t in_avail()
00332 {
00333 return storage_.size();
00334 }
00335
00337 std::size_t in_avail(asio::error_code& ec)
00338 {
00339 ec = asio::error_code();
00340 return storage_.size();
00341 }
00342
00343 private:
00346 template <typename MutableBufferSequence>
00347 std::size_t copy(const MutableBufferSequence& buffers)
00348 {
00349 using namespace std;
00350
00351 std::size_t bytes_avail = storage_.size();
00352 std::size_t bytes_copied = 0;
00353
00354 typename MutableBufferSequence::const_iterator iter = buffers.begin();
00355 typename MutableBufferSequence::const_iterator end = buffers.end();
00356 for (; iter != end && bytes_avail > 0; ++iter)
00357 {
00358 std::size_t max_length = buffer_size(*iter);
00359 std::size_t length = (max_length < bytes_avail)
00360 ? max_length : bytes_avail;
00361 memcpy(buffer_cast<void*>(*iter), storage_.data() + bytes_copied, length);
00362 bytes_copied += length;
00363 bytes_avail -= length;
00364 }
00365
00366 storage_.consume(bytes_copied);
00367 return bytes_copied;
00368 }
00369
00373 template <typename MutableBufferSequence>
00374 std::size_t peek_copy(const MutableBufferSequence& buffers)
00375 {
00376 using namespace std;
00377
00378 std::size_t bytes_avail = storage_.size();
00379 std::size_t bytes_copied = 0;
00380
00381 typename MutableBufferSequence::const_iterator iter = buffers.begin();
00382 typename MutableBufferSequence::const_iterator end = buffers.end();
00383 for (; iter != end && bytes_avail > 0; ++iter)
00384 {
00385 std::size_t max_length = buffer_size(*iter);
00386 std::size_t length = (max_length < bytes_avail)
00387 ? max_length : bytes_avail;
00388 memcpy(buffer_cast<void*>(*iter), storage_.data() + bytes_copied, length);
00389 bytes_copied += length;
00390 bytes_avail -= length;
00391 }
00392
00393 return bytes_copied;
00394 }
00395
00397 Stream next_layer_;
00398
00399
00400 detail::buffered_stream_storage storage_;
00401 };
00402
00403 }
00404
00405 #include "asio/detail/pop_options.hpp"
00406
00407 #endif // ASIO_BUFFERED_READ_STREAM_HPP