diff options
Diffstat (limited to 'include/jsoncons/detail/string_view.hpp')
-rw-r--r-- | include/jsoncons/detail/string_view.hpp | 537 |
1 files changed, 537 insertions, 0 deletions
diff --git a/include/jsoncons/detail/string_view.hpp b/include/jsoncons/detail/string_view.hpp new file mode 100644 index 0000000..fc568a1 --- /dev/null +++ b/include/jsoncons/detail/string_view.hpp @@ -0,0 +1,537 @@ +// Copyright 2019 Daniel Parker +// Distributed under the Boost license, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See https://github.com/danielaparker/jsoncons for latest version + +#ifndef JSONCONS_STRING_VIEW_HPP +#define JSONCONS_STRING_VIEW_HPP + +#include <stdexcept> +#include <string> +#include <vector> +#include <ostream> +#include <cmath> +#include <algorithm> // std::find, std::min, std::reverse +#include <memory> +#include <iterator> +#include <exception> +#include <stdexcept> +#include <istream> // std::basic_istream +#include <jsoncons/config/compiler_support.hpp> + +namespace jsoncons { +namespace detail { + + template <class CharT, class Traits = std::char_traits<CharT>> + class basic_string_view + { + private: + const CharT* data_; + std::size_t length_; + public: + using value_type = CharT; + using const_reference = const CharT&; + using traits_type = Traits; + using size_type = std::size_t; + static constexpr size_type npos = size_type(-1); + using const_iterator = const CharT*; + using iterator = const CharT*; + using const_reverse_iterator = std::reverse_iterator<const_iterator>; + + constexpr basic_string_view() noexcept + : data_(nullptr), length_(0) + { + } + constexpr basic_string_view(const CharT* data, std::size_t length) + : data_(data), length_(length) + { + } + + basic_string_view(const CharT* data) + : data_(data), length_(Traits::length(data)) + { + } + constexpr basic_string_view(const basic_string_view& other) noexcept = default; + + template <class Tr, class Allocator> + JSONCONS_CPP14_CONSTEXPR basic_string_view(const std::basic_string<CharT,Tr,Allocator>& s) noexcept + : data_(s.data()), length_(s.length()) + { + } + + JSONCONS_CPP14_CONSTEXPR basic_string_view& operator=( const basic_string_view& view ) noexcept + { + data_ = view.data(); + length_ = view.length(); + + return *this; + } + + template <class Allocator> + explicit operator std::basic_string<CharT,Traits,Allocator>() const + { + return std::basic_string<CharT,Traits,Allocator>(data_,length_); + } + + // iterator support + const_iterator begin() const noexcept + { + return data_; + } + const_iterator end() const noexcept + { + return data_ + length_; + } + const_iterator cbegin() const noexcept + { + return data_; + } + const_iterator cend() const noexcept + { + return data_ + length_; + } + const_reverse_iterator rbegin() const noexcept + { + return const_reverse_iterator(end()); + } + const_reverse_iterator rend() const noexcept + { + return const_reverse_iterator(begin()); + } + const_reverse_iterator crbegin() const noexcept + { + return const_reverse_iterator(end()); + } + const_reverse_iterator crend() const noexcept + { + return const_reverse_iterator(begin()); + } + + // capacity + + std::size_t size() const + { + return length_; + } + + std::size_t length() const + { + return length_; + } + size_type max_size() const noexcept + { + return length_; + } + bool empty() const noexcept + { + return length_ == 0; + } + + // element access + + const_reference operator[](size_type pos) const + { + return data_[pos]; + } + + const_reference at(std::size_t pos) const + { + if (pos >= length_) + { + JSONCONS_THROW(std::out_of_range("pos exceeds length")); + } + return data_[pos]; + } + + const_reference front() const + { + return data_[0]; + } + const_reference back() const + { + return data_[length_-1]; + } + + const CharT* data() const + { + return data_; + } + + // string operations + + basic_string_view substr(size_type pos, size_type n=npos) const + { + if (pos > length_) + { + JSONCONS_THROW(std::out_of_range("pos exceeds size")); + } + if (n == npos || pos + n > length_) + { + n = length_ - pos; + } + return basic_string_view(data_ + pos, n); + } + + int compare(const basic_string_view& s) const noexcept + { + const int rc = Traits::compare(data_, s.data_, (std::min)(length_, s.length_)); + return rc != 0 ? rc : (length_ == s.length_ ? 0 : length_ < s.length_ ? -1 : 1); + } + + int compare(const CharT* data) const noexcept + { + const size_t length = Traits::length(data); + const int rc = Traits::compare(data_, data, (std::min)(length_, length)); + return rc != 0 ? rc : (length_ == length? 0 : length_ < length? -1 : 1); + } + + template <class Allocator> + int compare(const std::basic_string<CharT,Traits,Allocator>& s) const noexcept + { + const int rc = Traits::compare(data_, s.data(), (std::min)(length_, s.length())); + return rc != 0 ? rc : (length_ == s.length() ? 0 : length_ < s.length() ? -1 : 1); + } + + size_type find(basic_string_view s, size_type pos = 0) const noexcept + { + if (pos > length_) + { + return npos; + } + if (s.length_ == 0) + { + return pos; + } + const_iterator it = std::search(cbegin() + pos, cend(), + s.cbegin(), s.cend(), Traits::eq); + return it == cend() ? npos : std::distance(cbegin(), it); + } + size_type find(CharT ch, size_type pos = 0) const noexcept + { + return find(basic_string_view(&ch, 1), pos); + } + size_type find(const CharT* s, size_type pos, size_type n) const noexcept + { + return find(basic_string_view(s, n), pos); + } + size_type find(const CharT* s, size_type pos = 0) const noexcept + { + return find(basic_string_view(s), pos); + } + + size_type rfind(basic_string_view s, size_type pos = npos) const noexcept + { + if (length_ < s.length_) + { + return npos; + } + if (pos > length_ - s.length_) + { + pos = length_ - s.length_; + } + if (s.length_ == 0) + { + return pos; + } + for (const CharT* p = data_ + pos; true; --p) + { + if (Traits::compare(p, s.data_, s.length_) == 0) + { + return p - data_; + } + if (p == data_) + { + return npos; + } + }; + } + size_type rfind(CharT ch, size_type pos = npos) const noexcept + { + return rfind(basic_string_view(&ch, 1), pos); + } + size_type rfind(const CharT* s, size_type pos, size_type n) const noexcept + { + return rfind(basic_string_view(s, n), pos); + } + size_type rfind(const CharT* s, size_type pos = npos) const noexcept + { + return rfind(basic_string_view(s), pos); + } + + size_type find_first_of(basic_string_view s, size_type pos = 0) const noexcept + { + if (pos >= length_ || s.length_ == 0) + { + return npos; + } + const_iterator it = std::find_first_of + (cbegin() + pos, cend(), s.cbegin(), s.cend(), Traits::eq); + return it == cend() ? npos : std::distance (cbegin(), it); + } + size_type find_first_of(CharT ch, size_type pos = 0) const noexcept + { + return find_first_of(basic_string_view(&ch, 1), pos); + } + size_type find_first_of(const CharT* s, size_type pos, size_type n) const noexcept + { + return find_first_of(basic_string_view(s, n), pos); + } + size_type find_first_of(const CharT* s, size_type pos = 0) const noexcept + { + return find_first_of(basic_string_view(s), pos); + } + + size_type find_last_of(basic_string_view s, size_type pos = npos) const noexcept + { + if (s.length_ == 0) + { + return npos; + } + if (pos >= length_) + { + pos = 0; + } + else + { + pos = length_ - (pos+1); + } + const_reverse_iterator it = std::find_first_of + (crbegin() + pos, crend(), s.cbegin(), s.cend(), Traits::eq); + return it == crend() ? npos : (length_ - 1 - std::distance(crbegin(), it)); + } + size_type find_last_of(CharT ch, size_type pos = npos) const noexcept + { + return find_last_of(basic_string_view(&ch, 1), pos); + } + size_type find_last_of(const CharT* s, size_type pos, size_type n) const noexcept + { + return find_last_of(basic_string_view(s, n), pos); + } + size_type find_last_of(const CharT* s, size_type pos = npos) const noexcept + { + return find_last_of(basic_string_view(s), pos); + } + + size_type find_first_not_of(basic_string_view s, size_type pos = 0) const noexcept + { + if (pos >= length_) + return npos; + if (s.length_ == 0) + return pos; + + const_iterator it = cend(); + for (auto p = cbegin()+pos; p != cend(); ++p) + { + if (Traits::find(s.data_, s.length_, *p) == 0) + { + it = p; + break; + } + } + return it == cend() ? npos : std::distance (cbegin(), it); + } + size_type find_first_not_of(CharT ch, size_type pos = 0) const noexcept + { + return find_first_not_of(basic_string_view(&ch, 1), pos); + } + size_type find_first_not_of(const CharT* s, size_type pos, size_type n) const noexcept + { + return find_first_not_of(basic_string_view(s, n), pos); + } + size_type find_first_not_of(const CharT* s, size_type pos = 0) const noexcept + { + return find_first_not_of(basic_string_view(s), pos); + } + + size_type find_last_not_of(basic_string_view s, size_type pos = npos) const noexcept + { + if (pos >= length_) + { + pos = length_ - 1; + } + if (s.length_ == 0) + { + return pos; + } + pos = length_ - (pos+1); + + const_iterator it = crend(); + for (auto p = crbegin()+pos; p != crend(); ++p) + { + if (Traits::find(s.data_, s.length_, *p) == 0) + { + it = p; + break; + } + } + return it == crend() ? npos : (length_ - 1 - std::distance(crbegin(), it)); + } + size_type find_last_not_of(CharT ch, size_type pos = npos) const noexcept + { + return find_last_not_of(basic_string_view(&ch, 1), pos); + } + size_type find_last_not_of(const CharT* s, size_type pos, size_type n) const noexcept + { + return find_last_not_of(basic_string_view(s, n), pos); + } + size_type find_last_not_of(const CharT* s, size_type pos = npos) const noexcept + { + return find_last_not_of(basic_string_view(s), pos); + } + + friend std::basic_ostream<CharT>& operator<<(std::basic_ostream<CharT>& os, const basic_string_view& sv) + { + os.write(sv.data_,sv.length_); + return os; + } + }; + + // == + template<class CharT,class Traits> + bool operator==(const basic_string_view<CharT,Traits>& lhs, + const basic_string_view<CharT,Traits>& rhs) noexcept + { + return lhs.compare(rhs) == 0; + } + template<class CharT,class Traits,class Allocator> + bool operator==(const basic_string_view<CharT,Traits>& lhs, + const std::basic_string<CharT,Traits,Allocator>& rhs) noexcept + { + return lhs.compare(rhs) == 0; + } + template<class CharT,class Traits,class Allocator> + bool operator==(const std::basic_string<CharT,Traits,Allocator>& lhs, + const basic_string_view<CharT,Traits>& rhs) noexcept + { + return rhs.compare(lhs) == 0; + } + template<class CharT,class Traits> + bool operator==(const basic_string_view<CharT,Traits>& lhs, + const CharT* rhs) noexcept + { + return lhs.compare(rhs) == 0; + } + template<class CharT,class Traits> + bool operator==(const CharT* lhs, + const basic_string_view<CharT,Traits>& rhs) noexcept + { + return rhs.compare(lhs) == 0; + } + + // != + template<class CharT,class Traits> + bool operator!=(const basic_string_view<CharT,Traits>& lhs, + const basic_string_view<CharT,Traits>& rhs) noexcept + { + return lhs.compare(rhs) != 0; + } + template<class CharT,class Traits,class Allocator> + bool operator!=(const basic_string_view<CharT,Traits>& lhs, + const std::basic_string<CharT,Traits,Allocator>& rhs) noexcept + { + return lhs.compare(rhs) != 0; + } + template<class CharT,class Traits,class Allocator> + bool operator!=(const std::basic_string<CharT,Traits,Allocator>& lhs, + const basic_string_view<CharT,Traits>& rhs) noexcept + { + return rhs.compare(lhs) != 0; + } + template<class CharT,class Traits> + bool operator!=(const basic_string_view<CharT,Traits>& lhs, + const CharT* rhs) noexcept + { + return lhs.compare(rhs) != 0; + } + template<class CharT,class Traits> + bool operator!=(const CharT* lhs, + const basic_string_view<CharT,Traits>& rhs) noexcept + { + return rhs.compare(lhs) != 0; + } + + // <= + template<class CharT,class Traits> + bool operator<=(const basic_string_view<CharT,Traits>& lhs, + const basic_string_view<CharT,Traits>& rhs) noexcept + { + return lhs.compare(rhs) <= 0; + } + template<class CharT,class Traits,class Allocator> + bool operator<=(const basic_string_view<CharT,Traits>& lhs, + const std::basic_string<CharT,Traits,Allocator>& rhs) noexcept + { + return lhs.compare(rhs) <= 0; + } + template<class CharT,class Traits,class Allocator> + bool operator<=(const std::basic_string<CharT,Traits,Allocator>& lhs, + const basic_string_view<CharT,Traits>& rhs) noexcept + { + return rhs.compare(lhs) >= 0; + } + + // < + template<class CharT,class Traits> + bool operator<(const basic_string_view<CharT,Traits>& lhs, + const basic_string_view<CharT,Traits>& rhs) noexcept + { + return lhs.compare(rhs) < 0; + } + template<class CharT,class Traits,class Allocator> + bool operator<(const basic_string_view<CharT,Traits>& lhs, + const std::basic_string<CharT,Traits,Allocator>& rhs) noexcept + { + return lhs.compare(rhs) < 0; + } + template<class CharT,class Traits,class Allocator> + bool operator<(const std::basic_string<CharT,Traits,Allocator>& lhs, + const basic_string_view<CharT,Traits>& rhs) noexcept + { + return rhs.compare(lhs) > 0; + } + + // >= + template<class CharT,class Traits> + bool operator>=(const basic_string_view<CharT,Traits>& lhs, + const basic_string_view<CharT,Traits>& rhs) noexcept + { + return lhs.compare(rhs) >= 0; + } + template<class CharT,class Traits,class Allocator> + bool operator>=(const basic_string_view<CharT,Traits>& lhs, + const std::basic_string<CharT,Traits,Allocator>& rhs) noexcept + { + return lhs.compare(rhs) >= 0; + } + template<class CharT,class Traits,class Allocator> + bool operator>=(const std::basic_string<CharT,Traits,Allocator>& lhs, + const basic_string_view<CharT,Traits>& rhs) noexcept + { + return rhs.compare(lhs) <= 0; + } + + // > + template<class CharT,class Traits> + bool operator>(const basic_string_view<CharT,Traits>& lhs, + const basic_string_view<CharT,Traits>& rhs) noexcept + { + return lhs.compare(rhs) > 0; + } + template<class CharT,class Traits,class Allocator> + bool operator>(const basic_string_view<CharT,Traits>& lhs, + const std::basic_string<CharT,Traits,Allocator>& rhs) noexcept + { + return lhs.compare(rhs) > 0; + } + template<class CharT,class Traits,class Allocator> + bool operator>(const std::basic_string<CharT,Traits,Allocator>& lhs, + const basic_string_view<CharT,Traits>& rhs) noexcept + { + return rhs.compare(lhs) < 0; + } + +} // namespace detail +} // namespace jsoncons + +#endif |