1 //===----------------------------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
10 #ifdef _LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS
11 # define _LIBCPP_ERROR_CATEGORY_DEFINE_LEGACY_INLINE_FUNCTIONS
21 #include <system_error>
23 #include "include/config_elast.h"
25 #if defined(__ANDROID__)
26 #include <android/api-level.h>
29 _LIBCPP_BEGIN_NAMESPACE_STD
31 // class error_category
33 #if defined(_LIBCPP_ERROR_CATEGORY_DEFINE_LEGACY_INLINE_FUNCTIONS)
34 error_category::error_category() noexcept
39 error_category::~error_category() noexcept
44 error_category::default_error_condition(int ev
) const noexcept
46 return error_condition(ev
, *this);
50 error_category::equivalent(int code
, const error_condition
& condition
) const noexcept
52 return default_error_condition(code
) == condition
;
56 error_category::equivalent(const error_code
& code
, int condition
) const noexcept
58 return *this == code
.category() && code
.value() == condition
;
61 #if !defined(_LIBCPP_HAS_NO_THREADS)
64 // GLIBC also uses 1024 as the maximum buffer size internally.
65 constexpr size_t strerror_buff_size
= 1024;
67 string
do_strerror_r(int ev
);
69 #if defined(_LIBCPP_MSVCRT_LIKE)
70 string
do_strerror_r(int ev
) {
71 char buffer
[strerror_buff_size
];
72 if (::strerror_s(buffer
, strerror_buff_size
, ev
) == 0)
73 return string(buffer
);
74 std::snprintf(buffer
, strerror_buff_size
, "unknown error %d", ev
);
75 return string(buffer
);
79 // Only one of the two following functions will be used, depending on
80 // the return type of strerror_r:
82 // For the GNU variant, a char* return value:
83 __attribute__((unused
)) const char *
84 handle_strerror_r_return(char *strerror_return
, char *buffer
) {
85 // GNU always returns a string pointer in its return value. The
86 // string might point to either the input buffer, or a static
87 // buffer, but we don't care which.
88 return strerror_return
;
91 // For the POSIX variant: an int return value.
92 __attribute__((unused
)) const char *
93 handle_strerror_r_return(int strerror_return
, char *buffer
) {
94 // The POSIX variant either:
95 // - fills in the provided buffer and returns 0
96 // - returns a positive error value, or
97 // - returns -1 and fills in errno with an error value.
98 if (strerror_return
== 0)
101 // Only handle EINVAL. Other errors abort.
102 int new_errno
= strerror_return
== -1 ? errno
: strerror_return
;
103 if (new_errno
== EINVAL
)
106 _LIBCPP_ASSERT(new_errno
== ERANGE
, "unexpected error from ::strerror_r");
107 // FIXME maybe? 'strerror_buff_size' is likely to exceed the
108 // maximum error size so ERANGE shouldn't be returned.
112 // This function handles both GNU and POSIX variants, dispatching to
113 // one of the two above functions.
114 string
do_strerror_r(int ev
) {
115 char buffer
[strerror_buff_size
];
116 // Preserve errno around the call. (The C++ standard requires that
117 // system_error functions not modify errno).
118 const int old_errno
= errno
;
119 const char *error_message
= handle_strerror_r_return(
120 ::strerror_r(ev
, buffer
, strerror_buff_size
), buffer
);
121 // If we didn't get any message, print one now.
122 if (!error_message
[0]) {
123 std::snprintf(buffer
, strerror_buff_size
, "Unknown error %d", ev
);
124 error_message
= buffer
;
127 return string(error_message
);
134 __do_message::message(int ev
) const
136 #if defined(_LIBCPP_HAS_NO_THREADS)
137 return string(::strerror(ev
));
139 return do_strerror_r(ev
);
143 class _LIBCPP_HIDDEN __generic_error_category
144 : public __do_message
147 virtual const char* name() const noexcept
;
148 virtual string
message(int ev
) const;
152 __generic_error_category::name() const noexcept
158 __generic_error_category::message(int ev
) const
161 if (ev
> _LIBCPP_ELAST
)
162 return string("unspecified generic_category error");
163 #endif // _LIBCPP_ELAST
164 return __do_message::message(ev
);
167 const error_category
&
168 generic_category() noexcept
170 static __generic_error_category s
;
174 class _LIBCPP_HIDDEN __system_error_category
175 : public __do_message
178 virtual const char* name() const noexcept
;
179 virtual string
message(int ev
) const;
180 virtual error_condition
default_error_condition(int ev
) const noexcept
;
184 __system_error_category::name() const noexcept
190 __system_error_category::message(int ev
) const
193 if (ev
> _LIBCPP_ELAST
)
194 return string("unspecified system_category error");
195 #endif // _LIBCPP_ELAST
196 return __do_message::message(ev
);
200 __system_error_category::default_error_condition(int ev
) const noexcept
203 if (ev
> _LIBCPP_ELAST
)
204 return error_condition(ev
, system_category());
205 #endif // _LIBCPP_ELAST
206 return error_condition(ev
, generic_category());
209 const error_category
&
210 system_category() noexcept
212 static __system_error_category s
;
219 error_condition::message() const
221 return __cat_
->message(__val_
);
227 error_code::message() const
229 return __cat_
->message(__val_
);
235 system_error::__init(const error_code
& ec
, string what_arg
)
239 if (!what_arg
.empty())
241 what_arg
+= ec
.message();
246 system_error::system_error(error_code ec
, const string
& what_arg
)
247 : runtime_error(__init(ec
, what_arg
)),
252 system_error::system_error(error_code ec
, const char* what_arg
)
253 : runtime_error(__init(ec
, what_arg
)),
258 system_error::system_error(error_code ec
)
259 : runtime_error(__init(ec
, "")),
264 system_error::system_error(int ev
, const error_category
& ecat
, const string
& what_arg
)
265 : runtime_error(__init(error_code(ev
, ecat
), what_arg
)),
266 __ec_(error_code(ev
, ecat
))
270 system_error::system_error(int ev
, const error_category
& ecat
, const char* what_arg
)
271 : runtime_error(__init(error_code(ev
, ecat
), what_arg
)),
272 __ec_(error_code(ev
, ecat
))
276 system_error::system_error(int ev
, const error_category
& ecat
)
277 : runtime_error(__init(error_code(ev
, ecat
), "")),
278 __ec_(error_code(ev
, ecat
))
282 system_error::~system_error() noexcept
287 __throw_system_error(int ev
, const char* what_arg
)
289 #ifndef _LIBCPP_NO_EXCEPTIONS
290 throw system_error(error_code(ev
, system_category()), what_arg
);
298 _LIBCPP_END_NAMESPACE_STD