[glib/gsettings] add GValue serialiser



commit 7e7f79ffcc3ae6a2557e445e3491321bb771bcbc
Author: Ryan Lortie <desrt desrt ca>
Date:   Mon Sep 28 23:44:46 2009 -0400

    add GValue serialiser

 glib/glib-object.h        |    1 +
 gobject/Makefile.am       |    2 +
 gobject/gobject.symbols   |    9 +
 gobject/gtype.c           |    3 +
 gobject/gtype.h           |    1 +
 gobject/gtypeserialiser.c |  592 +++++++++++++++++++++++++++++++++++++++++++++
 gobject/gtypeserialiser.h |   41 +++
 7 files changed, 649 insertions(+), 0 deletions(-)
---
diff --git a/glib/glib-object.h b/glib/glib-object.h
index 8687ef1..a8c90e2 100644
--- a/glib/glib-object.h
+++ b/glib/glib-object.h
@@ -35,6 +35,7 @@
 #include	<gobject/gvalue.h>
 #include	<gobject/gvaluearray.h>
 #include	<gobject/gvaluetypes.h>
+#include	<gobject/gtypeserialiser.h>
 
 #undef __GLIB_GOBJECT_H_INSIDE__
 
diff --git a/gobject/Makefile.am b/gobject/Makefile.am
index ec27aa1..c617b53 100644
--- a/gobject/Makefile.am
+++ b/gobject/Makefile.am
@@ -101,6 +101,7 @@ gobject_public_h_sources = \
 	gtype.h			\
 	gtypemodule.h		\
 	gtypeplugin.h		\
+	gtypeserialiser.h	\
 	gvalue.h		\
 	gvaluearray.h		\
 	gvaluecollector.h	\
@@ -123,6 +124,7 @@ gobject_c_sources = \
 	gtype.c			\
 	gtypemodule.c		\
 	gtypeplugin.c		\
+	gtypeserialiser.c	\
 	gvalue.c		\
 	gvaluearray.c		\
 	gvaluetransform.c	\
diff --git a/gobject/gobject.symbols b/gobject/gobject.symbols
index 3e0e162..b2fbc7f 100644
--- a/gobject/gobject.symbols
+++ b/gobject/gobject.symbols
@@ -436,6 +436,15 @@ g_value_set_instance
 #endif
 #endif
 
+#if IN_HEADER(__G_TYPE_SERIALISER_H__)
+#if IN_FILE(__G_TYPE_SERIALISER_C__)
+g_value_serialise
+g_value_deserialise
+g_type_serialiser_check
+g_type_serialiser_register_static
+#endif
+#endif
+
 #ifdef INCLUDE_VARIABLES
 g_param_spec_types
 #endif
diff --git a/gobject/gtype.c b/gobject/gtype.c
index c6dff7f..2f32ed5 100644
--- a/gobject/gtype.c
+++ b/gobject/gtype.c
@@ -4045,6 +4045,9 @@ g_type_init_with_debug_flags (GTypeDebugFlags debug_flags)
   /* G_TYPE_* value types
    */
   g_value_types_init ();
+
+  /* serialiser */
+  g_type_serialiser_init ();
   
   /* G_TYPE_ENUM & G_TYPE_FLAGS
    */
diff --git a/gobject/gtype.h b/gobject/gtype.h
index 1eeccde..4de5d4d 100644
--- a/gobject/gtype.h
+++ b/gobject/gtype.h
@@ -1449,6 +1449,7 @@ G_CONST_RETURN gchar* g_type_name_from_class	(GTypeClass	*g_class);
 /* --- internal functions --- */
 G_GNUC_INTERNAL void    g_value_c_init          (void); /* sync with gvalue.c */
 G_GNUC_INTERNAL void    g_value_types_init      (void); /* sync with gvaluetypes.c */
+G_GNUC_INTERNAL void    g_type_serialiser_init  (void); /* sync with gvalueserialiser.c */
 G_GNUC_INTERNAL void    g_enum_types_init       (void); /* sync with genums.c */
 G_GNUC_INTERNAL void    g_param_type_init       (void); /* sync with gparam.c */
 G_GNUC_INTERNAL void    g_boxed_type_init       (void); /* sync with gboxed.c */
