buffered_read_stream.hpp
Go to the documentation of this file.
00001 //
00002 // buffered_read_stream.hpp
00003 // ~~~~~~~~~~~~~~~~~~~~~~~~
00004 //
00005 // Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
00006 //
00007 // Distributed under the Boost Software License, Version 1.0. (See accompanying
00008 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
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; // For memcpy.
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; // For memcpy.
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; // For memcpy.
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   // The data in the buffer.
00407   detail::buffered_stream_storage storage_;
00408 };
00409 
00410 } // namespace asio
00411 
00412 #include "asio/detail/pop_options.hpp"
00413 
00414 #endif // ASIO_BUFFERED_READ_STREAM_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines


Castor
Author(s): Carpe Noctem
autogenerated on Fri Nov 8 2013 11:05:39