From 61377c582e0f2675baa5f5e6e30a35d1a4164b33 Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Mon, 1 May 2017 16:08:43 +0300 Subject: Add hxx extension for headers and lib prefix for library dir --- libbutl/utility.cxx | 143 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 libbutl/utility.cxx (limited to 'libbutl/utility.cxx') diff --git a/libbutl/utility.cxx b/libbutl/utility.cxx new file mode 100644 index 0000000..8ce2cbc --- /dev/null +++ b/libbutl/utility.cxx @@ -0,0 +1,143 @@ +// file : libbutl/utility.cxx -*- C++ -*- +// copyright : Copyright (c) 2014-2017 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#include + +#ifdef _WIN32 +# include +#endif + +#include +#include +#include + +namespace butl +{ + using namespace std; + +#ifndef __cpp_lib_uncaught_exceptions + +#ifdef __cpp_thread_local + thread_local +#else + __thread +#endif + bool exception_unwinding_dtor_ = false; + +#ifdef _WIN32 + bool& + exception_unwinding_dtor () {return exception_unwinding_dtor_;} +#endif + +#endif + + [[noreturn]] void + throw_generic_error (int errno_code, const char* what) + { + if (what == nullptr) + throw system_error (errno_code, generic_category ()); + else + throw system_error (errno_code, generic_category (), what); + } + + [[noreturn]] void +#ifndef _WIN32 + throw_system_error (int system_code, int) + { + throw system_error (system_code, system_category ()); +#else + throw_system_error (int system_code, int fallback_errno_code) + { + // Here we work around MinGW libstdc++ that interprets Windows system error + // codes (for example those returned by GetLastError()) as errno codes. The + // resulting system_error description will have the following form: + // + // : + // + // Also note that the fallback-related description suffix is stripped by + // our custom operator<<(ostream, exception) for the common case (see + // below). + // + throw system_error (fallback_errno_code, + system_category (), + win32::error_msg (system_code)); +#endif + } +} + +namespace std +{ + using namespace butl; + + ostream& + operator<< (ostream& o, const exception& e) + { + const char* d (e.what ()); + const char* s (d); + + // Strip the leading junk (colons and spaces). + // + // Note that error descriptions for ios_base::failure exceptions thrown by + // fdstream can have the ': ' prefix for libstdc++ (read more in comment + // for throw_ios_failure()). + // + for (; *s == ' ' || *s == ':'; ++s) ; + + // Strip the trailing junk (periods, spaces, newlines). + // + // Note that msvcrt adds some junk like this: + // + // Invalid data.\r\n + // + size_t n (string::traits_type::length (s)); + for (; n > 0; --n) + { + switch (s[n-1]) + { + case '\r': + case '\n': + case '.': + case ' ': continue; + } + + break; + } + + // Strip the suffix for system_error thrown by + // throw_system_error(system_code) on Windows. For example for the + // ERROR_INVALID_DATA error code the original description will be + // 'Invalid data. : Success' for MinGW libstdc++ and + // 'Invalid data. : Success.' for msvcrt. + // + if (n >= 11 && + string::traits_type::compare (s + n - 11, ". : Success", 11) == 0) + n -= 11; + + // Lower-case the first letter if the beginning looks like a word (the + // second character is the lower-case letter or space). + // + char c; + bool lc (n > 0 && alpha (c = s[0]) && c == ucase (c) && + (n == 1 || (alpha (c = s[1]) && c == lcase (c)) || c == ' ')); + + // Print the description as is if no adjustment is required. + // + if (!lc && s == d && s[n] == '\0') + o << d; + else + { + // We need to produce the resulting description and then write it + // with a single formatted output operation. + // + string r (s, n); + + if (lc) + r[0] = lcase (r[0]); + + o << r; + } + + return o; + } +} -- cgit v1.1