File indexing completed on 2025-09-17 08:40:09
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031 #ifndef BOOST_OUTCOME_SYSTEM_ERROR2_POSIX_CODE_HPP
0032 #define BOOST_OUTCOME_SYSTEM_ERROR2_POSIX_CODE_HPP
0033
0034 #ifdef BOOST_OUTCOME_SYSTEM_ERROR2_NOT_POSIX
0035 #error <posix_code.hpp> is not includable when BOOST_OUTCOME_SYSTEM_ERROR2_NOT_POSIX is defined!
0036 #endif
0037
0038 #include "quick_status_code_from_enum.hpp"
0039
0040 #include <cstring> // for strchr and strerror_r
0041
0042 #if defined(_MSC_VER) && !defined(__clang__)
0043 #pragma warning(push)
0044 #pragma warning(disable : 6326)
0045 #endif
0046
0047 BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_BEGIN
0048
0049
0050 #if !defined(_MSC_VER) && !defined(__APPLE__)
0051 namespace detail
0052 {
0053 namespace avoid_string_include
0054 {
0055 #if defined(__GLIBC__) && !defined(__UCLIBC__)
0056
0057 extern "C" char *strerror_r(int errnum, char *buf, size_t buflen);
0058 #else
0059 extern "C" int strerror_r(int errnum, char *buf, size_t buflen);
0060 #endif
0061 }
0062 }
0063 #endif
0064
0065 class _posix_code_domain;
0066
0067 using posix_code = status_code<_posix_code_domain>;
0068
0069 using posix_error = status_error<_posix_code_domain>;
0070
0071 namespace mixins
0072 {
0073 template <class Base> struct mixin<Base, _posix_code_domain> : public Base
0074 {
0075 using Base::Base;
0076
0077
0078 static posix_code current() noexcept;
0079 };
0080 }
0081
0082
0083
0084 class _posix_code_domain : public status_code_domain
0085 {
0086 template <class DomainType> friend class status_code;
0087 using _base = status_code_domain;
0088
0089 static _base::string_ref _make_string_ref(int c) noexcept
0090 {
0091 char buffer[1024] = "";
0092 #ifdef _WIN32
0093 strerror_s(buffer, sizeof(buffer), c);
0094 #elif defined(__GLIBC__) && !defined(__UCLIBC__)
0095 char *s = detail::avoid_string_include::strerror_r(c, buffer, sizeof(buffer));
0096 if(s != nullptr)
0097 {
0098 strncpy(buffer, s, sizeof(buffer) - 1);
0099 buffer[1023] = 0;
0100 }
0101 #elif !defined(__APPLE__)
0102 detail::avoid_string_include::strerror_r(c, buffer, sizeof(buffer));
0103 #else
0104 strerror_r(c, buffer, sizeof(buffer));
0105 #endif
0106 size_t length = strlen(buffer);
0107 auto *p = static_cast<char *>(malloc(length + 1));
0108 if(p == nullptr)
0109 {
0110 return _base::string_ref("failed to get message from system");
0111 }
0112 memcpy(p, buffer, length + 1);
0113 return _base::atomic_refcounted_string_ref(p, length);
0114 }
0115
0116 public:
0117
0118 using value_type = int;
0119 using _base::string_ref;
0120
0121
0122 constexpr explicit _posix_code_domain(typename _base::unique_id_type id = 0xa59a56fe5f310933) noexcept
0123 : _base(id)
0124 {
0125 }
0126 _posix_code_domain(const _posix_code_domain &) = default;
0127 _posix_code_domain(_posix_code_domain &&) = default;
0128 _posix_code_domain &operator=(const _posix_code_domain &) = default;
0129 _posix_code_domain &operator=(_posix_code_domain &&) = default;
0130 ~_posix_code_domain() = default;
0131
0132
0133 static inline constexpr const _posix_code_domain &get();
0134
0135 virtual string_ref name() const noexcept override { return string_ref("posix domain"); }
0136
0137 virtual payload_info_t payload_info() const noexcept override
0138 {
0139 return {sizeof(value_type), sizeof(status_code_domain *) + sizeof(value_type),
0140 (alignof(value_type) > alignof(status_code_domain *)) ? alignof(value_type) : alignof(status_code_domain *)};
0141 }
0142
0143 protected:
0144 virtual bool _do_failure(const status_code<void> &code) const noexcept override
0145 {
0146 assert(code.domain() == *this);
0147 return static_cast<const posix_code &>(code).value() != 0;
0148 }
0149 virtual bool _do_equivalent(const status_code<void> &code1, const status_code<void> &code2) const noexcept override
0150 {
0151 assert(code1.domain() == *this);
0152 const auto &c1 = static_cast<const posix_code &>(code1);
0153 if(code2.domain() == *this)
0154 {
0155 const auto &c2 = static_cast<const posix_code &>(code2);
0156 return c1.value() == c2.value();
0157 }
0158 if(code2.domain() == generic_code_domain)
0159 {
0160 const auto &c2 = static_cast<const generic_code &>(code2);
0161 if(static_cast<int>(c2.value()) == c1.value())
0162 {
0163 return true;
0164 }
0165 }
0166 return false;
0167 }
0168 virtual generic_code _generic_code(const status_code<void> &code) const noexcept override
0169 {
0170 assert(code.domain() == *this);
0171 const auto &c = static_cast<const posix_code &>(code);
0172 return generic_code(static_cast<errc>(c.value()));
0173 }
0174 virtual string_ref _do_message(const status_code<void> &code) const noexcept override
0175 {
0176 assert(code.domain() == *this);
0177 const auto &c = static_cast<const posix_code &>(code);
0178 return _make_string_ref(c.value());
0179 }
0180 #if defined(_CPPUNWIND) || defined(__EXCEPTIONS) || defined(BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE)
0181 BOOST_OUTCOME_SYSTEM_ERROR2_NORETURN virtual void _do_throw_exception(const status_code<void> &code) const override
0182 {
0183 assert(code.domain() == *this);
0184 const auto &c = static_cast<const posix_code &>(code);
0185 throw status_error<_posix_code_domain>(c);
0186 }
0187 #endif
0188 };
0189
0190 constexpr _posix_code_domain posix_code_domain;
0191 inline constexpr const _posix_code_domain &_posix_code_domain::get()
0192 {
0193 return posix_code_domain;
0194 }
0195
0196 namespace mixins
0197 {
0198 template <class Base> inline posix_code mixin<Base, _posix_code_domain>::current() noexcept
0199 {
0200 return posix_code(errno);
0201 }
0202 }
0203
0204 BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_END
0205
0206 #if defined(_MSC_VER) && !defined(__clang__)
0207 #pragma warning(pop)
0208 #endif
0209
0210 #endif