diff options
author | Ryan Lortie <desrt@desrt.ca> | 2014-12-03 03:12:06 -0500 |
---|---|---|
committer | Ryan Lortie <desrt@desrt.ca> | 2014-12-03 03:12:06 -0500 |
commit | 185449c5c6c403d69b1063875d1a51c889ea7c88 (patch) | |
tree | b0c5cb44b13bd7d5e999bef5ad247b8fcb78213c | |
parent | 3468ab849b4ee04f1494d5dead6045a7984f4886 (diff) | |
download | glib-185449c5c6c403d69b1063875d1a51c889ea7c88.tar.gz |
start fleshing out guts of vector deserialiser
-rw-r--r-- | glib/gvariant-serialiser.c | 182 | ||||
-rw-r--r-- | glib/gvariant-serialiser.h | 2 |
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); |