mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-11-30 13:58:19 +01:00
GVariant: support serialising to GVariantVectors
Add code for serialising GVariant to GVariantVectors. Export that internally via the glib-private machanism so that we can use it from GDBus.
This commit is contained in:
@@ -44,7 +44,9 @@ glib__private__ (void)
|
||||
g_main_context_new_with_next_id,
|
||||
|
||||
g_dir_open_with_errno,
|
||||
g_dir_new_from_dirp
|
||||
g_dir_new_from_dirp,
|
||||
|
||||
g_variant_to_vectors
|
||||
};
|
||||
|
||||
return &table;
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
#include <glib.h>
|
||||
#include "gwakeup.h"
|
||||
#include "gvariant-vectors.h"
|
||||
|
||||
#if defined(__GNUC__)
|
||||
# define _g_alignof(type) (__alignof__ (type))
|
||||
@@ -30,6 +31,8 @@
|
||||
GMainContext * g_get_worker_context (void);
|
||||
gboolean g_check_setuid (void);
|
||||
GMainContext * g_main_context_new_with_next_id (guint next_id);
|
||||
void g_variant_to_vectors (GVariant *value,
|
||||
GVariantVectors *vectors);
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
gchar *_glib_get_dll_directory (void);
|
||||
@@ -61,6 +64,10 @@ typedef struct {
|
||||
guint flags);
|
||||
GDir * (* g_dir_new_from_dirp) (gpointer dirp);
|
||||
|
||||
void (* g_variant_to_vectors) (GVariant *value,
|
||||
GVariantVectors *vectors);
|
||||
|
||||
|
||||
/* Add other private functions here, initialize them in glib-private.c */
|
||||
} GLibPrivateVTable;
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <glib/gvariant-core.h>
|
||||
#include "glib-private.h"
|
||||
|
||||
#include <glib/gvariant-serialiser.h>
|
||||
#include <glib/gtestutils.h>
|
||||
@@ -424,6 +425,61 @@ g_variant_ensure_serialised (GVariant *value)
|
||||
}
|
||||
}
|
||||
|
||||
/* Now we have the code to recursively serialise a GVariant into a
|
||||
* GVariantVectors structure.
|
||||
*
|
||||
* We want to do this in cases where the GVariant contains large chunks
|
||||
* of serialised data in order to avoid having to copy this data.
|
||||
*
|
||||
* This generally works the same as normal serialising (co-recursion
|
||||
* with the serialiser) but instead of using a callback we just hard-code
|
||||
* the callback with the name g_variant_callback_write_to_vectors().
|
||||
*
|
||||
* This is a private API that will be used by GDBus.
|
||||
*/
|
||||
gsize
|
||||
g_variant_callback_write_to_vectors (GVariantVectors *vectors,
|
||||
gpointer data,
|
||||
GVariantTypeInfo **type_info)
|
||||
{
|
||||
GVariant *value = data;
|
||||
|
||||
if (g_variant_lock_in_tree_form (value))
|
||||
{
|
||||
g_variant_serialiser_write_to_vectors (vectors, value->type_info, value->size,
|
||||
(gpointer *) value->contents.tree.children,
|
||||
value->contents.tree.n_children);
|
||||
|
||||
g_variant_unlock (value);
|
||||
}
|
||||
else
|
||||
g_variant_vectors_append_gbytes (vectors, value->contents.serialised.bytes,
|
||||
value->contents.serialised.data, value->size);
|
||||
|
||||
if (type_info)
|
||||
*type_info = value->type_info;
|
||||
|
||||
return value->size;
|
||||
}
|
||||
|
||||
/* < private >
|
||||
* g_variant_serialise_to_vectors:
|
||||
* @value: a #GVariant
|
||||
* @vectors: (out): the result
|
||||
*
|
||||
* Serialises @value into @vectors.
|
||||
*
|
||||
* The caller must free @vectors.
|
||||
*/
|
||||
void
|
||||
g_variant_to_vectors (GVariant *value,
|
||||
GVariantVectors *vectors)
|
||||
{
|
||||
g_variant_vectors_init (vectors);
|
||||
|
||||
g_variant_callback_write_to_vectors (vectors, value, NULL);
|
||||
}
|
||||
|
||||
/* < private >
|
||||
* g_variant_alloc:
|
||||
* @type: the type of the new instance
|
||||
|
||||
@@ -292,6 +292,19 @@ gvs_fixed_sized_maybe_serialise (GVariantSerialised value,
|
||||
}
|
||||
}
|
||||
|
||||
static gsize
|
||||
gvs_fixed_sized_maybe_write_to_vectors (GVariantVectors *vectors,
|
||||
GVariantTypeInfo *type_info,
|
||||
gsize size,
|
||||
const gpointer *children,
|
||||
gsize n_children)
|
||||
{
|
||||
if (!n_children)
|
||||
return 0;
|
||||
|
||||
return g_variant_callback_write_to_vectors (vectors, children[0], NULL);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gvs_fixed_sized_maybe_is_normal (GVariantSerialised value)
|
||||
{
|
||||
@@ -384,6 +397,20 @@ gvs_variable_sized_maybe_serialise (GVariantSerialised value,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gvs_variable_sized_maybe_write_to_vectors (GVariantVectors *vectors,
|
||||
GVariantTypeInfo *type_info,
|
||||
gsize size,
|
||||
const gpointer *children,
|
||||
gsize n_children)
|
||||
{
|
||||
if (n_children)
|
||||
{
|
||||
g_variant_callback_write_to_vectors (vectors, children[0], NULL);
|
||||
g_variant_vectors_append_copy (vectors, "", 1);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gvs_variable_sized_maybe_is_normal (GVariantSerialised value)
|
||||
{
|
||||
@@ -482,6 +509,19 @@ gvs_fixed_sized_array_serialise (GVariantSerialised value,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gvs_fixed_sized_array_write_to_vectors (GVariantVectors *vectors,
|
||||
GVariantTypeInfo *type_info,
|
||||
gsize size,
|
||||
const gpointer *children,
|
||||
gsize n_children)
|
||||
{
|
||||
gsize i;
|
||||
|
||||
for (i = 0; i < n_children; i++)
|
||||
g_variant_callback_write_to_vectors (vectors, children[i], NULL);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gvs_fixed_sized_array_is_normal (GVariantSerialised value)
|
||||
{
|
||||
@@ -747,6 +787,38 @@ gvs_variable_sized_array_serialise (GVariantSerialised value,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gvs_variable_sized_array_write_to_vectors (GVariantVectors *vectors,
|
||||
GVariantTypeInfo *type_info,
|
||||
gsize size,
|
||||
const gpointer *children,
|
||||
gsize n_children)
|
||||
{
|
||||
guint offset_key;
|
||||
guint alignment;
|
||||
gsize offset;
|
||||
gsize i;
|
||||
|
||||
if (n_children == 0)
|
||||
return;
|
||||
|
||||
offset_key = g_variant_vectors_reserve_offsets (vectors, n_children, gvs_get_offset_size (size));
|
||||
g_variant_type_info_query (type_info, &alignment, NULL);
|
||||
offset = 0;
|
||||
|
||||
for (i = 0; i < n_children; i++)
|
||||
{
|
||||
if ((-offset) & alignment)
|
||||
offset += g_variant_vectors_append_pad (vectors, (-offset) & alignment);
|
||||
|
||||
offset += g_variant_callback_write_to_vectors (vectors, children[i], NULL);
|
||||
|
||||
g_variant_vectors_write_to_offsets (vectors, i, offset, offset_key);
|
||||
}
|
||||
|
||||
g_variant_vectors_commit_offsets (vectors, offset_key);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gvs_variable_sized_array_is_normal (GVariantSerialised value)
|
||||
{
|
||||
@@ -1014,6 +1086,95 @@ gvs_tuple_serialise (GVariantSerialised value,
|
||||
value.data[offset++] = '\0';
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gvs_tuple_write_to_vectors (GVariantVectors *vectors,
|
||||
GVariantTypeInfo *type_info,
|
||||
gsize size,
|
||||
const gpointer *children,
|
||||
gsize n_children)
|
||||
{
|
||||
const GVariantMemberInfo *member_info = NULL;
|
||||
gsize fixed_size;
|
||||
gsize offset;
|
||||
gsize i;
|
||||
|
||||
if (n_children == 0)
|
||||
{
|
||||
g_variant_vectors_append_copy (vectors, "", 1);
|
||||
return;
|
||||
}
|
||||
|
||||
g_variant_type_info_query (type_info, NULL, &fixed_size);
|
||||
offset = 0;
|
||||
|
||||
if (!fixed_size)
|
||||
{
|
||||
gsize n_offsets;
|
||||
|
||||
member_info = g_variant_type_info_member_info (type_info, n_children - 1);
|
||||
n_offsets = member_info->i + 1;
|
||||
|
||||
if (n_offsets)
|
||||
{
|
||||
gsize offset_key = 0;
|
||||
|
||||
offset_key = g_variant_vectors_reserve_offsets (vectors, n_offsets, gvs_get_offset_size (size));
|
||||
|
||||
for (i = 0; i < n_children; i++)
|
||||
{
|
||||
guint alignment;
|
||||
|
||||
member_info = g_variant_type_info_member_info (type_info, i);
|
||||
g_variant_type_info_query (member_info->type_info, &alignment, NULL);
|
||||
|
||||
if ((-offset) & alignment)
|
||||
offset += g_variant_vectors_append_pad (vectors, (-offset) & alignment);
|
||||
|
||||
offset += g_variant_callback_write_to_vectors (vectors, children[i], NULL);
|
||||
|
||||
if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_OFFSET)
|
||||
g_variant_vectors_write_to_offsets (vectors, --n_offsets, offset, offset_key);
|
||||
}
|
||||
|
||||
g_variant_vectors_commit_offsets (vectors, offset_key);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < n_children; i++)
|
||||
{
|
||||
guint alignment;
|
||||
|
||||
member_info = g_variant_type_info_member_info (type_info, i);
|
||||
g_variant_type_info_query (member_info->type_info, &alignment, NULL);
|
||||
|
||||
if ((-offset) & alignment)
|
||||
offset += g_variant_vectors_append_pad (vectors, (-offset) & alignment);
|
||||
|
||||
offset += g_variant_callback_write_to_vectors (vectors, children[i], NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < n_children; i++)
|
||||
{
|
||||
guint alignment;
|
||||
|
||||
member_info = g_variant_type_info_member_info (type_info, i);
|
||||
g_variant_type_info_query (member_info->type_info, &alignment, NULL);
|
||||
|
||||
if ((-offset) & alignment)
|
||||
offset += g_variant_vectors_append_pad (vectors, (-offset) & alignment);
|
||||
|
||||
offset += g_variant_callback_write_to_vectors (vectors, children[i], NULL);
|
||||
}
|
||||
|
||||
g_assert (fixed_size - offset < 8);
|
||||
g_variant_vectors_append_pad (vectors, fixed_size - offset);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gvs_tuple_is_normal (GVariantSerialised value)
|
||||
{
|
||||
@@ -1226,6 +1387,23 @@ gvs_variant_serialise (GVariantSerialised value,
|
||||
memcpy (value.data + child.size + 1, type_string, strlen (type_string));
|
||||
}
|
||||
|
||||
static void
|
||||
gvs_variant_write_to_vectors (GVariantVectors *vectors,
|
||||
GVariantTypeInfo *type_info,
|
||||
gsize size,
|
||||
const gpointer *children,
|
||||
gsize n_children)
|
||||
{
|
||||
GVariantTypeInfo *child_type_info;
|
||||
const gchar *type_string;
|
||||
|
||||
g_variant_callback_write_to_vectors (vectors, children[0], &child_type_info);
|
||||
type_string = g_variant_type_info_get_type_string (child_type_info);
|
||||
|
||||
g_variant_vectors_append_copy (vectors, "", 1);
|
||||
g_variant_vectors_append_copy (vectors, type_string, strlen (type_string));
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
gvs_variant_is_normal (GVariantSerialised value)
|
||||
{
|
||||
@@ -1435,7 +1613,21 @@ g_variant_serialiser_needed_size (GVariantTypeInfo *type_info,
|
||||
|
||||
return gvs_/**/,/**/_needed_size (type_info, gvs_filler,
|
||||
children, n_children);
|
||||
)
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
g_variant_serialiser_write_to_vectors (GVariantVectors *vectors,
|
||||
GVariantTypeInfo *type_info,
|
||||
gsize size,
|
||||
const gpointer *children,
|
||||
gsize n_children)
|
||||
{
|
||||
DISPATCH_CASES (type_info,
|
||||
gvs_/**/,/**/_write_to_vectors (vectors, type_info, size, children, n_children);
|
||||
return;
|
||||
)
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#define __G_VARIANT_SERIALISER_H__
|
||||
|
||||
#include "gvarianttypeinfo.h"
|
||||
#include "gvariant-vectors.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@@ -70,4 +71,14 @@ GLIB_AVAILABLE_IN_ALL
|
||||
gboolean g_variant_serialiser_is_signature (gconstpointer data,
|
||||
gsize size);
|
||||
|
||||
|
||||
gsize g_variant_callback_write_to_vectors (GVariantVectors *vectors,
|
||||
gpointer data,
|
||||
GVariantTypeInfo **type_info);
|
||||
void g_variant_serialiser_write_to_vectors (GVariantVectors *items,
|
||||
GVariantTypeInfo *type_info,
|
||||
gsize size,
|
||||
const gpointer *children,
|
||||
gsize n_children);
|
||||
|
||||
#endif /* __G_VARIANT_SERIALISER_H__ */
|
||||
|
||||
Reference in New Issue
Block a user