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 <algorithm> 12 #include <cstring> 13 #include <string> 14 15 namespace skstd { 16 17 class string_view { 18 public: 19 using value_type = char; 20 using traits_type = std::char_traits<value_type>; 21 using const_pointer = const value_type*; 22 using const_reference = const value_type&; 23 using iterator = const_pointer; 24 using const_iterator = iterator; 25 using size_type = size_t; 26 static constexpr size_type npos = size_type(-1); 27 string_view()28 constexpr string_view() 29 : fData(nullptr) 30 , fLength(0) {} 31 32 constexpr string_view(const string_view&) = default; 33 string_view(const_pointer data,size_type length)34 constexpr string_view(const_pointer data, size_type length) 35 : fData(data) 36 , fLength(length) {} 37 string_view(const_pointer data)38 string_view(const_pointer data) 39 : string_view(data, strlen(data)) {} 40 string_view(const std::string & str)41 string_view(const std::string& str) 42 : string_view(str.data(), str.length()) {} 43 44 constexpr string_view& operator=(const string_view&) = default; 45 begin()46 constexpr iterator begin() const { 47 return fData; 48 } 49 end()50 constexpr iterator end() const { 51 return fData + fLength; 52 } 53 54 constexpr const_reference operator[](size_type idx) const { 55 return fData[idx]; 56 } 57 front()58 constexpr const_reference front() const { 59 return fData[0]; 60 } 61 back()62 constexpr const_reference back() const { 63 return fData[fLength - 1]; 64 } 65 data()66 constexpr const_pointer data() const { 67 return fData; 68 } 69 size()70 constexpr size_type size() const { 71 return fLength; 72 } 73 length()74 constexpr size_type length() const { 75 return fLength; 76 } 77 empty()78 constexpr bool empty() const { 79 return fLength == 0; 80 } 81 starts_with(string_view s)82 constexpr bool starts_with(string_view s) const { 83 if (s.length() > fLength) { 84 return false; 85 } 86 return s.length() == 0 || !memcmp(fData, s.fData, s.length()); 87 } 88 starts_with(value_type c)89 constexpr bool starts_with(value_type c) const { 90 return !this->empty() && this->front() == c; 91 } 92 ends_with(string_view s)93 constexpr bool ends_with(string_view s) const { 94 if (s.length() > fLength) { 95 return false; 96 } 97 return s.length() == 0 || !memcmp(this->end() - s.length(), s.fData, s.length()); 98 } 99 ends_with(value_type c)100 constexpr bool ends_with(value_type c) const { 101 return !this->empty() && this->back() == c; 102 } 103 104 size_type find(string_view needle, size_type pos = 0) const { 105 if (needle.length() == 0) { 106 return 0; 107 } 108 if (this->length() < needle.length()) { 109 return npos; 110 } 111 const char* match = nullptr; 112 const char* start = this->data() + pos; 113 const char* end = start + this->length() - needle.length() + 1; 114 while ((match = (const char*)(memchr(start, needle[0], (size_t)(end - start))))) { 115 if (!memcmp(match, needle.data(), needle.length())) { 116 return (size_type)(match - this->data()); 117 } else { 118 start = match + 1; 119 } 120 } 121 return npos; 122 } 123 contains(string_view needle)124 bool contains(string_view needle) const { 125 return this->find(needle) != npos; 126 } 127 128 constexpr string_view substr(size_type pos = 0, size_type count = npos) const { 129 if (pos > fLength) { 130 return {}; 131 } 132 return string_view{fData + pos, std::min(count, fLength - pos)}; 133 } 134 swap(string_view & other)135 constexpr void swap(string_view& other) { 136 const_pointer tempData = fData; 137 fData = other.fData; 138 other.fData = tempData; 139 140 size_type tempLength = fLength; 141 fLength = other.fLength; 142 other.fLength = tempLength; 143 } 144 remove_prefix(size_type n)145 constexpr void remove_prefix(size_type n) { 146 fData += n; 147 fLength -= n; 148 } 149 remove_suffix(size_type n)150 constexpr void remove_suffix(size_type n) { 151 fLength -= n; 152 } 153 154 private: 155 const_pointer fData; 156 size_type fLength; 157 }; 158 159 bool operator==(string_view left, string_view right); 160 161 bool operator!=(string_view left, string_view right); 162 163 bool operator<(string_view left, string_view right); 164 165 bool operator<=(string_view left, string_view right); 166 167 bool operator>(string_view left, string_view right); 168 169 bool operator>=(string_view left, string_view right); 170 171 } // namespace skstd 172 173 namespace std { 174 template<> struct hash<skstd::string_view> { 175 size_t operator()(const skstd::string_view& s) const { 176 size_t result = 0; 177 for (auto iter = s.begin(); iter != s.end(); ++iter) { 178 result = result * 101 + (size_t) *iter; 179 } 180 return result; 181 } 182 }; 183 } // namespace std 184 185 #endif 186