Compare commits

...

7 Commits

8 changed files with 227 additions and 13 deletions

View File

@@ -143,7 +143,7 @@ inline void error_category::init_stdcat() const
if( sc_init_.load( std::memory_order_acquire ) == 0 )
{
::new( static_cast<void*>( stdcat_ ) ) boost::system::detail::std_category( this, 0 );
::new( static_cast<void*>( stdcat_ ) ) boost::system::detail::std_category( this, system::detail::id_wrapper<0>() );
sc_init_.store( 1, std::memory_order_release );
}
}
@@ -160,7 +160,7 @@ inline BOOST_NOINLINE error_category::operator std::error_category const & () co
// This condition must be the same as the one in error_condition.hpp
#if defined(BOOST_SYSTEM_AVOID_STD_GENERIC_CATEGORY)
static const boost::system::detail::std_category generic_instance( this, 0x1F4D3 );
static const boost::system::detail::std_category generic_instance( this, system::detail::id_wrapper<0x1F4D3>() );
return generic_instance;
#else
@@ -175,7 +175,7 @@ inline BOOST_NOINLINE error_category::operator std::error_category const & () co
// This condition must be the same as the one in error_code.hpp
#if defined(BOOST_SYSTEM_AVOID_STD_SYSTEM_CATEGORY)
static const boost::system::detail::std_category system_instance( this, 0x1F4D7 );
static const boost::system::detail::std_category system_instance( this, system::detail::id_wrapper<0x1F4D7>() );
return system_instance;
#else

View File

