2021-06-07 20:09:59 +00:00
|
|
|
/*
|
|
|
|
* 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
|
|
|
|
|
2022-01-27 20:35:59 +00:00
|
|
|
#include <algorithm>
|
|
|
|
#include <cstring>
|
|
|
|
#include <string>
|
2021-06-07 20:09:59 +00:00
|
|
|
|
|
|
|
namespace skstd {
|
|
|
|
|
2022-01-27 20:35:59 +00:00
|
|
|
class string_view {
|
|
|
|
public:
|
|
|
|
using value_type = char;
|
|
|
|
using traits_type = std::char_traits<value_type>;
|
|
|
|
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;
|
|
|
|
static constexpr size_type npos = size_type(-1);
|
2021-06-07 20:09:59 +00:00
|
|
|
|
2022-01-27 20:35:59 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_type find(string_view needle, size_type pos = 0) const {
|
|
|
|
if (needle.length() == 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (this->length() < needle.length()) {
|
|
|
|
return npos;
|
|
|
|
}
|
|
|
|
const char* match = nullptr;
|
|
|
|
const char* start = this->data() + pos;
|
|
|
|
const char* end = start + this->length() - needle.length() + 1;
|
|
|
|
while ((match = (const char*)(memchr(start, needle[0], (size_t)(end - start))))) {
|
|
|
|
if (!memcmp(match, needle.data(), needle.length())) {
|
|
|
|
return (size_type)(match - this->data());
|
|
|
|
} else {
|
|
|
|
start = match + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return npos;
|
2021-09-07 17:49:07 +00:00
|
|
|
}
|
|
|
|
|
2022-01-27 20:35:59 +00:00
|
|
|
bool contains(string_view needle) const {
|
|
|
|
return this->find(needle) != npos;
|
|
|
|
}
|
2021-09-07 17:49:07 +00:00
|
|
|
|
2022-01-27 20:35:59 +00:00
|
|
|
constexpr string_view substr(size_type pos = 0, size_type count = npos) const {
|
|
|
|
if (pos > fLength) {
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
return string_view{fData + pos, std::min(count, fLength - pos)};
|
2021-09-01 18:57:44 +00:00
|
|
|
}
|
|
|
|
|
2022-01-27 20:35:59 +00:00
|
|
|
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);
|
2021-06-07 20:09:59 +00:00
|
|
|
|
2022-01-27 20:35:59 +00:00
|
|
|
} // namespace skstd
|
2021-06-07 20:09:59 +00:00
|
|
|
|
2022-01-27 20:35:59 +00:00
|
|
|
namespace std {
|
|
|
|
template<> struct hash<skstd::string_view> {
|
|
|
|
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
|
2021-06-10 15:21:59 +00:00
|
|
|
|
2021-06-07 20:09:59 +00:00
|
|
|
#endif
|