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)
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(ASIO_ENABLE_BUFFER_DEBUGGING)
00038 # include "asio/detail/push_options.hpp"
00039 # include <boost/function.hpp>
00040 # include "asio/detail/pop_options.hpp"
00041 #endif // ASIO_ENABLE_BUFFER_DEBUGGING
00042
00043 namespace asio {
00044
00045 class mutable_buffer;
00046 class const_buffer;
00047
00048 namespace detail {
00049 void* buffer_cast_helper(const mutable_buffer&);
00050 const void* buffer_cast_helper(const const_buffer&);
00051 std::size_t buffer_size_helper(const mutable_buffer&);
00052 std::size_t buffer_size_helper(const const_buffer&);
00053 }
00054
00056
00061 class mutable_buffer
00062 {
00063 public:
00065 mutable_buffer()
00066 : data_(0),
00067 size_(0)
00068 {
00069 }
00070
00072 mutable_buffer(void* data, std::size_t size)
00073 : data_(data),
00074 size_(size)
00075 {
00076 }
00077
00078 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
00079 mutable_buffer(void* data, std::size_t size,
00080 boost::function<void()> debug_check)
00081 : data_(data),
00082 size_(size),
00083 debug_check_(debug_check)
00084 {
00085 }
00086
00087 const boost::function<void()>& get_debug_check() const
00088 {
00089 return debug_check_;
00090 }
00091 #endif // ASIO_ENABLE_BUFFER_DEBUGGING
00092
00093 private:
00094 friend void* asio::detail::buffer_cast_helper(
00095 const mutable_buffer& b);
00096 friend std::size_t asio::detail::buffer_size_helper(
00097 const mutable_buffer& b);
00098
00099 void* data_;
00100 std::size_t size_;
00101
00102 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
00103 boost::function<void()> debug_check_;
00104 #endif // ASIO_ENABLE_BUFFER_DEBUGGING
00105 };
00106
00107 namespace detail {
00108
00109 inline void* buffer_cast_helper(const mutable_buffer& b)
00110 {
00111 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
00112 if (b.debug_check_)
00113 b.debug_check_();
00114 #endif // ASIO_ENABLE_BUFFER_DEBUGGING
00115 return b.data_;
00116 }
00117
00118 inline std::size_t buffer_size_helper(const mutable_buffer& b)
00119 {
00120 return b.size_;
00121 }
00122
00123 }
00124
00126
00129 template <typename PointerToPodType>
00130 inline PointerToPodType buffer_cast(const mutable_buffer& b)
00131 {
00132 return static_cast<PointerToPodType>(detail::buffer_cast_helper(b));
00133 }
00134
00136
00139 inline std::size_t buffer_size(const mutable_buffer& b)
00140 {
00141 return detail::buffer_size_helper(b);
00142 }
00143
00145
00148 inline mutable_buffer operator+(const mutable_buffer& b, std::size_t start)
00149 {
00150 if (start > buffer_size(b))
00151 return mutable_buffer();
00152 char* new_data = buffer_cast<char*>(b) + start;
00153 std::size_t new_size = buffer_size(b) - start;
00154 return mutable_buffer(new_data, new_size
00155 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
00156 , b.get_debug_check()
00157 #endif // ASIO_ENABLE_BUFFER_DEBUGGING
00158 );
00159 }
00160
00162
00165 inline mutable_buffer operator+(std::size_t start, const mutable_buffer& b)
00166 {
00167 if (start > buffer_size(b))
00168 return mutable_buffer();
00169 char* new_data = buffer_cast<char*>(b) + start;
00170 std::size_t new_size = buffer_size(b) - start;
00171 return mutable_buffer(new_data, new_size
00172 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
00173 , b.get_debug_check()
00174 #endif // ASIO_ENABLE_BUFFER_DEBUGGING
00175 );
00176 }
00177
00180 class mutable_buffers_1
00181 : public mutable_buffer
00182 {
00183 public:
00185 typedef mutable_buffer value_type;
00186
00188 typedef const mutable_buffer* const_iterator;
00189
00191 explicit mutable_buffers_1(const mutable_buffer& b)
00192 : mutable_buffer(b)
00193 {
00194 }
00195
00197 const_iterator begin() const
00198 {
00199 return this;
00200 }
00201
00203 const_iterator end() const
00204 {
00205 return begin() + 1;
00206 }
00207 };
00208
00210
00215 class const_buffer
00216 {
00217 public:
00219 const_buffer()
00220 : data_(0),
00221 size_(0)
00222 {
00223 }
00224
00226 const_buffer(const void* data, std::size_t size)
00227 : data_(data),
00228 size_(size)
00229 {
00230 }
00231
00233 const_buffer(const mutable_buffer& b)
00234 : data_(asio::detail::buffer_cast_helper(b)),
00235 size_(asio::detail::buffer_size_helper(b))
00236 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
00237 , debug_check_(b.get_debug_check())
00238 #endif
00239 {
00240 }
00241
00242 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
00243 const_buffer(const void* data, std::size_t size,
00244 boost::function<void()> debug_check)
00245 : data_(data),
00246 size_(size),
00247 debug_check_(debug_check)
00248 {
00249 }
00250
00251 const boost::function<void()>& get_debug_check() const
00252 {
00253 return debug_check_;
00254 }
00255 #endif // ASIO_ENABLE_BUFFER_DEBUGGING
00256
00257 private:
00258 friend const void* asio::detail::buffer_cast_helper(
00259 const const_buffer& b);
00260 friend std::size_t asio::detail::buffer_size_helper(
00261 const const_buffer& b);
00262
00263 const void* data_;
00264 std::size_t size_;
00265
00266 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
00267 boost::function<void()> debug_check_;
00268 #endif // ASIO_ENABLE_BUFFER_DEBUGGING
00269 };
00270
00271 namespace detail {
00272
00273 inline const void* buffer_cast_helper(const const_buffer& b)
00274 {
00275 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
00276 if (b.debug_check_)
00277 b.debug_check_();
00278 #endif // ASIO_ENABLE_BUFFER_DEBUGGING
00279 return b.data_;
00280 }
00281
00282 inline std::size_t buffer_size_helper(const const_buffer& b)
00283 {
00284 return b.size_;
00285 }
00286
00287 }
00288
00290
00293 template <typename PointerToPodType>
00294 inline PointerToPodType buffer_cast(const const_buffer& b)
00295 {
00296 return static_cast<PointerToPodType>(detail::buffer_cast_helper(b));
00297 }
00298
00300
00303 inline std::size_t buffer_size(const const_buffer& b)
00304 {
00305 return detail::buffer_size_helper(b);
00306 }
00307
00309
00312 inline const_buffer operator+(const const_buffer& b, std::size_t start)
00313 {
00314 if (start > buffer_size(b))
00315 return const_buffer();
00316 const char* new_data = buffer_cast<const char*>(b) + start;
00317 std::size_t new_size = buffer_size(b) - start;
00318 return const_buffer(new_data, new_size
00319 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
00320 , b.get_debug_check()
00321 #endif // ASIO_ENABLE_BUFFER_DEBUGGING
00322 );
00323 }
00324
00326
00329 inline const_buffer operator+(std::size_t start, const const_buffer& b)
00330 {
00331 if (start > buffer_size(b))
00332 return const_buffer();
00333 const char* new_data = buffer_cast<const char*>(b) + start;
00334 std::size_t new_size = buffer_size(b) - start;
00335 return const_buffer(new_data, new_size
00336 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
00337 , b.get_debug_check()
00338 #endif // ASIO_ENABLE_BUFFER_DEBUGGING
00339 );
00340 }
00341
00344 class const_buffers_1
00345 : public const_buffer
00346 {
00347 public:
00349 typedef const_buffer value_type;
00350
00352 typedef const const_buffer* const_iterator;
00353
00355 explicit const_buffers_1(const const_buffer& b)
00356 : const_buffer(b)
00357 {
00358 }
00359
00361 const_iterator begin() const
00362 {
00363 return this;
00364 }
00365
00367 const_iterator end() const
00368 {
00369 return begin() + 1;
00370 }
00371 };
00372
00373 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
00374 namespace detail {
00375
00376 template <typename Iterator>
00377 class buffer_debug_check
00378 {
00379 public:
00380 buffer_debug_check(Iterator iter)
00381 : iter_(iter)
00382 {
00383 }
00384
00385 void operator()()
00386 {
00387 *iter_;
00388 }
00389
00390 private:
00391 Iterator iter_;
00392 };
00393
00394 }
00395 #endif // ASIO_ENABLE_BUFFER_DEBUGGING
00396
00447
00449 inline mutable_buffers_1 buffer(const mutable_buffer& b)
00450 {
00451 return mutable_buffers_1(b);
00452 }
00453
00455 inline mutable_buffers_1 buffer(const mutable_buffer& b,
00456 std::size_t max_size_in_bytes)
00457 {
00458 return mutable_buffers_1(
00459 mutable_buffer(buffer_cast<void*>(b),
00460 buffer_size(b) < max_size_in_bytes
00461 ? buffer_size(b) : max_size_in_bytes
00462 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
00463 , b.get_debug_check()
00464 #endif // ASIO_ENABLE_BUFFER_DEBUGGING
00465 ));
00466 }
00467
00469 inline const_buffers_1 buffer(const const_buffer& b)
00470 {
00471 return const_buffers_1(b);
00472 }
00473
00475 inline const_buffers_1 buffer(const const_buffer& b,
00476 std::size_t max_size_in_bytes)
00477 {
00478 return const_buffers_1(
00479 const_buffer(buffer_cast<const void*>(b),
00480 buffer_size(b) < max_size_in_bytes
00481 ? buffer_size(b) : max_size_in_bytes
00482 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
00483 , b.get_debug_check()
00484 #endif // ASIO_ENABLE_BUFFER_DEBUGGING
00485 ));
00486 }
00487
00489 inline mutable_buffers_1 buffer(void* data, std::size_t size_in_bytes)
00490 {
00491 return mutable_buffers_1(mutable_buffer(data, size_in_bytes));
00492 }
00493
00495 inline const_buffers_1 buffer(const void* data,
00496 std::size_t size_in_bytes)
00497 {
00498 return const_buffers_1(const_buffer(data, size_in_bytes));
00499 }
00500
00502 template <typename PodType, std::size_t N>
00503 inline mutable_buffers_1 buffer(PodType (&data)[N])
00504 {
00505 return mutable_buffers_1(mutable_buffer(data, N * sizeof(PodType)));
00506 }
00507
00509 template <typename PodType, std::size_t N>
00510 inline mutable_buffers_1 buffer(PodType (&data)[N],
00511 std::size_t max_size_in_bytes)
00512 {
00513 return mutable_buffers_1(
00514 mutable_buffer(data,
00515 N * sizeof(PodType) < max_size_in_bytes
00516 ? N * sizeof(PodType) : max_size_in_bytes));
00517 }
00518
00520 template <typename PodType, std::size_t N>
00521 inline const_buffers_1 buffer(const PodType (&data)[N])
00522 {
00523 return const_buffers_1(const_buffer(data, N * sizeof(PodType)));
00524 }
00525
00527 template <typename PodType, std::size_t N>
00528 inline const_buffers_1 buffer(const PodType (&data)[N],
00529 std::size_t max_size_in_bytes)
00530 {
00531 return const_buffers_1(
00532 const_buffer(data,
00533 N * sizeof(PodType) < max_size_in_bytes
00534 ? N * sizeof(PodType) : max_size_in_bytes));
00535 }
00536
00537 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551 namespace detail {
00552
00553 template <bool IsConst>
00554 struct buffer_types_base;
00555
00556 template <>
00557 struct buffer_types_base<false>
00558 {
00559 typedef mutable_buffer buffer_type;
00560 typedef mutable_buffers_1 container_type;
00561 };
00562
00563 template <>
00564 struct buffer_types_base<true>
00565 {
00566 typedef const_buffer buffer_type;
00567 typedef const_buffers_1 container_type;
00568 };
00569
00570 template <typename PodType>
00571 struct buffer_types
00572 : public buffer_types_base<boost::is_const<PodType>::value>
00573 {
00574 };
00575
00576 }
00577
00578 template <typename PodType, std::size_t N>
00579 inline typename detail::buffer_types<PodType>::container_type
00580 buffer(boost::array<PodType, N>& data)
00581 {
00582 typedef typename asio::detail::buffer_types<PodType>::buffer_type
00583 buffer_type;
00584 typedef typename asio::detail::buffer_types<PodType>::container_type
00585 container_type;
00586 return container_type(
00587 buffer_type(data.c_array(), data.size() * sizeof(PodType)));
00588 }
00589
00590 template <typename PodType, std::size_t N>
00591 inline typename detail::buffer_types<PodType>::container_type
00592 buffer(boost::array<PodType, N>& data, std::size_t max_size_in_bytes)
00593 {
00594 typedef typename asio::detail::buffer_types<PodType>::buffer_type
00595 buffer_type;
00596 typedef typename asio::detail::buffer_types<PodType>::container_type
00597 container_type;
00598 return container_type(
00599 buffer_type(data.c_array(),
00600 data.size() * sizeof(PodType) < max_size_in_bytes
00601 ? data.size() * sizeof(PodType) : max_size_in_bytes));
00602 }
00603
00604 #else // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
00605
00607 template <typename PodType, std::size_t N>
00608 inline mutable_buffers_1 buffer(boost::array<PodType, N>& data)
00609 {
00610 return mutable_buffers_1(
00611 mutable_buffer(data.c_array(), data.size() * sizeof(PodType)));
00612 }
00613
00615 template <typename PodType, std::size_t N>
00616 inline mutable_buffers_1 buffer(boost::array<PodType, N>& data,
00617 std::size_t max_size_in_bytes)
00618 {
00619 return mutable_buffers_1(
00620 mutable_buffer(data.c_array(),
00621 data.size() * sizeof(PodType) < max_size_in_bytes
00622 ? data.size() * sizeof(PodType) : max_size_in_bytes));
00623 }
00624
00626 template <typename PodType, std::size_t N>
00627 inline const_buffers_1 buffer(boost::array<const PodType, N>& data)
00628 {
00629 return const_buffers_1(
00630 const_buffer(data.data(), data.size() * sizeof(PodType)));
00631 }
00632
00634 template <typename PodType, std::size_t N>
00635 inline const_buffers_1 buffer(boost::array<const PodType, N>& data,
00636 std::size_t max_size_in_bytes)
00637 {
00638 return const_buffers_1(
00639 const_buffer(data.data(),
00640 data.size() * sizeof(PodType) < max_size_in_bytes
00641 ? data.size() * sizeof(PodType) : max_size_in_bytes));
00642 }
00643
00644 #endif // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
00645
00647 template <typename PodType, std::size_t N>
00648 inline const_buffers_1 buffer(const boost::array<PodType, N>& data)
00649 {
00650 return const_buffers_1(
00651 const_buffer(data.data(), data.size() * sizeof(PodType)));
00652 }
00653
00655 template <typename PodType, std::size_t N>
00656 inline const_buffers_1 buffer(const boost::array<PodType, N>& data,
00657 std::size_t max_size_in_bytes)
00658 {
00659 return const_buffers_1(
00660 const_buffer(data.data(),
00661 data.size() * sizeof(PodType) < max_size_in_bytes
00662 ? data.size() * sizeof(PodType) : max_size_in_bytes));
00663 }
00664
00666
00670 template <typename PodType, typename Allocator>
00671 inline mutable_buffers_1 buffer(std::vector<PodType, Allocator>& data)
00672 {
00673 return mutable_buffers_1(
00674 mutable_buffer(&data[0], data.size() * sizeof(PodType)
00675 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
00676 , detail::buffer_debug_check<
00677 typename std::vector<PodType, Allocator>::iterator
00678 >(data.begin())
00679 #endif
00680 ));
00681 }
00682
00684
00688 template <typename PodType, typename Allocator>
00689 inline mutable_buffers_1 buffer(std::vector<PodType, Allocator>& data,
00690 std::size_t max_size_in_bytes)
00691 {
00692 return mutable_buffers_1(
00693 mutable_buffer(&data[0],
00694 data.size() * sizeof(PodType) < max_size_in_bytes
00695 ? data.size() * sizeof(PodType) : max_size_in_bytes
00696 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
00697 , detail::buffer_debug_check<
00698 typename std::vector<PodType, Allocator>::iterator
00699 >(data.begin())
00700 #endif
00701 ));
00702 }
00703
00705
00709 template <typename PodType, typename Allocator>
00710 inline const_buffers_1 buffer(
00711 const std::vector<PodType, Allocator>& data)
00712 {
00713 return const_buffers_1(
00714 const_buffer(&data[0], data.size() * sizeof(PodType)
00715 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
00716 , detail::buffer_debug_check<
00717 typename std::vector<PodType, Allocator>::const_iterator
00718 >(data.begin())
00719 #endif
00720 ));
00721 }
00722
00724
00728 template <typename PodType, typename Allocator>
00729 inline const_buffers_1 buffer(
00730 const std::vector<PodType, Allocator>& data, std::size_t max_size_in_bytes)
00731 {
00732 return const_buffers_1(
00733 const_buffer(&data[0],
00734 data.size() * sizeof(PodType) < max_size_in_bytes
00735 ? data.size() * sizeof(PodType) : max_size_in_bytes
00736 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
00737 , detail::buffer_debug_check<
00738 typename std::vector<PodType, Allocator>::const_iterator
00739 >(data.begin())
00740 #endif
00741 ));
00742 }
00743
00745
00749 inline const_buffers_1 buffer(const std::string& data)
00750 {
00751 return const_buffers_1(const_buffer(data.data(), data.size()
00752 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
00753 , detail::buffer_debug_check<std::string::const_iterator>(data.begin())
00754 #endif
00755 ));
00756 }
00757
00759
00763 inline const_buffers_1 buffer(const std::string& data,
00764 std::size_t max_size_in_bytes)
00765 {
00766 return const_buffers_1(
00767 const_buffer(data.data(),
00768 data.size() < max_size_in_bytes
00769 ? data.size() : max_size_in_bytes
00770 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
00771 , detail::buffer_debug_check<std::string::const_iterator>(data.begin())
00772 #endif
00773 ));
00774 }
00775
00778 }
00779
00780 #include "asio/detail/pop_options.hpp"
00781
00782 #endif // ASIO_BUFFER_HPP