aboutsummaryrefslogtreecommitdiff
path: root/include/jsoncons/detail/string_view.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'include/jsoncons/detail/string_view.hpp')
-rw-r--r--include/jsoncons/detail/string_view.hpp537
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