File indexing completed on 2026-08-20 08:38:41
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_ASIO_BUFFER_HPP
0012 #define BOOST_ASIO_BUFFER_HPP
0013
0014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
0015 # pragma once
0016 #endif
0017
0018 #include <boost/asio/detail/config.hpp>
0019 #include <cstddef>
0020 #include <cstring>
0021 #include <limits>
0022 #include <stdexcept>
0023 #include <string>
0024 #include <vector>
0025 #include <boost/asio/detail/array_fwd.hpp>
0026 #include <boost/asio/detail/memory.hpp>
0027 #include <boost/asio/detail/string_view.hpp>
0028 #include <boost/asio/detail/throw_exception.hpp>
0029 #include <boost/asio/detail/type_traits.hpp>
0030 #include <boost/asio/is_contiguous_iterator.hpp>
0031
0032 #if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1700)
0033 # if defined(_HAS_ITERATOR_DEBUGGING) && (_HAS_ITERATOR_DEBUGGING != 0)
0034 # if !defined(BOOST_ASIO_DISABLE_BUFFER_DEBUGGING)
0035 # define BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
0036 # endif
0037 # endif
0038 #endif
0039
0040 #if defined(__GNUC__)
0041 # if defined(_GLIBCXX_DEBUG)
0042 # if !defined(BOOST_ASIO_DISABLE_BUFFER_DEBUGGING)
0043 # define BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
0044 # endif
0045 # endif
0046 #endif
0047
0048 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
0049 # include <boost/asio/detail/functional.hpp>
0050 #endif
0051
0052 #include <boost/asio/detail/push_options.hpp>
0053
0054 namespace boost {
0055 namespace asio {
0056 namespace detail {
0057
0058 #if defined(BOOST_ASIO_MSVC)
0059
0060 struct span_memfns_base
0061 {
0062 void subspan();
0063 };
0064
0065 template <typename T>
0066 struct span_memfns_derived : T, span_memfns_base
0067 {
0068 };
0069
0070 template <typename T, T>
0071 struct span_memfns_check
0072 {
0073 };
0074
0075 template <typename>
0076 char (&subspan_memfn_helper(...))[2];
0077
0078 template <typename T>
0079 char subspan_memfn_helper(
0080 span_memfns_check<
0081 void (span_memfns_base::*)(),
0082 &span_memfns_derived<T>::subspan>*);
0083
0084 template <typename T>
0085 struct has_subspan_memfn :
0086 integral_constant<bool, sizeof(subspan_memfn_helper<T>(0)) != 1>
0087 {
0088 };
0089
0090 #endif
0091
0092 }
0093
0094 class mutable_buffer;
0095 class const_buffer;
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116 class mutable_buffer
0117 {
0118 public:
0119
0120 mutable_buffer() noexcept
0121 : data_(0),
0122 size_(0)
0123 {
0124 }
0125
0126
0127 mutable_buffer(void* data, std::size_t size) noexcept
0128 : data_(data),
0129 size_(size)
0130 {
0131 }
0132
0133
0134 template <template <typename, std::size_t> class Span,
0135 typename T, std::size_t Extent>
0136 mutable_buffer(const Span<T, Extent>& span,
0137 constraint_t<
0138 !is_const<T>::value,
0139 defaulted_constraint
0140 > = defaulted_constraint(),
0141 constraint_t<
0142 sizeof(T) == 1,
0143 defaulted_constraint
0144 > = defaulted_constraint(),
0145 constraint_t<
0146 #if defined(BOOST_ASIO_MSVC)
0147 detail::has_subspan_memfn<Span<T, Extent>>::value,
0148 #else
0149 is_same<
0150 decltype(span.subspan(0, 0)),
0151 Span<T, static_cast<std::size_t>(-1)>
0152 >::value,
0153 #endif
0154 defaulted_constraint
0155 > = defaulted_constraint())
0156 : data_(span.data()),
0157 size_(span.size())
0158 {
0159 }
0160
0161 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
0162 mutable_buffer(void* data, std::size_t size,
0163 boost::asio::detail::function<void()> debug_check)
0164 : data_(data),
0165 size_(size),
0166 debug_check_(debug_check)
0167 {
0168 }
0169
0170 const boost::asio::detail::function<void()>& get_debug_check() const
0171 {
0172 return debug_check_;
0173 }
0174 #endif
0175
0176
0177 void* data() const noexcept
0178 {
0179 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
0180 if (size_ && debug_check_)
0181 debug_check_();
0182 #endif
0183 return data_;
0184 }
0185
0186
0187 std::size_t size() const noexcept
0188 {
0189 return size_;
0190 }
0191
0192
0193 mutable_buffer& operator+=(std::size_t n) noexcept
0194 {
0195 std::size_t offset = n < size_ ? n : size_;
0196 data_ = static_cast<char*>(data_) + offset;
0197 size_ -= offset;
0198 return *this;
0199 }
0200
0201 private:
0202 void* data_;
0203 std::size_t size_;
0204
0205 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
0206 boost::asio::detail::function<void()> debug_check_;
0207 #endif
0208 };
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229 class const_buffer
0230 {
0231 public:
0232
0233 const_buffer() noexcept
0234 : data_(0),
0235 size_(0)
0236 {
0237 }
0238
0239
0240 const_buffer(const void* data, std::size_t size) noexcept
0241 : data_(data),
0242 size_(size)
0243 {
0244 }
0245
0246
0247 const_buffer(const mutable_buffer& b) noexcept
0248 : data_(b.data()),
0249 size_(b.size())
0250 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
0251 , debug_check_(b.get_debug_check())
0252 #endif
0253 {
0254 }
0255
0256
0257 template <template <typename, std::size_t> class Span,
0258 typename T, std::size_t Extent>
0259 const_buffer(const Span<T, Extent>& span,
0260 constraint_t<
0261 sizeof(T) == 1,
0262 defaulted_constraint
0263 > = defaulted_constraint(),
0264 constraint_t<
0265 #if defined(BOOST_ASIO_MSVC)
0266 detail::has_subspan_memfn<Span<T, Extent>>::value,
0267 #else
0268 is_same<
0269 decltype(span.subspan(0, 0)),
0270 Span<T, static_cast<std::size_t>(-1)>
0271 >::value,
0272 #endif
0273 defaulted_constraint
0274 > = defaulted_constraint())
0275 : data_(span.data()),
0276 size_(span.size())
0277 {
0278 }
0279
0280 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
0281 const_buffer(const void* data, std::size_t size,
0282 boost::asio::detail::function<void()> debug_check)
0283 : data_(data),
0284 size_(size),
0285 debug_check_(debug_check)
0286 {
0287 }
0288
0289 const boost::asio::detail::function<void()>& get_debug_check() const
0290 {
0291 return debug_check_;
0292 }
0293 #endif
0294
0295
0296 const void* data() const noexcept
0297 {
0298 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
0299 if (size_ && debug_check_)
0300 debug_check_();
0301 #endif
0302 return data_;
0303 }
0304
0305
0306 std::size_t size() const noexcept
0307 {
0308 return size_;
0309 }
0310
0311
0312 const_buffer& operator+=(std::size_t n) noexcept
0313 {
0314 std::size_t offset = n < size_ ? n : size_;
0315 data_ = static_cast<const char*>(data_) + offset;
0316 size_ -= offset;
0317 return *this;
0318 }
0319
0320 private:
0321 const void* data_;
0322 std::size_t size_;
0323
0324 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
0325 boost::asio::detail::function<void()> debug_check_;
0326 #endif
0327 };
0328
0329
0330
0331
0332 class BOOST_ASIO_DEPRECATED_MSG(
0333 "Use the socket/descriptor wait() and async_wait() member functions")
0334 null_buffers
0335 {
0336 public:
0337
0338 typedef mutable_buffer value_type;
0339
0340
0341 typedef const mutable_buffer* const_iterator;
0342
0343
0344 const_iterator begin() const noexcept
0345 {
0346 return &buf_;
0347 }
0348
0349
0350 const_iterator end() const noexcept
0351 {
0352 return &buf_;
0353 }
0354
0355 private:
0356 mutable_buffer buf_;
0357 };
0358
0359
0360
0361
0362
0363
0364
0365
0366
0367 template <typename MutableBuffer>
0368 inline const mutable_buffer* buffer_sequence_begin(const MutableBuffer& b,
0369 constraint_t<
0370 is_convertible<const MutableBuffer*, const mutable_buffer*>::value
0371 > = 0) noexcept
0372 {
0373 return static_cast<const mutable_buffer*>(detail::addressof(b));
0374 }
0375
0376
0377 template <typename ConstBuffer>
0378 inline const const_buffer* buffer_sequence_begin(const ConstBuffer& b,
0379 constraint_t<
0380 is_convertible<const ConstBuffer*, const const_buffer*>::value
0381 > = 0) noexcept
0382 {
0383 return static_cast<const const_buffer*>(detail::addressof(b));
0384 }
0385
0386
0387 template <typename ConvertibleToBuffer>
0388 inline const ConvertibleToBuffer* buffer_sequence_begin(
0389 const ConvertibleToBuffer& b,
0390 constraint_t<
0391 !is_convertible<const ConvertibleToBuffer*, const mutable_buffer*>::value
0392 > = 0,
0393 constraint_t<
0394 !is_convertible<const ConvertibleToBuffer*, const const_buffer*>::value
0395 > = 0,
0396 constraint_t<
0397 is_convertible<ConvertibleToBuffer, mutable_buffer>::value
0398 || is_convertible<ConvertibleToBuffer, const_buffer>::value
0399 > = 0) noexcept
0400 {
0401 return detail::addressof(b);
0402 }
0403
0404
0405 template <typename C>
0406 inline auto buffer_sequence_begin(C& c,
0407 constraint_t<
0408 !is_convertible<const C*, const mutable_buffer*>::value
0409 > = 0,
0410 constraint_t<
0411 !is_convertible<const C*, const const_buffer*>::value
0412 > = 0,
0413 constraint_t<
0414 !is_convertible<C, mutable_buffer>::value
0415 > = 0,
0416 constraint_t<
0417 !is_convertible<C, const_buffer>::value
0418 > = 0) noexcept -> decltype(c.begin())
0419 {
0420 return c.begin();
0421 }
0422
0423
0424 template <typename C>
0425 inline auto buffer_sequence_begin(const C& c,
0426 constraint_t<
0427 !is_convertible<const C*, const mutable_buffer*>::value
0428 > = 0,
0429 constraint_t<
0430 !is_convertible<const C*, const const_buffer*>::value
0431 > = 0,
0432 constraint_t<
0433 !is_convertible<C, mutable_buffer>::value
0434 > = 0,
0435 constraint_t<
0436 !is_convertible<C, const_buffer>::value
0437 > = 0) noexcept -> decltype(c.begin())
0438 {
0439 return c.begin();
0440 }
0441
0442
0443
0444
0445
0446
0447
0448
0449
0450
0451
0452 template <typename MutableBuffer>
0453 inline const mutable_buffer* buffer_sequence_end(const MutableBuffer& b,
0454 constraint_t<
0455 is_convertible<const MutableBuffer*, const mutable_buffer*>::value
0456 > = 0) noexcept
0457 {
0458 return static_cast<const mutable_buffer*>(detail::addressof(b)) + 1;
0459 }
0460
0461
0462 template <typename ConstBuffer>
0463 inline const const_buffer* buffer_sequence_end(const ConstBuffer& b,
0464 constraint_t<
0465 is_convertible<const ConstBuffer*, const const_buffer*>::value
0466 > = 0) noexcept
0467 {
0468 return static_cast<const const_buffer*>(detail::addressof(b)) + 1;
0469 }
0470
0471
0472 template <typename ConvertibleToBuffer>
0473 inline const ConvertibleToBuffer* buffer_sequence_end(
0474 const ConvertibleToBuffer& b,
0475 constraint_t<
0476 !is_convertible<const ConvertibleToBuffer*, const mutable_buffer*>::value
0477 > = 0,
0478 constraint_t<
0479 !is_convertible<const ConvertibleToBuffer*, const const_buffer*>::value
0480 > = 0,
0481 constraint_t<
0482 is_convertible<ConvertibleToBuffer, mutable_buffer>::value
0483 || is_convertible<ConvertibleToBuffer, const_buffer>::value
0484 > = 0) noexcept
0485 {
0486 return detail::addressof(b) + 1;
0487 }
0488
0489
0490 template <typename C>
0491 inline auto buffer_sequence_end(C& c,
0492 constraint_t<
0493 !is_convertible<const C*, const mutable_buffer*>::value
0494 > = 0,
0495 constraint_t<
0496 !is_convertible<const C*, const const_buffer*>::value
0497 > = 0,
0498 constraint_t<
0499 !is_convertible<C, mutable_buffer>::value
0500 > = 0,
0501 constraint_t<
0502 !is_convertible<C, const_buffer>::value
0503 > = 0) noexcept -> decltype(c.end())
0504 {
0505 return c.end();
0506 }
0507
0508
0509 template <typename C>
0510 inline auto buffer_sequence_end(const C& c,
0511 constraint_t<
0512 !is_convertible<const C*, const mutable_buffer*>::value
0513 > = 0,
0514 constraint_t<
0515 !is_convertible<const C*, const const_buffer*>::value
0516 > = 0,
0517 constraint_t<
0518 !is_convertible<C, mutable_buffer>::value
0519 > = 0,
0520 constraint_t<
0521 !is_convertible<C, const_buffer>::value
0522 > = 0) noexcept -> decltype(c.end())
0523 {
0524 return c.end();
0525 }
0526
0527
0528
0529 namespace detail {
0530
0531
0532 struct one_buffer {};
0533 struct multiple_buffers {};
0534
0535
0536 template <typename BufferSequence>
0537 struct buffer_sequence_cardinality :
0538 conditional_t<
0539 is_same<BufferSequence, mutable_buffer>::value
0540 || is_same<BufferSequence, const_buffer>::value,
0541 one_buffer, multiple_buffers> {};
0542
0543 template <typename Iterator>
0544 inline std::size_t buffer_size(one_buffer,
0545 Iterator begin, Iterator) noexcept
0546 {
0547 return const_buffer(*begin).size();
0548 }
0549
0550 template <typename Iterator>
0551 inline std::size_t buffer_size(multiple_buffers,
0552 Iterator begin, Iterator end) noexcept
0553 {
0554 std::size_t total_buffer_size = 0;
0555
0556 Iterator iter = begin;
0557 for (; iter != end; ++iter)
0558 {
0559 const_buffer b(*iter);
0560 total_buffer_size += b.size();
0561 }
0562
0563 return total_buffer_size;
0564 }
0565
0566 }
0567
0568
0569
0570
0571
0572
0573
0574
0575
0576
0577
0578
0579
0580
0581
0582
0583
0584
0585
0586 template <typename BufferSequence>
0587 inline std::size_t buffer_size(const BufferSequence& b) noexcept
0588 {
0589 return detail::buffer_size(
0590 detail::buffer_sequence_cardinality<BufferSequence>(),
0591 boost::asio::buffer_sequence_begin(b),
0592 boost::asio::buffer_sequence_end(b));
0593 }
0594
0595
0596
0597
0598
0599 inline mutable_buffer operator+(const mutable_buffer& b,
0600 std::size_t n) noexcept
0601 {
0602 std::size_t offset = n < b.size() ? n : b.size();
0603 char* new_data = static_cast<char*>(b.data()) + offset;
0604 std::size_t new_size = b.size() - offset;
0605 return mutable_buffer(new_data, new_size
0606 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
0607 , b.get_debug_check()
0608 #endif
0609 );
0610 }
0611
0612
0613
0614
0615
0616 inline mutable_buffer operator+(std::size_t n,
0617 const mutable_buffer& b) noexcept
0618 {
0619 return b + n;
0620 }
0621
0622
0623
0624
0625
0626 inline const_buffer operator+(const const_buffer& b,
0627 std::size_t n) noexcept
0628 {
0629 std::size_t offset = n < b.size() ? n : b.size();
0630 const char* new_data = static_cast<const char*>(b.data()) + offset;
0631 std::size_t new_size = b.size() - offset;
0632 return const_buffer(new_data, new_size
0633 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
0634 , b.get_debug_check()
0635 #endif
0636 );
0637 }
0638
0639
0640
0641
0642
0643 inline const_buffer operator+(std::size_t n,
0644 const const_buffer& b) noexcept
0645 {
0646 return b + n;
0647 }
0648
0649 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
0650 namespace detail {
0651
0652 template <typename Iterator>
0653 class buffer_debug_check
0654 {
0655 public:
0656 buffer_debug_check(Iterator iter)
0657 : iter_(iter)
0658 {
0659 }
0660
0661 ~buffer_debug_check()
0662 {
0663 #if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC == 1400)
0664
0665
0666
0667 iter_ = Iterator();
0668 #endif
0669 }
0670
0671 void operator()()
0672 {
0673 (void)*iter_;
0674 }
0675
0676 private:
0677 Iterator iter_;
0678 };
0679
0680 }
0681 #endif
0682
0683
0684
0685
0686
0687
0688
0689
0690
0691
0692
0693
0694
0695
0696
0697
0698
0699
0700
0701
0702
0703
0704
0705
0706
0707
0708
0709
0710
0711
0712
0713
0714
0715
0716
0717
0718
0719
0720
0721
0722
0723
0724
0725
0726
0727
0728
0729
0730
0731
0732
0733
0734
0735
0736
0737
0738
0739
0740
0741
0742
0743
0744
0745
0746
0747
0748
0749
0750
0751
0752
0753
0754
0755
0756
0757
0758
0759
0760
0761
0762
0763
0764
0765
0766
0767
0768
0769
0770
0771
0772
0773
0774
0775
0776
0777
0778
0779
0780
0781
0782
0783
0784
0785
0786
0787
0788
0789
0790
0791
0792
0793
0794
0795
0796
0797
0798
0799
0800
0801
0802
0803
0804
0805
0806
0807
0808
0809
0810
0811
0812
0813
0814
0815
0816
0817
0818
0819
0820
0821
0822
0823
0824
0825
0826
0827
0828
0829
0830
0831
0832
0833
0834
0835
0836
0837
0838
0839
0840
0841
0842
0843
0844
0845
0846
0847
0848
0849
0850
0851
0852
0853
0854
0855
0856
0857
0858
0859
0860
0861
0862
0863
0864
0865
0866
0867
0868
0869 BOOST_ASIO_NODISCARD inline mutable_buffer buffer(
0870 const mutable_buffer& b) noexcept
0871 {
0872 return mutable_buffer(b);
0873 }
0874
0875
0876
0877
0878
0879
0880
0881
0882 BOOST_ASIO_NODISCARD inline mutable_buffer buffer(
0883 const mutable_buffer& b,
0884 std::size_t max_size_in_bytes) noexcept
0885 {
0886 return mutable_buffer(
0887 mutable_buffer(b.data(),
0888 b.size() < max_size_in_bytes
0889 ? b.size() : max_size_in_bytes
0890 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
0891 , b.get_debug_check()
0892 #endif
0893 ));
0894 }
0895
0896
0897
0898
0899
0900 BOOST_ASIO_NODISCARD inline const_buffer buffer(
0901 const const_buffer& b) noexcept
0902 {
0903 return const_buffer(b);
0904 }
0905
0906
0907
0908
0909
0910
0911
0912
0913 BOOST_ASIO_NODISCARD inline const_buffer buffer(
0914 const const_buffer& b,
0915 std::size_t max_size_in_bytes) noexcept
0916 {
0917 return const_buffer(b.data(),
0918 b.size() < max_size_in_bytes
0919 ? b.size() : max_size_in_bytes
0920 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
0921 , b.get_debug_check()
0922 #endif
0923 );
0924 }
0925
0926
0927
0928
0929
0930 BOOST_ASIO_NODISCARD inline mutable_buffer buffer(
0931 void* data, std::size_t size_in_bytes) noexcept
0932 {
0933 return mutable_buffer(data, size_in_bytes);
0934 }
0935
0936
0937
0938
0939
0940 BOOST_ASIO_NODISCARD inline const_buffer buffer(
0941 const void* data, std::size_t size_in_bytes) noexcept
0942 {
0943 return const_buffer(data, size_in_bytes);
0944 }
0945
0946
0947
0948
0949
0950
0951
0952
0953 template <typename PodType, std::size_t N>
0954 BOOST_ASIO_NODISCARD inline mutable_buffer buffer(
0955 PodType (&data)[N]) noexcept
0956 {
0957 return mutable_buffer(data, N * sizeof(PodType));
0958 }
0959
0960
0961
0962
0963
0964
0965
0966
0967 template <typename PodType, std::size_t N>
0968 BOOST_ASIO_NODISCARD inline mutable_buffer buffer(
0969 PodType (&data)[N],
0970 std::size_t max_size_in_bytes) noexcept
0971 {
0972 return mutable_buffer(data,
0973 N * sizeof(PodType) < max_size_in_bytes
0974 ? N * sizeof(PodType) : max_size_in_bytes);
0975 }
0976
0977
0978
0979
0980
0981
0982
0983
0984 template <typename PodType, std::size_t N>
0985 BOOST_ASIO_NODISCARD inline const_buffer buffer(
0986 const PodType (&data)[N]) noexcept
0987 {
0988 return const_buffer(data, N * sizeof(PodType));
0989 }
0990
0991
0992
0993
0994
0995
0996
0997
0998 template <typename PodType, std::size_t N>
0999 BOOST_ASIO_NODISCARD inline const_buffer buffer(
1000 const PodType (&data)[N],
1001 std::size_t max_size_in_bytes) noexcept
1002 {
1003 return const_buffer(data,
1004 N * sizeof(PodType) < max_size_in_bytes
1005 ? N * sizeof(PodType) : max_size_in_bytes);
1006 }
1007
1008
1009
1010
1011
1012
1013
1014
1015 template <typename PodType, std::size_t N>
1016 BOOST_ASIO_NODISCARD inline mutable_buffer buffer(
1017 boost::array<PodType, N>& data) noexcept
1018 {
1019 return mutable_buffer(
1020 data.data(), data.size() * sizeof(PodType));
1021 }
1022
1023
1024
1025
1026
1027
1028
1029
1030 template <typename PodType, std::size_t N>
1031 BOOST_ASIO_NODISCARD inline mutable_buffer buffer(
1032 boost::array<PodType, N>& data,
1033 std::size_t max_size_in_bytes) noexcept
1034 {
1035 return mutable_buffer(data.data(),
1036 data.size() * sizeof(PodType) < max_size_in_bytes
1037 ? data.size() * sizeof(PodType) : max_size_in_bytes);
1038 }
1039
1040
1041
1042
1043
1044
1045
1046
1047 template <typename PodType, std::size_t N>
1048 BOOST_ASIO_NODISCARD inline const_buffer buffer(
1049 boost::array<const PodType, N>& data) noexcept
1050 {
1051 return const_buffer(data.data(), data.size() * sizeof(PodType));
1052 }
1053
1054
1055
1056
1057
1058
1059
1060
1061 template <typename PodType, std::size_t N>
1062 BOOST_ASIO_NODISCARD inline const_buffer buffer(
1063 boost::array<const PodType, N>& data,
1064 std::size_t max_size_in_bytes) noexcept
1065 {
1066 return const_buffer(data.data(),
1067 data.size() * sizeof(PodType) < max_size_in_bytes
1068 ? data.size() * sizeof(PodType) : max_size_in_bytes);
1069 }
1070
1071
1072
1073
1074
1075
1076
1077
1078 template <typename PodType, std::size_t N>
1079 BOOST_ASIO_NODISCARD inline const_buffer buffer(
1080 const boost::array<PodType, N>& data) noexcept
1081 {
1082 return const_buffer(data.data(), data.size() * sizeof(PodType));
1083 }
1084
1085
1086
1087
1088
1089
1090
1091
1092 template <typename PodType, std::size_t N>
1093 BOOST_ASIO_NODISCARD inline const_buffer buffer(
1094 const boost::array<PodType, N>& data,
1095 std::size_t max_size_in_bytes) noexcept
1096 {
1097 return const_buffer(data.data(),
1098 data.size() * sizeof(PodType) < max_size_in_bytes
1099 ? data.size() * sizeof(PodType) : max_size_in_bytes);
1100 }
1101
1102
1103
1104
1105
1106
1107
1108
1109 template <typename PodType, std::size_t N>
1110 BOOST_ASIO_NODISCARD inline mutable_buffer buffer(
1111 std::array<PodType, N>& data) noexcept
1112 {
1113 return mutable_buffer(data.data(), data.size() * sizeof(PodType));
1114 }
1115
1116
1117
1118
1119
1120
1121
1122
1123 template <typename PodType, std::size_t N>
1124 BOOST_ASIO_NODISCARD inline mutable_buffer buffer(
1125 std::array<PodType, N>& data,
1126 std::size_t max_size_in_bytes) noexcept
1127 {
1128 return mutable_buffer(data.data(),
1129 data.size() * sizeof(PodType) < max_size_in_bytes
1130 ? data.size() * sizeof(PodType) : max_size_in_bytes);
1131 }
1132
1133
1134
1135
1136
1137
1138
1139
1140 template <typename PodType, std::size_t N>
1141 BOOST_ASIO_NODISCARD inline const_buffer buffer(
1142 std::array<const PodType, N>& data) noexcept
1143 {
1144 return const_buffer(data.data(), data.size() * sizeof(PodType));
1145 }
1146
1147
1148
1149
1150
1151
1152
1153
1154 template <typename PodType, std::size_t N>
1155 BOOST_ASIO_NODISCARD inline const_buffer buffer(
1156 std::array<const PodType, N>& data,
1157 std::size_t max_size_in_bytes) noexcept
1158 {
1159 return const_buffer(data.data(),
1160 data.size() * sizeof(PodType) < max_size_in_bytes
1161 ? data.size() * sizeof(PodType) : max_size_in_bytes);
1162 }
1163
1164
1165
1166
1167
1168
1169
1170
1171 template <typename PodType, std::size_t N>
1172 BOOST_ASIO_NODISCARD inline const_buffer buffer(
1173 const std::array<PodType, N>& data) noexcept
1174 {
1175 return const_buffer(data.data(), data.size() * sizeof(PodType));
1176 }
1177
1178
1179
1180
1181
1182
1183
1184
1185 template <typename PodType, std::size_t N>
1186 BOOST_ASIO_NODISCARD inline const_buffer buffer(
1187 const std::array<PodType, N>& data,
1188 std::size_t max_size_in_bytes) noexcept
1189 {
1190 return const_buffer(data.data(),
1191 data.size() * sizeof(PodType) < max_size_in_bytes
1192 ? data.size() * sizeof(PodType) : max_size_in_bytes);
1193 }
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205 template <typename PodType, typename Allocator>
1206 BOOST_ASIO_NODISCARD inline mutable_buffer buffer(
1207 std::vector<PodType, Allocator>& data) noexcept
1208 {
1209 return mutable_buffer(
1210 data.size() ? &data[0] : 0, data.size() * sizeof(PodType)
1211 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
1212 , detail::buffer_debug_check<
1213 typename std::vector<PodType, Allocator>::iterator
1214 >(data.begin())
1215 #endif
1216 );
1217 }
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229 template <typename PodType, typename Allocator>
1230 BOOST_ASIO_NODISCARD inline mutable_buffer buffer(
1231 std::vector<PodType, Allocator>& data,
1232 std::size_t max_size_in_bytes) noexcept
1233 {
1234 return mutable_buffer(data.size() ? &data[0] : 0,
1235 data.size() * sizeof(PodType) < max_size_in_bytes
1236 ? data.size() * sizeof(PodType) : max_size_in_bytes
1237 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
1238 , detail::buffer_debug_check<
1239 typename std::vector<PodType, Allocator>::iterator
1240 >(data.begin())
1241 #endif
1242 );
1243 }
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255 template <typename PodType, typename Allocator>
1256 BOOST_ASIO_NODISCARD inline const_buffer buffer(
1257 const std::vector<PodType, Allocator>& data) noexcept
1258 {
1259 return const_buffer(
1260 data.size() ? &data[0] : 0, data.size() * sizeof(PodType)
1261 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
1262 , detail::buffer_debug_check<
1263 typename std::vector<PodType, Allocator>::const_iterator
1264 >(data.begin())
1265 #endif
1266 );
1267 }
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279 template <typename PodType, typename Allocator>
1280 BOOST_ASIO_NODISCARD inline const_buffer buffer(
1281 const std::vector<PodType, Allocator>& data,
1282 std::size_t max_size_in_bytes) noexcept
1283 {
1284 return const_buffer(data.size() ? &data[0] : 0,
1285 data.size() * sizeof(PodType) < max_size_in_bytes
1286 ? data.size() * sizeof(PodType) : max_size_in_bytes
1287 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
1288 , detail::buffer_debug_check<
1289 typename std::vector<PodType, Allocator>::const_iterator
1290 >(data.begin())
1291 #endif
1292 );
1293 }
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303 template <typename Elem, typename Traits, typename Allocator>
1304 BOOST_ASIO_NODISCARD inline mutable_buffer buffer(
1305 std::basic_string<Elem, Traits, Allocator>& data) noexcept
1306 {
1307 return mutable_buffer(data.size() ? &data[0] : 0,
1308 data.size() * sizeof(Elem)
1309 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
1310 , detail::buffer_debug_check<
1311 typename std::basic_string<Elem, Traits, Allocator>::iterator
1312 >(data.begin())
1313 #endif
1314 );
1315 }
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327 template <typename Elem, typename Traits, typename Allocator>
1328 BOOST_ASIO_NODISCARD inline mutable_buffer buffer(
1329 std::basic_string<Elem, Traits, Allocator>& data,
1330 std::size_t max_size_in_bytes) noexcept
1331 {
1332 return mutable_buffer(data.size() ? &data[0] : 0,
1333 data.size() * sizeof(Elem) < max_size_in_bytes
1334 ? data.size() * sizeof(Elem) : max_size_in_bytes
1335 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
1336 , detail::buffer_debug_check<
1337 typename std::basic_string<Elem, Traits, Allocator>::iterator
1338 >(data.begin())
1339 #endif
1340 );
1341 }
1342
1343
1344
1345
1346
1347
1348
1349
1350 template <typename Elem, typename Traits, typename Allocator>
1351 BOOST_ASIO_NODISCARD inline const_buffer buffer(
1352 const std::basic_string<Elem, Traits, Allocator>& data) noexcept
1353 {
1354 return const_buffer(data.data(), data.size() * sizeof(Elem)
1355 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
1356 , detail::buffer_debug_check<
1357 typename std::basic_string<Elem, Traits, Allocator>::const_iterator
1358 >(data.begin())
1359 #endif
1360 );
1361 }
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373 template <typename Elem, typename Traits, typename Allocator>
1374 BOOST_ASIO_NODISCARD inline const_buffer buffer(
1375 const std::basic_string<Elem, Traits, Allocator>& data,
1376 std::size_t max_size_in_bytes) noexcept
1377 {
1378 return const_buffer(data.data(),
1379 data.size() * sizeof(Elem) < max_size_in_bytes
1380 ? data.size() * sizeof(Elem) : max_size_in_bytes
1381 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
1382 , detail::buffer_debug_check<
1383 typename std::basic_string<Elem, Traits, Allocator>::const_iterator
1384 >(data.begin())
1385 #endif
1386 );
1387 }
1388
1389 #if defined(BOOST_ASIO_HAS_STRING_VIEW) \
1390 || defined(GENERATING_DOCUMENTATION)
1391
1392
1393
1394
1395
1396
1397 template <typename Elem, typename Traits>
1398 BOOST_ASIO_NODISCARD inline const_buffer buffer(
1399 basic_string_view<Elem, Traits> data) noexcept
1400 {
1401 return const_buffer(data.size() ? &data[0] : 0,
1402 data.size() * sizeof(Elem)
1403 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
1404 , detail::buffer_debug_check<
1405 typename basic_string_view<Elem, Traits>::iterator
1406 >(data.begin())
1407 #endif
1408 );
1409 }
1410
1411
1412
1413
1414
1415
1416
1417
1418 template <typename Elem, typename Traits>
1419 BOOST_ASIO_NODISCARD inline const_buffer buffer(
1420 basic_string_view<Elem, Traits> data,
1421 std::size_t max_size_in_bytes) noexcept
1422 {
1423 return const_buffer(data.size() ? &data[0] : 0,
1424 data.size() * sizeof(Elem) < max_size_in_bytes
1425 ? data.size() * sizeof(Elem) : max_size_in_bytes
1426 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
1427 , detail::buffer_debug_check<
1428 typename basic_string_view<Elem, Traits>::iterator
1429 >(data.begin())
1430 #endif
1431 );
1432 }
1433
1434 #endif
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444 template <typename T>
1445 BOOST_ASIO_NODISCARD inline mutable_buffer buffer(
1446 T& data,
1447 constraint_t<
1448 is_contiguous_iterator<typename T::iterator>::value,
1449 defaulted_constraint
1450 > = defaulted_constraint(),
1451 constraint_t<
1452 !is_convertible<T, const_buffer>::value,
1453 defaulted_constraint
1454 > = defaulted_constraint(),
1455 constraint_t<
1456 !is_convertible<T, mutable_buffer>::value,
1457 defaulted_constraint
1458 > = defaulted_constraint(),
1459 constraint_t<
1460 !is_const<
1461 remove_reference_t<
1462 typename std::iterator_traits<typename T::iterator>::reference
1463 >
1464 >::value,
1465 defaulted_constraint
1466 > = defaulted_constraint()) noexcept
1467 {
1468 return mutable_buffer(
1469 data.size() ? detail::to_address(data.begin()) : 0,
1470 data.size() * sizeof(typename T::value_type));
1471 }
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482 template <typename T>
1483 BOOST_ASIO_NODISCARD inline mutable_buffer buffer(
1484 T& data, std::size_t max_size_in_bytes,
1485 constraint_t<
1486 is_contiguous_iterator<typename T::iterator>::value,
1487 defaulted_constraint
1488 > = defaulted_constraint(),
1489 constraint_t<
1490 !is_convertible<T, const_buffer>::value,
1491 defaulted_constraint
1492 > = defaulted_constraint(),
1493 constraint_t<
1494 !is_convertible<T, mutable_buffer>::value,
1495 defaulted_constraint
1496 > = defaulted_constraint(),
1497 constraint_t<
1498 !is_const<
1499 remove_reference_t<
1500 typename std::iterator_traits<typename T::iterator>::reference
1501 >
1502 >::value,
1503 defaulted_constraint
1504 > = defaulted_constraint()) noexcept
1505 {
1506 return mutable_buffer(
1507 data.size() ? detail::to_address(data.begin()) : 0,
1508 data.size() * sizeof(typename T::value_type) < max_size_in_bytes
1509 ? data.size() * sizeof(typename T::value_type) : max_size_in_bytes);
1510 }
1511
1512
1513
1514
1515
1516
1517
1518
1519 template <typename T>
1520 BOOST_ASIO_NODISCARD inline const_buffer buffer(
1521 T& data,
1522 constraint_t<
1523 is_contiguous_iterator<typename T::iterator>::value,
1524 defaulted_constraint
1525 > = defaulted_constraint(),
1526 constraint_t<
1527 !is_convertible<T, const_buffer>::value,
1528 defaulted_constraint
1529 > = defaulted_constraint(),
1530 constraint_t<
1531 !is_convertible<T, mutable_buffer>::value,
1532 defaulted_constraint
1533 > = defaulted_constraint(),
1534 constraint_t<
1535 is_const<
1536 remove_reference_t<
1537 typename std::iterator_traits<typename T::iterator>::reference
1538 >
1539 >::value,
1540 defaulted_constraint
1541 > = defaulted_constraint()) noexcept
1542 {
1543 return const_buffer(
1544 data.size() ? detail::to_address(data.begin()) : 0,
1545 data.size() * sizeof(typename T::value_type));
1546 }
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557 template <typename T>
1558 BOOST_ASIO_NODISCARD inline const_buffer buffer(
1559 T& data, std::size_t max_size_in_bytes,
1560 constraint_t<
1561 is_contiguous_iterator<typename T::iterator>::value,
1562 defaulted_constraint
1563 > = defaulted_constraint(),
1564 constraint_t<
1565 !is_convertible<T, const_buffer>::value,
1566 defaulted_constraint
1567 > = defaulted_constraint(),
1568 constraint_t<
1569 !is_convertible<T, mutable_buffer>::value,
1570 defaulted_constraint
1571 > = defaulted_constraint(),
1572 constraint_t<
1573 is_const<
1574 remove_reference_t<
1575 typename std::iterator_traits<typename T::iterator>::reference
1576 >
1577 >::value,
1578 defaulted_constraint
1579 > = defaulted_constraint()) noexcept
1580 {
1581 return const_buffer(
1582 data.size() ? detail::to_address(data.begin()) : 0,
1583 data.size() * sizeof(typename T::value_type) < max_size_in_bytes
1584 ? data.size() * sizeof(typename T::value_type) : max_size_in_bytes);
1585 }
1586
1587
1588
1589
1590
1591
1592
1593
1594 template <typename T>
1595 BOOST_ASIO_NODISCARD inline const_buffer buffer(
1596 const T& data,
1597 constraint_t<
1598 is_contiguous_iterator<typename T::const_iterator>::value,
1599 defaulted_constraint
1600 > = defaulted_constraint(),
1601 constraint_t<
1602 !is_convertible<T, const_buffer>::value,
1603 defaulted_constraint
1604 > = defaulted_constraint(),
1605 constraint_t<
1606 !is_convertible<T, mutable_buffer>::value,
1607 defaulted_constraint
1608 > = defaulted_constraint()) noexcept
1609 {
1610 return const_buffer(
1611 data.size() ? detail::to_address(data.begin()) : 0,
1612 data.size() * sizeof(typename T::value_type));
1613 }
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624 template <typename T>
1625 BOOST_ASIO_NODISCARD inline const_buffer buffer(
1626 const T& data, std::size_t max_size_in_bytes,
1627 constraint_t<
1628 is_contiguous_iterator<typename T::const_iterator>::value,
1629 defaulted_constraint
1630 > = defaulted_constraint(),
1631 constraint_t<
1632 !is_convertible<T, const_buffer>::value,
1633 defaulted_constraint
1634 > = defaulted_constraint(),
1635 constraint_t<
1636 !is_convertible<T, mutable_buffer>::value,
1637 defaulted_constraint
1638 > = defaulted_constraint()) noexcept
1639 {
1640 return const_buffer(
1641 data.size() ? detail::to_address(data.begin()) : 0,
1642 data.size() * sizeof(typename T::value_type) < max_size_in_bytes
1643 ? data.size() * sizeof(typename T::value_type) : max_size_in_bytes);
1644 }
1645
1646
1647
1648
1649
1650 template <template <typename, std::size_t> class Span,
1651 typename T, std::size_t Extent>
1652 BOOST_ASIO_NODISCARD inline mutable_buffer buffer(
1653 const Span<T, Extent>& span,
1654 constraint_t<
1655 !is_const<T>::value,
1656 defaulted_constraint
1657 > = defaulted_constraint(),
1658 constraint_t<
1659 sizeof(T) == 1,
1660 defaulted_constraint
1661 > = defaulted_constraint(),
1662 constraint_t<
1663 #if defined(BOOST_ASIO_MSVC)
1664 detail::has_subspan_memfn<Span<T, Extent>>::value,
1665 #else
1666 is_same<
1667 decltype(span.subspan(0, 0)),
1668 Span<T, static_cast<std::size_t>(-1)>
1669 >::value,
1670 #endif
1671 defaulted_constraint
1672 > = defaulted_constraint()) noexcept
1673 {
1674 return mutable_buffer(span);
1675 }
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685 template <template <typename, std::size_t> class Span,
1686 typename T, std::size_t Extent>
1687 BOOST_ASIO_NODISCARD inline mutable_buffer buffer(
1688 const Span<T, Extent>& span,
1689 std::size_t max_size_in_bytes,
1690 constraint_t<
1691 !is_const<T>::value,
1692 defaulted_constraint
1693 > = defaulted_constraint(),
1694 constraint_t<
1695 sizeof(T) == 1,
1696 defaulted_constraint
1697 > = defaulted_constraint(),
1698 constraint_t<
1699 #if defined(BOOST_ASIO_MSVC)
1700 detail::has_subspan_memfn<Span<T, Extent>>::value,
1701 #else
1702 is_same<
1703 decltype(span.subspan(0, 0)),
1704 Span<T, static_cast<std::size_t>(-1)>
1705 >::value,
1706 #endif
1707 defaulted_constraint
1708 > = defaulted_constraint()) noexcept
1709 {
1710 return buffer(mutable_buffer(span), max_size_in_bytes);
1711 }
1712
1713
1714
1715
1716
1717 template <template <typename, std::size_t> class Span,
1718 typename T, std::size_t Extent>
1719 BOOST_ASIO_NODISCARD inline const_buffer buffer(
1720 const Span<const T, Extent>& span,
1721 constraint_t<
1722 sizeof(T) == 1,
1723 defaulted_constraint
1724 > = defaulted_constraint(),
1725 constraint_t<
1726 #if defined(BOOST_ASIO_MSVC)
1727 detail::has_subspan_memfn<Span<const T, Extent>>::value,
1728 #else
1729 is_same<
1730 decltype(span.subspan(0, 0)),
1731 Span<T, static_cast<std::size_t>(-1)>
1732 >::value,
1733 #endif
1734 defaulted_constraint
1735 > = defaulted_constraint()) noexcept
1736 {
1737 return const_buffer(span);
1738 }
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748 template <template <typename, std::size_t> class Span,
1749 typename T, std::size_t Extent>
1750 BOOST_ASIO_NODISCARD inline const_buffer buffer(
1751 const Span<const T, Extent>& span,
1752 std::size_t max_size_in_bytes,
1753 constraint_t<
1754 sizeof(T) == 1,
1755 defaulted_constraint
1756 > = defaulted_constraint(),
1757 constraint_t<
1758 #if defined(BOOST_ASIO_MSVC)
1759 detail::has_subspan_memfn<Span<const T, Extent>>::value,
1760 #else
1761 is_same<
1762 decltype(span.subspan(0, 0)),
1763 Span<T, static_cast<std::size_t>(-1)>
1764 >::value,
1765 #endif
1766 defaulted_constraint
1767 > = defaulted_constraint()) noexcept
1768 {
1769 return buffer(const_buffer(span), max_size_in_bytes);
1770 }
1771
1772
1773
1774
1775
1776
1777
1778 template <typename Elem, typename Traits, typename Allocator>
1779 class dynamic_string_buffer
1780 {
1781 public:
1782
1783
1784 typedef const_buffer const_buffers_type;
1785
1786
1787
1788 typedef mutable_buffer mutable_buffers_type;
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802 explicit dynamic_string_buffer(std::basic_string<Elem, Traits, Allocator>& s,
1803 std::size_t maximum_size =
1804 (std::numeric_limits<std::size_t>::max)()) noexcept
1805 : string_(s),
1806 #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
1807 size_((std::numeric_limits<std::size_t>::max)()),
1808 #endif
1809 max_size_(maximum_size)
1810 {
1811 }
1812
1813
1814 dynamic_string_buffer(const dynamic_string_buffer& other) noexcept
1815 : string_(other.string_),
1816 #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
1817 size_(other.size_),
1818 #endif
1819 max_size_(other.max_size_)
1820 {
1821 }
1822
1823
1824 dynamic_string_buffer(dynamic_string_buffer&& other) noexcept
1825 : string_(other.string_),
1826 #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
1827 size_(other.size_),
1828 #endif
1829 max_size_(other.max_size_)
1830 {
1831 }
1832
1833
1834
1835
1836
1837
1838
1839
1840 std::size_t size() const noexcept
1841 {
1842 #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
1843 if (size_ != (std::numeric_limits<std::size_t>::max)())
1844 return size_;
1845 #endif
1846 return (std::min)(string_.size(), max_size());
1847 }
1848
1849
1850
1851
1852
1853 std::size_t max_size() const noexcept
1854 {
1855 return max_size_;
1856 }
1857
1858
1859
1860
1861
1862
1863
1864 std::size_t capacity() const noexcept
1865 {
1866 return (std::min)(string_.capacity(), max_size());
1867 }
1868
1869 #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880 const_buffers_type data() const noexcept
1881 {
1882 return const_buffers_type(boost::asio::buffer(string_, size_));
1883 }
1884 #endif
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901 mutable_buffers_type data(std::size_t pos, std::size_t n) noexcept
1902 {
1903 return mutable_buffers_type(boost::asio::buffer(
1904 boost::asio::buffer(string_, max_size_) + pos, n));
1905 }
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919 const_buffers_type data(std::size_t pos,
1920 std::size_t n) const noexcept
1921 {
1922 return const_buffers_type(boost::asio::buffer(
1923 boost::asio::buffer(string_, max_size_) + pos, n));
1924 }
1925
1926 #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943 mutable_buffers_type prepare(std::size_t n)
1944 {
1945 if (size() > max_size() || max_size() - size() < n)
1946 {
1947 std::length_error ex("dynamic_string_buffer too long");
1948 boost::asio::detail::throw_exception(ex);
1949 }
1950
1951 if (size_ == (std::numeric_limits<std::size_t>::max)())
1952 size_ = string_.size();
1953
1954 string_.resize(size_ + n);
1955
1956 return boost::asio::buffer(boost::asio::buffer(string_) + size_, n);
1957 }
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972 void commit(std::size_t n)
1973 {
1974 size_ += (std::min)(n, string_.size() - size_);
1975 string_.resize(size_);
1976 }
1977 #endif
1978
1979
1980
1981
1982
1983
1984
1985
1986 void grow(std::size_t n)
1987 {
1988 if (size() > max_size() || max_size() - size() < n)
1989 {
1990 std::length_error ex("dynamic_string_buffer too long");
1991 boost::asio::detail::throw_exception(ex);
1992 }
1993
1994 string_.resize(size() + n);
1995 }
1996
1997
1998
1999
2000
2001
2002
2003
2004 void shrink(std::size_t n)
2005 {
2006 string_.resize(n > size() ? 0 : size() - n);
2007 }
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021 void consume(std::size_t n)
2022 {
2023 #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
2024 if (size_ != (std::numeric_limits<std::size_t>::max)())
2025 {
2026 std::size_t consume_length = (std::min)(n, size_);
2027 string_.erase(0, consume_length);
2028 size_ -= consume_length;
2029 return;
2030 }
2031 #endif
2032 string_.erase(0, n);
2033 }
2034
2035 private:
2036 std::basic_string<Elem, Traits, Allocator>& string_;
2037 #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
2038 std::size_t size_;
2039 #endif
2040 const std::size_t max_size_;
2041 };
2042
2043
2044
2045
2046
2047 template <typename Elem, typename Allocator>
2048 class dynamic_vector_buffer
2049 {
2050 public:
2051
2052
2053 typedef const_buffer const_buffers_type;
2054
2055
2056
2057 typedef mutable_buffer mutable_buffers_type;
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068 explicit dynamic_vector_buffer(std::vector<Elem, Allocator>& v,
2069 std::size_t maximum_size =
2070 (std::numeric_limits<std::size_t>::max)()) noexcept
2071 : vector_(v),
2072 #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
2073 size_((std::numeric_limits<std::size_t>::max)()),
2074 #endif
2075 max_size_(maximum_size)
2076 {
2077 }
2078
2079
2080 dynamic_vector_buffer(const dynamic_vector_buffer& other) noexcept
2081 : vector_(other.vector_),
2082 #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
2083 size_(other.size_),
2084 #endif
2085 max_size_(other.max_size_)
2086 {
2087 }
2088
2089
2090 dynamic_vector_buffer(dynamic_vector_buffer&& other) noexcept
2091 : vector_(other.vector_),
2092 #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
2093 size_(other.size_),
2094 #endif
2095 max_size_(other.max_size_)
2096 {
2097 }
2098
2099
2100
2101
2102
2103
2104
2105
2106 std::size_t size() const noexcept
2107 {
2108 #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
2109 if (size_ != (std::numeric_limits<std::size_t>::max)())
2110 return size_;
2111 #endif
2112 return (std::min)(vector_.size(), max_size());
2113 }
2114
2115
2116
2117
2118
2119
2120
2121 std::size_t max_size() const noexcept
2122 {
2123 return max_size_;
2124 }
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134 std::size_t capacity() const noexcept
2135 {
2136 return (std::min)(vector_.capacity(), max_size());
2137 }
2138
2139 #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151 const_buffers_type data() const noexcept
2152 {
2153 return const_buffers_type(boost::asio::buffer(vector_, size_));
2154 }
2155 #endif
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172 mutable_buffers_type data(std::size_t pos, std::size_t n) noexcept
2173 {
2174 return mutable_buffers_type(boost::asio::buffer(
2175 boost::asio::buffer(vector_, max_size_) + pos, n));
2176 }
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190 const_buffers_type data(std::size_t pos,
2191 std::size_t n) const noexcept
2192 {
2193 return const_buffers_type(boost::asio::buffer(
2194 boost::asio::buffer(vector_, max_size_) + pos, n));
2195 }
2196
2197 #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214 mutable_buffers_type prepare(std::size_t n)
2215 {
2216 if (size () > max_size() || max_size() - size() < n)
2217 {
2218 std::length_error ex("dynamic_vector_buffer too long");
2219 boost::asio::detail::throw_exception(ex);
2220 }
2221
2222 if (size_ == (std::numeric_limits<std::size_t>::max)())
2223 size_ = vector_.size();
2224
2225 vector_.resize(size_ + n);
2226
2227 return boost::asio::buffer(boost::asio::buffer(vector_) + size_, n);
2228 }
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243 void commit(std::size_t n)
2244 {
2245 size_ += (std::min)(n, vector_.size() - size_);
2246 vector_.resize(size_);
2247 }
2248 #endif
2249
2250
2251
2252
2253
2254
2255
2256
2257 void grow(std::size_t n)
2258 {
2259 if (size() > max_size() || max_size() - size() < n)
2260 {
2261 std::length_error ex("dynamic_vector_buffer too long");
2262 boost::asio::detail::throw_exception(ex);
2263 }
2264
2265 vector_.resize(size() + n);
2266 }
2267
2268
2269
2270
2271
2272
2273
2274
2275 void shrink(std::size_t n)
2276 {
2277 vector_.resize(n > size() ? 0 : size() - n);
2278 }
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292 void consume(std::size_t n)
2293 {
2294 #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
2295 if (size_ != (std::numeric_limits<std::size_t>::max)())
2296 {
2297 std::size_t consume_length = (std::min)(n, size_);
2298 vector_.erase(vector_.begin(), vector_.begin() + consume_length);
2299 size_ -= consume_length;
2300 return;
2301 }
2302 #endif
2303 vector_.erase(vector_.begin(), vector_.begin() + (std::min)(size(), n));
2304 }
2305
2306 private:
2307 std::vector<Elem, Allocator>& vector_;
2308 #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
2309 std::size_t size_;
2310 #endif
2311 const std::size_t max_size_;
2312 };
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325 template <typename Elem, typename Traits, typename Allocator>
2326 BOOST_ASIO_NODISCARD inline
2327 dynamic_string_buffer<Elem, Traits, Allocator> dynamic_buffer(
2328 std::basic_string<Elem, Traits, Allocator>& data) noexcept
2329 {
2330 return dynamic_string_buffer<Elem, Traits, Allocator>(data);
2331 }
2332
2333
2334
2335
2336
2337
2338 template <typename Elem, typename Traits, typename Allocator>
2339 BOOST_ASIO_NODISCARD inline
2340 dynamic_string_buffer<Elem, Traits, Allocator> dynamic_buffer(
2341 std::basic_string<Elem, Traits, Allocator>& data,
2342 std::size_t max_size) noexcept
2343 {
2344 return dynamic_string_buffer<Elem, Traits, Allocator>(data, max_size);
2345 }
2346
2347
2348
2349
2350
2351 template <typename Elem, typename Allocator>
2352 BOOST_ASIO_NODISCARD inline
2353 dynamic_vector_buffer<Elem, Allocator> dynamic_buffer(
2354 std::vector<Elem, Allocator>& data) noexcept
2355 {
2356 return dynamic_vector_buffer<Elem, Allocator>(data);
2357 }
2358
2359
2360
2361
2362
2363 template <typename Elem, typename Allocator>
2364 BOOST_ASIO_NODISCARD inline
2365 dynamic_vector_buffer<Elem, Allocator> dynamic_buffer(
2366 std::vector<Elem, Allocator>& data,
2367 std::size_t max_size) noexcept
2368 {
2369 return dynamic_vector_buffer<Elem, Allocator>(data, max_size);
2370 }
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402 namespace detail {
2403
2404 inline std::size_t buffer_copy_1(const mutable_buffer& target,
2405 const const_buffer& source)
2406 {
2407 using namespace std;
2408 std::size_t target_size = target.size();
2409 std::size_t source_size = source.size();
2410 std::size_t n = target_size < source_size ? target_size : source_size;
2411 if (n > 0)
2412 memcpy(target.data(), source.data(), n);
2413 return n;
2414 }
2415
2416 template <typename TargetIterator, typename SourceIterator>
2417 inline std::size_t buffer_copy(one_buffer, one_buffer,
2418 TargetIterator target_begin, TargetIterator,
2419 SourceIterator source_begin, SourceIterator) noexcept
2420 {
2421 return (buffer_copy_1)(*target_begin, *source_begin);
2422 }
2423
2424 template <typename TargetIterator, typename SourceIterator>
2425 inline std::size_t buffer_copy(one_buffer, one_buffer,
2426 TargetIterator target_begin, TargetIterator,
2427 SourceIterator source_begin, SourceIterator,
2428 std::size_t max_bytes_to_copy) noexcept
2429 {
2430 return (buffer_copy_1)(*target_begin,
2431 boost::asio::buffer(*source_begin, max_bytes_to_copy));
2432 }
2433
2434 template <typename TargetIterator, typename SourceIterator>
2435 std::size_t buffer_copy(one_buffer, multiple_buffers,
2436 TargetIterator target_begin, TargetIterator,
2437 SourceIterator source_begin, SourceIterator source_end,
2438 std::size_t max_bytes_to_copy
2439 = (std::numeric_limits<std::size_t>::max)()) noexcept
2440 {
2441 std::size_t total_bytes_copied = 0;
2442 SourceIterator source_iter = source_begin;
2443
2444 for (mutable_buffer target_buffer(
2445 boost::asio::buffer(*target_begin, max_bytes_to_copy));
2446 target_buffer.size() && source_iter != source_end; ++source_iter)
2447 {
2448 const_buffer source_buffer(*source_iter);
2449 std::size_t bytes_copied = (buffer_copy_1)(target_buffer, source_buffer);
2450 total_bytes_copied += bytes_copied;
2451 target_buffer += bytes_copied;
2452 }
2453
2454 return total_bytes_copied;
2455 }
2456
2457 template <typename TargetIterator, typename SourceIterator>
2458 std::size_t buffer_copy(multiple_buffers, one_buffer,
2459 TargetIterator target_begin, TargetIterator target_end,
2460 SourceIterator source_begin, SourceIterator,
2461 std::size_t max_bytes_to_copy
2462 = (std::numeric_limits<std::size_t>::max)()) noexcept
2463 {
2464 std::size_t total_bytes_copied = 0;
2465 TargetIterator target_iter = target_begin;
2466
2467 for (const_buffer source_buffer(
2468 boost::asio::buffer(*source_begin, max_bytes_to_copy));
2469 source_buffer.size() && target_iter != target_end; ++target_iter)
2470 {
2471 mutable_buffer target_buffer(*target_iter);
2472 std::size_t bytes_copied = (buffer_copy_1)(target_buffer, source_buffer);
2473 total_bytes_copied += bytes_copied;
2474 source_buffer += bytes_copied;
2475 }
2476
2477 return total_bytes_copied;
2478 }
2479
2480 template <typename TargetIterator, typename SourceIterator>
2481 std::size_t buffer_copy(multiple_buffers, multiple_buffers,
2482 TargetIterator target_begin, TargetIterator target_end,
2483 SourceIterator source_begin, SourceIterator source_end) noexcept
2484 {
2485 std::size_t total_bytes_copied = 0;
2486
2487 TargetIterator target_iter = target_begin;
2488 std::size_t target_buffer_offset = 0;
2489
2490 SourceIterator source_iter = source_begin;
2491 std::size_t source_buffer_offset = 0;
2492
2493 while (target_iter != target_end && source_iter != source_end)
2494 {
2495 mutable_buffer target_buffer =
2496 mutable_buffer(*target_iter) + target_buffer_offset;
2497
2498 const_buffer source_buffer =
2499 const_buffer(*source_iter) + source_buffer_offset;
2500
2501 std::size_t bytes_copied = (buffer_copy_1)(target_buffer, source_buffer);
2502 total_bytes_copied += bytes_copied;
2503
2504 if (bytes_copied == target_buffer.size())
2505 {
2506 ++target_iter;
2507 target_buffer_offset = 0;
2508 }
2509 else
2510 target_buffer_offset += bytes_copied;
2511
2512 if (bytes_copied == source_buffer.size())
2513 {
2514 ++source_iter;
2515 source_buffer_offset = 0;
2516 }
2517 else
2518 source_buffer_offset += bytes_copied;
2519 }
2520
2521 return total_bytes_copied;
2522 }
2523
2524 template <typename TargetIterator, typename SourceIterator>
2525 std::size_t buffer_copy(multiple_buffers, multiple_buffers,
2526 TargetIterator target_begin, TargetIterator target_end,
2527 SourceIterator source_begin, SourceIterator source_end,
2528 std::size_t max_bytes_to_copy) noexcept
2529 {
2530 std::size_t total_bytes_copied = 0;
2531
2532 TargetIterator target_iter = target_begin;
2533 std::size_t target_buffer_offset = 0;
2534
2535 SourceIterator source_iter = source_begin;
2536 std::size_t source_buffer_offset = 0;
2537
2538 while (total_bytes_copied != max_bytes_to_copy
2539 && target_iter != target_end && source_iter != source_end)
2540 {
2541 mutable_buffer target_buffer =
2542 mutable_buffer(*target_iter) + target_buffer_offset;
2543
2544 const_buffer source_buffer =
2545 const_buffer(*source_iter) + source_buffer_offset;
2546
2547 std::size_t bytes_copied = (buffer_copy_1)(
2548 target_buffer, boost::asio::buffer(source_buffer,
2549 max_bytes_to_copy - total_bytes_copied));
2550 total_bytes_copied += bytes_copied;
2551
2552 if (bytes_copied == target_buffer.size())
2553 {
2554 ++target_iter;
2555 target_buffer_offset = 0;
2556 }
2557 else
2558 target_buffer_offset += bytes_copied;
2559
2560 if (bytes_copied == source_buffer.size())
2561 {
2562 ++source_iter;
2563 source_buffer_offset = 0;
2564 }
2565 else
2566 source_buffer_offset += bytes_copied;
2567 }
2568
2569 return total_bytes_copied;
2570 }
2571
2572 }
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593 template <typename MutableBufferSequence, typename ConstBufferSequence>
2594 inline std::size_t buffer_copy(const MutableBufferSequence& target,
2595 const ConstBufferSequence& source) noexcept
2596 {
2597 return detail::buffer_copy(
2598 detail::buffer_sequence_cardinality<MutableBufferSequence>(),
2599 detail::buffer_sequence_cardinality<ConstBufferSequence>(),
2600 boost::asio::buffer_sequence_begin(target),
2601 boost::asio::buffer_sequence_end(target),
2602 boost::asio::buffer_sequence_begin(source),
2603 boost::asio::buffer_sequence_end(source));
2604 }
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630 template <typename MutableBufferSequence, typename ConstBufferSequence>
2631 inline std::size_t buffer_copy(const MutableBufferSequence& target,
2632 const ConstBufferSequence& source,
2633 std::size_t max_bytes_to_copy) noexcept
2634 {
2635 return detail::buffer_copy(
2636 detail::buffer_sequence_cardinality<MutableBufferSequence>(),
2637 detail::buffer_sequence_cardinality<ConstBufferSequence>(),
2638 boost::asio::buffer_sequence_begin(target),
2639 boost::asio::buffer_sequence_end(target),
2640 boost::asio::buffer_sequence_begin(source),
2641 boost::asio::buffer_sequence_end(source), max_bytes_to_copy);
2642 }
2643
2644
2645
2646 }
2647 }
2648
2649 #include <boost/asio/detail/pop_options.hpp>
2650 #include <boost/asio/detail/is_buffer_sequence.hpp>
2651 #include <boost/asio/detail/push_options.hpp>
2652
2653 namespace boost {
2654 namespace asio {
2655
2656
2657
2658 template <typename T>
2659 struct is_mutable_buffer_sequence
2660 #if defined(GENERATING_DOCUMENTATION)
2661 : integral_constant<bool, automatically_determined>
2662 #else
2663 : boost::asio::detail::is_buffer_sequence<T, mutable_buffer>
2664 #endif
2665 {
2666 };
2667
2668
2669
2670 template <typename T>
2671 struct is_const_buffer_sequence
2672 #if defined(GENERATING_DOCUMENTATION)
2673 : integral_constant<bool, automatically_determined>
2674 #else
2675 : boost::asio::detail::is_buffer_sequence<T, const_buffer>
2676 #endif
2677 {
2678 };
2679
2680 #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
2681
2682
2683 template <typename T>
2684 struct is_dynamic_buffer_v1
2685 #if defined(GENERATING_DOCUMENTATION)
2686 : integral_constant<bool, automatically_determined>
2687 #else
2688 : boost::asio::detail::is_dynamic_buffer_v1<T>
2689 #endif
2690 {
2691 };
2692 #endif
2693
2694
2695
2696 template <typename T>
2697 struct is_dynamic_buffer_v2
2698 #if defined(GENERATING_DOCUMENTATION)
2699 : integral_constant<bool, automatically_determined>
2700 #else
2701 : boost::asio::detail::is_dynamic_buffer_v2<T>
2702 #endif
2703 {
2704 };
2705
2706
2707
2708
2709
2710
2711
2712
2713 template <typename T>
2714 struct is_dynamic_buffer
2715 #if defined(GENERATING_DOCUMENTATION)
2716 : integral_constant<bool, automatically_determined>
2717 #elif defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
2718 : boost::asio::is_dynamic_buffer_v2<T>
2719 #else
2720 : boost::asio::is_dynamic_buffer_v1<T>
2721 #endif
2722 {
2723 };
2724
2725 namespace buffer_literals {
2726 namespace detail {
2727
2728 template <char... Chars>
2729 struct chars {};
2730
2731 template <unsigned char... Bytes>
2732 struct bytes {};
2733
2734
2735
2736 template <typename Bytes, char... Chars>
2737 struct bin_literal;
2738
2739 template <unsigned char... Bytes>
2740 struct bin_literal<bytes<Bytes...>>
2741 {
2742 static const std::size_t size = sizeof...(Bytes);
2743 static const unsigned char data[sizeof...(Bytes)];
2744 };
2745
2746 template <unsigned char... Bytes>
2747 const unsigned char bin_literal<bytes<Bytes...>>::data[sizeof...(Bytes)]
2748 = { Bytes... };
2749
2750 template <unsigned char... Bytes, char Bit7, char Bit6, char Bit5,
2751 char Bit4, char Bit3, char Bit2, char Bit1, char Bit0, char... Chars>
2752 struct bin_literal<bytes<Bytes...>, Bit7, Bit6,
2753 Bit5, Bit4, Bit3, Bit2, Bit1, Bit0, Chars...> :
2754 bin_literal<
2755 bytes<Bytes...,
2756 static_cast<unsigned char>(
2757 (Bit7 == '1' ? 0x80 : 0) |
2758 (Bit6 == '1' ? 0x40 : 0) |
2759 (Bit5 == '1' ? 0x20 : 0) |
2760 (Bit4 == '1' ? 0x10 : 0) |
2761 (Bit3 == '1' ? 0x08 : 0) |
2762 (Bit2 == '1' ? 0x04 : 0) |
2763 (Bit1 == '1' ? 0x02 : 0) |
2764 (Bit0 == '1' ? 0x01 : 0))
2765 >, Chars...> {};
2766
2767 template <unsigned char... Bytes, char... Chars>
2768 struct bin_literal<bytes<Bytes...>, Chars...>
2769 {
2770 static_assert(sizeof...(Chars) == 0,
2771 "number of digits in a binary buffer literal must be a multiple of 8");
2772
2773 static const std::size_t size = 0;
2774 static const unsigned char data[1];
2775 };
2776
2777 template <unsigned char... Bytes, char... Chars>
2778 const unsigned char bin_literal<bytes<Bytes...>, Chars...>::data[1] = {};
2779
2780
2781
2782 template <typename Bytes, char... Chars>
2783 struct hex_literal;
2784
2785 template <unsigned char... Bytes>
2786 struct hex_literal<bytes<Bytes...>>
2787 {
2788 static const std::size_t size = sizeof...(Bytes);
2789 static const unsigned char data[sizeof...(Bytes)];
2790 };
2791
2792 template <unsigned char... Bytes>
2793 const unsigned char hex_literal<bytes<Bytes...>>::data[sizeof...(Bytes)]
2794 = { Bytes... };
2795
2796 template <unsigned char... Bytes, char Hi, char Lo, char... Chars>
2797 struct hex_literal<bytes<Bytes...>, Hi, Lo, Chars...> :
2798 hex_literal<
2799 bytes<Bytes...,
2800 static_cast<unsigned char>(
2801 Lo >= 'A' && Lo <= 'F' ? Lo - 'A' + 10 :
2802 (Lo >= 'a' && Lo <= 'f' ? Lo - 'a' + 10 : Lo - '0')) |
2803 ((static_cast<unsigned char>(
2804 Hi >= 'A' && Hi <= 'F' ? Hi - 'A' + 10 :
2805 (Hi >= 'a' && Hi <= 'f' ? Hi - 'a' + 10 : Hi - '0'))) << 4)
2806 >, Chars...> {};
2807
2808 template <unsigned char... Bytes, char Char>
2809 struct hex_literal<bytes<Bytes...>, Char>
2810 {
2811 static_assert(!Char,
2812 "a hexadecimal buffer literal must have an even number of digits");
2813
2814 static const std::size_t size = 0;
2815 static const unsigned char data[1];
2816 };
2817
2818 template <unsigned char... Bytes, char Char>
2819 const unsigned char hex_literal<bytes<Bytes...>, Char>::data[1] = {};
2820
2821
2822
2823
2824 template <template <typename, char...> class Literal,
2825 typename Clean, char... Raw>
2826 struct remove_separators;
2827
2828 template <template <typename, char...> class Literal,
2829 char... Clean, char... Raw>
2830 struct remove_separators<Literal, chars<Clean...>, '\'', Raw...> :
2831 remove_separators<Literal, chars<Clean...>, Raw...> {};
2832
2833 template <template <typename, char...> class Literal,
2834 char... Clean, char C, char... Raw>
2835 struct remove_separators<Literal, chars<Clean...>, C, Raw...> :
2836 remove_separators<Literal, chars<Clean..., C>, Raw...> {};
2837
2838 template <template <typename, char...> class Literal, char... Clean>
2839 struct remove_separators<Literal, chars<Clean...>> :
2840 Literal<bytes<>, Clean...> {};
2841
2842
2843
2844 template <char... Chars>
2845 struct literal;
2846
2847 template <char... Chars>
2848 struct literal<'0', 'b', Chars...> :
2849 remove_separators<bin_literal, chars<>, Chars...>{};
2850
2851 template <char... Chars>
2852 struct literal<'0', 'B', Chars...> :
2853 remove_separators<bin_literal, chars<>, Chars...>{};
2854
2855 template <char... Chars>
2856 struct literal<'0', 'x', Chars...> :
2857 remove_separators<hex_literal, chars<>, Chars...>{};
2858
2859 template <char... Chars>
2860 struct literal<'0', 'X', Chars...> :
2861 remove_separators<hex_literal, chars<>, Chars...>{};
2862
2863 }
2864
2865
2866 inline const_buffer operator ""_buf(const char* data, std::size_t n)
2867 {
2868 return const_buffer(data, n);
2869 }
2870
2871
2872
2873 template <char... Chars>
2874 inline const_buffer operator ""_buf()
2875 {
2876 return const_buffer(
2877 +detail::literal<Chars...>::data,
2878 detail::literal<Chars...>::size);
2879 }
2880
2881 }
2882 }
2883 }
2884
2885 #include <boost/asio/detail/pop_options.hpp>
2886
2887 #endif