blob: d7115fc66472831d0f50e2bccb338dae95e4a5a6 [file] [log] [blame]
Howard Hinnant3e519522010-05-11 19:42:16 +00001//===---------------------- system_error.cpp ------------------------------===//
2//
Howard Hinnant5b08a8a2010-05-11 21:36:01 +00003// The LLVM Compiler Infrastructure
Howard Hinnant3e519522010-05-11 19:42:16 +00004//
Howard Hinnant412dbeb2010-11-16 22:09:02 +00005// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
Howard Hinnant3e519522010-05-11 19:42:16 +00007//
8//===----------------------------------------------------------------------===//
9
Jonathan Roelofsa409d592014-09-02 20:34:23 +000010#include "__config"
Dan Alberta76dfbd2015-01-06 17:34:51 +000011
12#define _LIBCPP_BUILDING_SYSTEM_ERROR
Howard Hinnant3e519522010-05-11 19:42:16 +000013#include "system_error"
Dan Alberta76dfbd2015-01-06 17:34:51 +000014
Eric Fiseliere8fd1642015-08-18 21:08:54 +000015#include "include/config_elast.h"
Eric Fiselier9778a6d2016-06-14 03:45:31 +000016#include "cerrno"
Howard Hinnant3e519522010-05-11 19:42:16 +000017#include "cstring"
Eric Fiselier9778a6d2016-06-14 03:45:31 +000018#include "cstdio"
19#include "cstdlib"
20#include "cassert"
Dan Alberta76dfbd2015-01-06 17:34:51 +000021#include "string"
Eric Fiselier9778a6d2016-06-14 03:45:31 +000022#include "string.h"
Howard Hinnant3e519522010-05-11 19:42:16 +000023
24_LIBCPP_BEGIN_NAMESPACE_STD
25
26// class error_category
27
Howard Hinnanta62f2892011-05-26 19:48:01 +000028error_category::error_category() _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +000029{
30}
31
Howard Hinnanta62f2892011-05-26 19:48:01 +000032error_category::~error_category() _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +000033{
34}
35
36error_condition
Howard Hinnanta62f2892011-05-26 19:48:01 +000037error_category::default_error_condition(int ev) const _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +000038{
39 return error_condition(ev, *this);
40}
41
42bool
Howard Hinnanta62f2892011-05-26 19:48:01 +000043error_category::equivalent(int code, const error_condition& condition) const _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +000044{
45 return default_error_condition(code) == condition;
46}
47
48bool
Howard Hinnanta62f2892011-05-26 19:48:01 +000049error_category::equivalent(const error_code& code, int condition) const _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +000050{
51 return *this == code.category() && code.value() == condition;
52}
53
Eric Fiselier9778a6d2016-06-14 03:45:31 +000054namespace {
55
56// GLIBC also uses 1024 as the maximum buffer size internally.
57constexpr size_t strerror_buff_size = 1024;
58
59string do_strerror_r(int ev);
60
61#if defined(__linux__) && !defined(_LIBCPP_HAS_MUSL_LIBC)
62// GNU Extended version
63string do_strerror_r(int ev) {
64 char buffer[strerror_buff_size];
65 char* ret = ::strerror_r(ev, buffer, strerror_buff_size);
66 return string(ret);
67}
68#else
69// POSIX version
70string do_strerror_r(int ev) {
71 char buffer[strerror_buff_size];
72 const int old_errno = errno;
Eric Fiselier79e05742016-06-14 06:03:20 +000073 if ((int ret = ::strerror_r(ev, buffer, strerror_buff_size)) != 0) {
74 // If `ret == -1` then the error is specified using `errno`, otherwise
75 // `ret` represents the error.
76 const int new_errno = ret == -1 ? errno : ret;
Eric Fiselier9778a6d2016-06-14 03:45:31 +000077 errno = old_errno;
78 if (new_errno == EINVAL) {
79 std::snprintf(buffer, strerror_buff_size, "Unknown error %d", ev);
80 return string(buffer);
81 } else {
82 assert(new_errno == ERANGE);
83 // FIXME maybe? 'strerror_buff_size' is likely to exceed the
84 // maximum error size so ERANGE shouldn't be returned.
85 std::abort();
86 }
87 }
88 return string(buffer);
89}
90#endif
91
92} // end namespace
93
Howard Hinnant3e519522010-05-11 19:42:16 +000094string
95__do_message::message(int ev) const
96{
Eric Fiselier9778a6d2016-06-14 03:45:31 +000097#if defined(_LIBCPP_HAS_NO_THREADS)
98 return string(::strerror(ev));
99#else
100 return do_strerror_r(ev);
101#endif
Howard Hinnant3e519522010-05-11 19:42:16 +0000102}
103
104class _LIBCPP_HIDDEN __generic_error_category
105 : public __do_message
106{
107public:
Howard Hinnanta62f2892011-05-26 19:48:01 +0000108 virtual const char* name() const _NOEXCEPT;
Howard Hinnant3e519522010-05-11 19:42:16 +0000109 virtual string message(int ev) const;
110};
111
112const char*
Howard Hinnanta62f2892011-05-26 19:48:01 +0000113__generic_error_category::name() const _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +0000114{
115 return "generic";
116}
117
118string
119__generic_error_category::message(int ev) const
120{
Jonathan Roelofsa409d592014-09-02 20:34:23 +0000121#ifdef _LIBCPP_ELAST
122 if (ev > _LIBCPP_ELAST)
Howard Hinnant128ba712010-05-24 17:49:41 +0000123 return string("unspecified generic_category error");
Jonathan Roelofsa409d592014-09-02 20:34:23 +0000124#endif // _LIBCPP_ELAST
Howard Hinnant128ba712010-05-24 17:49:41 +0000125 return __do_message::message(ev);
Howard Hinnant3e519522010-05-11 19:42:16 +0000126}
127
128const error_category&
Howard Hinnanta62f2892011-05-26 19:48:01 +0000129generic_category() _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +0000130{
131 static __generic_error_category s;
132 return s;
133}
134
135class _LIBCPP_HIDDEN __system_error_category
136 : public __do_message
137{
138public:
Howard Hinnanta62f2892011-05-26 19:48:01 +0000139 virtual const char* name() const _NOEXCEPT;
Howard Hinnant3e519522010-05-11 19:42:16 +0000140 virtual string message(int ev) const;
Howard Hinnanta62f2892011-05-26 19:48:01 +0000141 virtual error_condition default_error_condition(int ev) const _NOEXCEPT;
Howard Hinnant3e519522010-05-11 19:42:16 +0000142};
143
144const char*
Howard Hinnanta62f2892011-05-26 19:48:01 +0000145__system_error_category::name() const _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +0000146{
147 return "system";
148}
149
150string
151__system_error_category::message(int ev) const
152{
Jonathan Roelofsa409d592014-09-02 20:34:23 +0000153#ifdef _LIBCPP_ELAST
154 if (ev > _LIBCPP_ELAST)
Howard Hinnant128ba712010-05-24 17:49:41 +0000155 return string("unspecified system_category error");
Jonathan Roelofsa409d592014-09-02 20:34:23 +0000156#endif // _LIBCPP_ELAST
Howard Hinnant128ba712010-05-24 17:49:41 +0000157 return __do_message::message(ev);
Howard Hinnant3e519522010-05-11 19:42:16 +0000158}
159
160error_condition
Howard Hinnanta62f2892011-05-26 19:48:01 +0000161__system_error_category::default_error_condition(int ev) const _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +0000162{
Jonathan Roelofsa409d592014-09-02 20:34:23 +0000163#ifdef _LIBCPP_ELAST
164 if (ev > _LIBCPP_ELAST)
Howard Hinnant128ba712010-05-24 17:49:41 +0000165 return error_condition(ev, system_category());
Jonathan Roelofsa409d592014-09-02 20:34:23 +0000166#endif // _LIBCPP_ELAST
Howard Hinnant128ba712010-05-24 17:49:41 +0000167 return error_condition(ev, generic_category());
Howard Hinnant3e519522010-05-11 19:42:16 +0000168}
169
170const error_category&
Howard Hinnanta62f2892011-05-26 19:48:01 +0000171system_category() _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +0000172{
173 static __system_error_category s;
174 return s;
175}
176
177// error_condition
178
179string
180error_condition::message() const
181{
182 return __cat_->message(__val_);
183}
184
185// error_code
186
187string
188error_code::message() const
189{
190 return __cat_->message(__val_);
191}
192
193// system_error
194
195string
196system_error::__init(const error_code& ec, string what_arg)
197{
198 if (ec)
199 {
200 if (!what_arg.empty())
201 what_arg += ": ";
202 what_arg += ec.message();
203 }
Richard Trieu1c545ba2015-04-30 21:47:28 +0000204 return what_arg;
Howard Hinnant3e519522010-05-11 19:42:16 +0000205}
206
207system_error::system_error(error_code ec, const string& what_arg)
208 : runtime_error(__init(ec, what_arg)),
209 __ec_(ec)
210{
211}
212
213system_error::system_error(error_code ec, const char* what_arg)
214 : runtime_error(__init(ec, what_arg)),
215 __ec_(ec)
216{
217}
218
219system_error::system_error(error_code ec)
220 : runtime_error(__init(ec, "")),
221 __ec_(ec)
222{
223}
224
225system_error::system_error(int ev, const error_category& ecat, const string& what_arg)
226 : runtime_error(__init(error_code(ev, ecat), what_arg)),
227 __ec_(error_code(ev, ecat))
228{
229}
230
231system_error::system_error(int ev, const error_category& ecat, const char* what_arg)
232 : runtime_error(__init(error_code(ev, ecat), what_arg)),
233 __ec_(error_code(ev, ecat))
234{
235}
236
237system_error::system_error(int ev, const error_category& ecat)
238 : runtime_error(__init(error_code(ev, ecat), "")),
239 __ec_(error_code(ev, ecat))
240{
241}
242
Howard Hinnanta62f2892011-05-26 19:48:01 +0000243system_error::~system_error() _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +0000244{
245}
246
247void
248__throw_system_error(int ev, const char* what_arg)
249{
Howard Hinnant54b409f2010-08-11 17:04:31 +0000250#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant3e519522010-05-11 19:42:16 +0000251 throw system_error(error_code(ev, system_category()), what_arg);
Howard Hinnante00e6f22013-03-28 18:56:26 +0000252#else
253 (void)ev;
254 (void)what_arg;
Howard Hinnant54b409f2010-08-11 17:04:31 +0000255#endif
Howard Hinnant3e519522010-05-11 19:42:16 +0000256}
257
258_LIBCPP_END_NAMESPACE_STD