1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
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/.
10 #ifndef INCLUDED_O3TL_STRING_VIEW_HXX
11 #define INCLUDED_O3TL_STRING_VIEW_HXX
13 #include <sal/config.h>
22 #include <type_traits>
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.
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;
156 #pragma warning(push, 1)
157 #pragma warning(disable: 4814) // in C++14 'constexpr' will not imply 'const'
160 template<typename charT
, typename traits
= std::char_traits
<charT
>>
161 class basic_string_view
{
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
185 basic_string_view
& operator =(basic_string_view
const & other
) noexcept
186 #if defined _MSC_VER && _MSC_VER <= 1900 && !defined __clang__
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(
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
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
237 size_type
max_size() const noexcept
{
238 #if defined __clang__ // avoid constexpr issues with other, older compilers
239 (void) this; // loplugin:staticmethods
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());
253 #if HAVE_CXX14_CONSTEXPR
256 const_reference
at(size_type pos
) const {
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
267 return operator [](0);
270 constexpr const_reference
back() const {
271 #if HAVE_CXX14_CONSTEXPR
274 return operator [](size() - 1);
277 constexpr const_pointer
data() const noexcept
{ return data_
; }
279 #if HAVE_CXX14_CONSTEXPR
282 void remove_prefix(size_type n
) {
288 #if HAVE_CXX14_CONSTEXPR
291 void remove_suffix(size_type n
) {
296 #if HAVE_CXX14_CONSTEXPR
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 {
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
);
313 #if HAVE_CXX14_CONSTEXPR
316 basic_string_view
substr(size_type pos
= 0, size_type n
= npos
) const {
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
327 int compare(basic_string_view s
) const noexcept
{
328 auto n
= traits::compare(data(), s
.data(), std::min(size(), s
.size()));
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
)
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
,
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
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
) {
359 for (size_type i
= 0; i
!= s
.size(); ++i
) {
360 if (!traits::eq(data_
[xpos
+ i
], s
.data_
[i
])) {
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
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
);;
391 for (size_type i
= 0; i
!= s
.size(); ++i
) {
392 if (!traits::eq(data_
[xpos
+ i
], s
.data_
[i
])) {
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
420 size_type
find_first_of(basic_string_view s
, size_type pos
= 0) const
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
])) {
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
446 size_type
find_last_of(basic_string_view s
, size_type pos
= npos
) const
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
])) {
464 constexpr size_type
find_last_of(charT c
, size_type pos
= npos
) const
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
)
474 { return find_last_of(basic_string_view(s
), pos
); }
476 #if HAVE_CXX14_CONSTEXPR
479 size_type
find_first_not_of(basic_string_view s
, size_type pos
= 0) const
482 for (auto xpos
= pos
; xpos
< size(); ++xpos
) {
484 for (size_type i
= 0; i
!= s
.size(); ++i
) {
485 if (traits::eq(data_
[xpos
], s
.data_
[i
])) {
497 constexpr size_type
find_first_not_of(charT c
, size_type pos
= 0) const
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)
507 { return find_first_not_of(basic_string_view(s
), pos
); }
509 #if HAVE_CXX14_CONSTEXPR
512 size_type
find_last_not_of(basic_string_view s
, size_type pos
= npos
) const
516 for (auto xpos
= std::min
<size_type
>(size() - 1, pos
);; --xpos
) {
518 for (size_type i
= 0; i
!= s
.size(); ++i
) {
519 if (traits::eq(data_
[xpos
], s
.data_
[i
])) {
535 constexpr size_type
find_last_not_of(charT c
, size_type pos
= npos
) const
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
)
545 { return find_last_not_of(basic_string_view(s
), pos
); }
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(
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(
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
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(
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(
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(
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(
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(
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(
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(
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(
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(
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(
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(
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(
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);*/ }
693 template<class charT
, class traits
> constexpr bool operator ==(
694 basic_string_view
<charT
, traits
> x
, basic_string_view
<charT
, traits
> y
)
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
)
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
)
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
)
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
)
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
)
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
)
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
)
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
)
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
)
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
)
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
)
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
)
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
)
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
)
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
)
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
)
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
)
793 { return x
.compare(y
) >= 0; }
795 template<class charT
, class traits
> std::basic_ostream
<charT
, traits
> &
797 std::basic_ostream
<charT
, traits
> & os
,
798 basic_string_view
<charT
, traits
> str
)
800 typename
std::basic_ostream
<charT
, traits
>::sentry sentry
;
802 auto const w
= os
.width();
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
);
823 os
.setstate(std::ios_base::failbit
);
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
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())); }
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()); }
878 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */