From 32231fdb5273dd2a812c61549d6c0e681c0f5d59 Mon Sep 17 00:00:00 2001 From: Jonathan Lebon Date: Thu, 11 May 2017 10:48:30 -0400 Subject: glnx-errors.h: add a glnx_throw_prefix() variant For completeness. It just looks much cleaner than doing the `, FALSE` trick. It also takes care of appending the ': ' for you like its errno version. --- glnx-errors.c | 24 ++++++++++++++++++------ glnx-errors.h | 37 ++++++++++++++++++++++++++++++++++--- tests/test-libglnx-errors.c | 7 +++++++ 3 files changed, 59 insertions(+), 9 deletions(-) diff --git a/glnx-errors.c b/glnx-errors.c index edbce20..4800873 100644 --- a/glnx-errors.c +++ b/glnx-errors.c @@ -23,6 +23,22 @@ #include #include +void +glnx_real_set_prefix_error_va (GError *error, + const char *format, + va_list args) +{ + if (error == NULL) + return; + + g_autofree char *old_msg = g_steal_pointer (&error->message); + g_autoptr(GString) buf = g_string_new (""); + g_string_append_vprintf (buf, format, args); + g_string_append (buf, ": "); + g_string_append (buf, old_msg); + error->message = g_string_free (g_steal_pointer (&buf), FALSE); +} + void glnx_real_set_prefix_error_from_errno_va (GError **error, gint errsv, @@ -32,13 +48,9 @@ glnx_real_set_prefix_error_from_errno_va (GError **error, if (!error) return; - /* TODO - enhance GError to have a "set and take ownership" API */ - g_autoptr(GString) buf = g_string_new (""); - g_string_append_vprintf (buf, format, args); - g_string_append (buf, ": "); - g_string_append (buf, g_strerror (errsv)); g_set_error_literal (error, G_IO_ERROR, g_io_error_from_errno (errsv), - buf->str); + g_strerror (errsv)); + glnx_real_set_prefix_error_va (*error, format, args); } diff --git a/glnx-errors.h b/glnx-errors.h index 2f6b962..e26a513 100644 --- a/glnx-errors.h +++ b/glnx-errors.h @@ -30,7 +30,7 @@ G_BEGIN_DECLS * This function returns %FALSE so it can be used conveniently in a single * statement: * - * `` + * ``` * if (strcmp (foo, "somevalue") != 0) * return glnx_throw (error, "key must be somevalue, not '%s'", foo); * ``` @@ -49,16 +49,47 @@ glnx_throw (GError **error, const char *fmt, ...) return FALSE; } -/* Like glnx_throw(), but yields a NULL pointer. */ +/* Like `glnx_throw ()`, but returns %NULL. */ #define glnx_null_throw(error, args...) \ ({glnx_throw (error, args); NULL;}) +/* Implementation detail of glnx_throw_prefix() */ +void glnx_real_set_prefix_error_va (GError *error, + const char *format, + va_list args) G_GNUC_PRINTF (2,0); + +/* Prepend to @error's message by `$prefix: ` where `$prefix` is computed via + * printf @fmt. Returns %FALSE so it can be used conveniently in a single + * statement: + * + * ``` + * if (!function_that_fails (s, error)) + * return glnx_throw_prefix (error, "while handling '%s'", s); + * ``` + * */ +static inline gboolean G_GNUC_PRINTF (2,3) +glnx_prefix_error (GError **error, const char *fmt, ...) +{ + if (error == NULL) + return FALSE; + + va_list args; + va_start (args, fmt); + glnx_real_set_prefix_error_va (*error, fmt, args); + va_end (args); + return FALSE; +} + +/* Like `glnx_prefix_error ()`, but returns %NULL. */ +#define glnx_prefix_error_null(error, args...) \ + ({glnx_prefix_error (error, args); NULL;}) + /* Set @error using the value of `g_strerror (errno)`. * * This function returns %FALSE so it can be used conveniently in a single * statement: * - * `` + * ``` * if (unlinkat (fd, somepathname) < 0) * return glnx_throw_errno (error); * ``` diff --git a/tests/test-libglnx-errors.c b/tests/test-libglnx-errors.c index 7950244..721818b 100644 --- a/tests/test-libglnx-errors.c +++ b/tests/test-libglnx-errors.c @@ -60,6 +60,9 @@ test_error_errno (void) { g_assert (!glnx_throw_errno (&error)); g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND); + g_assert (!glnx_prefix_error (&error, "myprefix")); + g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND); + g_assert (g_str_has_prefix (error->message, "myprefix: ")); g_clear_error (&error); } else @@ -71,6 +74,10 @@ test_error_errno (void) gpointer dummy = glnx_null_throw_errno (&error); g_assert (dummy == NULL); g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND); + dummy = glnx_prefix_error_null (&error, "myprefix"); + g_assert (dummy == NULL); + g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND); + g_assert (g_str_has_prefix (error->message, "myprefix: ")); g_clear_error (&error); } else -- cgit v1.2.1