diff --git a/gobject/gtypeserialiser.c b/gobject/gtypeserialiser.c
new file mode 100644
index 0000000..d9f451d
--- /dev/null
+++ b/gobject/gtypeserialiser.c
@@ -0,0 +1,592 @@
+/*
+ * Copyright © 2009 Codethink Limited
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * licence, or (at your option) any later version.
+ *
+ * See the included COPYING file for more information.
+ */
+
+#include "gtypeserialiser.h"
+#include "gvaluetypes.h"
+#include "gvalue.h"
+
+#include "gobjectalias.h"
+
+static GQuark _table_quark;
+static GQuark
+table_quark (void)
+{
+  if (_table_quark == 0)
+    _table_quark = g_quark_from_string ("GTypeSerialiserTable");
+
+  return _table_quark;
+}
+
+static GTypeSerialiserTable *
+table_lookup (GType type)
+{
+  return g_type_get_qdata (type, table_quark ());
+}
+
+gboolean
+g_type_serialiser_check (GType               g_type,
+                         const GVariantType *type)
+{
+  GTypeSerialiserTable *table = table_lookup (g_type);
+
+  if (table)
+    return table->check (g_type, type);
+
+  return FALSE;
+}
+
+GVariant *
+g_value_serialise (GValue             *value,
+                   const GVariantType *type)
+{
+  GTypeSerialiserTable *table = table_lookup (value->g_type);
+
+  if (table)
+    {
+      GVariant *result;
+
+      if ((result = table->serialise (value, type)) != NULL)
+        /* XXX this is a little bit wrong... */
+        return g_variant_ref_sink (result);
+    }
+
+  return NULL;
+}
+
+gboolean
+g_value_deserialise (GValue   *value,
+                     GVariant *variant)
+{
+  GTypeSerialiserTable *table = table_lookup (value->g_type);
+
+  if (table)
+    return table->deserialise (value, variant);
+
+  return FALSE;
+}
+
+void
+g_type_serialiser_register_static (GType                       type,
+                                   const GTypeSerialiserTable *table)
+{
+  g_type_set_qdata (type, table_quark (), (gpointer) table);
+}
+
+static gboolean
+check_byte (GType               g_type,
+            const GVariantType *type)
+{
+  return g_variant_type_matches (type, G_VARIANT_TYPE_BYTE);
+}
+
+static gboolean
+check_boolean (GType               g_type,
+               const GVariantType *type)
+{
+  return g_variant_type_matches (type, G_VARIANT_TYPE_BOOLEAN);
+}
+
+static gboolean
+check_number (GType               g_type,
+              const GVariantType *type)
+{
+  switch (g_variant_type_get_class (type))
+    {
+      case G_VARIANT_TYPE_CLASS_INT16:
+      case G_VARIANT_TYPE_CLASS_UINT16:
+      case G_VARIANT_TYPE_CLASS_INT32:
+      case G_VARIANT_TYPE_CLASS_UINT32:
+      case G_VARIANT_TYPE_CLASS_INT64:
+      case G_VARIANT_TYPE_CLASS_UINT64:
+      case G_VARIANT_TYPE_CLASS_DOUBLE:
+        return TRUE;
+
+      default:
+        return FALSE;
+    }
+}
+
+static gboolean
+check_string (GType               g_type,
+              const GVariantType *type)
+{
+  switch (g_variant_type_get_class (type))
+    {
+      case G_VARIANT_TYPE_CLASS_STRING:
+      case G_VARIANT_TYPE_CLASS_OBJECT_PATH:
+      case G_VARIANT_TYPE_CLASS_SIGNATURE:
+        return TRUE;
+
+      default:
+        return FALSE;
+    }
+}
+
+static GVariant *
+serialise_boolean (GValue             *value,
+                   const GVariantType *type)
+{
+  return g_variant_new_boolean (value->data[0].v_ulong);
+}
+
+static GVariant *
+serialise_byte (GValue             *value,
+                const GVariantType *type)
+{
+  return g_variant_new_byte (value->data[0].v_ulong);
+}
+
+static GVariant *
+serialise_long0 (GValue             *value,
+                 const GVariantType *type)
+{
+  GVariantTypeClass class = g_variant_type_get_class (type);
+  gint64 integer;
+
+  g_assert (sizeof (gint) == 4);
+  g_assert (4 <= sizeof (glong) && sizeof (glong) <= 8);
+  g_assert (sizeof (gint64) == 8);
+
+  integer = value->data[0].v_long;
+
+  switch (class)
+    {
+      case G_VARIANT_TYPE_CLASS_INT16:
+        if (G_MININT16 <= integer && integer <= G_MAXINT16)
+          return g_variant_new_int16 (integer);
+        return NULL;
+
+      case G_VARIANT_TYPE_CLASS_UINT16:
+        if (0 <= integer && integer <= G_MAXUINT16)
+          return g_variant_new_uint16 (integer);
+        return NULL;
+
+      case G_VARIANT_TYPE_CLASS_INT32:
+        if (G_MININT32 <= integer && integer <= G_MAXINT32)
+          return g_variant_new_int32 (integer);
+        return NULL;
+
+      case G_VARIANT_TYPE_CLASS_UINT32:
+        if (0 <= integer && integer <= G_MAXUINT32)
+          return g_variant_new_uint32 (integer);
+        return NULL;
+
+      case G_VARIANT_TYPE_CLASS_INT64:
+        if (G_MININT64 <= integer && integer <= G_MAXINT64)
+          return g_variant_new_int64 (integer);
+        return NULL;
+
+      case G_VARIANT_TYPE_CLASS_UINT64:
+        if (0 <= integer && integer <= G_MAXUINT64)
+          return g_variant_new_uint64 (integer);
+        return NULL;
+
+      case G_VARIANT_TYPE_CLASS_DOUBLE:
+        return g_variant_new_double (integer);
+
+      default:
+        g_assert_not_reached ();
+    }
+}
+
+static GVariant *
+serialise_ulong0 (GValue             *value,
+                  const GVariantType *type)
+{
+  GVariantTypeClass class = g_variant_type_get_class (type);
+  guint64 integer;
+
+  g_assert (sizeof (gint) == 4);
+  g_assert (4 <= sizeof (glong) && sizeof (glong) <= 8);
+  g_assert (sizeof (gint64) == 8);
+
+  integer = value->data[0].v_ulong;
+
+  switch (class)
+    {
+      case G_VARIANT_TYPE_CLASS_INT16:
+        if (integer <= G_MAXINT16)
+          return g_variant_new_int16 (integer);
+        return NULL;
+
+      case G_VARIANT_TYPE_CLASS_UINT16:
+        if (integer <= G_MAXUINT16)
+          return g_variant_new_uint16 (integer);
+        return NULL;
+
+      case G_VARIANT_TYPE_CLASS_INT32:
+        if (integer <= G_MAXINT32)
+          return g_variant_new_int32 (integer);
+        return NULL;
+
+      case G_VARIANT_TYPE_CLASS_UINT32:
+        if (integer <= G_MAXUINT32)
+          return g_variant_new_uint32 (integer);
+        return NULL;
+
+      case G_VARIANT_TYPE_CLASS_INT64:
+        if (integer <= G_MAXINT64)
+          return g_variant_new_int64 (integer);
+        return NULL;
+
+      case G_VARIANT_TYPE_CLASS_UINT64:
+        if (integer <= G_MAXUINT64)
+          return g_variant_new_uint64 (integer);
+        return NULL;
+
+      case G_VARIANT_TYPE_CLASS_DOUBLE:
+        return g_variant_new_double (integer);
+
+      default:
+        g_assert_not_reached ();
+    }
+}
+
+static GVariant *
+serialise_floating (GValue             *value,
+                    const GVariantType *type)
+{
+  GVariantTypeClass class = g_variant_type_get_class (type);
+  gdouble floating;
+
+  if (value->g_type == G_TYPE_FLOAT)
+    floating = value->data[0].v_float;
+  else
+    floating = value->data[0].v_double;
+
+  switch (class)
+    {
+      case G_VARIANT_TYPE_CLASS_INT16:
+        if (G_MININT16 <= floating && floating <= G_MAXINT16)
+          return g_variant_new_int16 (floating);
+        return NULL;
+
+      case G_VARIANT_TYPE_CLASS_UINT16:
+        if (0 <= floating && floating <= G_MAXUINT16)
+          return g_variant_new_uint16 (floating);
+        return NULL;
+
+      case G_VARIANT_TYPE_CLASS_INT32:
+        if (G_MININT32 <= floating && floating <= G_MAXINT32)
+          return g_variant_new_int32 (floating);
+        return NULL;
+
+      case G_VARIANT_TYPE_CLASS_UINT32:
+        if (0 <= floating && floating <= G_MAXUINT32)
+          return g_variant_new_uint32 (floating);
+        return NULL;
+
+      case G_VARIANT_TYPE_CLASS_INT64:
+        if (G_MININT64 <= floating && floating <= G_MAXINT64)
+          return g_variant_new_int64 (floating);
+        return NULL;
+
+      case G_VARIANT_TYPE_CLASS_UINT64:
+        if (0 <= floating && floating <= G_MAXUINT64)
+          return g_variant_new_uint64 (floating);
+        return NULL;
+
+      case G_VARIANT_TYPE_CLASS_DOUBLE:
+        return g_variant_new_double (floating);
+
+      default:
+        g_assert_not_reached ();
+   }
+}
+
+static GVariant *
+serialise_string (GValue             *value,
+                  const GVariantType *type)
+{
+  const gchar *string = value->data[0].v_pointer;
+
+  switch (g_variant_type_get_class (type))
+    {
+      case G_VARIANT_TYPE_CLASS_STRING:
+        return g_variant_new_string (string);
+
+      case G_VARIANT_TYPE_CLASS_OBJECT_PATH:
+        if (g_variant_is_object_path (string))
+          return g_variant_new_object_path (string);
+        return NULL;
+
+      case G_VARIANT_TYPE_CLASS_SIGNATURE:
+        if (g_variant_is_signature (string))
+          return g_variant_new_signature (string);
+        return NULL;
+
+      default:
+        g_assert_not_reached ();
+    }
+}
+
+static gboolean
+deserialise_boolean (GValue   *value,
+                     GVariant *variant)
+{
+  value->data[0].v_ulong = g_variant_get_boolean (variant);
+  return TRUE;
+}
+
+static gboolean
+deserialise_byte (GValue   *value,
+                  GVariant *variant)
+{
+  if (value->g_type == G_TYPE_CHAR)
+    value->data[0].v_long = (gchar) g_variant_get_byte (variant);
+  else /* G_TYPE_UCHAR */
+    value->data[0].v_ulong = g_variant_get_byte (variant);
+  return TRUE;
+}
+
+static gboolean
+deserialise_long0 (GValue   *value,
+                   GVariant *variant)
+{
+  gint64 integer;
+
+  switch (g_variant_get_type_class (variant))
+    {
+      case G_VARIANT_TYPE_CLASS_INT16:
+        integer = g_variant_get_int16 (variant);
+        break;
+
+      case G_VARIANT_TYPE_CLASS_UINT16:
+        integer = g_variant_get_uint16 (variant);
+        break;
+
+      case G_VARIANT_TYPE_CLASS_INT32:
+        integer = g_variant_get_int32 (variant);
+        break;
+
+      case G_VARIANT_TYPE_CLASS_UINT32:
+        integer = g_variant_get_uint32 (variant);
+        break;
+
+      case G_VARIANT_TYPE_CLASS_INT64:
+        integer = g_variant_get_int64 (variant);
+        break;
+
+      case G_VARIANT_TYPE_CLASS_UINT64:
+        {
+          guint64 uinteger = g_variant_get_uint64 (variant);
+
+          if (uinteger > G_MAXINT64)
+            return FALSE;
+
+          integer = uinteger;
+        }
+        break;
+
+      case G_VARIANT_TYPE_CLASS_DOUBLE:
+        integer = g_variant_get_double (variant);
+        break;
+
+      default:
+        g_assert_not_reached ();
+    }
+
+  if ((value->g_type == G_TYPE_UINT &&
+       (integer > G_MAXINT || integer < G_MININT)) ||
+      (value->g_type == G_TYPE_ULONG &&
+       (integer > G_MAXLONG || integer < G_MINLONG)))
+    return FALSE;
+
+  value->data[0].v_long = integer;
+
+  return TRUE;
+}
+
+static gboolean
+deserialise_ulong0 (GValue   *value,
+                    GVariant *variant)
+{
+  guint64 integer;
+
+  switch (g_variant_get_type_class (variant))
+    {
+      case G_VARIANT_TYPE_CLASS_INT16:
+        integer = g_variant_get_int16 (variant);
+        break;
+
+      case G_VARIANT_TYPE_CLASS_UINT16:
+        integer = g_variant_get_uint16 (variant);
+        break;
+
+      case G_VARIANT_TYPE_CLASS_INT32:
+        integer = g_variant_get_int32 (variant);
+        break;
+
+      case G_VARIANT_TYPE_CLASS_UINT32:
+        integer = g_variant_get_uint32 (variant);
+        break;
+
+      case G_VARIANT_TYPE_CLASS_INT64:
+        {
+          gint64 sinteger = g_variant_get_int64 (variant);
+
+          if (sinteger < 0)
+            return FALSE;
+
+          integer = sinteger;
+        }
+        break;
+
+      case G_VARIANT_TYPE_CLASS_UINT64:
+        integer = g_variant_get_uint64 (variant);
+        break;
+
+      case G_VARIANT_TYPE_CLASS_DOUBLE:
+        integer = g_variant_get_double (variant);
+        break;
+
+      default:
+        g_assert_not_reached ();
+    }
+
+  if ((value->g_type == G_TYPE_UINT && integer > G_MAXUINT) ||
+      (value->g_type == G_TYPE_ULONG && integer > G_MAXULONG))
+    return FALSE;
+
+  value->data[0].v_ulong = integer;
+
+  return TRUE;
+}
+
+static gboolean
+deserialise_floating (GValue   *value,
+                      GVariant *variant)
+{
+  gdouble floating;
+
+  switch (g_variant_get_type_class (variant))
+    {
+      case G_VARIANT_TYPE_CLASS_INT16:
+        floating = g_variant_get_int16 (variant);
+        break;
+
+      case G_VARIANT_TYPE_CLASS_UINT16:
+        floating = g_variant_get_uint16 (variant);
+        break;
+
+      case G_VARIANT_TYPE_CLASS_INT32:
+        floating = g_variant_get_int32 (variant);
+        break;
+
+      case G_VARIANT_TYPE_CLASS_UINT32:
+        floating = g_variant_get_uint32 (variant);
+        break;
+
+      case G_VARIANT_TYPE_CLASS_INT64:
+        floating = g_variant_get_int64 (variant);
+        break;
+
+      case G_VARIANT_TYPE_CLASS_UINT64:
+        floating = g_variant_get_uint64 (variant);
+        break;
+
+      case G_VARIANT_TYPE_CLASS_DOUBLE:
+        floating = g_variant_get_double (variant);
+        break;
+
+      default:
+        g_assert_not_reached ();
+    }
+
+  if (value->g_type == G_TYPE_FLOAT)
+    value->data[0].v_float = floating;
+  else
+    value->data[0].v_double = floating;
+
+  return TRUE;
+}
+
+static gboolean
+deserialise_string (GValue   *value,
+                    GVariant *variant)
+{
+  g_value_set_string (value, g_variant_get_string (variant, NULL));
+
+  return TRUE;
+}
+
+void
+g_type_serialiser_init ()
+{
+  /* boolean */
+  {
+    static const GTypeSerialiserTable serialiser_table = {
+      check_boolean,
+      serialise_boolean,
+      deserialise_boolean
+    };
+    g_type_serialiser_register_static (G_TYPE_BOOLEAN, &serialiser_table);
+  }
+
+  /* char/uchar */
+  {
+    static const GTypeSerialiserTable serialiser_table = {
+      check_byte,
+      serialise_byte,
+      deserialise_byte
+    };
+    g_type_serialiser_register_static (G_TYPE_CHAR, &serialiser_table);
+    g_type_serialiser_register_static (G_TYPE_UCHAR, &serialiser_table);
+  }
+
+  /* signed integers */
+  {
+    static const GTypeSerialiserTable serialiser_table = {
+      check_number,
+      serialise_long0,
+      deserialise_long0
+    };
+    g_type_serialiser_register_static (G_TYPE_INT, &serialiser_table);
+    g_type_serialiser_register_static (G_TYPE_LONG, &serialiser_table);
+    g_type_serialiser_register_static (G_TYPE_INT64, &serialiser_table);
+  }
+
+  /* unsigned integers */
+  {
+    static const GTypeSerialiserTable serialiser_table = {
+      check_number,
+      serialise_ulong0,
+      deserialise_ulong0
+    };
+    g_type_serialiser_register_static (G_TYPE_UINT, &serialiser_table);
+    g_type_serialiser_register_static (G_TYPE_ULONG, &serialiser_table);
+    g_type_serialiser_register_static (G_TYPE_UINT64, &serialiser_table);
+  }
+
+  /* floating point */
+  {
+    static const GTypeSerialiserTable serialiser_table = {
+      check_number,
+      serialise_floating,
+      deserialise_floating
+    };
+    g_type_serialiser_register_static (G_TYPE_DOUBLE, &serialiser_table);
+    g_type_serialiser_register_static (G_TYPE_FLOAT, &serialiser_table);
+  }
+
+  /* strings */
+  {
+    static const GTypeSerialiserTable serialiser_table = {
+      check_string,
+      serialise_string,
+      deserialise_string
+    };
+    g_type_serialiser_register_static (G_TYPE_STRING, &serialiser_table);
+  }
+}
+
+#define __G_TYPE_SERIALISER_C__
+#include "gobjectaliasdef.c"
diff --git a/gobject/gtypeserialiser.h b/gobject/gtypeserialiser.h
new file mode 100644
index 0000000..2e23d18
--- /dev/null
+++ b/gobject/gtypeserialiser.h
@@ -0,0 +1,41 @@
+/* 
+ * Copyright © 2009 Codethink Limited
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * licence, or (at your option) any later version.
+ * 
+ * See the included COPYING file for more information.
+ */
+
+#ifndef __G_TYPE_SERIALISER_H__
+#define __G_TYPE_SERIALISER_H__
+
+#include "gtype.h"
+
+G_BEGIN_DECLS
+
+struct _GTypeSerialiserTable
+{
+  gboolean    (*check)       (GType               g_type,
+                              const GVariantType *type);
+  GVariant *  (*serialise)   (GValue             *value,
+                              const GVariantType *type);
+  gboolean    (*deserialise) (GValue             *value,
+                              GVariant           *variant);
+};
+
+typedef struct _GTypeSerialiserTable GTypeSerialiserTable;
+
+gboolean                g_type_serialiser_check                         (GType                       g_type,
+                                                                         const GVariantType         *type);
+GVariant *              g_value_serialise                               (GValue                     *value,
+                                                                         const GVariantType         *type);
+gboolean                g_value_deserialise                             (GValue                     *value,
+                                                                         GVariant                   *variant);
+void                    g_type_serialiser_register_static               (GType                       type,
+                                                                         const GTypeSerialiserTable *table);
+G_END_DECLS
+
+#endif /* __G_TYPE_SERIALISER_H__ */



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