From 4a364b1532c8745ed791edcd9041b1761655b3b1 Mon Sep 17 00:00:00 2001 From: Christopher Kohlhoff Date: Mon, 24 Sep 2007 12:53:37 +0000 Subject: [PATCH] Use a switch rather than an array to translate system_category error codes to their corresponding default error conditions. Add translations for the Winsock error codes. [SVN r39502] --- src/error_code.cpp | 336 +++++++++++++++++++-------------------- test/error_code_test.cpp | 37 +++-- 2 files changed, 189 insertions(+), 184 deletions(-) diff --git a/src/error_code.cpp b/src/error_code.cpp index ef3efee..a6d5bc3 100644 --- a/src/error_code.cpp +++ b/src/error_code.cpp @@ -45,157 +45,6 @@ using namespace boost::system::posix; namespace { - - struct system_to_posix_t - { - int system_value; - boost::system::posix::posix_errno posix_value; - }; - - const system_to_posix_t system_to_posix[] = - { - -#ifdef BOOST_POSIX_API - // POSIX-like O/S -> posix_errno decode table ----------------------------// - - // most common errors first to speed sequential search - { ENOENT, no_such_file_or_directory }, - { EACCES, permission_denied }, - { EINVAL, invalid_argument }, - - // rest are alphabetical for easy maintenance - { 0, success }, - { E2BIG, argument_list_too_long }, - { EADDRINUSE, address_in_use }, - { EADDRNOTAVAIL, address_not_available }, - { EAFNOSUPPORT, address_family_not_supported }, - { EAGAIN, resource_unavailable_try_again }, - { EALREADY, connection_already_in_progress }, - { EBADF, bad_file_descriptor }, - { EBADMSG, bad_message }, - { EBUSY, device_or_resource_busy }, - { ECANCELED, operation_canceled }, - { ECHILD, no_child_process }, - { ECONNABORTED, connection_aborted }, - { ECONNREFUSED, connection_refused }, - { ECONNRESET, connection_reset }, - { EDEADLK, resource_deadlock_would_occur }, - { EDESTADDRREQ, destination_address_required }, - { EDOM, argument_out_of_domain }, - { EEXIST, file_exists }, - { EFAULT, bad_address }, - { EFBIG, file_too_large }, - { EHOSTUNREACH, host_unreachable }, - { EIDRM, identifier_removed }, - { EILSEQ, illegal_byte_sequence }, - { EINPROGRESS, operation_in_progress }, - { EINTR, interrupted }, - { EIO, io_error }, - { EISCONN, already_connected }, - { EISDIR, is_a_directory }, - { ELOOP, too_many_synbolic_link_levels }, - { EMFILE, too_many_files_open }, - { EMLINK, too_many_links }, - { EMSGSIZE, message_size }, - { ENAMETOOLONG, filename_too_long }, - { ENETDOWN, network_down }, - { ENETRESET, network_reset }, - { ENETUNREACH, network_unreachable }, - { ENFILE, too_many_files_open_in_system }, - { ENOBUFS, no_buffer_space }, - { ENODATA, no_message_available }, - { ENODEV, no_such_device }, - { ENOEXEC, executable_format_error }, - { ENOLCK, no_lock_available }, - { ENOLINK, no_link }, - { ENOMEM, not_enough_memory }, - { ENOMSG, no_message }, - { ENOPROTOOPT, no_protocol_option }, - { ENOSPC, no_space_on_device }, - { ENOSR, no_stream_resources }, - { ENOSTR, not_a_stream }, - { ENOSYS, function_not_supported }, - { ENOTCONN, not_connected }, - { ENOTDIR, not_a_directory }, - { ENOTEMPTY, directory_not_empty }, - { ENOTRECOVERABLE, state_not_recoverable }, - { ENOTSOCK, not_a_socket }, - { ENOTSUP, not_supported }, - { ENOTTY, inappropriate_io_control_operation }, - { ENXIO, no_such_device_or_address }, - { EOPNOTSUPP, operation_not_supported }, - { EOVERFLOW, value_too_large }, - { EOWNERDEAD, owner_dead }, - { EPERM, operation_not_permitted }, - { EPIPE, broken_pipe }, - { EPROTO, protocol_error }, - { EPROTONOSUPPORT, protocol_not_supported }, - { EPROTOTYPE, wrong_protocol_type }, - { ERANGE, result_out_of_range }, - { EROFS, read_only_file_system }, - { ESPIPE, invalid_seek }, - { ESRCH, no_such_process }, - { ETIME, stream_timeout }, - { ETIMEDOUT, timed_out }, - { ETXTBSY, text_file_busy }, - { EWOULDBLOCK, operation_would_block }, - { EXDEV, cross_device_link } - -#else - - // Windows system -> posix_errno decode table ----------------------------// - - // see WinError.h comments for descriptions of errors - - // most common errors first to speed sequential search - { ERROR_FILE_NOT_FOUND, no_such_file_or_directory }, - { ERROR_PATH_NOT_FOUND, no_such_file_or_directory }, - - // rest are alphabetical for easy maintenance - { 0, success }, - { ERROR_ACCESS_DENIED, permission_denied }, - { ERROR_ALREADY_EXISTS, file_exists }, - { ERROR_BAD_UNIT, no_such_device }, - { ERROR_BUFFER_OVERFLOW, filename_too_long }, - { ERROR_BUSY, device_or_resource_busy }, - { ERROR_BUSY_DRIVE, device_or_resource_busy }, - { ERROR_CANNOT_MAKE, permission_denied }, - { ERROR_CANTOPEN, io_error }, - { ERROR_CANTREAD, io_error }, - { ERROR_CANTWRITE, io_error }, - { ERROR_CURRENT_DIRECTORY, permission_denied }, - { ERROR_DEV_NOT_EXIST, no_such_device }, - { ERROR_DEVICE_IN_USE, device_or_resource_busy }, - { ERROR_DIR_NOT_EMPTY, directory_not_empty }, - { ERROR_DIRECTORY, invalid_argument }, // WinError.h: "The directory name is invalid" - { ERROR_DISK_FULL, no_space_on_device }, - { ERROR_FILE_EXISTS, file_exists }, - { ERROR_HANDLE_DISK_FULL, no_space_on_device }, - { ERROR_INVALID_ACCESS, permission_denied }, - { ERROR_INVALID_DRIVE, no_such_device }, - { ERROR_INVALID_FUNCTION, function_not_supported }, - { ERROR_INVALID_HANDLE, invalid_argument }, - { ERROR_INVALID_NAME, invalid_argument }, - { ERROR_LOCK_VIOLATION, no_lock_available }, - { ERROR_LOCKED, no_lock_available }, - { ERROR_NEGATIVE_SEEK, invalid_argument }, - { ERROR_NOACCESS, permission_denied }, - { ERROR_NOT_ENOUGH_MEMORY, not_enough_memory }, - { ERROR_NOT_READY, resource_unavailable_try_again }, - { ERROR_NOT_SAME_DEVICE, cross_device_link }, - { ERROR_OPEN_FAILED, io_error }, - { ERROR_OPEN_FILES, device_or_resource_busy }, - { ERROR_OUTOFMEMORY, not_enough_memory }, - { ERROR_READ_FAULT, io_error }, - { ERROR_SEEK, io_error }, - { ERROR_SHARING_VIOLATION, permission_denied }, - { ERROR_TOO_MANY_OPEN_FILES, too_many_files_open }, - { ERROR_WRITE_FAULT, io_error }, - { ERROR_WRITE_PROTECT, permission_denied } - -#endif - }; - // standard error categories -------------------------------------------// class posix_error_category : public error_category @@ -209,7 +58,6 @@ namespace { public: const char * name() const; - posix::posix_errno posix( int ev ) const; std::string message( int ev ) const; error_condition default_error_condition( int ev ) const; }; @@ -298,25 +146,175 @@ namespace return "system"; } - posix_errno system_error_category::posix( int ev ) const - { - const system_to_posix_t * cur = system_to_posix; - do - { - if ( ev == cur->system_value ) - return cur->posix_value; - ++cur; - } while ( cur != system_to_posix - + sizeof(system_to_posix)/sizeof(system_to_posix_t) ); - return static_cast(-1); - } - error_condition system_error_category::default_error_condition( int ev ) const { - int tmp = posix(ev); - return tmp >= 0 - ? error_condition( tmp, posix_category ) - : error_condition( ev, system_category ); + 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 ); + case EALREADY: return make_error_condition( connection_already_in_progress ); + 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_synbolic_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 ); + case ENOTEMPTY: return make_error_condition( directory_not_empty ); + case ENOTRECOVERABLE: return make_error_condition( state_not_recoverable ); + 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 ); + case EOWNERDEAD: return make_error_condition( owner_dead ); + 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 ) diff --git a/test/error_code_test.cpp b/test/error_code_test.cpp index 0206ea1..12eb1f2 100644 --- a/test/error_code_test.cpp +++ b/test/error_code_test.cpp @@ -148,33 +148,40 @@ int test_main( int, char ** ) std::cout << "Windows tests...\n"; // these tests probe the Windows posix decoder // test the first entry in the decoder table: - ec = error_code( ERROR_FILE_NOT_FOUND, system_category ); - BOOST_CHECK( ec.value() == ERROR_FILE_NOT_FOUND ); - BOOST_CHECK( ec == posix::no_such_file_or_directory ); - BOOST_CHECK( ec.default_error_condition().value() == posix::no_such_file_or_directory ); - BOOST_CHECK( ec.default_error_condition().category() == posix_category ); - - // test the second entry in the decoder table: - ec = error_code( ERROR_PATH_NOT_FOUND, system_category ); - BOOST_CHECK( ec.value() == ERROR_PATH_NOT_FOUND ); - BOOST_CHECK( ec == posix::no_such_file_or_directory ); - BOOST_CHECK( ec.default_error_condition().value() == posix::no_such_file_or_directory ); - BOOST_CHECK( ec.default_error_condition().category() == posix_category ); - - // test the third entry in the decoder table: ec = error_code( ERROR_ACCESS_DENIED, system_category ); BOOST_CHECK( ec.value() == ERROR_ACCESS_DENIED ); BOOST_CHECK( ec == posix::permission_denied ); BOOST_CHECK( ec.default_error_condition().value() == posix::permission_denied ); BOOST_CHECK( ec.default_error_condition().category() == posix_category ); - // test the last regular entry in the decoder table: + // test the second entry in the decoder table: + ec = error_code( ERROR_ALREADY_EXISTS, system_category ); + BOOST_CHECK( ec.value() == ERROR_ALREADY_EXISTS ); + BOOST_CHECK( ec == posix::file_exists ); + BOOST_CHECK( ec.default_error_condition().value() == posix::file_exists ); + BOOST_CHECK( ec.default_error_condition().category() == posix_category ); + + // test the third entry in the decoder table: + ec = error_code( ERROR_BAD_UNIT, system_category ); + BOOST_CHECK( ec.value() == ERROR_BAD_UNIT ); + BOOST_CHECK( ec == posix::no_such_device ); + BOOST_CHECK( ec.default_error_condition().value() == posix::no_such_device ); + BOOST_CHECK( ec.default_error_condition().category() == posix_category ); + + // test the last non-Winsock entry in the decoder table: ec = error_code( ERROR_WRITE_PROTECT, system_category ); BOOST_CHECK( ec.value() == ERROR_WRITE_PROTECT ); BOOST_CHECK( ec == posix::permission_denied ); BOOST_CHECK( ec.default_error_condition().value() == posix::permission_denied ); BOOST_CHECK( ec.default_error_condition().category() == posix_category ); + // test the last Winsock entry in the decoder table: + ec = error_code( WSAEWOULDBLOCK, system_category ); + BOOST_CHECK( ec.value() == WSAEWOULDBLOCK ); + BOOST_CHECK( ec == posix::operation_would_block ); + BOOST_CHECK( ec.default_error_condition().value() == posix::operation_would_block ); + BOOST_CHECK( ec.default_error_condition().category() == posix_category ); + // test not-in-table condition: ec = error_code( 1234567890, system_category ); BOOST_CHECK( ec.value() == 1234567890 );