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