00001
00002
00003
00004
00005
00006
00007
00008
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 }
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 }
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
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 }
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
00436
00437
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 }
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
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
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 }
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
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
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
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
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
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
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
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
01031 ));
01032 }
01033
01036 }
01037
01038 #include "asio/detail/pop_options.hpp"
01039
01040 #endif // ASIO_BUFFER_HPP