[glib/wip/gvariant-kdbus: 17/17] GVariant vector deserialiser WIP
- From: Ryan Lortie <desrt src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib/wip/gvariant-kdbus: 17/17] GVariant vector deserialiser WIP
- Date: Wed, 3 Dec 2014 07:18:02 +0000 (UTC)
commit 3468ab849b4ee04f1494d5dead6045a7984f4886
Author: Ryan Lortie <desrt desrt ca>
Date: Wed Dec 3 02:14:19 2014 -0500
GVariant vector deserialiser WIP
glib/glib-private.c | 3 +-
glib/glib-private.h | 10 +++
glib/gvariant-core.c | 151 ++++++++++++++++++++++++++++++++++++++++++++
glib/gvariant-serialiser.c | 9 +++
glib/gvariant-serialiser.h | 13 ++++
glib/gvariant-vectors.h | 2 +-
6 files changed, 186 insertions(+), 2 deletions(-)
---
diff --git a/glib/glib-private.c b/glib/glib-private.c
index 3c1dac6..5c23c0c 100644
--- a/glib/glib-private.c
+++ b/glib/glib-private.c
@@ -46,7 +46,8 @@ glib__private__ (void)
g_dir_open_with_errno,
g_dir_new_from_dirp,
- g_variant_to_vectors
+ g_variant_to_vectors,
+ g_variant_from_vectors
};
return &table;
diff --git a/glib/glib-private.h b/glib/glib-private.h
index 40509b6..29fa2f2 100644
--- a/glib/glib-private.h
+++ b/glib/glib-private.h
@@ -33,6 +33,11 @@ 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);
+GVariant * g_variant_from_vectors (const GVariantType *type,
+ GVariantVector *vectors,
+ gsize n_vectors,
+ gsize size,
+ gboolean trusted);
#ifdef G_OS_WIN32
gchar *_glib_get_dll_directory (void);
@@ -66,6 +71,11 @@ typedef struct {
void (* g_variant_to_vectors) (GVariant *value,
GVariantVectors *vectors);
+ GVariant * (* g_variant_from_vectors) (const GVariantType *type,
+ GVariantVector *vectors,
+ gsize n_vectors,
+ gsize size,
+ gboolean trusted);
/* Add other private functions here, initialize them in glib-private.c */
diff --git a/glib/gvariant-core.c b/glib/gvariant-core.c
index 32b1a88..62aabaa 100644
--- a/glib/gvariant-core.c
+++ b/glib/gvariant-core.c
@@ -665,6 +665,157 @@ g_variant_get_serialised (GVariant *value,
return value->contents.serialised.data;
}
+static GVariant *
+g_variant_vector_deserialise (GVariantTypeInfo *type_info,
+ GVariantVector *first_vector,
+ GVariantVector *last_vector,
+ gsize size,
+ gboolean trusted,
+ GArray *children)
+{
+ g_assert (size > 0);
+
+ if (first_vector < last_vector)
+ {
+ GVariantVector *vector = first_vector;
+ gconstpointer end;
+ GVariant **new;
+ guint offset;
+ guint i, n;
+
+ end = last_vector->data.pointer + last_vector->size;
+
+ offset = children->len;
+
+ if (!g_variant_serialiser_unpack_all (type_info, end, last_vector->size, size, children))
+ {
+ /* We are supposed to consume type_info */
+ g_variant_type_info_unref (type_info);
+ return FALSE;
+ }
+
+ n = children->len - offset;
+ new = g_new (GVariant *, n);
+
+ for (i = 0; i < n; i++)
+ {
+ GVariantUnpacked *unpacked;
+ GVariantVector *fv;
+ gsize saved_size;
+
+ unpacked = &g_array_index (children, GVariantUnpacked, offset + i);
+
+ /* Skip the alignment.
+ *
+ * We can destroy vectors because we won't be going back.
+ *
+ * We do a >= compare because we want to go to the next vector
+ * if it is the start of our child.
+ */
+ while (unpacked->skip >= vector->size)
+ {
+ unpacked->skip -= vector->size;
+ vector++;
+ }
+ fv = vector;
+ fv->data.pointer += unpacked->skip;
+ fv->size -= unpacked->skip;
+
+ if (unpacked->size == 0)
+ {
+ new[i] = g_variant_new_serialised (type_info, g_bytes_new (NULL, 0), NULL, 0, trusted);
+ continue;
+ }
+
+ /* Now skip to the end, according to 'size'.
+ *
+ * We cannot destroy everything here because we will probably
+ * end up reusing the last one.
+ *
+ * We do a > compare because we want to stay on this vector if
+ * it is the end of our child.
+ */
+ size = unpacked->size;
+ while (unpacked->size > vector->size)
+ {
+ unpacked->size -= vector->size;
+ vector++;
+ }
+
+ /* temporarily replace the size field */
+ saved_size = vector->size;
+ vector->size = unpacked->size;
+
+ new[i] = g_variant_vector_deserialise (unpacked->type_info, fv, vector, size, trusted, children);
+
+ if (new[i] == NULL)
+ {
+ gint j;
+
+ /* Free the new children array and any children in it up
+ * to this point.
+ */
+ for (j = 0; j < i; j++)
+ g_variant_unref (new[j]);
+ g_free (new);
+
+ /* Consume the type_info for the remaining children */
+ for (j = i + 1; j < n; j++)
+ g_variant_type_info_unref (g_array_index (children, GVariantUnpacked, offset + i).type_info);
+
+ /* Rewind this */
+ g_array_set_size (children, offset);
+
+ /* We have to free this */
+ g_variant_type_info_unref (type_info);
+
+ return NULL;
+ }
+
+ /* Repair the last vector and move past our data */
+ vector->data.pointer += unpacked->size;
+ vector->size -= saved_size - unpacked->size;
+ }
+
+ /* Rewind */
+ g_array_set_size (children, offset);
+
+ /* Create the tree-form GVariant in the usual way */
+ return g_variant_new_from_children (type_info, new, n, trusted);
+ }
+ else
+ {
+ g_assert (first_vector == last_vector);
+ g_assert (size == first_vector->size);
+
+ return g_variant_new_serialised (type_info, g_bytes_ref (first_vector->gbytes),
+ first_vector->data.pointer, size, trusted);
+ }
+}
+
+GVariant *
+g_variant_from_vectors (const GVariantType *type,
+ GVariantVector *vectors,
+ gsize n_vectors,
+ gsize size,
+ gboolean trusted)
+{
+ GVariant *result;
+ GArray *tmp;
+
+ g_return_val_if_fail (vectors != NULL || n_vectors == 0, NULL);
+
+ if (size == 0)
+ return g_variant_new_serialised (g_variant_type_info_get (type), g_bytes_new (NULL, 0), NULL, 0,
trusted);
+
+ tmp = g_array_new (FALSE, FALSE, sizeof (GVariantUnpacked));
+ result = g_variant_vector_deserialise (g_variant_type_info_get (type),
+ vectors, vectors + n_vectors - 1, size, trusted, tmp);
+ g_array_free (tmp, TRUE);
+
+ return result;
+}
+
/* -- public -- */
/**
diff --git a/glib/gvariant-serialiser.c b/glib/gvariant-serialiser.c
index c25a7be..1c0a9fe 100644
--- a/glib/gvariant-serialiser.c
+++ b/glib/gvariant-serialiser.c
@@ -1617,6 +1617,15 @@ g_variant_serialiser_needed_size (GVariantTypeInfo *type_info,
g_assert_not_reached ();
}
+gboolean
+g_variant_serialiser_unpack_all (GVariantTypeInfo *type_info,
+ gconstpointer end,
+ gsize end_size,
+ gsize total_size,
+ GArray *results)
+{
+ return FALSE;
+}
void
g_variant_serialiser_write_to_vectors (GVariantVectors *vectors,
diff --git a/glib/gvariant-serialiser.h b/glib/gvariant-serialiser.h
index a558da0..2cd983a 100644
--- a/glib/gvariant-serialiser.h
+++ b/glib/gvariant-serialiser.h
@@ -31,6 +31,13 @@ typedef struct
gsize size;
} GVariantSerialised;
+typedef struct
+{
+ GVariantTypeInfo *type_info;
+ gsize skip;
+ gsize size;
+} GVariantUnpacked;
+
/* deserialisation */
GLIB_AVAILABLE_IN_ALL
gsize g_variant_serialised_n_children (GVariantSerialised
container);
@@ -38,6 +45,12 @@ GLIB_AVAILABLE_IN_ALL
GVariantSerialised g_variant_serialised_get_child (GVariantSerialised container,
gsize index);
+gboolean g_variant_serialiser_unpack_all (GVariantTypeInfo *type_info,
+ gconstpointer
end_pointer,
+ gsize end_size,
+ gsize
total_size,
+ GArray
*results_array);
+
/* serialisation */
typedef void (*GVariantSerialisedFiller) (GVariantSerialised
*serialised,
gpointer data);
diff --git a/glib/gvariant-vectors.h b/glib/gvariant-vectors.h
index b1f0519..73d1f2f 100644
--- a/glib/gvariant-vectors.h
+++ b/glib/gvariant-vectors.h
@@ -19,7 +19,7 @@ typedef struct
{
GBytes *gbytes;
union {
- gconstpointer pointer;
+ const guchar *pointer;
gsize offset;
} data;
gsize size;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]