#ifndef BOOST_LEAF_HPP_INCLUDED #define BOOST_LEAF_HPP_INCLUDED // LEAF single header distribution. Do not edit. // Generated on 01/28/2024 from https://github.com/boostorg/leaf/tree/ed8f9cd. // Latest version of this file: https://raw.githubusercontent.com/boostorg/leaf/gh-pages/leaf.hpp. // Copyright 2018-2023 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/config.hpp" #ifndef BOOST_LEAF_CONFIG_HPP_INCLUDED #define BOOST_LEAF_CONFIG_HPP_INCLUDED // Copyright 2018-2023 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 in part on Boost Config. // (C) Copyright John Maddock 2001 - 2003. // (C) Copyright Martin Wille 2003. // (C) Copyright Guillaume Melquiond 2003. #ifndef BOOST_LEAF_ASSERT # include # define BOOST_LEAF_ASSERT assert #endif //////////////////////////////////////// #ifdef BOOST_LEAF_DIAGNOSTICS # warning BOOST_LEAF_DIAGNOSTICS has been renamed to BOOST_LEAF_CFG_DIAGNOSTICS. # define BOOST_LEAF_CFG_DIAGNOSTICS BOOST_LEAF_DIAGNOSTICS #endif //////////////////////////////////////// #ifdef BOOST_LEAF_TLS_FREERTOS # ifndef BOOST_LEAF_EMBEDDED # define BOOST_LEAF_EMBEDDED # endif #endif //////////////////////////////////////// #ifdef BOOST_LEAF_EMBEDDED # ifndef BOOST_LEAF_CFG_DIAGNOSTICS # define BOOST_LEAF_CFG_DIAGNOSTICS 0 # endif # ifndef BOOST_LEAF_CFG_STD_SYSTEM_ERROR # define BOOST_LEAF_CFG_STD_SYSTEM_ERROR 0 # endif # ifndef BOOST_LEAF_CFG_STD_STRING # define BOOST_LEAF_CFG_STD_STRING 0 # endif # ifndef BOOST_LEAF_CFG_CAPTURE # define BOOST_LEAF_CFG_CAPTURE 0 # endif #endif //////////////////////////////////////// #ifndef BOOST_LEAF_CFG_DIAGNOSTICS # define BOOST_LEAF_CFG_DIAGNOSTICS 1 #endif #ifndef BOOST_LEAF_CFG_STD_SYSTEM_ERROR # define BOOST_LEAF_CFG_STD_SYSTEM_ERROR 1 #endif #ifndef BOOST_LEAF_CFG_STD_STRING # define BOOST_LEAF_CFG_STD_STRING 1 #endif #ifndef BOOST_LEAF_CFG_CAPTURE # define BOOST_LEAF_CFG_CAPTURE 1 #endif #ifndef BOOST_LEAF_CFG_WIN32 # define BOOST_LEAF_CFG_WIN32 0 #endif #ifndef BOOST_LEAF_CFG_GNUC_STMTEXPR # ifdef __GNUC__ # define BOOST_LEAF_CFG_GNUC_STMTEXPR 1 # else # define BOOST_LEAF_CFG_GNUC_STMTEXPR 0 # endif #endif #if BOOST_LEAF_CFG_DIAGNOSTICS!=0 && BOOST_LEAF_CFG_DIAGNOSTICS!=1 # error BOOST_LEAF_CFG_DIAGNOSTICS must be 0 or 1. #endif #if BOOST_LEAF_CFG_STD_SYSTEM_ERROR!=0 && BOOST_LEAF_CFG_STD_SYSTEM_ERROR!=1 # error BOOST_LEAF_CFG_STD_SYSTEM_ERROR must be 0 or 1. #endif #if BOOST_LEAF_CFG_STD_STRING!=0 && BOOST_LEAF_CFG_STD_STRING!=1 # error BOOST_LEAF_CFG_STD_STRING must be 0 or 1. #endif #if BOOST_LEAF_CFG_CAPTURE!=0 && BOOST_LEAF_CFG_CAPTURE!=1 # error BOOST_LEAF_CFG_CAPTURE must be 0 or 1. #endif #if BOOST_LEAF_CFG_WIN32!=0 && BOOST_LEAF_CFG_WIN32!=1 # error BOOST_LEAF_CFG_WIN32 must be 0 or 1. #endif #if BOOST_LEAF_CFG_GNUC_STMTEXPR!=0 && BOOST_LEAF_CFG_GNUC_STMTEXPR!=1 # error BOOST_LEAF_CFG_GNUC_STMTEXPR must be 0 or 1. #endif #if BOOST_LEAF_CFG_DIAGNOSTICS && !BOOST_LEAF_CFG_STD_STRING # error BOOST_LEAF_CFG_DIAGNOSTICS requires BOOST_LEAF_CFG_STD_STRING, which has been disabled. #endif #if BOOST_LEAF_CFG_STD_SYSTEM_ERROR && !BOOST_LEAF_CFG_STD_STRING # error BOOST_LEAF_CFG_STD_SYSTEM_ERROR requires BOOST_LEAF_CFG_STD_STRING, which has been disabled. #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 !_CPPUNWIND # define BOOST_LEAF_NO_EXCEPTIONS # endif # endif #endif //////////////////////////////////////// #ifdef _MSC_VER # define BOOST_LEAF_ALWAYS_INLINE __forceinline #else # define BOOST_LEAF_ALWAYS_INLINE __attribute__((always_inline)) inline #endif //////////////////////////////////////// #if defined(__has_attribute) && defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x5130) # if __has_attribute(nodiscard) # define BOOST_LEAF_ATTRIBUTE_NODISCARD [[nodiscard]] # endif #elif defined(__has_cpp_attribute) //clang-6 accepts [[nodiscard]] with -std=c++14, but warns about it -pedantic # if __has_cpp_attribute(nodiscard) && !(defined(__clang__) && (__cplusplus < 201703L)) && !(defined(__GNUC__) && (__cplusplus < 201100)) # define BOOST_LEAF_ATTRIBUTE_NODISCARD [[nodiscard]] # endif #endif #ifndef BOOST_LEAF_ATTRIBUTE_NODISCARD # define BOOST_LEAF_ATTRIBUTE_NODISCARD #endif //////////////////////////////////////// #ifndef BOOST_LEAF_CONSTEXPR # if __cplusplus > 201402L # define BOOST_LEAF_CONSTEXPR constexpr # else # define BOOST_LEAF_CONSTEXPR # endif #endif //////////////////////////////////////// #ifndef BOOST_LEAF_DEPRECATED # if __cplusplus > 201402L # define BOOST_LEAF_DEPRECATED(msg) [[deprecated(msg)]] # else # define BOOST_LEAF_DEPRECATED(msg) # endif #endif //////////////////////////////////////// #ifndef BOOST_LEAF_NO_EXCEPTIONS # include # if (defined(__cpp_lib_uncaught_exceptions) && __cpp_lib_uncaught_exceptions >= 201411L) || (defined(_MSC_VER) && _MSC_VER >= 1900) # define BOOST_LEAF_STD_UNCAUGHT_EXCEPTIONS 1 # else # define BOOST_LEAF_STD_UNCAUGHT_EXCEPTIONS 0 # endif #endif //////////////////////////////////////// #ifdef __GNUC__ # define BOOST_LEAF_SYMBOL_VISIBLE __attribute__((__visibility__("default"))) #else # define BOOST_LEAF_SYMBOL_VISIBLE #endif //////////////////////////////////////// #if defined(__GNUC__) && !(defined(__clang__) || defined(__INTEL_COMPILER) || defined(__ICL) || defined(__ICC) || defined(__ECC)) && (__GNUC__ * 100 + __GNUC_MINOR__) < 409 # ifndef BOOST_LEAF_NO_CXX11_REF_QUALIFIERS # define BOOST_LEAF_NO_CXX11_REF_QUALIFIERS # endif #endif //////////////////////////////////////// // Configure TLS access // >>> #include #line 1 "boost/leaf/config/tls.hpp" #ifndef BOOST_LEAF_CONFIG_TLS_HPP_INCLUDED #define BOOST_LEAF_CONFIG_TLS_HPP_INCLUDED // Copyright 2018-2023 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) #if defined(BOOST_LEAF_TLS_FREERTOS) // >>> # include #line 1 "boost/leaf/config/tls_freertos.hpp" #ifndef BOOST_LEAF_CONFIG_TLS_FREERTOS_HPP_INCLUDED #define BOOST_LEAF_CONFIG_TLS_FREERTOS_HPP_INCLUDED // Copyright 2018-2023 Emil Dotchevski and Reverge Studios, Inc. // Copyright (c) 2022 Khalil Estell // 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) // LEAF requires thread local storage support for pointers and for uin32_t values. // This header implements "thread local" storage via FreeTOS functions // pvTaskGetThreadLocalStoragePointer / pvTaskSetThreadLocalStoragePointer #include #ifndef BOOST_LEAF_USE_TLS_ARRAY # define BOOST_LEAF_USE_TLS_ARRAY #endif #ifndef BOOST_LEAF_CFG_TLS_ARRAY_SIZE # define BOOST_LEAF_CFG_TLS_ARRAY_SIZE configNUM_THREAD_LOCAL_STORAGE_POINTERS #endif static_assert((BOOST_LEAF_CFG_TLS_ARRAY_SIZE) <= configNUM_THREAD_LOCAL_STORAGE_POINTERS, "Bad BOOST_LEAF_CFG_TLS_ARRAY_SIZE"); namespace boost { namespace leaf { namespace tls { // See https://www.freertos.org/thread-local-storage-pointers.html. inline void * read_void_ptr( int tls_index ) noexcept { return pvTaskGetThreadLocalStoragePointer(0, tls_index); } inline void write_void_ptr( int tls_index, void * p ) noexcept { vTaskSetThreadLocalStoragePointer(0, tls_index, p); } } } } #endif // <<< # include #line 11 "boost/leaf/config/tls.hpp" #endif #ifndef BOOST_LEAF_USE_TLS_ARRAY # ifdef BOOST_LEAF_CFG_TLS_INDEX_TYPE # warning "BOOST_LEAF_CFG_TLS_INDEX_TYPE" is ignored if BOOST_LEAF_USE_TLS_ARRAY is not defined. # endif # ifdef BOOST_LEAF_CFG_TLS_ARRAY_SIZE # warning "BOOST_LEAF_CFG_TLS_ARRAY_SIZE" is ignored if BOOST_LEAF_USE_TLS_ARRAY is not defined. # endif # ifdef BOOST_LEAF_CFG_TLS_ARRAY_START_INDEX # warning "BOOST_LEAF_CFG_TLS_ARRAY_START_INDEX" is ignored if BOOST_LEAF_USE_TLS_ARRAY is not defined. # endif #endif #if defined BOOST_LEAF_USE_TLS_ARRAY // >>> # include #line 1 "boost/leaf/config/tls_array.hpp" #ifndef BOOST_LEAF_CONFIG_TLS_ARRAY_HPP_INCLUDED #define BOOST_LEAF_CONFIG_TLS_ARRAY_HPP_INCLUDED // Copyright 2018-2023 Emil Dotchevski and Reverge Studios, Inc. // Copyright (c) 2022 Khalil Estell // 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) // LEAF requires thread local storage support for pointers and for uin32_t values. // This header implements thread local storage for pointers and for unsigned int // values for platforms that support thread local pointers by index. namespace boost { namespace leaf { namespace tls { // The TLS support defined in this header requires the following two // functions to be defined elsewhere: void * read_void_ptr( int tls_index ) noexcept; void write_void_ptr( int tls_index, void * ) noexcept; } } } //////////////////////////////////////// #include #include #include #include #ifndef BOOST_LEAF_CFG_TLS_INDEX_TYPE # define BOOST_LEAF_CFG_TLS_INDEX_TYPE unsigned char #endif #ifndef BOOST_LEAF_CFG_TLS_ARRAY_START_INDEX # define BOOST_LEAF_CFG_TLS_ARRAY_START_INDEX 0 #endif static_assert((BOOST_LEAF_CFG_TLS_ARRAY_START_INDEX) >= 0, "Bad BOOST_LEAF_CFG_TLS_ARRAY_START_INDEX"); #ifdef BOOST_LEAF_CFG_TLS_ARRAY_SIZE static_assert((BOOST_LEAF_CFG_TLS_ARRAY_SIZE) > (BOOST_LEAF_CFG_TLS_ARRAY_START_INDEX), "Bad BOOST_LEAF_CFG_TLS_ARRAY_SIZE"); static_assert((BOOST_LEAF_CFG_TLS_ARRAY_SIZE) - 1 <= std::numeric_limits::max(), "Bad BOOST_LEAF_CFG_TLS_ARRAY_SIZE"); #endif //////////////////////////////////////// namespace boost { namespace leaf { namespace leaf_detail { using atomic_unsigned_int = std::atomic; } namespace tls { template class BOOST_LEAF_SYMBOL_VISIBLE index_counter { static int c_; static BOOST_LEAF_CFG_TLS_INDEX_TYPE next_() noexcept { int idx = ++c_; BOOST_LEAF_ASSERT(idx > (BOOST_LEAF_CFG_TLS_ARRAY_START_INDEX)); BOOST_LEAF_ASSERT(idx < (BOOST_LEAF_CFG_TLS_ARRAY_SIZE)); return idx; } public: template static BOOST_LEAF_CFG_TLS_INDEX_TYPE next() noexcept { return next_(); // Set breakpoint here to monitor TLS index allocation for T. } }; template struct BOOST_LEAF_SYMBOL_VISIBLE tls_index { static BOOST_LEAF_CFG_TLS_INDEX_TYPE idx; }; template struct BOOST_LEAF_SYMBOL_VISIBLE alloc_tls_index { static BOOST_LEAF_CFG_TLS_INDEX_TYPE const idx; }; template int index_counter::c_ = BOOST_LEAF_CFG_TLS_ARRAY_START_INDEX; template BOOST_LEAF_CFG_TLS_INDEX_TYPE tls_index::idx = BOOST_LEAF_CFG_TLS_ARRAY_START_INDEX; template BOOST_LEAF_CFG_TLS_INDEX_TYPE const alloc_tls_index::idx = tls_index::idx = index_counter<>::next(); //////////////////////////////////////// template T * read_ptr() noexcept { int tls_idx = tls_index::idx; if( tls_idx == (BOOST_LEAF_CFG_TLS_ARRAY_START_INDEX) ) return nullptr; --tls_idx; return reinterpret_cast(read_void_ptr(tls_idx)); } template void write_ptr( T * p ) noexcept { int tls_idx = alloc_tls_index::idx; --tls_idx; write_void_ptr(tls_idx, p); BOOST_LEAF_ASSERT(read_void_ptr(tls_idx) == p); } //////////////////////////////////////// template unsigned read_uint() noexcept { static_assert(sizeof(std::intptr_t) >= sizeof(unsigned), "Incompatible tls_array implementation"); return (unsigned) (std::intptr_t) (void *) read_ptr(); } template void write_uint( unsigned x ) noexcept { static_assert(sizeof(std::intptr_t) >= sizeof(unsigned), "Incompatible tls_array implementation"); write_ptr((Tag *) (void *) (std::intptr_t) x); } template void uint_increment() noexcept { write_uint(read_uint() + 1); } template void uint_decrement() noexcept { write_uint(read_uint() - 1); } } } } #endif // <<< # include #line 27 "boost/leaf/config/tls.hpp" #elif defined(BOOST_LEAF_NO_THREADS) // >>> # include #line 1 "boost/leaf/config/tls_globals.hpp" #ifndef BOOST_LEAF_CONFIG_TLS_GLOBALS_HPP_INCLUDED #define BOOST_LEAF_CONFIG_TLS_GLOBALS_HPP_INCLUDED // Copyright 2018-2023 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) // LEAF requires thread local storage support for pointers and for uin32_t values. // This header implements "thread local" storage for pointers and for unsigned int // values using globals, which is suitable for single thread environments. #include namespace boost { namespace leaf { namespace leaf_detail { using atomic_unsigned_int = unsigned int; } namespace tls { template struct BOOST_LEAF_SYMBOL_VISIBLE ptr { static T * p; }; template T * ptr::p; template T * read_ptr() noexcept { return ptr::p; } template void write_ptr( T * p ) noexcept { ptr::p = p; } //////////////////////////////////////// template struct BOOST_LEAF_SYMBOL_VISIBLE tagged_uint { static unsigned x; }; template unsigned tagged_uint::x; template unsigned read_uint() noexcept { return tagged_uint::x; } template void write_uint( unsigned x ) noexcept { tagged_uint::x = x; } template void uint_increment() noexcept { ++tagged_uint::x; } template void uint_decrement() noexcept { --tagged_uint::x; } } } } #endif // <<< # include #line 29 "boost/leaf/config/tls.hpp" #else // >>> # include #line 1 "boost/leaf/config/tls_cpp11.hpp" #ifndef BOOST_LEAF_CONFIG_TLS_CPP11_HPP_INCLUDED #define BOOST_LEAF_CONFIG_TLS_CPP11_HPP_INCLUDED // Copyright 2018-2023 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) // LEAF requires thread local storage support for pointers and for uin32_t values. // This header implements thread local storage for pointers and for unsigned int // values using the C++11 built-in thread_local storage class specifier. #include #include namespace boost { namespace leaf { namespace leaf_detail { using atomic_unsigned_int = std::atomic; } namespace tls { template struct BOOST_LEAF_SYMBOL_VISIBLE ptr { static thread_local T * p; }; template thread_local T * ptr::p; template T * read_ptr() noexcept { return ptr::p; } template void write_ptr( T * p ) noexcept { ptr::p = p; } //////////////////////////////////////// template struct BOOST_LEAF_SYMBOL_VISIBLE tagged_uint { static thread_local unsigned x; }; template thread_local unsigned tagged_uint::x; template unsigned read_uint() noexcept { return tagged_uint::x; } template void write_uint( unsigned x ) noexcept { tagged_uint::x = x; } template void uint_increment() noexcept { ++tagged_uint::x; } template void uint_decrement() noexcept { --tagged_uint::x; } } } } #endif // <<< # include #line 31 "boost/leaf/config/tls.hpp" #endif #endif // <<< #include #line 277 "boost/leaf/config.hpp" //////////////////////////////////////// #endif // >>> #include #line 1 "boost/leaf/capture.hpp" #ifndef BOOST_LEAF_CAPTURE_HPP_INCLUDED #define BOOST_LEAF_CAPTURE_HPP_INCLUDED // Copyright 2018-2023 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) // Expanded at line 16: #include // >>> #include #line 1 "boost/leaf/handle_errors.hpp" #ifndef BOOST_LEAF_HANDLE_ERRORS_HPP_INCLUDED #define BOOST_LEAF_HANDLE_ERRORS_HPP_INCLUDED // Copyright 2018-2023 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) // Expanded at line 16: #include // >>> #include #line 1 "boost/leaf/context.hpp" #ifndef BOOST_LEAF_CONTEXT_HPP_INCLUDED #define BOOST_LEAF_CONTEXT_HPP_INCLUDED // Copyright 2018-2023 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) // Expanded at line 16: #include // >>> #include #line 1 "boost/leaf/error.hpp" #ifndef BOOST_LEAF_ERROR_HPP_INCLUDED #define BOOST_LEAF_ERROR_HPP_INCLUDED // Copyright 2018-2023 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) // Expanded at line 16: #include // >>> #include #line 1 "boost/leaf/detail/optional.hpp" #ifndef BOOST_LEAF_DETAIL_OPTIONAL_HPP_INCLUDED #define BOOST_LEAF_DETAIL_OPTIONAL_HPP_INCLUDED // Copyright 2018-2023 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) // Expanded at line 16: #include #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() ) { load(key, x.value_); key_ = key; } return *this; } BOOST_LEAF_CONSTEXPR optional & operator=( optional && x ) noexcept { reset(); if( int key = x.key() ) { load(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 & load( int key ) { BOOST_LEAF_ASSERT(key); reset(); (void) new(&value_) T; key_=key; return value_; } BOOST_LEAF_CONSTEXPR T & load( int key, T const & v ) { BOOST_LEAF_ASSERT(key); reset(); (void) new(&value_) T(v); key_=key; return value_; } BOOST_LEAF_CONSTEXPR T & load( 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_ : nullptr; } BOOST_LEAF_CONSTEXPR T * has_value(int key) noexcept { BOOST_LEAF_ASSERT(key); return key_==key ? &value_ : nullptr; } BOOST_LEAF_CONSTEXPR T const & value(int key) const & noexcept { BOOST_LEAF_ASSERT(has_value(key) != 0); (void) key; return value_; } BOOST_LEAF_CONSTEXPR T & value(int key) & noexcept { BOOST_LEAF_ASSERT(has_value(key) != 0); (void) key; return value_; } BOOST_LEAF_CONSTEXPR T const && value(int key) const && noexcept { BOOST_LEAF_ASSERT(has_value(key) != 0); (void) key; return value_; } BOOST_LEAF_CONSTEXPR T value(int key) && noexcept { BOOST_LEAF_ASSERT(has_value(key) != 0); (void) key; T tmp(std::move(value_)); reset(); return tmp; } }; } } } #endif // <<< #include #line 11 "boost/leaf/error.hpp" // >>> #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 2018-2023 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/detail/mp11.hpp" #ifndef BOOST_LEAF_DETAIL_MP11_HPP_INCLUDED #define BOOST_LEAF_DETAIL_MP11_HPP_INCLUDED // Copyright 2015-2017 Peter Dimov. // Copyright 2018-2023 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 #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 10 "boost/leaf/detail/function_traits.hpp" #include namespace boost { namespace leaf { namespace leaf_detail { template struct remove_noexcept { using type = T; }; template struct remove_noexcept { using type = R(*)(A...); }; template struct remove_noexcept { using type = R(C::*)(A...); }; template struct remove_noexcept { using type = R(C::*)(A...) const; }; template struct gcc49_workaround //Thanks Glen Fernandes { using type = void; }; template using void_t = typename gcc49_workaround::type; template struct function_traits_impl { constexpr static int arity = -1; }; template struct function_traits_impl> { private: using tr = function_traits_impl::type>; 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_impl { 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_impl : function_traits_impl { }; template struct function_traits_impl : function_traits_impl { }; template struct function_traits_impl : function_traits_impl { }; template struct function_traits_impl : function_traits_impl { }; template struct function_traits_impl : function_traits_impl { }; template struct function_traits_impl : function_traits_impl { }; template struct function_traits_impl : function_traits_impl { }; template struct function_traits_impl : function_traits_impl { }; template struct function_traits: function_traits_impl::type> { }; 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 12 "boost/leaf/error.hpp" // >>> #include #line 1 "boost/leaf/detail/capture_list.hpp" #ifndef BOOST_LEAF_DETAIL_CAPTURE_HPP_INCLUDED #define BOOST_LEAF_DETAIL_CAPTURE_HPP_INCLUDED // Copyright 2018-2023 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) // Expanded at line 16: #include #if BOOST_LEAF_CFG_CAPTURE #include namespace boost { namespace leaf { namespace leaf_detail { struct BOOST_LEAF_SYMBOL_VISIBLE tls_tag_id_factory_current_id; class capture_list { capture_list( capture_list const & ) = delete; capture_list & operator=( capture_list const & ) = delete; protected: class node { friend class capture_list; virtual void unload( int err_id ) = 0; #if BOOST_LEAF_CFG_DIAGNOSTICS virtual void print( std::ostream &, int err_id_to_print ) const = 0; #endif protected: virtual ~node() noexcept { }; node * next_; BOOST_LEAF_CONSTEXPR explicit node( node * * & last ) noexcept: next_(nullptr) { BOOST_LEAF_ASSERT(last != nullptr); *last = this; last = &next_; } } * first_; template BOOST_LEAF_CONSTEXPR void for_each( F f ) const { for( node * p=first_; p; p=p->next_ ) f(*p); } public: BOOST_LEAF_CONSTEXPR explicit capture_list( node * first ) noexcept: first_(first) { } BOOST_LEAF_CONSTEXPR capture_list( capture_list && other ) noexcept: first_(other.first_) { other.first_ = nullptr; } ~capture_list() noexcept { for( node const * p = first_; p; ) { node const * n = p -> next_; delete p; p = n; } } void unload( int const err_id ) { capture_list moved(first_); first_ = nullptr; tls::write_uint(unsigned(err_id)); moved.for_each( [err_id]( node & n ) { n.unload(err_id); // last node may throw } ); } template void print( std::basic_ostream & os, char const * title, int const err_id_to_print ) const { BOOST_LEAF_ASSERT(title != nullptr); #if BOOST_LEAF_CFG_DIAGNOSTICS if( first_ ) { os << title; for_each( [&os, err_id_to_print]( node const & n ) { n.print(os, err_id_to_print); } ); } #else (void) os; (void) title; (void) err_id_to_print; #endif } }; } } } #endif #endif // <<< #include #line 13 "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 2018-2023 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) // Expanded at line 16: #include // >>> #include #line 1 "boost/leaf/detail/demangle.hpp" #ifndef BOOST_LEAF_DETAIL_DEMANGLE_HPP_INCLUDED #define BOOST_LEAF_DETAIL_DEMANGLE_HPP_INCLUDED // Copyright 2018-2023 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) // This file is based on boost::core::demangle // // Copyright 2014 Peter Dimov // Copyright 2014 Andrey Semashev // // 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 // Expanded at line 16: #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() { 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; } } } //////////////////////////////////////// // __has_include is currently supported by GCC and Clang. However GCC 4.9 may have issues and // returns 1 for 'defined( __has_include )', while '__has_include' is actually not supported: // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63662 #if defined(__has_include) && (!defined(__GNUC__) || defined(__clang__) || (__GNUC__ + 0) >= 5) # if __has_include() # define BOOST_LEAF_HAS_CXXABI_H # endif #elif defined( __GLIBCXX__ ) || defined( __GLIBCPP__ ) # define BOOST_LEAF_HAS_CXXABI_H #endif #if defined( BOOST_LEAF_HAS_CXXABI_H ) # include // For some archtectures (mips, mips64, x86, x86_64) cxxabi.h in Android NDK is implemented by gabi++ library // (https://android.googlesource.com/platform/ndk/+/master/sources/cxx-stl/gabi++/), which does not implement // abi::__cxa_demangle(). We detect this implementation by checking the include guard here. # if defined( __GABIXX_CXXABI_H__ ) # undef BOOST_LEAF_HAS_CXXABI_H # else # include # include # endif #endif #if BOOST_LEAF_CFG_STD_STRING #include namespace boost { namespace leaf { namespace leaf_detail { inline char const * demangle_alloc( char const * name ) noexcept; inline void demangle_free( char const * name ) noexcept; class scoped_demangled_name { private: char const * m_p; public: explicit scoped_demangled_name( char const * name ) noexcept : m_p( demangle_alloc( name ) ) { } ~scoped_demangled_name() noexcept { demangle_free( m_p ); } char const * get() const noexcept { return m_p; } scoped_demangled_name( scoped_demangled_name const& ) = delete; scoped_demangled_name& operator= ( scoped_demangled_name const& ) = delete; }; #ifdef BOOST_LEAF_HAS_CXXABI_H inline char const * demangle_alloc( char const * name ) noexcept { int status = 0; std::size_t size = 0; return abi::__cxa_demangle( name, NULL, &size, &status ); } inline void demangle_free( char const * name ) noexcept { std::free( const_cast< char* >( name ) ); } inline std::string demangle( char const * name ) { scoped_demangled_name demangled_name( name ); char const * p = demangled_name.get(); if( !p ) p = name; return p; } #else inline char const * demangle_alloc( char const * name ) noexcept { return name; } inline void demangle_free( char const * ) noexcept { } inline char const * demangle( char const * name ) { return name; } #endif } } } #else namespace boost { namespace leaf { namespace leaf_detail { inline char const * demangle( char const * name ) { return name; } } } } #endif #ifdef BOOST_LEAF_HAS_CXXABI_H # undef BOOST_LEAF_HAS_CXXABI_H #endif #endif // <<< #include #line 11 "boost/leaf/detail/print.hpp" #include #include #include #include namespace boost { namespace leaf { 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 < class Wrapper, bool WrapperPrintable = is_printable::value, bool ValuePrintable = has_printable_member_value::value, bool IsException = std::is_base_of::value, bool IsEnum = std::is_enum::value> struct diagnostic; template struct diagnostic { static constexpr bool is_invisible = false; template static void print( std::basic_ostream & os, Wrapper const & x ) { os << x; } }; template struct diagnostic { static constexpr bool is_invisible = false; template static void print( std::basic_ostream & os, Wrapper const & x ) { os << type() << ": " << x.value; } }; template struct diagnostic { static constexpr bool is_invisible = false; template static void print( std::basic_ostream & os, Wrapper const & ex ) { os << type() << ": std::exception::what(): " << ex.what(); } }; template struct diagnostic { static constexpr bool is_invisible = false; template static void print( std::basic_ostream & os, Wrapper const & ) { os << type() << ": {not printable}"; } }; template struct diagnostic { static constexpr bool is_invisible = false; template static void print( std::basic_ostream & os, Wrapper const & w ) { os << type() << ": " << static_cast::type>(w); } }; template <> struct diagnostic { static constexpr bool is_invisible = true; template BOOST_LEAF_CONSTEXPR static void print( std::basic_ostream &, std::exception_ptr const & ) { } }; } } } #endif // <<< #include #line 14 "boost/leaf/error.hpp" #if BOOST_LEAF_CFG_DIAGNOSTICS # include #endif #if BOOST_LEAF_CFG_STD_SYSTEM_ERROR # include #endif #if BOOST_LEAF_CFG_CAPTURE # include #endif #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_TMP BOOST_LEAF_TOKEN_PASTE2(boost_leaf_tmp_, __LINE__) #define BOOST_LEAF_ASSIGN(v,r)\ auto && BOOST_LEAF_TMP = r;\ static_assert(::boost::leaf::is_result_type::type>::value,\ "BOOST_LEAF_ASSIGN/BOOST_LEAF_AUTO requires a result object as the second argument (see is_result_type)");\ if( !BOOST_LEAF_TMP )\ return BOOST_LEAF_TMP.error();\ v = std::forward(BOOST_LEAF_TMP).value() #define BOOST_LEAF_AUTO(v, r)\ BOOST_LEAF_ASSIGN(auto v, r) #if BOOST_LEAF_CFG_GNUC_STMTEXPR #define BOOST_LEAF_CHECK(r)\ ({\ auto && BOOST_LEAF_TMP = (r);\ static_assert(::boost::leaf::is_result_type::type>::value,\ "BOOST_LEAF_CHECK requires a result object (see is_result_type)");\ if( !BOOST_LEAF_TMP )\ return BOOST_LEAF_TMP.error();\ std::move(BOOST_LEAF_TMP);\ }).value() #else #define BOOST_LEAF_CHECK(r)\ {\ auto && BOOST_LEAF_TMP = (r);\ static_assert(::boost::leaf::is_result_type::type>::value,\ "BOOST_LEAF_CHECK requires a result object (see is_result_type)");\ if( !BOOST_LEAF_TMP )\ return BOOST_LEAF_TMP.error();\ } #endif #define BOOST_LEAF_NEW_ERROR ::boost::leaf::leaf_detail::inject_loc{__FILE__,__LINE__,__FUNCTION__}+::boost::leaf::new_error namespace boost { namespace leaf { struct BOOST_LEAF_SYMBOL_VISIBLE e_source_location { char const * file; int line; char const * function; template friend std::ostream & operator<<( std::basic_ostream & os, e_source_location const & x ) { return os << leaf::type() << ": " << x.file << '(' << x.line << ") in function " << x.function; } }; //////////////////////////////////////// class BOOST_LEAF_SYMBOL_VISIBLE error_id; namespace leaf_detail { template class BOOST_LEAF_SYMBOL_VISIBLE slot: optional { slot( slot const & ) = delete; slot & operator=( slot const & ) = delete; using impl = optional; slot * prev_; public: BOOST_LEAF_CONSTEXPR slot() noexcept: prev_(nullptr) { } BOOST_LEAF_CONSTEXPR slot( slot && x ) noexcept: optional(std::move(x)), prev_(nullptr) { BOOST_LEAF_ASSERT(x.prev_==nullptr); } void activate() noexcept { prev_ = tls::read_ptr>(); tls::write_ptr>(this); } void deactivate() const noexcept { tls::write_ptr>(prev_); } void unload( int err_id ) noexcept(!BOOST_LEAF_CFG_CAPTURE); template void print( std::basic_ostream & os, int err_id_to_print ) const { if( !diagnostic::is_invisible ) if( int k = this->key() ) { if( err_id_to_print ) { if( err_id_to_print!=k ) return; } else os << '[' << k << "] "; diagnostic::print(os, value(k)); os << '\n'; } } using impl::load; using impl::has_value; using impl::value; }; } //////////////////////////////////////// #if BOOST_LEAF_CFG_CAPTURE namespace leaf_detail { class BOOST_LEAF_SYMBOL_VISIBLE dynamic_allocator: capture_list { dynamic_allocator( dynamic_allocator const & ) = delete; dynamic_allocator & operator=( dynamic_allocator const & ) = delete; class capturing_node: public capture_list::node { protected: BOOST_LEAF_CONSTEXPR explicit capturing_node( capture_list::node * * & last ) noexcept: node(last) { BOOST_LEAF_ASSERT(last == &next_); BOOST_LEAF_ASSERT(next_ == nullptr); } public: virtual void deactivate() const noexcept = 0; }; template class capturing_slot_node: public capturing_node, public slot { using impl = slot; capturing_slot_node( capturing_slot_node const & ) = delete; capturing_slot_node & operator=( capturing_slot_node const & ) = delete; void deactivate() const noexcept final override { impl::deactivate(); } void unload( int err_id ) final override { impl::unload(err_id); } #if BOOST_LEAF_CFG_DIAGNOSTICS void print( std::ostream & os, int err_id_to_print ) const final override { impl::print(os, err_id_to_print); } #endif public: template BOOST_LEAF_CONSTEXPR capturing_slot_node( capture_list::node * * & last, int err_id, T && e ): capturing_node(last) { BOOST_LEAF_ASSERT(last == &next_); BOOST_LEAF_ASSERT(next_ == nullptr); impl::load(err_id, std::forward(e)); } }; #ifndef BOOST_LEAF_NO_EXCEPTIONS class capturing_exception_node: public capturing_node { capturing_exception_node( capturing_exception_node const & ) = delete; capturing_exception_node & operator=( capturing_exception_node const & ) = delete; void deactivate() const noexcept final override { BOOST_LEAF_ASSERT(0); } void unload( int ) final override { std::rethrow_exception(ex_); } #if BOOST_LEAF_CFG_DIAGNOSTICS void print( std::ostream &, int err_id_to_print ) const final override { } #endif std::exception_ptr const ex_; public: explicit capturing_exception_node( capture_list::node * * & last, std::exception_ptr && ex ) noexcept: capturing_node(last), ex_(std::move(ex)) { BOOST_LEAF_ASSERT(last == &next_); BOOST_LEAF_ASSERT(ex_); } }; #endif int err_id_; node * * last_; public: dynamic_allocator() noexcept: capture_list(nullptr), err_id_(0), last_(&first_) { BOOST_LEAF_ASSERT(first_ == nullptr); } dynamic_allocator( dynamic_allocator && other ) noexcept: capture_list(std::move(other)), err_id_(other.err_id_), last_(other.last_ == &other.first_? &first_ : other.last_) { BOOST_LEAF_ASSERT(last_ != nullptr); BOOST_LEAF_ASSERT(*last_ == nullptr); BOOST_LEAF_ASSERT(other.first_ == nullptr); other.last_ = &other.first_; } void append( dynamic_allocator && other ) noexcept { if( node * other_first = other.first_ ) { *last_ = other_first; last_ = other.last_; other.first_ = nullptr; other.last_ = &other.first_; } } template typename std::decay::type & dynamic_load(int err_id, E && e) { using T = typename std::decay::type; BOOST_LEAF_ASSERT(last_ != nullptr); BOOST_LEAF_ASSERT(*last_ == nullptr); BOOST_LEAF_ASSERT(tls::read_ptr>() == nullptr); capturing_slot_node * csn = new capturing_slot_node(last_, err_id, std::forward(e)); csn->activate(); err_id_ = err_id; return csn->value(err_id); } void deactivate() const noexcept { for_each( []( capture_list::node const & n ) { static_cast(n).deactivate(); } ); } template LeafResult extract_capture_list() noexcept { #ifndef BOOST_LEAF_NO_EXCEPTIONS if( std::exception_ptr ex = std::current_exception() ) (void) new capturing_exception_node(last_, std::move(ex)); #endif leaf_detail::capture_list::node * const f = first_; first_ = nullptr; last_ = &first_; return { err_id_, capture_list(f) }; } using capture_list::print; }; template <> struct diagnostic { static constexpr bool is_invisible = true; template BOOST_LEAF_CONSTEXPR static void print( std::basic_ostream &, dynamic_allocator const & ) { } }; template <> inline void slot::deactivate() const noexcept { if( int const err_id = this->key() ) if( dynamic_allocator const * c = this->has_value(err_id) ) c->deactivate(); tls::write_ptr>(prev_); } template <> inline void slot::unload( int err_id ) noexcept(false) { BOOST_LEAF_ASSERT(err_id); if( dynamic_allocator * da1 = this->has_value(err_id) ) if( impl * p = tls::read_ptr>() ) if( dynamic_allocator * da2 = p->has_value(err_id) ) da2->append(std::move(*da1)); else *p = std::move(*this); } template inline void dynamic_load_( int err_id, E && e ) { if( slot * sl = tls::read_ptr>() ) { if( dynamic_allocator * c = sl->has_value(err_id) ) c->dynamic_load(err_id, std::forward(e)); else sl->load(err_id).dynamic_load(err_id, std::forward(e)); } } template inline void dynamic_accumulate_( int err_id, F && f ) { if( slot * sl = tls::read_ptr>() ) { if( dynamic_allocator * c = sl->has_value(err_id) ) (void) std::forward(f)(c->dynamic_load(err_id, E{})); else (void) std::forward(f)(sl->load(err_id).dynamic_load(err_id, E{})); } } template inline void dynamic_load( int err_id, E && e ) noexcept(OnError) { if( OnError ) { #ifndef BOOST_LEAF_NO_EXCEPTIONS try { #endif dynamic_load_(err_id, std::forward(e)); #ifndef BOOST_LEAF_NO_EXCEPTIONS } catch(...) { } #endif } else dynamic_load_(err_id, std::forward(e)); } template inline void dynamic_load_accumulate( int err_id, F && f ) noexcept(OnError) { if( OnError ) { #ifndef BOOST_LEAF_NO_EXCEPTIONS try { #endif dynamic_accumulate_(err_id, std::forward(f)); #ifndef BOOST_LEAF_NO_EXCEPTIONS } catch(...) { } #endif } else dynamic_accumulate_(err_id, std::forward(f)); } } #endif //////////////////////////////////////// namespace leaf_detail { template inline void slot::unload( int err_id ) noexcept(!BOOST_LEAF_CFG_CAPTURE) { BOOST_LEAF_ASSERT(err_id); if( this->key()!=err_id ) return; if( impl * p = tls::read_ptr>() ) *p = std::move(*this); #if BOOST_LEAF_CFG_CAPTURE else dynamic_load(err_id, std::move(*this).value(err_id)); #endif } template BOOST_LEAF_CONSTEXPR inline int load_slot( int err_id, E && e ) noexcept(OnError) { using T = typename std::decay::type; static_assert(!std::is_pointer::value, "Error objects of pointer types are not allowed"); static_assert(!std::is_same::value, "Error objects of type error_id are not allowed"); BOOST_LEAF_ASSERT((err_id&3)==1); if( slot * p = tls::read_ptr>() ) { if( !OnError || !p->has_value(err_id) ) (void) p->load(err_id, std::forward(e)); } #if BOOST_LEAF_CFG_CAPTURE else dynamic_load(err_id, std::forward(e)); #endif return 0; } template BOOST_LEAF_CONSTEXPR inline int load_slot_deferred( int err_id, F && f ) noexcept(OnError) { using E = typename function_traits::return_type; using T = typename std::decay::type; static_assert(!std::is_pointer::value, "Error objects of pointer types are not allowed"); static_assert(!std::is_same::value, "Error objects of type error_id are not allowed"); BOOST_LEAF_ASSERT((err_id&3)==1); if( slot * p = tls::read_ptr>() ) { if( !OnError || !p->has_value(err_id) ) (void) p->load(err_id, std::forward(f)()); } #if BOOST_LEAF_CFG_CAPTURE else dynamic_load(err_id, std::forward(f)()); #endif return 0; } template BOOST_LEAF_CONSTEXPR inline int load_slot_accumulate( int err_id, F && f ) noexcept(OnError) { 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 = tls::read_ptr>() ) { if( auto v = sl->has_value(err_id) ) (void) std::forward(f)(*v); else (void) std::forward(f)(sl->load(err_id,E())); } #if BOOST_LEAF_CFG_CAPTURE else dynamic_load_accumulate(err_id, std::forward(f)); #endif return 0; } } //////////////////////////////////////// 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_deferred(err_id, std::forward(f)); } }; template struct load_item { BOOST_LEAF_CONSTEXPR static int load_( int err_id, F && f ) noexcept { return load_slot_accumulate(err_id, std::forward(f)); } }; } //////////////////////////////////////// namespace leaf_detail { struct BOOST_LEAF_SYMBOL_VISIBLE tls_tag_id_factory_current_id; template struct BOOST_LEAF_SYMBOL_VISIBLE id_factory { static atomic_unsigned_int counter; 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(unsigned(-3)); inline int current_id() noexcept { unsigned id = tls::read_uint(); BOOST_LEAF_ASSERT(id==0 || (id&3)==1); return int(id); } inline int new_id() noexcept { unsigned id = id_factory<>::generate_next_id(); tls::write_uint(id); return int(id); } 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); } }; } #if BOOST_LEAF_CFG_STD_SYSTEM_ERROR namespace leaf_detail { class leaf_category final: 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 ) 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; } #endif //////////////////////////////////////// namespace leaf_detail { BOOST_LEAF_CONSTEXPR error_id make_error_id(int) noexcept; } class BOOST_LEAF_SYMBOL_VISIBLE 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) { } #if BOOST_LEAF_CFG_STD_SYSTEM_ERROR 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)) { } operator std::error_code() const noexcept { return std::error_code(value_, leaf_detail::get_error_category<>::cat); } #endif 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; } 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; } BOOST_LEAF_CONSTEXPR int value() const noexcept { BOOST_LEAF_ASSERT(value_==0 || ((value_&3)==1)); return value_; } 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_; } template friend std::ostream & operator<<( std::basic_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 { }; #if BOOST_LEAF_CFG_CAPTURE using context_ptr = std::shared_ptr; #endif //////////////////////////////////////////// template class context_activator { context_activator( context_activator const & ) = delete; context_activator & operator=( context_activator const & ) = delete; Ctx * ctx_; public: explicit BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE context_activator(Ctx & ctx) noexcept: ctx_(ctx.is_active() ? nullptr : &ctx) { if( ctx_ ) ctx_->activate(); } BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE context_activator( context_activator && x ) noexcept: ctx_(x.ctx_) { x.ctx_ = nullptr; } BOOST_LEAF_ALWAYS_INLINE ~context_activator() noexcept { if( ctx_ && ctx_->is_active() ) ctx_->deactivate(); } }; //////////////////////////////////////////// template struct is_result_type: std::false_type { }; template struct is_result_type: is_result_type { }; } } #endif // <<< #include #line 11 "boost/leaf/context.hpp" #if !defined(BOOST_LEAF_NO_THREADS) && !defined(NDEBUG) # include #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 const & 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_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 unload( Tuple & tup, int err_id ) noexcept { static_assert(!std::is_same(tup))>::type>::value, "Bug in LEAF: context type deduction"); BOOST_LEAF_ASSERT(err_id != 0); auto & sl = std::get(tup); sl.unload(err_id); tuple_for_each::unload(tup, err_id); } template static void print( std::basic_ostream & os, void const * tup, int err_id_to_print ) { BOOST_LEAF_ASSERT(tup != nullptr); tuple_for_each::print(os, tup, err_id_to_print); std::get(*static_cast(tup)).print(os, err_id_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 unload( Tuple &, int ) noexcept { } template BOOST_LEAF_CONSTEXPR static void print( std::basic_ostream &, void const *, int ) { } }; } //////////////////////////////////////////// namespace leaf_detail { template struct does_not_participate_in_context_deduction: std::is_abstract { }; template <> struct does_not_participate_in_context_deduction: std::true_type { }; template <> struct does_not_participate_in_context_deduction: std::true_type { }; template struct deduce_e_type_list; template class L, class... T> struct deduce_e_type_list> { using type = leaf_detail_mp11::mp_remove_if< leaf_detail_mp11::mp_unique< leaf_detail_mp11::mp_list::error_type...> >, does_not_participate_in_context_deduction >; }; template struct deduce_e_tuple_impl; template