From 615c6dbbca5226f4cad9ed7a38baf6aed0064470 Mon Sep 17 00:00:00 2001 From: tkaya Date: Sun, 1 Nov 2020 17:59:01 +0100 Subject: [PATCH 1/4] added leaf headers --- external/leaf/all.hpp | 4709 ++++++++++++++++++++++ external/leaf/capture.hpp | 300 ++ external/leaf/common.hpp | 96 + external/leaf/context.hpp | 461 +++ external/leaf/detail/all.hpp | 19 + external/leaf/detail/config.hpp | 184 + external/leaf/detail/demangle.hpp | 131 + external/leaf/detail/function_traits.hpp | 100 + external/leaf/detail/mp11.hpp | 303 ++ external/leaf/detail/optional.hpp | 180 + external/leaf/detail/print.hpp | 133 + external/leaf/error.hpp | 759 ++++ external/leaf/exception.hpp | 143 + external/leaf/handle_errors.hpp | 860 ++++ external/leaf/on_error.hpp | 265 ++ external/leaf/pred.hpp | 297 ++ external/leaf/result.hpp | 443 ++ 17 files changed, 9383 insertions(+) create mode 100644 external/leaf/all.hpp create mode 100644 external/leaf/capture.hpp create mode 100644 external/leaf/common.hpp create mode 100644 external/leaf/context.hpp create mode 100644 external/leaf/detail/all.hpp create mode 100644 external/leaf/detail/config.hpp create mode 100644 external/leaf/detail/demangle.hpp create mode 100644 external/leaf/detail/function_traits.hpp create mode 100644 external/leaf/detail/mp11.hpp create mode 100644 external/leaf/detail/optional.hpp create mode 100644 external/leaf/detail/print.hpp create mode 100644 external/leaf/error.hpp create mode 100644 external/leaf/exception.hpp create mode 100644 external/leaf/handle_errors.hpp create mode 100644 external/leaf/on_error.hpp create mode 100644 external/leaf/pred.hpp create mode 100644 external/leaf/result.hpp diff --git a/external/leaf/all.hpp b/external/leaf/all.hpp new file mode 100644 index 000000000..5d87f8dbb --- /dev/null +++ b/external/leaf/all.hpp @@ -0,0 +1,4709 @@ +#ifndef BOOST_LEAF_ALL_HPP_INCLUDED +#define BOOST_LEAF_ALL_HPP_INCLUDED + +// Copyright (c) 2018-2020 Emil Dotchevski and Reverge Studios, Inc. + +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// >>> #include +#line 1 "boost/leaf/capture.hpp" +#ifndef BOOST_LEAF_CAPTURE_HPP_INCLUDED +#define BOOST_LEAF_CAPTURE_HPP_INCLUDED + +// Copyright (c) 2018-2020 Emil Dotchevski and Reverge Studios, Inc. + +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_LEAF_ENABLE_WARNINGS +# if defined(__clang__) +# pragma clang system_header +# elif (__GNUC__*100+__GNUC_MINOR__>301) +# pragma GCC system_header +# elif defined(_MSC_VER) +# pragma warning(push,1) +# endif +#endif + +// >>> #include +#line 1 "boost/leaf/exception.hpp" +#ifndef BOOST_LEAF_EXCEPTION_HPP_INCLUDED +#define BOOST_LEAF_EXCEPTION_HPP_INCLUDED + +// Copyright (c) 2018-2020 Emil Dotchevski and Reverge Studios, Inc. + +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_LEAF_ENABLE_WARNINGS +# if defined(__clang__) +# pragma clang system_header +# elif (__GNUC__*100+__GNUC_MINOR__>301) +# pragma GCC system_header +# elif defined(_MSC_VER) +# pragma warning(push,1) +# endif +#endif + +// >>> #include +#line 1 "boost/leaf/error.hpp" +#ifndef BOOST_LEAF_ERROR_HPP_INCLUDED +#define BOOST_LEAF_ERROR_HPP_INCLUDED + +// Copyright (c) 2018-2020 Emil Dotchevski and Reverge Studios, Inc. + +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_LEAF_ENABLE_WARNINGS +# if defined(__clang__) +# pragma clang system_header +# elif (__GNUC__*100+__GNUC_MINOR__>301) +# pragma GCC system_header +# elif defined(_MSC_VER) +# pragma warning(push,1) +# endif +#endif + +// >>> #include +#line 1 "boost/leaf/detail/function_traits.hpp" +#ifndef BOOST_LEAF_DETAIL_FUNCTION_TRAITS_HPP_INCLUDED +#define BOOST_LEAF_DETAIL_FUNCTION_TRAITS_HPP_INCLUDED + +// Copyright (c) 2018-2020 Emil Dotchevski and Reverge Studios, Inc. + +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_LEAF_ENABLE_WARNINGS +# if defined(__clang__) +# pragma clang system_header +# elif (__GNUC__*100+__GNUC_MINOR__>301) +# pragma GCC system_header +# elif defined(_MSC_VER) +# pragma warning(push,1) +# endif +#endif + +// >>> #include +#line 1 "boost/leaf/detail/mp11.hpp" +#ifndef BOOST_LEAF_DETAIL_MP11_HPP_INCLUDED +#define BOOST_LEAF_DETAIL_MP11_HPP_INCLUDED + +// Copyright 2015-2017 Peter Dimov. +// Copyright 2019 Emil Dotchevski. +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#include +#include + +namespace boost { namespace leaf { namespace leaf_detail_mp11 { + +// mp_list +template struct mp_list +{ +}; + +// mp_identity +template struct mp_identity +{ + using type = T; +}; + +// mp_inherit +template struct mp_inherit: T... {}; + +// mp_if, mp_if_c +namespace detail +{ + +template struct mp_if_c_impl +{ +}; + +template struct mp_if_c_impl +{ + using type = T; +}; + +template struct mp_if_c_impl +{ + using type = E; +}; + +} // namespace detail + +template using mp_if_c = typename detail::mp_if_c_impl::type; +template using mp_if = typename detail::mp_if_c_impl(C::value), T, E...>::type; + +// mp_bool +template using mp_bool = std::integral_constant; + +using mp_true = mp_bool; +using mp_false = mp_bool; + +// mp_to_bool +template using mp_to_bool = mp_bool( T::value )>; + +// mp_not +template using mp_not = mp_bool< !T::value >; + +// mp_int +template using mp_int = std::integral_constant; + +// mp_size_t +template using mp_size_t = std::integral_constant; + +// mp_set_contains +namespace detail +{ + +template struct mp_set_contains_impl; + +template class L, class... T, class V> struct mp_set_contains_impl, V> +{ + using type = mp_to_bool, mp_inherit...> > >; +}; + +} // namespace detail + +template using mp_set_contains = typename detail::mp_set_contains_impl::type; + +// mp_set_push_back +namespace detail +{ + +template struct mp_set_push_back_impl; + +template class L, class... U> struct mp_set_push_back_impl> +{ + using type = L; +}; + +template class L, class... U, class T1, class... T> struct mp_set_push_back_impl, T1, T...> +{ + using S = mp_if, T1>, L, L>; + using type = typename mp_set_push_back_impl::type; +}; + +} // namespace detail + +template using mp_set_push_back = typename detail::mp_set_push_back_impl::type; + +// mp_unique +namespace detail +{ + +template struct mp_unique_impl; + +template class L, class... T> struct mp_unique_impl> +{ + using type = mp_set_push_back, T...>; +}; + +} // namespace detail + +template using mp_unique = typename detail::mp_unique_impl::type; + +// mp_append + +namespace detail +{ + +template struct mp_append_impl; + +template<> struct mp_append_impl<> +{ + using type = mp_list<>; +}; + +template class L, class... T> struct mp_append_impl> +{ + using type = L; +}; + +template class L1, class... T1, template class L2, class... T2, class... Lr> struct mp_append_impl, L2, Lr...> +{ + using type = typename mp_append_impl, Lr...>::type; +}; + +} + +template using mp_append = typename detail::mp_append_impl::type; + +// mp_front +namespace detail +{ + +template struct mp_front_impl +{ +// An error "no type named 'type'" here means that the argument to mp_front +// is either not a list, or is an empty list +}; + +template class L, class T1, class... T> struct mp_front_impl> +{ + using type = T1; +}; + +} // namespace detail + +template using mp_front = typename detail::mp_front_impl::type; + +// mp_pop_front +namespace detail +{ + +template struct mp_pop_front_impl +{ +// An error "no type named 'type'" here means that the argument to mp_pop_front +// is either not a list, or is an empty list +}; + +template class L, class T1, class... T> struct mp_pop_front_impl> +{ + using type = L; +}; + +} // namespace detail + +template using mp_pop_front = typename detail::mp_pop_front_impl::type; + +// mp_first +template using mp_first = mp_front; + +// mp_rest +template using mp_rest = mp_pop_front; + +// mp_remove_if +namespace detail +{ + +template class P> struct mp_remove_if_impl; + +template class L, class... T, template class P> struct mp_remove_if_impl, P> +{ + template using _f = mp_if, mp_list<>, mp_list>; + using type = mp_append, _f...>; +}; + +} // namespace detail + +template class P> using mp_remove_if = typename detail::mp_remove_if_impl::type; + +// integer_sequence +template struct integer_sequence +{ +}; + +// detail::make_integer_sequence_impl +namespace detail +{ + +// iseq_if_c +template struct iseq_if_c_impl; + +template struct iseq_if_c_impl +{ + using type = T; +}; + +template struct iseq_if_c_impl +{ + using type = E; +}; + +template using iseq_if_c = typename iseq_if_c_impl::type; + +// iseq_identity +template struct iseq_identity +{ + using type = T; +}; + +template struct append_integer_sequence; + +template struct append_integer_sequence, integer_sequence> +{ + using type = integer_sequence< T, I..., ( J + sizeof...(I) )... >; +}; + +template struct make_integer_sequence_impl; + +template struct make_integer_sequence_impl_ +{ +private: + + static_assert( N >= 0, "make_integer_sequence: N must not be negative" ); + + static T const M = N / 2; + static T const R = N % 2; + + using S1 = typename make_integer_sequence_impl::type; + using S2 = typename append_integer_sequence::type; + using S3 = typename make_integer_sequence_impl::type; + using S4 = typename append_integer_sequence::type; + +public: + + using type = S4; +}; + +template struct make_integer_sequence_impl: iseq_if_c>, iseq_if_c>, make_integer_sequence_impl_ > > +{ +}; + +} // namespace detail + +// make_integer_sequence +template using make_integer_sequence = typename detail::make_integer_sequence_impl::type; + +// index_sequence +template using index_sequence = integer_sequence; + +// make_index_sequence +template using make_index_sequence = make_integer_sequence; + +// index_sequence_for +template using index_sequence_for = make_integer_sequence; + +// implementation by Bruno Dutra (by the name is_evaluable) +namespace detail +{ + +template class F, class... T> struct mp_valid_impl +{ + template class G, class = G> static mp_true check(int); + template class> static mp_false check(...); + + using type = decltype(check(0)); +}; + +} // namespace detail + +template class F, class... T> using mp_valid = typename detail::mp_valid_impl::type; + +} } } + +#endif +// <<< #include +#line 20 "boost/leaf/detail/function_traits.hpp" +#include + +namespace boost { namespace leaf { + + namespace leaf_detail + { + template + struct gcc49_workaround //Thanks Glen Fernandes + { + using type = void; + }; + + template + using void_t = typename gcc49_workaround::type; + + template + struct function_traits + { + constexpr static int arity = -1; + }; + + template + struct function_traits> + { + private: + + using tr = function_traits; + + public: + + using return_type = typename tr::return_type; + static constexpr int arity = tr::arity - 1; + + using mp_args = typename leaf_detail_mp11::mp_rest; + + template + struct arg: + tr::template arg + { + }; + }; + + template + struct function_traits + { + using return_type = R; + static constexpr int arity = sizeof...(A); + + using mp_args = leaf_detail_mp11::mp_list; + + template + struct arg + { + static_assert(I < arity, "I out of range"); + using type = typename std::tuple_element>::type; + }; + }; + + template struct function_traits : function_traits { }; + template struct function_traits : function_traits { }; + template struct function_traits : function_traits { }; + template struct function_traits : function_traits { }; + template struct function_traits : function_traits { }; + template struct function_traits : function_traits { }; + template struct function_traits : function_traits { }; + template struct function_traits : function_traits { }; + + template + using fn_return_type = typename function_traits::return_type; + + template + using fn_arg_type = typename function_traits::template arg::type; + + template + using fn_mp_args = typename function_traits::mp_args; + + } + +} } + +#endif +// <<< #include +#line 20 "boost/leaf/error.hpp" +// >>> #include +#line 1 "boost/leaf/detail/print.hpp" +#ifndef BOOST_LEAF_DETAIL_PRINT_HPP_INCLUDED +#define BOOST_LEAF_DETAIL_PRINT_HPP_INCLUDED + +// Copyright (c) 2018-2020 Emil Dotchevski and Reverge Studios, Inc. + +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_LEAF_ENABLE_WARNINGS +# if defined(__clang__) +# pragma clang system_header +# elif (__GNUC__*100+__GNUC_MINOR__>301) +# pragma GCC system_header +# elif defined(_MSC_VER) +# pragma warning(push,1) +# endif +#endif + +// >>> #include +#line 1 "boost/leaf/detail/optional.hpp" +#ifndef BOOST_LEAF_DETAIL_OPTIONAL_HPP_INCLUDED +#define BOOST_LEAF_DETAIL_OPTIONAL_HPP_INCLUDED + +// Copyright (c) 2018-2020 Emil Dotchevski and Reverge Studios, Inc. + +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_LEAF_ENABLE_WARNINGS +# if defined(__clang__) +# pragma clang system_header +# elif (__GNUC__*100+__GNUC_MINOR__>301) +# pragma GCC system_header +# elif defined(_MSC_VER) +# pragma warning(push,1) +# endif +#endif + +// >>> #include +#line 1 "boost/leaf/detail/config.hpp" +#ifndef BOOST_LEAF_CONFIG_HPP_INCLUDED +#define BOOST_LEAF_CONFIG_HPP_INCLUDED + +// Copyright (c) 2018-2020 Emil Dotchevski and Reverge Studios, Inc. + +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// The following is based on Boost Config. + +// (C) Copyright John Maddock 2001 - 2003. +// (C) Copyright Martin Wille 2003. +// (C) Copyright Guillaume Melquiond 2003. + +#ifndef BOOST_LEAF_ENABLE_WARNINGS +# if defined(__clang__) +# pragma clang system_header +# elif (__GNUC__*100+__GNUC_MINOR__>301) +# pragma GCC system_header +# elif defined(_MSC_VER) +# pragma warning(push,1) +# endif +#endif + +//////////////////////////////////////// + +// Configure BOOST_LEAF_NO_EXCEPTIONS, unless already #defined +#ifndef BOOST_LEAF_NO_EXCEPTIONS + +# if defined(__clang__) && !defined(__ibmxl__) +// Clang C++ emulates GCC, so it has to appear early. + +# if !__has_feature(cxx_exceptions) +# define BOOST_LEAF_NO_EXCEPTIONS +# endif + +# elif defined(__DMC__) +// Digital Mars C++ + +# if !defined(_CPPUNWIND) +# define BOOST_LEAF_NO_EXCEPTIONS +# endif + +# elif defined(__GNUC__) && !defined(__ibmxl__) +// GNU C++: + +# if !defined(__EXCEPTIONS) +# define BOOST_LEAF_NO_EXCEPTIONS +# endif + +# elif defined(__KCC) +// Kai C++ + +# if !defined(_EXCEPTIONS) +# define BOOST_LEAF_NO_EXCEPTIONS +# endif + +# elif defined(__CODEGEARC__) +// CodeGear - must be checked for before Borland + +# if !defined(_CPPUNWIND) && !defined(__EXCEPTIONS) +# define BOOST_LEAF_NO_EXCEPTIONS +# endif + +# elif defined(__BORLANDC__) +// Borland + +# if !defined(_CPPUNWIND) && !defined(__EXCEPTIONS) +# define BOOST_LEAF_NO_EXCEPTIONS +# endif + +# elif defined(__MWERKS__) +// Metrowerks CodeWarrior + +# if !__option(exceptions) +# define BOOST_LEAF_NO_EXCEPTIONS +# endif + +# elif defined(__IBMCPP__) && defined(__COMPILER_VER__) && defined(__MVS__) +// IBM z/OS XL C/C++ + +# if !defined(_CPPUNWIND) && !defined(__EXCEPTIONS) +# define BOOST_LEAF_NO_EXCEPTIONS +# endif + +# elif defined(__ibmxl__) +// IBM XL C/C++ for Linux (Little Endian) + +# if !__has_feature(cxx_exceptions) +# define BOOST_LEAF_NO_EXCEPTIONS +# endif + +# elif defined(_MSC_VER) +// Microsoft Visual C++ +// +// Must remain the last #elif since some other vendors (Metrowerks, for +// example) also #define _MSC_VER + +# if !defined(_CPPUNWIND) +# define BOOST_LEAF_NO_EXCEPTIONS +# endif +# endif + +#endif + +#ifdef BOOST_NORETURN +# define BOOST_LEAF_NORETURN BOOST_NORETURN +#else +# if defined(_MSC_VER) +# define BOOST_LEAF_NORETURN __declspec(noreturn) +# elif defined(__GNUC__) +# define BOOST_LEAF_NORETURN __attribute__ ((__noreturn__)) +# elif defined(__has_attribute) && defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x5130) +# if __has_attribute(noreturn) +# define BOOST_LEAF_NORETURN [[noreturn]] +# endif +# elif defined(__has_cpp_attribute) +# if __has_cpp_attribute(noreturn) +# define BOOST_LEAF_NORETURN [[noreturn]] +# endif +# endif +#endif +#if !defined(BOOST_LEAF_NORETURN) +# define BOOST_LEAF_NORETURN +#endif + +//////////////////////////////////////// + +#ifndef BOOST_LEAF_DIAGNOSTICS +# define BOOST_LEAF_DIAGNOSTICS 1 +#endif + +#if BOOST_LEAF_DIAGNOSTICS!=0 && BOOST_LEAF_DIAGNOSTICS!=1 +# error BOOST_LEAF_DIAGNOSTICS must be 0 or 1. +#endif + +//////////////////////////////////////// + +#ifdef _MSC_VER +# define BOOST_LEAF_ALWAYS_INLINE __forceinline +#else +# define BOOST_LEAF_ALWAYS_INLINE __attribute__((always_inline)) inline +#endif + +//////////////////////////////////////// + +#ifndef BOOST_LEAF_NODISCARD +# if __cplusplus >= 201703L +# define BOOST_LEAF_NODISCARD [[nodiscard]] +# else +# define BOOST_LEAF_NODISCARD +# endif +#endif + +//////////////////////////////////////// + +#ifndef BOOST_LEAF_CONSTEXPR +# if __cplusplus > 201402L +# define BOOST_LEAF_CONSTEXPR constexpr +# else +# define BOOST_LEAF_CONSTEXPR +# endif +#endif + +//////////////////////////////////////// + +#if __cplusplus > 201402L +# define BOOST_LEAF_STD_UNCAUGHT_EXCEPTIONS 1 +#else +# define BOOST_LEAF_STD_UNCAUGHT_EXCEPTIONS 0 +#endif + +//////////////////////////////////////// + +#ifndef BOOST_LEAF_ASSERT +# ifdef BOOST_ASSERT +# define BOOST_LEAF_ASSERT BOOST_ASSERT +# else +# include +# define BOOST_LEAF_ASSERT assert +# endif +#endif + +#endif +// <<< #include +#line 20 "boost/leaf/detail/optional.hpp" +#include +#include + +namespace boost { namespace leaf { + + namespace leaf_detail + { + template + class optional + { + int key_; + union { T value_; }; + + public: + + typedef T value_type; + + BOOST_LEAF_CONSTEXPR optional() noexcept: + key_(0) + { + } + + BOOST_LEAF_CONSTEXPR optional( optional const & x ): + key_(x.key_) + { + if( x.key_ ) + (void) new (&value_) T( x.value_ ); + } + + BOOST_LEAF_CONSTEXPR optional( optional && x ) noexcept: + key_(x.key_) + { + if( x.key_ ) + { + (void) new (&value_) T( std::move(x.value_) ); + x.reset(); + } + } + + BOOST_LEAF_CONSTEXPR optional( int key, T const & v ): + key_(key), + value_(v) + { + BOOST_LEAF_ASSERT(!empty()); + } + + BOOST_LEAF_CONSTEXPR optional( int key, T && v ) noexcept: + key_(key), + value_(std::move(v)) + { + BOOST_LEAF_ASSERT(!empty()); + } + + BOOST_LEAF_CONSTEXPR optional & operator=( optional const & x ) + { + reset(); + if( int key = x.key() ) + { + put(key, x.value_); + key_ = key; + } + return *this; + } + + BOOST_LEAF_CONSTEXPR optional & operator=( optional && x ) noexcept + { + reset(); + if( int key = x.key() ) + { + put(key, std::move(x.value_)); + x.reset(); + } + return *this; + } + + ~optional() noexcept + { + reset(); + } + + BOOST_LEAF_CONSTEXPR bool empty() const noexcept + { + return key_==0; + } + + BOOST_LEAF_CONSTEXPR int key() const noexcept + { + return key_; + } + + BOOST_LEAF_CONSTEXPR void reset() noexcept + { + if( key_ ) + { + value_.~T(); + key_=0; + } + } + + BOOST_LEAF_CONSTEXPR T & put( int key, T const & v ) + { + BOOST_LEAF_ASSERT(key); + reset(); + (void) new(&value_) T(v); + key_=key; + return value_; + } + + BOOST_LEAF_CONSTEXPR T & put( int key, T && v ) noexcept + { + BOOST_LEAF_ASSERT(key); + reset(); + (void) new(&value_) T(std::move(v)); + key_=key; + return value_; + } + + BOOST_LEAF_CONSTEXPR T const * has_value(int key) const noexcept + { + BOOST_LEAF_ASSERT(key); + return key_==key ? &value_ : 0; + } + + BOOST_LEAF_CONSTEXPR T * has_value(int key) noexcept + { + BOOST_LEAF_ASSERT(key); + return key_==key ? &value_ : 0; + } + + BOOST_LEAF_CONSTEXPR T const & value(int key) const & noexcept + { + BOOST_LEAF_ASSERT(has_value(key) != 0); + return value_; + } + + BOOST_LEAF_CONSTEXPR T & value(int key) & noexcept + { + BOOST_LEAF_ASSERT(has_value(key) != 0); + return value_; + } + + BOOST_LEAF_CONSTEXPR T const && value(int key) const && noexcept + { + BOOST_LEAF_ASSERT(has_value(key) != 0); + return value_; + } + + BOOST_LEAF_CONSTEXPR T value(int key) && noexcept + { + BOOST_LEAF_ASSERT(has_value(key) != 0); + T tmp(std::move(value_)); + reset(); + return tmp; + } + }; + + } + +} } + +#endif +// <<< #include +#line 20 "boost/leaf/detail/print.hpp" +#include +#include +#include + +namespace boost { namespace leaf { + + namespace leaf_detail + { + template + BOOST_LEAF_CONSTEXPR inline char const * check_prefix( char const * t, char const (&prefix)[N] ) + { + return std::strncmp(t,prefix,sizeof(prefix)-1)==0 ? t+sizeof(prefix)-1 : t; + } + } + + template + inline char const * type() noexcept + { + using leaf_detail::check_prefix; + char const * t = +#ifdef __FUNCSIG__ + __FUNCSIG__; +#else + __PRETTY_FUNCTION__; +#endif +#if defined(__clang__) + BOOST_LEAF_ASSERT(check_prefix(t,"const char *boost::leaf::type() ")==t+32); + return t+32; +#elif defined(__GNUC__) + BOOST_LEAF_ASSERT(check_prefix(t,"const char* boost::leaf::type() ")==t+32); + return t+32; +#else + char const * clang_style = check_prefix(t,"const char *boost::leaf::type() "); + if( clang_style!=t ) + return clang_style; + char const * gcc_style = check_prefix(t,"const char* boost::leaf::type() "); + if( gcc_style!=t ) + return gcc_style; +#endif + return t; + } + + namespace leaf_detail + { + template + struct is_printable: std::false_type + { + }; + + template + struct is_printable()<(), void())>: std::true_type + { + }; + + //////////////////////////////////////// + + template + struct has_printable_member_value: std::false_type + { + }; + + template + struct has_printable_member_value()<().value, void())>: std::true_type + { + }; + + //////////////////////////////////////// + + template ::value, bool ValuePrintable=has_printable_member_value::value> + struct diagnostic; + + template + struct diagnostic + { + static constexpr bool is_invisible = false; + static void print( std::ostream & os, Wrapper const & x ) + { + os << x; + } + }; + + template + struct diagnostic + { + static constexpr bool is_invisible = false; + static void print( std::ostream & os, Wrapper const & x ) + { + os << type() << ": " << x.value; + } + }; + + template + struct diagnostic + { + static constexpr bool is_invisible = false; + static void print( std::ostream & os, Wrapper const & ) + { + os << type() << ": {Non-Printable}"; + } + }; + + template <> + struct diagnostic + { + static constexpr bool is_invisible = true; + BOOST_LEAF_CONSTEXPR static void print( std::ostream &, std::exception_ptr const & ) + { + } + }; + } + +} } + +#endif +// <<< #include +#line 21 "boost/leaf/error.hpp" +#include +#include +#include +#include +#include + +#define BOOST_LEAF_TOKEN_PASTE(x, y) x ## y +#define BOOST_LEAF_TOKEN_PASTE2(x, y) BOOST_LEAF_TOKEN_PASTE(x, y) + +#define BOOST_LEAF_ASSIGN(v,r)\ + static_assert(::boost::leaf::is_result_type::type>::value, "The BOOST_LEAF_ASSIGN macro requires a result type as the second argument");\ + auto && BOOST_LEAF_TOKEN_PASTE2(boost_leaf_temp_, __LINE__) = r;\ + if( !BOOST_LEAF_TOKEN_PASTE2(boost_leaf_temp_, __LINE__) )\ + return BOOST_LEAF_TOKEN_PASTE2(boost_leaf_temp_, __LINE__).error();\ + v = BOOST_LEAF_TOKEN_PASTE2(boost_leaf_temp_, __LINE__).value() + +#define BOOST_LEAF_AUTO(v, r)\ + BOOST_LEAF_ASSIGN(auto && v, r) + +#define BOOST_LEAF_CHECK(r)\ + {\ + static_assert(::boost::leaf::is_result_type::type>::value, "BOOST_LEAF_CHECK requires a result type");\ + auto && _r = r;\ + if( !_r )\ + return _r.error();\ + } + +#define BOOST_LEAF_NEW_ERROR ::leaf::leaf_detail::inject_loc{__FILE__,__LINE__,__FUNCTION__}+::boost::leaf::new_error + +namespace boost { namespace leaf { + + namespace leaf_detail + { + struct inject_loc + { + char const * const file; + int const line; + char const * const fn; + + template + friend T operator+( inject_loc loc, T && x ) noexcept + { + x.load_source_location_(loc.file, loc.line, loc.fn); + return std::move(x); + } + }; + } + +} } + +//////////////////////////////////////// + +#ifdef BOOST_LEAF_NO_EXCEPTIONS + +namespace boost +{ + BOOST_LEAF_NORETURN void throw_exception( std::exception const & ); // user defined +} + +namespace boost { namespace leaf { + + template + BOOST_LEAF_NORETURN void throw_exception( T const & e ) + { + ::boost::throw_exception(e); + } + +} } + +#else + +namespace boost { namespace leaf { + + template + BOOST_LEAF_NORETURN void throw_exception( T const & e ) + { + throw e; + } + +} } + +#endif + +//////////////////////////////////////// + +#ifdef BOOST_LEAF_NO_THREADS +# define BOOST_LEAF_THREAD_LOCAL + namespace boost { namespace leaf { + namespace leaf_detail + { + using atomic_unsigned_int = unsigned int; + } + } } +#else +# include +# include +# define BOOST_LEAF_THREAD_LOCAL thread_local + namespace boost { namespace leaf { + namespace leaf_detail + { + using atomic_unsigned_int = std::atomic; + } + } } +#endif + +//////////////////////////////////////// + +namespace boost { namespace leaf { + +#if BOOST_LEAF_DIAGNOSTICS + + namespace leaf_detail + { + class e_unexpected_count + { + public: + + char const * (*first_type)(); + int count; + + BOOST_LEAF_CONSTEXPR explicit e_unexpected_count(char const * (*first_type)()) noexcept: + first_type(first_type), + count(1) + { + } + + void print(std::ostream & os) const + { + BOOST_LEAF_ASSERT(first_type != 0); + BOOST_LEAF_ASSERT(count>0); + os << "Detected "; + if( count==1 ) + os << "1 attempt to communicate an unexpected error object"; + else + os << count << " attempts to communicate unexpected error objects, the first one"; + os << " of type " << first_type() << std::endl; + } + }; + + template <> + struct diagnostic + { + static constexpr bool is_invisible = true; + BOOST_LEAF_CONSTEXPR static void print(std::ostream &, e_unexpected_count const &) noexcept { } + }; + + class e_unexpected_info + { + std::string s_; + std::set already_; + + public: + + e_unexpected_info() noexcept + { + } + + template + void add(E const & e) + { + if( !diagnostic::is_invisible && already_.insert(&type).second ) + { + std::stringstream s; + diagnostic::print(s,e); + s << std::endl; + s_ += s.str(); + } + } + + void print(std::ostream & os) const + { + os << "Unexpected error objects:\n" << s_; + } + }; + + template <> + struct diagnostic + { + static constexpr bool is_invisible = true; + BOOST_LEAF_CONSTEXPR static void print(std::ostream &, e_unexpected_info const &) noexcept { } + }; + + template + struct tl_unexpected_enabled + { + static BOOST_LEAF_THREAD_LOCAL int counter; + }; + + template + BOOST_LEAF_THREAD_LOCAL int tl_unexpected_enabled::counter; + } + +#endif + +} } + +//////////////////////////////////////// + +namespace boost { namespace leaf { + + struct e_source_location + { + char const * const file; + int const line; + char const * const function; + + friend std::ostream & operator<<( std::ostream & os, e_source_location const & x ) + { + return os << leaf::type() << ": " << x.file << '(' << x.line << ") in function " << x.function; + } + }; + + //////////////////////////////////////// + + namespace leaf_detail + { + template + class slot; + + template + struct tl_slot_ptr + { + static BOOST_LEAF_THREAD_LOCAL slot * p; + }; + + template + BOOST_LEAF_THREAD_LOCAL slot * tl_slot_ptr::p; + + template + class slot: + optional + { + slot( slot const & ) = delete; + slot & operator=( slot const & ) = delete; + + using impl = optional; + slot * * top_; + slot * prev_; + + public: + + BOOST_LEAF_CONSTEXPR slot() noexcept: + top_(0) + { + } + + BOOST_LEAF_CONSTEXPR slot( slot && x ) noexcept: + optional(std::move(x)), + top_(0) + { + BOOST_LEAF_ASSERT(x.top_==0); + } + + BOOST_LEAF_CONSTEXPR void activate() noexcept + { + BOOST_LEAF_ASSERT(top_==0 || *top_!=this); + top_ = &tl_slot_ptr::p; + prev_ = *top_; + *top_ = this; + } + + BOOST_LEAF_CONSTEXPR void deactivate() noexcept + { + BOOST_LEAF_ASSERT(top_!=0 && *top_==this); + *top_ = prev_; + } + + BOOST_LEAF_CONSTEXPR void propagate() noexcept; + + void print( std::ostream & os, int key_to_print ) const + { + if( !diagnostic::is_invisible ) + if( int k = this->key() ) + { + if( key_to_print ) + { + if( key_to_print!=k ) + return; + } + else + os << '[' << k << ']'; + diagnostic::print(os, value(k)); + os << std::endl; + } + } + + using impl::put; + using impl::has_value; + using impl::value; + }; + +#if BOOST_LEAF_DIAGNOSTICS + + template + BOOST_LEAF_CONSTEXPR inline void load_unexpected_count( int err_id ) noexcept + { + if( slot * sl = tl_slot_ptr::p ) + if( e_unexpected_count * unx = sl->has_value(err_id) ) + ++unx->count; + else + sl->put(err_id, e_unexpected_count(&type)); + } + + template + BOOST_LEAF_CONSTEXPR inline void load_unexpected_info( int err_id, E && e ) noexcept + { + if( slot * sl = tl_slot_ptr::p ) + if( e_unexpected_info * unx = sl->has_value(err_id) ) + unx->add(e); + else + sl->put(err_id, e_unexpected_info()).add(e); + } + + template + BOOST_LEAF_CONSTEXPR inline void load_unexpected( int err_id, E && e ) noexcept + { + load_unexpected_count(err_id); + load_unexpected_info(err_id, std::move(e)); + } + +#endif + + template + BOOST_LEAF_CONSTEXPR inline void slot::propagate() noexcept + { + BOOST_LEAF_ASSERT(top_!=0 && (*top_==prev_ || *top_==this)); + if( prev_ ) + { + impl & that_ = *prev_; + if( that_.empty() ) + { + impl & this_ = *this; + that_ = std::move(this_); + } + } +#if BOOST_LEAF_DIAGNOSTICS + else + { + int c = tl_unexpected_enabled<>::counter; + BOOST_LEAF_ASSERT(c>=0); + if( c ) + if( int err_id = impl::key() ) + load_unexpected(err_id, std::move(*this).value(err_id)); + } +#endif + } + + template + BOOST_LEAF_CONSTEXPR inline int load_slot( int err_id, E && e ) noexcept + { + static_assert(!std::is_pointer::value, "Error objects of pointer types are not allowed"); + using T = typename std::decay::type; + BOOST_LEAF_ASSERT((err_id&3)==1); + if( slot * p = tl_slot_ptr::p ) + (void) p->put(err_id, std::forward(e)); +#if BOOST_LEAF_DIAGNOSTICS + else + { + int c = tl_unexpected_enabled<>::counter; + BOOST_LEAF_ASSERT(c>=0); + if( c ) + load_unexpected(err_id, std::forward(e)); + } +#endif + return 0; + } + + template + BOOST_LEAF_CONSTEXPR inline int accumulate_slot( int err_id, F && f ) noexcept + { + static_assert(function_traits::arity==1, "Lambdas passed to accumulate must take a single e-type argument by reference"); + using E = typename std::decay>::type; + static_assert(!std::is_pointer::value, "Error objects of pointer types are not allowed"); + BOOST_LEAF_ASSERT((err_id&3)==1); + if( auto sl = tl_slot_ptr::p ) + if( auto v = sl->has_value(err_id) ) + (void) std::forward(f)(*v); + else + (void) std::forward(f)(sl->put(err_id,E())); + return 0; + } + } + + //////////////////////////////////////// + + namespace leaf_detail + { + template + struct id_factory + { + static atomic_unsigned_int counter; + static BOOST_LEAF_THREAD_LOCAL unsigned current_id; + + BOOST_LEAF_CONSTEXPR static unsigned generate_next_id() noexcept + { + auto id = (counter+=4); + BOOST_LEAF_ASSERT((id&3)==1); + return id; + } + }; + + template + atomic_unsigned_int id_factory::counter(-3); + + template + BOOST_LEAF_THREAD_LOCAL unsigned id_factory::current_id(0); + + inline int current_id() noexcept + { + auto id = id_factory<>::current_id; + BOOST_LEAF_ASSERT(id==0 || (id&3)==1); + return id; + } + + inline int new_id() noexcept + { + auto id = id_factory<>::generate_next_id(); + return id_factory<>::current_id = id; + } + } + + //////////////////////////////////////// + + namespace leaf_detail + { + template ::arity> + struct load_item + { + static_assert(Arity==0 || Arity==1, "If a functions is passed to new_error or load, it must take zero or one argument"); + }; + + template + struct load_item + { + BOOST_LEAF_CONSTEXPR static int load( int err_id, E && e ) noexcept + { + return load_slot(err_id, std::forward(e)); + } + }; + + template + struct load_item + { + BOOST_LEAF_CONSTEXPR static int load( int err_id, F && f ) noexcept + { + return load_slot(err_id, std::forward(f)()); + } + }; + + template + struct load_item + { + BOOST_LEAF_CONSTEXPR static int load( int err_id, F && f ) noexcept + { + return accumulate_slot(err_id, std::forward(f)); + } + }; + } + + //////////////////////////////////////// + + namespace leaf_detail + { + class leaf_category: public std::error_category + { + bool equivalent( int, std::error_condition const & ) const noexcept final override { return false; } + bool equivalent( std::error_code const &, int ) const noexcept final override { return false; } + char const * name() const noexcept final override { return "LEAF error"; } + std::string message( int condition ) const final override { return name(); } + public: + ~leaf_category() noexcept final override { } + }; + + template + struct get_error_category + { + static leaf_category cat; + }; + + template + leaf_category get_error_category::cat; + + inline int import_error_code( std::error_code const & ec ) noexcept + { + if( int err_id = ec.value() ) + { + std::error_category const & cat = get_error_category<>::cat; + if( &ec.category()==&cat ) + { + BOOST_LEAF_ASSERT((err_id&3)==1); + return (err_id&~3)|1; + } + else + { + err_id = new_id(); + (void) load_slot(err_id, ec); + return (err_id&~3)|1; + } + } + else + return 0; + } + } + + inline bool is_error_id( std::error_code const & ec ) noexcept + { + bool res = (&ec.category() == &leaf_detail::get_error_category<>::cat); + BOOST_LEAF_ASSERT(!res || !ec.value() || ((ec.value()&3)==1)); + return res; + } + + //////////////////////////////////////// + + class error_id; + + namespace leaf_detail + { + BOOST_LEAF_CONSTEXPR error_id make_error_id(int) noexcept; + } + + class error_id + { + friend error_id BOOST_LEAF_CONSTEXPR leaf_detail::make_error_id(int) noexcept; + + int value_; + + BOOST_LEAF_CONSTEXPR explicit error_id( int value ) noexcept: + value_(value) + { + BOOST_LEAF_ASSERT(value_==0 || ((value_&3)==1)); + } + + public: + + BOOST_LEAF_CONSTEXPR error_id() noexcept: + value_(0) + { + } + + error_id( std::error_code const & ec ) noexcept: + value_(leaf_detail::import_error_code(ec)) + { + BOOST_LEAF_ASSERT(!value_ || ((value_&3)==1)); + } + + template + error_id( Enum e, typename std::enable_if::value, Enum>::type * = 0 ) noexcept: + value_(leaf_detail::import_error_code(e)) + { + } + + BOOST_LEAF_CONSTEXPR error_id load() const noexcept + { + return *this; + } + + template + BOOST_LEAF_CONSTEXPR error_id load( Item && ... item ) const noexcept + { + if( int err_id = value() ) + { + int const unused[ ] = { 42, leaf_detail::load_item::load(err_id, std::forward(item))... }; + (void) unused; + } + return *this; + } + + std::error_code to_error_code() const noexcept + { + return std::error_code(value_, leaf_detail::get_error_category<>::cat); + } + + BOOST_LEAF_CONSTEXPR int value() const noexcept + { + if( int v = value_ ) + { + BOOST_LEAF_ASSERT((v&3)==1); + return (v&~3)|1; + } + else + return 0; + } + + BOOST_LEAF_CONSTEXPR explicit operator bool() const noexcept + { + return value_ != 0; + } + + BOOST_LEAF_CONSTEXPR friend bool operator==( error_id a, error_id b ) noexcept + { + return a.value_ == b.value_; + } + + BOOST_LEAF_CONSTEXPR friend bool operator!=( error_id a, error_id b ) noexcept + { + return !(a == b); + } + + BOOST_LEAF_CONSTEXPR friend bool operator<( error_id a, error_id b ) noexcept + { + return a.value_ < b.value_; + } + + friend std::ostream & operator<<( std::ostream & os, error_id x ) + { + return os << x.value_; + } + + BOOST_LEAF_CONSTEXPR void load_source_location_( char const * file, int line, char const * function ) const noexcept + { + BOOST_LEAF_ASSERT(file&&*file); + BOOST_LEAF_ASSERT(line>0); + BOOST_LEAF_ASSERT(function&&*function); + BOOST_LEAF_ASSERT(value_); + (void) load(e_source_location {file,line,function}); + } + }; + + namespace leaf_detail + { + BOOST_LEAF_CONSTEXPR inline error_id make_error_id( int err_id ) noexcept + { + BOOST_LEAF_ASSERT(err_id==0 || (err_id&3)==1); + return error_id((err_id&~3)|1); + } + } + + inline error_id new_error() noexcept + { + return leaf_detail::make_error_id(leaf_detail::new_id()); + } + + template + inline error_id new_error( Item && ... item ) noexcept + { + return leaf_detail::make_error_id(leaf_detail::new_id()).load(std::forward(item)...); + } + + inline error_id current_error() noexcept + { + return leaf_detail::make_error_id(leaf_detail::current_id()); + } + + //////////////////////////////////////////// + + class polymorphic_context + { + protected: + + polymorphic_context() noexcept = default; + ~polymorphic_context() noexcept = default; + + public: + + virtual error_id propagate_captured_errors() noexcept = 0; + virtual void activate() noexcept = 0; + virtual void deactivate() noexcept = 0; + virtual void propagate() noexcept = 0; + virtual bool is_active() const noexcept = 0; + virtual void print( std::ostream & ) const = 0; + error_id captured_id_; + }; + + using context_ptr = std::shared_ptr; + + //////////////////////////////////////////// + + template + class context_activator + { + context_activator( context_activator const & ) = delete; + context_activator & operator=( context_activator const & ) = delete; + +#if !defined(BOOST_LEAF_NO_EXCEPTIONS) && BOOST_LEAF_STD_UNCAUGHT_EXCEPTIONS + int const uncaught_exceptions_; +#endif + Ctx * ctx_; + + public: + + explicit BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE context_activator(Ctx & ctx) noexcept: +#if !defined(BOOST_LEAF_NO_EXCEPTIONS) && BOOST_LEAF_STD_UNCAUGHT_EXCEPTIONS + uncaught_exceptions_(std::uncaught_exceptions()), +#endif + ctx_(ctx.is_active() ? 0 : &ctx) + { + if( ctx_ ) + ctx_->activate(); + } + + BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE context_activator( context_activator && x ) noexcept: +#if !defined(BOOST_LEAF_NO_EXCEPTIONS) && BOOST_LEAF_STD_UNCAUGHT_EXCEPTIONS + uncaught_exceptions_(x.uncaught_exceptions_), +#endif + ctx_(x.ctx_) + { + x.ctx_ = 0; + } + + BOOST_LEAF_ALWAYS_INLINE ~context_activator() noexcept + { + if( !ctx_ ) + return; + if( ctx_->is_active() ) + ctx_->deactivate(); +#ifndef BOOST_LEAF_NO_EXCEPTIONS +# if BOOST_LEAF_STD_UNCAUGHT_EXCEPTIONS + if( std::uncaught_exceptions() > uncaught_exceptions_ ) +# else + if( std::uncaught_exception() ) +# endif + ctx_->propagate(); +#endif + } + }; + + template + BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE context_activator activate_context(Ctx & ctx) noexcept + { + return context_activator(ctx); + } + + //////////////////////////////////////////// + + template + struct is_result_type: std::false_type + { + }; + + template + struct is_result_type: is_result_type + { + }; + +} } + +#undef BOOST_LEAF_THREAD_LOCAL + +#endif +// <<< #include +#line 20 "boost/leaf/exception.hpp" +#include + +#define BOOST_LEAF_EXCEPTION ::boost::leaf::leaf_detail::inject_loc{__FILE__,__LINE__,__FUNCTION__}+::boost::leaf::exception +#define BOOST_LEAF_THROW_EXCEPTION ::boost::leaf::leaf_detail::throw_with_loc{__FILE__,__LINE__,__FUNCTION__}+::boost::leaf::exception + +//////////////////////////////////////// + +namespace boost { namespace leaf { + + namespace leaf_detail + { + struct throw_with_loc + { + char const * const file; + int const line; + char const * const fn; + + template + [[noreturn]] friend void operator+( throw_with_loc loc, Ex const & ex ) + { + ex.load_source_location_(loc.file, loc.line, loc.fn); + ::boost::leaf::throw_exception(ex); + } + }; + } + +} } + +//////////////////////////////////////// + +namespace boost { namespace leaf { + + namespace leaf_detail + { + inline void enforce_std_exception( std::exception const & ) noexcept { } + + class exception_base + { + std::shared_ptr auto_id_bump_; + public: + + virtual error_id get_error_id() const noexcept = 0; + + protected: + + exception_base(): + auto_id_bump_(0, [](void const *) { (void) new_id(); }) + { + } + + ~exception_base() noexcept { } + }; + + template + class exception: + public Ex, + public exception_base, + public error_id + { + error_id get_error_id() const noexcept final override + { + return *this; + } + + public: + + exception( exception const & ) = default; + exception( exception && ) = default; + + BOOST_LEAF_CONSTEXPR exception( error_id id, Ex && ex ) noexcept: + Ex(std::move(ex)), + error_id(id) + { + enforce_std_exception(*this); + } + + explicit BOOST_LEAF_CONSTEXPR exception( error_id id ) noexcept: + error_id(id) + { + enforce_std_exception(*this); + } + }; + + template + struct at_least_one_derives_from_std_exception; + + template <> + struct at_least_one_derives_from_std_exception<>: std::false_type { }; + + template + struct at_least_one_derives_from_std_exception + { + constexpr static const bool value = std::is_base_of::value || at_least_one_derives_from_std_exception::value; + }; + } + + template + inline + typename std::enable_if::value, leaf_detail::exception>::type + exception( Ex && ex, E && ... e ) noexcept + { + static_assert(!leaf_detail::at_least_one_derives_from_std_exception::value, "Error objects passed to leaf::exception may not derive from std::exception"); + auto id = leaf::new_error(std::forward(e)...); + return leaf_detail::exception(id, std::forward(ex)); + } + + template + inline + typename std::enable_if::value, leaf_detail::exception>::type + exception( E1 && car, E && ... cdr ) noexcept + { + static_assert(!leaf_detail::at_least_one_derives_from_std_exception::value, "Error objects passed to leaf::exception may not derive from std::exception"); + auto id = leaf::new_error(std::forward(car), std::forward(cdr)...); + return leaf_detail::exception(id); + } + + inline leaf_detail::exception exception() noexcept + { + return leaf_detail::exception(leaf::new_error()); + } + +} } + +#endif +// <<< #include +#line 20 "boost/leaf/capture.hpp" +// >>> #include +#line 1 "boost/leaf/on_error.hpp" +#ifndef BOOST_LEAF_ON_ERROR_HPP_INCLUDED +#define BOOST_LEAF_ON_ERROR_HPP_INCLUDED + +// Copyright (c) 2018-2020 Emil Dotchevski and Reverge Studios, Inc. + +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_LEAF_ENABLE_WARNINGS +# if defined(__clang__) +# pragma clang system_header +# elif (__GNUC__*100+__GNUC_MINOR__>301) +# pragma GCC system_header +# elif defined(_MSC_VER) +# pragma warning(push,1) +# endif +#endif + + +namespace boost { namespace leaf { + + class error_monitor + { +#if !defined(BOOST_LEAF_NO_EXCEPTIONS) && BOOST_LEAF_STD_UNCAUGHT_EXCEPTIONS + int const uncaught_exceptions_; +#endif + int const err_id_; + + public: + + error_monitor() noexcept: +#if !defined(BOOST_LEAF_NO_EXCEPTIONS) && BOOST_LEAF_STD_UNCAUGHT_EXCEPTIONS + uncaught_exceptions_(std::uncaught_exceptions()), +#endif + err_id_(leaf_detail::current_id()) + { + } + + int check_id() const noexcept + { + int err_id = leaf_detail::current_id(); + if( err_id != err_id_ ) + return err_id; + else + { +#ifndef BOOST_LEAF_NO_EXCEPTIONS +# if BOOST_LEAF_STD_UNCAUGHT_EXCEPTIONS + if( std::uncaught_exceptions() > uncaught_exceptions_ ) +# else + if( std::uncaught_exception() ) +# endif + return leaf_detail::new_id(); +#endif + return 0; + } + } + + int get_id() const noexcept + { + int err_id = leaf_detail::current_id(); + if( err_id != err_id_ ) + return err_id; + else + return leaf_detail::new_id(); + } + + error_id check() const noexcept + { + return leaf_detail::make_error_id(check_id()); + } + + error_id assigned_error_id() const noexcept + { + return leaf_detail::make_error_id(get_id()); + } + }; + + //////////////////////////////////////////// + + namespace leaf_detail + { + template + struct tuple_for_each_preload + { + BOOST_LEAF_CONSTEXPR static void trigger( Tuple & tup, int err_id ) noexcept + { + BOOST_LEAF_ASSERT((err_id&3)==1); + tuple_for_each_preload::trigger(tup,err_id); + std::get(tup).trigger(err_id); + } + }; + + template + struct tuple_for_each_preload<0, Tuple> + { + BOOST_LEAF_CONSTEXPR static void trigger( Tuple const &, int ) noexcept { } + }; + + template + class preloaded_item + { + using decay_E = typename std::decay::type; + slot * s_; + decay_E e_; + + public: + + BOOST_LEAF_CONSTEXPR preloaded_item( E && e ): + s_(tl_slot_ptr::p), + e_(std::forward(e)) + { + } + + BOOST_LEAF_CONSTEXPR void trigger( int err_id ) noexcept + { + BOOST_LEAF_ASSERT((err_id&3)==1); + if( s_ ) + { + if( !s_->has_value(err_id) ) + s_->put(err_id, std::move(e_)); + } +#if BOOST_LEAF_DIAGNOSTICS + else + { + int c = tl_unexpected_enabled<>::counter; + BOOST_LEAF_ASSERT(c>=0); + if( c ) + load_unexpected(err_id, std::move(e_)); + } +#endif + } + }; + + template + class deferred_item + { + using E = decltype(std::declval()()); + slot * s_; + F f_; + + public: + + BOOST_LEAF_CONSTEXPR deferred_item( F && f ) noexcept: + s_(tl_slot_ptr::p), + f_(std::forward(f)) + { + } + + BOOST_LEAF_CONSTEXPR void trigger( int err_id ) noexcept + { + BOOST_LEAF_ASSERT((err_id&3)==1); + if( s_ ) + { + if( !s_->has_value(err_id) ) + s_->put(err_id, f_()); + } +#if BOOST_LEAF_DIAGNOSTICS + else + { + int c = tl_unexpected_enabled<>::counter; + BOOST_LEAF_ASSERT(c>=0); + if( c ) + load_unexpected(err_id, std::forward(f_())); + } +#endif + } + }; + + template , int arity = function_traits::arity> + class accumulating_item; + + template + class accumulating_item + { + using E = A0; + slot * s_; + F f_; + + public: + + BOOST_LEAF_CONSTEXPR accumulating_item( F && f ) noexcept: + s_(tl_slot_ptr::p), + f_(std::forward(f)) + { + } + + BOOST_LEAF_CONSTEXPR void trigger( int err_id ) noexcept + { + BOOST_LEAF_ASSERT((err_id&3)==1); + if( s_ ) + if( E * e = s_->has_value(err_id) ) + (void) f_(*e); + else + (void) f_(s_->put(err_id, E())); + } + }; + + template + class preloaded + { + preloaded & operator=( preloaded const & ) = delete; + + std::tuple p_; + bool moved_; + error_monitor id_; + + public: + + BOOST_LEAF_CONSTEXPR explicit preloaded( Item && ... i ): + p_(std::forward(i)...), + moved_(false) + { + } + + BOOST_LEAF_CONSTEXPR preloaded( preloaded && x ) noexcept: + p_(std::move(x.p_)), + moved_(false), + id_(std::move(x.id_)) + { + x.moved_ = true; + } + + ~preloaded() noexcept + { + if( moved_ ) + return; + if( auto id = id_.check_id() ) + tuple_for_each_preload::trigger(p_,id); + } + }; + + template ::arity> + struct deduce_item_type; + + template + struct deduce_item_type + { + using type = preloaded_item; + }; + + template + struct deduce_item_type + { + using type = deferred_item; + }; + + template + struct deduce_item_type + { + using type = accumulating_item; + }; + } + + template + BOOST_LEAF_NODISCARD BOOST_LEAF_CONSTEXPR inline + leaf_detail::preloaded::type...> + on_error( Item && ... i ) + { + return leaf_detail::preloaded::type...>(std::forward(i)...); + } + +} } + +#endif +// <<< #include +#line 21 "boost/leaf/capture.hpp" +#include + +namespace boost { namespace leaf { + + namespace leaf_detail + { + template ::value> + struct is_result_tag; + + template + struct is_result_tag + { + }; + + template + struct is_result_tag + { + }; + } + +#ifdef BOOST_LEAF_NO_EXCEPTIONS + + namespace leaf_detail + { + template + inline + decltype(std::declval()(std::forward(std::declval())...)) + capture_impl(is_result_tag, context_ptr && ctx, F && f, A... a) noexcept + { + auto active_context = activate_context(*ctx); + return std::forward(f)(std::forward(a)...); + } + + template + inline + decltype(std::declval()(std::forward(std::declval())...)) + capture_impl(is_result_tag, context_ptr && ctx, F && f, A... a) noexcept + { + auto active_context = activate_context(*ctx); + if( auto r = std::forward(f)(std::forward(a)...) ) + return r; + else + { + ctx->captured_id_ = r.error(); + return std::move(ctx); + } + } + + template + inline + decltype(std::declval().get()) + future_get_impl(is_result_tag, Future & fut) noexcept + { + return fut.get(); + } + + template + inline + decltype(std::declval().get()) + future_get_impl(is_result_tag, Future & fut) noexcept + { + if( auto r = fut.get() ) + return r; + else + return error_id(r.error()); // unloads + } + } + +#else + + namespace leaf_detail + { + class capturing_exception: + public std::exception + { + std::exception_ptr ex_; + context_ptr ctx_; + + public: + + capturing_exception(std::exception_ptr && ex, context_ptr && ctx) noexcept: + ex_(std::move(ex)), + ctx_(std::move(ctx)) + { + BOOST_LEAF_ASSERT(ex_); + BOOST_LEAF_ASSERT(ctx_); + BOOST_LEAF_ASSERT(ctx_->captured_id_); + } + + [[noreturn]] void unload_and_rethrow_original_exception() const + { + BOOST_LEAF_ASSERT(ctx_->captured_id_); + auto active_context = activate_context(*ctx_); + id_factory<>::current_id = ctx_->captured_id_.value(); + std::rethrow_exception(ex_); + } + + void print( std::ostream & os ) const + { + ctx_->print(os); + } + }; + + template + inline + decltype(std::declval()(std::forward(std::declval())...)) + capture_impl(is_result_tag, context_ptr && ctx, F && f, A... a) + { + auto active_context = activate_context(*ctx); + error_monitor cur_err; + try + { + return std::forward(f)(std::forward(a)...); + } + catch( capturing_exception const & ) + { + throw; + } + catch( exception_base const & e ) + { + ctx->captured_id_ = e.get_error_id(); + throw_exception( capturing_exception(std::current_exception(), std::move(ctx)) ); + } + catch(...) + { + ctx->captured_id_ = cur_err.assigned_error_id(); + throw_exception( capturing_exception(std::current_exception(), std::move(ctx)) ); + } + } + + template + inline + decltype(std::declval()(std::forward(std::declval())...)) + capture_impl(is_result_tag, context_ptr && ctx, F && f, A... a) + { + auto active_context = activate_context(*ctx); + error_monitor cur_err; + try + { + if( auto && r = std::forward(f)(std::forward(a)...) ) + return std::move(r); + else + { + ctx->captured_id_ = r.error(); + return std::move(ctx); + } + } + catch( capturing_exception const & ) + { + throw; + } + catch( exception_base const & e ) + { + ctx->captured_id_ = e.get_error_id(); + throw_exception( capturing_exception(std::current_exception(), std::move(ctx)) ); + } + catch(...) + { + ctx->captured_id_ = cur_err.assigned_error_id(); + throw_exception( capturing_exception(std::current_exception(), std::move(ctx)) ); + } + } + + template + inline + decltype(std::declval().get()) + future_get_impl(is_result_tag, Future & fut ) + { + try + { + return fut.get(); + } + catch( capturing_exception const & cap ) + { + cap.unload_and_rethrow_original_exception(); + } + } + + template + inline + decltype(std::declval().get()) + future_get_impl(is_result_tag, Future & fut ) + { + try + { + if( auto r = fut.get() ) + return r; + else + return error_id(r.error()); // unloads + } + catch( capturing_exception const & cap ) + { + cap.unload_and_rethrow_original_exception(); + } + } + } + +#endif + + template + inline + decltype(std::declval()(std::forward(std::declval())...)) + capture(context_ptr && ctx, F && f, A... a) + { + using namespace leaf_detail; + return capture_impl(is_result_tag()(std::forward(std::declval())...))>(), std::move(ctx), std::forward(f), std::forward(a)...); + } + + template + inline + decltype(std::declval().get()) + future_get( Future & fut ) + { + using namespace leaf_detail; + return future_get_impl(is_result_tag().get())>(), fut); + } + + //////////////////////////////////////// + +#ifndef BOOST_LEAF_NO_EXCEPTIONS + + template + class result; + + namespace leaf_detail + { + inline error_id catch_exceptions_helper( std::exception const & ex, leaf_detail_mp11::mp_list<> ) + { + return leaf::new_error(std::current_exception()); + } + + template + inline error_id catch_exceptions_helper( std::exception const & ex, leaf_detail_mp11::mp_list ) + { + if( Ex1 const * p = dynamic_cast(&ex) ) + return catch_exceptions_helper(ex, leaf_detail_mp11::mp_list{ }).load(*p); + else + return catch_exceptions_helper(ex, leaf_detail_mp11::mp_list{ }); + } + + template + struct deduce_exception_to_result_return_type_impl + { + using type = result; + }; + + template + struct deduce_exception_to_result_return_type_impl> + { + using type = result; + }; + + template + using deduce_exception_to_result_return_type = typename deduce_exception_to_result_return_type_impl::type; + } + + template + inline + leaf_detail::deduce_exception_to_result_return_type> + exception_to_result( F && f ) noexcept + { + try + { + return std::forward(f)(); + } + catch( std::exception const & ex ) + { + return leaf_detail::catch_exceptions_helper(ex, leaf_detail_mp11::mp_list()); + } + catch(...) + { + return leaf::new_error(std::current_exception()); + } + } + +#endif + +} } + +#endif +// <<< #include +#line 10 "../../include/boost/leaf/detail/all.hpp" +// >>> #include +#line 1 "boost/leaf/common.hpp" +#ifndef BOOST_LEAF_COMMON_HPP_INCLUDED +#define BOOST_LEAF_COMMON_HPP_INCLUDED + +// Copyright (c) 2018-2020 Emil Dotchevski and Reverge Studios, Inc. + +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_LEAF_ENABLE_WARNINGS +# if defined(__clang__) +# pragma clang system_header +# elif (__GNUC__*100+__GNUC_MINOR__>301) +# pragma GCC system_header +# elif defined(_MSC_VER) +# pragma warning(push,1) +# endif +#endif + +#include +#include +#ifdef _WIN32 +# include +# include +#ifdef min +# undef min +#endif +#ifdef max +# undef max +#endif +#endif + +namespace boost { namespace leaf { + + struct e_api_function { char const * value; }; + + struct e_file_name { std::string value; }; + + struct e_errno + { + int value; + + friend std::ostream & operator<<( std::ostream & os, e_errno const & err ) + { + return os << type() << ": " << err.value << ", \"" << std::strerror(err.value) << '"'; + } + }; + + struct e_type_info_name { char const * value; }; + + struct e_at_line { int value; }; + + namespace windows + { + struct e_LastError + { + unsigned value; + +#ifdef _WIN32 + friend std::ostream & operator<<( std::ostream & os, e_LastError const & err ) + { + struct msg_buf + { + LPVOID * p; + msg_buf(): p(0) { } + ~msg_buf() noexcept { if(p) LocalFree(p); } + }; + msg_buf mb; + if( FormatMessageA( + FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, + 0, + err.value, + MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT), + (LPSTR)&mb.p, + 0, + 0) ) + { + BOOST_LEAF_ASSERT(mb.p != 0); + char * z = std::strchr((LPSTR)mb.p,0); + if( z[-1] == '\n' ) + *--z = 0; + if( z[-1] == '\r' ) + *--z = 0; + return os << type() << ": " << err.value << ", \"" << (LPCSTR)mb.p << '"'; + } + return os; + } +#else + // TODO : Other platforms +#endif + }; + } + +} } + +#endif +// <<< #include +#line 11 "../../include/boost/leaf/detail/all.hpp" +// >>> #include +#line 1 "boost/leaf/context.hpp" +#ifndef BOOST_LEAF_CONTEXT_HPP_INCLUDED +#define BOOST_LEAF_CONTEXT_HPP_INCLUDED + +// Copyright (c) 2018-2020 Emil Dotchevski and Reverge Studios, Inc. + +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_LEAF_ENABLE_WARNINGS +# if defined(__clang__) +# pragma clang system_header +# elif (__GNUC__*100+__GNUC_MINOR__>301) +# pragma GCC system_header +# elif defined(_MSC_VER) +# pragma warning(push,1) +# endif +#endif + + +namespace boost { namespace leaf { + + class error_info; + class diagnostic_info; + class verbose_diagnostic_info; + + template + struct is_predicate: std::false_type + { + }; + + namespace leaf_detail + { + template + struct is_exception: std::is_base_of::type> + { + }; + + template + struct handler_argument_traits; + + template ::value> + struct handler_argument_traits_defaults; + + template + struct handler_argument_traits_defaults + { + using error_type = typename std::decay::type; + constexpr static bool always_available = false; + + template + BOOST_LEAF_CONSTEXPR static error_type const * check( Tup const &, error_info const & ) noexcept; + + template + BOOST_LEAF_CONSTEXPR static error_type * check( Tup &, error_info const & ) noexcept; + + template + BOOST_LEAF_CONSTEXPR static E get( Tup & tup, error_info const & ei ) noexcept + { + return *check(tup, ei); + } + + static_assert(!is_predicate::value, "Handlers must take predicate arguments by value"); + static_assert(!std::is_same::value, "Handlers must take leaf::error_info arguments by const &"); + static_assert(!std::is_same::value, "Handlers must take leaf::diagnostic_info arguments by const &"); + static_assert(!std::is_same::value, "Handlers must take leaf::verbose_diagnostic_info arguments by const &"); + }; + + template + struct handler_argument_traits_defaults: handler_argument_traits + { + using base = handler_argument_traits; + static_assert(!base::always_available, "Predicates can't use types that are always_available"); + + template + BOOST_LEAF_CONSTEXPR static bool check( Tup & tup, error_info const & ei ) noexcept + { + auto e = base::check(tup, ei); + return e && Pred::evaluate(*e); + }; + + template + BOOST_LEAF_CONSTEXPR static Pred get( Tup const & tup, error_info const & ei ) noexcept + { + return Pred{*base::check(tup, ei)}; + } + }; + + template + struct handler_argument_always_available + { + using error_type = E; + constexpr static bool always_available = true; + + template + BOOST_LEAF_CONSTEXPR static bool check( Tup &, error_info const & ) noexcept + { + return true; + }; + }; + + template + struct handler_argument_traits: handler_argument_traits_defaults + { + }; + + template <> + struct handler_argument_traits + { + using error_type = void; + constexpr static bool always_available = false; + + template + BOOST_LEAF_CONSTEXPR static std::exception const * check( Tup const &, error_info const & ) noexcept; + }; + + template + struct handler_argument_traits + { + static_assert(sizeof(E) == 0, "Error handlers may not take rvalue ref arguments"); + }; + + template + struct handler_argument_traits: handler_argument_always_available::type> + { + template + BOOST_LEAF_CONSTEXPR static E * get( Tup & tup, error_info const & ei) noexcept + { + return handler_argument_traits_defaults::check(tup, ei); + } + }; + + template <> + struct handler_argument_traits: handler_argument_always_available + { + template + BOOST_LEAF_CONSTEXPR static error_info const & get( Tup const &, error_info const & ei ) noexcept + { + return ei; + } + }; + + template + struct handler_argument_traits_require_by_value + { + static_assert(sizeof(E) == 0, "Error handlers must take this type by value"); + }; + } + + //////////////////////////////////////// + + namespace leaf_detail + { + template + struct tuple_for_each + { + BOOST_LEAF_CONSTEXPR static void activate( Tuple & tup ) noexcept + { + static_assert(!std::is_same(tup))>::type>::value, "Bug in LEAF: context type deduction"); + tuple_for_each::activate(tup); + std::get(tup).activate(); + } + + BOOST_LEAF_CONSTEXPR static void deactivate( Tuple & tup ) noexcept + { + static_assert(!std::is_same(tup))>::type>::value, "Bug in LEAF: context type deduction"); + std::get(tup).deactivate(); + tuple_for_each::deactivate(tup); + } + + BOOST_LEAF_CONSTEXPR static void propagate( Tuple & tup ) noexcept + { + static_assert(!std::is_same(tup))>::type>::value, "Bug in LEAF: context type deduction"); + auto & sl = std::get(tup); + sl.propagate(); + tuple_for_each::propagate(tup); + } + + BOOST_LEAF_CONSTEXPR static void propagate_captured( Tuple & tup, int err_id ) noexcept + { + static_assert(!std::is_same(tup))>::type>::value, "Bug in LEAF: context type deduction"); + auto & sl = std::get(tup); + if( sl.has_value(err_id) ) + load_slot(err_id, std::move(sl).value(err_id)); + tuple_for_each::propagate_captured(tup, err_id); + } + + static void print( std::ostream & os, void const * tup, int key_to_print ) + { + BOOST_LEAF_ASSERT(tup != 0); + tuple_for_each::print(os, tup, key_to_print); + std::get(*static_cast(tup)).print(os, key_to_print); + } + }; + + template + struct tuple_for_each<0, Tuple> + { + BOOST_LEAF_CONSTEXPR static void activate( Tuple & ) noexcept { } + BOOST_LEAF_CONSTEXPR static void deactivate( Tuple & ) noexcept { } + BOOST_LEAF_CONSTEXPR static void propagate( Tuple & tup ) noexcept { } + BOOST_LEAF_CONSTEXPR static void propagate_captured( Tuple & tup, int ) noexcept { } + static void print( std::ostream &, void const *, int ) { } + }; + } + + //////////////////////////////////////////// + +#if BOOST_LEAF_DIAGNOSTICS + + namespace leaf_detail + { + template struct requires_unexpected { constexpr static bool value = false; }; + template struct requires_unexpected { constexpr static bool value = requires_unexpected::value; }; + template struct requires_unexpected { constexpr static bool value = requires_unexpected::value; }; + template struct requires_unexpected { constexpr static bool value = requires_unexpected::value; }; + template <> struct requires_unexpected { constexpr static bool value = true; }; + template <> struct requires_unexpected { constexpr static bool value = true; }; + + template + struct unexpected_requested; + + template