[glib/wip/gvariant-kdbus] start fleshing out guts of vector deserialiser



commit 185449c5c6c403d69b1063875d1a51c889ea7c88
Author: Ryan Lortie <desrt desrt ca>
Date:   Wed Dec 3 03:12:06 2014 -0500

    start fleshing out guts of vector deserialiser

 glib/gvariant-serialiser.c |  182 +++++++++++++++++++++++++++++++++++++++++++-
 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 1c0a9fe..7880c5a 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 2cd983a..142c914 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);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]