[glib] GVariant: avoid byteswapping in some cases



commit 2ce2d587edbeb98b355c4038c218d75a8c8f9c99
Author: Ryan Lortie <desrt desrt ca>
Date:   Sun Oct 3 22:39:47 2010 -0400

    GVariant: avoid byteswapping in some cases
    
    Make g_variant_byteswap() merely return a new reference on the given
    value in the event that we know that byteswapping will have no effect
    (ie: types which have no alignment requirement).
    
    This fixes a somewhat complicated interaction between GVariant,
    GSettings and GVDB on big endian machines:  GSettings assumes that it
    can unref values returned from GVDB without losing access to the
    underlying data.  This only works if the underlying data is in the
    mapped file -- not a freshly-allocated buffer that GVariant byteswapped
    into.

 glib/gvariant.c |   40 +++++++++++++++++++++++++++-------------
 1 files changed, 27 insertions(+), 13 deletions(-)
---
diff --git a/glib/gvariant.c b/glib/gvariant.c
index f9eb851..e333597 100644
--- a/glib/gvariant.c
+++ b/glib/gvariant.c
@@ -4566,23 +4566,37 @@ g_variant_get_normal_form (GVariant *value)
 GVariant *
 g_variant_byteswap (GVariant *value)
 {
-  GVariantSerialised serialised;
-  GVariant *trusted;
-  GBuffer *buffer;
+  GVariantTypeInfo *type_info;
+  guint alignment;
   GVariant *new;
 
-  trusted = g_variant_get_normal_form (value);
-  serialised.type_info = g_variant_get_type_info (trusted);
-  serialised.size = g_variant_get_size (trusted);
-  serialised.data = g_malloc (serialised.size);
-  g_variant_store (trusted, serialised.data);
-  g_variant_unref (trusted);
+  type_info = g_variant_get_type_info (value);
 
-  g_variant_serialised_byteswap (serialised);
+  g_variant_type_info_query (type_info, &alignment, NULL);
 
-  buffer = g_buffer_new_take_data (serialised.data, serialised.size);
-  new = g_variant_new_from_buffer (g_variant_get_type (value), buffer, TRUE);
-  g_buffer_unref (buffer);
+  if (alignment)
+    /* (potentially) contains multi-byte numeric data */
+    {
+      GVariantSerialised serialised;
+      GVariant *trusted;
+      GBuffer *buffer;
+
+      trusted = g_variant_get_normal_form (value);
+      serialised.type_info = g_variant_get_type_info (trusted);
+      serialised.size = g_variant_get_size (trusted);
+      serialised.data = g_malloc (serialised.size);
+      g_variant_store (trusted, serialised.data);
+      g_variant_unref (trusted);
+
+      g_variant_serialised_byteswap (serialised);
+
+      buffer = g_buffer_new_take_data (serialised.data, serialised.size);
+      new = g_variant_new_from_buffer (g_variant_get_type (value), buffer, TRUE);
+      g_buffer_unref (buffer);
+    }
+  else
+    /* contains no multi-byte data */
+    new = value;
 
   return g_variant_ref_sink (new);
 }



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