aboutsummaryrefslogtreecommitdiff
path: root/libbutl/utility.cxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2018-08-21 17:34:57 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2018-08-21 17:34:57 +0200
commitf8fc81a5c9fcd986473797df9286c6c9fef683bf (patch)
treed81b4a0c456f776bd40725efa372e81441d88196 /libbutl/utility.cxx
parent338a16f0df3c45bcbeaf5e7ffd0b4dc515e11502 (diff)
Add utility functions for throwing ios::failure
Diffstat (limited to 'libbutl/utility.cxx')
-rw-r--r--libbutl/utility.cxx63
1 files changed, 63 insertions, 0 deletions
diff --git a/libbutl/utility.cxx b/libbutl/utility.cxx
index 1212aa1..b572d69 100644
--- a/libbutl/utility.cxx
+++ b/libbutl/utility.cxx
@@ -18,6 +18,7 @@
#include <utility>
#include <ostream>
+#include <type_traits> // enable_if, is_base_of
#include <system_error>
#endif
@@ -90,6 +91,68 @@ namespace butl
#endif
}
+ // Throw ios::failure differently depending on whether it is derived from
+ // system_error.
+ //
+ template <bool v>
+ [[noreturn]] static inline typename enable_if<v>::type
+ throw_ios_failure (error_code e, const char* w)
+ {
+ // The idea here is to make an error code to be saved into failure
+ // exception and to make a string returned by what() to contain the error
+ // description plus an optional custom message if provided. Unfortunatelly
+ // there is no way to say that the custom message is absent. Passing an
+ // empty string results for libstdc++ (as of version 5.3.1) with a
+ // description like this (note the ': ' prefix):
+ //
+ // : No such file or directory
+ //
+ // Note that our custom operator<<(ostream, exception) strips this prefix.
+ //
+ throw ios_base::failure (w != nullptr ? w : "", e);
+ }
+
+ template <bool v>
+ [[noreturn]] static inline typename enable_if<!v>::type
+ throw_ios_failure (error_code e, const char* w)
+ {
+ throw ios_base::failure (w != nullptr ? w : e.message ().c_str ());
+ }
+
+ [[noreturn]] void
+ throw_generic_ios_failure (int errno_code, const char* w)
+ {
+ error_code ec (errno_code, generic_category ());
+ throw_ios_failure<is_base_of<system_error, ios_base::failure>::value> (
+ ec, w);
+ }
+
+ [[noreturn]] void
+ throw_system_ios_failure (int system_code, const char* w)
+ {
+#ifdef _WIN32
+ // Here we work around MinGW libstdc++ that interprets Windows system error
+ // codes (for example those returned by GetLastError()) as errno codes.
+ //
+ // Note that the resulting system_error description will have ': Success.'
+ // suffix that is stripped by our custom operator<<(ostream, exception).
+ //
+ error_code ec (0, system_category ());
+ string m;
+
+ if (w == nullptr)
+ {
+ m = win32::error_msg (system_code);
+ w = m.c_str ();
+ }
+#else
+ error_code ec (system_code, system_category ());
+#endif
+
+ throw_ios_failure<is_base_of<system_error, ios_base::failure>::value> (
+ ec, w);
+ }
+
string&
trim (string& l)
{