@@ -403,7 +403,12 @@ public:
{
#if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)
if( lhs.lc_flags_ == 1 && rhs.lc_flags_ == 1 )
bool s1 = lhs.lc_flags_ == 1;
bool s2 = rhs.lc_flags_ == 1;
if( s1 != s2 ) return false;
if( s1 && s2 )
{
std::error_code const& e1 = *reinterpret_cast<std::error_code const*>( lhs.d2_ );
std::error_code const& e2 = *reinterpret_cast<std::error_code const*>( rhs.d2_ );
@@ -421,7 +426,13 @@ public:
{
#if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)
if( lhs.lc_flags_ == 1 && rhs.lc_flags_ == 1 )
bool s1 = lhs.lc_flags_ == 1;
bool s2 = rhs.lc_flags_ == 1;
if( s1 < s2 ) return true;
if( s2 < s1 ) return false;
if( s1 && s2 )
{
std::error_code const& e1 = *reinterpret_cast<std::error_code const*>( lhs.d2_ );
std::error_code const& e2 = *reinterpret_cast<std::error_code const*>( rhs.d2_ );

View File

@@ -11,6 +11,7 @@
// See library home page at http://www.boost.org/libs/system
#include <boost/system/detail/error_category.hpp>
#include <boost/config.hpp>
#include <system_error>
//
@@ -24,6 +25,8 @@ namespace system
namespace detail
{
template<unsigned Id> struct id_wrapper {};
class BOOST_SYMBOL_VISIBLE std_category: public std::error_category
{
private:
@@ -39,20 +42,22 @@ public:
public:
explicit std_category( boost::system::error_category const * pc, unsigned id ): pc_( pc )
template<unsigned Id>
explicit std_category( boost::system::error_category const * pc, id_wrapper<Id> ): pc_( pc )
{
if( id != 0 )
{
#if defined(_MSC_VER) && defined(_CPPLIB_VER) && _MSC_VER >= 1900 && _MSC_VER < 2000
// Poking into the protected _Addr member of std::error_category
// is not a particularly good programming practice, but what can
// you do
// We used to assign to the protected _Addr member of std::error_category
// here when Id != 0, but this should never happen now because this code
// path is no longer used
_Addr = id;
#if !defined(BOOST_NO_CXX11_STATIC_ASSERT)
static_assert( Id == 0, "This constructor should only be called with Id == 0 under MS STL 14.0+" );
#endif
#endif
}
}
const char * name() const BOOST_NOEXCEPT BOOST_OVERRIDE

View File

@@ -59,6 +59,7 @@ inline int system_category_condition_win32( int ev ) BOOST_NOEXCEPT
case ERROR_ACCESS_DENIED_: return permission_denied;
case ERROR_ALREADY_EXISTS_: return file_exists;
case ERROR_BAD_NETPATH_: return no_such_file_or_directory;
case ERROR_BAD_NET_NAME_: return no_such_file_or_directory;
case ERROR_BAD_UNIT_: return no_such_device;
case ERROR_BROKEN_PIPE_: return broken_pipe;
case ERROR_BUFFER_OVERFLOW_: return filename_too_long;
@@ -75,6 +76,7 @@ inline int system_category_condition_win32( int ev ) BOOST_NOEXCEPT
case ERROR_DIR_NOT_EMPTY_: return directory_not_empty;
case ERROR_DIRECTORY_: return invalid_argument; // WinError.h: "The directory name is invalid"
case ERROR_DISK_FULL_: return no_space_on_device;
case ERROR_FILENAME_EXCED_RANGE_: return filename_too_long;
case ERROR_FILE_EXISTS_: return file_exists;
case ERROR_FILE_NOT_FOUND_: return no_such_file_or_directory;
case ERROR_HANDLE_DISK_FULL_: return no_space_on_device;
@@ -100,12 +102,16 @@ inline int system_category_condition_win32( int ev ) BOOST_NOEXCEPT
case ERROR_REPARSE_TAG_INVALID_: return invalid_argument;
case ERROR_RETRY_: return resource_unavailable_try_again;
case ERROR_SEEK_: return io_error;
case ERROR_SEM_TIMEOUT_: return timed_out;
case ERROR_SHARING_VIOLATION_: return permission_denied;
case ERROR_NOT_SUPPORTED_: return not_supported; // WinError.h: "The request is not supported."
case ERROR_TIMEOUT_: return timed_out;
case ERROR_TOO_MANY_OPEN_FILES_: return too_many_files_open;
case ERROR_WRITE_FAULT_: return io_error;
case ERROR_WRITE_PROTECT_: return permission_denied;
case 258: return timed_out; // WAIT_TIMEOUT
case WSAEACCES_: return permission_denied;
case WSAEADDRINUSE_: return address_in_use;
case WSAEADDRNOTAVAIL_: return address_not_available;

View File

@@ -130,6 +130,10 @@ boost_test(TYPE compile SOURCES constexpr_test2.cpp)
boost_test(TYPE run SOURCES error_code_test3.cpp)
boost_test(TYPE run SOURCES std_interop_test15.cpp)
boost_test(TYPE run SOURCES win32_generic_test.cpp)
boost_test(TYPE run SOURCES ec_hash_value_test.cpp)
# result
set(BOOST_TEST_COMPILE_FEATURES cxx_std_11)

View File

@@ -158,6 +158,10 @@ compile constexpr_test2.cpp ;
run error_code_test3.cpp ;
run std_interop_test15.cpp ;
run win32_generic_test.cpp ;
run ec_hash_value_test.cpp ;
# result
import ../../config/checks/config : requires ;

132
test/ec_hash_value_test.cpp Normal file
View File

@@ -0,0 +1,132 @@
// Copyright 2022 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0.
// http://www.boost.org/LICENSE_1_0.txt
#include <boost/system/error_code.hpp>
#include <boost/system/generic_category.hpp>
#include <boost/system/system_category.hpp>
#include <boost/core/lightweight_test.hpp>
#include <cerrno>
#if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)
#include <system_error>
#endif
namespace sys = boost::system;
int main()
{
// normal against normal (equal, system)
{
sys::error_code e2( 0, sys::system_category() );
sys::error_code e3( e2.value(), e2.category() );
BOOST_TEST( e2 != e3 || hash_value( e2 ) == hash_value( e3 ) );
BOOST_TEST( e2 == e3 || hash_value( e2 ) != hash_value( e3 ) );
}
// normal against normal (equal, generic)
{
sys::error_code e2( EINVAL, sys::generic_category() );
sys::error_code e3( e2.value(), e2.category() );
BOOST_TEST( e2 != e3 || hash_value( e2 ) == hash_value( e3 ) );
BOOST_TEST( e2 == e3 || hash_value( e2 ) != hash_value( e3 ) );
}
// normal against normal (inequal, value, generic)
{
sys::error_code e2( 0, sys::generic_category() );
sys::error_code e3( EINVAL, sys::generic_category() );
BOOST_TEST( e2 != e3 || hash_value( e2 ) == hash_value( e3 ) );
BOOST_TEST( e2 == e3 || hash_value( e2 ) != hash_value( e3 ) );
}
// normal against normal (inequal, value, system)
{
sys::error_code e2( 1, sys::system_category() );
sys::error_code e3( 2, sys::system_category() );
BOOST_TEST( e2 != e3 || hash_value( e2 ) == hash_value( e3 ) );
BOOST_TEST( e2 == e3 || hash_value( e2 ) != hash_value( e3 ) );
}
// normal against normal (inequal, category)
{
sys::error_code e2( 0, sys::system_category() );
sys::error_code e3( 0, sys::generic_category() );
BOOST_TEST( e2 != e3 || hash_value( e2 ) == hash_value( e3 ) );
BOOST_TEST( e2 == e3 || hash_value( e2 ) != hash_value( e3 ) );
}
// empty against normal
{
sys::error_code e2;
sys::error_code e3( e2.value(), e2.category() );
BOOST_TEST( e2 != e3 || hash_value( e2 ) == hash_value( e3 ) );
BOOST_TEST( e2 == e3 || hash_value( e2 ) != hash_value( e3 ) );
}
#if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)
// std:: wrapping against normal
{
std::error_code e1( EINVAL, std::generic_category() );
sys::error_code e2( e1 );
sys::error_code e3( e2.value(), e2.category() );
BOOST_TEST( e2 != e3 || hash_value( e2 ) == hash_value( e3 ) );
BOOST_TEST( e2 == e3 || hash_value( e2 ) != hash_value( e3 ) );
}
// empty against wrapping std:: empty
{
std::error_code e1;
sys::error_code e2( e1 );
sys::error_code e3;
BOOST_TEST( e2 != e3 || hash_value( e2 ) == hash_value( e3 ) );
BOOST_TEST( e2 == e3 || hash_value( e2 ) != hash_value( e3 ) );
}
// empty against roundtrip via std
{
sys::error_code e2;
std::error_code e1( e2 );
sys::error_code e3( e1 );
BOOST_TEST( e2 != e3 || hash_value( e2 ) == hash_value( e3 ) );
BOOST_TEST( e2 == e3 || hash_value( e2 ) != hash_value( e3 ) );
}
// normal/generic against roundtrip via std
{
sys::error_code e2( EINVAL, boost::system::generic_category() );
std::error_code e1( e2 );
sys::error_code e3( e1 );
BOOST_TEST( e2 != e3 || hash_value( e2 ) == hash_value( e3 ) );
BOOST_TEST( e2 == e3 || hash_value( e2 ) != hash_value( e3 ) );
}
// normal/system against roundtrip via std
{
sys::error_code e2( 0, boost::system::system_category() );
std::error_code e1( e2 );
sys::error_code e3( e1 );
BOOST_TEST( e2 != e3 || hash_value( e2 ) == hash_value( e3 ) );
BOOST_TEST( e2 == e3 || hash_value( e2 ) != hash_value( e3 ) );
}
#endif
return boost::report_errors();
}

View File

@@ -0,0 +1,52 @@
// Copyright 2022 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/system.hpp>
#include <boost/config.hpp>
#include <boost/config/pragma_message.hpp>
#if !defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)
BOOST_PRAGMA_MESSAGE( "Skipping test, BOOST_SYSTEM_HAS_SYSTEM_ERROR is not defined" )
int main() {}
#elif !defined(BOOST_MSSTL_VERSION) || BOOST_MSSTL_VERSION < 140
BOOST_PRAGMA_MESSAGE( "Skipping test, BOOST_MSSTL_VERSION is not defined or is less than 140" )
int main() {}
#else
#include <system_error>
#include <iostream>
int main()
{
namespace sys = boost::system;
int n = 0;
for( int i = 0; i < 65000; ++i )
{
sys::error_code ec1( i, sys::system_category() );
sys::error_condition en1 = ec1.default_error_condition();
std::error_code ec2( i, std::system_category() );
std::error_condition en2 = ec2.default_error_condition();
if( en1 != en2 )
{
std::cout << i << ": " << en1 << " (" << en1.message() << ") != cond:" << en2.category().name() << ":" << en2.value() << " (" << en2.message() << ")\n";
if( en2.category() == std::generic_category() && i != 123 ) // msvc-14.0, msvc-14.1 disagree with us on ERROR_INVALID_NAME
{
++n;
}
}
}
return n < 256 ? n: 255;
}
#endif