MongoDB C++ Driver mongocxx-3.10.1
Loading...
Searching...
No Matches
string_view.hpp
1// Copyright 2023 MongoDB Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#pragma once
16
17#include <bsoncxx/config/prelude.hpp>
18
19#if defined(BSONCXX_POLY_USE_MNMLSTC)
20
21#include <core/string.hpp>
22
23namespace bsoncxx {
24namespace v_noabi {
25namespace stdx {
26
27using ::core::basic_string_view;
28using ::core::string_view;
29
30} // namespace stdx
31} // namespace v_noabi
32} // namespace bsoncxx
33
34#elif defined(BSONCXX_POLY_USE_BOOST)
35
36#include <boost/version.hpp>
37
38#if BOOST_VERSION >= 106100
39
40#include <boost/utility/string_view.hpp>
41
42namespace bsoncxx {
43namespace v_noabi {
44namespace stdx {
45
46using ::boost::basic_string_view;
47using ::boost::string_view;
48
49} // namespace stdx
50} // namespace v_noabi
51} // namespace bsoncxx
52
53#else
54
55#include <boost/utility/string_ref.hpp>
56
57namespace bsoncxx {
58namespace v_noabi {
59namespace stdx {
60
61template <typename charT, typename traits = std::char_traits<charT>>
62using basic_string_view = ::boost::basic_string_ref<charT, traits>;
63using string_view = ::boost::string_ref;
64
65} // namespace stdx
66} // namespace v_noabi
67} // namespace bsoncxx
68
69#endif
70
71#elif defined(BSONCXX_POLY_USE_STD_EXPERIMENTAL)
72
73#include <experimental/string_view>
74
75namespace bsoncxx {
76namespace v_noabi {
77namespace stdx {
78
79using ::std::experimental::basic_string_view;
80using ::std::experimental::string_view;
81
82} // namespace stdx
83} // namespace v_noabi
84} // namespace bsoncxx
85
86#elif defined(BSONCXX_POLY_USE_STD)
87
88#include <string_view>
89
90namespace bsoncxx {
91namespace v_noabi {
92namespace stdx {
93
94using ::std::basic_string_view;
95using ::std::string_view;
96
97} // namespace stdx
98} // namespace v_noabi
99} // namespace bsoncxx
100
101#elif defined(BSONCXX_POLY_USE_IMPLS)
102
103#include <algorithm>
104#include <cstddef>
105#include <ios>
106#include <limits>
107#include <stdexcept>
108#include <string>
109#include <utility>
110
111#include <bsoncxx/stdx/operators.hpp>
112#include <bsoncxx/stdx/type_traits.hpp>
113
114namespace bsoncxx {
115namespace v_noabi {
116namespace stdx {
117
121template <typename Char, typename Traits = std::char_traits<Char>>
122class basic_string_view : bsoncxx::detail::equality_operators, bsoncxx::detail::ordering_operators {
123 public:
124 // Pointer to (non-const) character type
125 using pointer = Char*;
126 // Pointer to const-character type
127 using const_pointer = const Char*;
128 // Type representing the size of a string
129 using size_type = std::size_t;
130 // Type representing the offset within a string
131 using difference_type = std::ptrdiff_t;
132 // The type of the string character
133 using value_type = Char;
134
135 // Constant sentinel value to represent an impossible/invalid string position
136 static constexpr size_type npos = static_cast<size_type>(-1);
137
138 private:
139 // Pointer to the beginning of the string being viewed
140 const_pointer _begin = nullptr;
141 // The size of the array that is being viewed via `_begin`
142 size_type _size = 0;
143
144 public:
145 using traits_type = Traits;
146 using reference = Char&;
147 using const_reference = const Char&;
148 using const_iterator = const_pointer;
149 using iterator = const_iterator;
150 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
151 using reverse_iterator = const_reverse_iterator;
152
156 constexpr basic_string_view() noexcept = default;
157 constexpr basic_string_view(const basic_string_view&) noexcept = default;
158 bsoncxx_cxx14_constexpr basic_string_view& operator=(const basic_string_view&) noexcept =
159 default;
160
165 constexpr basic_string_view(const_pointer s, size_type count) : _begin(s), _size(count) {}
166
172 constexpr basic_string_view(const_pointer s) : _begin(s), _size(traits_type::length(s)) {}
173
180 template <typename Alloc>
181 constexpr basic_string_view(
182 const std::basic_string<value_type, traits_type, Alloc>& str) noexcept
183 : _begin(str.data()), _size(str.size()) {}
184
185#if __cpp_lib_string_view
186 constexpr basic_string_view(std::basic_string_view<value_type, traits_type> sv) noexcept
187 : _begin(sv.data()), _size(sv.size()) {}
188#endif
189
190 // Construction from a null pointer is deleted
191 basic_string_view(std::nullptr_t) = delete;
192
193 constexpr const_iterator begin() const noexcept {
194 return const_iterator(_begin);
195 }
196 constexpr const_iterator end() const noexcept {
197 return begin() + size();
198 }
199 constexpr const_iterator cbegin() const noexcept {
200 return begin();
201 }
202 constexpr const_iterator cend() const noexcept {
203 return end();
204 }
205
206 constexpr const_reverse_iterator rbegin() const noexcept {
207 return const_reverse_iterator{end()};
208 }
209
210 constexpr const_reverse_iterator rend() const noexcept {
211 return const_reverse_iterator{begin()};
212 }
213
214 constexpr const_reverse_iterator crbegin() const noexcept {
215 return const_reverse_iterator{cend()};
216 }
217
218 constexpr const_reverse_iterator crend() const noexcept {
219 return const_reverse_iterator{crbegin()};
220 }
221
228 constexpr const_reference operator[](size_type offset) const {
229 return _begin[offset];
230 }
231
238 bsoncxx_cxx14_constexpr const_reference at(size_type pos) const {
239 if (pos >= size()) {
240 throw std::out_of_range{"bsoncxx::stdx::basic_string_view::at()"};
241 }
242 return _begin[pos];
243 }
245 constexpr const_reference front() const {
246 return (*this)[0];
247 }
249 constexpr const_reference back() const {
250 return (*this)[size() - 1];
251 }
252
254 constexpr const_pointer data() const noexcept {
255 return _begin;
256 }
258 constexpr size_type size() const noexcept {
259 return _size;
260 }
262 constexpr size_type length() const noexcept {
263 return size();
264 }
266 constexpr bool empty() const noexcept {
267 return size() == 0;
268 }
270 constexpr size_type max_size() const noexcept {
271 return static_cast<size_type>(std::numeric_limits<difference_type>::max());
272 }
273
279 bsoncxx_cxx14_constexpr void remove_prefix(size_type n) {
280 _begin += n;
281 _size -= n;
282 }
283
289 bsoncxx_cxx14_constexpr void remove_suffix(size_type n) {
290 _size -= n;
291 }
292
296 bsoncxx_cxx14_constexpr void swap(basic_string_view& other) {
297 std::swap(_begin, other._begin);
298 std::swap(_size, other._size);
299 }
300
312 size_type copy(pointer dest, size_type count, size_type pos = 0) const {
313 if (pos > size()) {
314 throw std::out_of_range{"bsoncxx::stdx::basic_string_view::substr()"};
315 }
316 count = (std::min)(count, size() - pos);
317 Traits::copy(dest, data() + pos, count);
318 return count;
319 }
320
330 bsoncxx_cxx14_constexpr basic_string_view substr(size_type pos = 0,
331 size_type count = npos) const {
332 if (pos > size()) {
333 throw std::out_of_range{"bsoncxx::stdx::basic_string_view::substr()"};
334 }
335 return basic_string_view(_begin + pos, (std::min)(count, size() - pos));
336 }
337
346 constexpr int compare(basic_string_view other) const noexcept {
347 // Another level of indirection to support restricted C++11 constexpr
348 return _compare2(Traits::compare(data(), other.data(), (std::min)(size(), other.size())),
349 other);
350 }
351
357 constexpr int compare(const_pointer cstr) const {
358 return compare(basic_string_view(cstr));
359 }
360
366 constexpr int compare(size_type pos1, size_type count1, basic_string_view other) const {
367 return substr(pos1, count1).compare(other);
368 }
369
375 constexpr int compare(size_type pos1, size_type count1, const_pointer cstr) const {
376 return compare(pos1, count1, basic_string_view(cstr));
377 }
378
384 constexpr int compare(size_type pos1,
385 size_type count1,
386 basic_string_view other,
387 size_type pos2,
388 size_type count2) const {
389 return substr(pos1, count1).compare(other.substr(pos2, count2));
390 }
391
397 constexpr int compare(size_type pos1,
398 size_type count1,
399 const_pointer str,
400 size_type count2) const {
401 return substr(pos1, count1).compare(basic_string_view(str, count2));
402 }
403
408 bsoncxx_cxx14_constexpr size_type find(basic_string_view infix, size_type pos = 0) const
409 noexcept {
410 if (pos > size()) {
411 return npos;
412 }
413 basic_string_view sub = this->substr(pos);
414 if (infix.empty()) {
415 // The empty string is always "present" at the beginning of any string
416 return pos;
417 }
418 const_iterator found = std::search(sub.begin(), sub.end(), infix.begin(), infix.end());
419 if (found == sub.end()) {
420 return npos;
421 }
422 return static_cast<size_type>(found - begin());
423 }
424
429 bsoncxx_cxx14_constexpr size_type rfind(basic_string_view infix, size_type pos = npos) const
430 noexcept {
431 // Calc the endpos where searching should begin, which includes the infix size
432 const size_type substr_size = pos != npos ? pos + infix.size() : pos;
433 if (infix.empty()) {
434 return (std::min)(pos, size());
435 }
436 basic_string_view searched = this->substr(0, substr_size);
437 auto f = std::search(searched.rbegin(), searched.rend(), infix.rbegin(), infix.rend());
438 if (f == searched.rend()) {
439 return npos;
440 }
441 return static_cast<size_type>(rend() - f) - infix.size();
442 }
443
448 constexpr size_type find_first_of(basic_string_view set, size_type pos = 0) const noexcept {
449 return _find_if(pos, [&](value_type chr) { return set.find(chr) != npos; });
450 }
451
456 constexpr size_type find_last_of(basic_string_view set, size_type pos = npos) const noexcept {
457 return _rfind_if(pos, [&](value_type chr) { return set.find(chr) != npos; });
458 }
459
464 constexpr size_type find_first_not_of(basic_string_view set, size_type pos = 0) const noexcept {
465 return _find_if(pos, [&](value_type chr) { return set.find(chr) == npos; });
466 }
467
472 constexpr size_type find_last_not_of(basic_string_view set, size_type pos = npos) const
473 noexcept {
474 return _rfind_if(pos, [&](value_type chr) { return set.find(chr) == npos; });
475 }
476
477#pragma push_macro("DECL_FINDERS")
478#undef DECL_FINDERS
479#define DECL_FINDERS(Name, DefaultPos) \
480 constexpr size_type Name(value_type chr, size_type pos = DefaultPos) const noexcept { \
481 return Name(basic_string_view(&chr, 1), pos); \
482 } \
483 constexpr size_type Name(const_pointer cstr, size_type pos, size_type count) const { \
484 return Name(basic_string_view(cstr, count), pos); \
485 } \
486 constexpr size_type Name(const_pointer cstr, size_type pos = DefaultPos) const { \
487 return Name(basic_string_view(cstr), pos); \
488 } \
489 BSONCXX_FORCE_SEMICOLON
490 DECL_FINDERS(find, 0);
491 DECL_FINDERS(rfind, npos);
492 DECL_FINDERS(find_first_of, 0);
493 DECL_FINDERS(find_last_of, npos);
494 DECL_FINDERS(find_first_not_of, 0);
495 DECL_FINDERS(find_last_not_of, npos);
496#pragma pop_macro("DECL_FINDERS")
497
501 template <typename Allocator>
502 explicit operator std::basic_string<Char, Traits, Allocator>() const {
503 return std::basic_string<Char, Traits, Allocator>(data(), size());
504 }
505
506#if __cpp_lib_string_view
507 explicit operator std::basic_string_view<value_type, traits_type>() const noexcept {
508 return std::basic_string_view<value_type, traits_type>(data(), size());
509 }
510#endif
511
512 private:
513 // Additional level-of-indirection for constexpr compare()
514 constexpr int _compare2(int diff, basic_string_view other) const noexcept {
515 // "diff" is the diff according to Traits::cmp
516 return diff ? diff : static_cast<int>(size() - other.size());
517 }
518
519 // Implementation of equality comparison
520 constexpr friend bool tag_invoke(bsoncxx::detail::equal_to,
521 basic_string_view left,
522 basic_string_view right) noexcept {
523 return left.size() == right.size() && left.compare(right) == 0;
524 }
525
526 // Implementation of a three-way-comparison
527 constexpr friend bsoncxx::detail::strong_ordering tag_invoke(
528 bsoncxx::detail::compare_three_way cmp,
529 basic_string_view left,
530 basic_string_view right) noexcept {
531 return cmp(left.compare(right), 0);
532 }
533
534 friend std::basic_ostream<Char, Traits>& operator<<(std::basic_ostream<Char, Traits>& out,
535 basic_string_view self) {
536 out << std::basic_string<Char, Traits>(self);
537 return out;
538 }
539
540 // Find the first in-bounds index I in [pos, size()) where the given predicate
541 // returns true for substr(I). If no index exists, returns npos
542 template <typename F>
543 bsoncxx_cxx14_constexpr size_type _find_if(size_type pos, F pred) const noexcept {
544 const auto sub = substr(pos);
545 const iterator found = std::find_if(sub.begin(), sub.end(), pred);
546 if (found == end()) {
547 return npos;
548 }
549 return static_cast<size_type>(found - begin());
550 }
551
552 // Find the LAST index I in [0, pos] where the given predicate returns true for
553 // substr(0, I). If no such index exists, returns npos.
554 template <typename F>
555 bsoncxx_cxx14_constexpr size_type _rfind_if(size_type pos, F pred) const noexcept {
556 // Adjust 'pos' for an inclusive range in substr()
557 const auto rpos = pos == npos ? npos : pos + 1;
558 // The substring that will be searched:
559 const auto prefix = substr(0, rpos);
560 const const_reverse_iterator found = std::find_if(prefix.rbegin(), prefix.rend(), pred);
561 if (found == rend()) {
562 return npos;
563 }
564 // Adjust by 1 to account for reversed-ness
565 return static_cast<size_type>(rend() - found) - 1u;
566 }
567};
568
569// Required to define this here for C++≤14 compatibility. Can be removed in C++≥17
570template <typename C, typename Tr>
571const std::size_t basic_string_view<C, Tr>::npos;
572
573using string_view = basic_string_view<char>;
574
575} // namespace stdx
576} // namespace v_noabi
577} // namespace bsoncxx
578
579namespace std {
580
581template <typename CharT, typename Traits>
582struct hash<bsoncxx::v_noabi::stdx::basic_string_view<CharT, Traits>>
583 : private std::hash<std::basic_string<CharT, Traits>> {
584 std::size_t operator()(
585 const bsoncxx::v_noabi::stdx::basic_string_view<CharT, Traits>& str) const {
586 return std::hash<std::basic_string<CharT, Traits>>::operator()(
587 std::basic_string<CharT, Traits>(str.data(), str.size()));
588 }
589};
590
591} // namespace std
592
593#else
594#error "Cannot find a valid polyfill for string_view"
595#endif
596
597#include <bsoncxx/config/postlude.hpp>
598
599namespace bsoncxx {
600namespace stdx {
601
602using ::bsoncxx::v_noabi::stdx::basic_string_view;
603using ::bsoncxx::v_noabi::stdx::string_view;
604
605} // namespace stdx
606} // namespace bsoncxx
The top-level namespace for bsoncxx library entities.
Definition element-fwd.hpp:19