Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-13 08:42:38

0001 /* Proposed SG14 status_code
0002 (C) 2018 - 2024 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
0003 File Created: Feb 2018
0004 
0005 
0006 Licensed under the Apache License, Version 2.0 (the "License");
0007 you may not use this file except in compliance with the License.
0008 You may obtain a copy of the License in the accompanying file
0009 Licence.txt or at
0010 
0011 http://www.apache.org/licenses/LICENSE-2.0
0012 
0013 Unless required by applicable law or agreed to in writing, software
0014 distributed under the License is distributed on an "AS IS" BASIS,
0015 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0016 See the License for the specific language governing permissions and
0017 limitations under the License.
0018 
0019 
0020 Distributed under the Boost Software License, Version 1.0.
0021 (See accompanying file Licence.txt or copy at
0022 http://www.boost.org/LICENSE_1_0.txt)
0023 */
0024 
0025 #ifndef BOOST_OUTCOME_SYSTEM_ERROR2_GENERIC_CODE_HPP
0026 #define BOOST_OUTCOME_SYSTEM_ERROR2_GENERIC_CODE_HPP
0027 
0028 #include "status_error.hpp"
0029 
0030 #include <cerrno>  // for error constants
0031 
0032 #if defined(_MSC_VER) && !defined(__clang__)
0033 #pragma warning(push)
0034 #pragma warning(disable : 6326)  // constant comparison
0035 #endif
0036 
0037 BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_BEGIN
0038 
0039 //! The generic error coding (POSIX)
0040 enum class errc : int
0041 {
0042   success = 0,
0043   unknown = -1,
0044 
0045   address_family_not_supported = EAFNOSUPPORT,
0046   address_in_use = EADDRINUSE,
0047   address_not_available = EADDRNOTAVAIL,
0048   already_connected = EISCONN,
0049   argument_list_too_long = E2BIG,
0050   argument_out_of_domain = EDOM,
0051   bad_address = EFAULT,
0052   bad_file_descriptor = EBADF,
0053   bad_message = EBADMSG,
0054   broken_pipe = EPIPE,
0055   connection_aborted = ECONNABORTED,
0056   connection_already_in_progress = EALREADY,
0057   connection_refused = ECONNREFUSED,
0058   connection_reset = ECONNRESET,
0059   cross_device_link = EXDEV,
0060   destination_address_required = EDESTADDRREQ,
0061   device_or_resource_busy = EBUSY,
0062   directory_not_empty = ENOTEMPTY,
0063   executable_format_error = ENOEXEC,
0064   file_exists = EEXIST,
0065   file_too_large = EFBIG,
0066   filename_too_long = ENAMETOOLONG,
0067   function_not_supported = ENOSYS,
0068   host_unreachable = EHOSTUNREACH,
0069   identifier_removed = EIDRM,
0070   illegal_byte_sequence = EILSEQ,
0071   inappropriate_io_control_operation = ENOTTY,
0072   interrupted = EINTR,
0073   invalid_argument = EINVAL,
0074   invalid_seek = ESPIPE,
0075   io_error = EIO,
0076   is_a_directory = EISDIR,
0077   message_size = EMSGSIZE,
0078   network_down = ENETDOWN,
0079   network_reset = ENETRESET,
0080   network_unreachable = ENETUNREACH,
0081   no_buffer_space = ENOBUFS,
0082   no_child_process = ECHILD,
0083   no_link = ENOLINK,
0084   no_lock_available = ENOLCK,
0085   no_message = ENOMSG,
0086   no_protocol_option = ENOPROTOOPT,
0087   no_space_on_device = ENOSPC,
0088   no_stream_resources = ENOSR,
0089   no_such_device_or_address = ENXIO,
0090   no_such_device = ENODEV,
0091   no_such_file_or_directory = ENOENT,
0092   no_such_process = ESRCH,
0093   not_a_directory = ENOTDIR,
0094   not_a_socket = ENOTSOCK,
0095   not_a_stream = ENOSTR,
0096   not_connected = ENOTCONN,
0097   not_enough_memory = ENOMEM,
0098   not_supported = ENOTSUP,
0099   operation_canceled = ECANCELED,
0100   operation_in_progress = EINPROGRESS,
0101   operation_not_permitted = EPERM,
0102   operation_not_supported = EOPNOTSUPP,
0103   operation_would_block = EWOULDBLOCK,
0104   owner_dead = EOWNERDEAD,
0105   permission_denied = EACCES,
0106   protocol_error = EPROTO,
0107   protocol_not_supported = EPROTONOSUPPORT,
0108   read_only_file_system = EROFS,
0109   resource_deadlock_would_occur = EDEADLK,
0110   resource_unavailable_try_again = EAGAIN,
0111   result_out_of_range = ERANGE,
0112   state_not_recoverable = ENOTRECOVERABLE,
0113   stream_timeout = ETIME,
0114   text_file_busy = ETXTBSY,
0115   timed_out = ETIMEDOUT,
0116   too_many_files_open_in_system = ENFILE,
0117   too_many_files_open = EMFILE,
0118   too_many_links = EMLINK,
0119   too_many_symbolic_link_levels = ELOOP,
0120   value_too_large = EOVERFLOW,
0121   wrong_protocol_type = EPROTOTYPE
0122 };
0123 
0124 namespace detail
0125 {
0126   BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 inline const char *generic_code_message(errc code) noexcept
0127   {
0128     switch(code)
0129     {
0130     case errc::success:
0131       return "Success";
0132     case errc::address_family_not_supported:
0133       return "Address family not supported by protocol";
0134     case errc::address_in_use:
0135       return "Address already in use";
0136     case errc::address_not_available:
0137       return "Cannot assign requested address";
0138     case errc::already_connected:
0139       return "Transport endpoint is already connected";
0140     case errc::argument_list_too_long:
0141       return "Argument list too long";
0142     case errc::argument_out_of_domain:
0143       return "Numerical argument out of domain";
0144     case errc::bad_address:
0145       return "Bad address";
0146     case errc::bad_file_descriptor:
0147       return "Bad file descriptor";
0148     case errc::bad_message:
0149       return "Bad message";
0150     case errc::broken_pipe:
0151       return "Broken pipe";
0152     case errc::connection_aborted:
0153       return "Software caused connection abort";
0154     case errc::connection_already_in_progress:
0155       return "Operation already in progress";
0156     case errc::connection_refused:
0157       return "Connection refused";
0158     case errc::connection_reset:
0159       return "Connection reset by peer";
0160     case errc::cross_device_link:
0161       return "Invalid cross-device link";
0162     case errc::destination_address_required:
0163       return "Destination address required";
0164     case errc::device_or_resource_busy:
0165       return "Device or resource busy";
0166     case errc::directory_not_empty:
0167       return "Directory not empty";
0168     case errc::executable_format_error:
0169       return "Exec format error";
0170     case errc::file_exists:
0171       return "File exists";
0172     case errc::file_too_large:
0173       return "File too large";
0174     case errc::filename_too_long:
0175       return "File name too long";
0176     case errc::function_not_supported:
0177       return "Function not implemented";
0178     case errc::host_unreachable:
0179       return "No route to host";
0180     case errc::identifier_removed:
0181       return "Identifier removed";
0182     case errc::illegal_byte_sequence:
0183       return "Invalid or incomplete multibyte or wide character";
0184     case errc::inappropriate_io_control_operation:
0185       return "Inappropriate ioctl for device";
0186     case errc::interrupted:
0187       return "Interrupted system call";
0188     case errc::invalid_argument:
0189       return "Invalid argument";
0190     case errc::invalid_seek:
0191       return "Illegal seek";
0192     case errc::io_error:
0193       return "Input/output error";
0194     case errc::is_a_directory:
0195       return "Is a directory";
0196     case errc::message_size:
0197       return "Message too long";
0198     case errc::network_down:
0199       return "Network is down";
0200     case errc::network_reset:
0201       return "Network dropped connection on reset";
0202     case errc::network_unreachable:
0203       return "Network is unreachable";
0204     case errc::no_buffer_space:
0205       return "No buffer space available";
0206     case errc::no_child_process:
0207       return "No child processes";
0208     case errc::no_link:
0209       return "Link has been severed";
0210     case errc::no_lock_available:
0211       return "No locks available";
0212     case errc::no_message:
0213       return "No message of desired type";
0214     case errc::no_protocol_option:
0215       return "Protocol not available";
0216     case errc::no_space_on_device:
0217       return "No space left on device";
0218     case errc::no_stream_resources:
0219       return "Out of streams resources";
0220     case errc::no_such_device_or_address:
0221       return "No such device or address";
0222     case errc::no_such_device:
0223       return "No such device";
0224     case errc::no_such_file_or_directory:
0225       return "No such file or directory";
0226     case errc::no_such_process:
0227       return "No such process";
0228     case errc::not_a_directory:
0229       return "Not a directory";
0230     case errc::not_a_socket:
0231       return "Socket operation on non-socket";
0232     case errc::not_a_stream:
0233       return "Device not a stream";
0234     case errc::not_connected:
0235       return "Transport endpoint is not connected";
0236     case errc::not_enough_memory:
0237       return "Cannot allocate memory";
0238 #if ENOTSUP != EOPNOTSUPP
0239     case errc::not_supported:
0240       return "Operation not supported";
0241 #endif
0242     case errc::operation_canceled:
0243       return "Operation canceled";
0244     case errc::operation_in_progress:
0245       return "Operation now in progress";
0246     case errc::operation_not_permitted:
0247       return "Operation not permitted";
0248     case errc::operation_not_supported:
0249       return "Operation not supported";
0250 #if EAGAIN != EWOULDBLOCK
0251     case errc::operation_would_block:
0252       return "Resource temporarily unavailable";
0253 #endif
0254     case errc::owner_dead:
0255       return "Owner died";
0256     case errc::permission_denied:
0257       return "Permission denied";
0258     case errc::protocol_error:
0259       return "Protocol error";
0260     case errc::protocol_not_supported:
0261       return "Protocol not supported";
0262     case errc::read_only_file_system:
0263       return "Read-only file system";
0264     case errc::resource_deadlock_would_occur:
0265       return "Resource deadlock avoided";
0266     case errc::resource_unavailable_try_again:
0267       return "Resource temporarily unavailable";
0268     case errc::result_out_of_range:
0269       return "Numerical result out of range";
0270     case errc::state_not_recoverable:
0271       return "State not recoverable";
0272     case errc::stream_timeout:
0273       return "Timer expired";
0274     case errc::text_file_busy:
0275       return "Text file busy";
0276     case errc::timed_out:
0277       return "Connection timed out";
0278     case errc::too_many_files_open_in_system:
0279       return "Too many open files in system";
0280     case errc::too_many_files_open:
0281       return "Too many open files";
0282     case errc::too_many_links:
0283       return "Too many links";
0284     case errc::too_many_symbolic_link_levels:
0285       return "Too many levels of symbolic links";
0286     case errc::value_too_large:
0287       return "Value too large for defined data type";
0288     case errc::wrong_protocol_type:
0289       return "Protocol wrong type for socket";
0290     default:
0291       return "unknown";
0292     }
0293   }
0294 }  // namespace detail
0295 
0296 /*! The implementation of the domain for generic status codes, those mapped by `errc` (POSIX).
0297  */
0298 class _generic_code_domain : public status_code_domain
0299 {
0300   template <class> friend class status_code;
0301   using _base = status_code_domain;
0302 
0303 public:
0304   //! The value type of the generic code, which is an `errc` as per POSIX.
0305   using value_type = errc;
0306   using string_ref = _base::string_ref;
0307 
0308 public:
0309   //! Default constructor
0310   constexpr explicit _generic_code_domain(typename _base::unique_id_type id = 0x746d6354f4f733e9) noexcept
0311       : _base(id)
0312   {
0313   }
0314   _generic_code_domain(const _generic_code_domain &) = default;
0315   _generic_code_domain(_generic_code_domain &&) = default;
0316   _generic_code_domain &operator=(const _generic_code_domain &) = default;
0317   _generic_code_domain &operator=(_generic_code_domain &&) = default;
0318   ~_generic_code_domain() = default;
0319 
0320   //! Constexpr singleton getter. Returns the constexpr generic_code_domain variable.
0321   static inline constexpr const _generic_code_domain &get();
0322 
0323   virtual _base::string_ref name() const noexcept override { return string_ref("generic domain"); }  // NOLINT
0324 
0325   virtual payload_info_t payload_info() const noexcept override
0326   {
0327     return {sizeof(value_type), sizeof(status_code_domain *) + sizeof(value_type),
0328             (alignof(value_type) > alignof(status_code_domain *)) ? alignof(value_type) : alignof(status_code_domain *)};
0329   }
0330 
0331 protected:
0332   virtual bool _do_failure(const status_code<void> &code) const noexcept override  // NOLINT
0333   {
0334     assert(code.domain() == *this);                                           // NOLINT
0335     return static_cast<const generic_code &>(code).value() != errc::success;  // NOLINT
0336   }
0337   virtual bool _do_equivalent(const status_code<void> &code1, const status_code<void> &code2) const noexcept override  // NOLINT
0338   {
0339     assert(code1.domain() == *this);                            // NOLINT
0340     const auto &c1 = static_cast<const generic_code &>(code1);  // NOLINT
0341     if(code2.domain() == *this)
0342     {
0343       const auto &c2 = static_cast<const generic_code &>(code2);  // NOLINT
0344       return c1.value() == c2.value();
0345     }
0346     return false;
0347   }
0348   virtual generic_code _generic_code(const status_code<void> &code) const noexcept override  // NOLINT
0349   {
0350     assert(code.domain() == *this);                  // NOLINT
0351     return static_cast<const generic_code &>(code);  // NOLINT
0352   }
0353   virtual _base::string_ref _do_message(const status_code<void> &code) const noexcept override  // NOLINT
0354   {
0355     assert(code.domain() == *this);                           // NOLINT
0356     const auto &c = static_cast<const generic_code &>(code);  // NOLINT
0357     return string_ref(detail::generic_code_message(c.value()));
0358   }
0359 #if defined(_CPPUNWIND) || defined(__EXCEPTIONS) || defined(BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE)
0360   BOOST_OUTCOME_SYSTEM_ERROR2_NORETURN virtual void _do_throw_exception(const status_code<void> &code) const override  // NOLINT
0361   {
0362     assert(code.domain() == *this);                           // NOLINT
0363     const auto &c = static_cast<const generic_code &>(code);  // NOLINT
0364     throw status_error<_generic_code_domain>(c);
0365   }
0366 #endif
0367 };
0368 //! A specialisation of `status_error` for the generic code domain.
0369 using generic_error = status_error<_generic_code_domain>;
0370 //! A constexpr source variable for the generic code domain, which is that of `errc` (POSIX). Returned by `_generic_code_domain::get()`.
0371 constexpr _generic_code_domain generic_code_domain;
0372 inline constexpr const _generic_code_domain &_generic_code_domain::get()
0373 {
0374   return generic_code_domain;
0375 }
0376 // Enable implicit construction of generic_code from errc
0377 BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 inline generic_code make_status_code(errc c) noexcept
0378 {
0379   return generic_code(in_place, c);
0380 }
0381 
0382 
0383 /*************************************************************************************************************/
0384 
0385 
0386 template <class T> inline BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 bool status_code<void>::equivalent(const status_code<T> &o) const noexcept
0387 {
0388   if(_domain && o._domain)
0389   {
0390     if(_domain->_do_equivalent(*this, o))
0391     {
0392       return true;
0393     }
0394     if(o._domain->_do_equivalent(o, *this))
0395     {
0396       return true;
0397     }
0398     generic_code c1 = o._domain->_generic_code(o);
0399     if(c1.value() != errc::unknown && _domain->_do_equivalent(*this, c1))
0400     {
0401       return true;
0402     }
0403     generic_code c2 = _domain->_generic_code(*this);
0404     if(c2.value() != errc::unknown && o._domain->_do_equivalent(o, c2))
0405     {
0406       return true;
0407     }
0408   }
0409   // If we are both empty, we are equivalent, otherwise not equivalent
0410   return (!_domain && !o._domain);
0411 }
0412 //! True if the status code's are semantically equal via `equivalent()`.
0413 template <class DomainType1, class DomainType2>
0414 BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 inline bool operator==(const status_code<DomainType1> &a, const status_code<DomainType2> &b) noexcept
0415 {
0416   return a.equivalent(b);
0417 }
0418 //! True if the status code's are not semantically equal via `equivalent()`.
0419 template <class DomainType1, class DomainType2>
0420 BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 inline bool operator!=(const status_code<DomainType1> &a, const status_code<DomainType2> &b) noexcept
0421 {
0422   return !a.equivalent(b);
0423 }
0424 //! True if the status code's are semantically equal via `equivalent()` to `make_status_code(T)`.
0425 BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class DomainType1, class T,  //
0426                        class MakeStatusCodeResult =
0427                        typename detail::safe_get_make_status_code_result<const T &>::type)  // Safe ADL lookup of make_status_code(), returns void if not found
0428 BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(is_status_code<MakeStatusCodeResult>::value))   // ADL makes a status code
0429 BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 inline bool operator==(const status_code<DomainType1> &a, const T &b)
0430 {
0431   return a.equivalent(make_status_code(b));
0432 }
0433 //! True if the status code's are semantically equal via `equivalent()` to `make_status_code(T)`.
0434 BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class T, class DomainType1,  //
0435                        class MakeStatusCodeResult =
0436                        typename detail::safe_get_make_status_code_result<const T &>::type)  // Safe ADL lookup of make_status_code(), returns void if not found
0437 BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(is_status_code<MakeStatusCodeResult>::value))   // ADL makes a status code
0438 BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 inline bool operator==(const T &a, const status_code<DomainType1> &b)
0439 {
0440   return b.equivalent(make_status_code(a));
0441 }
0442 //! True if the status code's are not semantically equal via `equivalent()` to `make_status_code(T)`.
0443 BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class DomainType1, class T,  //
0444                        class MakeStatusCodeResult =
0445                        typename detail::safe_get_make_status_code_result<const T &>::type)  // Safe ADL lookup of make_status_code(), returns void if not found
0446 BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(is_status_code<MakeStatusCodeResult>::value))   // ADL makes a status code
0447 BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 inline bool operator!=(const status_code<DomainType1> &a, const T &b)
0448 {
0449   return !a.equivalent(make_status_code(b));
0450 }
0451 //! True if the status code's are semantically equal via `equivalent()` to `make_status_code(T)`.
0452 BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class T, class DomainType1,  //
0453                        class MakeStatusCodeResult =
0454                        typename detail::safe_get_make_status_code_result<const T &>::type)  // Safe ADL lookup of make_status_code(), returns void if not found
0455 BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(is_status_code<MakeStatusCodeResult>::value))   // ADL makes a status code
0456 BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 inline bool operator!=(const T &a, const status_code<DomainType1> &b)
0457 {
0458   return !b.equivalent(make_status_code(a));
0459 }
0460 //! True if the status code's are semantically equal via `equivalent()` to `quick_status_code_from_enum<T>::code_type(b)`.
0461 template <class DomainType1, class T,                                                     //
0462           class QuickStatusCodeType = typename quick_status_code_from_enum<T>::code_type  // Enumeration has been activated
0463           >
0464 BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 inline bool operator==(const status_code<DomainType1> &a, const T &b)
0465 {
0466   return a.equivalent(QuickStatusCodeType(b));
0467 }
0468 //! True if the status code's are semantically equal via `equivalent()` to `quick_status_code_from_enum<T>::code_type(a)`.
0469 template <class T, class DomainType1,                                                     //
0470           class QuickStatusCodeType = typename quick_status_code_from_enum<T>::code_type  // Enumeration has been activated
0471           >
0472 BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 inline bool operator==(const T &a, const status_code<DomainType1> &b)
0473 {
0474   return b.equivalent(QuickStatusCodeType(a));
0475 }
0476 //! True if the status code's are not semantically equal via `equivalent()` to `quick_status_code_from_enum<T>::code_type(b)`.
0477 template <class DomainType1, class T,                                                     //
0478           class QuickStatusCodeType = typename quick_status_code_from_enum<T>::code_type  // Enumeration has been activated
0479           >
0480 BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 inline bool operator!=(const status_code<DomainType1> &a, const T &b)
0481 {
0482   return !a.equivalent(QuickStatusCodeType(b));
0483 }
0484 //! True if the status code's are not semantically equal via `equivalent()` to `quick_status_code_from_enum<T>::code_type(a)`.
0485 template <class T, class DomainType1,                                                     //
0486           class QuickStatusCodeType = typename quick_status_code_from_enum<T>::code_type  // Enumeration has been activated
0487           >
0488 BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 inline bool operator!=(const T &a, const status_code<DomainType1> &b)
0489 {
0490   return !b.equivalent(QuickStatusCodeType(a));
0491 }
0492 
0493 
0494 BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_END
0495 
0496 #if defined(_MSC_VER) && !defined(__clang__)
0497 #pragma warning(pop)
0498 #endif
0499 
0500 #endif