| // -*-c++-*- |
| // vim: set ft=cpp: |
| |
| /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying |
| file Copyright.txt or https://cmake.org/licensing for details. */ |
| #ifndef cm_string_view |
| #define cm_string_view |
| |
| #if __cplusplus >= 201703L || defined(_MSVC_LANG) && _MSVC_LANG >= 201703L |
| # define CMake_HAVE_CXX_STRING_VIEW |
| #endif |
| |
| #ifdef CMake_HAVE_CXX_STRING_VIEW |
| # include <string_view> // IWYU pragma: export |
| namespace cm { |
| using std::string_view; |
| } |
| #else |
| # include <cstddef> |
| # include <functional> |
| # include <iosfwd> |
| # include <iterator> |
| # include <string> |
| |
| namespace cm { |
| |
| class string_view |
| { |
| public: |
| using traits_type = std::string::traits_type; |
| using value_type = char; |
| using pointer = char*; |
| using const_pointer = const char*; |
| using reference = char&; |
| using const_reference = char const&; |
| using const_iterator = const char*; |
| using iterator = const_iterator; |
| using const_reverse_iterator = std::reverse_iterator<const_iterator>; |
| using reverse_iterator = const_reverse_iterator; |
| using size_type = std::string::size_type; |
| using difference_type = std::string::difference_type; |
| |
| static size_type const npos = static_cast<size_type>(-1); |
| |
| string_view() noexcept = default; |
| string_view(string_view const&) noexcept = default; |
| |
| string_view(const char* s, size_t count) noexcept |
| : data_(s) |
| , size_(count) |
| { |
| } |
| |
| string_view(const char* s) noexcept |
| : data_(s) |
| , size_(traits_type::length(s)) |
| { |
| } |
| |
| // C++17 does not define this constructor. Instead it defines |
| // a conversion operator on std::string to create a string_view. |
| // Since this implementation is used in C++11, std::string does |
| // not have that conversion. |
| string_view(std::string const& s) noexcept |
| : data_(s.data()) |
| , size_(s.size()) |
| { |
| } |
| |
| // C++17 does not define this conversion. Instead it defines |
| // a constructor on std::string that can take a string_view. |
| // Since this implementation is used in C++11, std::string does |
| // not have that constructor. |
| explicit operator std::string() const { return std::string(data_, size_); } |
| |
| string_view& operator=(string_view const&) = default; |
| |
| const_iterator begin() const noexcept { return data_; } |
| const_iterator end() const noexcept { return data_ + size_; } |
| const_iterator cbegin() const noexcept { return begin(); } |
| 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(); } |
| |
| const_reference operator[](size_type pos) const noexcept |
| { |
| return data_[pos]; |
| } |
| const_reference at(size_type pos) const; |
| const_reference front() const noexcept { return data_[0]; } |
| const_reference back() const noexcept { return data_[size_ - 1]; } |
| const_pointer data() const noexcept { return data_; } |
| |
| size_type size() const noexcept { return size_; } |
| size_type length() const noexcept { return size_; } |
| size_type max_size() const noexcept { return npos - 1; } |
| bool empty() const noexcept { return size_ == 0; } |
| |
| void remove_prefix(size_type n) noexcept |
| { |
| data_ += n; |
| size_ -= n; |
| } |
| void remove_suffix(size_type n) noexcept { size_ -= n; } |
| void swap(string_view& v) noexcept |
| { |
| string_view tmp = v; |
| v = *this; |
| *this = tmp; |
| } |
| |
| size_type copy(char* dest, size_type count, size_type pos = 0) const; |
| string_view substr(size_type pos = 0, size_type count = npos) const; |
| |
| int compare(string_view v) const noexcept; |
| int compare(size_type pos1, size_type count1, string_view v) const; |
| int compare(size_type pos1, size_type count1, string_view v, size_type pos2, |
| size_type count2) const; |
| int compare(const char* s) const; |
| int compare(size_type pos1, size_type count1, const char* s) const; |
| int compare(size_type pos1, size_type count1, const char* s, |
| size_type count2) const; |
| |
| size_type find(string_view v, size_type pos = 0) const noexcept; |
| size_type find(char c, size_type pos = 0) const noexcept; |
| size_type find(const char* s, size_type pos, size_type count) const; |
| size_type find(const char* s, size_type pos = 0) const; |
| |
| size_type rfind(string_view v, size_type pos = npos) const noexcept; |
| size_type rfind(char c, size_type pos = npos) const noexcept; |
| size_type rfind(const char* s, size_type pos, size_type count) const; |
| size_type rfind(const char* s, size_type pos = npos) const; |
| |
| size_type find_first_of(string_view v, size_type pos = 0) const noexcept; |
| size_type find_first_of(char c, size_type pos = 0) const noexcept; |
| size_type find_first_of(const char* s, size_type pos, size_type count) const; |
| size_type find_first_of(const char* s, size_type pos = 0) const; |
| |
| size_type find_last_of(string_view v, size_type pos = npos) const noexcept; |
| size_type find_last_of(char c, size_type pos = npos) const noexcept; |
| size_type find_last_of(const char* s, size_type pos, size_type count) const; |
| size_type find_last_of(const char* s, size_type pos = npos) const; |
| |
| size_type find_first_not_of(string_view v, size_type pos = 0) const noexcept; |
| size_type find_first_not_of(char c, size_type pos = 0) const noexcept; |
| size_type find_first_not_of(const char* s, size_type pos, |
| size_type count) const; |
| size_type find_first_not_of(const char* s, size_type pos = 0) const; |
| |
| size_type find_last_not_of(string_view v, size_type pos = npos) const |
| noexcept; |
| size_type find_last_not_of(char c, size_type pos = npos) const noexcept; |
| size_type find_last_not_of(const char* s, size_type pos, |
| size_type count) const; |
| size_type find_last_not_of(const char* s, size_type pos = npos) const; |
| |
| private: |
| const char* data_ = nullptr; |
| size_type size_ = 0; |
| }; |
| |
| std::ostream& operator<<(std::ostream& o, string_view v); |
| |
| std::string& operator+=(std::string& s, string_view v); |
| |
| inline bool operator==(string_view l, string_view r) noexcept |
| { |
| return l.compare(r) == 0; |
| } |
| |
| inline bool operator!=(string_view l, string_view r) noexcept |
| { |
| return l.compare(r) != 0; |
| } |
| |
| inline bool operator<(string_view l, string_view r) noexcept |
| { |
| return l.compare(r) < 0; |
| } |
| |
| inline bool operator<=(string_view l, string_view r) noexcept |
| { |
| return l.compare(r) <= 0; |
| } |
| |
| inline bool operator>(string_view l, string_view r) noexcept |
| { |
| return l.compare(r) > 0; |
| } |
| |
| inline bool operator>=(string_view l, string_view r) noexcept |
| { |
| return l.compare(r) >= 0; |
| } |
| } |
| |
| namespace std { |
| |
| template <> |
| struct hash<cm::string_view> |
| { |
| using argument_type = cm::string_view; |
| using result_type = size_t; |
| result_type operator()(argument_type const& s) const noexcept; |
| }; |
| } |
| |
| #endif |
| #endif |