1 /* 2 * Copyright 2021 Google LLC. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #ifndef SkStringView_DEFINED 9 #define SkStringView_DEFINED 10 11 #include "include/core/SkTypes.h" 12 13 #include <algorithm> 14 #include <cstring> 15 #include <string> 16 17 namespace skstd { 18 19 class string_view { 20 public: 21 using value_type = char; 22 using traits_type = std::char_traits<value_type>; 23 using const_pointer = const value_type*; 24 using const_reference = const value_type&; 25 using iterator = const_pointer; 26 using const_iterator = iterator; 27 using size_type = size_t; 28 static constexpr size_type npos = size_type(-1); 29 string_view()30 constexpr string_view() 31 : fData(nullptr) 32 , fLength(0) {} 33 34 constexpr string_view(const string_view&) = default; 35 string_view(const_pointer data, size_type length)36 constexpr string_view(const_pointer data, size_type length) 37 : fData(data) 38 , fLength(length) {} 39 string_view(const_pointer data)40 string_view(const_pointer data) 41 : string_view(data, strlen(data)) {} 42 string_view(const std::string& str)43 string_view(const std::string& str) 44 : string_view(str.data(), str.length()) {} 45 46 constexpr string_view& operator=(const string_view&) = default; 47 begin() const48 constexpr iterator begin() const { 49 return fData; 50 } 51 end() const52 constexpr iterator end() const { 53 return fData + fLength; 54 } 55 operator [](size_type idx) const56 constexpr const_reference operator[](size_type idx) const { 57 return fData[idx]; 58 } 59 front() const60 constexpr const_reference front() const { 61 return fData[0]; 62 } 63 back() const64 constexpr const_reference back() const { 65 return fData[fLength - 1]; 66 } 67 data() const68 constexpr const_pointer data() const { 69 return fData; 70 } 71 size() const72 constexpr size_type size() const { 73 return fLength; 74 } 75 length() const76 constexpr size_type length() const { 77 return fLength; 78 } 79 empty() const80 constexpr bool empty() const { 81 return fLength == 0; 82 } 83 starts_with(string_view s) const84 constexpr bool starts_with(string_view s) const { 85 if (s.length() > fLength) { 86 return false; 87 } 88 return s.length() == 0 || !memcmp(fData, s.fData, s.length()); 89 } 90 starts_with(value_type c) const91 constexpr bool starts_with(value_type c) const { 92 return !this->empty() && this->front() == c; 93 } 94 ends_with(string_view s) const95 constexpr bool ends_with(string_view s) const { 96 if (s.length() > fLength) { 97 return false; 98 } 99 return s.length() == 0 || !memcmp(this->end() - s.length(), s.fData, s.length()); 100 } 101 ends_with(value_type c) const102 constexpr bool ends_with(value_type c) const { 103 return !this->empty() && this->back() == c; 104 } 105 find(string_view needle, size_type pos = 0) const106 size_type find(string_view needle, size_type pos = 0) const { 107 if (needle.length() == 0) { 108 return 0; 109 } 110 if (this->length() < needle.length()) { 111 return npos; 112 } 113 const char* match = nullptr; 114 const char* start = this->data() + pos; 115 const char* end = start + this->length() - needle.length() + 1; 116 while ((match = (const char*)(memchr(start, needle[0], (size_t)(end - start))))) { 117 if (!memcmp(match, needle.data(), needle.length())) { 118 return (size_type)(match - this->data()); 119 } else { 120 start = match + 1; 121 } 122 } 123 return npos; 124 } 125 contains(string_view needle) const126 bool contains(string_view needle) const { 127 return this->find(needle) != npos; 128 } 129 substr(size_type pos = 0, size_type count = npos) const130 constexpr string_view substr(size_type pos = 0, size_type count = npos) const { 131 if (pos > fLength) { 132 return {}; 133 } 134 return string_view{fData + pos, std::min(count, fLength - pos)}; 135 } 136 swap(string_view& other)137 constexpr void swap(string_view& other) { 138 const_pointer tempData = fData; 139 fData = other.fData; 140 other.fData = tempData; 141 142 size_type tempLength = fLength; 143 fLength = other.fLength; 144 other.fLength = tempLength; 145 } 146 remove_prefix(size_type n)147 constexpr void remove_prefix(size_type n) { 148 fData += n; 149 fLength -= n; 150 } 151 remove_suffix(size_type n)152 constexpr void remove_suffix(size_type n) { 153 fLength -= n; 154 } 155 156 private: 157 const_pointer fData; 158 size_type fLength; 159 }; 160 161 SK_API bool operator==(string_view left, string_view right); 162 163 SK_API bool operator!=(string_view left, string_view right); 164 165 SK_API bool operator<(string_view left, string_view right); 166 167 SK_API bool operator<=(string_view left, string_view right); 168 169 SK_API bool operator>(string_view left, string_view right); 170 171 SK_API bool operator>=(string_view left, string_view right); 172 173 } // namespace skstd 174 175 namespace std { 176 template<> struct hash<skstd::string_view> { operator ()std::hash177 size_t operator()(const skstd::string_view& s) const { 178 size_t result = 0; 179 for (auto iter = s.begin(); iter != s.end(); ++iter) { 180 result = result * 101 + (size_t) *iter; 181 } 182 return result; 183 } 184 }; 185 } // namespace std 186 187 #endif 188