diff --git a/.travis.yml b/.travis.yml index 5c65a91..0ecc47e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -108,18 +108,18 @@ matrix: - ubuntu-toolchain-r-test - os: linux - compiler: g++-7 - env: UBSAN=1 TOOLSET=gcc COMPILER=g++-7 CXXSTD=03,11,14,17 UBSAN_OPTIONS=print_stacktrace=1 LINKFLAGS=-fuse-ld=gold + compiler: g++-8 + env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=03,11,14,17 addons: apt: packages: - - g++-7 + - g++-8 sources: - ubuntu-toolchain-r-test - os: linux compiler: g++-8 - env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=03,11,14,17 + env: UBSAN=1 TOOLSET=gcc COMPILER=g++-8 CXXSTD=03,11,14,17 UBSAN_OPTIONS=print_stacktrace=1 LINKFLAGS=-fuse-ld=gold addons: apt: packages: @@ -297,18 +297,6 @@ matrix: - ubuntu-toolchain-r-test - llvm-toolchain-trusty-5.0 - - os: linux - compiler: clang++-5.0 - env: UBSAN=1 TOOLSET=clang COMPILER=clang++-5.0 CXXSTD=03,11,14,1z UBSAN_OPTIONS=print_stacktrace=1 - addons: - apt: - packages: - - clang-5.0 - - libstdc++-4.9-dev - sources: - - ubuntu-toolchain-r-test - - llvm-toolchain-trusty-5.0 - - os: linux compiler: clang++-6.0 env: TOOLSET=clang COMPILER=clang++-6.0 CXXSTD=03,11,14,17 @@ -332,6 +320,18 @@ matrix: - ubuntu-toolchain-r-test - llvm-toolchain-trusty-6.0 + - os: linux + compiler: clang++-6.0 + env: UBSAN=1 TOOLSET=clang COMPILER=clang++-6.0 CXXSTD=03,11,14,1z UBSAN_OPTIONS=print_stacktrace=1 + addons: + apt: + packages: + - clang-6.0 + - libstdc++-5-dev + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-trusty-6.0 + - os: linux compiler: clang++-libc++ env: TOOLSET=clang COMPILER=clang++-libc++ CXXSTD=03,11,14,1z diff --git a/include/boost/system/config.hpp b/include/boost/system/config.hpp index 14faa63..1e5f686 100644 --- a/include/boost/system/config.hpp +++ b/include/boost/system/config.hpp @@ -7,15 +7,16 @@ // See http://www.boost.org/libs/system for documentation. -#ifndef BOOST_SYSTEM_CONFIG_HPP +#ifndef BOOST_SYSTEM_CONFIG_HPP #define BOOST_SYSTEM_CONFIG_HPP #include -#include #include // for BOOST_POSIX_API or BOOST_WINDOWS_API -// This header implements separate compilation features as described in +// This header implemented separate compilation features as described in // http://www.boost.org/more/separate_compilation.html +// +// It's only retained for compatibility now that the library is header-only. // normalize macros ------------------------------------------------------------------// @@ -46,25 +47,4 @@ # define BOOST_SYSTEM_DECL #endif -// enable automatic library variant selection ----------------------------------------// - -#if !defined(BOOST_SYSTEM_SOURCE) && !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_SYSTEM_NO_LIB) -// -// Set the name of our library, this will get undef'ed by auto_link.hpp -// once it's done with it: -// -#define BOOST_LIB_NAME boost_system -// -// If we're importing code from a dll, then tell auto_link.hpp about it: -// -#if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_SYSTEM_DYN_LINK) -# define BOOST_DYN_LINK -#endif -// -// And include the header that does the work: -// -#include -#endif // auto-linking disabled - #endif // BOOST_SYSTEM_CONFIG_HPP - diff --git a/include/boost/system/detail/config.hpp b/include/boost/system/detail/config.hpp new file mode 100644 index 0000000..fde93cb --- /dev/null +++ b/include/boost/system/detail/config.hpp @@ -0,0 +1,53 @@ +#ifndef BOOST_SYSTEM_DETAIL_CONFIG_HPP_INCLUDED +#define BOOST_SYSTEM_DETAIL_CONFIG_HPP_INCLUDED + +// Copyright 2018 Peter Dimov +// +// 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) +// +// See http://www.boost.org/libs/system for documentation. + +#include +#include + +// BOOST_SYSTEM_HAS_SYSTEM_ERROR + +#if !defined(BOOST_NO_CXX11_HDR_SYSTEM_ERROR) +# define BOOST_SYSTEM_HAS_SYSTEM_ERROR +#endif + +#if BOOST_WORKAROUND(BOOST_GCC, < 40600) +// g++ 4.4's is not good enough +# undef BOOST_SYSTEM_HAS_SYSTEM_ERROR +#endif + +// BOOST_SYSTEM_NOEXCEPT +// Retained for backward compatibility + +#define BOOST_SYSTEM_NOEXCEPT BOOST_NOEXCEPT + +// BOOST_SYSTEM_HAS_CONSTEXPR + +#if !defined(BOOST_NO_CXX14_CONSTEXPR) +# define BOOST_SYSTEM_HAS_CONSTEXPR +#endif + +#if defined(BOOST_SYSTEM_HAS_CONSTEXPR) +# define BOOST_SYSTEM_CONSTEXPR constexpr +#else +# define BOOST_SYSTEM_CONSTEXPR +#endif + +// BOOST_SYSTEM_REQUIRE_CONST_INIT + +#define BOOST_SYSTEM_REQUIRE_CONST_INIT + +#if defined(__has_cpp_attribute) +#if __has_cpp_attribute(clang::require_constant_initialization) +# undef BOOST_SYSTEM_REQUIRE_CONST_INIT +# define BOOST_SYSTEM_REQUIRE_CONST_INIT [[clang::require_constant_initialization]] +#endif +#endif + +#endif // BOOST_SYSTEM_DETAIL_CONFIG_HPP_INCLUDED diff --git a/include/boost/system/detail/error_code.ipp b/include/boost/system/detail/error_code.ipp deleted file mode 100644 index f9516e0..0000000 --- a/include/boost/system/detail/error_code.ipp +++ /dev/null @@ -1,496 +0,0 @@ -// error_code support implementation file --------------------------------------------// - -// Copyright Beman Dawes 2002, 2006 -// Copyright (c) Microsoft Corporation 2014 -// 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) - -// See library home page at http://www.boost.org/libs/system - -//--------------------------------------------------------------------------------------// - -#include - -#include -#include -#include -#include -#include -#include - -#include // for strerror/strerror_r - -# if defined( BOOST_WINDOWS_API ) -# include -# include -# include -# if !BOOST_PLAT_WINDOWS_RUNTIME -# include -# endif -# ifndef ERROR_INCORRECT_SIZE -# define ERROR_INCORRECT_SIZE ERROR_BAD_ARGUMENTS -# endif -# endif - -//--------------------------------------------------------------------------------------// -namespace boost -{ - -namespace system -{ - -namespace detail -{ - -#ifdef BOOST_ERROR_CODE_HEADER_ONLY -# define BOOST_SYSTEM_DECL_ inline -#else -# define BOOST_SYSTEM_DECL_ BOOST_SYSTEM_DECL -#endif - - // generic_error_category implementation ---------------------------------// - - BOOST_SYSTEM_DECL_ std::string generic_error_category::message( int ev ) const - { - using namespace boost::system::errc; -#if defined(__PGI) - using boost::system::errc::invalid_argument; -#endif - - static std::string unknown_err( "Unknown error" ); - // strerror_r is preferred because it is always thread safe, - // however, we fallback to strerror in certain cases because: - // -- Windows doesn't provide strerror_r. - // -- HP and Sun do provide strerror_r on newer systems, but there is - // no way to tell if is available at runtime and in any case their - // versions of strerror are thread safe anyhow. - // -- Linux only sometimes provides strerror_r. - // -- Tru64 provides strerror_r only when compiled -pthread. - // -- VMS doesn't provide strerror_r, but on this platform, strerror is - // thread safe. - # if defined(BOOST_WINDOWS_API) || defined(__hpux) || defined(__sun)\ - || (defined(__linux) && (!defined(__USE_XOPEN2K)\ - || defined(BOOST_SYSTEM_USE_STRERROR)))\ - || (defined(__osf__) && !defined(_REENTRANT))\ - || (defined(__INTEGRITY))\ - || (defined(__vms))\ - || (defined(__QNXNTO__)) - const char * c_str = std::strerror( ev ); - return c_str - ? std::string( c_str ) - : unknown_err; - # else // use strerror_r - char buf[64]; - char * bp = buf; - std::size_t sz = sizeof(buf); - # if defined(__CYGWIN__) || defined(__USE_GNU) - // Oddball version of strerror_r - const char * c_str = strerror_r( ev, bp, sz ); - return c_str - ? std::string( c_str ) - : unknown_err; - # else - // POSIX version of strerror_r - int result; - for (;;) - { - // strerror_r returns 0 on success, otherwise ERANGE if buffer too small, - // invalid_argument if ev not a valid error number - # if defined (__sgi) - const char * c_str = strerror( ev ); - result = 0; - return c_str - ? std::string( c_str ) - : unknown_err; - # else - result = strerror_r( ev, bp, sz ); - # endif - if (result == 0 ) - break; - else - { - # if defined(__linux) - // Linux strerror_r returns -1 on error, with error number in errno - result = errno; - # endif - if ( result != ERANGE ) break; - if ( sz > sizeof(buf) ) std::free( bp ); - sz *= 2; - if ( (bp = static_cast(std::malloc( sz ))) == 0 ) - return std::string( "ENOMEM" ); - } - } - std::string msg; -# ifndef BOOST_NO_EXCEPTIONS - try -# endif - { - msg = ( ( result == invalid_argument ) ? "Unknown error" : bp ); - } - -# ifndef BOOST_NO_EXCEPTIONS - // See ticket #2098 - catch(...) - { - // just eat the exception - } -# endif - - if ( sz > sizeof(buf) ) std::free( bp ); - return msg; - # endif // else POSIX version of strerror_r - # endif // else use strerror_r - } - // system_error_category implementation --------------------------------------------// - - BOOST_SYSTEM_DECL_ error_condition system_error_category::default_error_condition( int ev ) const - BOOST_SYSTEM_NOEXCEPT - { - using namespace boost::system::errc; -#if defined(__PGI) - using boost::system::errc::invalid_argument; -#endif - -# if defined(BOOST_WINDOWS_API) -# if defined(WINAPI_FAMILY) && ((WINAPI_FAMILY & WINAPI_PARTITION_APP) != 0) - // When using the Windows Runtime, most system errors are reported as HRESULTs. - // We want to map the common Win32 errors to their equivalent error condition, - // whether or not they are reported via an HRESULT. - if ( ev < 0 ) // Check for failed HRESULTs only. - if ( HRESULT_FACILITY( ev ) == FACILITY_WIN32 ) - ev = HRESULT_CODE( ev ); -# endif -# endif - -# if defined(BOOST_WINDOWS_API) - - using namespace boost::winapi; // for error codes - -# endif - - switch ( ev ) - { - case 0: return make_error_condition( success ); -# if defined(BOOST_POSIX_API) - // POSIX-like O/S -> posix_errno decode table -------------------------------------// - case E2BIG: return make_error_condition( argument_list_too_long ); - case EACCES: return make_error_condition( permission_denied ); - case EADDRINUSE: return make_error_condition( address_in_use ); - case EADDRNOTAVAIL: return make_error_condition( address_not_available ); - case EAFNOSUPPORT: return make_error_condition( address_family_not_supported ); - case EAGAIN: return make_error_condition( resource_unavailable_try_again ); -# if EALREADY != EBUSY // EALREADY and EBUSY are the same on QNX Neutrino - case EALREADY: return make_error_condition( connection_already_in_progress ); -# endif - case EBADF: return make_error_condition( bad_file_descriptor ); - case EBADMSG: return make_error_condition( bad_message ); - case EBUSY: return make_error_condition( device_or_resource_busy ); - case ECANCELED: return make_error_condition( operation_canceled ); - case ECHILD: return make_error_condition( no_child_process ); - case ECONNABORTED: return make_error_condition( connection_aborted ); - case ECONNREFUSED: return make_error_condition( connection_refused ); - case ECONNRESET: return make_error_condition( connection_reset ); - case EDEADLK: return make_error_condition( resource_deadlock_would_occur ); - case EDESTADDRREQ: return make_error_condition( destination_address_required ); - case EDOM: return make_error_condition( argument_out_of_domain ); - case EEXIST: return make_error_condition( file_exists ); - case EFAULT: return make_error_condition( bad_address ); - case EFBIG: return make_error_condition( file_too_large ); - case EHOSTUNREACH: return make_error_condition( host_unreachable ); - case EIDRM: return make_error_condition( identifier_removed ); - case EILSEQ: return make_error_condition( illegal_byte_sequence ); - case EINPROGRESS: return make_error_condition( operation_in_progress ); - case EINTR: return make_error_condition( interrupted ); - case EINVAL: return make_error_condition( invalid_argument ); - case EIO: return make_error_condition( io_error ); - case EISCONN: return make_error_condition( already_connected ); - case EISDIR: return make_error_condition( is_a_directory ); - case ELOOP: return make_error_condition( too_many_symbolic_link_levels ); - case EMFILE: return make_error_condition( too_many_files_open ); - case EMLINK: return make_error_condition( too_many_links ); - case EMSGSIZE: return make_error_condition( message_size ); - case ENAMETOOLONG: return make_error_condition( filename_too_long ); - case ENETDOWN: return make_error_condition( network_down ); - case ENETRESET: return make_error_condition( network_reset ); - case ENETUNREACH: return make_error_condition( network_unreachable ); - case ENFILE: return make_error_condition( too_many_files_open_in_system ); - case ENOBUFS: return make_error_condition( no_buffer_space ); - case ENODATA: return make_error_condition( no_message_available ); - case ENODEV: return make_error_condition( no_such_device ); - case ENOENT: return make_error_condition( no_such_file_or_directory ); - case ENOEXEC: return make_error_condition( executable_format_error ); - case ENOLCK: return make_error_condition( no_lock_available ); - case ENOLINK: return make_error_condition( no_link ); - case ENOMEM: return make_error_condition( not_enough_memory ); - case ENOMSG: return make_error_condition( no_message ); - case ENOPROTOOPT: return make_error_condition( no_protocol_option ); - case ENOSPC: return make_error_condition( no_space_on_device ); - case ENOSR: return make_error_condition( no_stream_resources ); - case ENOSTR: return make_error_condition( not_a_stream ); - case ENOSYS: return make_error_condition( function_not_supported ); - case ENOTCONN: return make_error_condition( not_connected ); - case ENOTDIR: return make_error_condition( not_a_directory ); - # if ENOTEMPTY != EEXIST // AIX treats ENOTEMPTY and EEXIST as the same value - case ENOTEMPTY: return make_error_condition( directory_not_empty ); - # endif // ENOTEMPTY != EEXIST - # if ENOTRECOVERABLE != ECONNRESET // the same on some Broadcom chips - case ENOTRECOVERABLE: return make_error_condition( state_not_recoverable ); - # endif // ENOTRECOVERABLE != ECONNRESET - case ENOTSOCK: return make_error_condition( not_a_socket ); - case ENOTSUP: return make_error_condition( not_supported ); - case ENOTTY: return make_error_condition( inappropriate_io_control_operation ); - case ENXIO: return make_error_condition( no_such_device_or_address ); - # if EOPNOTSUPP != ENOTSUP - case EOPNOTSUPP: return make_error_condition( operation_not_supported ); - # endif // EOPNOTSUPP != ENOTSUP - case EOVERFLOW: return make_error_condition( value_too_large ); - # if EOWNERDEAD != ECONNABORTED // the same on some Broadcom chips - case EOWNERDEAD: return make_error_condition( owner_dead ); - # endif // EOWNERDEAD != ECONNABORTED - case EPERM: return make_error_condition( operation_not_permitted ); - case EPIPE: return make_error_condition( broken_pipe ); - case EPROTO: return make_error_condition( protocol_error ); - case EPROTONOSUPPORT: return make_error_condition( protocol_not_supported ); - case EPROTOTYPE: return make_error_condition( wrong_protocol_type ); - case ERANGE: return make_error_condition( result_out_of_range ); - case EROFS: return make_error_condition( read_only_file_system ); - case ESPIPE: return make_error_condition( invalid_seek ); - case ESRCH: return make_error_condition( no_such_process ); - case ETIME: return make_error_condition( stream_timeout ); - case ETIMEDOUT: return make_error_condition( timed_out ); - case ETXTBSY: return make_error_condition( text_file_busy ); - # if EAGAIN != EWOULDBLOCK - case EWOULDBLOCK: return make_error_condition( operation_would_block ); - # endif // EAGAIN != EWOULDBLOCK - case EXDEV: return make_error_condition( cross_device_link ); - #else - // Windows system -> posix_errno decode table ---------------------------// - // see WinError.h comments for descriptions of errors - case ERROR_ACCESS_DENIED_: return make_error_condition( permission_denied ); - case ERROR_ALREADY_EXISTS_: return make_error_condition( file_exists ); - case ERROR_BAD_UNIT_: return make_error_condition( no_such_device ); - case ERROR_BUFFER_OVERFLOW_: return make_error_condition( filename_too_long ); - case ERROR_BUSY_: return make_error_condition( device_or_resource_busy ); - case ERROR_BUSY_DRIVE_: return make_error_condition( device_or_resource_busy ); - case ERROR_CANNOT_MAKE_: return make_error_condition( permission_denied ); - case ERROR_CANTOPEN_: return make_error_condition( io_error ); - case ERROR_CANTREAD_: return make_error_condition( io_error ); - case ERROR_CANTWRITE_: return make_error_condition( io_error ); - case ERROR_CURRENT_DIRECTORY_: return make_error_condition( permission_denied ); - case ERROR_DEV_NOT_EXIST_: return make_error_condition( no_such_device ); - case ERROR_DEVICE_IN_USE_: return make_error_condition( device_or_resource_busy ); - case ERROR_DIR_NOT_EMPTY_: return make_error_condition( directory_not_empty ); - case ERROR_DIRECTORY_: return make_error_condition( invalid_argument );\ - // WinError.h: "The directory name is invalid" - case ERROR_DISK_FULL_: return make_error_condition( no_space_on_device ); - case ERROR_FILE_EXISTS_: return make_error_condition( file_exists ); - case ERROR_FILE_NOT_FOUND_: return make_error_condition( no_such_file_or_directory ); - case ERROR_HANDLE_DISK_FULL_: return make_error_condition( no_space_on_device ); - case ERROR_INVALID_ACCESS_: return make_error_condition( permission_denied ); - case ERROR_INVALID_DRIVE_: return make_error_condition( no_such_device ); - case ERROR_INVALID_FUNCTION_: return make_error_condition( function_not_supported ); - case ERROR_INVALID_HANDLE_: return make_error_condition( invalid_argument ); - case ERROR_INVALID_NAME_: return make_error_condition( invalid_argument ); - case ERROR_LOCK_VIOLATION_: return make_error_condition( no_lock_available ); - case ERROR_LOCKED_: return make_error_condition( no_lock_available ); - case ERROR_NEGATIVE_SEEK_: return make_error_condition( invalid_argument ); - case ERROR_NOACCESS_: return make_error_condition( permission_denied ); - case ERROR_NOT_ENOUGH_MEMORY_: return make_error_condition( not_enough_memory ); - case ERROR_NOT_READY_: return make_error_condition( resource_unavailable_try_again ); - case ERROR_NOT_SAME_DEVICE_: return make_error_condition( cross_device_link ); - case ERROR_OPEN_FAILED_: return make_error_condition( io_error ); - case ERROR_OPEN_FILES_: return make_error_condition( device_or_resource_busy ); - case ERROR_OPERATION_ABORTED_: return make_error_condition( operation_canceled ); - case ERROR_OUTOFMEMORY_: return make_error_condition( not_enough_memory ); - case ERROR_PATH_NOT_FOUND_: return make_error_condition( no_such_file_or_directory ); - case ERROR_READ_FAULT_: return make_error_condition( io_error ); - case ERROR_RETRY_: return make_error_condition( resource_unavailable_try_again ); - case ERROR_SEEK_: return make_error_condition( io_error ); - case ERROR_SHARING_VIOLATION_: return make_error_condition( permission_denied ); - case ERROR_TOO_MANY_OPEN_FILES_: return make_error_condition( too_many_files_open ); - case ERROR_WRITE_FAULT_: return make_error_condition( io_error ); - case ERROR_WRITE_PROTECT_: return make_error_condition( permission_denied ); - case WSAEACCES_: return make_error_condition( permission_denied ); - case WSAEADDRINUSE_: return make_error_condition( address_in_use ); - case WSAEADDRNOTAVAIL_: return make_error_condition( address_not_available ); - case WSAEAFNOSUPPORT_: return make_error_condition( address_family_not_supported ); - case WSAEALREADY_: return make_error_condition( connection_already_in_progress ); - case WSAEBADF_: return make_error_condition( bad_file_descriptor ); - case WSAECONNABORTED_: return make_error_condition( connection_aborted ); - case WSAECONNREFUSED_: return make_error_condition( connection_refused ); - case WSAECONNRESET_: return make_error_condition( connection_reset ); - case WSAEDESTADDRREQ_: return make_error_condition( destination_address_required ); - case WSAEFAULT_: return make_error_condition( bad_address ); - case WSAEHOSTUNREACH_: return make_error_condition( host_unreachable ); - case WSAEINPROGRESS_: return make_error_condition( operation_in_progress ); - case WSAEINTR_: return make_error_condition( interrupted ); - case WSAEINVAL_: return make_error_condition( invalid_argument ); - case WSAEISCONN_: return make_error_condition( already_connected ); - case WSAEMFILE_: return make_error_condition( too_many_files_open ); - case WSAEMSGSIZE_: return make_error_condition( message_size ); - case WSAENAMETOOLONG_: return make_error_condition( filename_too_long ); - case WSAENETDOWN_: return make_error_condition( network_down ); - case WSAENETRESET_: return make_error_condition( network_reset ); - case WSAENETUNREACH_: return make_error_condition( network_unreachable ); - case WSAENOBUFS_: return make_error_condition( no_buffer_space ); - case WSAENOPROTOOPT_: return make_error_condition( no_protocol_option ); - case WSAENOTCONN_: return make_error_condition( not_connected ); - case WSAENOTSOCK_: return make_error_condition( not_a_socket ); - case WSAEOPNOTSUPP_: return make_error_condition( operation_not_supported ); - case WSAEPROTONOSUPPORT_: return make_error_condition( protocol_not_supported ); - case WSAEPROTOTYPE_: return make_error_condition( wrong_protocol_type ); - case WSAETIMEDOUT_: return make_error_condition( timed_out ); - case WSAEWOULDBLOCK_: return make_error_condition( operation_would_block ); - #endif - default: return error_condition( ev, system_category() ); - } - } - -# if !defined( BOOST_WINDOWS_API ) - - BOOST_SYSTEM_DECL_ std::string system_error_category::message( int ev ) const - { - return generic_category().message( ev ); - } -# else - - BOOST_SYSTEM_DECL_ std::string system_error_category::message( int ev ) const - { -#if defined(UNDER_CE) || BOOST_PLAT_WINDOWS_RUNTIME || defined(BOOST_NO_ANSI_APIS) - std::wstring buf(128, wchar_t()); - for (;;) - { - boost::winapi::DWORD_ retval = boost::winapi::FormatMessageW( - boost::winapi::FORMAT_MESSAGE_FROM_SYSTEM_ | - boost::winapi::FORMAT_MESSAGE_IGNORE_INSERTS_, - NULL, - ev, - boost::winapi::MAKELANGID_(boost::winapi::LANG_NEUTRAL_, - boost::winapi::SUBLANG_DEFAULT_), // Default language - &buf[0], - static_cast(buf.size()), - NULL - ); - - if (retval > 0) - { - buf.resize(retval); - break; - } - else if (boost::winapi::GetLastError() != - boost::winapi::ERROR_INSUFFICIENT_BUFFER_) - { - return std::string("Unknown error"); - } - else - { - buf.resize(buf.size() + buf.size() / 2); - } - } - - int num_chars = static_cast(buf.size() + 1) * 2; - - boost::winapi::LPSTR_ narrow_buffer = -#if defined(__GNUC__) - (boost::winapi::LPSTR_)__builtin_alloca(num_chars); -#else - (boost::winapi::LPSTR_)_alloca(num_chars); -#endif - - if (boost::winapi::WideCharToMultiByte(boost::winapi::CP_ACP_, 0, - buf.c_str(), -1, narrow_buffer, num_chars, NULL, NULL) == 0) - { - return std::string("Unknown error"); - } - - std::string str( narrow_buffer ); -#else - boost::winapi::LPVOID_ lpMsgBuf = 0; - boost::winapi::DWORD_ retval = boost::winapi::FormatMessageA( - boost::winapi::FORMAT_MESSAGE_ALLOCATE_BUFFER_ | - boost::winapi::FORMAT_MESSAGE_FROM_SYSTEM_ | - boost::winapi::FORMAT_MESSAGE_IGNORE_INSERTS_, - NULL, - ev, - boost::winapi::MAKELANGID_(boost::winapi::LANG_NEUTRAL_, - boost::winapi::SUBLANG_DEFAULT_), // Default language - (boost::winapi::LPSTR_) &lpMsgBuf, - 0, - NULL - ); - detail::local_free_on_destruction lfod(lpMsgBuf); - if (retval == 0) - return std::string("Unknown error"); - - std::string str(static_cast(lpMsgBuf)); -# endif - while ( str.size() - && (str[str.size()-1] == '\n' || str[str.size()-1] == '\r') ) - str.erase( str.size()-1 ); - if ( str.size() && str[str.size()-1] == '.' ) - { str.erase( str.size()-1 ); } - return str; - } -# endif - -#undef BOOST_SYSTEM_DECL_ - -} // namespace detail - - -# ifdef BOOST_SYSTEM_ENABLE_DEPRECATED - BOOST_SYSTEM_DECL error_code throws; // "throw on error" special error_code; - // note that it doesn't matter if this - // isn't initialized before use since - // the only use is to take its - // address for comparison purposes -# endif - -#if defined(BOOST_ERROR_CODE_HEADER_ONLY) - -// defined in error_code.hpp - -#elif defined(BOOST_SYSTEM_HAS_CONSTEXPR) - -namespace detail -{ - -BOOST_SYSTEM_REQUIRE_CONST_INIT BOOST_SYSTEM_DECL system_error_category system_category_instance; -BOOST_SYSTEM_REQUIRE_CONST_INIT BOOST_SYSTEM_DECL generic_error_category generic_category_instance; - -BOOST_SYSTEM_DECL const error_category & system_category_ncx() BOOST_SYSTEM_NOEXCEPT -{ - return system_category_instance; -} - -BOOST_SYSTEM_DECL const error_category & generic_category_ncx() BOOST_SYSTEM_NOEXCEPT -{ - return generic_category_instance; -} - -} // namespace detail - -#else - -namespace detail -{ - -BOOST_SYSTEM_DECL const error_category & system_category_ncx() BOOST_SYSTEM_NOEXCEPT -{ - static const detail::system_error_category system_category_instance; - return system_category_instance; -} - -BOOST_SYSTEM_DECL const error_category & generic_category_ncx() BOOST_SYSTEM_NOEXCEPT -{ - static const detail::generic_error_category generic_category_instance; - return generic_category_instance; -} - -} // namespace detail - -#endif - -} // namespace system - -} // namespace boost diff --git a/include/boost/system/detail/generic_category.hpp b/include/boost/system/detail/generic_category.hpp new file mode 100644 index 0000000..cba4a2e --- /dev/null +++ b/include/boost/system/detail/generic_category.hpp @@ -0,0 +1,69 @@ +// Implementation details of generic_error_category +// +// Copyright 2018 Peter Dimov +// +// 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) +// +// See library home page at http://www.boost.org/libs/system + +#include + +namespace boost +{ + +namespace system +{ + +namespace detail +{ + +#if defined(__GLIBC__) + +// std::strerror is not thread-safe on glibc (for no reason) +// glibc also has two incompatible strerror_r definitions (for no reason) + +inline char const * strerror_r_helper( char const * r, char const * ) +{ + return r; +} + +inline char const * strerror_r_helper( int r, char const * buffer ) +{ + return r == 0? buffer: "Unknown error"; +} + +inline std::string generic_error_category_message( int ev ) +{ + char buffer[ 128 ]; + return strerror_r_helper( strerror_r( ev, buffer, sizeof( buffer ) ), buffer ); +} + +#else + +// std::strerror is thread-safe on everything else, incl. Windows + +inline std::string generic_error_category_message( int ev ) +{ + +# if defined( BOOST_MSVC ) +# pragma warning( push ) +# pragma warning( disable: 4996 ) +# endif + + char const * m = std::strerror( ev ); + +# if defined( BOOST_MSVC ) +# pragma warning( pop ) +# endif + + return m? m: "Unknown error"; + +#endif +} + +} // namespace detail + +} // namespace system + +} // namespace boost diff --git a/include/boost/system/detail/local_free_on_destruction.hpp b/include/boost/system/detail/local_free_on_destruction.hpp deleted file mode 100644 index 9016e74..0000000 --- a/include/boost/system/detail/local_free_on_destruction.hpp +++ /dev/null @@ -1,42 +0,0 @@ -// local_free_on_exit.hpp ------------------------------------------------------------// - -// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// Copyright (c) 2010 Beman Dawes - -// Distributed under the Boost Software License, Version 1.0. -// See http://www.boost.org/LICENSE_1_0.txt - -// This is derived from boost/asio/detail/local_free_on_block_exit.hpp to avoid -// a dependency on asio. Thanks to Chris Kohlhoff for pointing it out. - -#ifndef BOOST_SYSTEM_LOCAL_FREE_ON_EXIT_HPP -#define BOOST_SYSTEM_LOCAL_FREE_ON_EXIT_HPP - -#include - -namespace boost { -namespace system { -namespace detail { - -class local_free_on_destruction -{ -public: - explicit local_free_on_destruction(void* p) - : p_(p) {} - - ~local_free_on_destruction() - { - boost::winapi::LocalFree(p_); - } - -private: - void* p_; - local_free_on_destruction(const local_free_on_destruction&); // = deleted - local_free_on_destruction& operator=(const local_free_on_destruction&); // = deleted -}; - -} // namespace detail -} // namespace system -} // namespace boost - -#endif // BOOST_SYSTEM_LOCAL_FREE_ON_EXIT_HPP diff --git a/include/boost/system/detail/std_interoperability.hpp b/include/boost/system/detail/std_interoperability.hpp new file mode 100644 index 0000000..b1b41d3 --- /dev/null +++ b/include/boost/system/detail/std_interoperability.hpp @@ -0,0 +1,141 @@ +// Support for interoperability between Boost.System and +// +// Copyright 2018 Peter Dimov +// +// 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) +// +// See library home page at http://www.boost.org/libs/system + +#include +#include +#include + +// + +namespace boost +{ + +namespace system +{ + +namespace detail +{ + +class BOOST_SYMBOL_VISIBLE std_category: public std::error_category +{ +private: + + boost::system::error_category const * pc_; + +public: + + explicit std_category( boost::system::error_category const * pc ): pc_( pc ) + { + } + + virtual const char * name() const BOOST_NOEXCEPT + { + return pc_->name(); + } + + virtual std::string message( int ev ) const + { + return pc_->message( ev ); + } + + virtual std::error_condition default_error_condition( int ev ) const BOOST_NOEXCEPT + { + return pc_->default_error_condition( ev ); + } + + virtual bool equivalent( int code, const std::error_condition & condition ) const BOOST_NOEXCEPT; + virtual bool equivalent( const std::error_code & code, int condition ) const BOOST_NOEXCEPT; +}; + +inline std::error_category const & to_std_category( boost::system::error_category const & cat ) +{ + typedef std::map< boost::system::error_category const *, std::unique_ptr > map_type; + + static map_type map_; + + map_type::iterator i = map_.find( &cat ); + + if( i == map_.end() ) + { + std::unique_ptr p( new std_category( &cat ) ); + + std::pair r = map_.insert( map_type::value_type( &cat, std::move( p ) ) ); + + i = r.first; + } + + return *i->second; +} + +inline bool std_category::equivalent( int code, const std::error_condition & condition ) const BOOST_NOEXCEPT +{ + if( condition.category() == *this ) + { + boost::system::error_condition bn( condition.value(), *pc_ ); + return pc_->equivalent( code, bn ); + } + else if( condition.category() == std::generic_category() || condition.category() == boost::system::generic_category() ) + { + boost::system::error_condition bn( condition.value(), boost::system::generic_category() ); + return pc_->equivalent( code, bn ); + } + +#ifndef BOOST_NO_RTTI + + else if( std_category const* pc2 = dynamic_cast< std_category const* >( &condition.category() ) ) + { + boost::system::error_condition bn( condition.value(), *pc2->pc_ ); + return pc_->equivalent( code, bn ); + } + +#endif + + else + { + return default_error_condition( code ) == condition; + } +} + +inline bool std_category::equivalent( const std::error_code & code, int condition ) const BOOST_NOEXCEPT +{ + if( code.category() == *this ) + { + boost::system::error_code bc( code.value(), *pc_ ); + return pc_->equivalent( bc, condition ); + } + else if( code.category() == std::generic_category() || code.category() == boost::system::generic_category() ) + { + boost::system::error_code bc( code.value(), boost::system::generic_category() ); + return pc_->equivalent( bc, condition ); + } + +#ifndef BOOST_NO_RTTI + + else if( std_category const* pc2 = dynamic_cast< std_category const* >( &code.category() ) ) + { + boost::system::error_code bc( code.value(), *pc2->pc_ ); + return pc_->equivalent( bc, condition ); + } +#endif + + else if( *pc_ == boost::system::generic_category() ) + { + return std::generic_category().equivalent( code, condition ); + } + else + { + return false; + } +} + +} // namespace detail + +} // namespace system + +} // namespace boost diff --git a/include/boost/system/detail/system_category_posix.hpp b/include/boost/system/detail/system_category_posix.hpp new file mode 100644 index 0000000..9a40623 --- /dev/null +++ b/include/boost/system/detail/system_category_posix.hpp @@ -0,0 +1,132 @@ +// POSIX-specific implementation details of system_error_category +// +// Copyright 2018 Peter Dimov +// +// 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) +// +// See library home page at http://www.boost.org/libs/system + +namespace boost +{ + +namespace system +{ + +namespace detail +{ + +inline bool is_generic_value( int ev ) BOOST_NOEXCEPT +{ + using namespace errc; + + static int const gen[] = + { + success, + address_family_not_supported, + address_in_use, + address_not_available, + already_connected, + argument_list_too_long, + argument_out_of_domain, + bad_address, + bad_file_descriptor, + bad_message, + broken_pipe, + connection_aborted, + connection_already_in_progress, + connection_refused, + connection_reset, + cross_device_link, + destination_address_required, + device_or_resource_busy, + directory_not_empty, + executable_format_error, + file_exists, + file_too_large, + filename_too_long, + function_not_supported, + host_unreachable, + identifier_removed, + illegal_byte_sequence, + inappropriate_io_control_operation, + interrupted, + invalid_argument, + invalid_seek, + io_error, + is_a_directory, + message_size, + network_down, + network_reset, + network_unreachable, + no_buffer_space, + no_child_process, + no_link, + no_lock_available, + no_message_available, + no_message, + no_protocol_option, + no_space_on_device, + no_stream_resources, + no_such_device_or_address, + no_such_device, + no_such_file_or_directory, + no_such_process, + not_a_directory, + not_a_socket, + not_a_stream, + not_connected, + not_enough_memory, + not_supported, + operation_canceled, + operation_in_progress, + operation_not_permitted, + operation_not_supported, + operation_would_block, + owner_dead, + permission_denied, + protocol_error, + protocol_not_supported, + read_only_file_system, + resource_deadlock_would_occur, + resource_unavailable_try_again, + result_out_of_range, + state_not_recoverable, + stream_timeout, + text_file_busy, + timed_out, + too_many_files_open_in_system, + too_many_files_open, + too_many_links, + too_many_symbolic_link_levels, + value_too_large, + wrong_protocol_type + }; + + int const n = sizeof( gen ) / sizeof( gen[0] ); + + for( int i = 0; i < n; ++i ) + { + if( ev == gen[ i ] ) return true; + } + + return false; +} + +inline error_condition system_category_default_error_condition_posix( int ev ) BOOST_NOEXCEPT +{ + if( is_generic_value( ev ) ) + { + return error_condition( ev, generic_category() ); + } + else + { + return error_condition( ev, system_category() ); + } +} + +} // namespace detail + +} // namespace system + +} // namespace boost diff --git a/include/boost/system/detail/system_category_win32.hpp b/include/boost/system/detail/system_category_win32.hpp new file mode 100644 index 0000000..66b8e1e --- /dev/null +++ b/include/boost/system/detail/system_category_win32.hpp @@ -0,0 +1,203 @@ +// Windows implementation of system_error_category +// +// Copyright Beman Dawes 2002, 2006 +// Copyright (c) Microsoft Corporation 2014 +// Copyright 2018 Peter Dimov +// +// 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) +// +// See library home page at http://www.boost.org/libs/system + +#include +#include +#include + +// + +namespace boost +{ + +namespace system +{ + +namespace detail +{ + +inline std::string system_category_message_win32( int ev ) +{ + using namespace boost::winapi; + + std::wstring buf( 128, wchar_t() ); + + for( ;; ) + { + DWORD_ retval = boost::winapi::FormatMessageW( + FORMAT_MESSAGE_FROM_SYSTEM_ | FORMAT_MESSAGE_IGNORE_INSERTS_, + NULL, + ev, + MAKELANGID_( LANG_NEUTRAL_, SUBLANG_DEFAULT_ ), // Default language + &buf[0], + static_cast( buf.size() ), + NULL + ); + + if( retval > 0 ) + { + buf.resize(retval); + break; + } + else if( boost::winapi::GetLastError() != ERROR_INSUFFICIENT_BUFFER_ ) + { + return "Unknown error"; + } + else + { + buf.resize( buf.size() + buf.size() / 2 ); + } + } + + int num_chars = static_cast( buf.size() + 1 ) * 2; + + boost::winapi::LPSTR_ narrow_buffer = +#if defined(__GNUC__) + (boost::winapi::LPSTR_)__builtin_alloca( num_chars ); +#else + (boost::winapi::LPSTR_)_alloca( num_chars ); +#endif + + if( boost::winapi::WideCharToMultiByte( CP_ACP_, 0, buf.c_str(), -1, narrow_buffer, num_chars, NULL, NULL ) == 0 ) + { + return "Unknown error"; + } + + std::string str( narrow_buffer ); + + while( !str.empty() && ( str[ str.size() - 1 ] == '\n' || str[ str.size() - 1 ] == '\r' ) ) + { + str.erase( str.size() - 1 ); + } + + if( str.size() && str[ str.size() - 1 ] == '.' ) + { + str.erase( str.size() - 1 ); + } + + return str; +} + +inline error_condition system_category_default_error_condition_win32( int ev ) BOOST_NOEXCEPT +{ + // When using the Windows Runtime, most system errors are reported as HRESULTs. + // We want to map the common Win32 errors to their equivalent error condition, + // whether or not they are reported via an HRESULT. + +#define BOOST_SYSTEM_FAILED(hr) ((hr) < 0) +#define BOOST_SYSTEM_HRESULT_FACILITY(hr) (((hr) >> 16) & 0x1fff) +#define BOOST_SYSTEM_HRESULT_CODE(hr) ((hr) & 0xFFFF) +#define BOOST_SYSTEM_FACILITY_WIN32 7 + + if( BOOST_SYSTEM_FAILED( ev ) && BOOST_SYSTEM_HRESULT_FACILITY( ev ) == BOOST_SYSTEM_FACILITY_WIN32 ) + { + ev = BOOST_SYSTEM_HRESULT_CODE( ev ); + } + +#undef BOOST_SYSTEM_FAILED +#undef BOOST_SYSTEM_HRESULT_FACILITY +#undef BOOST_SYSTEM_HRESULT_CODE +#undef BOOST_SYSTEM_FACILITY_WIN32 + + using namespace boost::winapi; + using namespace errc; + + // Windows system -> posix_errno decode table + // see WinError.h comments for descriptions of errors + + switch ( ev ) + { + case 0: return make_error_condition( success ); + + case ERROR_ACCESS_DENIED_: return make_error_condition( permission_denied ); + case ERROR_ALREADY_EXISTS_: return make_error_condition( file_exists ); + case ERROR_BAD_UNIT_: return make_error_condition( no_such_device ); + case ERROR_BUFFER_OVERFLOW_: return make_error_condition( filename_too_long ); + case ERROR_BUSY_: return make_error_condition( device_or_resource_busy ); + case ERROR_BUSY_DRIVE_: return make_error_condition( device_or_resource_busy ); + case ERROR_CANNOT_MAKE_: return make_error_condition( permission_denied ); + case ERROR_CANTOPEN_: return make_error_condition( io_error ); + case ERROR_CANTREAD_: return make_error_condition( io_error ); + case ERROR_CANTWRITE_: return make_error_condition( io_error ); + case ERROR_CURRENT_DIRECTORY_: return make_error_condition( permission_denied ); + case ERROR_DEV_NOT_EXIST_: return make_error_condition( no_such_device ); + case ERROR_DEVICE_IN_USE_: return make_error_condition( device_or_resource_busy ); + case ERROR_DIR_NOT_EMPTY_: return make_error_condition( directory_not_empty ); + case ERROR_DIRECTORY_: return make_error_condition( invalid_argument ); // WinError.h: "The directory name is invalid" + case ERROR_DISK_FULL_: return make_error_condition( no_space_on_device ); + case ERROR_FILE_EXISTS_: return make_error_condition( file_exists ); + case ERROR_FILE_NOT_FOUND_: return make_error_condition( no_such_file_or_directory ); + case ERROR_HANDLE_DISK_FULL_: return make_error_condition( no_space_on_device ); + case ERROR_INVALID_ACCESS_: return make_error_condition( permission_denied ); + case ERROR_INVALID_DRIVE_: return make_error_condition( no_such_device ); + case ERROR_INVALID_FUNCTION_: return make_error_condition( function_not_supported ); + case ERROR_INVALID_HANDLE_: return make_error_condition( invalid_argument ); + case ERROR_INVALID_NAME_: return make_error_condition( invalid_argument ); + case ERROR_LOCK_VIOLATION_: return make_error_condition( no_lock_available ); + case ERROR_LOCKED_: return make_error_condition( no_lock_available ); + case ERROR_NEGATIVE_SEEK_: return make_error_condition( invalid_argument ); + case ERROR_NOACCESS_: return make_error_condition( permission_denied ); + case ERROR_NOT_ENOUGH_MEMORY_: return make_error_condition( not_enough_memory ); + case ERROR_NOT_READY_: return make_error_condition( resource_unavailable_try_again ); + case ERROR_NOT_SAME_DEVICE_: return make_error_condition( cross_device_link ); + case ERROR_OPEN_FAILED_: return make_error_condition( io_error ); + case ERROR_OPEN_FILES_: return make_error_condition( device_or_resource_busy ); + case ERROR_OPERATION_ABORTED_: return make_error_condition( operation_canceled ); + case ERROR_OUTOFMEMORY_: return make_error_condition( not_enough_memory ); + case ERROR_PATH_NOT_FOUND_: return make_error_condition( no_such_file_or_directory ); + case ERROR_READ_FAULT_: return make_error_condition( io_error ); + case ERROR_RETRY_: return make_error_condition( resource_unavailable_try_again ); + case ERROR_SEEK_: return make_error_condition( io_error ); + case ERROR_SHARING_VIOLATION_: return make_error_condition( permission_denied ); + case ERROR_TOO_MANY_OPEN_FILES_: return make_error_condition( too_many_files_open ); + case ERROR_WRITE_FAULT_: return make_error_condition( io_error ); + case ERROR_WRITE_PROTECT_: return make_error_condition( permission_denied ); + case WSAEACCES_: return make_error_condition( permission_denied ); + case WSAEADDRINUSE_: return make_error_condition( address_in_use ); + case WSAEADDRNOTAVAIL_: return make_error_condition( address_not_available ); + case WSAEAFNOSUPPORT_: return make_error_condition( address_family_not_supported ); + case WSAEALREADY_: return make_error_condition( connection_already_in_progress ); + case WSAEBADF_: return make_error_condition( bad_file_descriptor ); + case WSAECONNABORTED_: return make_error_condition( connection_aborted ); + case WSAECONNREFUSED_: return make_error_condition( connection_refused ); + case WSAECONNRESET_: return make_error_condition( connection_reset ); + case WSAEDESTADDRREQ_: return make_error_condition( destination_address_required ); + case WSAEFAULT_: return make_error_condition( bad_address ); + case WSAEHOSTUNREACH_: return make_error_condition( host_unreachable ); + case WSAEINPROGRESS_: return make_error_condition( operation_in_progress ); + case WSAEINTR_: return make_error_condition( interrupted ); + case WSAEINVAL_: return make_error_condition( invalid_argument ); + case WSAEISCONN_: return make_error_condition( already_connected ); + case WSAEMFILE_: return make_error_condition( too_many_files_open ); + case WSAEMSGSIZE_: return make_error_condition( message_size ); + case WSAENAMETOOLONG_: return make_error_condition( filename_too_long ); + case WSAENETDOWN_: return make_error_condition( network_down ); + case WSAENETRESET_: return make_error_condition( network_reset ); + case WSAENETUNREACH_: return make_error_condition( network_unreachable ); + case WSAENOBUFS_: return make_error_condition( no_buffer_space ); + case WSAENOPROTOOPT_: return make_error_condition( no_protocol_option ); + case WSAENOTCONN_: return make_error_condition( not_connected ); + case WSAENOTSOCK_: return make_error_condition( not_a_socket ); + case WSAEOPNOTSUPP_: return make_error_condition( operation_not_supported ); + case WSAEPROTONOSUPPORT_: return make_error_condition( protocol_not_supported ); + case WSAEPROTOTYPE_: return make_error_condition( wrong_protocol_type ); + case WSAETIMEDOUT_: return make_error_condition( timed_out ); + case WSAEWOULDBLOCK_: return make_error_condition( operation_would_block ); + + default: return error_condition( ev, system_category() ); + } +} + +} // namespace detail + +} // namespace system + +} // namespace boost diff --git a/include/boost/system/error_code.hpp b/include/boost/system/error_code.hpp index eb22f8e..684cd47 100644 --- a/include/boost/system/error_code.hpp +++ b/include/boost/system/error_code.hpp @@ -1,943 +1,821 @@ -// boost/system/error_code.hpp -------------------------------------------------------// +#ifndef BOOST_SYSTEM_ERROR_CODE_HPP_INCLUDED +#define BOOST_SYSTEM_ERROR_CODE_HPP_INCLUDED // Copyright Beman Dawes 2006, 2007 // Copyright Christoper Kohlhoff 2007 // Copyright Peter Dimov 2017, 2018 - +// // 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) - +// // See library home page at http://www.boost.org/libs/system -#ifndef BOOST_SYSTEM_ERROR_CODE_HPP -#define BOOST_SYSTEM_ERROR_CODE_HPP - -#include +#include +#include #include -#include -#include +#include #include #include -#include #include // TODO: undef these macros if not already defined #include +#if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR) +# include +#endif + #if !defined(BOOST_POSIX_API) && !defined(BOOST_WINDOWS_API) # error BOOST_POSIX_API or BOOST_WINDOWS_API must be defined #endif -#ifndef BOOST_NO_CXX11_HDR_SYSTEM_ERROR -#include -#endif - -#include // must be the last #include - -#ifndef BOOST_SYSTEM_NOEXCEPT -#define BOOST_SYSTEM_NOEXCEPT BOOST_NOEXCEPT -#endif - -#if !defined(BOOST_NO_CXX14_CONSTEXPR) -# define BOOST_SYSTEM_HAS_CONSTEXPR -#endif - -#if defined(__GNUC__) && (__GNUC__ == 7 && __GNUC_MINOR__ < 4) && __cplusplus >= 201700L -// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83835 -# undef BOOST_SYSTEM_HAS_CONSTEXPR -#endif - -#if defined(__clang__) && defined(_MSC_VER) && defined(_CPPLIB_VER) -// Clang on Windows with MSVC headers, the constructor of std::error_category -// is not constexpr at least up to VS2017 15.7.x (_MSVC_STL_UPDATE 201803) -# undef BOOST_SYSTEM_HAS_CONSTEXPR -#endif - -#if defined(__clang__) && defined(BOOST_LIBSTDCXX_VERSION) && BOOST_LIBSTDCXX_VERSION < 40900 -// The constructor of std::error_category is not constexpr in libstdc++ 4.8 -# undef BOOST_SYSTEM_HAS_CONSTEXPR -#endif - -#if defined(BOOST_SYSTEM_HAS_CONSTEXPR) -# define BOOST_SYSTEM_CONSTEXPR constexpr -#else -# define BOOST_SYSTEM_CONSTEXPR -#endif - namespace boost { - namespace system - { - class error_code; // values defined by the operating system - class error_condition; // portable generic values defined below, but ultimately - // based on the POSIX standard +namespace system +{ - // "Concept" helpers -------------------------------------------------------------// +class error_code; // values defined by the operating system +class error_condition; // portable generic values defined below, but ultimately + // based on the POSIX standard - template< class T > - struct is_error_code_enum { static const bool value = false; }; +// "Concept" helpers - template< class T > - struct is_error_condition_enum { static const bool value = false; }; +template struct is_error_code_enum +{ + static const bool value = false; +}; - // generic error_conditions ------------------------------------------------------// +template struct is_error_condition_enum +{ + static const bool value = false; +}; - namespace errc - { - enum errc_t - { - success = 0, - address_family_not_supported = EAFNOSUPPORT, - address_in_use = EADDRINUSE, - address_not_available = EADDRNOTAVAIL, - already_connected = EISCONN, - argument_list_too_long = E2BIG, - argument_out_of_domain = EDOM, - bad_address = EFAULT, - bad_file_descriptor = EBADF, - bad_message = EBADMSG, - broken_pipe = EPIPE, - connection_aborted = ECONNABORTED, - connection_already_in_progress = EALREADY, - connection_refused = ECONNREFUSED, - connection_reset = ECONNRESET, - cross_device_link = EXDEV, - destination_address_required = EDESTADDRREQ, - device_or_resource_busy = EBUSY, - directory_not_empty = ENOTEMPTY, - executable_format_error = ENOEXEC, - file_exists = EEXIST, - file_too_large = EFBIG, - filename_too_long = ENAMETOOLONG, - function_not_supported = ENOSYS, - host_unreachable = EHOSTUNREACH, - identifier_removed = EIDRM, - illegal_byte_sequence = EILSEQ, - inappropriate_io_control_operation = ENOTTY, - interrupted = EINTR, - invalid_argument = EINVAL, - invalid_seek = ESPIPE, - io_error = EIO, - is_a_directory = EISDIR, - message_size = EMSGSIZE, - network_down = ENETDOWN, - network_reset = ENETRESET, - network_unreachable = ENETUNREACH, - no_buffer_space = ENOBUFS, - no_child_process = ECHILD, - no_link = ENOLINK, - no_lock_available = ENOLCK, - no_message_available = ENODATA, - no_message = ENOMSG, - no_protocol_option = ENOPROTOOPT, - no_space_on_device = ENOSPC, - no_stream_resources = ENOSR, - no_such_device_or_address = ENXIO, - no_such_device = ENODEV, - no_such_file_or_directory = ENOENT, - no_such_process = ESRCH, - not_a_directory = ENOTDIR, - not_a_socket = ENOTSOCK, - not_a_stream = ENOSTR, - not_connected = ENOTCONN, - not_enough_memory = ENOMEM, - not_supported = ENOTSUP, - operation_canceled = ECANCELED, - operation_in_progress = EINPROGRESS, - operation_not_permitted = EPERM, - operation_not_supported = EOPNOTSUPP, - operation_would_block = EWOULDBLOCK, - owner_dead = EOWNERDEAD, - permission_denied = EACCES, - protocol_error = EPROTO, - protocol_not_supported = EPROTONOSUPPORT, - read_only_file_system = EROFS, - resource_deadlock_would_occur = EDEADLK, - resource_unavailable_try_again = EAGAIN, - result_out_of_range = ERANGE, - state_not_recoverable = ENOTRECOVERABLE, - stream_timeout = ETIME, - text_file_busy = ETXTBSY, - timed_out = ETIMEDOUT, - too_many_files_open_in_system = ENFILE, - too_many_files_open = EMFILE, - too_many_links = EMLINK, - too_many_symbolic_link_levels = ELOOP, - value_too_large = EOVERFLOW, - wrong_protocol_type = EPROTOTYPE - }; +// Generic error_conditions - } // namespace errc +namespace errc +{ -# ifdef BOOST_SYSTEM_ENABLE_DEPRECATED - namespace posix = errc; - namespace posix_error = errc; -# endif +enum errc_t +{ + success = 0, + address_family_not_supported = EAFNOSUPPORT, + address_in_use = EADDRINUSE, + address_not_available = EADDRNOTAVAIL, + already_connected = EISCONN, + argument_list_too_long = E2BIG, + argument_out_of_domain = EDOM, + bad_address = EFAULT, + bad_file_descriptor = EBADF, + bad_message = EBADMSG, + broken_pipe = EPIPE, + connection_aborted = ECONNABORTED, + connection_already_in_progress = EALREADY, + connection_refused = ECONNREFUSED, + connection_reset = ECONNRESET, + cross_device_link = EXDEV, + destination_address_required = EDESTADDRREQ, + device_or_resource_busy = EBUSY, + directory_not_empty = ENOTEMPTY, + executable_format_error = ENOEXEC, + file_exists = EEXIST, + file_too_large = EFBIG, + filename_too_long = ENAMETOOLONG, + function_not_supported = ENOSYS, + host_unreachable = EHOSTUNREACH, + identifier_removed = EIDRM, + illegal_byte_sequence = EILSEQ, + inappropriate_io_control_operation = ENOTTY, + interrupted = EINTR, + invalid_argument = EINVAL, + invalid_seek = ESPIPE, + io_error = EIO, + is_a_directory = EISDIR, + message_size = EMSGSIZE, + network_down = ENETDOWN, + network_reset = ENETRESET, + network_unreachable = ENETUNREACH, + no_buffer_space = ENOBUFS, + no_child_process = ECHILD, + no_link = ENOLINK, + no_lock_available = ENOLCK, + no_message_available = ENODATA, + no_message = ENOMSG, + no_protocol_option = ENOPROTOOPT, + no_space_on_device = ENOSPC, + no_stream_resources = ENOSR, + no_such_device_or_address = ENXIO, + no_such_device = ENODEV, + no_such_file_or_directory = ENOENT, + no_such_process = ESRCH, + not_a_directory = ENOTDIR, + not_a_socket = ENOTSOCK, + not_a_stream = ENOSTR, + not_connected = ENOTCONN, + not_enough_memory = ENOMEM, + not_supported = ENOTSUP, + operation_canceled = ECANCELED, + operation_in_progress = EINPROGRESS, + operation_not_permitted = EPERM, + operation_not_supported = EOPNOTSUPP, + operation_would_block = EWOULDBLOCK, + owner_dead = EOWNERDEAD, + permission_denied = EACCES, + protocol_error = EPROTO, + protocol_not_supported = EPROTONOSUPPORT, + read_only_file_system = EROFS, + resource_deadlock_would_occur = EDEADLK, + resource_unavailable_try_again = EAGAIN, + result_out_of_range = ERANGE, + state_not_recoverable = ENOTRECOVERABLE, + stream_timeout = ETIME, + text_file_busy = ETXTBSY, + timed_out = ETIMEDOUT, + too_many_files_open_in_system = ENFILE, + too_many_files_open = EMFILE, + too_many_links = EMLINK, + too_many_symbolic_link_levels = ELOOP, + value_too_large = EOVERFLOW, + wrong_protocol_type = EPROTOTYPE +}; - template<> struct is_error_condition_enum - { static const bool value = true; }; +} // namespace errc +#ifdef BOOST_SYSTEM_ENABLE_DEPRECATED - // --------------------------------------------------------------------------------// +namespace posix = errc; +namespace posix_error = errc; - // Operating system specific interfaces ------------------------------------------// - - - // The interface is divided into general and system-specific portions to - // meet these requirements: - // - // * Code calling an operating system API can create an error_code with - // a single category (system_category), even for POSIX-like operating - // systems that return some POSIX errno values and some native errno - // values. This code should not have to pay the cost of distinguishing - // between categories, since it is not yet known if that is needed. - // - // * Users wishing to write system-specific code should be given enums for - // at least the common error cases. - // - // * System specific code should fail at compile time if moved to another - // operating system. - - // The system specific portions of the interface are located in headers - // with names reflecting the operating system. For example, - // - // - // - // - // - // These headers are effectively empty for compiles on operating systems - // where they are not applicable. - - // --------------------------------------------------------------------------------// - -#ifdef BOOST_MSVC -#pragma warning(push) -// 'this' : used in base member initializer list -#pragma warning(disable: 4355) #endif - // class error_category ------------------------------------------------// +template<> struct is_error_condition_enum +{ + static const bool value = true; +}; - class error_category : public noncopyable - { -#ifndef BOOST_NO_CXX11_HDR_SYSTEM_ERROR +// class error_category - private: +#ifdef BOOST_MSVC +#pragma warning( push ) +// 'this' : used in base member initializer list +#pragma warning( disable: 4355 ) +#endif - class std_category: public std::error_category - { - private: +std::size_t hash_value( error_code const & ec ); - boost::system::error_category const * pc_; +class BOOST_SYMBOL_VISIBLE error_category +{ +private: - public: + friend std::size_t hash_value( error_code const & ec ); - BOOST_SYSTEM_CONSTEXPR explicit std_category( boost::system::error_category const * pc ): pc_( pc ) - { - } +#if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) +public: - virtual const char * name() const BOOST_NOEXCEPT - { - return pc_->name(); - } + error_category( error_category const & ) = delete; + error_category& operator=( error_category const & ) = delete; - virtual std::string message( int ev ) const - { - return pc_->message( ev ); - } +#else +private: - virtual std::error_condition default_error_condition( int ev ) const - BOOST_NOEXCEPT; - virtual bool equivalent( int code, const std::error_condition & condition ) const - BOOST_NOEXCEPT; - virtual bool equivalent( const std::error_code & code, int condition ) const - BOOST_NOEXCEPT; - }; + error_category( error_category const & ); + error_category& operator=( error_category const & ); - std_category std_cat_; +#endif - public: +private: - BOOST_SYSTEM_CONSTEXPR error_category() BOOST_SYSTEM_NOEXCEPT: std_cat_( this ) {} + boost::ulong_long_type id_; - operator std::error_category const & () const BOOST_SYSTEM_NOEXCEPT - { - // do not map generic to std::generic on purpose; occasionally, - // there are two std::generic categories in a program, which leads - // to error codes/conditions mysteriously not being equal to themselves - return std_cat_; - } +protected: + +#if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) && !defined(BOOST_NO_CXX11_NON_PUBLIC_DEFAULTED_FUNCTIONS) + + ~error_category() = default; #else - // to maintain ABI compatibility between 03 and 11, - // define a class with the same layout - - private: - - class std_category - { - private: - - boost::system::error_category const * pc_; - - public: - - BOOST_SYSTEM_CONSTEXPR explicit std_category( boost::system::error_category const * pc ): pc_( pc ) - { - } - - virtual ~std_category() {} - - virtual const char * name() const BOOST_NOEXCEPT - { - return pc_->name(); - } - - // we can't define message, because (1) it returns an std::string, - // which can be different between 03 and 11, and (2) on mingw, there - // are actually two `message` functions, not one, so it doesn't work - // even if we do - - // neither can we define default_error_condition or equivalent - - // if these functions are called, it will crash, but that's still - // better than the alternative of having the class layout change - }; - - std_category std_cat_; - - public: - - BOOST_SYSTEM_CONSTEXPR error_category() BOOST_SYSTEM_NOEXCEPT: std_cat_( this ) {} + ~error_category() + { + } #endif - public: - virtual ~error_category(){} + explicit BOOST_SYSTEM_CONSTEXPR error_category( boost::ulong_long_type id ) BOOST_NOEXCEPT: id_( id ) + { + } - virtual const char * name() const BOOST_SYSTEM_NOEXCEPT = 0; - virtual std::string message( int ev ) const = 0; - inline virtual error_condition default_error_condition( int ev ) const - BOOST_SYSTEM_NOEXCEPT; - inline virtual bool equivalent( int code, - const error_condition & condition ) const - BOOST_SYSTEM_NOEXCEPT; - inline virtual bool equivalent( const error_code & code, - int condition ) const BOOST_SYSTEM_NOEXCEPT; - }; +public: - BOOST_SYSTEM_CONSTEXPR inline bool operator==( const error_category & lhs, - const error_category & rhs ) BOOST_SYSTEM_NOEXCEPT - { return &lhs == &rhs; } + BOOST_SYSTEM_CONSTEXPR error_category() BOOST_NOEXCEPT: id_( 0 ) + { + } - BOOST_SYSTEM_CONSTEXPR inline bool operator!=( const error_category & lhs, - const error_category & rhs ) BOOST_SYSTEM_NOEXCEPT - { return &lhs != &rhs; } + virtual const char * name() const BOOST_NOEXCEPT = 0; - inline bool operator<( const error_category & lhs, - const error_category & rhs ) BOOST_SYSTEM_NOEXCEPT - { return std::less()( &lhs, &rhs ); } + virtual std::string message( int ev ) const = 0; + + virtual error_condition default_error_condition( int ev ) const BOOST_NOEXCEPT; + virtual bool equivalent( int code, const error_condition & condition ) const BOOST_NOEXCEPT; + virtual bool equivalent( const error_code & code, int condition ) const BOOST_NOEXCEPT; + + BOOST_SYSTEM_CONSTEXPR bool operator==( const error_category & rhs ) const BOOST_NOEXCEPT + { + return rhs.id_ == 0? this == &rhs: id_ == rhs.id_; + } + + BOOST_SYSTEM_CONSTEXPR bool operator!=( const error_category & rhs ) const BOOST_NOEXCEPT + { + return !( *this == rhs ); + } + + BOOST_SYSTEM_CONSTEXPR bool operator<( const error_category & rhs ) const BOOST_NOEXCEPT + { + if( id_ < rhs.id_ ) + { + return true; + } + + if( id_ > rhs.id_ ) + { + return false; + } + + if( rhs.id_ != 0 ) + { + return false; // equal + } + + return std::less()( this, &rhs ); + } + +#if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR) + + operator std::error_category const & () const; + +#endif +}; #ifdef BOOST_MSVC -#pragma warning(pop) +#pragma warning( pop ) #endif - // predefined error categories ---------------------------------------------------// +// predefined error categories namespace detail { -#ifdef BOOST_ERROR_CODE_HEADER_ONLY -# define BOOST_SYSTEM_DECL_ -#else -# define BOOST_SYSTEM_DECL_ BOOST_SYSTEM_DECL -#endif - -class generic_error_category: public error_category +class BOOST_SYMBOL_VISIBLE generic_error_category: public error_category { public: // clang++ 3.8 and below: initialization of const object // requires a user-provided default constructor - BOOST_SYSTEM_CONSTEXPR generic_error_category() BOOST_SYSTEM_NOEXCEPT + BOOST_SYSTEM_CONSTEXPR generic_error_category() BOOST_NOEXCEPT: error_category( 0xB2AB117A257EDF0Dull ) { } - const char * name() const BOOST_SYSTEM_NOEXCEPT + const char * name() const BOOST_NOEXCEPT { return "generic"; } - BOOST_SYSTEM_DECL_ std::string message( int ev ) const; + std::string message( int ev ) const; }; -class system_error_category: public error_category +class BOOST_SYMBOL_VISIBLE system_error_category: public error_category { public: - BOOST_SYSTEM_CONSTEXPR system_error_category() BOOST_SYSTEM_NOEXCEPT + BOOST_SYSTEM_CONSTEXPR system_error_category() BOOST_NOEXCEPT: error_category( 0x8FAFD21E25C5E09Bull ) { } - const char * name() const BOOST_SYSTEM_NOEXCEPT + const char * name() const BOOST_NOEXCEPT { return "system"; } - BOOST_SYSTEM_DECL_ std::string message( int ev ) const; - BOOST_SYSTEM_DECL_ error_condition default_error_condition( int ev ) const BOOST_SYSTEM_NOEXCEPT; + std::string message( int ev ) const; + error_condition default_error_condition( int ev ) const BOOST_NOEXCEPT; }; -#undef BOOST_SYSTEM_DECL_ - } // namespace detail -#define BOOST_SYSTEM_REQUIRE_CONST_INIT +// generic_category(), system_category() -#if defined(__has_cpp_attribute) -#if __has_cpp_attribute(clang::require_constant_initialization) -# undef BOOST_SYSTEM_REQUIRE_CONST_INIT -# define BOOST_SYSTEM_REQUIRE_CONST_INIT [[clang::require_constant_initialization]] -#endif -#endif - -#if defined(BOOST_ERROR_CODE_HEADER_ONLY) - -# if defined(BOOST_SYSTEM_HAS_CONSTEXPR) +#if defined(BOOST_SYSTEM_HAS_CONSTEXPR) namespace detail { template struct cat_holder { - static system_error_category system_category_instance; - static generic_error_category generic_category_instance; + BOOST_SYSTEM_REQUIRE_CONST_INIT static constexpr system_error_category system_category_instance{}; + BOOST_SYSTEM_REQUIRE_CONST_INIT static constexpr generic_error_category generic_category_instance{}; }; -template BOOST_SYSTEM_REQUIRE_CONST_INIT system_error_category cat_holder::system_category_instance; -template BOOST_SYSTEM_REQUIRE_CONST_INIT generic_error_category cat_holder::generic_category_instance; +template BOOST_SYSTEM_REQUIRE_CONST_INIT constexpr system_error_category cat_holder::system_category_instance; +template BOOST_SYSTEM_REQUIRE_CONST_INIT constexpr generic_error_category cat_holder::generic_category_instance; } // namespace detail -constexpr const error_category & system_category() BOOST_SYSTEM_NOEXCEPT +constexpr error_category const & system_category() BOOST_NOEXCEPT { return detail::cat_holder::system_category_instance; } -constexpr const error_category & generic_category() BOOST_SYSTEM_NOEXCEPT +constexpr error_category const & generic_category() BOOST_NOEXCEPT { return detail::cat_holder::generic_category_instance; } -# else +#else // #if defined(BOOST_SYSTEM_HAS_CONSTEXPR) -inline const error_category & system_category() BOOST_SYSTEM_NOEXCEPT +inline error_category const & system_category() BOOST_NOEXCEPT { static const detail::system_error_category system_category_instance; return system_category_instance; } -inline const error_category & generic_category() BOOST_SYSTEM_NOEXCEPT +inline error_category const & generic_category() BOOST_NOEXCEPT { static const detail::generic_error_category generic_category_instance; return generic_category_instance; } -# endif +#endif // #if defined(BOOST_SYSTEM_HAS_CONSTEXPR) -#elif defined(BOOST_SYSTEM_HAS_CONSTEXPR) - -namespace detail -{ - -#if defined(BOOST_SYSTEM_SOURCE) - -// clang++ requires a strictly matching declaration -BOOST_SYSTEM_DECL extern system_error_category system_category_instance; -BOOST_SYSTEM_DECL extern generic_error_category generic_category_instance; - -#else - -extern system_error_category system_category_instance; -extern generic_error_category generic_category_instance; - -#endif - -} // namespace detail - -constexpr const error_category & system_category() BOOST_SYSTEM_NOEXCEPT -{ - return detail::system_category_instance; -} - -constexpr const error_category & generic_category() BOOST_SYSTEM_NOEXCEPT -{ - return detail::generic_category_instance; -} - -#else - -namespace detail -{ - -BOOST_SYSTEM_DECL const error_category & system_category_ncx() BOOST_SYSTEM_NOEXCEPT; -BOOST_SYSTEM_DECL const error_category & generic_category_ncx() BOOST_SYSTEM_NOEXCEPT; - -} // namespace detail - -inline const error_category & system_category() BOOST_SYSTEM_NOEXCEPT -{ - return detail::system_category_ncx(); -} - -inline const error_category & generic_category() BOOST_SYSTEM_NOEXCEPT -{ - return detail::generic_category_ncx(); -} - -#endif - - // deprecated synonyms ------------------------------------------------------------// +// deprecated synonyms #ifdef BOOST_SYSTEM_ENABLE_DEPRECATED - inline const error_category & get_system_category() { return system_category(); } - inline const error_category & get_generic_category() { return generic_category(); } - inline const error_category & get_posix_category() { return generic_category(); } - static const error_category & posix_category BOOST_ATTRIBUTE_UNUSED - = generic_category(); - static const error_category & errno_ecat BOOST_ATTRIBUTE_UNUSED - = generic_category(); - static const error_category & native_ecat BOOST_ATTRIBUTE_UNUSED - = system_category(); + +inline const error_category & get_system_category() { return system_category(); } +inline const error_category & get_generic_category() { return generic_category(); } +inline const error_category & get_posix_category() { return generic_category(); } +static const error_category & posix_category BOOST_ATTRIBUTE_UNUSED = generic_category(); +static const error_category & errno_ecat BOOST_ATTRIBUTE_UNUSED = generic_category(); +static const error_category & native_ecat BOOST_ATTRIBUTE_UNUSED = system_category(); + #endif - // class error_condition ---------------------------------------------------------// +// enable_if - // error_conditions are portable, error_codes are system or library specific +namespace detail +{ - class error_condition +template struct enable_if +{ + typedef T type; +}; + +template struct enable_if +{ +}; + +} // namespace detail + +// class error_condition + +// error_conditions are portable, error_codes are system or library specific + +class error_condition +{ +private: + + int m_val; + error_category const * m_cat; + +public: + + // constructors: + + BOOST_SYSTEM_CONSTEXPR error_condition() BOOST_NOEXCEPT: m_val( 0 ), m_cat( &generic_category() ) { - public: + } - // constructors: - BOOST_SYSTEM_CONSTEXPR error_condition() BOOST_SYSTEM_NOEXCEPT : m_val(0), m_cat(&generic_category()) {} - BOOST_SYSTEM_CONSTEXPR error_condition( int val, const error_category & cat ) BOOST_SYSTEM_NOEXCEPT - : m_val(val), m_cat(&cat) {} + BOOST_SYSTEM_CONSTEXPR error_condition( int val, const error_category & cat ) BOOST_NOEXCEPT: m_val( val ), m_cat( &cat ) + { + } - template - error_condition(ErrorConditionEnum e, - typename boost::enable_if_::value>::type* - = 0) BOOST_SYSTEM_NOEXCEPT - { - *this = make_error_condition(e); - } + template BOOST_SYSTEM_CONSTEXPR error_condition( ErrorConditionEnum e, + typename detail::enable_if::value>::type* = 0) BOOST_NOEXCEPT + { + *this = make_error_condition( e ); + } - // modifiers: + // modifiers: - BOOST_SYSTEM_CONSTEXPR void assign( int val, const error_category & cat ) BOOST_SYSTEM_NOEXCEPT - { + BOOST_SYSTEM_CONSTEXPR void assign( int val, const error_category & cat ) BOOST_NOEXCEPT + { m_val = val; m_cat = &cat; - } + } - template - typename boost::enable_if_::value, - error_condition>::type & - operator=( ErrorConditionEnum val ) BOOST_SYSTEM_NOEXCEPT - { - *this = make_error_condition(val); + template + BOOST_SYSTEM_CONSTEXPR typename detail::enable_if::value, error_condition>::type & + operator=( ErrorConditionEnum val ) BOOST_NOEXCEPT + { + *this = make_error_condition( val ); return *this; - } + } - BOOST_SYSTEM_CONSTEXPR void clear() BOOST_SYSTEM_NOEXCEPT - { + BOOST_SYSTEM_CONSTEXPR void clear() BOOST_NOEXCEPT + { m_val = 0; m_cat = &generic_category(); - } + } - // observers: - BOOST_SYSTEM_CONSTEXPR int value() const BOOST_SYSTEM_NOEXCEPT { return m_val; } - BOOST_SYSTEM_CONSTEXPR const error_category & category() const BOOST_SYSTEM_NOEXCEPT { return *m_cat; } - std::string message() const { return m_cat->message(value()); } + // observers: + + BOOST_SYSTEM_CONSTEXPR int value() const BOOST_NOEXCEPT + { + return m_val; + } + + BOOST_SYSTEM_CONSTEXPR const error_category & category() const BOOST_NOEXCEPT + { + return *m_cat; + } + + std::string message() const + { + return m_cat->message( value() ); + } #if !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) - BOOST_SYSTEM_CONSTEXPR explicit operator bool() const BOOST_SYSTEM_NOEXCEPT // true if error - { + BOOST_SYSTEM_CONSTEXPR explicit operator bool() const BOOST_NOEXCEPT // true if error + { return m_val != 0; - } + } #else - typedef void (*unspecified_bool_type)(); - static void unspecified_bool_true() {} + typedef void (*unspecified_bool_type)(); + static void unspecified_bool_true() {} - BOOST_SYSTEM_CONSTEXPR operator unspecified_bool_type() const BOOST_SYSTEM_NOEXCEPT // true if error - { - return m_val == 0 ? 0 : unspecified_bool_true; - } - - BOOST_SYSTEM_CONSTEXPR bool operator!() const BOOST_SYSTEM_NOEXCEPT // true if no error - { - return m_val == 0; - } - -#endif - - // relationals: - // the more symmetrical non-member syntax allows enum - // conversions work for both rhs and lhs. - BOOST_SYSTEM_CONSTEXPR inline friend bool operator==( const error_condition & lhs, - const error_condition & rhs ) BOOST_SYSTEM_NOEXCEPT - { - return lhs.m_cat == rhs.m_cat && lhs.m_val == rhs.m_val; - } - - inline friend bool operator<( const error_condition & lhs, - const error_condition & rhs ) BOOST_SYSTEM_NOEXCEPT - // the more symmetrical non-member syntax allows enum - // conversions work for both rhs and lhs. - { - return lhs.m_cat < rhs.m_cat - || (lhs.m_cat == rhs.m_cat && lhs.m_val < rhs.m_val); - } - -#ifndef BOOST_NO_CXX11_HDR_SYSTEM_ERROR - - operator std::error_condition () const BOOST_SYSTEM_NOEXCEPT - { - return std::error_condition( value(), category() ); - } - -#endif - - private: - int m_val; - const error_category * m_cat; - - }; - - // class error_code --------------------------------------------------------------// - - // We want error_code to be a value type that can be copied without slicing - // and without requiring heap allocation, but we also want it to have - // polymorphic behavior based on the error category. This is achieved by - // abstract base class error_category supplying the polymorphic behavior, - // and error_code containing a pointer to an object of a type derived - // from error_category. - class error_code + BOOST_SYSTEM_CONSTEXPR operator unspecified_bool_type() const BOOST_NOEXCEPT // true if error { - public: + return m_val == 0? 0 : unspecified_bool_true; + } - // constructors: - BOOST_SYSTEM_CONSTEXPR error_code() BOOST_SYSTEM_NOEXCEPT : m_val(0), m_cat(&system_category()) {} - BOOST_SYSTEM_CONSTEXPR error_code( int val, const error_category & cat ) BOOST_SYSTEM_NOEXCEPT - : m_val(val), m_cat(&cat) {} + BOOST_SYSTEM_CONSTEXPR bool operator!() const BOOST_NOEXCEPT // true if no error + { + return m_val == 0; + } - template - error_code(ErrorCodeEnum e, - typename boost::enable_if_::value>::type* = 0) - BOOST_SYSTEM_NOEXCEPT - { - *this = make_error_code(e); - } +#endif - // modifiers: - BOOST_SYSTEM_CONSTEXPR void assign( int val, const error_category & cat ) BOOST_SYSTEM_NOEXCEPT - { + // relationals: + // the more symmetrical non-member syntax allows enum + // conversions work for both rhs and lhs. + + BOOST_SYSTEM_CONSTEXPR inline friend bool operator==( const error_condition & lhs, const error_condition & rhs ) BOOST_NOEXCEPT + { + return lhs.m_val == rhs.m_val && *lhs.m_cat == *rhs.m_cat; + } + + BOOST_SYSTEM_CONSTEXPR inline friend bool operator<( const error_condition & lhs, const error_condition & rhs ) BOOST_NOEXCEPT + { + return *lhs.m_cat < *rhs.m_cat || ( *lhs.m_cat == *rhs.m_cat && lhs.m_val < rhs.m_val ); + } + +#if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR) + + operator std::error_condition () const BOOST_NOEXCEPT + { + return std::error_condition( value(), category() ); + } + +#endif +}; + +// class error_code + +// We want error_code to be a value type that can be copied without slicing +// and without requiring heap allocation, but we also want it to have +// polymorphic behavior based on the error category. This is achieved by +// abstract base class error_category supplying the polymorphic behavior, +// and error_code containing a pointer to an object of a type derived +// from error_category. + +class error_code +{ +private: + + int m_val; + const error_category * m_cat; + +public: + + // constructors: + + BOOST_SYSTEM_CONSTEXPR error_code() BOOST_NOEXCEPT: m_val( 0 ), m_cat( &system_category() ) + { + } + + BOOST_SYSTEM_CONSTEXPR error_code( int val, const error_category & cat ) BOOST_NOEXCEPT: m_val( val ), m_cat( &cat ) + { + } + + template BOOST_SYSTEM_CONSTEXPR error_code( ErrorCodeEnum e, + typename detail::enable_if::value>::type* = 0 ) BOOST_NOEXCEPT + { + *this = make_error_code( e ); + } + + // modifiers: + + BOOST_SYSTEM_CONSTEXPR void assign( int val, const error_category & cat ) BOOST_NOEXCEPT + { m_val = val; m_cat = &cat; - } + } - template - typename boost::enable_if_::value, error_code>::type & - operator=( ErrorCodeEnum val ) BOOST_SYSTEM_NOEXCEPT - { - *this = make_error_code(val); + template + BOOST_SYSTEM_CONSTEXPR typename detail::enable_if::value, error_code>::type & + operator=( ErrorCodeEnum val ) BOOST_NOEXCEPT + { + *this = make_error_code( val ); return *this; - } + } - BOOST_SYSTEM_CONSTEXPR void clear() BOOST_SYSTEM_NOEXCEPT - { + BOOST_SYSTEM_CONSTEXPR void clear() BOOST_NOEXCEPT + { m_val = 0; m_cat = &system_category(); - } + } - // observers: - BOOST_SYSTEM_CONSTEXPR int value() const BOOST_SYSTEM_NOEXCEPT { return m_val; } - BOOST_SYSTEM_CONSTEXPR const error_category & category() const BOOST_SYSTEM_NOEXCEPT { return *m_cat; } - error_condition default_error_condition() const BOOST_SYSTEM_NOEXCEPT - { return m_cat->default_error_condition(value()); } - std::string message() const { return m_cat->message(value()); } + // observers: + + BOOST_SYSTEM_CONSTEXPR int value() const BOOST_NOEXCEPT + { + return m_val; + } + + BOOST_SYSTEM_CONSTEXPR const error_category & category() const BOOST_NOEXCEPT + { + return *m_cat; + } + + error_condition default_error_condition() const BOOST_NOEXCEPT + { + return m_cat->default_error_condition( value() ); + } + + std::string message() const + { + return m_cat->message( value() ); + } #if !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) - BOOST_SYSTEM_CONSTEXPR explicit operator bool() const BOOST_SYSTEM_NOEXCEPT // true if error - { + BOOST_SYSTEM_CONSTEXPR explicit operator bool() const BOOST_NOEXCEPT // true if error + { return m_val != 0; - } + } #else - typedef void (*unspecified_bool_type)(); - static void unspecified_bool_true() {} + typedef void (*unspecified_bool_type)(); + static void unspecified_bool_true() {} - BOOST_SYSTEM_CONSTEXPR operator unspecified_bool_type() const BOOST_SYSTEM_NOEXCEPT // true if error - { - return m_val == 0 ? 0 : unspecified_bool_true; - } + BOOST_SYSTEM_CONSTEXPR operator unspecified_bool_type() const BOOST_NOEXCEPT // true if error + { + return m_val == 0? 0 : unspecified_bool_true; + } - BOOST_SYSTEM_CONSTEXPR bool operator!() const BOOST_SYSTEM_NOEXCEPT // true if no error - { + BOOST_SYSTEM_CONSTEXPR bool operator!() const BOOST_NOEXCEPT // true if no error + { return m_val == 0; - } + } #endif - // relationals: - BOOST_SYSTEM_CONSTEXPR inline friend bool operator==( const error_code & lhs, - const error_code & rhs ) BOOST_SYSTEM_NOEXCEPT - // the more symmetrical non-member syntax allows enum - // conversions work for both rhs and lhs. - { - return lhs.m_cat == rhs.m_cat && lhs.m_val == rhs.m_val; - } + // relationals: - inline friend bool operator<( const error_code & lhs, - const error_code & rhs ) BOOST_SYSTEM_NOEXCEPT - // the more symmetrical non-member syntax allows enum - // conversions work for both rhs and lhs. - { - return lhs.m_cat < rhs.m_cat - || (lhs.m_cat == rhs.m_cat && lhs.m_val < rhs.m_val); - } + // the more symmetrical non-member syntax allows enum + // conversions work for both rhs and lhs. -#ifndef BOOST_NO_CXX11_HDR_SYSTEM_ERROR + BOOST_SYSTEM_CONSTEXPR inline friend bool operator==( const error_code & lhs, const error_code & rhs ) BOOST_NOEXCEPT + { + return lhs.m_val == rhs.m_val && *lhs.m_cat == *rhs.m_cat; + } - operator std::error_code () const BOOST_SYSTEM_NOEXCEPT - { + BOOST_SYSTEM_CONSTEXPR inline friend bool operator<( const error_code & lhs, const error_code & rhs ) BOOST_NOEXCEPT + { + return *lhs.m_cat < *rhs.m_cat || ( *lhs.m_cat == *rhs.m_cat && lhs.m_val < rhs.m_val ); + } + +#if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR) + + operator std::error_code () const BOOST_NOEXCEPT + { return std::error_code( value(), category() ); - } + } #endif +}; - private: - int m_val; - const error_category * m_cat; +} // namespace system - }; +// boost::throws() - // predefined error_code object used as "throw on error" tag -# ifdef BOOST_SYSTEM_ENABLE_DEPRECATED - BOOST_SYSTEM_DECL extern error_code throws; -# endif +namespace detail +{ - // Moving from a "throws" object to a "throws" function without breaking - // existing code is a bit of a problem. The workaround is to place the - // "throws" function in namespace boost rather than namespace boost::system. +// Misuse of the error_code object is turned into a noisy failure by +// poisoning the reference. This particular implementation doesn't +// produce warnings or errors from popular compilers, is very efficient +// (as determined by inspecting generated code), and does not suffer +// from order of initialization problems. In practice, it also seems +// cause user function error handling implementation errors to be detected +// very early in the development cycle. - } // namespace system - - namespace detail - { - // Misuse of the error_code object is turned into a noisy failure by - // poisoning the reference. This particular implementation doesn't - // produce warnings or errors from popular compilers, is very efficient - // (as determined by inspecting generated code), and does not suffer - // from order of initialization problems. In practice, it also seems - // cause user function error handling implementation errors to be detected - // very early in the development cycle. - inline system::error_code* throws() - { - // See github.com/boostorg/system/pull/12 by visigoth for why the return - // is poisoned with nonzero rather than (0). A test, test_throws_usage(), - // has been added to error_code_test.cpp, and as visigoth mentioned it - // fails on clang for release builds with a return of 0 but works fine - // with (1). - // Since the undefined behavior sanitizer (-fsanitize=undefined) does not - // allow a reference to be formed to the unaligned address of (1), we use - // (8) instead. - return reinterpret_cast(8); - } - } +inline system::error_code* throws() +{ + // See github.com/boostorg/system/pull/12 by visigoth for why the return + // is poisoned with nonzero rather than (0). A test, test_throws_usage(), + // has been added to error_code_test.cpp, and as visigoth mentioned it + // fails on clang for release builds with a return of 0 but works fine + // with (1). + // Since the undefined behavior sanitizer (-fsanitize=undefined) does not + // allow a reference to be formed to the unaligned address of (1), we use + // (8) instead. - inline system::error_code& throws() - { return *detail::throws(); } + return reinterpret_cast(8); +} - namespace system - { - // non-member functions ------------------------------------------------// +} // namespace detail - BOOST_SYSTEM_CONSTEXPR inline bool operator!=( const error_code & lhs, - const error_code & rhs ) BOOST_SYSTEM_NOEXCEPT - { - return !(lhs == rhs); - } +inline system::error_code& throws() +{ + return *detail::throws(); +} - BOOST_SYSTEM_CONSTEXPR inline bool operator!=( const error_condition & lhs, - const error_condition & rhs ) BOOST_SYSTEM_NOEXCEPT - { - return !(lhs == rhs); - } +// non-member functions of error_code and error_condition - inline bool operator==( const error_code & code, - const error_condition & condition ) BOOST_SYSTEM_NOEXCEPT - { - return code.category().equivalent( code.value(), condition ) - || condition.category().equivalent( code, condition.value() ); - } +namespace system +{ - inline bool operator!=( const error_code & lhs, - const error_condition & rhs ) BOOST_SYSTEM_NOEXCEPT - { - return !(lhs == rhs); - } +BOOST_SYSTEM_CONSTEXPR inline bool operator!=( const error_code & lhs, const error_code & rhs ) BOOST_NOEXCEPT +{ + return !( lhs == rhs ); +} - inline bool operator==( const error_condition & condition, - const error_code & code ) BOOST_SYSTEM_NOEXCEPT - { - return condition.category().equivalent( code, condition.value() ) - || code.category().equivalent( code.value(), condition ); - } +BOOST_SYSTEM_CONSTEXPR inline bool operator!=( const error_condition & lhs, const error_condition & rhs ) BOOST_NOEXCEPT +{ + return !( lhs == rhs ); +} - inline bool operator!=( const error_condition & lhs, - const error_code & rhs ) BOOST_SYSTEM_NOEXCEPT - { - return !(lhs == rhs); - } +inline bool operator==( const error_code & code, const error_condition & condition ) BOOST_NOEXCEPT +{ + return code.category().equivalent( code.value(), condition ) || condition.category().equivalent( code, condition.value() ); +} - // TODO: both of these may move elsewhere, but the LWG hasn't spoken yet. +inline bool operator!=( const error_code & lhs, const error_condition & rhs ) BOOST_NOEXCEPT +{ + return !( lhs == rhs ); +} - template +inline bool operator==( const error_condition & condition, const error_code & code ) BOOST_NOEXCEPT +{ + return condition.category().equivalent( code, condition.value() ) || code.category().equivalent( code.value(), condition ); +} + +inline bool operator!=( const error_condition & lhs, const error_code & rhs ) BOOST_NOEXCEPT +{ + return !( lhs == rhs ); +} + +template inline std::basic_ostream& - operator<< (std::basic_ostream& os, error_code ec) + operator<< (std::basic_ostream& os, error_code ec) +{ + os << ec.category().name() << ':' << ec.value(); + return os; +} + +inline std::size_t hash_value( error_code const & ec ) +{ + error_category const & cat = ec.category(); + + boost::ulong_long_type id = cat.id_; + + if( id == 0 ) { - os << ec.category().name() << ':' << ec.value(); - return os; + id = reinterpret_cast( &cat ); } - inline std::size_t hash_value( const error_code & ec ) - { - return static_cast(ec.value()) - + reinterpret_cast(&ec.category()); - } + boost::ulong_long_type hv = 0xCBF29CE484222325ull; + boost::ulong_long_type const prime = 0x00000100000001B3ull; - // make_* functions for errc::errc_t ---------------------------------------------// + // id - namespace errc - { - // explicit conversion: - inline error_code make_error_code( errc_t e ) BOOST_SYSTEM_NOEXCEPT - { return error_code( e, generic_category() ); } + hv ^= id; + hv *= prime; - // implicit conversion: - inline error_condition make_error_condition( errc_t e ) BOOST_SYSTEM_NOEXCEPT - { return error_condition( e, generic_category() ); } - } + // value - // error_category default implementation -----------------------------------------// + hv ^= static_cast( ec.value() ); + hv *= prime; - error_condition error_category::default_error_condition( int ev ) const - BOOST_SYSTEM_NOEXCEPT - { - return error_condition( ev, *this ); - } + return static_cast( hv ); +} - bool error_category::equivalent( int code, - const error_condition & condition ) const BOOST_SYSTEM_NOEXCEPT - { - return default_error_condition( code ) == condition; - } +// make_* functions for errc::errc_t - bool error_category::equivalent( const error_code & code, - int condition ) const BOOST_SYSTEM_NOEXCEPT - { - return *this == code.category() && code.value() == condition; - } +namespace errc +{ -#ifndef BOOST_NO_CXX11_HDR_SYSTEM_ERROR +// explicit conversion: +BOOST_SYSTEM_CONSTEXPR inline error_code make_error_code( errc_t e ) BOOST_NOEXCEPT +{ + return error_code( e, generic_category() ); +} - inline std::error_condition error_category::std_category::default_error_condition( - int ev ) const BOOST_NOEXCEPT - { - return pc_->default_error_condition( ev ); - } +// implicit conversion: +BOOST_SYSTEM_CONSTEXPR inline error_condition make_error_condition( errc_t e ) BOOST_NOEXCEPT +{ + return error_condition( e, generic_category() ); +} - inline bool error_category::std_category::equivalent( int code, - const std::error_condition & condition ) const BOOST_NOEXCEPT - { - if( condition.category() == *this ) - { - boost::system::error_condition bn( condition.value(), *pc_ ); - return pc_->equivalent( code, bn ); - } - else if( condition.category() == std::generic_category() - || condition.category() == boost::system::generic_category() ) - { - boost::system::error_condition bn( condition.value(), - boost::system::generic_category() ); +} // namespace errc - return pc_->equivalent( code, bn ); - } -#ifndef BOOST_NO_RTTI - else if( std_category const* pc2 = dynamic_cast< std_category const* >( - &condition.category() ) ) - { - boost::system::error_condition bn( condition.value(), *pc2->pc_ ); - return pc_->equivalent( code, bn ); - } -#endif - else - { - return default_error_condition( code ) == condition; - } - } +// error_category default implementation - inline bool error_category::std_category::equivalent( const std::error_code & code, - int condition ) const BOOST_NOEXCEPT - { - if( code.category() == *this ) - { - boost::system::error_code bc( code.value(), *pc_ ); - return pc_->equivalent( bc, condition ); - } - else if( code.category() == std::generic_category() - || code.category() == boost::system::generic_category() ) - { - boost::system::error_code bc( code.value(), - boost::system::generic_category() ); +inline error_condition error_category::default_error_condition( int ev ) const BOOST_NOEXCEPT +{ + return error_condition( ev, *this ); +} - return pc_->equivalent( bc, condition ); - } -#ifndef BOOST_NO_RTTI - else if( std_category const* pc2 = dynamic_cast< std_category const* >( - &code.category() ) ) - { - boost::system::error_code bc( code.value(), *pc2->pc_ ); - return pc_->equivalent( bc, condition ); - } -#endif - else if( *pc_ == boost::system::generic_category() ) - { - return std::generic_category().equivalent( code, condition ); - } - else - { - return false; - } - } +inline bool error_category::equivalent( int code, const error_condition & condition ) const BOOST_NOEXCEPT +{ + return default_error_condition( code ) == condition; +} -#endif +inline bool error_category::equivalent( const error_code & code, int condition ) const BOOST_NOEXCEPT +{ + return *this == code.category() && code.value() == condition; +} + +} // namespace system - } // namespace system } // namespace boost -#include // pops abi_prefix.hpp pragmas +// generic_error_category implementation -# ifdef BOOST_ERROR_CODE_HEADER_ONLY -# include -# endif +#include -#endif // BOOST_SYSTEM_ERROR_CODE_HPP +inline std::string boost::system::detail::generic_error_category::message( int ev ) const +{ + return generic_error_category_message( ev ); +} + +// system_error_category implementation + +#if defined(BOOST_WINDOWS_API) + +#include + +inline std::string boost::system::detail::system_error_category::message( int ev ) const +{ + return system_category_message_win32( ev ); +} + +inline boost::system::error_condition boost::system::detail::system_error_category::default_error_condition( int ev ) const BOOST_NOEXCEPT +{ + return system_category_default_error_condition_win32( ev ); +} + +#else // #if defined(BOOST_WINDOWS_API) + +#include + +inline std::string boost::system::detail::system_error_category::message( int ev ) const +{ + return generic_error_category_message( ev ); +} + +inline boost::system::error_condition boost::system::detail::system_error_category::default_error_condition( int ev ) const BOOST_NOEXCEPT +{ + return system_category_default_error_condition_posix( ev ); +} + +#endif // #if defined(BOOST_WINDOWS_API) + +// interoperability with std::error_code, std::error_condition + +#if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR) + +#include + +inline boost::system::error_category::operator std::error_category const & () const +{ + return boost::system::detail::to_std_category( *this ); +} + +#endif // #if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR) + +#endif // BOOST_SYSTEM_ERROR_CODE_HPP_INCLUDED diff --git a/src/error_code.cpp b/src/error_code.cpp index aa628ab..b86a38c 100644 --- a/src/error_code.cpp +++ b/src/error_code.cpp @@ -1,6 +1,7 @@ -// error_code support implementation file ----------------------------------// +// error_code stub implementation, for compatibility only // Copyright Beman Dawes 2002, 2006 +// Copyright Peter Dimov 2018 // 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) @@ -13,8 +14,18 @@ // the library is being built (possibly exporting rather than importing code) #define BOOST_SYSTEM_SOURCE -#include +#include -#ifndef BOOST_ERROR_CODE_HEADER_ONLY -#include -#endif +namespace boost +{ + +namespace system +{ + +BOOST_SYSTEM_DECL void dummy_exported_function() +{ +} + +} // namespace system + +} // namespace boost diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 037b004..9e5beb7 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -123,6 +123,7 @@ else [ system-run before_main_test.cpp ] [ run-fail throws_assign_fail.cpp ] [ system-run- constexpr_test.cpp ] + [ system-run win32_hresult_test.cpp ] ; # Quick (CI) test diff --git a/test/error_code_test.cpp b/test/error_code_test.cpp index 7965541..82f0fb1 100644 --- a/test/error_code_test.cpp +++ b/test/error_code_test.cpp @@ -123,17 +123,7 @@ int main( int, char ** ) BOOST_TEST( generic_category() != system_category() ); BOOST_TEST( system_category() != generic_category() ); - if ( std::less()( &generic_category(), &system_category() ) ) - { - BOOST_TEST( generic_category() < system_category() ); - BOOST_TEST( !(system_category() < generic_category()) ); - } - else - { - BOOST_TEST( system_category() < generic_category() ); - BOOST_TEST( !(generic_category() < system_category()) ); - } - + BOOST_TEST_NE( generic_category() < system_category(), system_category() < generic_category() ); error_code ec; error_condition econd; diff --git a/test/single_instance_test.cpp b/test/single_instance_test.cpp index d5b67cf..65de5a9 100644 --- a/test/single_instance_test.cpp +++ b/test/single_instance_test.cpp @@ -25,8 +25,23 @@ error_code get_generic_code(); int main() { - BOOST_TEST_EQ( lib1::get_system_code(), lib2::get_system_code() ); - BOOST_TEST_EQ( lib1::get_generic_code(), lib2::get_generic_code() ); + { + error_code e1 = lib1::get_system_code(); + error_code e2 = lib2::get_system_code(); + + BOOST_TEST_EQ( e1, e2 ); + + BOOST_TEST_EQ( hash_value( e1 ), hash_value( e2 ) ); + } + + { + error_code e1 = lib1::get_generic_code(); + error_code e2 = lib2::get_generic_code(); + + BOOST_TEST_EQ( e1, e2 ); + + BOOST_TEST_EQ( hash_value( e1 ), hash_value( e2 ) ); + } return boost::report_errors(); } diff --git a/test/std_interop_test.cpp b/test/std_interop_test.cpp index 5e52c50..94845d1 100644 --- a/test/std_interop_test.cpp +++ b/test/std_interop_test.cpp @@ -11,10 +11,14 @@ // Avoid spurious VC++ warnings # define _CRT_SECURE_NO_WARNINGS +#include #include +#include #include -#if defined(BOOST_NO_CXX11_HDR_SYSTEM_ERROR) +#if !defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR) + +BOOST_PRAGMA_MESSAGE( "BOOST_SYSTEM_HAS_SYSTEM_ERROR not defined, test will be skipped" ) int main() { @@ -25,7 +29,6 @@ int main() #else -#include #include #include #include diff --git a/test/std_mismatch_test.cpp b/test/std_mismatch_test.cpp index 9c97cdd..3a34bb2 100644 --- a/test/std_mismatch_test.cpp +++ b/test/std_mismatch_test.cpp @@ -11,10 +11,14 @@ // Avoid spurious VC++ warnings # define _CRT_SECURE_NO_WARNINGS +#include #include +#include #include -#if defined(BOOST_NO_CXX11_HDR_SYSTEM_ERROR) +#if !defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR) + +BOOST_PRAGMA_MESSAGE( "BOOST_SYSTEM_HAS_SYSTEM_ERROR not defined, test will be skipped" ) int main() { @@ -25,7 +29,6 @@ int main() #else -#include #include #include #include diff --git a/test/win32_hresult_test.cpp b/test/win32_hresult_test.cpp new file mode 100644 index 0000000..b79c51d --- /dev/null +++ b/test/win32_hresult_test.cpp @@ -0,0 +1,41 @@ + +// Copyright 2018 Peter Dimov. +// +// 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 + +// See library home page at http://www.boost.org/libs/system + +#include +#include + +#if !defined(BOOST_WINDOWS_API) + +BOOST_PRAGMA_MESSAGE( "Skipping test, BOOST_WINDOWS_API is not defined" ) +int main() {} + +#else + +#include +#include + +int main() +{ + namespace sys = boost::system; + + HRESULT r = HRESULT_FROM_WIN32( ERROR_ACCESS_DENIED ); + + sys::error_code ec( r, sys::system_category() ); + sys::error_condition en = make_error_condition( sys::errc::permission_denied ); + + BOOST_TEST( ec == en ); + BOOST_TEST( ec.default_error_condition() == en ); + + BOOST_TEST_EQ( ec.default_error_condition().value(), en.value() ); + + return boost::report_errors(); +} + +#endif