libcxx

libcxx mirror with random patches
git clone https://git.neptards.moe/neptards/libcxx.git
Log | Files | Refs

system_error.cpp (7049B)


      1 //===---------------------- system_error.cpp ------------------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is dual licensed under the MIT and the University of Illinois Open
      6 // Source Licenses. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #include "__config"
     11 
     12 #include "system_error"
     13 
     14 #include "include/config_elast.h"
     15 #include "cerrno"
     16 #include "cstring"
     17 #include "cstdio"
     18 #include "cstdlib"
     19 #include "string"
     20 #include "string.h"
     21 #include "__debug"
     22 
     23 #if defined(__ANDROID__)
     24 #include <android/api-level.h>
     25 #endif
     26 
     27 _LIBCPP_BEGIN_NAMESPACE_STD
     28 
     29 // class error_category
     30 
     31 #if defined(_LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS)
     32 error_category::error_category() _NOEXCEPT
     33 {
     34 }
     35 #endif
     36 
     37 error_category::~error_category() _NOEXCEPT
     38 {
     39 }
     40 
     41 error_condition
     42 error_category::default_error_condition(int ev) const _NOEXCEPT
     43 {
     44     return error_condition(ev, *this);
     45 }
     46 
     47 bool
     48 error_category::equivalent(int code, const error_condition& condition) const _NOEXCEPT
     49 {
     50     return default_error_condition(code) == condition;
     51 }
     52 
     53 bool
     54 error_category::equivalent(const error_code& code, int condition) const _NOEXCEPT
     55 {
     56     return *this == code.category() && code.value() == condition;
     57 }
     58 
     59 #if !defined(_LIBCPP_HAS_NO_THREADS)
     60 namespace {
     61 
     62 //  GLIBC also uses 1024 as the maximum buffer size internally.
     63 constexpr size_t strerror_buff_size = 1024;
     64 
     65 string do_strerror_r(int ev);
     66 
     67 #if defined(_LIBCPP_MSVCRT_LIKE) || defined(__vita__)
     68 string do_strerror_r(int ev) {
     69   char buffer[strerror_buff_size];
     70   if (::strerror_s(buffer, strerror_buff_size, ev) == 0)
     71     return string(buffer);
     72   std::snprintf(buffer, strerror_buff_size, "unknown error %d", ev);
     73   return string(buffer);
     74 }
     75 #else
     76 
     77 // Only one of the two following functions will be used, depending on
     78 // the return type of strerror_r:
     79 
     80 // For the GNU variant, a char* return value:
     81 __attribute__((unused)) const char *
     82 handle_strerror_r_return(char *strerror_return, char *buffer) {
     83   // GNU always returns a string pointer in its return value. The
     84   // string might point to either the input buffer, or a static
     85   // buffer, but we don't care which.
     86   return strerror_return;
     87 }
     88 
     89 // For the POSIX variant: an int return value.
     90 __attribute__((unused)) const char *
     91 handle_strerror_r_return(int strerror_return, char *buffer) {
     92   // The POSIX variant either:
     93   // - fills in the provided buffer and returns 0
     94   // - returns a positive error value, or
     95   // - returns -1 and fills in errno with an error value.
     96   if (strerror_return == 0)
     97     return buffer;
     98 
     99   // Only handle EINVAL. Other errors abort.
    100   int new_errno = strerror_return == -1 ? errno : strerror_return;
    101   if (new_errno == EINVAL)
    102     return "";
    103 
    104   _LIBCPP_ASSERT(new_errno == ERANGE, "unexpected error from ::strerror_r");
    105   // FIXME maybe? 'strerror_buff_size' is likely to exceed the
    106   // maximum error size so ERANGE shouldn't be returned.
    107   std::abort();
    108 }
    109 
    110 // This function handles both GNU and POSIX variants, dispatching to
    111 // one of the two above functions.
    112 string do_strerror_r(int ev) {
    113     char buffer[strerror_buff_size];
    114     // Preserve errno around the call. (The C++ standard requires that
    115     // system_error functions not modify errno).
    116     const int old_errno = errno;
    117     const char *error_message = handle_strerror_r_return(
    118         ::strerror_r(ev, buffer, strerror_buff_size), buffer);
    119     // If we didn't get any message, print one now.
    120     if (!error_message[0]) {
    121       std::snprintf(buffer, strerror_buff_size, "Unknown error %d", ev);
    122       error_message = buffer;
    123     }
    124     errno = old_errno;
    125     return string(error_message);
    126 }
    127 #endif
    128 } // end namespace
    129 #endif
    130 
    131 string
    132 __do_message::message(int ev) const
    133 {
    134 #if defined(_LIBCPP_HAS_NO_THREADS)
    135     return string(::strerror(ev));
    136 #else
    137     return do_strerror_r(ev);
    138 #endif
    139 }
    140 
    141 class _LIBCPP_HIDDEN __generic_error_category
    142     : public __do_message
    143 {
    144 public:
    145     virtual const char* name() const _NOEXCEPT;
    146     virtual string message(int ev) const;
    147 };
    148 
    149 const char*
    150 __generic_error_category::name() const _NOEXCEPT
    151 {
    152     return "generic";
    153 }
    154 
    155 string
    156 __generic_error_category::message(int ev) const
    157 {
    158 #ifdef _LIBCPP_ELAST
    159     if (ev > _LIBCPP_ELAST)
    160       return string("unspecified generic_category error");
    161 #endif  // _LIBCPP_ELAST
    162     return __do_message::message(ev);
    163 }
    164 
    165 const error_category&
    166 generic_category() _NOEXCEPT
    167 {
    168     static __generic_error_category s;
    169     return s;
    170 }
    171 
    172 class _LIBCPP_HIDDEN __system_error_category
    173     : public __do_message
    174 {
    175 public:
    176     virtual const char* name() const _NOEXCEPT;
    177     virtual string message(int ev) const;
    178     virtual error_condition default_error_condition(int ev) const _NOEXCEPT;
    179 };
    180 
    181 const char*
    182 __system_error_category::name() const _NOEXCEPT
    183 {
    184     return "system";
    185 }
    186 
    187 string
    188 __system_error_category::message(int ev) const
    189 {
    190 #ifdef _LIBCPP_ELAST
    191     if (ev > _LIBCPP_ELAST)
    192       return string("unspecified system_category error");
    193 #endif  // _LIBCPP_ELAST
    194     return __do_message::message(ev);
    195 }
    196 
    197 error_condition
    198 __system_error_category::default_error_condition(int ev) const _NOEXCEPT
    199 {
    200 #ifdef _LIBCPP_ELAST
    201     if (ev > _LIBCPP_ELAST)
    202       return error_condition(ev, system_category());
    203 #endif  // _LIBCPP_ELAST
    204     return error_condition(ev, generic_category());
    205 }
    206 
    207 const error_category&
    208 system_category() _NOEXCEPT
    209 {
    210     static __system_error_category s;
    211     return s;
    212 }
    213 
    214 // error_condition
    215 
    216 string
    217 error_condition::message() const
    218 {
    219     return __cat_->message(__val_);
    220 }
    221 
    222 // error_code
    223 
    224 string
    225 error_code::message() const
    226 {
    227     return __cat_->message(__val_);
    228 }
    229 
    230 // system_error
    231 
    232 string
    233 system_error::__init(const error_code& ec, string what_arg)
    234 {
    235     if (ec)
    236     {
    237         if (!what_arg.empty())
    238             what_arg += ": ";
    239         what_arg += ec.message();
    240     }
    241     return what_arg;
    242 }
    243 
    244 system_error::system_error(error_code ec, const string& what_arg)
    245     : runtime_error(__init(ec, what_arg)),
    246       __ec_(ec)
    247 {
    248 }
    249 
    250 system_error::system_error(error_code ec, const char* what_arg)
    251     : runtime_error(__init(ec, what_arg)),
    252       __ec_(ec)
    253 {
    254 }
    255 
    256 system_error::system_error(error_code ec)
    257     : runtime_error(__init(ec, "")),
    258       __ec_(ec)
    259 {
    260 }
    261 
    262 system_error::system_error(int ev, const error_category& ecat, const string& what_arg)
    263     : runtime_error(__init(error_code(ev, ecat), what_arg)),
    264       __ec_(error_code(ev, ecat))
    265 {
    266 }
    267 
    268 system_error::system_error(int ev, const error_category& ecat, const char* what_arg)
    269     : runtime_error(__init(error_code(ev, ecat), what_arg)),
    270       __ec_(error_code(ev, ecat))
    271 {
    272 }
    273 
    274 system_error::system_error(int ev, const error_category& ecat)
    275     : runtime_error(__init(error_code(ev, ecat), "")),
    276       __ec_(error_code(ev, ecat))
    277 {
    278 }
    279 
    280 system_error::~system_error() _NOEXCEPT
    281 {
    282 }
    283 
    284 void
    285 __throw_system_error(int ev, const char* what_arg)
    286 {
    287 #ifndef _LIBCPP_NO_EXCEPTIONS
    288     throw system_error(error_code(ev, system_category()), what_arg);
    289 #else
    290     (void)ev;
    291     (void)what_arg;
    292     _VSTD::abort();
    293 #endif
    294 }
    295 
    296 _LIBCPP_END_NAMESPACE_STD