From f8fc81a5c9fcd986473797df9286c6c9fef683bf Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Tue, 21 Aug 2018 17:34:57 +0200 Subject: Add utility functions for throwing ios::failure --- libbutl/utility.cxx | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) (limited to 'libbutl/utility.cxx') 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 #include +#include // enable_if, is_base_of #include #endif @@ -90,6 +91,68 @@ namespace butl #endif } + // Throw ios::failure differently depending on whether it is derived from + // system_error. + // + template + [[noreturn]] static inline typename enable_if::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 + [[noreturn]] static inline typename enable_if::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::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::value> ( + ec, w); + } + string& trim (string& l) { -- cgit v1.1