Version 5.4.3.2, tag libreoffice-5.4.3.2
[LibreOffice.git] / include / o3tl / string_view.hxx
blobae284b20173d748885e7e8c534096c5564bc8baf
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
10 #ifndef INCLUDED_O3TL_STRING_VIEW_HXX
11 #define INCLUDED_O3TL_STRING_VIEW_HXX
13 #include <sal/config.h>
15 #include <algorithm>
16 #include <cstddef>
17 #include <ios>
18 #include <iterator>
19 #include <ostream>
20 #include <stdexcept>
21 #include <string>
22 #include <type_traits>
23 #include <utility>
25 #include <config_global.h>
26 #include <rtl/string.hxx>
27 #include <rtl/ustring.hxx>
28 #include <sal/types.h>
30 // An approximation of C++17 <string_view>, including implicit conversion
31 // from rtl::OString and rtl::OUString.
33 namespace o3tl {
35 namespace detail {
37 template<typename T> struct CharPtrDetector {
38 static constexpr bool ok = false;
41 template<> struct CharPtrDetector<char *> {
42 static constexpr bool ok = true;
45 template<> struct CharPtrDetector<char const *> {
46 static constexpr bool ok = true;
49 template<typename T> struct NonConstCharArrayDetector {
50 static constexpr bool ok = false;
53 template<std::size_t N> struct NonConstCharArrayDetector<char [N]> {
54 static constexpr bool ok = true;
57 template<typename T> struct ConstCharArrayDetector {
58 static constexpr bool ok = false;
61 template<std::size_t N> struct ConstCharArrayDetector<char const[N]> {
62 static constexpr bool ok = true;
63 static constexpr std::size_t length = N - 1;
66 template<typename T> struct Char16PtrDetector {
67 static constexpr bool ok = false;
70 template<> struct Char16PtrDetector<char16_t *> {
71 static constexpr bool ok = true;
74 template<> struct Char16PtrDetector<char16_t const *> {
75 static constexpr bool ok = true;
78 template<typename T> struct NonConstChar16ArrayDetector {
79 static constexpr bool ok = false;
82 template<std::size_t N> struct NonConstChar16ArrayDetector<char16_t [N]> {
83 static constexpr bool ok = true;
86 template<typename T> struct ConstChar16ArrayDetector {
87 static constexpr bool ok = false;
90 template<std::size_t N> struct ConstChar16ArrayDetector<char16_t const[N]> {
91 static constexpr bool ok = true;
92 static constexpr std::size_t length = N - 1;
95 template<typename T> struct Char32PtrDetector {
96 static constexpr bool ok = false;
99 template<> struct Char32PtrDetector<char32_t *> {
100 static constexpr bool ok = true;
103 template<> struct Char32PtrDetector<char32_t const *> {
104 static constexpr bool ok = true;
107 template<typename T> struct NonConstChar32ArrayDetector {
108 static constexpr bool ok = false;
111 template<std::size_t N> struct NonConstChar32ArrayDetector<char32_t [N]> {
112 static constexpr bool ok = true;
115 template<typename T> struct ConstChar32ArrayDetector {
116 static constexpr bool ok = false;
119 template<std::size_t N> struct ConstChar32ArrayDetector<char32_t const[N]> {
120 static constexpr bool ok = true;
121 static constexpr std::size_t length = N - 1;
124 template<typename T> struct WcharPtrDetector {
125 static constexpr bool ok = false;
128 template<> struct WcharPtrDetector<wchar_t *> {
129 static constexpr bool ok = true;
132 template<> struct WcharPtrDetector<wchar_t const *> {
133 static constexpr bool ok = true;
136 template<typename T> struct NonConstWcharArrayDetector {
137 static constexpr bool ok = false;
140 template<std::size_t N> struct NonConstWcharArrayDetector<wchar_t [N]> {
141 static constexpr bool ok = true;
144 template<typename T> struct ConstWcharArrayDetector {
145 static constexpr bool ok = false;
148 template<std::size_t N> struct ConstWcharArrayDetector<wchar_t const[N]> {
149 static constexpr bool ok = true;
150 static constexpr std::size_t length = N - 1;
155 #if defined _MSC_VER
156 #pragma warning(push, 1)
157 #pragma warning(disable: 4814) // in C++14 'constexpr' will not imply 'const'
158 #endif
160 template<typename charT, typename traits = std::char_traits<charT>>
161 class basic_string_view {
162 public:
163 using traits_type = traits;
164 using value_type = charT;
165 using pointer = value_type *;
166 using const_pointer = value_type const *;
167 using reference = value_type &;
168 using const_reference = value_type const &;
169 using const_iterator = const_pointer;
170 using iterator = const_iterator;
171 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
172 using reverse_iterator = const_reverse_iterator;
173 using size_type = std::size_t;
174 using difference_type = std::ptrdiff_t;
176 static constexpr size_type npos = size_type(-1);
178 constexpr basic_string_view() noexcept: data_(nullptr), size_(0) {}
180 constexpr basic_string_view(basic_string_view const &) noexcept = default;
182 #if HAVE_CXX14_CONSTEXPR
183 constexpr
184 #endif
185 basic_string_view & operator =(basic_string_view const & other) noexcept
186 #if defined _MSC_VER && _MSC_VER <= 1900 && !defined __clang__
188 data_ = other.data_;
189 size_ = other.size_;
190 return *this;
192 #else
193 = default;
194 #endif
196 // The various character types are handled below in the "LO specifics, to
197 // make up for traits::length not necessarily being constexpr yet for
198 // literal arguments" section:
199 template<typename T = charT> constexpr basic_string_view(
200 charT const * str,
201 typename std::enable_if<
202 !(std::is_same<T, char>::value || std::is_same<T, char16_t>::value
203 || std::is_same<T, char32_t>::value
204 || std::is_same<T, wchar_t>::value),
205 rtl::libreoffice_internal::Dummy>::type = {}):
206 data_(str), size_(traits::length(str)) {}
208 constexpr basic_string_view(charT const * str, size_type len):
209 data_(str), size_(len) {}
211 constexpr const_iterator begin() const noexcept { return data_; }
213 constexpr const_iterator end() const noexcept { return begin() + size(); }
215 constexpr const_iterator cbegin() const noexcept { return begin(); }
217 constexpr const_iterator cend() const noexcept { return end(); }
219 constexpr const_reverse_iterator rbegin() const noexcept
220 { return const_reverse_iterator(end()); }
222 constexpr const_reverse_iterator rend() const noexcept
223 { return const_reverse_iterator(begin()); }
225 constexpr const_reverse_iterator crbegin() const noexcept
226 { return rbegin(); }
228 constexpr const_reverse_iterator crend() const noexcept { return rend(); }
230 constexpr size_type size() const noexcept { return size_; }
232 constexpr size_type length() const noexcept { return size(); }
234 #if !defined __clang__ || HAVE_CXX14_CONSTEXPR
235 constexpr
236 #endif
237 size_type max_size() const noexcept {
238 #if defined __clang__ // avoid constexpr issues with other, older compilers
239 (void) this; // loplugin:staticmethods
240 #endif
241 return npos - 1;
244 constexpr bool empty() const noexcept { return size_ == 0; }
246 constexpr const_reference operator [](size_type pos) const {
247 #if HAVE_CXX14_CONSTEXPR
248 assert(pos < size());
249 #endif
250 return data_[pos];
253 #if HAVE_CXX14_CONSTEXPR
254 constexpr
255 #endif
256 const_reference at(size_type pos) const {
257 if (pos >= size()) {
258 throw std::out_of_range("o3tl::basic_string_view::at");
260 return operator [](pos);
263 constexpr const_reference front() const {
264 #if HAVE_CXX14_CONSTEXPR
265 assert(!empty());
266 #endif
267 return operator [](0);
270 constexpr const_reference back() const {
271 #if HAVE_CXX14_CONSTEXPR
272 assert(!empty());
273 #endif
274 return operator [](size() - 1);
277 constexpr const_pointer data() const noexcept { return data_; }
279 #if HAVE_CXX14_CONSTEXPR
280 constexpr
281 #endif
282 void remove_prefix(size_type n) {
283 assert(n <= size());
284 data_ += n;
285 size_ -= n;
288 #if HAVE_CXX14_CONSTEXPR
289 constexpr
290 #endif
291 void remove_suffix(size_type n) {
292 assert(n <= size());
293 size_ -= n;
296 #if HAVE_CXX14_CONSTEXPR
297 constexpr
298 #endif
299 void swap(basic_string_view & s) noexcept {
300 std::swap(data_, s.data_);
301 std::swap(size_, s.size_);
304 size_type copy(charT * s, size_type n, size_type pos = 0) const {
305 if (pos > size()) {
306 throw std::out_of_range("o3tl::basic_string_view::copy");
308 auto rlen = std::min(n, size_type(size() - pos));
309 traits::copy(s, data() + pos, rlen);
310 return rlen;
313 #if HAVE_CXX14_CONSTEXPR
314 constexpr
315 #endif
316 basic_string_view substr(size_type pos = 0, size_type n = npos) const {
317 if (pos > size()) {
318 throw std::out_of_range("o3tl::basic_string_view::copy");
320 return basic_string_view(
321 data() + pos, std::min(n, size_type(size() - pos)));
324 #if HAVE_CXX14_CONSTEXPR
325 constexpr
326 #endif
327 int compare(basic_string_view s) const noexcept {
328 auto n = traits::compare(data(), s.data(), std::min(size(), s.size()));
329 return n == 0
330 ? (size() < s.size() ? -1 : size() == s.size() ? 0 : 1) : n;
333 constexpr int compare(size_type pos1, size_type n1, basic_string_view s)
334 const
335 { return substr(pos1, n1).compare(s); }
337 constexpr int compare(
338 size_type pos1, size_type n1, basic_string_view s, size_type pos2,
339 size_type n2) const
340 { return substr(pos1, n1).compare(s.substr(pos2, n2)); }
342 constexpr int compare(charT const * s) const
343 { return compare(basic_string_view(s)); }
345 constexpr int compare(size_type pos1, size_type n1, charT const * s) const
346 { return substr(pos1, n1).compare(s); }
348 constexpr int compare(
349 size_type pos1, size_type n1, charT const * s, size_type n2) const
350 { return substr(pos1, n1).compare(basic_string_view(s, n2)); }
352 #if HAVE_CXX14_CONSTEXPR
353 constexpr
354 #endif
355 size_type find(basic_string_view s, size_type pos = 0) const noexcept {
356 if (s.size() <= size()) {
357 for (auto xpos = pos; xpos <= size() - s.size(); ++xpos) {
358 bool match = true;
359 for (size_type i = 0; i != s.size(); ++i) {
360 if (!traits::eq(data_[xpos + i], s.data_[i])) {
361 match = false;
362 break;
365 if (match) {
366 return xpos;
370 return npos;
373 constexpr size_type find(charT c, size_type pos = 0) const noexcept
374 { return find(basic_string_view(&c, 1), pos); }
376 constexpr size_type find(charT const * s, size_type pos, size_type n) const
377 { return find(basic_string_view(s, n), pos); }
379 constexpr size_type find(charT const * s, size_type pos = 0) const
380 { return find(basic_string_view(s), pos); }
382 #if HAVE_CXX14_CONSTEXPR
383 constexpr
384 #endif
385 size_type rfind(basic_string_view s, size_type pos = npos) const noexcept {
386 if (s.size() <= size()) {
387 for (auto xpos = std::min<size_type>(size() - s.size(), pos);;
388 --xpos)
390 bool match = true;
391 for (size_type i = 0; i != s.size(); ++i) {
392 if (!traits::eq(data_[xpos + i], s.data_[i])) {
393 match = false;
394 break;
397 if (match) {
398 return xpos;
400 if (xpos == 0) {
401 break;
405 return npos;
408 constexpr size_type rfind(charT c, size_type pos = npos) const noexcept
409 { return rfind(basic_string_view(&c, 1), pos); }
411 constexpr size_type rfind(charT const * s, size_type pos, size_type n) const
412 { return rfind(basic_string_view(s, n), pos); }
414 constexpr size_type rfind(charT const * s, size_type pos = npos) const
415 { return rfind(basic_string_view(s), pos); }
417 #if HAVE_CXX14_CONSTEXPR
418 constexpr
419 #endif
420 size_type find_first_of(basic_string_view s, size_type pos = 0) const
421 noexcept
423 for (auto xpos = pos; xpos < size(); ++xpos) {
424 for (size_type i = 0; i != s.size(); ++i) {
425 if (traits::eq(data_[xpos], s.data_[i])) {
426 return xpos;
430 return npos;
433 constexpr size_type find_first_of(charT c, size_type pos = 0) const noexcept
434 { return find_first_of(basic_string_view(&c, 1), pos); }
436 constexpr size_type find_first_of(
437 charT const * s, size_type pos, size_type n) const
438 { return find_first_of(basic_string_view(s, n), pos); }
440 constexpr size_type find_first_of(charT const * s, size_type pos = 0) const
441 { return find_first_of(basic_string_view(s), pos); }
443 #if HAVE_CXX14_CONSTEXPR
444 constexpr
445 #endif
446 size_type find_last_of(basic_string_view s, size_type pos = npos) const
447 noexcept
449 if (!empty()) {
450 for (auto xpos = std::min<size_type>(size() - 1, pos);; --xpos) {
451 for (size_type i = 0; i != s.size(); ++i) {
452 if (traits::eq(data_[xpos], s.data_[i])) {
453 return xpos;
456 if (xpos == 0) {
457 break;
461 return npos;
464 constexpr size_type find_last_of(charT c, size_type pos = npos) const
465 noexcept
466 { return find_last_of(basic_string_view(&c, 1), pos); }
468 constexpr size_type find_last_of(
469 charT const * s, size_type pos, size_type n) const
470 { return find_last_of(basic_string_view(s, n), pos); }
472 constexpr size_type find_last_of(charT const * s, size_type pos = npos)
473 const
474 { return find_last_of(basic_string_view(s), pos); }
476 #if HAVE_CXX14_CONSTEXPR
477 constexpr
478 #endif
479 size_type find_first_not_of(basic_string_view s, size_type pos = 0) const
480 noexcept
482 for (auto xpos = pos; xpos < size(); ++xpos) {
483 bool match = true;
484 for (size_type i = 0; i != s.size(); ++i) {
485 if (traits::eq(data_[xpos], s.data_[i])) {
486 match = false;
487 break;
490 if (match) {
491 return xpos;
494 return npos;
497 constexpr size_type find_first_not_of(charT c, size_type pos = 0) const
498 noexcept
499 { return find_first_not_of(basic_string_view(&c, 1), pos); }
501 constexpr size_type find_first_not_of(
502 charT const * s, size_type pos, size_type n) const
503 { return find_first_not_of(basic_string_view(s, n), pos); }
505 constexpr size_type find_first_not_of(charT const * s, size_type pos = 0)
506 const
507 { return find_first_not_of(basic_string_view(s), pos); }
509 #if HAVE_CXX14_CONSTEXPR
510 constexpr
511 #endif
512 size_type find_last_not_of(basic_string_view s, size_type pos = npos) const
513 noexcept
515 if (!empty()) {
516 for (auto xpos = std::min<size_type>(size() - 1, pos);; --xpos) {
517 bool match = true;
518 for (size_type i = 0; i != s.size(); ++i) {
519 if (traits::eq(data_[xpos], s.data_[i])) {
520 match = false;
521 break;
524 if (match) {
525 return xpos;
527 if (xpos == 0) {
528 break;
532 return npos;
535 constexpr size_type find_last_not_of(charT c, size_type pos = npos) const
536 noexcept
537 { return find_last_not_of(basic_string_view(&c, 1), pos); }
539 constexpr size_type find_last_not_of(
540 charT const * s, size_type pos, size_type n) const
541 { return find_last_not_of(basic_string_view(s, n), pos); }
543 constexpr size_type find_last_not_of(charT const * s, size_type pos = npos)
544 const
545 { return find_last_not_of(basic_string_view(s), pos); }
547 // LO specifics:
549 // For std::basic_string_view, this is provided via a non-explicit
550 // conversion operator from std::basic_string:
551 constexpr basic_string_view(std::basic_string<charT, traits> const & s):
552 data_(s.data()), size_(s.size()) {}
554 // For std::string_view, this will be provided by a (LIBO_INTERNAL_ONLY)
555 // non-explicit conversion operator from rtl::OString:
556 template<typename T = charT> basic_string_view(
557 OString const & s,
558 typename std::enable_if<
559 std::is_same<T, char>::value,
560 rtl::libreoffice_internal::Dummy>::type = {}):
561 data_(s.getStr()), size_(s.getLength()) {}
563 // For std::u16string_view, this will be provided by a (LIBO_INTERNAL_ONLY)
564 // non-explicit conversion operator from rtl::OUString:
565 template<typename T = charT> basic_string_view(
566 OUString const & s,
567 typename std::enable_if<
568 std::is_same<T, sal_Unicode>::value,
569 rtl::libreoffice_internal::Dummy>::type = {}):
570 data_(s.getStr()), size_(s.getLength()) {}
572 // For std::u16string_view, this would either be provided by a
573 // (LIBO_INTERNAL_ONLY) non-explicit conversion operator from
574 // rtl::OUStringLiteral, or rtl::OUStringLiteral would be given up in favor
575 // of std::u16string_view anyway (but this constructor also serves to reject
576 // as ambiguous construction of a o3tl::u16string_view from a narrow string
577 // literal, which would otherwise go via the above rtl::OUString
578 // constructor):
579 template<typename T = charT> constexpr basic_string_view(
580 OUStringLiteral literal,
581 typename std::enable_if<
582 std::is_same<T, sal_Unicode>::value,
583 rtl::libreoffice_internal::Dummy>::type = {}):
584 data_(literal.data), size_(literal.size) {}
586 // LO specifics, to make up for traits::length not necessarily being
587 // constexpr yet for literal arguments:
589 template<typename T1, typename T2 = charT> constexpr basic_string_view(
590 T1 const & value,
591 typename std::enable_if<
592 std::is_same<T2, char>::value && detail::CharPtrDetector<T1>::ok,
593 rtl::libreoffice_internal::Dummy>::type = {}):
594 data_(value), size_(traits::length(value)) {}
596 template<typename T1, typename T2 = charT> constexpr basic_string_view(
597 T1 & value,
598 typename std::enable_if<
599 (std::is_same<T2, char>::value
600 && detail::NonConstCharArrayDetector<T1>::ok),
601 rtl::libreoffice_internal::Dummy>::type = {}):
602 data_(value), size_(traits::length(value)) {}
604 template<typename T1, typename T2 = charT> constexpr basic_string_view(
605 T1 & literal,
606 typename std::enable_if<
607 (std::is_same<T2, char>::value
608 && detail::ConstCharArrayDetector<T1>::ok),
609 rtl::libreoffice_internal::Dummy>::type = {}):
610 data_(literal), size_(detail::ConstCharArrayDetector<T1>::length)
611 { /*assert(size_ == traits::length(literal);*/ }
613 template<typename T1, typename T2 = charT> constexpr basic_string_view(
614 T1 const & value,
615 typename std::enable_if<
616 (std::is_same<T2, char16_t>::value
617 && detail::Char16PtrDetector<T1>::ok),
618 rtl::libreoffice_internal::Dummy>::type = {}):
619 data_(value), size_(traits::length(value)) {}
621 template<typename T1, typename T2 = charT> constexpr basic_string_view(
622 T1 & value,
623 typename std::enable_if<
624 (std::is_same<T2, char16_t>::value
625 && detail::NonConstChar16ArrayDetector<T1>::ok),
626 rtl::libreoffice_internal::Dummy>::type = {}):
627 data_(value), size_(traits::length(value)) {}
629 template<typename T1, typename T2 = charT> constexpr basic_string_view(
630 T1 & literal,
631 typename std::enable_if<
632 (std::is_same<T2, char16_t>::value
633 && detail::ConstChar16ArrayDetector<T1>::ok),
634 rtl::libreoffice_internal::Dummy>::type = {}):
635 data_(literal), size_(detail::ConstChar16ArrayDetector<T1>::length)
636 { /*assert(size_ == traits::length(literal);*/ }
638 template<typename T1, typename T2 = charT> constexpr basic_string_view(
639 T1 const & value,
640 typename std::enable_if<
641 (std::is_same<T2, char32_t>::value
642 && detail::Char32PtrDetector<T1>::ok),
643 rtl::libreoffice_internal::Dummy>::type = {}):
644 data_(value), size_(traits::length(value)) {}
646 template<typename T1, typename T2 = charT> constexpr basic_string_view(
647 T1 & value,
648 typename std::enable_if<
649 (std::is_same<T2, char32_t>::value
650 && detail::NonConstChar32ArrayDetector<T1>::ok),
651 rtl::libreoffice_internal::Dummy>::type = {}):
652 data_(value), size_(traits::length(value)) {}
654 template<typename T1, typename T2 = charT> constexpr basic_string_view(
655 T1 & literal,
656 typename std::enable_if<
657 (std::is_same<T2, char32_t>::value
658 && detail::ConstChar32ArrayDetector<T1>::ok),
659 rtl::libreoffice_internal::Dummy>::type = {}):
660 data_(literal), size_(detail::ConstChar32ArrayDetector<T1>::length)
661 { /*assert(size_ == traits::length(literal);*/ }
663 template<typename T1, typename T2 = charT> constexpr basic_string_view(
664 T1 const & value,
665 typename std::enable_if<
666 (std::is_same<T2, wchar_t>::value
667 && detail::WcharPtrDetector<T1>::ok),
668 rtl::libreoffice_internal::Dummy>::type = {}):
669 data_(value), size_(traits::length(value)) {}
671 template<typename T1, typename T2 = charT> constexpr basic_string_view(
672 T1 & value,
673 typename std::enable_if<
674 (std::is_same<T2, wchar_t>::value
675 && detail::NonConstWcharArrayDetector<T1>::ok),
676 rtl::libreoffice_internal::Dummy>::type = {}):
677 data_(value), size_(traits::length(value)) {}
679 template<typename T1, typename T2 = charT> constexpr basic_string_view(
680 T1 & literal,
681 typename std::enable_if<
682 (std::is_same<T2, wchar_t>::value
683 && detail::ConstWcharArrayDetector<T1>::ok),
684 rtl::libreoffice_internal::Dummy>::type = {}):
685 data_(literal), size_(detail::ConstWcharArrayDetector<T1>::length)
686 { /*assert(size_ == traits::length(literal);*/ }
688 private:
689 const_pointer data_;
690 size_type size_;
693 template<class charT, class traits> constexpr bool operator ==(
694 basic_string_view<charT, traits> x, basic_string_view<charT, traits> y)
695 noexcept
696 { return x.compare(y) == 0; }
698 template<class charT, class traits> constexpr bool operator ==(
699 basic_string_view<charT, traits> x,
700 typename std::decay<basic_string_view<charT, traits>>::type y)
701 noexcept
702 { return x.compare(y) == 0; }
704 template<class charT, class traits> constexpr bool operator ==(
705 typename std::decay<basic_string_view<charT, traits>>::type x,
706 basic_string_view<charT, traits> y)
707 noexcept
708 { return x.compare(y) == 0; }
710 template<class charT, class traits> constexpr bool operator !=(
711 basic_string_view<charT, traits> x, basic_string_view<charT, traits> y)
712 noexcept
713 { return x.compare(y) != 0; }
715 template<class charT, class traits> constexpr bool operator !=(
716 basic_string_view<charT, traits> x,
717 typename std::decay<basic_string_view<charT, traits>>::type y)
718 noexcept
719 { return x.compare(y) != 0; }
721 template<class charT, class traits> constexpr bool operator !=(
722 typename std::decay<basic_string_view<charT, traits>>::type x,
723 basic_string_view<charT, traits> y)
724 noexcept
725 { return x.compare(y) != 0; }
727 template<class charT, class traits> constexpr bool operator <(
728 basic_string_view<charT, traits> x, basic_string_view<charT, traits> y)
729 noexcept
730 { return x.compare(y) < 0; }
732 template<class charT, class traits> constexpr bool operator <(
733 basic_string_view<charT, traits> x,
734 typename std::decay<basic_string_view<charT, traits>>::type y)
735 noexcept
736 { return x.compare(y) < 0; }
738 template<class charT, class traits> constexpr bool operator <(
739 typename std::decay<basic_string_view<charT, traits>>::type x,
740 basic_string_view<charT, traits> y)
741 noexcept
742 { return x.compare(y) < 0; }
744 template<class charT, class traits> constexpr bool operator >(
745 basic_string_view<charT, traits> x, basic_string_view<charT, traits> y)
746 noexcept
747 { return x.compare(y) > 0; }
749 template<class charT, class traits> constexpr bool operator >(
750 basic_string_view<charT, traits> x,
751 typename std::decay<basic_string_view<charT, traits>>::type y)
752 noexcept
753 { return x.compare(y) > 0; }
755 template<class charT, class traits> constexpr bool operator >(
756 typename std::decay<basic_string_view<charT, traits>>::type x,
757 basic_string_view<charT, traits> y)
758 noexcept
759 { return x.compare(y) > 0; }
761 template<class charT, class traits> constexpr bool operator <=(
762 basic_string_view<charT, traits> x, basic_string_view<charT, traits> y)
763 noexcept
764 { return x.compare(y) <= 0; }
766 template<class charT, class traits> constexpr bool operator <=(
767 basic_string_view<charT, traits> x,
768 typename std::decay<basic_string_view<charT, traits>>::type y)
769 noexcept
770 { return x.compare(y) <= 0; }
772 template<class charT, class traits> constexpr bool operator <=(
773 typename std::decay<basic_string_view<charT, traits>>::type x,
774 basic_string_view<charT, traits> y)
775 noexcept
776 { return x.compare(y) <= 0; }
778 template<class charT, class traits> constexpr bool operator >=(
779 basic_string_view<charT, traits> x, basic_string_view<charT, traits> y)
780 noexcept
781 { return x.compare(y) >= 0; }
783 template<class charT, class traits> constexpr bool operator >=(
784 basic_string_view<charT, traits> x,
785 typename std::decay<basic_string_view<charT, traits>>::type y)
786 noexcept
787 { return x.compare(y) >= 0; }
789 template<class charT, class traits> constexpr bool operator >=(
790 typename std::decay<basic_string_view<charT, traits>>::type x,
791 basic_string_view<charT, traits> y)
792 noexcept
793 { return x.compare(y) >= 0; }
795 template<class charT, class traits> std::basic_ostream<charT, traits> &
796 operator <<(
797 std::basic_ostream<charT, traits> & os,
798 basic_string_view<charT, traits> str)
800 typename std::basic_ostream<charT, traits>::sentry sentry;
801 if (sentry) {
802 auto const w = os.width();
803 auto const pad
804 = std::max<std::make_unsigned<decltype(w + str.size())>::type>(
805 w < 0 ? 0 : w, str.size());
806 auto const after = (os.flags() & std::ios_base::adjustfield)
807 == std::ios_base::left;
808 if (pad != 0 && !after) {
809 auto const c = os.fill();
810 for (; pad != 0; --pad) {
811 os.rdbuf()->sputc(c);
814 os.rdbuf()->sputn(str.data(), str.size());
815 if (pad != 0 && after) {
816 auto const c = os.fill();
817 for (; pad != 0; --pad) {
818 os.rdbuf()->sputc(c);
821 os.width(0);
822 } else {
823 os.setstate(std::ios_base::failbit);
825 return os;
828 #if defined _MSC_VER
829 #pragma warning(pop)
830 #endif
832 using string_view = basic_string_view<char>;
833 using u16string_view = basic_string_view<char16_t>;
834 using u32string_view = basic_string_view<char32_t>;
835 using wstring_view = basic_string_view<wchar_t>;
837 // no literals::string_view_literals::operator "" sv
841 namespace std {
843 template<> struct hash<o3tl::string_view> {
844 std::size_t operator ()(o3tl::string_view s)
845 { return hash<string>()(string(s.data(), s.size())); }
848 template<> struct hash<o3tl::u16string_view> {
849 std::size_t operator ()(o3tl::u16string_view s)
850 { return hash<u16string>()(u16string(s.data(), s.size())); }
853 template<> struct hash<o3tl::u32string_view> {
854 std::size_t operator ()(o3tl::u32string_view s)
855 { return hash<u32string>()(u32string(s.data(), s.size())); }
858 template<> struct hash<o3tl::wstring_view> {
859 std::size_t operator ()(o3tl::wstring_view s)
860 { return hash<wstring>()(wstring(s.data(), s.size())); }
865 namespace o3tl {
867 // LO-specific convenience functions:
869 // For std::u16string_view, this will be provided by a (LIBO_INTERNAL_ONLY)
870 // rtl::OUString constructor:
871 inline OUString toOUString(u16string_view s)
872 { return OUString(s.data(), s.size()); }
876 #endif
878 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */