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 error_category::error_category() _NOEXCEPT
36 error_category::~error_category() _NOEXCEPT
41 error_category::default_error_condition(int ev) const _NOEXCEPT
43 return error_condition(ev, *this);
47 error_category::equivalent(int code, const error_condition& condition) const _NOEXCEPT
49 return default_error_condition(code) == condition;
53 error_category::equivalent(const error_code& code, int condition) const _NOEXCEPT
55 return *this == code.category() && code.value() == condition;
60 // GLIBC also uses 1024 as the maximum buffer size internally.
61 constexpr size_t strerror_buff_size = 1024;
63 string do_strerror_r(int ev);
65 #if defined(__linux__) && !defined(_LIBCPP_HAS_MUSL_LIBC) \
66 && (!defined(__ANDROID__) || __ANDROID_API__ >= 23)
67 // GNU Extended version
68 string do_strerror_r(int ev) {
69 char buffer[strerror_buff_size];
70 char* ret = ::strerror_r(ev, buffer, strerror_buff_size);
75 string do_strerror_r(int ev) {
76 char buffer[strerror_buff_size];
77 const int old_errno = errno;
79 if ((ret = ::strerror_r(ev, buffer, strerror_buff_size)) != 0) {
80 // If `ret == -1` then the error is specified using `errno`, otherwise
81 // `ret` represents the error.
82 const int new_errno = ret == -1 ? errno : ret;
84 if (new_errno == EINVAL) {
85 std::snprintf(buffer, strerror_buff_size, "Unknown error %d", ev);
86 return string(buffer);
88 assert(new_errno == ERANGE);
89 // FIXME maybe? 'strerror_buff_size' is likely to exceed the
90 // maximum error size so ERANGE shouldn't be returned.
94 return string(buffer);
101 __do_message::message(int ev) const
103 #if defined(_LIBCPP_HAS_NO_THREADS)
104 return string(::strerror(ev));
106 return do_strerror_r(ev);
110 class _LIBCPP_HIDDEN __generic_error_category
111 : public __do_message
114 virtual const char* name() const _NOEXCEPT;
115 virtual string message(int ev) const;
119 __generic_error_category::name() const _NOEXCEPT
125 __generic_error_category::message(int ev) const
128 if (ev > _LIBCPP_ELAST)
129 return string("unspecified generic_category error");
130 #endif // _LIBCPP_ELAST
131 return __do_message::message(ev);
134 const error_category&
135 generic_category() _NOEXCEPT
137 static __generic_error_category s;
141 class _LIBCPP_HIDDEN __system_error_category
142 : public __do_message
145 virtual const char* name() const _NOEXCEPT;
146 virtual string message(int ev) const;
147 virtual error_condition default_error_condition(int ev) const _NOEXCEPT;
151 __system_error_category::name() const _NOEXCEPT
157 __system_error_category::message(int ev) const
160 if (ev > _LIBCPP_ELAST)
161 return string("unspecified system_category error");
162 #endif // _LIBCPP_ELAST
163 return __do_message::message(ev);
167 __system_error_category::default_error_condition(int ev) const _NOEXCEPT
170 if (ev > _LIBCPP_ELAST)
171 return error_condition(ev, system_category());
172 #endif // _LIBCPP_ELAST
173 return error_condition(ev, generic_category());
176 const error_category&
177 system_category() _NOEXCEPT
179 static __system_error_category s;
186 error_condition::message() const
188 return __cat_->message(__val_);
194 error_code::message() const
196 return __cat_->message(__val_);
202 system_error::__init(const error_code& ec, string what_arg)
206 if (!what_arg.empty())
208 what_arg += ec.message();
213 system_error::system_error(error_code ec, const string& what_arg)
214 : runtime_error(__init(ec, what_arg)),
219 system_error::system_error(error_code ec, const char* what_arg)
220 : runtime_error(__init(ec, what_arg)),
225 system_error::system_error(error_code ec)
226 : runtime_error(__init(ec, "")),
231 system_error::system_error(int ev, const error_category& ecat, const string& what_arg)
232 : runtime_error(__init(error_code(ev, ecat), what_arg)),
233 __ec_(error_code(ev, ecat))
237 system_error::system_error(int ev, const error_category& ecat, const char* what_arg)
238 : runtime_error(__init(error_code(ev, ecat), what_arg)),
239 __ec_(error_code(ev, ecat))
243 system_error::system_error(int ev, const error_category& ecat)
244 : runtime_error(__init(error_code(ev, ecat), "")),
245 __ec_(error_code(ev, ecat))
249 system_error::~system_error() _NOEXCEPT
254 __throw_system_error(int ev, const char* what_arg)
256 #ifndef _LIBCPP_NO_EXCEPTIONS
257 throw system_error(error_code(ev, system_category()), what_arg);
264 _LIBCPP_END_NAMESPACE_STD