aboutsummaryrefslogtreecommitdiff
path: root/libbutl/utility.cxx
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2017-05-01 16:08:43 +0300
committerKaren Arutyunov <karen@codesynthesis.com>2017-05-01 16:59:24 +0300
commit61377c582e0f2675baa5f5e6e30a35d1a4164b33 (patch)
tree11cdca992834d7f7f197f72856712fbcb3020e3d /libbutl/utility.cxx
parent442c1a6790e52baa0c081f310d4d9e9b6f1ff638 (diff)
Add hxx extension for headers and lib prefix for library dir
Diffstat (limited to 'libbutl/utility.cxx')
-rw-r--r--libbutl/utility.cxx143
1 files changed, 143 insertions, 0 deletions
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 <libbutl/utility.hxx>
+
+#ifdef _WIN32
+# include <libbutl/win32-utility.hxx>
+#endif
+
+#include <string>
+#include <ostream>
+#include <system_error>
+
+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:
+ //
+ // <system_code description>: <fallback_errno_code description>
+ //
+ // 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;
+ }
+}