blob: 885afd18ce371ae47fc957cc746ac00789e54910 [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 Fiselier61df7902016-06-14 06:08:10 +000073 int ret;
74 if ((ret = ::strerror_r(ev, buffer, strerror_buff_size)) != 0) {
Eric Fiselier79e05742016-06-14 06:03:20 +000075 // If `ret == -1` then the error is specified using `errno`, otherwise
76 // `ret` represents the error.
77 const int new_errno = ret == -1 ? errno : ret;
Eric Fiselier9778a6d2016-06-14 03:45:31 +000078 errno = old_errno;
79 if (new_errno == EINVAL) {
80 std::snprintf(buffer, strerror_buff_size, "Unknown error %d", ev);
81 return string(buffer);
82 } else {
83 assert(new_errno == ERANGE);
84 // FIXME maybe? 'strerror_buff_size' is likely to exceed the
85 // maximum error size so ERANGE shouldn't be returned.
86 std::abort();
87 }
88 }
89 return string(buffer);
90}
91#endif
92
93} // end namespace
94
Howard Hinnant3e519522010-05-11 19:42:16 +000095string
96__do_message::message(int ev) const
97{
Eric Fiselier9778a6d2016-06-14 03:45:31 +000098#if defined(_LIBCPP_HAS_NO_THREADS)
99 return string(::strerror(ev));
100#else
101 return do_strerror_r(ev);
102#endif
Howard Hinnant3e519522010-05-11 19:42:16 +0000103}
104
105class _LIBCPP_HIDDEN __generic_error_category
106 : public __do_message
107{
108public:
Howard Hinnanta62f2892011-05-26 19:48:01 +0000109 virtual const char* name() const _NOEXCEPT;
Howard Hinnant3e519522010-05-11 19:42:16 +0000110 virtual string message(int ev) const;
111};
112
113const char*
Howard Hinnanta62f2892011-05-26 19:48:01 +0000114__generic_error_category::name() const _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +0000115{
116 return "generic";
117}
118
119string
120__generic_error_category::message(int ev) const
121{
Jonathan Roelofsa409d592014-09-02 20:34:23 +0000122#ifdef _LIBCPP_ELAST
123 if (ev > _LIBCPP_ELAST)
Howard Hinnant128ba712010-05-24 17:49:41 +0000124 return string("unspecified generic_category error");
Jonathan Roelofsa409d592014-09-02 20:34:23 +0000125#endif // _LIBCPP_ELAST
Howard Hinnant128ba712010-05-24 17:49:41 +0000126 return __do_message::message(ev);
Howard Hinnant3e519522010-05-11 19:42:16 +0000127}
128
129const error_category&
Howard Hinnanta62f2892011-05-26 19:48:01 +0000130generic_category() _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +0000131{
132 static __generic_error_category s;
133 return s;
134}
135
136class _LIBCPP_HIDDEN __system_error_category
137 : public __do_message
138{
139public:
Howard Hinnanta62f2892011-05-26 19:48:01 +0000140 virtual const char* name() const _NOEXCEPT;
Howard Hinnant3e519522010-05-11 19:42:16 +0000141 virtual string message(int ev) const;
Howard Hinnanta62f2892011-05-26 19:48:01 +0000142 virtual error_condition default_error_condition(int ev) const _NOEXCEPT;
Howard Hinnant3e519522010-05-11 19:42:16 +0000143};
144
145const char*
Howard Hinnanta62f2892011-05-26 19:48:01 +0000146__system_error_category::name() const _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +0000147{
148 return "system";
149}
150
151string
152__system_error_category::message(int ev) const
153{
Jonathan Roelofsa409d592014-09-02 20:34:23 +0000154#ifdef _LIBCPP_ELAST
155 if (ev > _LIBCPP_ELAST)
Howard Hinnant128ba712010-05-24 17:49:41 +0000156 return string("unspecified system_category error");
Jonathan Roelofsa409d592014-09-02 20:34:23 +0000157#endif // _LIBCPP_ELAST
Howard Hinnant128ba712010-05-24 17:49:41 +0000158 return __do_message::message(ev);
Howard Hinnant3e519522010-05-11 19:42:16 +0000159}
160
161error_condition
Howard Hinnanta62f2892011-05-26 19:48:01 +0000162__system_error_category::default_error_condition(int ev) const _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +0000163{
Jonathan Roelofsa409d592014-09-02 20:34:23 +0000164#ifdef _LIBCPP_ELAST
165 if (ev > _LIBCPP_ELAST)
Howard Hinnant128ba712010-05-24 17:49:41 +0000166 return error_condition(ev, system_category());
Jonathan Roelofsa409d592014-09-02 20:34:23 +0000167#endif // _LIBCPP_ELAST
Howard Hinnant128ba712010-05-24 17:49:41 +0000168 return error_condition(ev, generic_category());
Howard Hinnant3e519522010-05-11 19:42:16 +0000169}
170
171const error_category&
Howard Hinnanta62f2892011-05-26 19:48:01 +0000172system_category() _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +0000173{
174 static __system_error_category s;
175 return s;
176}
177
178// error_condition
179
180string
181error_condition::message() const
182{
183 return __cat_->message(__val_);
184}
185
186// error_code
187
188string
189error_code::message() const
190{
191 return __cat_->message(__val_);
192}
193
194// system_error
195
196string
197system_error::__init(const error_code& ec, string what_arg)
198{
199 if (ec)
200 {
201 if (!what_arg.empty())
202 what_arg += ": ";
203 what_arg += ec.message();
204 }
Richard Trieu1c545ba2015-04-30 21:47:28 +0000205 return what_arg;
Howard Hinnant3e519522010-05-11 19:42:16 +0000206}
207
208system_error::system_error(error_code ec, const string& what_arg)
209 : runtime_error(__init(ec, what_arg)),
210 __ec_(ec)
211{
212}
213
214system_error::system_error(error_code ec, const char* what_arg)
215 : runtime_error(__init(ec, what_arg)),
216 __ec_(ec)
217{
218}
219
220system_error::system_error(error_code ec)
221 : runtime_error(__init(ec, "")),
222 __ec_(ec)
223{
224}
225
226system_error::system_error(int ev, const error_category& ecat, const string& what_arg)
227 : runtime_error(__init(error_code(ev, ecat), what_arg)),
228 __ec_(error_code(ev, ecat))
229{
230}
231
232system_error::system_error(int ev, const error_category& ecat, const char* what_arg)
233 : runtime_error(__init(error_code(ev, ecat), what_arg)),
234 __ec_(error_code(ev, ecat))
235{
236}
237
238system_error::system_error(int ev, const error_category& ecat)
239 : runtime_error(__init(error_code(ev, ecat), "")),
240 __ec_(error_code(ev, ecat))
241{
242}
243
Howard Hinnanta62f2892011-05-26 19:48:01 +0000244system_error::~system_error() _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +0000245{
246}
247
248void
249__throw_system_error(int ev, const char* what_arg)
250{
Howard Hinnant54b409f2010-08-11 17:04:31 +0000251#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant3e519522010-05-11 19:42:16 +0000252 throw system_error(error_code(ev, system_category()), what_arg);
Howard Hinnante00e6f22013-03-28 18:56:26 +0000253#else
254 (void)ev;
255 (void)what_arg;
Howard Hinnant54b409f2010-08-11 17:04:31 +0000256#endif
Howard Hinnant3e519522010-05-11 19:42:16 +0000257}
258
259_LIBCPP_END_NAMESPACE_STD