[retro-gtk] Add and use retro_try()
- From: Adrien Plazas <aplazas src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [retro-gtk] Add and use retro_try()
- Date: Fri, 16 Apr 2021 20:22:11 +0000 (UTC)
commit 30977ebe548784e7b7d0ac6e57923a651e38979d
Author: Adrien Plazas <kekun plazas laposte net>
Date: Tue Dec 22 10:20:18 2020 +0100
Add and use retro_try()
This simplifies error handling and hardens it by simulating a try/catch
block pair. This also automatically fixes some error leaks.
This also adds retro_try_propagate() and retro_try_propagate_val() to
simplify the most common use-case of retro_try().
retro-gtk/retro-core-descriptor.c | 365 +++++++++++++++-----------------------
retro-gtk/retro-core.c | 41 ++---
retro-gtk/retro-gl-display.c | 12 +-
retro-gtk/retro-glsl-filter.c | 81 ++++-----
retro-gtk/retro-glsl-shader.c | 20 +--
retro-gtk/retro-module-iterator.c | 68 ++++---
retro-gtk/retro-runner-process.c | 37 ++--
retro-runner/retro-core.c | 164 +++++++----------
retro-runner/retro-game-info.c | 15 +-
shared/retro-error-private.h | 256 ++++++++++++++++++++++++++
tests/retro-reftest-file.c | 142 ++++++---------
11 files changed, 648 insertions(+), 553 deletions(-)
---
diff --git a/retro-gtk/retro-core-descriptor.c b/retro-gtk/retro-core-descriptor.c
index 9081153..8d8923f 100644
--- a/retro-gtk/retro-core-descriptor.c
+++ b/retro-gtk/retro-core-descriptor.c
@@ -9,6 +9,8 @@
#include "retro-core-descriptor.h"
+#include "retro-error-private.h"
+
struct _RetroCoreDescriptor
{
GObject parent_instance;
@@ -101,22 +103,18 @@ has_key_prefixed (RetroCoreDescriptor *self,
{
g_autofree gchar *group = NULL;
gboolean has_key;
- GError *tmp_error = NULL;
g_assert (group_prefix != NULL);
g_assert (group_suffix != NULL);
g_assert (key != NULL);
group = g_strconcat (group_prefix, group_suffix, NULL);
- has_key = g_key_file_has_key (self->key_file,
- group,
- key,
- &tmp_error);
- if (G_UNLIKELY (tmp_error != NULL)) {
- g_propagate_error (error, tmp_error);
-
- return FALSE;
- }
+ retro_try_propagate_val ({
+ has_key = g_key_file_has_key (self->key_file,
+ group,
+ key,
+ &catch);
+ }, catch, error, FALSE);
return has_key;
}
@@ -130,7 +128,6 @@ get_string_prefixed (RetroCoreDescriptor *self,
{
g_autofree gchar *group = NULL;
g_autofree gchar *string = NULL;
- GError *tmp_error = NULL;
g_assert (group_prefix != NULL);
g_assert (group_suffix != NULL);
@@ -138,12 +135,14 @@ get_string_prefixed (RetroCoreDescriptor *self,
group = g_strconcat (group_prefix, group_suffix, NULL);
- string = g_key_file_get_string (self->key_file,
- group,
- key,
- &tmp_error);
- if (G_UNLIKELY (tmp_error != NULL))
+ retro_try ({
+ string = g_key_file_get_string (self->key_file,
+ group,
+ key,
+ &catch);
+ }, catch, {
return NULL;
+ });
return g_steal_pointer (&string);
}
@@ -158,7 +157,6 @@ get_string_list_prefixed (RetroCoreDescriptor *self,
{
g_autofree gchar *group = NULL;
g_auto (GStrv) list = NULL;
- GError *tmp_error = NULL;
g_assert (group_prefix != NULL);
g_assert (group_suffix != NULL);
@@ -166,16 +164,13 @@ get_string_list_prefixed (RetroCoreDescriptor *self,
g_assert (length != NULL);
group = g_strconcat (group_prefix, group_suffix, NULL);
- list = g_key_file_get_string_list (self->key_file,
- group,
- key,
- length,
- &tmp_error);
- if (G_UNLIKELY (tmp_error != NULL)) {
- g_propagate_error (error, tmp_error);
-
- return NULL;
- }
+ retro_try_propagate_val ({
+ list = g_key_file_get_string_list (self->key_file,
+ group,
+ key,
+ length,
+ &catch);
+ }, catch, error, NULL);
return g_steal_pointer (&list);
}
@@ -187,20 +182,16 @@ check_has_required_key (RetroCoreDescriptor *self,
GError **error)
{
gboolean has_key;
- GError *tmp_error = NULL;
g_assert (group != NULL);
g_assert (key != NULL);
- has_key = g_key_file_has_key (self->key_file,
- LIBRETRO_GROUP,
- TYPE_KEY,
- &tmp_error);
- if (G_UNLIKELY (tmp_error != NULL)) {
- g_propagate_error (error, tmp_error);
-
- return;
- }
+ retro_try_propagate ({
+ has_key = g_key_file_has_key (self->key_file,
+ LIBRETRO_GROUP,
+ TYPE_KEY,
+ &catch);
+ }, catch, error);
if (!has_key)
g_set_error (error,
@@ -217,47 +208,33 @@ static void
check_libretro_group (RetroCoreDescriptor *self,
GError **error)
{
- GError *tmp_error = NULL;
-
- check_has_required_key (self,
- LIBRETRO_GROUP,
- TYPE_KEY,
- &tmp_error);
- if (G_UNLIKELY (tmp_error != NULL)) {
- g_propagate_error (error, tmp_error);
-
- return;
- }
-
- check_has_required_key (self,
- LIBRETRO_GROUP,
- NAME_KEY,
- &tmp_error);
- if (G_UNLIKELY (tmp_error != NULL)) {
- g_propagate_error (error, tmp_error);
-
- return;
- }
-
- check_has_required_key (self,
- LIBRETRO_GROUP,
- MODULE_KEY,
- &tmp_error);
- if (G_UNLIKELY (tmp_error != NULL)) {
- g_propagate_error (error, tmp_error);
-
- return;
- }
-
- check_has_required_key (self,
- LIBRETRO_GROUP,
- LIBRETRO_VERSION_KEY,
- &tmp_error);
- if (G_UNLIKELY (tmp_error != NULL)) {
- g_propagate_error (error, tmp_error);
-
- return;
- }
+ retro_try_propagate ({
+ check_has_required_key (self,
+ LIBRETRO_GROUP,
+ TYPE_KEY,
+ &catch);
+ }, catch, error);
+
+ retro_try_propagate ({
+ check_has_required_key (self,
+ LIBRETRO_GROUP,
+ NAME_KEY,
+ &catch);
+ }, catch, error);
+
+ retro_try_propagate ({
+ check_has_required_key (self,
+ LIBRETRO_GROUP,
+ MODULE_KEY,
+ &catch);
+ }, catch, error);
+
+ retro_try_propagate ({
+ check_has_required_key (self,
+ LIBRETRO_GROUP,
+ LIBRETRO_VERSION_KEY,
+ &catch);
+ }, catch, error);
}
static void
@@ -267,43 +244,33 @@ check_platform_group (RetroCoreDescriptor *self,
{
gboolean has_key;
g_auto (GStrv) firmwares = NULL;
- GError *tmp_error = NULL;
g_assert (group != NULL);
- check_has_required_key (self,
- group,
- PLATFORM_MIME_TYPE_KEY,
- &tmp_error);
- if (G_UNLIKELY (tmp_error != NULL)) {
- g_propagate_error (error, tmp_error);
-
- return;
- }
+ retro_try_propagate ({
+ check_has_required_key (self,
+ group,
+ PLATFORM_MIME_TYPE_KEY,
+ &catch);
+ }, catch, error);
- has_key = g_key_file_has_key (self->key_file,
- group,
- PLATFORM_FIRMWARES_KEY,
- &tmp_error);
- if (G_UNLIKELY (tmp_error != NULL)) {
- g_propagate_error (error, tmp_error);
-
- return;
- }
+ retro_try_propagate ({
+ has_key = g_key_file_has_key (self->key_file,
+ group,
+ PLATFORM_FIRMWARES_KEY,
+ &catch);
+ }, catch, error);
if (!has_key)
return;
- firmwares = g_key_file_get_string_list (self->key_file,
- group,
- PLATFORM_FIRMWARES_KEY,
- NULL,
- &tmp_error);
- if (G_UNLIKELY (tmp_error != NULL)) {
- g_propagate_error (error, tmp_error);
-
- return;
- }
+ retro_try_propagate ({
+ firmwares = g_key_file_get_string_list (self->key_file,
+ group,
+ PLATFORM_FIRMWARES_KEY,
+ NULL,
+ &catch);
+ }, catch, error);
for (GStrv firmware_p = firmwares; *firmware_p != NULL; firmware_p++) {
g_autofree gchar *firmware_group = NULL;
@@ -329,29 +296,21 @@ check_firmware_group (RetroCoreDescriptor *self,
const gchar *group,
GError **error)
{
- GError *tmp_error = NULL;
-
g_assert (group != NULL);
- check_has_required_key (self,
- group,
- FIRMWARE_PATH_KEY,
- &tmp_error);
- if (G_UNLIKELY (tmp_error != NULL)) {
- g_propagate_error (error, tmp_error);
+ retro_try_propagate ({
+ check_has_required_key (self,
+ group,
+ FIRMWARE_PATH_KEY,
+ &catch);
+ }, catch, error);
- return;
- }
-
- check_has_required_key (self,
- group,
- FIRMWARE_MANDATORY_KEY,
- &tmp_error);
- if (G_UNLIKELY (tmp_error != NULL)) {
- g_propagate_error (error, tmp_error);
-
- return;
- }
+ retro_try_propagate ({
+ check_has_required_key (self,
+ group,
+ FIRMWARE_MANDATORY_KEY,
+ &catch);
+ }, catch, error);
}
/* Public */
@@ -370,19 +329,15 @@ retro_core_descriptor_has_icon (RetroCoreDescriptor *self,
GError **error)
{
gboolean has_icon;
- GError *tmp_error = NULL;
g_return_val_if_fail (RETRO_IS_CORE_DESCRIPTOR (self), FALSE);
- has_icon = g_key_file_has_key (self->key_file,
- LIBRETRO_GROUP,
- ICON_KEY,
- &tmp_error);
- if (G_UNLIKELY (tmp_error != NULL)) {
- g_propagate_error (error, tmp_error);
-
- return FALSE;
- }
+ retro_try_propagate_val ({
+ has_icon = g_key_file_has_key (self->key_file,
+ LIBRETRO_GROUP,
+ ICON_KEY,
+ &catch);
+ }, catch, error, FALSE);
return has_icon;
}
@@ -440,19 +395,15 @@ retro_core_descriptor_get_is_game (RetroCoreDescriptor *self,
{
g_autofree gchar *type = NULL;
gboolean is_game;
- GError *tmp_error = NULL;
g_return_val_if_fail (RETRO_IS_CORE_DESCRIPTOR (self), FALSE);
- type = g_key_file_get_string (self->key_file,
- LIBRETRO_GROUP,
- TYPE_KEY,
- &tmp_error);
- if (G_UNLIKELY (tmp_error != NULL)) {
- g_propagate_error (error, tmp_error);
-
- return FALSE;
- }
+ retro_try_propagate_val ({
+ type = g_key_file_get_string (self->key_file,
+ LIBRETRO_GROUP,
+ TYPE_KEY,
+ &catch);
+ }, catch, error, FALSE);
is_game = g_strcmp0 (type, TYPE_GAME) == 0;
@@ -474,19 +425,15 @@ retro_core_descriptor_get_is_emulator (RetroCoreDescriptor *self,
{
g_autofree gchar *type = NULL;
gboolean is_emulator;
- GError *tmp_error = NULL;
g_return_val_if_fail (RETRO_IS_CORE_DESCRIPTOR (self), FALSE);
- type = g_key_file_get_string (self->key_file,
- LIBRETRO_GROUP,
- TYPE_KEY,
- &tmp_error);
- if (G_UNLIKELY (tmp_error != NULL)) {
- g_propagate_error (error, tmp_error);
-
- return FALSE;
- }
+ retro_try_propagate_val ({
+ type = g_key_file_get_string (self->key_file,
+ LIBRETRO_GROUP,
+ TYPE_KEY,
+ &catch);
+ }, catch, error, FALSE);
is_emulator = g_strcmp0 (type, TYPE_EMULATOR) == 0;
@@ -529,19 +476,15 @@ retro_core_descriptor_get_icon (RetroCoreDescriptor *self,
{
g_autofree gchar *icon_name = NULL;
GIcon *icon;
- GError *tmp_error = NULL;
g_return_val_if_fail (RETRO_IS_CORE_DESCRIPTOR (self), NULL);
- icon_name = g_key_file_get_string (self->key_file,
- LIBRETRO_GROUP,
- ICON_KEY,
- &tmp_error);
- if (G_UNLIKELY (tmp_error != NULL)) {
- g_propagate_error (error, tmp_error);
-
- return NULL;
- }
+ retro_try_propagate_val ({
+ icon_name = g_key_file_get_string (self->key_file,
+ LIBRETRO_GROUP,
+ ICON_KEY,
+ &catch);
+ }, catch, error, NULL);
icon = G_ICON (g_themed_icon_new (icon_name));
@@ -586,7 +529,6 @@ retro_core_descriptor_get_module_file (RetroCoreDescriptor *self,
g_autoptr (GFile) dir = NULL;
g_autofree gchar *module = NULL;
g_autoptr (GFile) module_file = NULL;
- GError *tmp_error = NULL;
g_return_val_if_fail (RETRO_IS_CORE_DESCRIPTOR (self), NULL);
@@ -595,12 +537,9 @@ retro_core_descriptor_get_module_file (RetroCoreDescriptor *self,
if (dir == NULL)
return NULL;
- module = retro_core_descriptor_get_module (self, &tmp_error);
- if (G_UNLIKELY (tmp_error != NULL)) {
- g_propagate_error (error, tmp_error);
-
- return NULL;
- }
+ retro_try_propagate_val ({
+ module = retro_core_descriptor_get_module (self, &catch);
+ }, catch, error, NULL);
module_file = g_file_get_child (dir, module);
if (!g_file_query_exists (module_file, NULL))
@@ -850,21 +789,18 @@ retro_core_descriptor_get_is_firmware_mandatory (RetroCoreDescriptor *self,
{
g_autofree gchar *group = NULL;
gboolean is_mandatory;
- GError *tmp_error = NULL;
g_return_val_if_fail (RETRO_IS_CORE_DESCRIPTOR (self), FALSE);
g_return_val_if_fail (firmware != NULL, FALSE);
group = g_strconcat (FIRMWARE_GROUP_PREFIX, firmware, NULL);
- is_mandatory = g_key_file_get_boolean (self->key_file,
- group,
- FIRMWARE_MANDATORY_KEY,
- &tmp_error);
- if (G_UNLIKELY (tmp_error != NULL)) {
- g_propagate_error (error, tmp_error);
-
- return FALSE;
- }
+
+ retro_try_propagate_val ({
+ is_mandatory = g_key_file_get_boolean (self->key_file,
+ group,
+ FIRMWARE_MANDATORY_KEY,
+ &catch);
+ }, catch, error, FALSE);
return is_mandatory;
}
@@ -888,22 +824,18 @@ retro_core_descriptor_get_platform_supports_mime_types (RetroCoreDescriptor *se
{
g_auto (GStrv) supported_mime_types = NULL;
gsize supported_mime_types_length;
- GError *tmp_error = NULL;
g_return_val_if_fail (RETRO_IS_CORE_DESCRIPTOR (self), FALSE);
g_return_val_if_fail (platform != NULL, FALSE);
g_return_val_if_fail (mime_types != NULL, FALSE);
- supported_mime_types =
- retro_core_descriptor_get_mime_type (self,
- platform,
- &supported_mime_types_length,
- &tmp_error);
- if (G_UNLIKELY (tmp_error != NULL)) {
- g_propagate_error (error, tmp_error);
-
- return FALSE;
- }
+ retro_try_propagate_val ({
+ supported_mime_types =
+ retro_core_descriptor_get_mime_type (self,
+ platform,
+ &supported_mime_types_length,
+ &catch);
+ }, catch, error, FALSE);
for (; *mime_types != NULL; mime_types++)
if (!g_strv_contains ((const char * const *) supported_mime_types,
@@ -929,49 +861,36 @@ retro_core_descriptor_new (const gchar *filename,
g_autoptr (RetroCoreDescriptor) self = NULL;
g_auto (GStrv) groups = NULL;
gsize groups_length;
- GError *tmp_error = NULL;
g_return_val_if_fail (filename != NULL, NULL);
self = g_object_new (RETRO_TYPE_CORE_DESCRIPTOR, NULL);
self->filename = g_strdup (filename);
self->key_file = g_key_file_new ();
- g_key_file_load_from_file (self->key_file,
- filename,
- G_KEY_FILE_NONE,
- &tmp_error);
- if (G_UNLIKELY (tmp_error != NULL)) {
- g_propagate_error (error, tmp_error);
+ retro_try_propagate_val ({
+ g_key_file_load_from_file (self->key_file,
+ filename,
+ G_KEY_FILE_NONE,
+ &catch);
+ }, catch, error, NULL);
- return NULL;
- }
-
- check_libretro_group (self, &tmp_error);
- if (G_UNLIKELY (tmp_error != NULL)) {
- g_propagate_error (error, tmp_error);
-
- return NULL;
- }
+ retro_try_propagate_val ({
+ check_libretro_group (self, &catch);
+ }, catch, error, NULL);
groups = g_key_file_get_groups (self->key_file, &groups_length);
for (gsize i = 0; i < groups_length; i++) {
if (g_str_has_prefix (groups[i],
PLATFORM_GROUP_PREFIX)) {
- check_platform_group (self, groups[i], &tmp_error);
- if (G_UNLIKELY (tmp_error != NULL)) {
- g_propagate_error (error, tmp_error);
-
- return NULL;
- }
+ retro_try_propagate_val ({
+ check_platform_group (self, groups[i], &catch);
+ }, catch, error, NULL);
}
else if (g_str_has_prefix (groups[i],
FIRMWARE_GROUP_PREFIX)) {
- check_firmware_group (self, groups[i], &tmp_error);
- if (G_UNLIKELY (tmp_error != NULL)) {
- g_propagate_error (error, tmp_error);
-
- return NULL;
- }
+ retro_try_propagate_val ({
+ check_firmware_group (self, groups[i], &catch);
+ }, catch, error, NULL);
}
}
diff --git a/retro-gtk/retro-core.c b/retro-gtk/retro-core.c
index a290e15..ab3a048 100644
--- a/retro-gtk/retro-core.c
+++ b/retro-gtk/retro-core.c
@@ -17,6 +17,7 @@
#include "retro-controller-iterator-private.h"
#include "retro-controller-state-private.h"
#include "retro-controller-type.h"
+#include "retro-error-private.h"
#include "retro-framebuffer-private.h"
#include "retro-input-private.h"
#include "retro-keyboard-private.h"
@@ -1020,26 +1021,24 @@ insert_variable (RetroCore *self,
const gchar *value)
{
RetroOption *option;
- GError *tmp_error = NULL;
- option = retro_option_new (key, value, &tmp_error);
- if (G_UNLIKELY (tmp_error != NULL)) {
- g_debug ("%s", tmp_error->message);
- g_clear_error (&tmp_error);
+ retro_try ({
+ option = retro_option_new (key, value, &catch);
+ }, catch, {
+ g_debug ("%s", catch->message);
return;
- }
+ });
if (g_hash_table_contains (self->option_overrides, key)) {
gchar *override;
override = g_hash_table_lookup (self->option_overrides, key);
- retro_option_set_value (option, override, &tmp_error);
-
- if (G_UNLIKELY (tmp_error != NULL)) {
- g_debug ("%s", tmp_error->message);
- g_clear_error (&tmp_error);
- }
+ retro_try ({
+ retro_option_set_value (option, override, &catch);
+ }, catch, {
+ g_debug ("%s", catch->message);
+ });
}
g_hash_table_insert (self->options, g_strdup (key), option);
@@ -1193,11 +1192,12 @@ retro_core_boot (RetroCore *self,
g_return_if_fail (RETRO_IS_CORE (self));
- retro_runner_process_start (self->process, &tmp_error);
- if (tmp_error) {
- crash (self, tmp_error);
+ retro_try ({
+ retro_runner_process_start (self->process, &catch);
+ }, catch, {
+ crash (self, catch);
return;
- }
+ });
proxy = retro_runner_process_get_proxy (self->process);
g_signal_connect_object (proxy, "variables-set", G_CALLBACK (variables_set_cb), self, 0);
@@ -1251,11 +1251,12 @@ retro_core_boot (RetroCore *self,
g_variant_get (framebuffer_variant, "h", &handle);
if (G_LIKELY (handle < g_unix_fd_list_get_length (out_fd_list))) {
- fd = g_unix_fd_list_get (out_fd_list, handle, &tmp_error);
- if (tmp_error) {
- crash (self, tmp_error);
+ retro_try ({
+ fd = g_unix_fd_list_get (out_fd_list, handle, &catch);
+ }, catch, {
+ crash (self, catch);
return;
- }
+ });
} else {
g_critical ("Invalid framebuffer handle");
return;
diff --git a/retro-gtk/retro-gl-display.c b/retro-gtk/retro-gl-display.c
index 17e89c7..b58f902 100644
--- a/retro-gtk/retro-gl-display.c
+++ b/retro-gtk/retro-gl-display.c
@@ -10,6 +10,7 @@
#include "retro-gl-display-private.h"
#include <epoxy/gl.h>
+#include "retro-error-private.h"
#include "retro-glsl-filter-private.h"
#include "retro-pixbuf.h"
#include "retro-pixdata.h"
@@ -209,7 +210,6 @@ realize (RetroGLDisplay *self)
GLuint vertex_array_object;
GLuint element_buffer_object;
RetroVideoFilter current_filter;
- GError *inner_error = NULL;
gtk_gl_area_make_current (GTK_GL_AREA (self));
@@ -227,16 +227,16 @@ realize (RetroGLDisplay *self)
for (RetroVideoFilter filter = 0; filter < RETRO_VIDEO_FILTER_COUNT; filter++) {
RetroGLSLShader *shader;
- self->glsl_filter[filter] = retro_glsl_filter_new (filter_uris[filter], &inner_error);
- if (G_UNLIKELY (inner_error != NULL)) {
+ retro_try ({
+ self->glsl_filter[filter] = retro_glsl_filter_new (filter_uris[filter], &catch);
+ }, catch, {
g_critical ("Shader program %s creation failed: %s",
filter_uris[filter],
- inner_error->message);
+ catch->message);
g_clear_object (&self->glsl_filter[filter]);
- g_clear_error (&inner_error);
continue;
- }
+ });
shader = retro_glsl_filter_get_shader (self->glsl_filter[filter]);
diff --git a/retro-gtk/retro-glsl-filter.c b/retro-gtk/retro-glsl-filter.c
index d4c0d8f..d3f564e 100644
--- a/retro-gtk/retro-glsl-filter.c
+++ b/retro-gtk/retro-glsl-filter.c
@@ -2,6 +2,8 @@
#include "retro-glsl-filter-private.h"
+#include "retro-error-private.h"
+
struct _RetroGLSLFilter
{
GObject parent_instance;
@@ -18,15 +20,14 @@ g_key_file_try_get_string (GKeyFile *key_file,
const gchar *key)
{
const gchar *value;
- GError *inner_error = NULL;
- value = g_key_file_get_string (key_file, group, key, &inner_error);
- if (G_UNLIKELY (inner_error != NULL)) {
- g_debug ("%s", inner_error->message);
- g_clear_error (&inner_error);
+ retro_try ({
+ value = g_key_file_get_string (key_file, group, key, &catch);
+ }, catch, {
+ g_debug ("%s", catch->message);
return NULL;
- }
+ });
return value;
}
@@ -37,41 +38,40 @@ g_file_try_read_bytes (GFile *file)
g_autoptr (GFileInputStream) stream = NULL;
goffset size;
GBytes *bytes;
- GError *inner_error = NULL;
- stream = g_file_read (file, NULL, &inner_error);
- if (G_UNLIKELY (inner_error != NULL)) {
- g_debug ("%s", inner_error->message);
- g_clear_error (&inner_error);
+ retro_try ({
+ stream = g_file_read (file, NULL, &catch);
+ }, catch, {
+ g_debug ("%s", catch->message);
return NULL;
- }
+ });
- g_seekable_seek (G_SEEKABLE (stream), 0, G_SEEK_END, NULL, &inner_error);
- if (G_UNLIKELY (inner_error != NULL)) {
- g_debug ("%s", inner_error->message);
- g_clear_error (&inner_error);
+ retro_try ({
+ g_seekable_seek (G_SEEKABLE (stream), 0, G_SEEK_END, NULL, &catch);
+ }, catch, {
+ g_debug ("%s", catch->message);
return NULL;
- }
+ });
size = g_seekable_tell (G_SEEKABLE (stream));
- g_seekable_seek (G_SEEKABLE (stream), 0, G_SEEK_SET, NULL, &inner_error);
- if (G_UNLIKELY (inner_error != NULL)) {
- g_debug ("%s", inner_error->message);
- g_clear_error (&inner_error);
+ retro_try ({
+ g_seekable_seek (G_SEEKABLE (stream), 0, G_SEEK_SET, NULL, &catch);
+ }, catch, {
+ g_debug ("%s", catch->message);
return NULL;
- }
+ });
- bytes = g_input_stream_read_bytes (G_INPUT_STREAM (stream), size, NULL, &inner_error);
- if (G_UNLIKELY (inner_error != NULL)) {
- g_debug ("%s", inner_error->message);
- g_clear_error (&inner_error);
+ retro_try ({
+ bytes = g_input_stream_read_bytes (G_INPUT_STREAM (stream), size, NULL, &catch);
+ }, catch, {
+ g_debug ("%s", catch->message);
return NULL;
- }
+ });
return bytes;
}
@@ -119,7 +119,6 @@ retro_glsl_filter_new (const char *uri,
g_autoptr (GFile) parent = NULL;
g_autoptr (GBytes) bytes = NULL;
const gchar *value;
- GError *inner_error = NULL;
g_return_val_if_fail (uri != NULL, NULL);
@@ -129,12 +128,9 @@ retro_glsl_filter_new (const char *uri,
return NULL;
key_file = g_key_file_new ();
- g_key_file_load_from_bytes (key_file, bytes, G_KEY_FILE_NONE, &inner_error);
- if (G_UNLIKELY (inner_error != NULL)) {
- g_propagate_error (error, inner_error);
-
- return NULL;
- }
+ retro_try_propagate_val ({
+ g_key_file_load_from_bytes (key_file, bytes, G_KEY_FILE_NONE, &catch);
+ }, catch, error, NULL);
self = g_object_new (RETRO_TYPE_GLSL_FILTER, NULL);
@@ -172,16 +168,13 @@ retro_glsl_filter_new (const char *uri,
if (fragment == NULL)
fragment = g_file_try_read_child_bytes (parent, "sharp.fs");
- self->shader = retro_glsl_shader_new (vertex,
- fragment,
- wrap,
- filter,
- &inner_error);
- if (G_UNLIKELY (inner_error != NULL)) {
- g_propagate_error (error, inner_error);
-
- return NULL;
- }
+ retro_try_propagate_val ({
+ self->shader = retro_glsl_shader_new (vertex,
+ fragment,
+ wrap,
+ filter,
+ &catch);
+ }, catch, error, NULL);
return g_steal_pointer (&self);
}
diff --git a/retro-gtk/retro-glsl-shader.c b/retro-gtk/retro-glsl-shader.c
index 51eb148..b606c1b 100644
--- a/retro-gtk/retro-glsl-shader.c
+++ b/retro-gtk/retro-glsl-shader.c
@@ -2,6 +2,8 @@
#include "retro-glsl-shader-private.h"
+#include "retro-error-private.h"
+
struct _RetroGLSLShader
{
GObject parent_instance;
@@ -98,7 +100,6 @@ retro_glsl_shader_new (GBytes *vertex,
gint status = 0;
GLuint vertex_shader;
GLuint fragment_shader;
- GError *inner_error = NULL;
g_return_val_if_fail (vertex != NULL, NULL);
g_return_val_if_fail (fragment != NULL, NULL);
@@ -112,20 +113,17 @@ retro_glsl_shader_new (GBytes *vertex,
self->wrap = wrap;
self->filter = filter;
- vertex_shader = create_shader (self->vertex, GL_VERTEX_SHADER, &inner_error);
- if (G_UNLIKELY (inner_error != NULL)) {
- g_propagate_error (error, inner_error);
+ retro_try_propagate_val ({
+ vertex_shader = create_shader (self->vertex, GL_VERTEX_SHADER, &catch);
+ }, catch, error, NULL);
- return NULL;
- }
-
- fragment_shader = create_shader (self->fragment, GL_FRAGMENT_SHADER, &inner_error);
- if (G_UNLIKELY (inner_error != NULL)) {
- g_propagate_error (error, inner_error);
+ retro_try ({
+ fragment_shader = create_shader (self->fragment, GL_FRAGMENT_SHADER, &catch);
+ }, catch, {
glDeleteShader (vertex_shader);
return NULL;
- }
+ });
self->program = glCreateProgram ();
glAttachShader (self->program, vertex_shader);
diff --git a/retro-gtk/retro-module-iterator.c b/retro-gtk/retro-module-iterator.c
index 939ac4a..701909f 100644
--- a/retro-gtk/retro-module-iterator.c
+++ b/retro-gtk/retro-module-iterator.c
@@ -9,6 +9,8 @@
#include "retro-module-iterator.h"
+#include "retro-error-private.h"
+
struct _RetroModuleIterator
{
GObject parent_instance;
@@ -120,7 +122,6 @@ iterate_next_in_current_path (RetroModuleIterator *self,
g_autoptr (GFile) core_descriptor_file = NULL;
g_autofree gchar *core_descriptor_path = NULL;
RetroCoreDescriptor *core_descriptor;
- GError *tmp_error = NULL;
g_assert (G_IS_FILE (directory));
g_assert (G_IS_FILE_INFO (info));
@@ -150,14 +151,13 @@ iterate_next_in_current_path (RetroModuleIterator *self,
core_descriptor_file = g_file_get_child (directory, core_descriptor_basename);
core_descriptor_path = g_file_get_path (core_descriptor_file);
- core_descriptor = retro_core_descriptor_new (core_descriptor_path, &tmp_error);
- if (G_UNLIKELY (tmp_error != NULL)) {
- g_debug ("%s", tmp_error->message);
-
- g_error_free (tmp_error);
+ retro_try ({
+ core_descriptor = retro_core_descriptor_new (core_descriptor_path, &catch);
+ }, catch, {
+ g_debug ("%s", catch->message);
return FALSE;
- }
+ });
g_clear_object (&self->core_descriptor);
self->core_descriptor = core_descriptor;
@@ -171,7 +171,6 @@ next_in_current_path (RetroModuleIterator *self,
{
g_autoptr (GFile) directory = NULL;
gboolean found = FALSE;
- GError *tmp_error = NULL;
if (self->sub_directory != NULL && next_in_sub_directory (self))
return TRUE;
@@ -179,18 +178,18 @@ next_in_current_path (RetroModuleIterator *self,
directory = g_file_new_for_path (self->directories[self->current_directory]);
if (self->file_enumerator == NULL) {
- self->file_enumerator =
- g_file_enumerate_children (directory,
- "",
- G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
- NULL,
- &tmp_error);
- if (G_UNLIKELY (tmp_error != NULL)) {
- g_propagate_error (error, tmp_error);
- g_clear_object (&self->file_enumerator);
-
- return FALSE;
- }
+ g_autoptr (GFileEnumerator) file_enumerator = NULL;
+
+ retro_try_propagate_val ({
+ file_enumerator =
+ g_file_enumerate_children (directory,
+ "",
+ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+ NULL,
+ &catch);
+ }, catch, error, FALSE);
+
+ self->file_enumerator = g_steal_pointer (&file_enumerator);
}
if (self->file_enumerator == NULL)
@@ -199,22 +198,16 @@ next_in_current_path (RetroModuleIterator *self,
while (TRUE) {
g_autoptr (GFileInfo) info = NULL;
- info = g_file_enumerator_next_file (self->file_enumerator, NULL, &tmp_error);
- if (G_UNLIKELY (tmp_error != NULL)) {
- g_propagate_error (error, tmp_error);
-
- return FALSE;
- }
+ retro_try_propagate_val ({
+ info = g_file_enumerator_next_file (self->file_enumerator, NULL, &catch);
+ }, catch, error, FALSE);
if (info == NULL)
break;
- found = iterate_next_in_current_path (self, directory, info, &tmp_error);
- if (G_UNLIKELY (tmp_error != NULL)) {
- g_propagate_error (error, tmp_error);
-
- return FALSE;
- }
+ retro_try_propagate_val ({
+ found = iterate_next_in_current_path (self, directory, info, &catch);
+ }, catch, error, FALSE);
if (found)
return TRUE;
@@ -258,19 +251,18 @@ gboolean
retro_module_iterator_next (RetroModuleIterator *self)
{
gboolean found_next_in_current_path;
- GError *tmp_error = NULL;
g_return_val_if_fail (RETRO_IS_MODULE_ITERATOR (self), FALSE);
while (self->directories[self->current_directory] != NULL) {
set_current_directory_as_visited (self);
- found_next_in_current_path = next_in_current_path (self, &tmp_error);
- if (G_UNLIKELY (tmp_error != NULL)) {
- g_debug ("%s", tmp_error->message);
- g_clear_error (&tmp_error);
+ retro_try ({
+ found_next_in_current_path = next_in_current_path (self, &catch);
+ }, catch, {
+ g_debug ("%s", catch->message);
found_next_in_current_path = FALSE;
- }
+ });
if (found_next_in_current_path)
return TRUE;
diff --git a/retro-gtk/retro-runner-process.c b/retro-gtk/retro-runner-process.c
index 953ad69..490ddcb 100644
--- a/retro-gtk/retro-runner-process.c
+++ b/retro-gtk/retro-runner-process.c
@@ -7,6 +7,7 @@
#include <glib-unix.h>
#include <gio/gunixconnection.h>
#include <sys/socket.h>
+#include "retro-error-private.h"
struct _RetroRunnerProcess
{
@@ -233,7 +234,6 @@ retro_runner_process_start (RetroRunnerProcess *self,
g_autoptr(GSocketConnection) connection = NULL;
g_autoptr(GSubprocessLauncher) launcher = NULL;
g_autoptr(GSubprocess) process = NULL;
- GError *tmp_error = NULL;
g_return_if_fail (RETRO_IS_RUNNER_PROCESS (self));
g_return_if_fail (!G_IS_DBUS_CONNECTION (self->connection));
@@ -243,22 +243,20 @@ retro_runner_process_start (RetroRunnerProcess *self,
if (!(connection = create_connection (launcher, 3, error)))
return;
- if (!(process = g_subprocess_launcher_spawn (launcher, &tmp_error,
+ retro_try_propagate ({
+ process = g_subprocess_launcher_spawn (launcher, &catch,
RETRO_RUNNER_PATH,
g_get_application_name (),
- self->filename, NULL))) {
- g_propagate_error (error, tmp_error);
- return;
- }
+ self->filename, NULL);
+ }, catch, error);
- if (!(self->connection = g_dbus_connection_new_sync (G_IO_STREAM (connection),
+ retro_try_propagate ({
+ self->connection = g_dbus_connection_new_sync (G_IO_STREAM (connection),
NULL,
G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING |
G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
- NULL, NULL, &tmp_error))) {
- g_propagate_error (error, tmp_error);
- return;
- }
+ NULL, NULL, &catch);
+ }, catch, error);
g_dbus_connection_start_message_processing (self->connection);
@@ -266,11 +264,11 @@ retro_runner_process_start (RetroRunnerProcess *self,
g_subprocess_wait_check_async (process, self->cancellable,
(GAsyncReadyCallback) wait_check_cb, self);
- self->proxy = ipc_runner_proxy_new_sync (self->connection, 0, NULL,
- "/org/gnome/Retro/Runner", NULL,
- &tmp_error);
- if (!self->proxy)
- g_propagate_error (error, tmp_error);
+ retro_try_propagate ({
+ self->proxy = ipc_runner_proxy_new_sync (self->connection, 0, NULL,
+ "/org/gnome/Retro/Runner", NULL,
+ &catch);
+ }, catch, error);
}
/**
@@ -284,15 +282,14 @@ void
retro_runner_process_stop (RetroRunnerProcess *self,
GError **error)
{
- GError *tmp_error = NULL;
-
g_return_if_fail (RETRO_IS_RUNNER_PROCESS (self));
g_return_if_fail (G_IS_DBUS_CONNECTION (self->connection));
g_cancellable_cancel (self->cancellable);
- if (!g_dbus_connection_close_sync (self->connection, NULL, &tmp_error))
- g_propagate_error (error, tmp_error);
+ retro_try_propagate ({
+ g_dbus_connection_close_sync (self->connection, NULL, &catch);
+ }, catch, error);
g_clear_object (&self->proxy);
g_clear_object (&self->connection);
diff --git a/retro-runner/retro-core.c b/retro-runner/retro-core.c
index 784b182..d4a6e3d 100644
--- a/retro-runner/retro-core.c
+++ b/retro-runner/retro-core.c
@@ -4,6 +4,7 @@
#include <gio/gio.h>
#include <string.h>
+#include "retro-error-private.h"
#include "retro-input-private.h"
#include "retro-main-loop-source-private.h"
#include "retro-memfd-private.h"
@@ -842,57 +843,38 @@ load_discs (RetroCore *self,
{
guint length;
gboolean fullpath;
- GError *tmp_error = NULL;
- set_disk_ejected (self, TRUE, &tmp_error);
- if (G_UNLIKELY (tmp_error != NULL)) {
- g_propagate_error (error, tmp_error);
-
- return;
- }
+ retro_try_propagate ({
+ set_disk_ejected (self, TRUE, &catch);
+ }, catch, error);
length = g_strv_length (self->media_uris);
- while (get_disk_images_number (self, &tmp_error) < length &&
- (tmp_error == NULL)) {
- add_disk_image_index (self, &tmp_error);
- if (G_UNLIKELY (tmp_error != NULL)) {
- g_propagate_error (error, tmp_error);
-
- return;
+ retro_try_propagate ({
+ while (get_disk_images_number (self, &catch) < length && (catch == NULL)) {
+ retro_try_propagate ({
+ add_disk_image_index (self, &catch);
+ }, catch, error);
}
- }
-
- if (G_UNLIKELY (tmp_error != NULL)) {
- g_propagate_error (error, tmp_error);
-
- return;
- }
+ }, catch, error);
fullpath = get_needs_full_path (self);
for (gsize index = 0; index < length; index++) {
g_autoptr (RetroGameInfo) game_info = NULL;
- game_info = retro_game_info_new (self->media_uris[index], fullpath, &tmp_error);
- if (G_UNLIKELY (tmp_error != NULL)) {
- g_propagate_error (error, tmp_error);
-
- return;
- }
-
- replace_disk_image_index (self, index, game_info, &tmp_error);
- if (G_UNLIKELY (tmp_error != NULL)) {
- g_propagate_error (error, tmp_error);
+ retro_try_propagate ({
+ game_info = retro_game_info_new (self->media_uris[index],
+ fullpath,
+ &catch);
+ }, catch, error);
- return;
- }
+ retro_try_propagate ({
+ replace_disk_image_index (self, index, game_info, &catch);
+ }, catch, error);
}
- set_disk_ejected (self, FALSE, &tmp_error);
- if (G_UNLIKELY (tmp_error != NULL)) {
- g_propagate_error (error, tmp_error);
-
- return;
- }
+ retro_try_propagate ({
+ set_disk_ejected (self, FALSE, &catch);
+ }, catch, error);
}
static gboolean
@@ -949,7 +931,6 @@ load_medias (RetroCore *self,
{
guint length;
g_autoptr (RetroGameInfo) game_info = NULL;
- GError *tmp_error = NULL;
length = self->media_uris == NULL ? 0 : g_strv_length (self->media_uris);
@@ -959,24 +940,19 @@ load_medias (RetroCore *self,
return;
}
- game_info = retro_game_info_new (self->media_uris[0], get_needs_full_path (self), &tmp_error);
- if (G_UNLIKELY (tmp_error != NULL)) {
- g_propagate_error (error, tmp_error);
-
- return;
- }
+ retro_try_propagate ({
+ game_info = retro_game_info_new (self->media_uris[0],
+ get_needs_full_path (self),
+ &catch);
+ }, catch, error);
if (!load_game (self, game_info))
return;
- if (self->disk_control_callback != NULL) {
- load_discs (self, &tmp_error);
- if (G_UNLIKELY (tmp_error != NULL)) {
- g_propagate_error (error, tmp_error);
-
- return;
- }
- }
+ if (self->disk_control_callback != NULL)
+ retro_try_propagate ({
+ load_discs (self, &catch);
+ }, catch, error);
}
void retro_core_set_environment_interface (RetroCore *self);
@@ -1334,7 +1310,6 @@ retro_core_boot (RetroCore *self,
GError **error)
{
RetroInit init;
- GError *tmp_error = NULL;
g_return_if_fail (RETRO_IS_CORE (self));
@@ -1345,12 +1320,9 @@ retro_core_boot (RetroCore *self,
set_is_initiated (self, TRUE);
- load_medias (self, &tmp_error);
- if (G_UNLIKELY (tmp_error != NULL)) {
- g_propagate_error (error, tmp_error);
-
- return;
- }
+ retro_try_propagate ({
+ load_medias (self, &catch);
+ }, catch, error);
}
/**
@@ -1390,7 +1362,6 @@ retro_core_set_current_media (RetroCore *self,
GError **error)
{
guint length;
- GError *tmp_error = NULL;
g_return_if_fail (RETRO_IS_CORE (self));
@@ -1401,26 +1372,17 @@ retro_core_set_current_media (RetroCore *self,
if (self->disk_control_callback == NULL)
return;
- set_disk_ejected (self, TRUE, &tmp_error);
- if (tmp_error != NULL) {
- g_propagate_error (error, tmp_error);
-
- return;
- }
-
- set_disk_image_index (self, media_index, &tmp_error);
- if (tmp_error != NULL) {
- g_propagate_error (error, tmp_error);
-
- return;
- }
+ retro_try_propagate ({
+ set_disk_ejected (self, TRUE, &catch);
+ }, catch, error);
- set_disk_ejected (self, FALSE, &tmp_error);
- if (tmp_error != NULL) {
- g_propagate_error (error, tmp_error);
+ retro_try_propagate ({
+ set_disk_image_index (self, media_index, &catch);
+ }, catch, error);
- return;
- }
+ retro_try_propagate ({
+ set_disk_ejected (self, FALSE, &catch);
+ }, catch, error);
}
void
@@ -1701,7 +1663,6 @@ retro_core_save_state (RetroCore *self,
g_autofree guint8 *data = NULL;
gsize size;
gboolean success;
- g_autoptr (GError) tmp_error = NULL;
g_return_if_fail (RETRO_IS_CORE (self));
g_return_if_fail (filename != NULL);
@@ -1732,12 +1693,16 @@ retro_core_save_state (RetroCore *self,
return;
}
- g_file_set_contents (filename, (gchar *) data, size, &tmp_error);
- if (G_UNLIKELY (tmp_error != NULL))
+ retro_try ({
+ g_file_set_contents (filename, (gchar *) data, size, &catch);
+ }, catch, {
g_set_error (error,
RETRO_CORE_ERROR,
RETRO_CORE_ERROR_COULDNT_ACCESS_FILE,
- "Couldn't serialize the internal state: %s", tmp_error->message);
+ "Couldn't serialize the internal state: %s", catch->message);
+
+ return;
+ });
}
/**
@@ -1758,20 +1723,20 @@ retro_core_load_state (RetroCore *self,
gsize expected_size, data_size;
g_autofree gchar *data = NULL;
gboolean success;
- g_autoptr (GError) tmp_error = NULL;
g_return_if_fail (RETRO_IS_CORE (self));
g_return_if_fail (filename != NULL);
- g_file_get_contents (filename, &data, &data_size, &tmp_error);
- if (G_UNLIKELY (tmp_error != NULL)) {
+ retro_try ({
+ g_file_get_contents (filename, &data, &data_size, &catch);
+ }, catch, {
g_set_error (error,
RETRO_CORE_ERROR,
RETRO_CORE_ERROR_COULDNT_ACCESS_FILE,
- "Couldn't deserialize the internal state: %s", tmp_error->message);
+ "Couldn't deserialize the internal state: %s", catch->message);
return;
- }
+ });
/* Some cores, such as MAME and ParaLLEl N64, can only properly restore the
* state after at least one frame has been run. */
@@ -1858,7 +1823,6 @@ retro_core_save_memory (RetroCore *self,
RetroGetMemorySize get_mem_size;
gchar *data;
gsize size;
- g_autoptr (GError) tmp_error = NULL;
g_return_if_fail (RETRO_IS_CORE (self));
g_return_if_fail (filename != NULL);
@@ -1868,12 +1832,16 @@ retro_core_save_memory (RetroCore *self,
data = get_mem_data (memory_type);
size = get_mem_size (memory_type);
- g_file_set_contents (filename, data, size, &tmp_error);
- if (G_UNLIKELY (tmp_error != NULL))
+ retro_try ({
+ g_file_set_contents (filename, data, size, &catch);
+ }, catch, {
g_set_error (error,
RETRO_CORE_ERROR,
RETRO_CORE_ERROR_COULDNT_ACCESS_FILE,
- "Couldn't save the memory state: %s", tmp_error->message);
+ "Couldn't save the memory state: %s", catch->message);
+
+ return;
+ });
}
/**
@@ -1897,7 +1865,6 @@ retro_core_load_memory (RetroCore *self,
gsize memory_region_size;
g_autofree gchar *data = NULL;
gsize data_size;
- GError *tmp_error = NULL;
g_return_if_fail (RETRO_IS_CORE (self));
g_return_if_fail (filename != NULL);
@@ -1907,15 +1874,16 @@ retro_core_load_memory (RetroCore *self,
memory_region = get_mem_region (memory_type);
memory_region_size = get_mem_region_size (memory_type);
- g_file_get_contents (filename, &data, &data_size, &tmp_error);
- if (G_UNLIKELY (tmp_error != NULL)) {
+ retro_try ({
+ g_file_get_contents (filename, &data, &data_size, &catch);
+ }, catch, {
g_set_error (error,
RETRO_CORE_ERROR,
RETRO_CORE_ERROR_COULDNT_ACCESS_FILE,
- "Couldn't load the memory state: %s", tmp_error->message);
+ "Couldn't load the memory state: %s", catch->message);
return;
- }
+ });
if (memory_region == NULL) {
g_set_error (error,
diff --git a/retro-runner/retro-game-info.c b/retro-runner/retro-game-info.c
index f5c84ec..80f8c12 100644
--- a/retro-runner/retro-game-info.c
+++ b/retro-runner/retro-game-info.c
@@ -3,6 +3,7 @@
#include "retro-game-info-private.h"
#include <gio/gio.h>
+#include "retro-error-private.h"
G_DEFINE_BOXED_TYPE (RetroGameInfo, retro_game_info, retro_game_info_copy, retro_game_info_free)
@@ -22,16 +23,10 @@ retro_game_info_new (const gchar *uri,
self->path = g_file_get_path (file);
if (needs_full_path)
self->data = g_new0 (guint8, 0);
- else {
- GError *tmp_error = NULL;
-
- g_file_get_contents (self->path, (gchar **) &self->data, &self->size, &tmp_error);
- if (G_UNLIKELY (tmp_error != NULL)) {
- g_propagate_error (error, tmp_error);
-
- return NULL;
- }
- }
+ else
+ retro_try_propagate_val ({
+ g_file_get_contents (self->path, (gchar **) &self->data, &self->size, &catch);
+ }, catch, error, NULL);
return g_steal_pointer (&self);
}
diff --git a/shared/retro-error-private.h b/shared/retro-error-private.h
new file mode 100644
index 0000000..d15c548
--- /dev/null
+++ b/shared/retro-error-private.h
@@ -0,0 +1,256 @@
+// This file is part of retro-gtk. License: GPL-3.0+.
+
+#pragma once
+
+#if !defined(__RETRO_GTK_INSIDE__) && !defined(RETRO_GTK_COMPILATION)
+# error "Only <retro-gtk.h> can be included directly."
+#endif
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+/**
+ * retro_try:
+ * @try: the block that can throw an error
+ * @catch: the name for the variable storing the caught error
+ * @code: the block that can handle the caught error
+ *
+ * Creates the temporary #GError pointer named @catch, executes the @try block,
+ * then checks if an error has been caught.
+ *
+ * If an error is caught, executes the @code clock and free the caught error.
+ * If you don't want the caught error to be freed, set @caught to %NULL.
+ *
+ * If you want to propagate the caught error, consider using
+ * retro_try_propagate() and retro_try_propagate_val() instead.
+ *
+ * |[<!-- language="C" -->
+ * void
+ * my_function_that_can_fail (GError **error)
+ * {
+ * g_return_if_fail (error == NULL || *error == NULL);
+ *
+ * // Try sub_function_that_can_fail(), if it throws an error, catch it, let
+ * // you handle it in the second block, and frees it.
+ * retro_try ({
+ * sub_function_that_can_fail (&catch);
+ * }, catch, {
+ * g_debug ("Caught error: %s", catch->message);
+ * });
+ *
+ * …
+ * }
+ * ]|
+ *
+ * Error pileups are always a bug.
+ * For example, this code is incorrect:
+ * |[<!-- language="C" -->
+ * void
+ * my_function_that_can_fail (GError **error)
+ * {
+ * g_return_if_fail (error == NULL || *error == NULL);
+ *
+ * // Errors thrown by sub_function_that_can_fail() are incorrectly unhandled.
+ * retro_try_propagate ({
+ * sub_function_that_can_fail (&catch);
+ * other_function_that_can_fail (&catch);
+ * }, catch, {
+ * g_debug ("Caught error: %s", catch->message);
+ * });
+ *
+ * …
+ * }
+ * ]|
+ *
+ * You must never return from the @try block or use statements to jump out of
+ * the @try block, that would skip the error handling, defeating the purpose of
+ * using retro_try().
+ * For example, this code is incorrect:
+ * |[<!-- language="C" -->
+ * gboolean
+ * my_function_that_can_fail (GError **error)
+ * {
+ * g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+ *
+ * // Errors thrown by sub_function_that_can_fail() are incorrectly unhandled.
+ * retro_try ({
+ * return sub_function_that_can_fail (&catch);
+ * }, catch, {
+ * g_debug ("Caught error: %s", catch->message);
+ * return FALSE;
+ * });
+ *
+ * …
+ * }
+ * ]|
+ */
+#define retro_try(try, catch, code) \
+ G_STMT_START { \
+ g_autoptr (GError) catch = NULL; \
+ {try;} \
+ if (G_UNLIKELY (catch != NULL)) {code;} \
+ } G_STMT_END
+
+/**
+ * retro_try_propagate:
+ * @try: the block that can throw an error
+ * @catch: the name for the variable storing the caught error
+ * @dest: (out callee-allocates) (optional) (nullable): error return location
+ *
+ * Creates the temporary #GError pointer named @catch, executes the @try block,
+ * then checks if an error has been caught.
+ * If the function returns a value, use retro_try_propagate_val() instead.
+ *
+ * If an error is caught, it is propagated into @dest and the function returns.
+ * Otherwise, the execution continues after this block.
+ *
+ * The error variable @dest points to must be %NULL.
+ *
+ * You can't clean up before the function returns, use auto cleanups or
+ * retro_try() for that.
+ *
+ * |[<!-- language="C" -->
+ * void
+ * my_function_that_can_fail (GError **error)
+ * {
+ * g_autofree gchar *string = NULL;
+ *
+ * g_return_val_if_fail (error == NULL || *error == NULL);
+ *
+ * string = g_strdup ("I will be freed on error propagation.");
+ *
+ * // Try sub_function_that_can_fail(), if it throws an error, propagate it to
+ * // error if it isn't NULL, frees it otherwise, and return.
+ * retro_try_propagate ({
+ * sub_function_that_can_fail (&catch);
+ * }, catch, error);
+ *
+ * // If no error was caught, continue.
+ * …
+ * }
+ * ]|
+ *
+ * Error pileups are always a bug.
+ * For example, this code is incorrect:
+ * |[<!-- language="C" -->
+ * void
+ * my_function_that_can_fail (GError **error)
+ * {
+ * g_return_if_fail (error == NULL || *error == NULL);
+ *
+ * // Errors thrown by sub_function_that_can_fail() are incorrectly unhandled.
+ * retro_try_propagate ({
+ * sub_function_that_can_fail (&catch);
+ * other_function_that_can_fail (&catch);
+ * }, catch, error);
+ *
+ * …
+ * }
+ * ]|
+ *
+ * You must never return from the @try block or use statements to jump out of
+ * the @try block, that would skip the error handling, defeating the purpose of
+ * using retro_try_propagate().
+ * For example, this code is incorrect:
+ * |[<!-- language="C" -->
+ * void
+ * my_function_that_can_fail (GError **error)
+ * {
+ * g_return_if_fail (error == NULL || *error == NULL);
+ *
+ * // Errors thrown by sub_function_that_can_fail() are incorrectly unhandled.
+ * retro_try_propagate ({
+ * if (!sub_function_that_can_fail (&catch))
+ * return;
+ * }, catch, error);
+ *
+ * …
+ * }
+ * ]|
+ */
+#define retro_try_propagate(try, catch, dest) \
+ retro_try (try, catch, { g_propagate_error (dest, catch); return; })
+
+/**
+ * retro_try_propagate_val:
+ * @try: the block that can throw an error
+ * @catch: the name for the variable storing the caught error
+ * @dest: (out callee-allocates) (optional) (nullable): error return location
+ * @val: the value to return from the current function if the error is propagated
+ *
+ * Creates the temporary #GError pointer named @catch, executes the @try block,
+ * then checks if an error has been caught.
+ * If the function does not return a value, use retro_try_propagate() instead.
+ *
+ * If an error is caught, it is propagated into @dest and the function returns
+ * @val.
+ * Otherwise, the execution continues after this block.
+ *
+ * The error variable @dest points to must be %NULL.
+ *
+ * You can't clean up before the function returns, use auto cleanups or
+ * retro_try() for that.
+ *
+ * |[<!-- language="C" -->
+ * gboolean
+ * my_function_that_can_fail (GError **error)
+ * {
+ * g_autofree gchar *string = NULL;
+ *
+ * g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+ *
+ * string = g_strdup ("I will be freed on error propagation.");
+ *
+ * // Try sub_function_that_can_fail(), if it throws an error, propagate it to
+ * // error if it isn't NULL, frees it otherwise, and return.
+ * retro_try_propagate_val ({
+ * sub_function_that_can_fail (&catch);
+ * }, catch, error, FALSE);
+ *
+ * // If no error was caught, continue.
+ * …
+ * }
+ * ]|
+ *
+ * Error pileups are always a bug.
+ * For example, this code is incorrect:
+ * |[<!-- language="C" -->
+ * gboolean
+ * my_function_that_can_fail (GError **error)
+ * {
+ * g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+ *
+ * // Errors thrown by sub_function_that_can_fail() are incorrectly unhandled.
+ * retro_try_propagate_val ({
+ * sub_function_that_can_fail (&catch);
+ * other_function_that_can_fail (&catch);
+ * }, catch, error, FALSE);
+ *
+ * …
+ * }
+ * ]|
+ *
+ * You must never return from the @try block or use statements to jump out of
+ * the @try block, that would skip the error handling, defeating the purpose of
+ * using retro_try_propagate_val().
+ * For example, this code is incorrect:
+ * |[<!-- language="C" -->
+ * gboolean
+ * my_function_that_can_fail (GError **error)
+ * {
+ * g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+ *
+ * // Errors thrown by sub_function_that_can_fail() are incorrectly unhandled.
+ * retro_try_propagate_val ({
+ * return sub_function_that_can_fail (&catch);
+ * }, catch, error, FALSE);
+ *
+ * …
+ * }
+ * ]|
+ */
+#define retro_try_propagate_val(try, catch, dest, val) \
+ retro_try (try, catch, { g_propagate_error (dest, catch); return (val); })
+
+G_END_DECLS
diff --git a/tests/retro-reftest-file.c b/tests/retro-reftest-file.c
index 0ce160c..1467d09 100644
--- a/tests/retro-reftest-file.c
+++ b/tests/retro-reftest-file.c
@@ -22,6 +22,7 @@
#include <errno.h>
#include "retro-test-controller.h"
+#include "retro-error-private.h"
struct _RetroReftestFile
{
@@ -356,28 +357,25 @@ retro_reftest_file_get_core (RetroReftestFile *self,
g_auto (GStrv) key_file_medias = NULL;
gsize key_file_medias_length = 0;
g_auto (GStrv) media_uris = NULL;
- GError *tmp_error = NULL;
- key_file_core = g_key_file_get_string (self->key_file,
- RETRO_REFTEST_FILE_RETRO_REFTEST_GROUP,
- RETRO_REFTEST_FILE_CORE_KEY,
- &tmp_error);
- if (G_UNLIKELY (tmp_error != NULL)) {
- g_propagate_error (error, tmp_error);
-
- return NULL;
- }
+ retro_try_propagate_val ({
+ key_file_core = g_key_file_get_string (self->key_file,
+ RETRO_REFTEST_FILE_RETRO_REFTEST_GROUP,
+ RETRO_REFTEST_FILE_CORE_KEY,
+ &catch);
+ }, catch, error, NULL);
core_file = get_sibling (self, key_file_core);
path = g_file_get_path (core_file);
core = retro_core_new (path);
- key_file_medias = g_key_file_get_string_list (self->key_file,
- RETRO_REFTEST_FILE_RETRO_REFTEST_GROUP,
- RETRO_REFTEST_FILE_MEDIAS_KEY,
- &key_file_medias_length,
- &tmp_error);
- g_clear_error (&tmp_error);
+ retro_try ({
+ key_file_medias = g_key_file_get_string_list (self->key_file,
+ RETRO_REFTEST_FILE_RETRO_REFTEST_GROUP,
+ RETRO_REFTEST_FILE_MEDIAS_KEY,
+ &key_file_medias_length,
+ &catch);
+ }, catch, {});
if (key_file_medias == NULL)
return core;
@@ -411,32 +409,25 @@ retro_reftest_file_get_options (RetroReftestFile *self,
g_auto (GStrv) keys = NULL;
gsize keys_length = 0;
g_autoptr (GHashTable) options = NULL;
- GError *tmp_error = NULL;
- keys = g_key_file_get_keys (self->key_file,
- RETRO_REFTEST_FILE_OPTIONS_GROUP,
- &keys_length,
- &tmp_error);
- if (G_UNLIKELY (tmp_error != NULL)) {
- g_propagate_error (error, tmp_error);
-
- return NULL;
- }
+ retro_try_propagate_val ({
+ keys = g_key_file_get_keys (self->key_file,
+ RETRO_REFTEST_FILE_OPTIONS_GROUP,
+ &keys_length,
+ &catch);
+ }, catch, error, NULL);
options = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_strfreev);
for (gsize i = 0; i < keys_length; i++) {
g_auto (GStrv) values = NULL;
- values = g_key_file_get_string_list (self->key_file,
- RETRO_REFTEST_FILE_OPTIONS_GROUP,
- keys[i],
- NULL,
- &tmp_error);
- if (G_UNLIKELY (tmp_error != NULL)) {
- g_propagate_error (error, tmp_error);
-
- return NULL;
- }
+ retro_try_propagate_val ({
+ values = g_key_file_get_string_list (self->key_file,
+ RETRO_REFTEST_FILE_OPTIONS_GROUP,
+ keys[i],
+ NULL,
+ &catch);
+ }, catch, error, NULL);
g_hash_table_insert (options, g_strdup (keys[i]), g_steal_pointer (&values));
}
@@ -453,31 +444,24 @@ retro_reftest_file_get_controllers (RetroReftestFile *self,
g_auto (GStrv) controller_names = NULL;
g_autoptr (GArray) controllers = NULL;
RetroControllerType type;
- GError *tmp_error = NULL;
- has_controllers = g_key_file_has_key (self->key_file,
- RETRO_REFTEST_FILE_RETRO_REFTEST_GROUP,
- RETRO_REFTEST_FILE_CONTROLLERS_KEY,
- &tmp_error);
- if (G_UNLIKELY (tmp_error != NULL)) {
- g_propagate_error (error, tmp_error);
-
- return NULL;
- }
+ retro_try_propagate_val ({
+ has_controllers = g_key_file_has_key (self->key_file,
+ RETRO_REFTEST_FILE_RETRO_REFTEST_GROUP,
+ RETRO_REFTEST_FILE_CONTROLLERS_KEY,
+ &catch);
+ }, catch, error, NULL);
if (!has_controllers)
return NULL;
- controller_names = g_key_file_get_string_list (self->key_file,
- RETRO_REFTEST_FILE_RETRO_REFTEST_GROUP,
- RETRO_REFTEST_FILE_CONTROLLERS_KEY,
- length,
- &tmp_error);
- if (G_UNLIKELY (tmp_error != NULL)) {
- g_propagate_error (error, tmp_error);
-
- return NULL;
- }
+ retro_try_propagate_val ({
+ controller_names = g_key_file_get_string_list (self->key_file,
+ RETRO_REFTEST_FILE_RETRO_REFTEST_GROUP,
+ RETRO_REFTEST_FILE_CONTROLLERS_KEY,
+ length,
+ &catch);
+ }, catch, error, NULL);
controllers = g_array_sized_new (TRUE, TRUE, sizeof (RetroTestController *), *length);
g_array_set_clear_func (controllers, (GDestroyNotify) g_object_pointer_unref);
@@ -584,17 +568,13 @@ retro_reftest_file_get_video (RetroReftestFile *self,
GError **error)
{
g_autofree gchar *key_file_video = NULL;
- GError *tmp_error = NULL;
- key_file_video = g_key_file_get_string (self->key_file,
- g_hash_table_lookup (self->frames, &frame),
- RETRO_REFTEST_FILE_FRAME_VIDEO_KEY,
- &tmp_error);
- if (G_UNLIKELY (tmp_error != NULL)) {
- g_propagate_error (error, tmp_error);
-
- return NULL;
- }
+ retro_try_propagate_val ({
+ key_file_video = g_key_file_get_string (self->key_file,
+ g_hash_table_lookup (self->frames, &frame),
+ RETRO_REFTEST_FILE_FRAME_VIDEO_KEY,
+ &catch);
+ }, catch, error, NULL);
return get_sibling (self, key_file_video);
}
@@ -609,15 +589,11 @@ retro_reftest_file_get_controller_states (RetroReftestFile *self,
g_auto (GStrv) keys = NULL;
RetroControllerState *state;
GArray *states;
- GError *tmp_error = NULL;
group = g_hash_table_lookup (self->frames, &frame);
- keys = g_key_file_get_keys (self->key_file, group, NULL, &tmp_error);
- if (G_UNLIKELY (tmp_error != NULL)) {
- g_propagate_error (error, tmp_error);
-
- return NULL;
- }
+ retro_try_propagate_val ({
+ keys = g_key_file_get_keys (self->key_file, group, NULL, &catch);
+ }, catch, error, NULL);
controllers = g_hash_table_new_full (g_int_hash, g_int_equal, g_free, (GDestroyNotify) g_array_unref);
@@ -631,21 +607,21 @@ retro_reftest_file_get_controller_states (RetroReftestFile *self,
controller_number_string = *key_i + strlen (RETRO_REFTEST_FILE_FRAME_CONTROLLER_PREFIX);
controller_number = g_new (guint, 1);
- *controller_number = str_to_uint (controller_number_string, &tmp_error);
- if (G_UNLIKELY (tmp_error != NULL)) {
- g_critical ("Invalid controller key [%s]: %s", *key_i, tmp_error->message);
- g_clear_error (&tmp_error);
+ retro_try ({
+ *controller_number = str_to_uint (controller_number_string, &catch);
+ }, catch, {
+ g_critical ("Invalid controller key [%s]: %s", *key_i, catch->message);
continue;
- }
+ });
- inputs = g_key_file_get_string_list (self->key_file, group, *key_i, NULL, &tmp_error);
- if (G_UNLIKELY (tmp_error != NULL)) {
- g_critical ("%s", tmp_error->message);
- g_clear_error (&tmp_error);
+ retro_try ({
+ inputs = g_key_file_get_string_list (self->key_file, group, *key_i, NULL, &catch);
+ }, catch, {
+ g_critical ("%s", catch->message);
continue;
- }
+ });
states = g_array_new (TRUE, TRUE, sizeof (RetroControllerState *));
g_array_set_clear_func (states, (GDestroyNotify) g_pointer_free);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]