// -*-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 // IWYU pragma: export namespace cm { using std::string_view; } #else # include # include # include # include # include 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; 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(-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 { using argument_type = cm::string_view; using result_type = size_t; result_type operator()(argument_type const& s) const noexcept; }; } #endif #endif