/* * Copyright 2021 Google LLC. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef SkStringView_DEFINED #define SkStringView_DEFINED #include #include namespace skstd { class string_view { public: using value_type = char; using traits_type = std::char_traits; using const_pointer = const value_type*; using const_reference = const value_type&; using iterator = const_pointer; using const_iterator = iterator; using size_type = size_t; constexpr string_view() : fData(nullptr) , fLength(0) {} constexpr string_view(const string_view&) = default; constexpr string_view(const_pointer data, size_type length) : fData(data) , fLength(length) {} string_view(const_pointer data) : string_view(data, strlen(data)) {} string_view(const std::string& str) : string_view(str.data(), str.length()) {} constexpr string_view& operator=(const string_view&) = default; constexpr iterator begin() const { return fData; } constexpr iterator end() const { return fData + fLength; } constexpr const_reference operator[](size_type idx) const { return fData[idx]; } constexpr const_reference front() const { return fData[0]; } constexpr const_reference back() const { return fData[fLength - 1]; } constexpr const_pointer data() const { return fData; } constexpr size_type size() const { return fLength; } constexpr size_type length() const { return fLength; } constexpr bool empty() const { return fLength == 0; } constexpr bool starts_with(string_view s) const { if (s.length() > fLength) { return false; } return s.length() == 0 || !memcmp(fData, s.fData, s.length()); } constexpr bool starts_with(value_type c) const { return !this->empty() && this->front() == c; } constexpr bool ends_with(string_view s) const { if (s.length() > fLength) { return false; } return s.length() == 0 || !memcmp(this->end() - s.length(), s.fData, s.length()); } constexpr bool ends_with(value_type c) const { return !this->empty() && this->back() == c; } constexpr void swap(string_view& other) { const_pointer tempData = fData; fData = other.fData; other.fData = tempData; size_type tempLength = fLength; fLength = other.fLength; other.fLength = tempLength; } constexpr void remove_prefix(size_type n) { fData += n; fLength -= n; } constexpr void remove_suffix(size_type n) { fLength -= n; } private: const_pointer fData; size_type fLength; }; bool operator==(string_view left, string_view right); bool operator!=(string_view left, string_view right); bool operator<(string_view left, string_view right); bool operator<=(string_view left, string_view right); bool operator>(string_view left, string_view right); bool operator>=(string_view left, string_view right); } // namespace skstd namespace std { template<> struct hash { size_t operator()(const skstd::string_view& s) const { size_t result = 0; for (auto iter = s.begin(); iter != s.end(); ++iter) { result = result * 101 + (size_t) *iter; } return result; } }; } // namespace std #endif