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)
00062
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
00098 asio::io_service& io_service()
00099 {
00100 return next_layer_.get_io_service();
00101 }
00102
00104 asio::io_service& get_io_service()
00105 {
00106 return next_layer_.get_io_service();
00107 }
00108
00110 void close()
00111 {
00112 next_layer_.close();
00113 }
00114
00116 asio::error_code close(asio::error_code& ec)
00117 {
00118 return next_layer_.close(ec);
00119 }
00120
00123 template <typename ConstBufferSequence>
00124 std::size_t write_some(const ConstBufferSequence& buffers)
00125 {
00126 return next_layer_.write_some(buffers);
00127 }
00128
00131 template <typename ConstBufferSequence>
00132 std::size_t write_some(const ConstBufferSequence& buffers,
00133 asio::error_code& ec)
00134 {
00135 return next_layer_.write_some(buffers, ec);
00136 }
00137
00140 template <typename ConstBufferSequence, typename WriteHandler>
00141 void async_write_some(const ConstBufferSequence& buffers,
00142 WriteHandler handler)
00143 {
00144 next_layer_.async_write_some(buffers, handler);
00145 }
00146
00149 std::size_t fill()
00150 {
00151 detail::buffer_resize_guard<detail::buffered_stream_storage>
00152 resize_guard(storage_);
00153 std::size_t previous_size = storage_.size();
00154 storage_.resize(storage_.capacity());
00155 storage_.resize(previous_size + next_layer_.read_some(buffer(
00156 storage_.data() + previous_size,
00157 storage_.size() - previous_size)));
00158 resize_guard.commit();
00159 return storage_.size() - previous_size;
00160 }
00161
00164 std::size_t fill(asio::error_code& ec)
00165 {
00166 detail::buffer_resize_guard<detail::buffered_stream_storage>
00167 resize_guard(storage_);
00168 std::size_t previous_size = storage_.size();
00169 storage_.resize(storage_.capacity());
00170 storage_.resize(previous_size + next_layer_.read_some(buffer(
00171 storage_.data() + previous_size,
00172 storage_.size() - previous_size),
00173 ec));
00174 resize_guard.commit();
00175 return storage_.size() - previous_size;
00176 }
00177
00178 template <typename ReadHandler>
00179 class fill_handler
00180 {
00181 public:
00182 fill_handler(asio::io_service& io_service,
00183 detail::buffered_stream_storage& storage,
00184 std::size_t previous_size, ReadHandler handler)
00185 : io_service_(io_service),
00186 storage_(storage),
00187 previous_size_(previous_size),
00188 handler_(handler)
00189 {
00190 }
00191
00192 void operator()(const asio::error_code& ec,
00193 std::size_t bytes_transferred)
00194 {
00195 storage_.resize(previous_size_ + bytes_transferred);
00196 io_service_.dispatch(detail::bind_handler(
00197 handler_, ec, bytes_transferred));
00198 }
00199
00200 private:
00201 asio::io_service& io_service_;
00202 detail::buffered_stream_storage& storage_;
00203 std::size_t previous_size_;
00204 ReadHandler handler_;
00205 };
00206
00208 template <typename ReadHandler>
00209 void async_fill(ReadHandler handler)
00210 {
00211 std::size_t previous_size = storage_.size();
00212 storage_.resize(storage_.capacity());
00213 next_layer_.async_read_some(
00214 buffer(
00215 storage_.data() + previous_size,
00216 storage_.size() - previous_size),
00217 fill_handler<ReadHandler>(get_io_service(),
00218 storage_, previous_size, handler));
00219 }
00220
00223 template <typename MutableBufferSequence>
00224 std::size_t read_some(const MutableBufferSequence& buffers)
00225 {
00226 if (storage_.empty())
00227 fill();
00228 return copy(buffers);
00229 }
00230
00233 template <typename MutableBufferSequence>
00234 std::size_t read_some(const MutableBufferSequence& buffers,
00235 asio::error_code& ec)
00236 {
00237 ec = asio::error_code();
00238 if (storage_.empty() && !fill(ec))
00239 return 0;
00240 return copy(buffers);
00241 }
00242
00243 template <typename MutableBufferSequence, typename ReadHandler>
00244 class read_some_handler
00245 {
00246 public:
00247 read_some_handler(asio::io_service& io_service,
00248 detail::buffered_stream_storage& storage,
00249 const MutableBufferSequence& buffers, ReadHandler handler)
00250 : io_service_(io_service),
00251 storage_(storage),
00252 buffers_(buffers),
00253 handler_(handler)
00254 {
00255 }
00256
00257 void operator()(const asio::error_code& ec, std::size_t)
00258 {
00259 if (ec || storage_.empty())
00260 {
00261 std::size_t length = 0;
00262 io_service_.dispatch(detail::bind_handler(handler_, ec, length));
00263 }
00264 else
00265 {
00266 using namespace std;
00267
00268 std::size_t bytes_avail = storage_.size();
00269 std::size_t bytes_copied = 0;
00270
00271 typename MutableBufferSequence::const_iterator iter = buffers_.begin();
00272 typename MutableBufferSequence::const_iterator end = buffers_.end();
00273 for (; iter != end && bytes_avail > 0; ++iter)
00274 {
00275 std::size_t max_length = buffer_size(*iter);
00276 std::size_t length = (max_length < bytes_avail)
00277 ? max_length : bytes_avail;
00278 memcpy(buffer_cast<void*>(*iter),
00279 storage_.data() + bytes_copied, length);
00280 bytes_copied += length;
00281 bytes_avail -= length;
00282 }
00283
00284 storage_.consume(bytes_copied);
00285 io_service_.dispatch(detail::bind_handler(handler_, ec, bytes_copied));
00286 }
00287 }
00288
00289 private:
00290 asio::io_service& io_service_;
00291 detail::buffered_stream_storage& storage_;
00292 MutableBufferSequence buffers_;
00293 ReadHandler handler_;
00294 };
00295
00298 template <typename MutableBufferSequence, typename ReadHandler>
00299 void async_read_some(const MutableBufferSequence& buffers,
00300 ReadHandler handler)
00301 {
00302 if (storage_.empty())
00303 {
00304 async_fill(read_some_handler<MutableBufferSequence, ReadHandler>(
00305 get_io_service(), storage_, buffers, handler));
00306 }
00307 else
00308 {
00309 std::size_t length = copy(buffers);
00310 get_io_service().post(detail::bind_handler(
00311 handler, asio::error_code(), length));
00312 }
00313 }
00314
00317 template <typename MutableBufferSequence>
00318 std::size_t peek(const MutableBufferSequence& buffers)
00319 {
00320 if (storage_.empty())
00321 fill();
00322 return peek_copy(buffers);
00323 }
00324
00327 template <typename MutableBufferSequence>
00328 std::size_t peek(const MutableBufferSequence& buffers,
00329 asio::error_code& ec)
00330 {
00331 ec = asio::error_code();
00332 if (storage_.empty() && !fill(ec))
00333 return 0;
00334 return peek_copy(buffers);
00335 }
00336
00338 std::size_t in_avail()
00339 {
00340 return storage_.size();
00341 }
00342
00344 std::size_t in_avail(asio::error_code& ec)
00345 {
00346 ec = asio::error_code();
00347 return storage_.size();
00348 }
00349
00350 private:
00353 template <typename MutableBufferSequence>
00354 std::size_t copy(const MutableBufferSequence& buffers)
00355 {
00356 using namespace std;
00357
00358 std::size_t bytes_avail = storage_.size();
00359 std::size_t bytes_copied = 0;
00360
00361 typename MutableBufferSequence::const_iterator iter = buffers.begin();
00362 typename MutableBufferSequence::const_iterator end = buffers.end();
00363 for (; iter != end && bytes_avail > 0; ++iter)
00364 {
00365 std::size_t max_length = buffer_size(*iter);
00366 std::size_t length = (max_length < bytes_avail)
00367 ? max_length : bytes_avail;
00368 memcpy(buffer_cast<void*>(*iter), storage_.data() + bytes_copied, length);
00369 bytes_copied += length;
00370 bytes_avail -= length;
00371 }
00372
00373 storage_.consume(bytes_copied);
00374 return bytes_copied;
00375 }
00376
00380 template <typename MutableBufferSequence>
00381 std::size_t peek_copy(const MutableBufferSequence& buffers)
00382 {
00383 using namespace std;
00384
00385 std::size_t bytes_avail = storage_.size();
00386 std::size_t bytes_copied = 0;
00387
00388 typename MutableBufferSequence::const_iterator iter = buffers.begin();
00389 typename MutableBufferSequence::const_iterator end = buffers.end();
00390 for (; iter != end && bytes_avail > 0; ++iter)
00391 {
00392 std::size_t max_length = buffer_size(*iter);
00393 std::size_t length = (max_length < bytes_avail)
00394 ? max_length : bytes_avail;
00395 memcpy(buffer_cast<void*>(*iter), storage_.data() + bytes_copied, length);
00396 bytes_copied += length;
00397 bytes_avail -= length;
00398 }
00399
00400 return bytes_copied;
00401 }
00402
00404 Stream next_layer_;
00405
00406
00407 detail::buffered_stream_storage storage_;
00408 };
00409
00410 }
00411
00412 #include "asio/detail/pop_options.hpp"
00413
00414 #endif // ASIO_BUFFERED_READ_STREAM_HPP