gresource: Remove unnecessary errors from g_resources_lookup_data()

This is slightly more involved than the previous couple of commits, as
`g_resource_lookup_data()` can return two errors: one if the resource is
not found, and another if decompression fails.

We want to avoid allocating the `G_RESOURCE_ERROR_NOT_FOUND` error, as
`g_resources_lookup_data()` will be looping through multiple
`GResource`s trying to find the given path, and all but one of them will
return `G_RESOURCE_ERROR_NOT_FOUND`. For a large application, this can
amount to a lot of `GError`s allocated and then immediately freed on
startup.

Use the split from the previous commit to replace the call to
`g_resource_lookup_data()` with its two constituent parts. We can then
handle errors from them separately, ignoring the `NOT_FOUND` error from
`do_lookup()`, while paying attention to any errors from
`resource_to_bytes()`.

This should result in no functional difference to
`g_resources_lookup_data()`, but fewer allocations overall.

Spotted by Christian Hergert.

Signed-off-by: Philip Withnall <pwithnall@gnome.org>

Helps: #3465
This commit is contained in:
Philip Withnall 2024-09-05 12:20:01 +01:00
parent 68a9b9d3ca
commit 8b13f8854a
No known key found for this signature in database
GPG Key ID: DCDF5885B1F3ED73

View File

@ -834,6 +834,10 @@ static GBytes *resource_to_bytes (GResource *resource,
* *
* @lookup_flags controls the behaviour of the lookup. * @lookup_flags controls the behaviour of the lookup.
* *
* This can return error %G_RESOURCE_ERROR_NOT_FOUND if @path was not found in
* @resource, or %G_RESOURCE_ERROR_INTERNAL if decompression of a compressed
* resource failed.
*
* Returns: (transfer full): #GBytes or %NULL on error. * Returns: (transfer full): #GBytes or %NULL on error.
* Free the returned object with g_bytes_unref() * Free the returned object with g_bytes_unref()
* *
@ -1195,7 +1199,6 @@ g_resources_lookup_data (const gchar *path,
{ {
GBytes *res = NULL; GBytes *res = NULL;
GList *l; GList *l;
GBytes *data;
if (g_resource_find_overlay (path, get_overlay_bytes, &res)) if (g_resource_find_overlay (path, get_overlay_bytes, &res))
return res; return res;
@ -1207,19 +1210,16 @@ g_resources_lookup_data (const gchar *path,
for (l = registered_resources; l != NULL; l = l->next) for (l = registered_resources; l != NULL; l = l->next)
{ {
GResource *r = l->data; GResource *r = l->data;
GError *my_error = NULL; const void *data;
guint32 flags;
gsize data_size;
gsize size;
data = g_resource_lookup_data (r, path, lookup_flags, &my_error); /* This is essentially g_resource_lookup_data(), but split up so we can
if (data == NULL && * avoid allocating a #GError if the resource is not found. */
g_error_matches (my_error, G_RESOURCE_ERROR, G_RESOURCE_ERROR_NOT_FOUND)) if (do_lookup (r, path, lookup_flags, &size, &flags, &data, &data_size, NULL))
{ {
g_clear_error (&my_error); res = resource_to_bytes (r, path, size, data, data_size, flags, error);
}
else
{
if (data == NULL)
g_propagate_error (error, my_error);
res = data;
break; break;
} }
} }