$search
00001 // 00002 // buffer.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_BUFFER_HPP 00012 #define ASIO_BUFFER_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 <boost/config.hpp> 00023 #include <boost/array.hpp> 00024 #include <boost/type_traits/is_const.hpp> 00025 #include <string> 00026 #include <vector> 00027 #include "asio/detail/pop_options.hpp" 00028 00029 #if defined(BOOST_MSVC) 00030 # if defined(_HAS_ITERATOR_DEBUGGING) && (_HAS_ITERATOR_DEBUGGING != 0) 00031 # if !defined(ASIO_DISABLE_BUFFER_DEBUGGING) 00032 # define ASIO_ENABLE_BUFFER_DEBUGGING 00033 # endif // !defined(ASIO_DISABLE_BUFFER_DEBUGGING) 00034 # endif // defined(_HAS_ITERATOR_DEBUGGING) 00035 #endif // defined(BOOST_MSVC) 00036 00037 #if defined(__GNUC__) 00038 # if defined(_GLIBCXX_DEBUG) 00039 # if !defined(ASIO_DISABLE_BUFFER_DEBUGGING) 00040 # define ASIO_ENABLE_BUFFER_DEBUGGING 00041 # endif // !defined(ASIO_DISABLE_BUFFER_DEBUGGING) 00042 # endif // defined(_GLIBCXX_DEBUG) 00043 #endif // defined(__GNUC__) 00044 00045 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING) 00046 # include "asio/detail/push_options.hpp" 00047 # include <boost/function.hpp> 00048 # include "asio/detail/pop_options.hpp" 00049 #endif // ASIO_ENABLE_BUFFER_DEBUGGING 00050 00051 namespace asio { 00052 00053 class mutable_buffer; 00054 class const_buffer; 00055 00056 namespace detail { 00057 void* buffer_cast_helper(const mutable_buffer&); 00058 const void* buffer_cast_helper(const const_buffer&); 00059 std::size_t buffer_size_helper(const mutable_buffer&); 00060 std::size_t buffer_size_helper(const const_buffer&); 00061 } // namespace detail 00062 00064 00069 class mutable_buffer 00070 { 00071 public: 00073 mutable_buffer() 00074 : data_(0), 00075 size_(0) 00076 { 00077 } 00078 00080 mutable_buffer(void* data, std::size_t size) 00081 : data_(data), 00082 size_(size) 00083 { 00084 } 00085 00086 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING) 00087 mutable_buffer(void* data, std::size_t size, 00088 boost::function<void()> debug_check) 00089 : data_(data), 00090 size_(size), 00091 debug_check_(debug_check) 00092 { 00093 } 00094 00095 const boost::function<void()>& get_debug_check() const 00096 { 00097 return debug_check_; 00098 } 00099 #endif // ASIO_ENABLE_BUFFER_DEBUGGING 00100 00101 private: 00102 friend void* asio::detail::buffer_cast_helper( 00103 const mutable_buffer& b); 00104 friend std::size_t asio::detail::buffer_size_helper( 00105 const mutable_buffer& b); 00106 00107 void* data_; 00108 std::size_t size_; 00109 00110 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING) 00111 boost::function<void()> debug_check_; 00112 #endif // ASIO_ENABLE_BUFFER_DEBUGGING 00113 }; 00114 00115 namespace detail { 00116 00117 inline void* buffer_cast_helper(const mutable_buffer& b) 00118 { 00119 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING) 00120 if (b.size_ && b.debug_check_) 00121 b.debug_check_(); 00122 #endif // ASIO_ENABLE_BUFFER_DEBUGGING 00123 return b.data_; 00124 } 00125 00126 inline std::size_t buffer_size_helper(const mutable_buffer& b) 00127 { 00128 return b.size_; 00129 } 00130 00131 } // namespace detail 00132 00134 00137 template <typename PointerToPodType> 00138 inline PointerToPodType buffer_cast(const mutable_buffer& b) 00139 { 00140 return static_cast<PointerToPodType>(detail::buffer_cast_helper(b)); 00141 } 00142 00144 00147 inline std::size_t buffer_size(const mutable_buffer& b) 00148 { 00149 return detail::buffer_size_helper(b); 00150 } 00151 00153 00156 inline mutable_buffer operator+(const mutable_buffer& b, std::size_t start) 00157 { 00158 if (start > buffer_size(b)) 00159 return mutable_buffer(); 00160 char* new_data = buffer_cast<char*>(b) + start; 00161 std::size_t new_size = buffer_size(b) - start; 00162 return mutable_buffer(new_data, new_size 00163 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING) 00164 , b.get_debug_check() 00165 #endif // ASIO_ENABLE_BUFFER_DEBUGGING 00166 ); 00167 } 00168 00170 00173 inline mutable_buffer operator+(std::size_t start, const mutable_buffer& b) 00174 { 00175 if (start > buffer_size(b)) 00176 return mutable_buffer(); 00177 char* new_data = buffer_cast<char*>(b) + start; 00178 std::size_t new_size = buffer_size(b) - start; 00179 return mutable_buffer(new_data, new_size 00180 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING) 00181 , b.get_debug_check() 00182 #endif // ASIO_ENABLE_BUFFER_DEBUGGING 00183 ); 00184 } 00185 00188 class mutable_buffers_1 00189 : public mutable_buffer 00190 { 00191 public: 00193 typedef mutable_buffer value_type; 00194 00196 typedef const mutable_buffer* const_iterator; 00197 00199 mutable_buffers_1(void* data, std::size_t size) 00200 : mutable_buffer(data, size) 00201 { 00202 } 00203 00205 explicit mutable_buffers_1(const mutable_buffer& b) 00206 : mutable_buffer(b) 00207 { 00208 } 00209 00211 const_iterator begin() const 00212 { 00213 return this; 00214 } 00215 00217 const_iterator end() const 00218 { 00219 return begin() + 1; 00220 } 00221 }; 00222 00224 00229 class const_buffer 00230 { 00231 public: 00233 const_buffer() 00234 : data_(0), 00235 size_(0) 00236 { 00237 } 00238 00240 const_buffer(const void* data, std::size_t size) 00241 : data_(data), 00242 size_(size) 00243 { 00244 } 00245 00247 const_buffer(const mutable_buffer& b) 00248 : data_(asio::detail::buffer_cast_helper(b)), 00249 size_(asio::detail::buffer_size_helper(b)) 00250 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING) 00251 , debug_check_(b.get_debug_check()) 00252 #endif // ASIO_ENABLE_BUFFER_DEBUGGING 00253 { 00254 } 00255 00256 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING) 00257 const_buffer(const void* data, std::size_t size, 00258 boost::function<void()> debug_check) 00259 : data_(data), 00260 size_(size), 00261 debug_check_(debug_check) 00262 { 00263 } 00264 00265 const boost::function<void()>& get_debug_check() const 00266 { 00267 return debug_check_; 00268 } 00269 #endif // ASIO_ENABLE_BUFFER_DEBUGGING 00270 00271 private: 00272 friend const void* asio::detail::buffer_cast_helper( 00273 const const_buffer& b); 00274 friend std::size_t asio::detail::buffer_size_helper( 00275 const const_buffer& b); 00276 00277 const void* data_; 00278 std::size_t size_; 00279 00280 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING) 00281 boost::function<void()> debug_check_; 00282 #endif // ASIO_ENABLE_BUFFER_DEBUGGING 00283 }; 00284 00285 namespace detail { 00286 00287 inline const void* buffer_cast_helper(const const_buffer& b) 00288 { 00289 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING) 00290 if (b.size_ && b.debug_check_) 00291 b.debug_check_(); 00292 #endif // ASIO_ENABLE_BUFFER_DEBUGGING 00293 return b.data_; 00294 } 00295 00296 inline std::size_t buffer_size_helper(const const_buffer& b) 00297 { 00298 return b.size_; 00299 } 00300 00301 } // namespace detail 00302 00304 00307 template <typename PointerToPodType> 00308 inline PointerToPodType buffer_cast(const const_buffer& b) 00309 { 00310 return static_cast<PointerToPodType>(detail::buffer_cast_helper(b)); 00311 } 00312 00314 00317 inline std::size_t buffer_size(const const_buffer& b) 00318 { 00319 return detail::buffer_size_helper(b); 00320 } 00321 00323 00326 inline const_buffer operator+(const const_buffer& b, std::size_t start) 00327 { 00328 if (start > buffer_size(b)) 00329 return const_buffer(); 00330 const char* new_data = buffer_cast<const char*>(b) + start; 00331 std::size_t new_size = buffer_size(b) - start; 00332 return const_buffer(new_data, new_size 00333 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING) 00334 , b.get_debug_check() 00335 #endif // ASIO_ENABLE_BUFFER_DEBUGGING 00336 ); 00337 } 00338 00340 00343 inline const_buffer operator+(std::size_t start, const const_buffer& b) 00344 { 00345 if (start > buffer_size(b)) 00346 return const_buffer(); 00347 const char* new_data = buffer_cast<const char*>(b) + start; 00348 std::size_t new_size = buffer_size(b) - start; 00349 return const_buffer(new_data, new_size 00350 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING) 00351 , b.get_debug_check() 00352 #endif // ASIO_ENABLE_BUFFER_DEBUGGING 00353 ); 00354 } 00355 00358 class const_buffers_1 00359 : public const_buffer 00360 { 00361 public: 00363 typedef const_buffer value_type; 00364 00366 typedef const const_buffer* const_iterator; 00367 00369 const_buffers_1(const void* data, std::size_t size) 00370 : const_buffer(data, size) 00371 { 00372 } 00373 00375 explicit const_buffers_1(const const_buffer& b) 00376 : const_buffer(b) 00377 { 00378 } 00379 00381 const_iterator begin() const 00382 { 00383 return this; 00384 } 00385 00387 const_iterator end() const 00388 { 00389 return begin() + 1; 00390 } 00391 }; 00392 00395 class null_buffers 00396 { 00397 public: 00399 typedef mutable_buffer value_type; 00400 00402 typedef const mutable_buffer* const_iterator; 00403 00405 const_iterator begin() const 00406 { 00407 return &buf_; 00408 } 00409 00411 const_iterator end() const 00412 { 00413 return &buf_; 00414 } 00415 00416 private: 00417 mutable_buffer buf_; 00418 }; 00419 00420 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING) 00421 namespace detail { 00422 00423 template <typename Iterator> 00424 class buffer_debug_check 00425 { 00426 public: 00427 buffer_debug_check(Iterator iter) 00428 : iter_(iter) 00429 { 00430 } 00431 00432 ~buffer_debug_check() 00433 { 00434 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) 00435 // MSVC's string iterator checking may crash in a std::string::iterator 00436 // object's destructor when the iterator points to an already-destroyed 00437 // std::string object, unless the iterator is cleared first. 00438 iter_ = Iterator(); 00439 #endif // BOOST_WORKAROUND(BOOST_MSVC, >= 1400) 00440 } 00441 00442 void operator()() 00443 { 00444 *iter_; 00445 } 00446 00447 private: 00448 Iterator iter_; 00449 }; 00450 00451 } // namespace detail 00452 #endif // ASIO_ENABLE_BUFFER_DEBUGGING 00453 00591 00593 00596 inline mutable_buffers_1 buffer(const mutable_buffer& b) 00597 { 00598 return mutable_buffers_1(b); 00599 } 00600 00602 00608 inline mutable_buffers_1 buffer(const mutable_buffer& b, 00609 std::size_t max_size_in_bytes) 00610 { 00611 return mutable_buffers_1( 00612 mutable_buffer(buffer_cast<void*>(b), 00613 buffer_size(b) < max_size_in_bytes 00614 ? buffer_size(b) : max_size_in_bytes 00615 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING) 00616 , b.get_debug_check() 00617 #endif // ASIO_ENABLE_BUFFER_DEBUGGING 00618 )); 00619 } 00620 00622 00625 inline const_buffers_1 buffer(const const_buffer& b) 00626 { 00627 return const_buffers_1(b); 00628 } 00629 00631 00637 inline const_buffers_1 buffer(const const_buffer& b, 00638 std::size_t max_size_in_bytes) 00639 { 00640 return const_buffers_1( 00641 const_buffer(buffer_cast<const void*>(b), 00642 buffer_size(b) < max_size_in_bytes 00643 ? buffer_size(b) : max_size_in_bytes 00644 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING) 00645 , b.get_debug_check() 00646 #endif // ASIO_ENABLE_BUFFER_DEBUGGING 00647 )); 00648 } 00649 00651 00654 inline mutable_buffers_1 buffer(void* data, std::size_t size_in_bytes) 00655 { 00656 return mutable_buffers_1(mutable_buffer(data, size_in_bytes)); 00657 } 00658 00660 00663 inline const_buffers_1 buffer(const void* data, 00664 std::size_t size_in_bytes) 00665 { 00666 return const_buffers_1(const_buffer(data, size_in_bytes)); 00667 } 00668 00670 00676 template <typename PodType, std::size_t N> 00677 inline mutable_buffers_1 buffer(PodType (&data)[N]) 00678 { 00679 return mutable_buffers_1(mutable_buffer(data, N * sizeof(PodType))); 00680 } 00681 00683 00689 template <typename PodType, std::size_t N> 00690 inline mutable_buffers_1 buffer(PodType (&data)[N], 00691 std::size_t max_size_in_bytes) 00692 { 00693 return mutable_buffers_1( 00694 mutable_buffer(data, 00695 N * sizeof(PodType) < max_size_in_bytes 00696 ? N * sizeof(PodType) : max_size_in_bytes)); 00697 } 00698 00700 00706 template <typename PodType, std::size_t N> 00707 inline const_buffers_1 buffer(const PodType (&data)[N]) 00708 { 00709 return const_buffers_1(const_buffer(data, N * sizeof(PodType))); 00710 } 00711 00713 00719 template <typename PodType, std::size_t N> 00720 inline const_buffers_1 buffer(const PodType (&data)[N], 00721 std::size_t max_size_in_bytes) 00722 { 00723 return const_buffers_1( 00724 const_buffer(data, 00725 N * sizeof(PodType) < max_size_in_bytes 00726 ? N * sizeof(PodType) : max_size_in_bytes)); 00727 } 00728 00729 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582)) \ 00730 || BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590)) 00731 00732 // Borland C++ and Sun Studio think the overloads: 00733 // 00734 // unspecified buffer(boost::array<PodType, N>& array ...); 00735 // 00736 // and 00737 // 00738 // unspecified buffer(boost::array<const PodType, N>& array ...); 00739 // 00740 // are ambiguous. This will be worked around by using a buffer_types traits 00741 // class that contains typedefs for the appropriate buffer and container 00742 // classes, based on whether PodType is const or non-const. 00743 00744 namespace detail { 00745 00746 template <bool IsConst> 00747 struct buffer_types_base; 00748 00749 template <> 00750 struct buffer_types_base<false> 00751 { 00752 typedef mutable_buffer buffer_type; 00753 typedef mutable_buffers_1 container_type; 00754 }; 00755 00756 template <> 00757 struct buffer_types_base<true> 00758 { 00759 typedef const_buffer buffer_type; 00760 typedef const_buffers_1 container_type; 00761 }; 00762 00763 template <typename PodType> 00764 struct buffer_types 00765 : public buffer_types_base<boost::is_const<PodType>::value> 00766 { 00767 }; 00768 00769 } // namespace detail 00770 00771 template <typename PodType, std::size_t N> 00772 inline typename detail::buffer_types<PodType>::container_type 00773 buffer(boost::array<PodType, N>& data) 00774 { 00775 typedef typename asio::detail::buffer_types<PodType>::buffer_type 00776 buffer_type; 00777 typedef typename asio::detail::buffer_types<PodType>::container_type 00778 container_type; 00779 return container_type( 00780 buffer_type(data.c_array(), data.size() * sizeof(PodType))); 00781 } 00782 00783 template <typename PodType, std::size_t N> 00784 inline typename detail::buffer_types<PodType>::container_type 00785 buffer(boost::array<PodType, N>& data, std::size_t max_size_in_bytes) 00786 { 00787 typedef typename asio::detail::buffer_types<PodType>::buffer_type 00788 buffer_type; 00789 typedef typename asio::detail::buffer_types<PodType>::container_type 00790 container_type; 00791 return container_type( 00792 buffer_type(data.c_array(), 00793 data.size() * sizeof(PodType) < max_size_in_bytes 00794 ? data.size() * sizeof(PodType) : max_size_in_bytes)); 00795 } 00796 00797 #else // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582)) 00798 // || BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590)) 00799 00801 00807 template <typename PodType, std::size_t N> 00808 inline mutable_buffers_1 buffer(boost::array<PodType, N>& data) 00809 { 00810 return mutable_buffers_1( 00811 mutable_buffer(data.c_array(), data.size() * sizeof(PodType))); 00812 } 00813 00815 00821 template <typename PodType, std::size_t N> 00822 inline mutable_buffers_1 buffer(boost::array<PodType, N>& data, 00823 std::size_t max_size_in_bytes) 00824 { 00825 return mutable_buffers_1( 00826 mutable_buffer(data.c_array(), 00827 data.size() * sizeof(PodType) < max_size_in_bytes 00828 ? data.size() * sizeof(PodType) : max_size_in_bytes)); 00829 } 00830 00832 00838 template <typename PodType, std::size_t N> 00839 inline const_buffers_1 buffer(boost::array<const PodType, N>& data) 00840 { 00841 return const_buffers_1( 00842 const_buffer(data.data(), data.size() * sizeof(PodType))); 00843 } 00844 00846 00852 template <typename PodType, std::size_t N> 00853 inline const_buffers_1 buffer(boost::array<const PodType, N>& data, 00854 std::size_t max_size_in_bytes) 00855 { 00856 return const_buffers_1( 00857 const_buffer(data.data(), 00858 data.size() * sizeof(PodType) < max_size_in_bytes 00859 ? data.size() * sizeof(PodType) : max_size_in_bytes)); 00860 } 00861 00862 #endif // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582)) 00863 // || BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590)) 00864 00866 00872 template <typename PodType, std::size_t N> 00873 inline const_buffers_1 buffer(const boost::array<PodType, N>& data) 00874 { 00875 return const_buffers_1( 00876 const_buffer(data.data(), data.size() * sizeof(PodType))); 00877 } 00878 00880 00886 template <typename PodType, std::size_t N> 00887 inline const_buffers_1 buffer(const boost::array<PodType, N>& data, 00888 std::size_t max_size_in_bytes) 00889 { 00890 return const_buffers_1( 00891 const_buffer(data.data(), 00892 data.size() * sizeof(PodType) < max_size_in_bytes 00893 ? data.size() * sizeof(PodType) : max_size_in_bytes)); 00894 } 00895 00897 00906 template <typename PodType, typename Allocator> 00907 inline mutable_buffers_1 buffer(std::vector<PodType, Allocator>& data) 00908 { 00909 return mutable_buffers_1( 00910 mutable_buffer(data.size() ? &data[0] : 0, data.size() * sizeof(PodType) 00911 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING) 00912 , detail::buffer_debug_check< 00913 typename std::vector<PodType, Allocator>::iterator 00914 >(data.begin()) 00915 #endif // ASIO_ENABLE_BUFFER_DEBUGGING 00916 )); 00917 } 00918 00920 00929 template <typename PodType, typename Allocator> 00930 inline mutable_buffers_1 buffer(std::vector<PodType, Allocator>& data, 00931 std::size_t max_size_in_bytes) 00932 { 00933 return mutable_buffers_1( 00934 mutable_buffer(data.size() ? &data[0] : 0, 00935 data.size() * sizeof(PodType) < max_size_in_bytes 00936 ? data.size() * sizeof(PodType) : max_size_in_bytes 00937 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING) 00938 , detail::buffer_debug_check< 00939 typename std::vector<PodType, Allocator>::iterator 00940 >(data.begin()) 00941 #endif // ASIO_ENABLE_BUFFER_DEBUGGING 00942 )); 00943 } 00944 00946 00955 template <typename PodType, typename Allocator> 00956 inline const_buffers_1 buffer( 00957 const std::vector<PodType, Allocator>& data) 00958 { 00959 return const_buffers_1( 00960 const_buffer(data.size() ? &data[0] : 0, data.size() * sizeof(PodType) 00961 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING) 00962 , detail::buffer_debug_check< 00963 typename std::vector<PodType, Allocator>::const_iterator 00964 >(data.begin()) 00965 #endif // ASIO_ENABLE_BUFFER_DEBUGGING 00966 )); 00967 } 00968 00970 00979 template <typename PodType, typename Allocator> 00980 inline const_buffers_1 buffer( 00981 const std::vector<PodType, Allocator>& data, std::size_t max_size_in_bytes) 00982 { 00983 return const_buffers_1( 00984 const_buffer(data.size() ? &data[0] : 0, 00985 data.size() * sizeof(PodType) < max_size_in_bytes 00986 ? data.size() * sizeof(PodType) : max_size_in_bytes 00987 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING) 00988 , detail::buffer_debug_check< 00989 typename std::vector<PodType, Allocator>::const_iterator 00990 >(data.begin()) 00991 #endif // ASIO_ENABLE_BUFFER_DEBUGGING 00992 )); 00993 } 00994 00996 01002 inline const_buffers_1 buffer(const std::string& data) 01003 { 01004 return const_buffers_1(const_buffer(data.data(), data.size() 01005 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING) 01006 , detail::buffer_debug_check<std::string::const_iterator>(data.begin()) 01007 #endif // ASIO_ENABLE_BUFFER_DEBUGGING 01008 )); 01009 } 01010 01012 01021 inline const_buffers_1 buffer(const std::string& data, 01022 std::size_t max_size_in_bytes) 01023 { 01024 return const_buffers_1( 01025 const_buffer(data.data(), 01026 data.size() < max_size_in_bytes 01027 ? data.size() : max_size_in_bytes 01028 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING) 01029 , detail::buffer_debug_check<std::string::const_iterator>(data.begin()) 01030 #endif // ASIO_ENABLE_BUFFER_DEBUGGING 01031 )); 01032 } 01033 01036 } // namespace asio 01037 01038 #include "asio/detail/pop_options.hpp" 01039 01040 #endif // ASIO_BUFFER_HPP