From 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c Mon Sep 17 00:00:00 2001 From: Lorry Tar Creator Date: Tue, 27 Jun 2017 06:07:23 +0000 Subject: webkitgtk-2.16.5 --- Source/WTF/wtf/Expected.h | 456 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 456 insertions(+) create mode 100644 Source/WTF/wtf/Expected.h (limited to 'Source/WTF/wtf/Expected.h') diff --git a/Source/WTF/wtf/Expected.h b/Source/WTF/wtf/Expected.h new file mode 100644 index 000000000..39c7e876b --- /dev/null +++ b/Source/WTF/wtf/Expected.h @@ -0,0 +1,456 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +// WTF::Expected is based on std::expected, as described here: http://wg21.link/p0323r1 +// The specification expects to throw. This implementation doesn't support exceptions, uses RELEASE_ASSERT instead. + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace WTF { + +template +class UnexpectedType { +public: + UnexpectedType() = delete; + constexpr explicit UnexpectedType(const E& e) : val(e) { } + constexpr explicit UnexpectedType(E&& e) : val(std::forward(e)) { } + constexpr const E& value() const& { return val; } + RELAXED_CONSTEXPR E& value() & { return val; } + RELAXED_CONSTEXPR E&& value() && { return WTFMove(val); } + +private: + E val; +}; + +template constexpr bool operator==(const UnexpectedType& lhs, const UnexpectedType& rhs) { return lhs.value() == rhs.value(); } +template constexpr bool operator!=(const UnexpectedType& lhs, const UnexpectedType& rhs) { return lhs.value() != rhs.value(); } +template constexpr bool operator<(const UnexpectedType& lhs, const UnexpectedType& rhs) { return lhs.value() < rhs.value(); } +template constexpr bool operator>(const UnexpectedType& lhs, const UnexpectedType& rhs) { return lhs.value() > rhs.value(); } +template constexpr bool operator<=(const UnexpectedType& lhs, const UnexpectedType& rhs) { return lhs.value() <= rhs.value(); } +template constexpr bool operator>=(const UnexpectedType& lhs, const UnexpectedType& rhs) { return lhs.value() >= rhs.value(); } + +template constexpr UnexpectedType> makeUnexpected(E&& v) { return UnexpectedType::type>(std::forward(v)); } + +struct UnexpectTag { + UnexpectTag() = delete; +}; +constexpr UnexpectTag Unexpect { }; + +namespace ExpectedDetail { + +// Invoked where std::Expected would instead throw. +inline NO_RETURN_DUE_TO_CRASH void Throw() { RELEASE_ASSERT_NOT_REACHED(); } + +static constexpr enum class ValueTagType { } ValueTag { }; +static constexpr enum class ErrorTagType { } ErrorTag { }; + +template::value>* = nullptr> void destroy(T&) { } +template::value && (std::is_class::value || std::is_union::value)>* = nullptr> void destroy(T& t) { t.~T(); } + +template +union ConstexprStorage { + typedef T ValueType; + typedef E ErrorType; + char dummy; + ValueType val; + ErrorType err; + constexpr ConstexprStorage() : dummy() { } + constexpr ConstexprStorage(ValueTagType) : val() { } + constexpr ConstexprStorage(ErrorTagType) : err() { } + constexpr ConstexprStorage(ValueTagType, const ValueType& v) : val(v) { } + constexpr ConstexprStorage(ErrorTagType, const ErrorType& e) : err(e) { } + ~ConstexprStorage() = default; +}; + +template +union Storage { + typedef T ValueType; + typedef E ErrorType; + char dummy; + ValueType val; + ErrorType err; + constexpr Storage() : dummy() { } + constexpr Storage(ValueTagType) : val() { } + constexpr Storage(ErrorTagType) : err() { } + constexpr Storage(ValueTagType, const ValueType& val) : val(val) { } + constexpr Storage(ValueTagType, ValueType&& val) : val(std::forward(val)) { } + constexpr Storage(ErrorTagType, const ErrorType& err) : err(err) { } + constexpr Storage(ErrorTagType, ErrorType&& err) : err(std::forward(err)) { } + ~Storage() { } +}; + +template +union ConstexprStorage { + typedef void ValueType; + typedef E ErrorType; + char dummy; + ErrorType err; + constexpr ConstexprStorage() : dummy() { } + constexpr ConstexprStorage(ValueTagType) : dummy() { } + constexpr ConstexprStorage(ErrorTagType) : err() { } + constexpr ConstexprStorage(ErrorTagType, const ErrorType& e) : err(e) { } + ~ConstexprStorage() = default; +}; + +template +union Storage { + typedef void ValueType; + typedef E ErrorType; + char dummy; + ErrorType err; + constexpr Storage() : dummy() { } + constexpr Storage(ValueTagType) : dummy() { } + constexpr Storage(ErrorTagType) : err() { } + constexpr Storage(ErrorTagType, const ErrorType& err) : err(err) { } + constexpr Storage(ErrorTagType, ErrorType&& err) : err(std::forward(err)) { } + ~Storage() { } +}; + +template +struct ConstexprBase { + typedef T ValueType; + typedef E ErrorType; + ConstexprStorage s; + bool has; + constexpr ConstexprBase() : s(), has(true) { } + constexpr ConstexprBase(ValueTagType tag) : s(tag), has(true) { } + constexpr ConstexprBase(ErrorTagType tag) : s(tag), has(false) { } + constexpr ConstexprBase(ValueTagType tag, const ValueType& val) : s(tag, val), has(true) { } + constexpr ConstexprBase(ErrorTagType tag, const ErrorType& err) : s(tag, err), has(false) { } + ~ConstexprBase() = default; +}; + +template +struct Base { + typedef T ValueType; + typedef E ErrorType; + Storage s; + bool has; + constexpr Base() : s(), has(true) { } + constexpr Base(ValueTagType tag) : s(tag), has(true) { } + constexpr Base(ErrorTagType tag) : s(tag), has(false) { } + constexpr Base(ValueTagType tag, const ValueType& val) : s(tag, val), has(true) { } + constexpr Base(ValueTagType tag, ValueType&& val) : s(tag, std::forward(val)), has(true) { } + constexpr Base(ErrorTagType tag, const ErrorType& err) : s(tag, err), has(false) { } + constexpr Base(ErrorTagType tag, ErrorType&& err) : s(tag, std::forward(err)), has(false) { } + Base(const Base& o) + : has(o.has) + { + if (has) + ::new (&s.val) ValueType(o.s.val); + else + ::new (&s.err) ErrorType(o.s.err); + } + Base(Base&& o) + : has(o.has) + { + if (has) + ::new (&s.val) ValueType(WTFMove(o.s.val)); + else + ::new (&s.err) ErrorType(WTFMove(o.s.err)); + } + ~Base() + { + if (has) + destroy(s.val); + else + destroy(s.err); + } +}; + +template +struct ConstexprBase { + typedef void ValueType; + typedef E ErrorType; + ConstexprStorage s; + bool has; + constexpr ConstexprBase() : s(), has(true) { } + constexpr ConstexprBase(ValueTagType tag) : s(tag), has(true) { } + constexpr ConstexprBase(ErrorTagType tag) : s(tag), has(false) { } + constexpr ConstexprBase(ErrorTagType tag, const ErrorType& err) : s(tag, err), has(false) { } + constexpr ConstexprBase(ErrorTagType tag, ErrorType&& err) : s(tag, std::forward(err)), has(false) { } + ~ConstexprBase() = default; +}; + +template +struct Base { + typedef void ValueType; + typedef E ErrorType; + Storage s; + bool has; + constexpr Base() : s(), has(true) { } + constexpr Base(ValueTagType tag) : s(tag), has(true) { } + constexpr Base(ErrorTagType tag) : s(tag), has(false) { } + constexpr Base(ErrorTagType tag, const ErrorType& err) : s(tag, err), has(false) { } + constexpr Base(ErrorTagType tag, ErrorType&& err) : s(tag, std::forward(err)), has(false) { } + Base(const Base& o) + : has(o.has) + { + if (!has) + ::new (&s.err) ErrorType(o.s.err); + } + Base(Base&& o) + : has(o.has) + { + if (!has) + ::new (&s.err) ErrorType(WTFMove(o.s.err)); + } + ~Base() + { + if (!has) + destroy(s.err); + } +}; + +template +using BaseSelect = typename std::conditional< + ((std::is_void::value || std::is_trivially_destructible::value) + && std::is_trivially_destructible::value), + ConstexprBase::type, typename std::remove_const::type>, + Base::type, typename std::remove_const::type> +>::type; + +} // namespace ExpectedDetail + +template +class Expected : private ExpectedDetail::BaseSelect { + typedef ExpectedDetail::BaseSelect base; + +public: + typedef typename base::ValueType ValueType; + typedef typename base::ErrorType ErrorType; + +private: + typedef Expected type; + +public: + // template struct rebind { using type = Expected; }; + + constexpr Expected() : base(ExpectedDetail::ValueTag) { } + Expected(const Expected&) = default; + Expected(Expected&&) = default; + constexpr Expected(const ValueType& e) : base(ExpectedDetail::ValueTag, e) { } + constexpr Expected(ValueType&& e) : base(ExpectedDetail::ValueTag, std::forward(e)) { } + // template constexpr explicit Expected(in_place_t, Args&&...); + // template constexpr explicit Expected(in_place_t, std::initializer_list, Args&&...); + constexpr Expected(UnexpectedType const& u) : base(ExpectedDetail::ErrorTag, u.value()) { } + constexpr Expected(UnexpectedType&& u) : base(ExpectedDetail::ErrorTag, std::forward>(u).value()) { } + template constexpr Expected(UnexpectedType const& u) : base(ExpectedDetail::ErrorTag, u.value()) { } + // template constexpr explicit Expected(UnexpectTag, Args&&...); + // template constexpr explicit Expected(UnexpectTag, std::initializer_list, Args&&...); + + ~Expected() = default; + + Expected& operator=(const Expected& e) { type(e).swap(*this); return *this; } + Expected& operator=(Expected&& e) { type(WTFMove(e)).swap(*this); return *this; } + template Expected& operator=(U&& u) { type(WTFMove(u)).swap(*this); return *this; } + Expected& operator=(const UnexpectedType& u) { type(u).swap(*this); return *this; } + Expected& operator=(UnexpectedType&& u) { type(WTFMove(u)).swap(*this); return *this; } + // template void emplace(Args&&...); + // template void emplace(std::initializer_list, Args&&...); + + void swap(Expected& o) + { + using std::swap; + if (base::has && o.has) + swap(base::s.val, o.s.val); + else if (base::has && !o.has) { + ErrorType e(WTFMove(o.s.err)); + ExpectedDetail::destroy(o.s.err); + ::new (&o.s.val) ValueType(WTFMove(base::s.val)); + ExpectedDetail::destroy(base::s.val); + ::new (&base::s.err) ErrorType(WTFMove(e)); + swap(base::has, o.has); + } else if (!base::has && o.has) { + ValueType v(WTFMove(o.s.val)); + ExpectedDetail::destroy(o.s.val); + ::new (&o.s.err) ErrorType(WTFMove(base::s.err)); + ExpectedDetail::destroy(base::s.err); + ::new (&base::s.val) ValueType(WTFMove(v)); + swap(base::has, o.has); + } else + swap(base::s.err, o.s.err); + } + + constexpr const ValueType* operator->() const { return &base::s.val; } + ValueType* operator->() { return &base::s.val; } + constexpr const ValueType& operator*() const & { return base::s.val; } + ValueType& operator*() & { return base::s.val; } + constexpr const ValueType&& operator*() const && { return WTFMove(base::s.val); } + RELAXED_CONSTEXPR ValueType&& operator*() && { return WTFMove(base::s.val); } + constexpr explicit operator bool() const { return base::has; } + constexpr bool hasValue() const { return base::has; } + constexpr const ValueType& value() const & { return base::has ? base::s.val : (ExpectedDetail::Throw(), base::s.val); } + RELAXED_CONSTEXPR ValueType& value() & { return base::has ? base::s.val : (ExpectedDetail::Throw(), base::s.val); } + constexpr const ValueType&& value() const && { return base::has ? base::s.val : (ExpectedDetail::Throw(), base::s.val); } + RELAXED_CONSTEXPR ValueType&& value() && { return WTFMove(base::has ? base::s.val : (ExpectedDetail::Throw(), base::s.val)); } + constexpr const ErrorType& error() const & { return !base::has ? base::s.err : (ExpectedDetail::Throw(), base::s.err); } + ErrorType& error() & { return !base::has ? base::s.err : (ExpectedDetail::Throw(), base::s.err); } + RELAXED_CONSTEXPR ErrorType&& error() && { return !base::has ? base::s.err : (ExpectedDetail::Throw(), base::s.err); } + constexpr const ErrorType&& error() const && { return !base::has ? base::s.err : (ExpectedDetail::Throw(), base::s.err); } + constexpr UnexpectedType getUnexpected() const { return UnexpectedType(base::s.err); } + template constexpr ValueType valueOr(U&& u) const & { return base::has ? **this : static_cast(std::forward(u)); } + template ValueType valueOr(U&& u) && { return base::has ? WTFMove(**this) : static_cast(std::forward(u)); } +}; + +template +class Expected : private ExpectedDetail::BaseSelect { + typedef ExpectedDetail::BaseSelect base; + +public: + typedef typename base::ValueType ValueType; + typedef typename base::ErrorType ErrorType; + +private: + typedef Expected type; + +public: + // template struct rebind { typedef Expected type; }; + + constexpr Expected() : base(ExpectedDetail::ValueTag) { } + Expected(const Expected&) = default; + Expected(Expected&&) = default; + // constexpr explicit Expected(in_place_t); + constexpr Expected(UnexpectedType const& u) : base(ExpectedDetail::ErrorTag, u.value()) { } + constexpr Expected(UnexpectedType&& u) : base(ExpectedDetail::ErrorTag, std::forward>(u).value()) { } + template constexpr Expected(UnexpectedType const& u) : base(ExpectedDetail::ErrorTag, u.value()) { } + + ~Expected() = default; + + Expected& operator=(const Expected& e) { type(e).swap(*this); return *this; } + Expected& operator=(Expected&& e) { type(WTFMove(e)).swap(*this); return *this; } + Expected& operator=(const UnexpectedType& u) { type(u).swap(*this); return *this; } // Not in the current paper. + Expected& operator=(UnexpectedType&& u) { type(WTFMove(u)).swap(*this); return *this; } // Not in the current paper. + // void emplace(); + + void swap(Expected& o) + { + using std::swap; + if (base::has && o.has) { + // Do nothing. + } else if (base::has && !o.has) { + ErrorType e(WTFMove(o.s.err)); + ::new (&base::s.err) ErrorType(e); + swap(base::has, o.has); + } else if (!base::has && o.has) { + ::new (&o.s.err) ErrorType(WTFMove(base::s.err)); + swap(base::has, o.has); + } else + swap(base::s.err, o.s.err); + } + + constexpr explicit operator bool() const { return base::has; } + constexpr bool hasValue() const { return base::has; } + void value() const { !base::has ? ExpectedDetail::Throw() : void(); } + constexpr const E& error() const & { return !base::has ? base::s.err : (ExpectedDetail::Throw(), base::s.err); } + E& error() & { return !base::has ? base::s.err : (ExpectedDetail::Throw(), base::s.err); } // Not in the current paper. + RELAXED_CONSTEXPR E&& error() && { return !base::has ? base::s.err : (ExpectedDetail::Throw(), base::s.err); } + constexpr const E&& error() const && { return !base::has ? base::s.err : (ExpectedDetail::Throw(), base::s.err); } // Not in the current paper. + // constexpr E& error() &; + constexpr UnexpectedType getUnexpected() const { return UnexpectedType(base::s.err); } +}; + +template constexpr bool operator==(const Expected& x, const Expected& y) { return bool(x) == bool(y) && (x ? x.value() == y.value() : x.error() == y.error()); } +template constexpr bool operator!=(const Expected& x, const Expected& y) { return !(x == y); } +template constexpr bool operator<(const Expected& x, const Expected& y) { return (!bool(x) && bool(y)) ? false : ((bool(x) && !bool(y)) ? true : ((bool(x) && bool(y)) ? x.value() < y.value() : x.error() < y.error())); } +template constexpr bool operator>(const Expected& x, const Expected& y) { return !(x == y) && !(x < y); } +template constexpr bool operator<=(const Expected& x, const Expected& y) { return (x == y) || (x < y); } +template constexpr bool operator>=(const Expected& x, const Expected& y) { return (x == y) || (x > y); } + +template constexpr bool operator==(const Expected& x, const Expected& y) { return bool(x) == bool(y) && (x ? true : x.error() == y.error()); } // Not in the current paper. +template constexpr bool operator<(const Expected& x, const Expected& y) { return (!bool(x) && bool(y)) ? false : ((bool(x) && !bool(y)) ? true : ((bool(x) && bool(y)) ? false : x.error() < y.error())); } // Not in the current paper. + +template constexpr bool operator==(const Expected& x, const T& y) { return x == Expected(y); } +template constexpr bool operator==(const T& x, const Expected& y) { return Expected(x) == y; } +template constexpr bool operator!=(const Expected& x, const T& y) { return x != Expected(y); } +template constexpr bool operator!=(const T& x, const Expected& y) { return Expected(x) != y; } +template constexpr bool operator<(const Expected& x, const T& y) { return x < Expected(y); } +template constexpr bool operator<(const T& x, const Expected& y) { return Expected(x) < y; } +template constexpr bool operator<=(const Expected& x, const T& y) { return x <= Expected(y); } +template constexpr bool operator<=(const T& x, const Expected& y) { return Expected(x) <= y; } +template constexpr bool operator>(const Expected& x, const T& y) { return x > Expected(y); } +template constexpr bool operator>(const T& x, const Expected& y) { return Expected(x) > y; } +template constexpr bool operator>=(const Expected& x, const T& y) { return x >= Expected(y); } +template constexpr bool operator>=(const T& x, const Expected& y) { return Expected(x) >= y; } + +template constexpr bool operator==(const Expected& x, const UnexpectedType& y) { return x == Expected(y); } +template constexpr bool operator==(const UnexpectedType& x, const Expected& y) { return Expected(x) == y; } +template constexpr bool operator!=(const Expected& x, const UnexpectedType& y) { return x != Expected(y); } +template constexpr bool operator!=(const UnexpectedType& x, const Expected& y) { return Expected(x) != y; } +template constexpr bool operator<(const Expected& x, const UnexpectedType& y) { return x < Expected(y); } +template constexpr bool operator<(const UnexpectedType& x, const Expected& y) { return Expected(x) < y; } +template constexpr bool operator<=(const Expected& x, const UnexpectedType& y) { return x <= Expected(y); } +template constexpr bool operator<=(const UnexpectedType& x, const Expected& y) { return Expected(x) <= y; } +template constexpr bool operator>(const Expected& x, const UnexpectedType& y) { return x > Expected(y); } +template constexpr bool operator>(const UnexpectedType& x, const Expected& y) { return Expected(x) > y; } +template constexpr bool operator>=(const Expected& x, const UnexpectedType& y) { return x >= Expected(y); } +template constexpr bool operator>=(const UnexpectedType& x, const Expected& y) { return Expected(x) >= y; } + +template void swap(Expected& x, Expected& y) { x.swap(y); } + +template constexpr Expected, E> makeExpected(T&& v) +{ + return Expected::type, E>(std::forward(v)); +} +template constexpr Expected> makeExpectedFromError(E&& e) { return Expected>(makeUnexpected(e)); } +template constexpr Expected makeExpectedFromError(U&& u) { return Expected(makeUnexpected(E { std::forward(u) } )); } +// template constexpr Expected::type, E> makeExpected_from_call(F f); + +inline Expected makeExpected() { return Expected(); } + +} // namespace WTF + +namespace std { + +template struct hash> { + typedef WTF::Expected argument_type; + typedef std::size_t result_type; + result_type operator()(argument_type const& e) const { return e ? hash { } (e.value()) : hash { } (e.error()); } +}; + +template struct hash> { + typedef WTF::Expected argument_type; + typedef std::size_t result_type; + result_type operator()(argument_type const& e) const { return e ? 0 : hash { } (e.error()); } +}; + +} + +using WTF::UnexpectedType; +using WTF::makeUnexpected; +using WTF::Unexpect; +using WTF::Expected; +using WTF::makeExpected; +using WTF::makeExpectedFromError; -- cgit v1.2.1