skia2/include/core/SkStringView.h
Ethan Nicholas 9173b3ff9a Fixed constructor signature in skstd::string_view
Prior to this change, creating a string_view from a string was broken.
We would copy the string, take a reference to the copy's characters,
and then drop the copy on the floor, causing a use-after-free.

Change-Id: Ieef05c2df5d64c7993a572f490c7096d02bd22fa
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/417096
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
Commit-Queue: John Stiles <johnstiles@google.com>
Auto-Submit: Ethan Nicholas <ethannicholas@google.com>
Reviewed-by: John Stiles <johnstiles@google.com>
2021-06-09 16:27:19 +00:00

132 lines
3.0 KiB
C++

/*
* 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
#include <cstring>
#include <string>
namespace skstd {
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;
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;
}
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;
}
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);
} // namespace skstd
#endif