async_mqtt 5.0.0
Loading...
Searching...
No Matches
buffer.hpp
1// Copyright Takatoshi Kondo 2022
2//
3// Distributed under the Boost Software License, Version 1.0.
4// (See accompanying file LICENSE_1_0.txt or copy at
5// http://www.boost.org/LICENSE_1_0.txt)
6
7#if !defined(ASYNC_MQTT_BUFFER_HPP)
8#define ASYNC_MQTT_BUFFER_HPP
9
10#include <string_view>
11
12#include <boost/asio/buffer.hpp>
13#include <boost/container_hash/hash.hpp>
14
15#include <async_mqtt/util/move.hpp>
16#include <async_mqtt/util/any.hpp>
17#include <async_mqtt/util/shared_ptr_array.hpp>
18#include <async_mqtt/util/is_iterator.hpp>
19#include <async_mqtt/util/string_view.hpp>
20
21namespace async_mqtt {
22
23namespace as = boost::asio;
24
30class buffer {
31public:
32 using traits_type = string_view::traits_type;
33 using value_type = string_view::value_type;
34 using pointer = string_view::pointer;
35 using const_pointer = string_view::const_pointer;
36 using reference = string_view::reference;
37 using const_reference = string_view::const_reference;
38 using iterator = string_view::iterator;
39 using const_iterator = string_view::const_iterator;
40 using const_reverse_iterator = string_view::const_reverse_iterator;
41 using reverse_iterator = string_view::reverse_iterator;
42 using size_type = string_view::size_type;
43 using difference_type = string_view::difference_type;
44
45 static constexpr size_type npos = string_view::npos;
46
47 constexpr buffer() noexcept = default;
48 constexpr buffer(char const* s, std::size_t count)
49 :view_{s, count}
50 {}
51 constexpr buffer(char const* s)
52 :view_{s}
53 {}
54
55 template <
56 typename It,
57 typename End,
58 typename std::enable_if_t<
59 is_input_iterator<It>::value &&
60 is_input_iterator<End>::value
61 >* = nullptr
62 >
63 constexpr buffer(It first, End last)
64 :view_{&*first, &*first + std::distance(first, last)}
65 {}
66
73 explicit constexpr buffer(string_view sv)
74 : view_{force_move(sv)}
75 {}
76
83 explicit buffer(std::string) = delete; // to avoid misuse
84
91 buffer(string_view sv, any life)
92 : view_{force_move(sv)},
93 life_{force_move(life)}
94 {
95 }
96
97 buffer(char const* s, std::size_t count, any life)
98 : view_{s, count},
99 life_{force_move(life)}
100 {}
101 buffer(char const* s, any life)
102 : view_{s},
103 life_{force_move(life)}
104 {}
105
106 template <
107 typename It,
108 typename End,
109 typename std::enable_if_t<
110 is_input_iterator<It>::value &&
111 is_input_iterator<End>::value
112 >* = nullptr
113 >
114 buffer(It first, End last, any life)
115 : view_{&*first, static_cast<std::size_t>(std::distance(first, last))},
116 life_{force_move(life)}
117 {}
118
119 constexpr const_iterator begin() const noexcept {
120 return view_.begin();
121 }
122 constexpr const_iterator cbegin() const noexcept {
123 return view_.cbegin();
124 }
125 constexpr const_iterator end() const noexcept {
126 return view_.end();
127 }
128 constexpr const_iterator cend() const noexcept {
129 return view_.cend();
130 }
131 constexpr const_reverse_iterator rbegin() const noexcept {
132 return view_.rbegin();
133 }
134 constexpr const_reverse_iterator crbegin() const noexcept {
135 return view_.crbegin();
136 }
137 constexpr const_reverse_iterator rend() const noexcept {
138 return view_.rend();
139 }
140 constexpr const_reverse_iterator crend() const noexcept {
141 return view_.crend();
142 }
143
144 constexpr const_reference operator[](size_type pos) const {
145 return view_[pos];
146 }
147 constexpr const_reference at(size_type pos) const {
148 return view_.at(pos);
149 }
150
151 constexpr const_reference front() const {
152 return view_.front();
153 }
154 constexpr const_reference back() const {
155 return view_.back();
156 }
157
158 constexpr const_pointer data() const noexcept {
159 return view_.data();
160 }
161
162 constexpr size_type size() const noexcept {
163 return view_.size();
164 }
165 constexpr size_type length() const noexcept {
166 return view_.length();
167 }
168 constexpr size_type max_size() const noexcept {
169 return view_.max_size();
170 }
171
172 constexpr bool empty() const noexcept {
173 return view_.empty();
174 }
175
176 constexpr void remove_prefix(size_type n) {
177 view_.remove_prefix(n);
178 }
179
180 constexpr void remove_suffix(size_type n) {
181 view_.remove_suffix(n);
182 }
183
184 void swap(buffer& buf) noexcept {
185 view_.swap(buf.view_);
186 life_.swap(buf.life_);
187 }
188
189 size_type copy(char* dest, size_type count, size_type pos = 0 ) const {
190 return view_.copy(dest, count, pos);
191 }
192
201 buffer substr(size_type pos = 0, size_type count = npos) const& {
202 // range is checked in string_view::substr.
203 return buffer(view_.substr(pos, count), life_);
204 }
205
214 buffer substr(size_type pos = 0, size_type count = npos) && {
215 // range is checked in string_view::substr.
216 return buffer(view_.substr(pos, count), force_move(life_));
217 }
218
219 constexpr int compare(buffer const& buf) const noexcept {
220 return view_.compare(buf.view_);
221 }
222 constexpr int compare(string_view const& v) const noexcept {
223 return view_.compare(v);
224 }
225 constexpr int compare(size_type pos1, size_type count1, buffer const& buf) const noexcept {
226 return view_.compare(pos1, count1, buf.view_);
227 }
228 constexpr int compare(size_type pos1, size_type count1, string_view const& v) const noexcept {
229 return view_.compare(pos1, count1, v);
230 }
231 constexpr int compare(
232 size_type pos1,
233 size_type count1,
234 buffer const& buf,
235 size_type pos2,
236 size_type count2
237 ) const noexcept {
238 return view_.compare(pos1, count1, buf.view_, pos2, count2);
239 }
240 constexpr int compare(
241 size_type pos1,
242 size_type count1,
243 string_view const& v,
244 size_type pos2,
245 size_type count2
246 ) const noexcept {
247 return view_.compare(pos1, count1, v, pos2, count2);
248 }
249 constexpr int compare(char const* s) const noexcept {
250 return view_.compare(s);
251 }
252 constexpr int compare(size_type pos1, size_type count1, char const* s) const noexcept {
253 return view_.compare(pos1, count1, s);
254 }
255 constexpr int compare(
256 size_type pos1,
257 size_type count1,
258 char const* s,
259 size_type pos2,
260 size_type count2
261 ) const noexcept {
262 return view_.compare(pos1, count1, s, pos2, count2);
263 }
264
265 constexpr size_type find(buffer const& buf, size_type pos = 0) const noexcept {
266 return view_.find(buf.view_, pos);
267 }
268 constexpr size_type find(string_view v, size_type pos = 0) const noexcept {
269 return view_.find(v, pos);
270 }
271 constexpr size_type find(char ch, size_type pos = 0) const noexcept {
272 return view_.find(ch, pos);
273 }
274 constexpr size_type find(char const* s, size_type pos, size_type count) const {
275 return view_.find(s, pos, count);
276 }
277 constexpr size_type find(char const* s, size_type pos = 0) const {
278 return view_.find(s, pos);
279 }
280
281 constexpr size_type rfind(buffer const& buf, size_type pos = npos) const noexcept {
282 return view_.rfind(buf.view_, pos);
283 }
284 constexpr size_type rfind( string_view v, size_type pos = npos) const noexcept {
285 return view_.rfind(v, pos);
286 }
287 constexpr size_type rfind(char ch, size_type pos = npos) const noexcept {
288 return view_.rfind(ch, pos);
289 }
290 constexpr size_type rfind(char const* s, size_type pos, size_type count) const {
291 return view_.rfind(s, pos, count);
292 }
293 constexpr size_type rfind(char const* s, size_type pos = npos) const {
294 return view_.rfind(s, pos);
295 }
296
297 constexpr size_type find_first_of(buffer const& buf, size_type pos = 0) const noexcept {
298 return view_.find_first_of(buf.view_, pos);
299 }
300 constexpr size_type find_first_of( string_view v, size_type pos = 0) const noexcept {
301 return view_.find_first_of(v, pos);
302 }
303 constexpr size_type find_first_of(char ch, size_type pos = 0) const noexcept {
304 return view_.find_first_of(ch, pos);
305 }
306 constexpr size_type find_first_of(char const* s, size_type pos, size_type count) const {
307 return view_.find_first_of(s, pos, count);
308 }
309 constexpr size_type find_first_of(char const* s, size_type pos = 0) const {
310 return view_.find_first_of(s, pos);
311 }
312
313 constexpr size_type find_last_of(buffer const& buf, size_type pos = npos) const noexcept {
314 return view_.find_last_of(buf.view_, pos);
315 }
316 constexpr size_type find_last_of( string_view v, size_type pos = npos) const noexcept {
317 return view_.find_last_of(v, pos);
318 }
319 constexpr size_type find_last_of(char ch, size_type pos = npos) const noexcept {
320 return view_.find_last_of(ch, pos);
321 }
322 constexpr size_type find_last_of(char const* s, size_type pos, size_type count) const {
323 return view_.find_last_of(s, pos, count);
324 }
325 constexpr size_type find_last_of(char const* s, size_type pos = npos) const {
326 return view_.find_last_of(s, pos);
327 }
328
329 constexpr size_type find_first_not_of(buffer const& buf, size_type pos = 0) const noexcept {
330 return view_.find_first_not_of(buf.view_, pos);
331 }
332 constexpr size_type find_first_not_of( string_view v, size_type pos = 0) const noexcept {
333 return view_.find_first_not_of(v, pos);
334 }
335 constexpr size_type find_first_not_of(char ch, size_type pos = 0) const noexcept {
336 return view_.find_first_not_of(ch, pos);
337 }
338 constexpr size_type find_first_not_of(char const* s, size_type pos, size_type count) const {
339 return view_.find_first_not_of(s, pos, count);
340 }
341 constexpr size_type find_first_not_of(char const* s, size_type pos = 0) const {
342 return view_.find_first_not_of(s, pos);
343 }
344
345 constexpr size_type find_last_not_of(buffer const& buf, size_type pos = npos) const noexcept {
346 return view_.find_last_not_of(buf.view_, pos);
347 }
348 constexpr size_type find_last_not_of( string_view v, size_type pos = npos) const noexcept {
349 return view_.find_last_not_of(v, pos);
350 }
351 constexpr size_type find_last_not_of(char ch, size_type pos = npos) const noexcept {
352 return view_.find_last_not_of(ch, pos);
353 }
354 constexpr size_type find_last_not_of(char const* s, size_type pos, size_type count) const {
355 return view_.find_last_not_of(s, pos, count);
356 }
357 constexpr size_type find_last_not_of(char const* s, size_type pos = npos) const {
358 return view_.find_last_not_of(s, pos);
359 }
360
361 any const& get_life() const {
362 return life_;
363 }
364
365 operator as::const_buffer() const {
366 return as::buffer(view_.data(), view_.size());
367 }
368
369 operator string_view() const {
370 return view_;
371 }
372
373 friend
374 constexpr bool operator==(buffer const& lhs, buffer const& rhs ) noexcept {
375 return lhs.view_ == rhs.view_;
376 }
377 friend
378 constexpr bool operator!=(buffer const& lhs, buffer const& rhs ) noexcept {
379 return lhs.view_ != rhs.view_;
380 }
381 friend
382 constexpr bool operator<(buffer const& lhs, buffer const& rhs ) noexcept {
383 return lhs.view_ < rhs.view_;
384 }
385 friend
386 constexpr bool operator<=(buffer const& lhs, buffer const& rhs ) noexcept {
387 return lhs.view_ <= rhs.view_;
388 }
389 friend
390 constexpr bool operator>(buffer const& lhs, buffer const& rhs ) noexcept {
391 return lhs.view_ > rhs.view_;
392 }
393 friend
394 constexpr bool operator>=(buffer const& lhs, buffer const& rhs ) noexcept {
395 return lhs.view_ >= rhs.view_;
396 }
397
398 friend
399 std::ostream& operator<<(std::ostream& o, buffer const& buf) {
400 o << buf.view_;
401 return o;
402 }
403private:
404 string_view view_;
405 any life_;
406};
407
408inline std::size_t hash_value(buffer const& v) noexcept {
409 std::size_t result = 0;
410 boost::hash_combine(result, static_cast<string_view const&>(v));
411 return result;
412}
413
414inline namespace literals {
415
428inline buffer operator""_mb(char const* str, std::size_t length) {
429 return buffer(str, length);
430}
431
432} // namespace literals
433
444template <typename Iterator>
445inline buffer allocate_buffer(Iterator b, Iterator e) {
446 auto size = static_cast<std::size_t>(std::distance(b, e));
447 if (size == 0) return buffer(&*b, size);
448 auto spa = make_shared_ptr_array(size);
449 std::copy(b, e, spa.get());
450 auto p = spa.get();
451 return buffer(p, size, force_move(spa));
452}
453
463inline buffer allocate_buffer(string_view sv) {
464 return allocate_buffer(sv.begin(), sv.end());
465}
466
467inline buffer const* buffer_sequence_begin(buffer const& buf) {
468 return std::addressof(buf);
469}
470
471inline buffer const* buffer_sequence_end(buffer const& buf) {
472 return std::addressof(buf) + 1;
473}
474
475template <typename Col>
476inline typename Col::const_iterator buffer_sequence_begin(Col const& col) {
477 return col.cbegin();
478}
479
480template <typename Col>
481inline typename Col::const_iterator buffer_sequence_end(Col const& col) {
482 return col.cend();
483}
484
485namespace detail {
486
487template <typename>
488char buffer_sequence_begin_helper(...);
489
490template <typename T>
491char (&buffer_sequence_begin_helper(
492 T* t,
493 typename std::enable_if<
494 !std::is_same<
495 decltype(buffer_sequence_begin(*t)),
496 void
497 >::value
498 >::type*)
499)[2];
500
501template <typename>
502char buffer_sequence_end_helper(...);
503
504template <typename T>
505char (&buffer_sequence_end_helper(
506 T* t,
507 typename std::enable_if<
508 !std::is_same<
509 decltype(buffer_sequence_end(*t)),
510 void
511 >::value
512 >::type*)
513)[2];
514
515template <typename, typename>
516char (&buffer_sequence_element_type_helper(...))[2];
517
518template <typename T, typename Buffer>
519char buffer_sequence_element_type_helper(
520 T* t,
521 typename std::enable_if<
522 std::is_convertible<
523 decltype(*buffer_sequence_begin(*t)),
524 Buffer
525 >::value
526 >::type*
527);
528
529template <typename T, typename Buffer>
530struct is_buffer_sequence_class
531 : std::integral_constant<bool,
532 sizeof(buffer_sequence_begin_helper<T>(0, 0)) != 1 &&
533 sizeof(buffer_sequence_end_helper<T>(0, 0)) != 1 &&
534 sizeof(buffer_sequence_element_type_helper<T, Buffer>(0, 0)) == 1>
535{
536};
537
538} // namespace detail
539
540template <typename T>
541struct is_buffer_sequence :
542 std::conditional<
543 std::is_class<T>::value,
544 detail::is_buffer_sequence_class<T, buffer>,
545 std::false_type
546 >::type
547{
548};
549
550template <>
551struct is_buffer_sequence<buffer> : std::true_type
552{
553};
554
555} // namespace async_mqtt
556
557namespace boost {
558namespace asio {
559
569inline const_buffer buffer(async_mqtt::buffer const& data) {
570 return buffer(data.data(), data.size());
571}
572
573} // namespace asio
574} // namespace boost
575
576namespace std {
577
578template <>
579class hash<async_mqtt::buffer> {
580public:
581 std::uint64_t operator()(async_mqtt::buffer const& v) const noexcept {
582 return std::hash<std::string_view>()(static_cast<std::string_view const&>(v));
583 }
584};
585
586} // namespace std
587
588#endif // ASYNC_MQTT_BUFFER_HPP
buffer that has string_view interface This class provides string_view interface. This class hold stri...
Definition buffer.hpp:30
constexpr buffer(string_view sv)
string_view constructor
Definition buffer.hpp:73
buffer substr(size_type pos=0, size_type count=npos) const &
get substring The returned buffer ragnge is the same as string_view::substr(). In addition the lifeti...
Definition buffer.hpp:201
buffer(std::string)=delete
string constructor (deleted)
buffer substr(size_type pos=0, size_type count=npos) &&
get substring The returned buffer ragnge is the same as string_view::substr(). In addition the lifeti...
Definition buffer.hpp:214
buffer(string_view sv, any life)
string_view and lifetime constructor
Definition buffer.hpp:91