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_EXTERNAL_ERROR_CATEGORY_CONSTRUCTOR)
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)
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);
76 #elif defined(__linux__) && !defined(_LIBCPP_HAS_MUSL_LIBC) && \
77 (!defined(__ANDROID__) || __ANDROID_API__ >= 23)
78 // GNU Extended version
79 string do_strerror_r(int ev) {
80 char buffer[strerror_buff_size];
81 char* ret = ::strerror_r(ev, buffer, strerror_buff_size);
86 string do_strerror_r(int ev) {
87 char buffer[strerror_buff_size];
88 const int old_errno = errno;
90 if ((ret = ::strerror_r(ev, buffer, strerror_buff_size)) != 0) {
91 // If `ret == -1` then the error is specified using `errno`, otherwise
92 // `ret` represents the error.
93 const int new_errno = ret == -1 ? errno : ret;
95 if (new_errno == EINVAL) {
96 std::snprintf(buffer, strerror_buff_size, "Unknown error %d", ev);
97 return string(buffer);
99 assert(new_errno == ERANGE);
100 // FIXME maybe? 'strerror_buff_size' is likely to exceed the
101 // maximum error size so ERANGE shouldn't be returned.
105 return string(buffer);
113 __do_message::message(int ev) const
115 #if defined(_LIBCPP_HAS_NO_THREADS)
116 return string(::strerror(ev));
118 return do_strerror_r(ev);
122 class _LIBCPP_HIDDEN __generic_error_category
123 : public __do_message
126 virtual const char* name() const _NOEXCEPT;
127 virtual string message(int ev) const;
131 __generic_error_category::name() const _NOEXCEPT
137 __generic_error_category::message(int ev) const
140 if (ev > _LIBCPP_ELAST)
141 return string("unspecified generic_category error");
142 #endif // _LIBCPP_ELAST
143 return __do_message::message(ev);
146 const error_category&
147 generic_category() _NOEXCEPT
149 static __generic_error_category s;
153 class _LIBCPP_HIDDEN __system_error_category
154 : public __do_message
157 virtual const char* name() const _NOEXCEPT;
158 virtual string message(int ev) const;
159 virtual error_condition default_error_condition(int ev) const _NOEXCEPT;
163 __system_error_category::name() const _NOEXCEPT
169 __system_error_category::message(int ev) const
172 if (ev > _LIBCPP_ELAST)
173 return string("unspecified system_category error");
174 #endif // _LIBCPP_ELAST
175 return __do_message::message(ev);
179 __system_error_category::default_error_condition(int ev) const _NOEXCEPT
182 if (ev > _LIBCPP_ELAST)
183 return error_condition(ev, system_category());
184 #endif // _LIBCPP_ELAST
185 return error_condition(ev, generic_category());
188 const error_category&
189 system_category() _NOEXCEPT
191 static __system_error_category s;
198 error_condition::message() const
200 return __cat_->message(__val_);
206 error_code::message() const
208 return __cat_->message(__val_);
214 system_error::__init(const error_code& ec, string what_arg)
218 if (!what_arg.empty())
220 what_arg += ec.message();
225 system_error::system_error(error_code ec, const string& what_arg)
226 : runtime_error(__init(ec, what_arg)),
231 system_error::system_error(error_code ec, const char* what_arg)
232 : runtime_error(__init(ec, what_arg)),
237 system_error::system_error(error_code ec)
238 : runtime_error(__init(ec, "")),
243 system_error::system_error(int ev, const error_category& ecat, const string& what_arg)
244 : runtime_error(__init(error_code(ev, ecat), what_arg)),
245 __ec_(error_code(ev, ecat))
249 system_error::system_error(int ev, const error_category& ecat, const char* what_arg)
250 : runtime_error(__init(error_code(ev, ecat), what_arg)),
251 __ec_(error_code(ev, ecat))
255 system_error::system_error(int ev, const error_category& ecat)
256 : runtime_error(__init(error_code(ev, ecat), "")),
257 __ec_(error_code(ev, ecat))
261 system_error::~system_error() _NOEXCEPT
266 __throw_system_error(int ev, const char* what_arg)
268 #ifndef _LIBCPP_NO_EXCEPTIONS
269 throw system_error(error_code(ev, system_category()), what_arg);
277 _LIBCPP_END_NAMESPACE_STD