blob: 748b5f7bbd076f1f69aacd711015748d3635279e [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;
73 if (::strerror_r(ev, buffer, strerror_buff_size) == -1) {
74 const int new_errno = errno;
75 errno = old_errno;
76 if (new_errno == EINVAL) {
77 std::snprintf(buffer, strerror_buff_size, "Unknown error %d", ev);
78 return string(buffer);
79 } else {
80 assert(new_errno == ERANGE);
81 // FIXME maybe? 'strerror_buff_size' is likely to exceed the
82 // maximum error size so ERANGE shouldn't be returned.
83 std::abort();
84 }
85 }
86 return string(buffer);
87}
88#endif
89
90} // end namespace
91
Howard Hinnant3e519522010-05-11 19:42:16 +000092string
93__do_message::message(int ev) const
94{
Eric Fiselier9778a6d2016-06-14 03:45:31 +000095#if defined(_LIBCPP_HAS_NO_THREADS)
96 return string(::strerror(ev));
97#else
98 return do_strerror_r(ev);
99#endif
Howard Hinnant3e519522010-05-11 19:42:16 +0000100}
101
102class _LIBCPP_HIDDEN __generic_error_category
103 : public __do_message
104{
105public:
Howard Hinnanta62f2892011-05-26 19:48:01 +0000106 virtual const char* name() const _NOEXCEPT;
Howard Hinnant3e519522010-05-11 19:42:16 +0000107 virtual string message(int ev) const;
108};
109
110const char*
Howard Hinnanta62f2892011-05-26 19:48:01 +0000111__generic_error_category::name() const _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +0000112{
113 return "generic";
114}
115
116string
117__generic_error_category::message(int ev) const
118{
Jonathan Roelofsa409d592014-09-02 20:34:23 +0000119#ifdef _LIBCPP_ELAST
120 if (ev > _LIBCPP_ELAST)
Howard Hinnant128ba712010-05-24 17:49:41 +0000121 return string("unspecified generic_category error");
Jonathan Roelofsa409d592014-09-02 20:34:23 +0000122#endif // _LIBCPP_ELAST
Howard Hinnant128ba712010-05-24 17:49:41 +0000123 return __do_message::message(ev);
Howard Hinnant3e519522010-05-11 19:42:16 +0000124}
125
126const error_category&
Howard Hinnanta62f2892011-05-26 19:48:01 +0000127generic_category() _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +0000128{
129 static __generic_error_category s;
130 return s;
131}
132
133class _LIBCPP_HIDDEN __system_error_category
134 : public __do_message
135{
136public:
Howard Hinnanta62f2892011-05-26 19:48:01 +0000137 virtual const char* name() const _NOEXCEPT;
Howard Hinnant3e519522010-05-11 19:42:16 +0000138 virtual string message(int ev) const;
Howard Hinnanta62f2892011-05-26 19:48:01 +0000139 virtual error_condition default_error_condition(int ev) const _NOEXCEPT;
Howard Hinnant3e519522010-05-11 19:42:16 +0000140};
141
142const char*
Howard Hinnanta62f2892011-05-26 19:48:01 +0000143__system_error_category::name() const _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +0000144{
145 return "system";
146}
147
148string
149__system_error_category::message(int ev) const
150{
Jonathan Roelofsa409d592014-09-02 20:34:23 +0000151#ifdef _LIBCPP_ELAST
152 if (ev > _LIBCPP_ELAST)
Howard Hinnant128ba712010-05-24 17:49:41 +0000153 return string("unspecified system_category error");
Jonathan Roelofsa409d592014-09-02 20:34:23 +0000154#endif // _LIBCPP_ELAST
Howard Hinnant128ba712010-05-24 17:49:41 +0000155 return __do_message::message(ev);
Howard Hinnant3e519522010-05-11 19:42:16 +0000156}
157
158error_condition
Howard Hinnanta62f2892011-05-26 19:48:01 +0000159__system_error_category::default_error_condition(int ev) const _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +0000160{
Jonathan Roelofsa409d592014-09-02 20:34:23 +0000161#ifdef _LIBCPP_ELAST
162 if (ev > _LIBCPP_ELAST)
Howard Hinnant128ba712010-05-24 17:49:41 +0000163 return error_condition(ev, system_category());
Jonathan Roelofsa409d592014-09-02 20:34:23 +0000164#endif // _LIBCPP_ELAST
Howard Hinnant128ba712010-05-24 17:49:41 +0000165 return error_condition(ev, generic_category());
Howard Hinnant3e519522010-05-11 19:42:16 +0000166}
167
168const error_category&
Howard Hinnanta62f2892011-05-26 19:48:01 +0000169system_category() _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +0000170{
171 static __system_error_category s;
172 return s;
173}
174
175// error_condition
176
177string
178error_condition::message() const
179{
180 return __cat_->message(__val_);
181}
182
183// error_code
184
185string
186error_code::message() const
187{
188 return __cat_->message(__val_);
189}
190
191// system_error
192
193string
194system_error::__init(const error_code& ec, string what_arg)
195{
196 if (ec)
197 {
198 if (!what_arg.empty())
199 what_arg += ": ";
200 what_arg += ec.message();
201 }
Richard Trieu1c545ba2015-04-30 21:47:28 +0000202 return what_arg;
Howard Hinnant3e519522010-05-11 19:42:16 +0000203}
204
205system_error::system_error(error_code ec, const string& what_arg)
206 : runtime_error(__init(ec, what_arg)),
207 __ec_(ec)
208{
209}
210
211system_error::system_error(error_code ec, const char* what_arg)
212 : runtime_error(__init(ec, what_arg)),
213 __ec_(ec)
214{
215}
216
217system_error::system_error(error_code ec)
218 : runtime_error(__init(ec, "")),
219 __ec_(ec)
220{
221}
222
223system_error::system_error(int ev, const error_category& ecat, const string& what_arg)
224 : runtime_error(__init(error_code(ev, ecat), what_arg)),
225 __ec_(error_code(ev, ecat))
226{
227}
228
229system_error::system_error(int ev, const error_category& ecat, const char* what_arg)
230 : runtime_error(__init(error_code(ev, ecat), what_arg)),
231 __ec_(error_code(ev, ecat))
232{
233}
234
235system_error::system_error(int ev, const error_category& ecat)
236 : runtime_error(__init(error_code(ev, ecat), "")),
237 __ec_(error_code(ev, ecat))
238{
239}
240
Howard Hinnanta62f2892011-05-26 19:48:01 +0000241system_error::~system_error() _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +0000242{
243}
244
245void
246__throw_system_error(int ev, const char* what_arg)
247{
Howard Hinnant54b409f2010-08-11 17:04:31 +0000248#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant3e519522010-05-11 19:42:16 +0000249 throw system_error(error_code(ev, system_category()), what_arg);
Howard Hinnante00e6f22013-03-28 18:56:26 +0000250#else
251 (void)ev;
252 (void)what_arg;
Howard Hinnant54b409f2010-08-11 17:04:31 +0000253#endif
Howard Hinnant3e519522010-05-11 19:42:16 +0000254}
255
256_LIBCPP_END_NAMESPACE_STD