$search
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