1 //===---------------------- system_error.cpp ------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is dual licensed under the MIT and the University of Illinois Open
6 // Source Licenses. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
12 #define _LIBCPP_BUILDING_SYSTEM_ERROR
13 #include "system_error"
15 #include "include/config_elast.h"
24 #if defined(__ANDROID__)
25 #include <android/api-level.h>
28 _LIBCPP_BEGIN_NAMESPACE_STD
30 // class error_category
32 #if defined(_LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS)
33 error_category::error_category() _NOEXCEPT
38 error_category::~error_category() _NOEXCEPT
43 error_category::default_error_condition(int ev) const _NOEXCEPT
45 return error_condition(ev, *this);
49 error_category::equivalent(int code, const error_condition& condition) const _NOEXCEPT
51 return default_error_condition(code) == condition;
55 error_category::equivalent(const error_code& code, int condition) const _NOEXCEPT
57 return *this == code.category() && code.value() == condition;
60 #if !defined(_LIBCPP_HAS_NO_THREADS)
63 // GLIBC also uses 1024 as the maximum buffer size internally.
64 constexpr size_t strerror_buff_size = 1024;
66 string do_strerror_r(int ev);
68 #if defined(_LIBCPP_MSVCRT_LIKE)
69 string do_strerror_r(int ev) {
70 char buffer[strerror_buff_size];
71 if (::strerror_s(buffer, strerror_buff_size, ev) == 0)
72 return string(buffer);
73 std::snprintf(buffer, strerror_buff_size, "unknown error %d", ev);
74 return string(buffer);
78 // Only one of the two following functions will be used, depending on
79 // the return type of strerror_r:
81 // For the GNU variant, a char* return value:
82 __attribute__((unused)) const char *
83 handle_strerror_r_return(char *strerror_return, char *buffer) {
84 // GNU always returns a string pointer in its return value. The
85 // string might point to either the input buffer, or a static
86 // buffer, but we don't care which.
87 return strerror_return;
90 // For the POSIX variant: an int return value.
91 __attribute__((unused)) const char *
92 handle_strerror_r_return(int strerror_return, char *buffer) {
93 // The POSIX variant either:
94 // - fills in the provided buffer and returns 0
95 // - returns a positive error value, or
96 // - returns -1 and fills in errno with an error value.
97 if (strerror_return == 0)
100 // Only handle EINVAL. Other errors abort.
101 int new_errno = strerror_return == -1 ? errno : strerror_return;
102 if (new_errno == EINVAL)
105 _LIBCPP_ASSERT(new_errno == ERANGE, "unexpected error from ::strerror_r");
106 // FIXME maybe? 'strerror_buff_size' is likely to exceed the
107 // maximum error size so ERANGE shouldn't be returned.
111 // This function handles both GNU and POSIX variants, dispatching to
112 // one of the two above functions.
113 string do_strerror_r(int ev) {
114 char buffer[strerror_buff_size];
115 // Preserve errno around the call. (The C++ standard requires that
116 // system_error functions not modify errno).
117 const int old_errno = errno;
118 const char *error_message = handle_strerror_r_return(
119 ::strerror_r(ev, buffer, strerror_buff_size), buffer);
120 // If we didn't get any message, print one now.
121 if (!error_message[0]) {
122 std::snprintf(buffer, strerror_buff_size, "Unknown error %d", ev);
123 error_message = buffer;
126 return string(error_message);
133 __do_message::message(int ev) const
135 #if defined(_LIBCPP_HAS_NO_THREADS)
136 return string(::strerror(ev));
138 return do_strerror_r(ev);
142 class _LIBCPP_HIDDEN __generic_error_category
143 : public __do_message
146 virtual const char* name() const _NOEXCEPT;
147 virtual string message(int ev) const;
151 __generic_error_category::name() const _NOEXCEPT
157 __generic_error_category::message(int ev) const
160 if (ev > _LIBCPP_ELAST)
161 return string("unspecified generic_category error");
162 #endif // _LIBCPP_ELAST
163 return __do_message::message(ev);
166 const error_category&
167 generic_category() _NOEXCEPT
169 static __generic_error_category s;
173 class _LIBCPP_HIDDEN __system_error_category
174 : public __do_message
177 virtual const char* name() const _NOEXCEPT;
178 virtual string message(int ev) const;
179 virtual error_condition default_error_condition(int ev) const _NOEXCEPT;
183 __system_error_category::name() const _NOEXCEPT
189 __system_error_category::message(int ev) const
192 if (ev > _LIBCPP_ELAST)
193 return string("unspecified system_category error");
194 #endif // _LIBCPP_ELAST
195 return __do_message::message(ev);
199 __system_error_category::default_error_condition(int ev) const _NOEXCEPT
202 if (ev > _LIBCPP_ELAST)
203 return error_condition(ev, system_category());
204 #endif // _LIBCPP_ELAST
205 return error_condition(ev, generic_category());
208 const error_category&
209 system_category() _NOEXCEPT
211 static __system_error_category s;
218 error_condition::message() const
220 return __cat_->message(__val_);
226 error_code::message() const
228 return __cat_->message(__val_);
234 system_error::__init(const error_code& ec, string what_arg)
238 if (!what_arg.empty())
240 what_arg += ec.message();
245 system_error::system_error(error_code ec, const string& what_arg)
246 : runtime_error(__init(ec, what_arg)),
251 system_error::system_error(error_code ec, const char* what_arg)
252 : runtime_error(__init(ec, what_arg)),
257 system_error::system_error(error_code ec)
258 : runtime_error(__init(ec, "")),
263 system_error::system_error(int ev, const error_category& ecat, const string& what_arg)
264 : runtime_error(__init(error_code(ev, ecat), what_arg)),
265 __ec_(error_code(ev, ecat))
269 system_error::system_error(int ev, const error_category& ecat, const char* what_arg)
270 : runtime_error(__init(error_code(ev, ecat), what_arg)),
271 __ec_(error_code(ev, ecat))
275 system_error::system_error(int ev, const error_category& ecat)
276 : runtime_error(__init(error_code(ev, ecat), "")),
277 __ec_(error_code(ev, ecat))
281 system_error::~system_error() _NOEXCEPT
286 __throw_system_error(int ev, const char* what_arg)
288 #ifndef _LIBCPP_NO_EXCEPTIONS
289 throw system_error(error_code(ev, system_category()), what_arg);
297 _LIBCPP_END_NAMESPACE_STD