[vte] lib: Add GError convenience class



commit f3f7fd4e1b550e22fd6f92d9c5579d23ade81f4c
Author: Christian Persch <chpe src gnome org>
Date:   Sun Dec 1 22:58:51 2019 +0100

    lib: Add GError convenience class

 src/app/app.cc      | 90 ++++++++++++++++++++++++-----------------------------
 src/app/meson.build |  2 +-
 src/decoder-cat.cc  |  8 ++---
 src/glib-glue.hh    | 59 +++++++++++++++++++++++++++++++++++
 src/meson.build     | 14 ++++++---
 src/parser-cat.cc   |  8 ++---
 src/pty.cc          | 15 ++++-----
 src/vtegtk.cc       | 14 +++------
 8 files changed, 130 insertions(+), 80 deletions(-)
---
diff --git a/src/app/app.cc b/src/app/app.cc
index 495e3f41..0a66ad00 100644
--- a/src/app/app.cc
+++ b/src/app/app.cc
@@ -32,6 +32,7 @@
 #include <cairo/cairo-gobject.h>
 #include <vte/vte.h>
 #include "vtepcre2.h"
+#include "glib-glue.hh"
 
 #include <algorithm>
 
@@ -512,12 +513,11 @@ static void
 jit_regex(VteRegex* regex,
           char const* pattern)
 {
-        GError *err = nullptr;
-        if (!vte_regex_jit(regex, PCRE2_JIT_COMPLETE, &err) ||
-            !vte_regex_jit(regex, PCRE2_JIT_PARTIAL_SOFT, &err)) {
-                if (!g_error_matches(err, VTE_REGEX_ERROR, -45 /* PCRE2_ERROR_JIT_BADOPTION: JIT not 
supported */))
-                        verbose_printerr("JITing regex \"%s\" failed: %s\n", pattern, err->message);
-                g_error_free(err);
+        auto error = vte::glib::Error{};
+        if (!vte_regex_jit(regex, PCRE2_JIT_COMPLETE, error) ||
+            !vte_regex_jit(regex, PCRE2_JIT_PARTIAL_SOFT, error)) {
+                if (!error.matches(VTE_REGEX_ERROR, -45 /* PCRE2_ERROR_JIT_BADOPTION: JIT not supported */))
+                        verbose_printerr("JITing regex \"%s\" failed: %s\n", pattern, error.message());
         }
 }
 
@@ -637,22 +637,20 @@ vteapp_search_popover_update_regex(VteappSearchPopover* popover)
         popover->regex_pattern = nullptr;
 
         if (search_text[0] != '\0') {
-                GError* error = nullptr;
-
-                auto regex = compile_regex_for_search(pattern, caseless, &error);
+                auto error = vte::glib::Error{};
+                auto regex = compile_regex_for_search(pattern, caseless, error);
                 vte_terminal_search_set_regex(popover->terminal, regex, 0);
                 if (regex != nullptr)
                         vte_regex_unref(regex);
 
-                if (error == nullptr) {
+                if (error.error()) {
                         popover->has_regex = true;
                         popover->regex_pattern = pattern; /* adopt */
                         pattern = nullptr; /* adopted */
                         gtk_widget_set_tooltip_text(popover->search_entry, nullptr);
                 } else {
                         popover->has_regex = false;
-                        gtk_widget_set_tooltip_text(popover->search_entry, error->message);
-                        g_error_free(error);
+                        gtk_widget_set_tooltip_text(popover->search_entry, error.message());
                 }
         }
 
@@ -987,17 +985,17 @@ vteapp_window_add_dingus(VteappWindow* window,
                          char const* const* dingus)
 {
         for (auto i = 0; dingus[i] != nullptr; i++) {
-                int tag = -1;
-                GError* error = nullptr;
-                auto regex = compile_regex_for_match(dingus[i], true, &error);
+                auto tag = int{-1};
+                auto error = vte::glib::Error{};
+                auto regex = compile_regex_for_match(dingus[i], true, error);
                 if (regex) {
                         tag = vte_terminal_match_add_regex(window->terminal, regex, 0);
                         vte_regex_unref(regex);
                 }
 
-                if (error != nullptr) {
-                        verbose_printerr("Failed to compile regex \"%s\": %s\n", dingus[i], error->message);
-                        g_error_free(error);
+                if (error.error()) {
+                        verbose_printerr("Failed to compile regex \"%s\": %s\n",
+                                         dingus[i], error.message());
                 }
 
                 if (tag != -1)
@@ -1298,22 +1296,20 @@ vteapp_window_fork(VteappWindow* window,
 static void
 vteapp_window_launch(VteappWindow* window)
 {
-        bool rv;
-        GError* err = nullptr;
+        auto rv = bool{};
+        auto error = vte::glib::Error{};
 
         if (options.exec_argv != nullptr)
-                rv = vteapp_window_launch_argv(window, options.exec_argv, &err);
+                rv = vteapp_window_launch_argv(window, options.exec_argv, error);
         else if (options.command != nullptr)
-                rv = vteapp_window_launch_commandline(window, options.command, &err);
+                rv = vteapp_window_launch_commandline(window, options.command, error);
         else if (!options.no_shell)
-                rv = vteapp_window_launch_shell(window, &err);
+                rv = vteapp_window_launch_shell(window, error);
         else
-                rv = vteapp_window_fork(window, &err);
+                rv = vteapp_window_fork(window, error);
 
-        if (!rv) {
-                verbose_printerr("Error launching: %s\n", err->message);
-                g_error_free(err);
-        }
+        if (!rv)
+                verbose_printerr("Error launching: %s\n", error.message());
 }
 
 static void
@@ -1460,9 +1456,9 @@ vteapp_window_show_context_menu(VteappWindow* window,
                 static const char extra_pattern[] = "(\\d+)\\s*(\\w+)";
                 char* extra_match = nullptr;
                 char *extra_subst = nullptr;
-                GError* err = nullptr;
-                auto regex = compile_regex_for_match(extra_pattern, false, &err);
-                g_assert_no_error(err);
+                auto error = vte::glib::Error{};
+                auto regex = compile_regex_for_match(extra_pattern, false, error);
+                error.assert_no_error();
                 vte_terminal_event_check_regex_simple(window->terminal, event,
                                                       &regex, 1, 0,
                                                       &extra_match);
@@ -1471,9 +1467,8 @@ vteapp_window_show_context_menu(VteappWindow* window,
                     (extra_subst = vte_regex_substitute(regex, extra_match, "$2 $1",
                                                         PCRE2_SUBSTITUTE_EXTENDED |
                                                         PCRE2_SUBSTITUTE_GLOBAL,
-                                                        &err)) == nullptr) {
-                        verbose_printerr("Substitution failed: %s\n", err->message);
-                        g_error_free(err);
+                                                        error)) == nullptr) {
+                        verbose_printerr("Substitution failed: %s\n", error.message());
                 }
 
                 vte_regex_unref(regex);
@@ -1546,22 +1541,20 @@ window_child_exited_cb(VteTerminal* term,
 
         if (options.output_filename != nullptr) {
                 auto file = g_file_new_for_commandline_arg(options.output_filename);
-
-                GError* err = nullptr;
-                auto stream = g_file_replace(file, nullptr, false, G_FILE_CREATE_NONE, nullptr, &err);
+                auto error = vte::glib::Error{};
+                auto stream = g_file_replace(file, nullptr, false, G_FILE_CREATE_NONE, nullptr, error);
                 g_object_unref(file);
                 if (stream != nullptr) {
                         vte_terminal_write_contents_sync(window->terminal,
                                                          G_OUTPUT_STREAM(stream),
                                                          VTE_WRITE_DEFAULT,
-                                                         nullptr, &err);
+                                                         nullptr, error);
                         g_object_unref(stream);
                 }
 
-                if (err != nullptr) {
+                if (error.error()) {
                         verbose_printerr("Failed to write output to \"%s\": %s\n",
-                                         options.output_filename, err->message);
-                        g_error_free(err);
+                                         options.output_filename, error.message());
                 }
         }
 
@@ -1870,11 +1863,9 @@ vteapp_window_constructed(GObject *object)
         }
 
         if (options.encoding != nullptr) {
-                GError* err = nullptr;
-                if (!vte_terminal_set_encoding(window->terminal, options.encoding, &err)) {
-                        g_printerr("Failed to set encoding: %s\n", err->message);
-                        g_error_free(err);
-                }
+                auto error = vte::glib::Error{};
+                if (!vte_terminal_set_encoding(window->terminal, options.encoding, error))
+                        g_printerr("Failed to set encoding: %s\n", error.message());
         }
 
         if (options.word_char_exceptions != nullptr)
@@ -2159,10 +2150,9 @@ main(int argc,
        g_set_prgname("Terminal");
        g_set_application_name("Terminal");
 
-       GError* error = nullptr;
-       if (!options.parse_argv(argc, argv, &error)) {
-               g_printerr("Error parsing arguments: %s\n", error->message);
-               g_error_free(error);
+       auto error = vte::glib::Error{};
+       if (!options.parse_argv(argc, argv, error)) {
+               g_printerr("Error parsing arguments: %s\n", error.message());
                return EXIT_FAILURE;
        }
 
diff --git a/src/app/meson.build b/src/app/meson.build
index 03068f32..1bed9160 100644
--- a/src/app/meson.build
+++ b/src/app/meson.build
@@ -14,7 +14,7 @@
 # You should have received a copy of the GNU Lesser General Public License
 # along with this library.  If not, see <https://www.gnu.org/licenses/>.
 
-app_sources = files(
+app_sources = glib_glue_sources + files(
   'app.cc',
 )
 
diff --git a/src/decoder-cat.cc b/src/decoder-cat.cc
index 7d34fd91..c3bd83c5 100644
--- a/src/decoder-cat.cc
+++ b/src/decoder-cat.cc
@@ -32,6 +32,7 @@
 #include <string>
 
 #include "debug.h"
+#include "glib-glue.hh"
 #include "icu-decoder.hh"
 #include "icu-glue.hh"
 #include "utf8.hh"
@@ -518,10 +519,9 @@ main(int argc,
         _vte_debug_init();
 
         auto options = Options{};
-        GError* err{nullptr};
-        if (!options.parse(argc, argv, &err)) {
-                g_printerr("Failed to parse arguments: %s\n", err->message);
-                g_error_free(err);
+        auto error = vte::glib::Error{};
+        if (!options.parse(argc, argv, error)) {
+                g_printerr("Failed to parse arguments: %s\n", error.message());
                 return EXIT_FAILURE;
         }
 
diff --git a/src/glib-glue.hh b/src/glib-glue.hh
new file mode 100644
index 00000000..c55ef016
--- /dev/null
+++ b/src/glib-glue.hh
@@ -0,0 +1,59 @@
+/*
+ * Copyright © 2019 Christian Persch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <memory>
+
+#include <glib.h>
+
+namespace vte::glib {
+
+class Error {
+public:
+        Error() = default;
+        ~Error() { reset(); }
+
+        Error(Error const&) = delete;
+        Error(Error&&) = delete;
+        Error& operator=(Error const&) = delete;
+        Error& operator=(Error&&) = delete;
+
+        operator GError* ()  noexcept { return m_error; }
+        operator GError** () noexcept { return &m_error; }
+
+        auto error()   const noexcept { return m_error != nullptr; }
+        auto domain()  const noexcept { return error() ? m_error->domain : 0; }
+        auto code()    const noexcept { return error() ? m_error->code : -1; }
+        auto message() const noexcept { return error() ? m_error->message : nullptr; }
+
+        void assert_no_error() const noexcept { g_assert_no_error(m_error); }
+
+        bool matches(GQuark domain, int code) const noexcept
+        {
+                return error() && g_error_matches(m_error, domain, code);
+        }
+
+        void reset() noexcept { g_clear_error(&m_error); }
+
+        bool propagate(GError** error) noexcept { *error = m_error; m_error = nullptr; return false; }
+
+private:
+        GError* m_error{nullptr};
+};
+
+} // namespace vte::glib
diff --git a/src/meson.build b/src/meson.build
index 78ee6341..428afac6 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -28,6 +28,10 @@ debug_sources = files(
   'debug.h',
 )
 
+glib_glue_sources = files(
+  'glib-glue.hh',
+)
+
 icu_sources = files(
   'icu-converter.cc',
   'icu-converter.hh',
@@ -80,7 +84,7 @@ utf8_sources = files(
   'utf8.hh',
 )
 
-libvte_common_sources = debug_sources + modes_sources + parser_sources + pty_sources + regex_sources + 
utf8_sources + files(
+libvte_common_sources = debug_sources + glib_glue_sources + modes_sources + parser_sources + pty_sources + 
regex_sources + utf8_sources + files(
   'attr.hh',
   'bidi.cc',
   'bidi.hh',
@@ -239,8 +243,8 @@ endif
 
 # decoder cat
 
-decoder_cat_sources = icu_sources + utf8_sources + debug_sources + files(
-  'decoder-cat.cc'
+decoder_cat_sources = glib_glue_sources + icu_sources + utf8_sources + debug_sources + files(
+  'decoder-cat.cc',
 )
 
 decoder_cat = executable(
@@ -254,8 +258,8 @@ decoder_cat = executable(
 
 # parser cat
 
-parser_cat_sources = parser_sources + utf8_sources + debug_sources + files(
-  'parser-cat.cc'
+parser_cat_sources = glib_glue_sources + parser_sources + utf8_sources + debug_sources + files(
+  'parser-cat.cc',
 )
 
 parser_cat = executable(
diff --git a/src/parser-cat.cc b/src/parser-cat.cc
index d0091978..083bc58a 100644
--- a/src/parser-cat.cc
+++ b/src/parser-cat.cc
@@ -31,6 +31,7 @@
 #include <string>
 
 #include "debug.h"
+#include "glib-glue.hh"
 #include "parser.hh"
 #include "parser-glue.hh"
 #include "utf8.hh"
@@ -904,10 +905,9 @@ main(int argc,
         _vte_debug_init();
 
         Options options{};
-        GError* err = nullptr;
-        if (!options.parse(argc, argv, &err)) {
-                g_printerr("Failed to parse arguments: %s\n", err->message);
-                g_error_free(err);
+        auto error = vte::glib::Error{};
+        if (!options.parse(argc, argv, error)) {
+                g_printerr("Failed to parse arguments: %s\n", error.message());
                 return EXIT_FAILURE;
         }
 
diff --git a/src/pty.cc b/src/pty.cc
index 97f0fbe0..c17600c0 100644
--- a/src/pty.cc
+++ b/src/pty.cc
@@ -72,6 +72,8 @@
 
 #include <glib/gi18n-lib.h>
 
+#include "glib-glue.hh"
+
 /* NSIG isn't in POSIX, so if it doesn't exist use this here. See bug #759196 */
 #ifndef NSIG
 #define NSIG (8 * sizeof(sigset_t))
@@ -389,7 +391,6 @@ Pty::spawn(char const* directory,
         bool inherit_envv;
         char** envp2;
         int i;
-        GError* err{nullptr};
         GPollFD pollfd;
 
         if (cancellable && !g_cancellable_make_pollfd(cancellable, &pollfd)) {
@@ -431,6 +432,7 @@ Pty::spawn(char const* directory,
        m_extra_child_setup.func = child_setup_func;
        m_extra_child_setup.data = child_setup_data;
 
+        auto err = vte::glib::Error{};
         ret = vte_spawn_async_with_pipes_cancellable(directory,
                                                      argv, envp2,
                                                      (GSpawnFlags)spawn_flags,
@@ -440,12 +442,12 @@ Pty::spawn(char const* directory,
                                                      nullptr, nullptr, nullptr,
                                                      timeout,
                                                      cancellable ? &pollfd : nullptr,
-                                                     &err);
+                                                     err);
         if (!ret &&
             directory != nullptr &&
-            g_error_matches(err, G_SPAWN_ERROR, G_SPAWN_ERROR_CHDIR)) {
+            err.matches(G_SPAWN_ERROR, G_SPAWN_ERROR_CHDIR)) {
                 /* try spawning in our working directory */
-                g_clear_error(&err);
+                err.reset();
                 ret = vte_spawn_async_with_pipes_cancellable(nullptr,
                                                              argv, envp2,
                                                              (GSpawnFlags)spawn_flags,
@@ -455,7 +457,7 @@ Pty::spawn(char const* directory,
                                                              nullptr, nullptr, nullptr,
                                                              timeout,
                                                              cancellable ? &pollfd : nullptr,
-                                                             &err);
+                                                             err);
         }
 
         g_strfreev (envp2);
@@ -469,8 +471,7 @@ Pty::spawn(char const* directory,
         if (ret)
                 return true;
 
-        g_propagate_error(error, err);
-        return false;
+        return err.propagate(error);
 }
 
 /*
diff --git a/src/vtegtk.cc b/src/vtegtk.cc
index 418564ef..35eee92f 100644
--- a/src/vtegtk.cc
+++ b/src/vtegtk.cc
@@ -48,6 +48,7 @@
 #include "vte/vtetypebuiltins.h"
 
 #include "debug.h"
+#include "glib-glue.hh"
 #include "marshal.h"
 #include "reaper.hh"
 #include "vtedefines.hh"
@@ -2792,8 +2793,8 @@ spawn_async_cb (GObject *source,
         VtePty *pty = VTE_PTY(source);
 
         GPid pid = -1;
-        GError *error = nullptr;
-        vte_pty_spawn_finish(pty, result, &pid, &error);
+        auto error = vte::glib::Error{};
+        vte_pty_spawn_finish(pty, result, &pid, error);
 
         /* Now get a ref to the terminal */
         VteTerminal* terminal = (VteTerminal*)g_weak_ref_get(&data->wref);
@@ -2828,9 +2829,6 @@ spawn_async_cb (GObject *source,
                 }
         }
 
-        if (error)
-                g_error_free(error);
-
         spawn_async_callback_data_free(data);
 
         if (terminal != nullptr)
@@ -2917,15 +2915,13 @@ vte_terminal_spawn_async(VteTerminal *terminal,
         g_return_if_fail(!child_setup_data_destroy || child_setup_data);
         g_return_if_fail(cancellable == nullptr || G_IS_CANCELLABLE (cancellable));
 
-        GError *error = NULL;
-        VtePty* pty = vte_terminal_pty_new_sync(terminal, pty_flags, cancellable, &error);
+        auto error = vte::glib::Error{};
+        auto pty = vte_terminal_pty_new_sync(terminal, pty_flags, cancellable, error);
         if (pty == nullptr) {
                 if (child_setup_data_destroy)
                         child_setup_data_destroy(child_setup_data);
 
                 callback(terminal, -1, error, user_data);
-
-                g_error_free(error);
                 return;
         }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]