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