// Copyright 2016 Glyn Matthews. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef NETWORK_STRING_VIEW_INC #define NETWORK_STRING_VIEW_INC /** * \file * \brief Contains an implementation of C++17 string_view (n3921). */ #include #include #include #include #include namespace network { /** * \class basic_string_view string_view.hpp network/uri/string_view.hpp * \brief An implementation of C++17 string_view (n3921) */ template > class basic_string_view { public: typedef traits traits_type; typedef charT value_type; typedef charT *pointer; typedef const charT *const_pointer; typedef charT &reference; typedef const charT &const_reference; typedef const charT *const_iterator; typedef const_iterator iterator; typedef std::reverse_iterator const_reverse_iterator; typedef const_reverse_iterator reverse_iterator; typedef std::size_t size_type; typedef std::ptrdiff_t difference_type; static constexpr size_type npos = size_type(-1); /** * \brief Constructor. */ constexpr basic_string_view() noexcept : data_(nullptr), size_(0) {} /** * \brief Copy constructor. */ constexpr basic_string_view(const basic_string_view &) noexcept = default; /** * \brief Assignment operator. */ basic_string_view &operator=(const basic_string_view &) noexcept = default; /** * \brief Constructor. */ template basic_string_view( const std::basic_string &str) noexcept : data_(str.data()), size_(str.size()) {} /** * \brief Constructor. */ constexpr basic_string_view(const charT *str) : data_(str), size_(traits::length(str)) {} /** * \brief Constructor. */ constexpr basic_string_view(const charT *str, size_type len) : data_(str), size_(len) {} constexpr const_iterator begin() const noexcept { return data_; } constexpr const_iterator end() const noexcept { return data_ + size_; } constexpr const_iterator cbegin() const noexcept { return begin(); } constexpr const_iterator cend() const noexcept { return end(); } 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 rbegin(); } const_reverse_iterator crend() const noexcept { return rend(); } constexpr size_type size() const noexcept { return size_; } constexpr size_type length() const noexcept { return size_; } constexpr size_type max_size() const noexcept { return size_; } constexpr bool empty() const noexcept { return size_ == 0; } constexpr const_reference operator[](size_type pos) const { return data_[pos]; } const_reference at(size_type pos) const { if (pos >= size_) { throw std::out_of_range("Index out of range."); } return data_[pos]; } const_reference front() const { return *begin(); } const_reference back() const { auto last = (end()) - 1; return *last; } constexpr const_pointer data() const noexcept { return data_; } void clear() noexcept { data_ = nullptr; size_ = 0; } void remove_prefix(size_type n) { data_ += n; size_ -= n; } void remove_suffix(size_type n) { size_ -= n; } void swap(basic_string_view &s) noexcept { std::swap(data_, s.data_); std::swap(size_, s.size_); } template explicit operator std::basic_string() const { return to_string(); } template > std::basic_string to_string( const Allocator &a = Allocator()) const { return std::basic_string(begin(), end(), a); } size_type copy(charT *s, size_type n, size_type pos = 0) const { size_type rlen = std::min(n, size() - pos); std::copy_n(begin() + pos, rlen, s); return rlen; } constexpr basic_string_view substr(size_type pos = 0, size_type n = npos) const { return basic_string_view(data() + pos, std::min(n, size() - pos)); } constexpr int compare(basic_string_view s) const noexcept { return size() == s.size() ? traits::compare(data(), s.data(), size()) : (size() < s.size() ? (traits::compare(data(), s.data(), size()) > 0 ? 1 : -1) : (traits::compare(data(), s.data(), size()) < 0 ? -1 : 1)); } 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(const charT *s) const { return compare(basic_string_view(s)); } constexpr int compare(size_type pos1, size_type n1, const charT *s) const { return substr(pos1, n1).compare(basic_string_view(s)); } constexpr int compare(size_type pos1, size_type n1, const charT *s, size_type n2) const { return substr(pos1, n1).compare(basic_string_view(s, n2)); } private: const_pointer data_; size_type size_; }; /** * \brief Equality operator. * \returns lhs.compare(rhs) == 0. */ template constexpr bool operator==(basic_string_view lhs, basic_string_view rhs) noexcept { return lhs.compare(rhs) == 0; } /** * \brief Inequality operator. * \returns !(lhs == rhs). */ template constexpr bool operator!=(basic_string_view lhs, basic_string_view rhs) noexcept { return !(lhs == rhs); } /** * \brief Comparison operator. * \returns lhs.compare(rhs) < 0. */ template constexpr bool operator<(basic_string_view lhs, basic_string_view rhs) noexcept { return lhs.compare(rhs) < 0; } /** * \brief Comparison operator. * \returns rhs < lhs. */ template constexpr bool operator>(basic_string_view lhs, basic_string_view rhs) noexcept { return rhs < lhs; } /** * \brief Comparison operator. * \returns !(lhs > rhs). */ template constexpr bool operator<=(basic_string_view lhs, basic_string_view rhs) noexcept { return !(lhs > rhs); } /** * \brief Comparison operator. * \returns !(lhs < rhs). */ template constexpr bool operator>=(basic_string_view lhs, basic_string_view rhs) noexcept { return !(lhs < rhs); } /** * \brief Output stream operator. */ template std::basic_ostream &operator<<( std::basic_ostream &os, basic_string_view str) { return os << str.to_string(); } typedef basic_string_view string_view; } // namespace network #endif // NETWORK_STRING_VIEW_INC