• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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