mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-03 01:36:17 +01:00
Merge branch 'wip/chergert/gvariant-inline-suffix-data' into 'main'
glib/gvariant: Inline small gvariant data using C99 flexible arrays See merge request GNOME/glib!4301
This commit is contained in:
commit
019de2cbbc
@ -75,8 +75,15 @@ struct _GVariant
|
|||||||
gint state;
|
gint state;
|
||||||
gatomicrefcount ref_count;
|
gatomicrefcount ref_count;
|
||||||
gsize depth;
|
gsize depth;
|
||||||
|
|
||||||
|
guint8 suffix[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Ensure our suffix data aligns to largest guaranteed offset
|
||||||
|
* within GVariant, of 8 bytes.
|
||||||
|
*/
|
||||||
|
G_STATIC_ASSERT (G_STRUCT_OFFSET (GVariant, suffix) % 8 == 0);
|
||||||
|
|
||||||
/* struct GVariant:
|
/* struct GVariant:
|
||||||
*
|
*
|
||||||
* There are two primary forms of GVariant instances: "serialized form"
|
* There are two primary forms of GVariant instances: "serialized form"
|
||||||
@ -543,21 +550,31 @@ g_variant_ensure_serialised (GVariant *value)
|
|||||||
* @type: the type of the new instance
|
* @type: the type of the new instance
|
||||||
* @serialised: if the instance will be in serialised form
|
* @serialised: if the instance will be in serialised form
|
||||||
* @trusted: if the instance will be trusted
|
* @trusted: if the instance will be trusted
|
||||||
|
* @suffix_size: amount of extra bytes to add to allocation
|
||||||
*
|
*
|
||||||
* Allocates a #GVariant instance and does some common work (such as
|
* Allocates a #GVariant instance and does some common work (such as
|
||||||
* looking up and filling in the type info), setting the state field,
|
* looking up and filling in the type info), setting the state field,
|
||||||
* and setting the ref_count to 1.
|
* and setting the ref_count to 1.
|
||||||
*
|
*
|
||||||
|
* Use @suffix_size when you want to store data inside of the GVariant
|
||||||
|
* without having to add an additional GBytes allocation.
|
||||||
|
*
|
||||||
* Returns: a new #GVariant with a floating reference
|
* Returns: a new #GVariant with a floating reference
|
||||||
*/
|
*/
|
||||||
static GVariant *
|
static GVariant *
|
||||||
g_variant_alloc (const GVariantType *type,
|
g_variant_alloc (const GVariantType *type,
|
||||||
gboolean serialised,
|
gboolean serialised,
|
||||||
gboolean trusted)
|
gboolean trusted,
|
||||||
|
gsize suffix_size)
|
||||||
{
|
{
|
||||||
|
G_GNUC_UNUSED gboolean size_check;
|
||||||
GVariant *value;
|
GVariant *value;
|
||||||
|
gsize size;
|
||||||
|
|
||||||
value = g_slice_new (GVariant);
|
size_check = g_size_checked_add (&size, sizeof *value, suffix_size);
|
||||||
|
g_assert (size_check);
|
||||||
|
|
||||||
|
value = g_malloc (size);
|
||||||
value->type_info = g_variant_type_info_get (type);
|
value->type_info = g_variant_type_info_get (type);
|
||||||
value->state = (serialised ? STATE_SERIALISED : 0) |
|
value->state = (serialised ? STATE_SERIALISED : 0) |
|
||||||
(trusted ? STATE_TRUSTED : 0) |
|
(trusted ? STATE_TRUSTED : 0) |
|
||||||
@ -599,6 +616,54 @@ g_variant_new_from_bytes (const GVariantType *type,
|
|||||||
|
|
||||||
/* -- internal -- */
|
/* -- internal -- */
|
||||||
|
|
||||||
|
/* < internal >
|
||||||
|
* g_variant_new_preallocated_trusted:
|
||||||
|
* @data: data to copy
|
||||||
|
* @size: the size of data
|
||||||
|
*
|
||||||
|
* Creates a new #GVariant for simple types such as int32, double, or
|
||||||
|
* bytes.
|
||||||
|
*
|
||||||
|
* Instead of allocating a GBytes, the data will be stored at the tail of
|
||||||
|
* the GVariant structures allocation. This can save considerable malloc
|
||||||
|
* overhead.
|
||||||
|
*
|
||||||
|
* The data is always aligned to the maximum alignment GVariant provides
|
||||||
|
* which is 8 bytes and therefore does not need to verify alignment based
|
||||||
|
* on the the @type provided.
|
||||||
|
*
|
||||||
|
* This should only be used for creating GVariant with trusted data.
|
||||||
|
*
|
||||||
|
* Returns: a new #GVariant with a floating reference
|
||||||
|
*/
|
||||||
|
GVariant *
|
||||||
|
g_variant_new_preallocated_trusted (const GVariantType *type,
|
||||||
|
gconstpointer data,
|
||||||
|
gsize size)
|
||||||
|
{
|
||||||
|
GVariant *value;
|
||||||
|
gsize expected_size;
|
||||||
|
guint alignment;
|
||||||
|
|
||||||
|
value = g_variant_alloc (type, TRUE, TRUE, size);
|
||||||
|
|
||||||
|
g_variant_type_info_query (value->type_info, &alignment, &expected_size);
|
||||||
|
|
||||||
|
g_assert (expected_size == 0 || size == expected_size);
|
||||||
|
|
||||||
|
value->contents.serialised.ordered_offsets_up_to = G_MAXSIZE;
|
||||||
|
value->contents.serialised.checked_offsets_up_to = G_MAXSIZE;
|
||||||
|
value->contents.serialised.bytes = NULL;
|
||||||
|
value->contents.serialised.data = value->suffix;
|
||||||
|
value->size = size;
|
||||||
|
|
||||||
|
memcpy (value->suffix, data, size);
|
||||||
|
|
||||||
|
TRACE(GLIB_VARIANT_FROM_BUFFER(value, value->type_info, value->ref_count, value->state));
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
/* < internal >
|
/* < internal >
|
||||||
* g_variant_new_take_bytes:
|
* g_variant_new_take_bytes:
|
||||||
* @bytes: (transfer full): a #GBytes
|
* @bytes: (transfer full): a #GBytes
|
||||||
@ -620,7 +685,7 @@ g_variant_new_take_bytes (const GVariantType *type,
|
|||||||
GBytes *owned_bytes = NULL;
|
GBytes *owned_bytes = NULL;
|
||||||
GVariantSerialised serialised;
|
GVariantSerialised serialised;
|
||||||
|
|
||||||
value = g_variant_alloc (type, TRUE, trusted);
|
value = g_variant_alloc (type, TRUE, trusted, 0);
|
||||||
|
|
||||||
g_variant_type_info_query (value->type_info,
|
g_variant_type_info_query (value->type_info,
|
||||||
&alignment, &size);
|
&alignment, &size);
|
||||||
@ -728,7 +793,7 @@ g_variant_new_from_children (const GVariantType *type,
|
|||||||
{
|
{
|
||||||
GVariant *value;
|
GVariant *value;
|
||||||
|
|
||||||
value = g_variant_alloc (type, FALSE, trusted);
|
value = g_variant_alloc (type, FALSE, trusted, 0);
|
||||||
value->contents.tree.children = children;
|
value->contents.tree.children = children;
|
||||||
value->contents.tree.n_children = n_children;
|
value->contents.tree.n_children = n_children;
|
||||||
TRACE(GLIB_VARIANT_FROM_CHILDREN(value, value->type_info, value->ref_count, value->state));
|
TRACE(GLIB_VARIANT_FROM_CHILDREN(value, value->type_info, value->ref_count, value->state));
|
||||||
@ -823,7 +888,7 @@ g_variant_unref (GVariant *value)
|
|||||||
g_variant_release_children (value);
|
g_variant_release_children (value);
|
||||||
|
|
||||||
memset (value, 0, sizeof (GVariant));
|
memset (value, 0, sizeof (GVariant));
|
||||||
g_slice_free (GVariant, value);
|
g_free (value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1074,14 +1139,18 @@ g_variant_get_data_as_bytes (GVariant *value)
|
|||||||
{
|
{
|
||||||
const gchar *bytes_data;
|
const gchar *bytes_data;
|
||||||
const gchar *data;
|
const gchar *data;
|
||||||
gsize bytes_size;
|
gsize bytes_size = 0;
|
||||||
gsize size;
|
gsize size;
|
||||||
|
|
||||||
g_variant_lock (value);
|
g_variant_lock (value);
|
||||||
g_variant_ensure_serialised (value);
|
g_variant_ensure_serialised (value);
|
||||||
g_variant_unlock (value);
|
g_variant_unlock (value);
|
||||||
|
|
||||||
bytes_data = g_bytes_get_data (value->contents.serialised.bytes, &bytes_size);
|
if (value->contents.serialised.bytes != NULL)
|
||||||
|
bytes_data = g_bytes_get_data (value->contents.serialised.bytes, &bytes_size);
|
||||||
|
else
|
||||||
|
bytes_data = NULL;
|
||||||
|
|
||||||
data = value->contents.serialised.data;
|
data = value->contents.serialised.data;
|
||||||
size = value->size;
|
size = value->size;
|
||||||
|
|
||||||
@ -1091,11 +1160,13 @@ g_variant_get_data_as_bytes (GVariant *value)
|
|||||||
data = bytes_data;
|
data = bytes_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data == bytes_data && size == bytes_size)
|
if (bytes_data != NULL && data == bytes_data && size == bytes_size)
|
||||||
return g_bytes_ref (value->contents.serialised.bytes);
|
return g_bytes_ref (value->contents.serialised.bytes);
|
||||||
else
|
else if (bytes_data != NULL)
|
||||||
return g_bytes_new_from_bytes (value->contents.serialised.bytes,
|
return g_bytes_new_from_bytes (value->contents.serialised.bytes,
|
||||||
data - bytes_data, size);
|
data - bytes_data, size);
|
||||||
|
else
|
||||||
|
return g_bytes_new (value->contents.serialised.data, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1226,7 +1297,7 @@ g_variant_get_child_value (GVariant *value,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* create a new serialized instance out of it */
|
/* create a new serialized instance out of it */
|
||||||
child = g_slice_new (GVariant);
|
child = g_new (GVariant, 1);
|
||||||
child->type_info = s_child.type_info;
|
child->type_info = s_child.type_info;
|
||||||
child->state = (value->state & STATE_TRUSTED) |
|
child->state = (value->state & STATE_TRUSTED) |
|
||||||
STATE_SERIALISED;
|
STATE_SERIALISED;
|
||||||
|
@ -25,8 +25,17 @@
|
|||||||
#include <glib/gvariant.h>
|
#include <glib/gvariant.h>
|
||||||
#include <glib/gbytes.h>
|
#include <glib/gbytes.h>
|
||||||
|
|
||||||
|
#if GLIB_SIZEOF_VOID_P == 8
|
||||||
|
# define G_VARIANT_MAX_PREALLOCATED 64
|
||||||
|
#else
|
||||||
|
# define G_VARIANT_MAX_PREALLOCATED 32
|
||||||
|
#endif
|
||||||
|
|
||||||
/* gvariant-core.c */
|
/* gvariant-core.c */
|
||||||
|
|
||||||
|
GVariant * g_variant_new_preallocated_trusted (const GVariantType *type,
|
||||||
|
gconstpointer data,
|
||||||
|
gsize size);
|
||||||
GVariant * g_variant_new_take_bytes (const GVariantType *type,
|
GVariant * g_variant_new_take_bytes (const GVariantType *type,
|
||||||
GBytes *bytes,
|
GBytes *bytes,
|
||||||
gboolean trusted);
|
gboolean trusted);
|
||||||
|
@ -321,7 +321,10 @@ g_variant_new_from_trusted (const GVariantType *type,
|
|||||||
gconstpointer data,
|
gconstpointer data,
|
||||||
gsize size)
|
gsize size)
|
||||||
{
|
{
|
||||||
return g_variant_new_take_bytes (type, g_bytes_new (data, size), TRUE);
|
if (size <= G_VARIANT_MAX_PREALLOCATED)
|
||||||
|
return g_variant_new_preallocated_trusted (type, data, size);
|
||||||
|
else
|
||||||
|
return g_variant_new_take_bytes (type, g_bytes_new (data, size), TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user