diff options
author | Stephan Bergmann <sbergman@redhat.com> | 2017-04-07 15:59:12 +0200 |
---|---|---|
committer | Stephan Bergmann <sbergman@redhat.com> | 2017-04-07 20:12:31 +0000 |
commit | 50057a37a877213d935958d5c643fde1434d680c (patch) | |
tree | f02ca6d5a9be4f7df10643a82d24ab10f5c44646 /include/o3tl | |
parent | 39038a3544d1b42388a15e6098ccad8398e8ef36 (diff) |
Introduce o3tl::string_view.hxx approximation of C++17 <string_view>
...and use it in configmgr/source/writemodfile.hxx
Change-Id: Ie683dc21010ed45cc454ff89bea0376994b351f2
Reviewed-on: https://gerrit.libreoffice.org/36270
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
Diffstat (limited to 'include/o3tl')
-rw-r--r-- | include/o3tl/string_view.hxx | 867 |
1 files changed, 867 insertions, 0 deletions
diff --git a/include/o3tl/string_view.hxx b/include/o3tl/string_view.hxx new file mode 100644 index 000000000000..9230909b7edf --- /dev/null +++ b/include/o3tl/string_view.hxx @@ -0,0 +1,867 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_O3TL_STRING_VIEW_HXX +#define INCLUDED_O3TL_STRING_VIEW_HXX + +#include <sal/config.h> + +#include <algorithm> +#include <cstddef> +#include <ios> +#include <iterator> +#include <ostream> +#include <stdexcept> +#include <string> +#include <type_traits> +#include <utility> + +#include <config_global.h> +#include <rtl/string.hxx> +#include <rtl/ustring.hxx> +#include <sal/types.h> + +// An approximation of C++17 <string_view>, including implicit conversion +// from rtl::OString and rtl::OUString. + +namespace o3tl { + +namespace detail { + +template<typename T> struct CharPtrDetector { + static constexpr bool ok = false; +}; + +template<> struct CharPtrDetector<char *> { + static constexpr bool ok = true; +}; + +template<> struct CharPtrDetector<char const *> { + static constexpr bool ok = true; +}; + +template<typename T> struct NonConstCharArrayDetector { + static constexpr bool ok = false; +}; + +template<std::size_t N> struct NonConstCharArrayDetector<char [N]> { + static constexpr bool ok = true; +}; + +template<typename T> struct ConstCharArrayDetector { + static constexpr bool ok = false; +}; + +template<std::size_t N> struct ConstCharArrayDetector<char const[N]> { + static constexpr bool ok = true; + static constexpr std::size_t length = N - 1; +}; + +template<typename T> struct Char16PtrDetector { + static constexpr bool ok = false; +}; + +template<> struct Char16PtrDetector<char16_t *> { + static constexpr bool ok = true; +}; + +template<> struct Char16PtrDetector<char16_t const *> { + static constexpr bool ok = true; +}; + +template<typename T> struct NonConstChar16ArrayDetector { + static constexpr bool ok = false; +}; + +template<std::size_t N> struct NonConstChar16ArrayDetector<char16_t [N]> { + static constexpr bool ok = true; +}; + +template<typename T> struct ConstChar16ArrayDetector { + static constexpr bool ok = false; +}; + +template<std::size_t N> struct ConstChar16ArrayDetector<char16_t const[N]> { + static constexpr bool ok = true; + static constexpr std::size_t length = N - 1; +}; + +template<typename T> struct Char32PtrDetector { + static constexpr bool ok = false; +}; + +template<> struct Char32PtrDetector<char32_t *> { + static constexpr bool ok = true; +}; + +template<> struct Char32PtrDetector<char32_t const *> { + static constexpr bool ok = true; +}; + +template<typename T> struct NonConstChar32ArrayDetector { + static constexpr bool ok = false; +}; + +template<std::size_t N> struct NonConstChar32ArrayDetector<char32_t [N]> { + static constexpr bool ok = true; +}; + +template<typename T> struct ConstChar32ArrayDetector { + static constexpr bool ok = false; +}; + +template<std::size_t N> struct ConstChar32ArrayDetector<char32_t const[N]> { + static constexpr bool ok = true; + static constexpr std::size_t length = N - 1; +}; + +template<typename T> struct WcharPtrDetector { + static constexpr bool ok = false; +}; + +template<> struct WcharPtrDetector<wchar_t *> { + static constexpr bool ok = true; +}; + +template<> struct WcharPtrDetector<wchar_t const *> { + static constexpr bool ok = true; +}; + +template<typename T> struct NonConstWcharArrayDetector { + static constexpr bool ok = false; +}; + +template<std::size_t N> struct NonConstWcharArrayDetector<wchar_t [N]> { + static constexpr bool ok = true; +}; + +template<typename T> struct ConstWcharArrayDetector { + static constexpr bool ok = false; +}; + +template<std::size_t N> struct ConstWcharArrayDetector<wchar_t const[N]> { + static constexpr bool ok = true; + static constexpr std::size_t length = N - 1; +}; + +} + +#if defined _MSC_VER +#pragma warning(push, 1) +#pragma warning(disable: 4814) // in C++14 'constexpr' will not imply 'const' +#endif + +template<typename charT, typename traits = std::char_traits<charT>> +class basic_string_view { +public: + using traits_type = traits; + using value_type = charT; + using pointer = value_type *; + using const_pointer = value_type const *; + using reference = value_type &; + using const_reference = value_type const &; + using const_iterator = const_pointer; + using iterator = const_iterator; + using const_reverse_iterator = std::reverse_iterator<const_iterator>; + using reverse_iterator = const_reverse_iterator; + using size_type = std::size_t; + using difference_type = std::ptrdiff_t; + + static constexpr size_type npos = size_type(-1); + + constexpr basic_string_view() noexcept: data_(nullptr), size_(0) {} + + constexpr basic_string_view(basic_string_view const &) noexcept = default; + +#if HAVE_CXX14_CONSTEXPR + constexpr +#endif + basic_string_view & operator =(basic_string_view const & other) noexcept +#if defined _MSC_VER && _MSC_VER <= 1900 && !defined __clang__ + { + data_ = other.data_; + size_ = other.size_; + return *this; + } +#else + = default; +#endif + + // The various character types are handled below in the "LO specifics, to + // make up for traits::length not necessarily being constexpr yet for + // literal arguments" section: + template<typename T = charT> constexpr basic_string_view( + charT const * str, + typename std::enable_if< + !(std::is_same<T, char>::value || std::is_same<T, char16_t>::value + || std::is_same<T, char32_t>::value + || std::is_same<T, wchar_t>::value), + rtl::libreoffice_internal::Dummy>::type = {}): + data_(str), size_(traits::length(str)) {} + + constexpr basic_string_view(charT const * str, size_type len): + data_(str), size_(len) {} + + constexpr const_iterator begin() const noexcept { return data_; } + + constexpr const_iterator end() const noexcept { return begin() + size(); } + + constexpr const_iterator cbegin() const noexcept { return begin(); } + + constexpr const_iterator cend() const noexcept { return end(); } + + constexpr const_reverse_iterator rbegin() const noexcept + { return const_reverse_iterator(end()); } + + constexpr const_reverse_iterator rend() const noexcept + { return const_reverse_iterator(begin()); } + + constexpr const_reverse_iterator crbegin() const noexcept + { return rbegin(); } + + constexpr const_reverse_iterator crend() const noexcept { return rend(); } + + constexpr size_type size() const noexcept { return size_; } + + constexpr size_type length() const noexcept { return size(); } + +#if !defined __clang__ || HAVE_CXX14_CONSTEXPR + constexpr +#endif + size_type max_size() const noexcept { +#if defined __clang__ // avoid constexpr issues with other, older compilers + (void) this; // loplugin:staticmethods +#endif + return npos - 1; + } + + constexpr bool empty() const noexcept { return size_ == 0; } + + constexpr const_reference operator [](size_type pos) const { +#if HAVE_CXX14_CONSTEXPR + assert(pos < size()); +#endif + return data_[pos]; + } + +#if HAVE_CXX14_CONSTEXPR + constexpr +#endif + const_reference at(size_type pos) const { + if (pos >= size()) { + throw std::out_of_range("o3tl::basic_string_view::at"); + } + return operator [](pos); + } + + constexpr const_reference front() const { +#if HAVE_CXX14_CONSTEXPR + assert(!empty()); +#endif + return operator [](0); + } + + constexpr const_reference back() const { +#if HAVE_CXX14_CONSTEXPR + assert(!empty()); +#endif + return operator [](size() - 1); + } + + constexpr const_pointer data() const noexcept { return data_; } + +#if HAVE_CXX14_CONSTEXPR + constexpr +#endif + void remove_prefix(size_type n) { + assert(n <= size()); + data_ += n; + size_ -= n; + } + +#if HAVE_CXX14_CONSTEXPR + constexpr +#endif + void remove_suffix(size_type n) { + assert(n <= size()); + size_ -= n; + } + +#if HAVE_CXX14_CONSTEXPR + constexpr +#endif + void swap(basic_string_view & s) noexcept { + std::swap(data_, s.data_); + std::swap(size_, s.size_); + } + + size_type copy(charT * s, size_type n, size_type pos = 0) const { + if (pos > size()) { + throw std::out_of_range("o3tl::basic_string_view::copy"); + } + auto rlen = std::min(n, size_type(size() - pos)); + traits::copy(s, data() + pos, rlen); + return rlen; + } + +#if HAVE_CXX14_CONSTEXPR + constexpr +#endif + basic_string_view substr(size_type pos = 0, size_type n = npos) const { + if (pos > size()) { + throw std::out_of_range("o3tl::basic_string_view::copy"); + } + return basic_string_view( + data() + pos, std::min(n, size_type(size() - pos))); + } + +#if HAVE_CXX14_CONSTEXPR + constexpr +#endif + int compare(basic_string_view s) const noexcept { + auto n = traits::compare(data(), s.data(), std::min(size(), s.size())); + return n == 0 + ? (size() < s.size() ? -1 : size() == s.size() ? 0 : 1) : n; + } + + constexpr int compare(size_type pos1, size_type n1, basic_string_view s) + const + { return substr(pos1, n1).compare(s); } + + constexpr int compare( + size_type pos1, size_type n1, basic_string_view s, size_type pos2, + size_type n2) const + { return substr(pos1, n1).compare(s.substr(pos2, n2)); } + + constexpr int compare(charT const * s) const + { return compare(basic_string_view(s)); } + + constexpr int compare(size_type pos1, size_type n1, charT const * s) const + { return substr(pos1, n1).compare(s); } + + constexpr int compare( + size_type pos1, size_type n1, charT const * s, size_type n2) const + { return substr(pos1, n1).compare(basic_string_view(s, n2)); } + +#if HAVE_CXX14_CONSTEXPR + constexpr +#endif + size_type find(basic_string_view s, size_type pos = 0) const noexcept { + if (s.size() <= size()) { + for (auto xpos = pos; xpos <= size() - s.size(); ++xpos) { + bool match = true; + for (size_type i = 0; i != s.size(); ++i) { + if (!traits::eq(data_[xpos + i], s.data_[i])) { + match = false; + break; + } + } + if (match) { + return xpos; + } + } + } + return npos; + } + + constexpr size_type find(charT c, size_type pos = 0) const noexcept + { return find(basic_string_view(&c, 1), pos); } + + constexpr size_type find(charT const * s, size_type pos, size_type n) const + { return find(basic_string_view(s, n), pos); } + + constexpr size_type find(charT const * s, size_type pos = 0) const + { return find(basic_string_view(s), pos); } + +#if HAVE_CXX14_CONSTEXPR + constexpr +#endif + size_type rfind(basic_string_view s, size_type pos = npos) const noexcept { + if (s.size() <= size()) { + for (auto xpos = std::min<size_type>(size() - s.size(), pos);; + --xpos) + { + bool match = true; + for (size_type i = 0; i != s.size(); ++i) { + if (!traits::eq(data_[xpos + i], s.data_[i])) { + match = false; + break; + } + } + if (match) { + return xpos; + } + if (xpos == 0) { + break; + } + } + } + return npos; + } + + constexpr size_type rfind(charT c, size_type pos = npos) const noexcept + { return rfind(basic_string_view(&c, 1), pos); } + + constexpr size_type rfind(charT const * s, size_type pos, size_type n) const + { return rfind(basic_string_view(s, n), pos); } + + constexpr size_type rfind(charT const * s, size_type pos = npos) const + { return rfind(basic_string_view(s), pos); } + +#if HAVE_CXX14_CONSTEXPR + constexpr +#endif + size_type find_first_of(basic_string_view s, size_type pos = 0) const + noexcept + { + for (auto xpos = pos; xpos < size(); ++xpos) { + for (size_type i = 0; i != s.size(); ++i) { + if (traits::eq(data_[xpos], s.data_[i])) { + return xpos; + } + } + } + return npos; + } + + constexpr size_type find_first_of(charT c, size_type pos = 0) const noexcept + { return find_first_of(basic_string_view(&c, 1), pos); } + + constexpr size_type find_first_of( + charT const * s, size_type pos, size_type n) const + { return find_first_of(basic_string_view(s, n), pos); } + + constexpr size_type find_first_of(charT const * s, size_type pos = 0) const + { return find_first_of(basic_string_view(s), pos); } + +#if HAVE_CXX14_CONSTEXPR + constexpr +#endif + size_type find_last_of(basic_string_view s, size_type pos = npos) const + noexcept + { + if (!empty()) { + for (auto xpos = std::min<size_type>(size() - 1, pos);; --xpos) { + for (size_type i = 0; i != s.size(); ++i) { + if (traits::eq(data_[xpos], s.data_[i])) { + return xpos; + } + } + if (xpos == 0) { + break; + } + } + } + return npos; + } + + constexpr size_type find_last_of(charT c, size_type pos = npos) const + noexcept + { return find_last_of(basic_string_view(&c, 1), pos); } + + constexpr size_type find_last_of( + charT const * s, size_type pos, size_type n) const + { return find_last_of(basic_string_view(s, n), pos); } + + constexpr size_type find_last_of(charT const * s, size_type pos = npos) + const + { return find_last_of(basic_string_view(s), pos); } + +#if HAVE_CXX14_CONSTEXPR + constexpr +#endif + size_type find_first_not_of(basic_string_view s, size_type pos = 0) const + noexcept + { + for (auto xpos = pos; xpos < size(); ++xpos) { + bool match = true; + for (size_type i = 0; i != s.size(); ++i) { + if (traits::eq(data_[xpos], s.data_[i])) { + match = false; + break; + } + } + if (match) { + return xpos; + } + } + return npos; + } + + constexpr size_type find_first_not_of(charT c, size_type pos = 0) const + noexcept + { return find_first_not_of(basic_string_view(&c, 1), pos); } + + constexpr size_type find_first_not_of( + charT const * s, size_type pos, size_type n) const + { return find_first_not_of(basic_string_view(s, n), pos); } + + constexpr size_type find_first_not_of(charT const * s, size_type pos = 0) + const + { return find_first_not_of(basic_string_view(s), pos); } + +#if HAVE_CXX14_CONSTEXPR + constexpr +#endif + size_type find_last_not_of(basic_string_view s, size_type pos = npos) const + noexcept + { + if (!empty()) { + for (auto xpos = std::min<size_type>(size() - 1, pos);; --xpos) { + bool match = true; + for (size_type i = 0; i != s.size(); ++i) { + if (traits::eq(data_[xpos], s.data_[i])) { + match = false; + break; + } + } + if (match) { + return xpos; + } + if (xpos == 0) { + break; + } + } + } + return npos; + } + + constexpr size_type find_last_not_of(charT c, size_type pos = npos) const + noexcept + { return find_last_not_of(basic_string_view(&c, 1), pos); } + + constexpr size_type find_last_not_of( + charT const * s, size_type pos, size_type n) const + { return find_last_not_of(basic_string_view(s, n), pos); } + + constexpr size_type find_last_not_of(charT const * s, size_type pos = npos) + const + { return find_last_not_of(basic_string_view(s), pos); } + + // LO specifics: + + // For std::basic_string_view, this is provided via a non-explicit + // conversion operator from std::basic_string: + constexpr basic_string_view(std::basic_string<charT, traits> const & s): + data_(s.data()), size_(s.size()) {} + + // For std::string_view, this will be provided by a (LIBO_INTERNAL_ONLY) + // non-explicit conversion operator from rtl::OString: + template<typename T = charT> basic_string_view( + OString const & s, + typename std::enable_if< + std::is_same<T, char>::value, + rtl::libreoffice_internal::Dummy>::type = {}): + data_(s.getStr()), size_(s.getLength()) {} + + // For std::u16string_view, this will be provided by a (LIBO_INTERNAL_ONLY) + // non-explicit conversion operator from rtl::OUString: + template<typename T = charT> basic_string_view( + OUString const & s, + typename std::enable_if< + std::is_same<T, sal_Unicode>::value, + rtl::libreoffice_internal::Dummy>::type = {}): + data_(s.getStr()), size_(s.getLength()) {} + + // For std::u16string_view, this would either be provided by a + // (LIBO_INTERNAL_ONLY) non-explicit conversion operator from + // rtl::OUStringLiteral, or rtl::OUStringLiteral would be given up in favor + // of std::u16string_view anyway (but this constructor also serves to reject + // as ambiguous construction of a o3tl::u16string_view from a narrow string + // literal, which would otherwise go via the above rtl::OUString + // constructor): + template<typename T = charT> constexpr basic_string_view( + OUStringLiteral literal, + typename std::enable_if< + std::is_same<T, sal_Unicode>::value, + rtl::libreoffice_internal::Dummy>::type = {}): + data_(literal.data), size_(literal.size) {} + + // LO specifics, to make up for traits::length not necessarily being + // constexpr yet for literal arguments: + + template<typename T1, typename T2 = charT> constexpr basic_string_view( + T1 const & value, + typename std::enable_if< + std::is_same<T2, char>::value && detail::CharPtrDetector<T1>::ok, + rtl::libreoffice_internal::Dummy>::type = {}): + data_(value), size_(traits::length(value)) {} + + template<typename T1, typename T2 = charT> constexpr basic_string_view( + T1 & value, + typename std::enable_if< + (std::is_same<T2, char>::value + && detail::NonConstCharArrayDetector<T1>::ok), + rtl::libreoffice_internal::Dummy>::type = {}): + data_(value), size_(traits::length(value)) {} + + template<typename T1, typename T2 = charT> constexpr basic_string_view( + T1 & literal, + typename std::enable_if< + (std::is_same<T2, char>::value + && detail::ConstCharArrayDetector<T1>::ok), + rtl::libreoffice_internal::Dummy>::type = {}): + data_(literal), size_(detail::ConstCharArrayDetector<T1>::length) + { /*assert(size_ == traits::length(literal);*/ } + + template<typename T1, typename T2 = charT> constexpr basic_string_view( + T1 const & value, + typename std::enable_if< + (std::is_same<T2, char16_t>::value + && detail::Char16PtrDetector<T1>::ok), + rtl::libreoffice_internal::Dummy>::type = {}): + data_(value), size_(traits::length(value)) {} + + template<typename T1, typename T2 = charT> constexpr basic_string_view( + T1 & value, + typename std::enable_if< + (std::is_same<T2, char16_t>::value + && detail::NonConstChar16ArrayDetector<T1>::ok), + rtl::libreoffice_internal::Dummy>::type = {}): + data_(value), size_(traits::length(value)) {} + + template<typename T1, typename T2 = charT> constexpr basic_string_view( + T1 & literal, + typename std::enable_if< + (std::is_same<T2, char16_t>::value + && detail::ConstChar16ArrayDetector<T1>::ok), + rtl::libreoffice_internal::Dummy>::type = {}): + data_(literal), size_(detail::ConstChar16ArrayDetector<T1>::length) + { /*assert(size_ == traits::length(literal);*/ } + + template<typename T1, typename T2 = charT> constexpr basic_string_view( + T1 const & value, + typename std::enable_if< + (std::is_same<T2, char32_t>::value + && detail::Char32PtrDetector<T1>::ok), + rtl::libreoffice_internal::Dummy>::type = {}): + data_(value), size_(traits::length(value)) {} + + template<typename T1, typename T2 = charT> constexpr basic_string_view( + T1 & value, + typename std::enable_if< + (std::is_same<T2, char32_t>::value + && detail::NonConstChar32ArrayDetector<T1>::ok), + rtl::libreoffice_internal::Dummy>::type = {}): + data_(value), size_(traits::length(value)) {} + + template<typename T1, typename T2 = charT> constexpr basic_string_view( + T1 & literal, + typename std::enable_if< + (std::is_same<T2, char32_t>::value + && detail::ConstChar32ArrayDetector<T1>::ok), + rtl::libreoffice_internal::Dummy>::type = {}): + data_(literal), size_(detail::ConstChar32ArrayDetector<T1>::length) + { /*assert(size_ == traits::length(literal);*/ } + + template<typename T1, typename T2 = charT> constexpr basic_string_view( + T1 const & value, + typename std::enable_if< + (std::is_same<T2, wchar_t>::value + && detail::WcharPtrDetector<T1>::ok), + rtl::libreoffice_internal::Dummy>::type = {}): + data_(value), size_(traits::length(value)) {} + + template<typename T1, typename T2 = charT> constexpr basic_string_view( + T1 & value, + typename std::enable_if< + (std::is_same<T2, wchar_t>::value + && detail::NonConstWcharArrayDetector<T1>::ok), + rtl::libreoffice_internal::Dummy>::type = {}): + data_(value), size_(traits::length(value)) {} + + template<typename T1, typename T2 = charT> constexpr basic_string_view( + T1 & literal, + typename std::enable_if< + (std::is_same<T2, wchar_t>::value + && detail::ConstWcharArrayDetector<T1>::ok), + rtl::libreoffice_internal::Dummy>::type = {}): + data_(literal), size_(detail::ConstWcharArrayDetector<T1>::length) + { /*assert(size_ == traits::length(literal);*/ } + +private: + const_pointer data_; + size_type size_; +}; + +template<class charT, class traits> constexpr bool operator ==( + basic_string_view<charT, traits> x, basic_string_view<charT, traits> y) + noexcept +{ return x.compare(y) == 0; } + +template<class charT, class traits> constexpr bool operator ==( + basic_string_view<charT, traits> x, + typename std::decay<basic_string_view<charT, traits>>::type y) + noexcept +{ return x.compare(y) == 0; } + +template<class charT, class traits> constexpr bool operator ==( + typename std::decay<basic_string_view<charT, traits>>::type x, + basic_string_view<charT, traits> y) + noexcept +{ return x.compare(y) == 0; } + +template<class charT, class traits> constexpr bool operator !=( + basic_string_view<charT, traits> x, basic_string_view<charT, traits> y) + noexcept +{ return x.compare(y) != 0; } + +template<class charT, class traits> constexpr bool operator !=( + basic_string_view<charT, traits> x, + typename std::decay<basic_string_view<charT, traits>>::type y) + noexcept +{ return x.compare(y) != 0; } + +template<class charT, class traits> constexpr bool operator !=( + typename std::decay<basic_string_view<charT, traits>>::type x, + basic_string_view<charT, traits> y) + noexcept +{ return x.compare(y) != 0; } + +template<class charT, class traits> constexpr bool operator <( + basic_string_view<charT, traits> x, basic_string_view<charT, traits> y) + noexcept +{ return x.compare(y) < 0; } + +template<class charT, class traits> constexpr bool operator <( + basic_string_view<charT, traits> x, + typename std::decay<basic_string_view<charT, traits>>::type y) + noexcept +{ return x.compare(y) < 0; } + +template<class charT, class traits> constexpr bool operator <( + typename std::decay<basic_string_view<charT, traits>>::type x, + basic_string_view<charT, traits> y) + noexcept +{ return x.compare(y) < 0; } + +template<class charT, class traits> constexpr bool operator >( + basic_string_view<charT, traits> x, basic_string_view<charT, traits> y) + noexcept +{ return x.compare(y) > 0; } + +template<class charT, class traits> constexpr bool operator >( + basic_string_view<charT, traits> x, + typename std::decay<basic_string_view<charT, traits>>::type y) + noexcept +{ return x.compare(y) > 0; } + +template<class charT, class traits> constexpr bool operator >( + typename std::decay<basic_string_view<charT, traits>>::type x, + basic_string_view<charT, traits> y) + noexcept +{ return x.compare(y) > 0; } + +template<class charT, class traits> constexpr bool operator <=( + basic_string_view<charT, traits> x, basic_string_view<charT, traits> y) + noexcept +{ return x.compare(y) <= 0; } + +template<class charT, class traits> constexpr bool operator <=( + basic_string_view<charT, traits> x, + typename std::decay<basic_string_view<charT, traits>>::type y) + noexcept +{ return x.compare(y) <= 0; } + +template<class charT, class traits> constexpr bool operator <=( + typename std::decay<basic_string_view<charT, traits>>::type x, + basic_string_view<charT, traits> y) + noexcept +{ return x.compare(y) <= 0; } + +template<class charT, class traits> constexpr bool operator >=( + basic_string_view<charT, traits> x, basic_string_view<charT, traits> y) + noexcept +{ return x.compare(y) >= 0; } + +template<class charT, class traits> constexpr bool operator >=( + basic_string_view<charT, traits> x, + typename std::decay<basic_string_view<charT, traits>>::type y) + noexcept +{ return x.compare(y) >= 0; } + +template<class charT, class traits> constexpr bool operator >=( + typename std::decay<basic_string_view<charT, traits>>::type x, + basic_string_view<charT, traits> y) + noexcept +{ return x.compare(y) >= 0; } + +template<class charT, class traits> std::basic_ostream<charT, traits> & +operator <<( + std::basic_ostream<charT, traits> & os, + basic_string_view<charT, traits> str) +{ + typename std::basic_ostream<charT, traits>::sentry sentry; + if (sentry) { + auto const w = os.width(); + auto const pad + = std::max<std::make_unsigned<decltype(w + str.size())>::type>( + w < 0 ? 0 : w, str.size()); + auto const after = (os.flags() & std::ios_base::adjustfield) + == std::ios_base::left; + if (pad != 0 && !after) { + auto const c = os.fill(); + for (; pad != 0; --pad) { + os.rdbuf()->sputc(c); + } + } + os.rdbuf()->sputn(str.data(), str.size()); + if (pad != 0 && after) { + auto const c = os.fill(); + for (; pad != 0; --pad) { + os.rdbuf()->sputc(c); + } + } + os.width(0); + } else { + os.setstate(std::ios_base::failbit); + } + return os; +} + +#if defined _MSC_VER +#pragma warning(pop) +#endif + +using string_view = basic_string_view<char>; +using u16string_view = basic_string_view<char16_t>; +using u32string_view = basic_string_view<char32_t>; +using wstring_view = basic_string_view<wchar_t>; + +// no literals::string_view_literals::operator "" sv + +} + +namespace std { + +template<> struct hash<o3tl::string_view> { + std::size_t operator ()(o3tl::string_view s) + { return hash<string>()(string(s.data(), s.size())); } +}; + +template<> struct hash<o3tl::u16string_view> { + std::size_t operator ()(o3tl::u16string_view s) + { return hash<u16string>()(u16string(s.data(), s.size())); } +}; + +template<> struct hash<o3tl::u32string_view> { + std::size_t operator ()(o3tl::u32string_view s) + { return hash<u32string>()(u32string(s.data(), s.size())); } +}; + +template<> struct hash<o3tl::wstring_view> { + std::size_t operator ()(o3tl::wstring_view s) + { return hash<wstring>()(wstring(s.data(), s.size())); } +}; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ |