summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyan Lortie <desrt@desrt.ca>2014-12-03 03:12:06 -0500
committerRyan Lortie <desrt@desrt.ca>2014-12-03 03:12:06 -0500
commit185449c5c6c403d69b1063875d1a51c889ea7c88 (patch)
treeb0c5cb44b13bd7d5e999bef5ad247b8fcb78213c
parent3468ab849b4ee04f1494d5dead6045a7984f4886 (diff)
downloadglib-185449c5c6c403d69b1063875d1a51c889ea7c88.tar.gz
start fleshing out guts of vector deserialiser
-rw-r--r--glib/gvariant-serialiser.c182
-rw-r--r--glib/gvariant-serialiser.h2
2 files changed, 180 insertions, 4 deletions
diff --git a/glib/gvariant-serialiser.c b/glib/gvariant-serialiser.c
index 1c0a9fe77..7880c5a7a 100644
--- a/glib/gvariant-serialiser.c
+++ b/glib/gvariant-serialiser.c
@@ -259,6 +259,28 @@ gvs_fixed_sized_maybe_get_child (GVariantSerialised value,
return value;
}
+static gboolean
+gvs_fixed_sized_maybe_unpack_all (GVariantTypeInfo *type_info,
+ const guchar *end,
+ gsize end_size,
+ gsize total_size,
+ GArray *results)
+{
+ if (total_size)
+ {
+ GVariantUnpacked unpacked;
+
+ unpacked.type_info = g_variant_type_info_element (type_info);
+ g_variant_type_info_ref (unpacked.type_info);
+ unpacked.skip = 0;
+ unpacked.size = total_size;
+
+ g_array_append_val (results, unpacked);
+ }
+
+ return TRUE;
+}
+
static gsize
gvs_fixed_sized_maybe_needed_size (GVariantTypeInfo *type_info,
GVariantSerialisedFiller gvs_filler,
@@ -363,6 +385,28 @@ gvs_variable_sized_maybe_get_child (GVariantSerialised value,
return value;
}
+static gboolean
+gvs_variable_sized_maybe_unpack_all (GVariantTypeInfo *type_info,
+ const guchar *end,
+ gsize end_size,
+ gsize total_size,
+ GArray *results)
+{
+ if (total_size)
+ {
+ GVariantUnpacked unpacked;
+
+ unpacked.type_info = g_variant_type_info_element (type_info);
+ g_variant_type_info_ref (unpacked.type_info);
+ unpacked.skip = 0;
+ unpacked.size = total_size - 1;
+
+ g_array_append_val (results, unpacked);
+ }
+
+ return TRUE;
+}
+
static gsize
gvs_variable_sized_maybe_needed_size (GVariantTypeInfo *type_info,
GVariantSerialisedFiller gvs_filler,
@@ -476,6 +520,39 @@ gvs_fixed_sized_array_get_child (GVariantSerialised value,
return child;
}
+static gboolean
+gvs_fixed_sized_array_unpack_all (GVariantTypeInfo *type_info,
+ const guchar *end,
+ gsize end_size,
+ gsize total_size,
+ GArray *results)
+{
+ GVariantTypeInfo *element;
+ gsize element_fixed_size;
+ gsize i, n;
+
+ element = g_variant_type_info_element (type_info);
+ g_variant_type_info_query (element, NULL, &element_fixed_size);
+
+ if (total_size % element_fixed_size)
+ return FALSE;
+
+ n = total_size / element_fixed_size;
+
+ for (i = 0; i < n; i++)
+ {
+ GVariantUnpacked unpacked;
+
+ unpacked.type_info = g_variant_type_info_ref (element);
+ unpacked.skip = 0;
+ unpacked.size = element_fixed_size;
+
+ g_array_append_val (results, unpacked);
+ }
+
+ return TRUE;
+}
+
static gsize
gvs_fixed_sized_array_needed_size (GVariantTypeInfo *type_info,
GVariantSerialisedFiller gvs_filler,
@@ -592,8 +669,8 @@ gvs_fixed_sized_array_is_normal (GVariantSerialised value)
/* bytes may be NULL if (size == 0). */
static inline gsize
-gvs_read_unaligned_le (guchar *bytes,
- guint size)
+gvs_read_unaligned_le (const guchar *bytes,
+ guint size)
{
union
{
@@ -728,6 +805,78 @@ gvs_variable_sized_array_get_child (GVariantSerialised value,
return child;
}
+static gboolean
+gvs_variable_sized_array_unpack_all (GVariantTypeInfo *type_info,
+ const guchar *end,
+ gsize end_size,
+ gsize total_size,
+ GArray *results)
+{
+ GVariantTypeInfo *element;
+ guint element_alignment;
+ const guchar *offsets;
+ gsize offset_size;
+ gsize offsets_array_size;
+ gsize prev_end;
+ gsize last_end;
+ gsize i, n;
+
+ if (total_size == 0)
+ return TRUE;
+
+ element = g_variant_type_info_element (type_info);
+ g_variant_type_info_query (element, &element_alignment, NULL);
+
+ offset_size = gvs_get_offset_size (total_size);
+
+ if (offset_size > end_size)
+ return FALSE;
+
+ last_end = gvs_read_unaligned_le (end - offset_size, offset_size);
+
+ if (last_end > total_size)
+ return 0;
+
+ offsets_array_size = total_size - last_end;
+
+ if (offsets_array_size > end_size)
+ return FALSE;
+
+ offsets = end - offsets_array_size;
+
+ if (offsets_array_size % offset_size)
+ return FALSE;
+
+ n = offsets_array_size / offset_size;
+
+ if (n == 0)
+ return FALSE;
+
+ prev_end = 0;
+
+ for (i = 0; i < n; i++)
+ {
+ GVariantUnpacked unpacked;
+ gsize start;
+ gsize end;
+
+ start = prev_end + ((-prev_end) & element_alignment);
+ end = gvs_read_unaligned_le (offsets, offset_size);
+ offsets += offset_size;
+
+ if (start < prev_end || end < start) { g_assert_not_reached ();
+ return FALSE; /* XXX free the array and type infos */ }
+
+ unpacked.type_info = g_variant_type_info_ref (element);
+ unpacked.skip = start - prev_end;
+ unpacked.size = end - start;
+
+ g_array_append_val (results, unpacked);
+ }
+
+ return TRUE;
+}
+
static gsize
gvs_variable_sized_array_needed_size (GVariantTypeInfo *type_info,
GVariantSerialisedFiller gvs_filler,
@@ -1004,6 +1153,17 @@ gvs_tuple_get_child (GVariantSerialised value,
return child;
}
+static gboolean
+gvs_tuple_unpack_all (GVariantTypeInfo *type_info,
+ const guchar *end,
+ gsize end_size,
+ gsize total_size,
+ GArray *results)
+{
+ g_assert_not_reached (); /* FIXME */
+ return FALSE;
+}
+
static gsize
gvs_tuple_needed_size (GVariantTypeInfo *type_info,
GVariantSerialisedFiller gvs_filler,
@@ -1355,6 +1515,17 @@ gvs_variant_get_child (GVariantSerialised value,
return child;
}
+static gboolean
+gvs_variant_unpack_all (GVariantTypeInfo *type_info,
+ const guchar *end,
+ gsize end_size,
+ gsize total_size,
+ GArray *results)
+{
+ g_assert_not_reached (); /* FIXME */
+ return FALSE;
+}
+
static inline gsize
gvs_variant_needed_size (GVariantTypeInfo *type_info,
GVariantSerialisedFiller gvs_filler,
@@ -1619,11 +1790,16 @@ g_variant_serialiser_needed_size (GVariantTypeInfo *type_info,
gboolean
g_variant_serialiser_unpack_all (GVariantTypeInfo *type_info,
- gconstpointer end,
+ const guchar *end,
gsize end_size,
gsize total_size,
GArray *results)
{
+ DISPATCH_CASES (type_info,
+ return gvs_/**/,/**/_unpack_all (type_info, end, end_size, total_size, results);
+ )
+
+ /* We are here because type_info is not a container type */
return FALSE;
}
diff --git a/glib/gvariant-serialiser.h b/glib/gvariant-serialiser.h
index 2cd983a3b..142c914de 100644
--- a/glib/gvariant-serialiser.h
+++ b/glib/gvariant-serialiser.h
@@ -46,7 +46,7 @@ GVariantSerialised g_variant_serialised_get_child (GVarian
gsize index);
gboolean g_variant_serialiser_unpack_all (GVariantTypeInfo *type_info,
- gconstpointer end_pointer,
+ const guchar *end_pointer,
gsize end_size,
gsize total_size,
GArray *results_array);