aboutsummaryrefslogtreecommitdiff
path: root/src/deps/skia/include/private/SkTOptional.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/deps/skia/include/private/SkTOptional.h')
-rw-r--r--src/deps/skia/include/private/SkTOptional.h362
1 files changed, 362 insertions, 0 deletions
diff --git a/src/deps/skia/include/private/SkTOptional.h b/src/deps/skia/include/private/SkTOptional.h
new file mode 100644
index 000000000..f610493b0
--- /dev/null
+++ b/src/deps/skia/include/private/SkTOptional.h
@@ -0,0 +1,362 @@
+/*
+ * 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 SkTOptional_DEFINED
+#define SkTOptional_DEFINED
+
+#include "include/core/SkTypes.h"
+
+#include <utility>
+
+namespace skstd {
+
+/**
+ * An empty optional is represented with `nullopt`.
+ */
+struct nullopt_t {
+ struct tag {};
+
+ // nullopt_t must not be default-constructible.
+ explicit constexpr nullopt_t(tag) {}
+};
+
+static constexpr nullopt_t nullopt{nullopt_t::tag{}};
+
+/**
+ * Simple drop-in replacement for std::optional until we move to C++17. This does not have all of
+ * std::optional's capabilities, but it covers our needs for the time being.
+ */
+template<typename T>
+class optional {
+public:
+ optional(const T& value)
+ : fHasValue(true) {
+ new(&fPayload.fValue) T(value);
+ }
+
+ optional(T&& value)
+ : fHasValue(true) {
+ new(&fPayload.fValue) T(std::move(value));
+ }
+
+ optional() {}
+
+ optional(const optional& other) {
+ *this = other;
+ }
+
+ // Construction with nullopt is the same as default construction.
+ optional(nullopt_t) : optional() {}
+
+ // We need a non-const copy constructor because otherwise optional(nonConstSrc) isn't an exact
+ // match for the copy constructor, and we'd end up invoking the Args&&... template by mistake.
+ optional(optional& other) {
+ *this = other;
+ }
+
+ optional(optional&& other) {
+ *this = std::move(other);
+ }
+
+ template<typename... Args>
+ optional(Args&&... args) {
+ fHasValue = true;
+ new(&fPayload.fValue) T(std::forward<Args>(args)...);
+ }
+
+ ~optional() {
+ this->reset();
+ }
+
+ optional& operator=(const optional& other) {
+ if (this != &other) {
+ if (fHasValue) {
+ if (other.fHasValue) {
+ fPayload.fValue = other.fPayload.fValue;
+ } else {
+ this->reset();
+ }
+ } else {
+ if (other.fHasValue) {
+ fHasValue = true;
+ new (&fPayload.fValue) T(other.fPayload.fValue);
+ } else {
+ // do nothing, no value on either side
+ }
+ }
+ }
+ return *this;
+ }
+
+ optional& operator=(optional&& other) {
+ if (this != &other) {
+ if (fHasValue) {
+ if (other.fHasValue) {
+ fPayload.fValue = std::move(other.fPayload.fValue);
+ } else {
+ this->reset();
+ }
+ } else {
+ if (other.fHasValue) {
+ fHasValue = true;
+ new (&fPayload.fValue) T(std::move(other.fPayload.fValue));
+ } else {
+ // do nothing, no value on either side
+ }
+ }
+ }
+ return *this;
+ }
+
+ template<typename... Args>
+ optional& emplace(Args&&... args) {
+ this->reset();
+ fHasValue = true;
+ new(&fPayload.fValue) T(std::forward<Args>(args)...);
+ return *this;
+ }
+
+ template<typename U, typename... Args>
+ optional& emplace(std::initializer_list<U> il, Args&&... args) {
+ this->reset();
+ fHasValue = true;
+ new(&fPayload.fValue) T(il, std::forward<Args>(args)...);
+ return *this;
+ }
+
+ // Assignment to nullopt is the same as reset().
+ optional& operator=(nullopt_t) {
+ this->reset();
+ return *this;
+ }
+
+ T& operator*() & {
+ SkASSERT(fHasValue);
+ return fPayload.fValue;
+ }
+
+ const T& operator*() const& {
+ SkASSERT(fHasValue);
+ return fPayload.fValue;
+ }
+
+ T&& operator*() && {
+ SkASSERT(fHasValue);
+ return std::move(fPayload.fValue);
+ }
+
+ const T&& operator*() const&& {
+ SkASSERT(fHasValue);
+ return std::move(fPayload.fValue);
+ }
+
+ const T& value() const& {
+ SkASSERT_RELEASE(fHasValue);
+ return **this;
+ }
+
+ T& value() & {
+ SkASSERT_RELEASE(fHasValue);
+ return **this;
+ }
+
+ const T&& value() const&& {
+ SkASSERT_RELEASE(fHasValue);
+ return std::move(**this);
+ }
+
+ T&& value() && {
+ SkASSERT_RELEASE(fHasValue);
+ return std::move(**this);
+ }
+
+ T* operator->() {
+ return &**this;
+ }
+
+ const T* operator->() const {
+ return &**this;
+ }
+
+ template<typename U>
+ T value_or(U&& value) const& {
+ return this->has_value() ? **this : static_cast<T>(std::forward<U>(value));
+ }
+
+ template<typename U>
+ T value_or(U&& value) && {
+ return this->has_value() ? std::move(**this) : static_cast<T>(std::forward<U>(value));
+ }
+
+ bool has_value() const {
+ return fHasValue;
+ }
+
+ explicit operator bool() const {
+ return this->has_value();
+ }
+
+ void reset() {
+ if (fHasValue) {
+ fPayload.fValue.~T();
+ fHasValue = false;
+ }
+ }
+
+private:
+ union Payload {
+ T fValue;
+
+ Payload() {}
+
+ ~Payload() {}
+ } fPayload;
+
+ bool fHasValue = false;
+};
+
+// Comparison operators for optional x optional
+template <typename T, typename U> bool operator==(const optional<T>& a, const optional<U>& b) {
+ return (a.has_value() != b.has_value()) ? false :
+ !a.has_value() ? true :
+ (*a == *b);
+}
+
+template <typename T, typename U> bool operator!=(const optional<T>& a, const optional<U>& b) {
+ return (a.has_value() != b.has_value()) ? true :
+ !a.has_value() ? false :
+ (*a != *b);
+}
+
+template <typename T, typename U> bool operator<(const optional<T>& a, const optional<U>& b) {
+ return !b.has_value() ? false :
+ !a.has_value() ? true :
+ (*a < *b);
+}
+
+template <typename T, typename U> bool operator<=(const optional<T>& a, const optional<U>& b) {
+ return !a.has_value() ? true :
+ !b.has_value() ? false :
+ (*a <= *b);
+}
+
+template <typename T, typename U> bool operator>(const optional<T>& a, const optional<U>& b) {
+ return !a.has_value() ? false :
+ !b.has_value() ? true :
+ (*a > *b);
+}
+
+template <typename T, typename U> bool operator>=(const optional<T>& a, const optional<U>& b) {
+ return !b.has_value() ? true :
+ !a.has_value() ? false :
+ (*a >= *b);
+}
+
+// Comparison operators for optional x nullopt
+template <typename T> bool operator==(const optional<T>& a, nullopt_t) {
+ return !a.has_value();
+}
+
+template <typename T> bool operator!=(const optional<T>& a, nullopt_t) {
+ return a.has_value();
+}
+
+template <typename T> bool operator<(const optional<T>&, nullopt_t) {
+ return false;
+}
+
+template <typename T> bool operator<=(const optional<T>& a, nullopt_t) {
+ return !a.has_value();
+}
+
+template <typename T> bool operator>(const optional<T>& a, nullopt_t) {
+ return a.has_value();
+}
+
+template <typename T>
+bool operator>=(const optional<T>&, nullopt_t) {
+ return true;
+}
+
+// Comparison operators for nullopt x optional
+template <typename U> bool operator==(nullopt_t, const optional<U>& b) {
+ return !b.has_value();
+}
+
+template <typename U> bool operator!=(nullopt_t, const optional<U>& b) {
+ return b.has_value();
+}
+
+template <typename U> bool operator<(nullopt_t, const optional<U>& b) {
+ return b.has_value();
+}
+
+template <typename U> bool operator<=(nullopt_t, const optional<U>&) {
+ return true;
+}
+
+template <typename U> bool operator>(nullopt_t, const optional<U>&) {
+ return false;
+}
+
+template <typename U> bool operator>=(nullopt_t, const optional<U>& b) {
+ return !b.has_value();
+}
+
+// Comparison operators for optional x value
+template <typename T, typename U> bool operator==(const optional<T>& a, const U& b) {
+ return a.has_value() && (*a == b);
+}
+
+template <typename T, typename U> bool operator!=(const optional<T>& a, const U& b) {
+ return !a.has_value() || (*a != b);
+}
+
+template <typename T, typename U> bool operator<(const optional<T>& a, const U& b) {
+ return !a.has_value() || (*a < b);
+}
+
+template <typename T, typename U> bool operator<=(const optional<T>& a, const U& b) {
+ return !a.has_value() || (*a <= b);
+}
+
+template <typename T, typename U> bool operator>(const optional<T>& a, const U& b) {
+ return a.has_value() && (*a > b);
+}
+
+template <typename T, typename U> bool operator>=(const optional<T>& a, const U& b) {
+ return a.has_value() && (*a >= b);
+}
+
+// Comparison operators for value x optional
+template <typename T, typename U> bool operator==(const T& a, const optional<U>& b) {
+ return b.has_value() && (a == *b);
+}
+
+template <typename T, typename U> bool operator!=(const T& a, const optional<U>& b) {
+ return !b.has_value() || (a != *b);
+}
+
+template <typename T, typename U> bool operator<(const T& a, const optional<U>& b) {
+ return b.has_value() && (a < *b);
+}
+
+template <typename T, typename U> bool operator<=(const T& a, const optional<U>& b) {
+ return b.has_value() && (a <= *b);
+}
+
+template <typename T, typename U> bool operator>(const T& a, const optional<U>& b) {
+ return !b.has_value() || (a > *b);
+}
+
+template <typename T, typename U> bool operator>=(const T& a, const optional<U>& b) {
+ return !b.has_value() || (a >= *b);
+}
+
+} // namespace skstd
+
+#endif