mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-23 10:42:11 +01:00
Merge branch 'avoid-resource-allocation' into 'main'
resource: Add g_resource[s]_has_children and avoid a pointless allocation See merge request GNOME/glib!4245
This commit is contained in:
commit
744cdd0f0d
@ -11,11 +11,11 @@ cache:
|
||||
- _ccache/
|
||||
|
||||
variables:
|
||||
FEDORA_IMAGE: "registry.gitlab.gnome.org/gnome/glib/fedora:v39.2"
|
||||
FEDORA_IMAGE: "registry.gitlab.gnome.org/gnome/glib/fedora:v39.3"
|
||||
COVERITY_IMAGE: "registry.gitlab.gnome.org/gnome/glib/coverity:v7"
|
||||
DEBIAN_IMAGE: "registry.gitlab.gnome.org/gnome/glib/debian-stable:v20"
|
||||
ALPINE_IMAGE: "registry.gitlab.gnome.org/gnome/glib/alpine:v4"
|
||||
MINGW_IMAGE: "registry.gitlab.gnome.org/gnome/glib/mingw:v39.2"
|
||||
DEBIAN_IMAGE: "registry.gitlab.gnome.org/gnome/glib/debian-stable:v21"
|
||||
ALPINE_IMAGE: "registry.gitlab.gnome.org/gnome/glib/alpine:v5"
|
||||
MINGW_IMAGE: "registry.gitlab.gnome.org/gnome/glib/mingw:v39.3"
|
||||
GOBJECT_INTROSPECTION_TAG: "1.80.1"
|
||||
MESON_TEST_TIMEOUT_MULTIPLIER: 4
|
||||
G_MESSAGES_DEBUG: all
|
||||
@ -584,6 +584,8 @@ vs2017-x64:
|
||||
- win32-ps
|
||||
needs: []
|
||||
variables:
|
||||
GIT_SUBMODULE_STRATEGY: recursive
|
||||
GIT_SUBMODULE_DEPTH: 1
|
||||
PYTHONUTF8: "1"
|
||||
script:
|
||||
# FIXME: These should use --wrap-mode=nodownload but the Windows CI machines
|
||||
@ -615,6 +617,8 @@ vs2017-x64-static:
|
||||
- win32-ps
|
||||
needs: []
|
||||
variables:
|
||||
GIT_SUBMODULE_STRATEGY: recursive
|
||||
GIT_SUBMODULE_DEPTH: 1
|
||||
PYTHONUTF8: "1"
|
||||
script:
|
||||
# FIXME: These should use --wrap-mode=nodownload but the Windows CI machines
|
||||
|
@ -1,4 +1,4 @@
|
||||
FROM registry.gitlab.gnome.org/gnome/glib/fedora:v39.2
|
||||
FROM registry.gitlab.gnome.org/gnome/glib/fedora:v39.3
|
||||
|
||||
USER root
|
||||
|
||||
|
2
.gitmodules
vendored
2
.gitmodules
vendored
@ -1,5 +1,5 @@
|
||||
[submodule "subprojects/gvdb"]
|
||||
path = subprojects/gvdb
|
||||
url = ../../GNOME/gvdb.git
|
||||
branch = 0854af0fdb6d527a8d1999835ac2c5059976c210
|
||||
branch = 2b42fc75f09dbe1cd1057580b5782b08f2dcb400
|
||||
shallow = true
|
||||
|
150
gio/gresource.c
150
gio/gresource.c
@ -923,6 +923,44 @@ g_resource_get_info (GResource *resource,
|
||||
return do_lookup (resource, path, lookup_flags, size, flags, NULL, NULL, error);
|
||||
}
|
||||
|
||||
static inline const char *
|
||||
ensure_slash_suffix (const char *path,
|
||||
char *local_str,
|
||||
gsize len,
|
||||
char **free_path)
|
||||
{
|
||||
gsize path_len;
|
||||
|
||||
path_len = strlen (path);
|
||||
|
||||
if G_UNLIKELY (path[path_len-1] != '/')
|
||||
{
|
||||
if (path_len < len - 2)
|
||||
{
|
||||
/*
|
||||
* We got a path that does not have a trailing /. It is not the
|
||||
* ideal use of this API as we require trailing / for our lookup
|
||||
* into gvdb. Some degenerate application configurations can hit
|
||||
* this code path quite a bit, so we try to avoid using the
|
||||
* g_strconcat()/g_free().
|
||||
*/
|
||||
memcpy (local_str, path, path_len);
|
||||
local_str[path_len] = '/';
|
||||
local_str[path_len+1] = 0;
|
||||
return local_str;
|
||||
}
|
||||
else
|
||||
{
|
||||
*free_path = g_strconcat (path, "/", NULL);
|
||||
return *free_path;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* g_resource_enumerate_children:
|
||||
* @resource: A #GResource
|
||||
@ -949,17 +987,14 @@ g_resource_enumerate_children (GResource *resource,
|
||||
GResourceLookupFlags lookup_flags,
|
||||
GError **error)
|
||||
{
|
||||
gchar local_str[256];
|
||||
const gchar *path_with_slash;
|
||||
gchar **children;
|
||||
gchar *free_path = NULL;
|
||||
gsize path_len;
|
||||
|
||||
/*
|
||||
* Size of 256 is arbitrarily chosen based on being large enough
|
||||
/* Size of 256 is arbitrarily chosen based on being large enough
|
||||
* for pretty much everything we come across, but not cumbersome
|
||||
* on the stack. It also matches common cacheline sizes.
|
||||
*/
|
||||
gchar local_str[256];
|
||||
const char *path_with_slash;
|
||||
char *free_path = NULL;
|
||||
gchar **children;
|
||||
|
||||
if (*path == 0)
|
||||
{
|
||||
@ -970,35 +1005,10 @@ g_resource_enumerate_children (GResource *resource,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
path_len = strlen (path);
|
||||
|
||||
if G_UNLIKELY (path[path_len-1] != '/')
|
||||
{
|
||||
if (path_len < sizeof (local_str) - 2)
|
||||
{
|
||||
/*
|
||||
* We got a path that does not have a trailing /. It is not the
|
||||
* ideal use of this API as we require trailing / for our lookup
|
||||
* into gvdb. Some degenerate application configurations can hit
|
||||
* this code path quite a bit, so we try to avoid using the
|
||||
* g_strconcat()/g_free().
|
||||
*/
|
||||
memcpy (local_str, path, path_len);
|
||||
local_str[path_len] = '/';
|
||||
local_str[path_len+1] = 0;
|
||||
path_with_slash = local_str;
|
||||
}
|
||||
else
|
||||
{
|
||||
path_with_slash = free_path = g_strconcat (path, "/", NULL);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
path_with_slash = path;
|
||||
}
|
||||
path_with_slash = ensure_slash_suffix (path, local_str, sizeof (local_str), &free_path);
|
||||
|
||||
children = gvdb_table_list (resource->table, path_with_slash);
|
||||
|
||||
g_free (free_path);
|
||||
|
||||
if (children == NULL)
|
||||
@ -1013,6 +1023,43 @@ g_resource_enumerate_children (GResource *resource,
|
||||
return children;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_resource_has_children:
|
||||
* @resource: A #GResource
|
||||
* @path: A pathname inside the resource
|
||||
*
|
||||
* Returns whether the specified @path in the resource
|
||||
* has children.
|
||||
*
|
||||
* Returns: %TRUE if @path has children
|
||||
*
|
||||
* Since: 2.84
|
||||
*/
|
||||
gboolean
|
||||
g_resource_has_children (GResource *resource,
|
||||
const char *path)
|
||||
{
|
||||
/* Size of 256 is arbitrarily chosen based on being large enough
|
||||
* for pretty much everything we come across, but not cumbersome
|
||||
* on the stack. It also matches common cacheline sizes.
|
||||
*/
|
||||
char local_str[256];
|
||||
const char *path_with_slash;
|
||||
guint n;
|
||||
char *freeme = NULL;
|
||||
|
||||
if (*path == 0)
|
||||
return FALSE;
|
||||
|
||||
path_with_slash = ensure_slash_suffix (path, local_str, sizeof (local_str), &freeme);
|
||||
|
||||
n = gvdb_table_n_children (resource->table, path_with_slash);
|
||||
|
||||
g_free (freeme);
|
||||
|
||||
return n > 0;
|
||||
}
|
||||
|
||||
static GRWLock resources_lock;
|
||||
static GList *registered_resources;
|
||||
|
||||
@ -1291,6 +1338,39 @@ g_resources_enumerate_children (const gchar *path,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* g_resources_has_children:
|
||||
* @path: A pathname
|
||||
*
|
||||
* Returns whether the specified @path in the set of
|
||||
* globally registered resources has children.
|
||||
*
|
||||
* Returns: %TRUE if @patch has children
|
||||
*
|
||||
* Since: 2.84
|
||||
*/
|
||||
gboolean
|
||||
g_resources_has_children (const char *path)
|
||||
{
|
||||
register_lazy_static_resources ();
|
||||
|
||||
g_rw_lock_reader_lock (&resources_lock);
|
||||
|
||||
for (GList *l = registered_resources; l != NULL; l = l->next)
|
||||
{
|
||||
GResource *r = l->data;
|
||||
|
||||
if (g_resource_has_children (r, path))
|
||||
{
|
||||
g_rw_lock_reader_unlock (&resources_lock);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
g_rw_lock_reader_unlock (&resources_lock);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_resources_get_info:
|
||||
* @path: A pathname inside the resource
|
||||
|
@ -119,6 +119,12 @@ gboolean g_resources_get_info (const char *path,
|
||||
guint32 *flags,
|
||||
GError **error);
|
||||
|
||||
GIO_AVAILABLE_IN_2_84
|
||||
gboolean g_resource_has_children (GResource *resource,
|
||||
const char *path);
|
||||
GIO_AVAILABLE_IN_2_84
|
||||
gboolean g_resources_has_children (const char *path);
|
||||
|
||||
|
||||
GIO_AVAILABLE_IN_2_32
|
||||
void g_static_resource_init (GStaticResource *static_resource);
|
||||
|
@ -455,21 +455,14 @@ g_resource_file_query_info (GFile *file,
|
||||
gboolean res;
|
||||
gsize size = 0;
|
||||
guint32 resource_flags = 0;
|
||||
char **children;
|
||||
gboolean is_dir;
|
||||
char *base;
|
||||
|
||||
is_dir = FALSE;
|
||||
children = g_resources_enumerate_children (resource->path, 0, NULL);
|
||||
if (children != NULL)
|
||||
{
|
||||
g_strfreev (children);
|
||||
is_dir = TRUE;
|
||||
}
|
||||
|
||||
/* root is always there */
|
||||
if (strcmp ("/", resource->path) == 0)
|
||||
is_dir = TRUE;
|
||||
else
|
||||
is_dir = g_resources_has_children (resource->path);
|
||||
|
||||
if (!is_dir)
|
||||
{
|
||||
|
@ -1046,6 +1046,31 @@ test_overlay (void)
|
||||
g_test_trap_assert_passed ();
|
||||
}
|
||||
|
||||
static void
|
||||
test_resource_has_children (void)
|
||||
{
|
||||
GResource *resource;
|
||||
GError *error = NULL;
|
||||
|
||||
g_assert_true (g_resources_has_children ("/auto_loaded"));
|
||||
g_assert_true (g_resources_has_children ("/auto_loaded/"));
|
||||
g_assert_false (g_resources_has_children ("/auto_loaded/test1.txt"));
|
||||
g_assert_false (g_resources_has_children ("/no/such/prefix"));
|
||||
g_assert_false (g_resources_has_children (""));
|
||||
|
||||
resource = g_resource_load (g_test_get_filename (G_TEST_BUILT, "test.gresource", NULL), &error);
|
||||
g_assert_nonnull (resource);
|
||||
g_assert_no_error (error);
|
||||
|
||||
g_assert_true (g_resource_has_children (resource, "/a_prefix"));
|
||||
g_assert_true (g_resource_has_children (resource, "/a_prefix/"));
|
||||
g_assert_false (g_resource_has_children (resource, "/a_prefix/test2.txt"));
|
||||
g_assert_false (g_resource_has_children (resource, "/no/such/prefix"));
|
||||
g_assert_false (g_resource_has_children (resource, ""));
|
||||
|
||||
g_resource_unref (resource);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char *argv[])
|
||||
@ -1075,6 +1100,7 @@ main (int argc,
|
||||
g_test_add_func ("/resource/64k", test_resource_64k);
|
||||
g_test_add_func ("/resource/overlay", test_overlay);
|
||||
g_test_add_func ("/resource/digits", test_resource_digits);
|
||||
g_test_add_func ("/resource/has-children", test_resource_has_children);
|
||||
|
||||
return g_test_run();
|
||||
}
|
||||
|
@ -2239,7 +2239,7 @@ else
|
||||
endif
|
||||
|
||||
# Import the gvdb sources as a subproject to avoid having the copylib in-tree
|
||||
subproject('gvdb')
|
||||
subproject('gvdb', default_options: {'tests': false})
|
||||
gvdb_dep = dependency('gvdb')
|
||||
|
||||
libm = cc.find_library('m', required : false)
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 0854af0fdb6d527a8d1999835ac2c5059976c210
|
||||
Subproject commit 2b42fc75f09dbe1cd1057580b5782b08f2dcb400
|
@ -1,7 +1,7 @@
|
||||
[wrap-git]
|
||||
directory=gvdb
|
||||
url=https://gitlab.gnome.org/GNOME/gvdb.git
|
||||
revision=0854af0fdb6d527a8d1999835ac2c5059976c210
|
||||
revision=2b42fc75f09dbe1cd1057580b5782b08f2dcb400
|
||||
depth=1
|
||||
|
||||
[provide]
|
||||
|
Loading…
x
Reference in New Issue
Block a user