From b631f54a54d7689a1215782c47f84b69ec74eae8 Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Wed, 2 Feb 2011 18:40:52 +0900 Subject: [PATCH] Implement serialization to GVariant (WIP). --- eek/Makefile.am | 2 ++ eek/eek-container.c | 62 +++++++++++++++++++++++++++++++- eek/eek-element.c | 62 +++++++++++++++++++++++++++++++- eek/eek-key.c | 80 +++++++++++++++++++++++++++++++++++++++++- eek/eek-serializable.c | 75 +++++++++++++++++++++++++++++++++++++++ eek/eek-serializable.h | 59 +++++++++++++++++++++++++++++++ eek/eek-types.h | 2 +- 7 files changed, 338 insertions(+), 4 deletions(-) create mode 100644 eek/eek-serializable.c create mode 100644 eek/eek-serializable.h diff --git a/eek/Makefile.am b/eek/Makefile.am index 3e2d5087..50ae3ff2 100644 --- a/eek/Makefile.am +++ b/eek/Makefile.am @@ -37,6 +37,7 @@ libeek_public_headers = \ $(srcdir)/eek-keysym.h \ $(srcdir)/eek-types.h \ $(srcdir)/eek-xml.h \ + $(srcdir)/eek-serializable.h \ $(srcdir)/eek.h libeek_private_headers = \ @@ -57,6 +58,7 @@ libeek_sources = \ $(srcdir)/eek-symbol.c \ $(srcdir)/eek-keysym.c \ $(srcdir)/eek-types.c \ + $(srcdir)/eek-serializable.c \ $(srcdir)/eek-xml.c \ $(srcdir)/eek-xml-layout.c \ $(srcdir)/eek-renderer.c \ diff --git a/eek/eek-container.c b/eek/eek-container.c index eb0808e5..331ace45 100644 --- a/eek/eek-container.c +++ b/eek/eek-container.c @@ -31,6 +31,7 @@ #endif /* HAVE_CONFIG_H */ #include "eek-container.h" +#include "eek-serializable.h" enum { CHILD_ADDED, @@ -40,7 +41,11 @@ enum { static guint signals[LAST_SIGNAL] = { 0, }; -G_DEFINE_ABSTRACT_TYPE (EekContainer, eek_container, EEK_TYPE_ELEMENT); +static void eek_serializable_iface_init (EekSerializableIface *iface); + +G_DEFINE_ABSTRACT_TYPE_WITH_CODE (EekContainer, eek_container, EEK_TYPE_ELEMENT, + G_IMPLEMENT_INTERFACE (EEK_TYPE_SERIALIZABLE, + eek_serializable_iface_init)); #define EEK_CONTAINER_GET_PRIVATE(obj) \ (G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_CONTAINER, EekContainerPrivate)) @@ -51,6 +56,61 @@ struct _EekContainerPrivate GSList *children; }; +static EekSerializableIface *eek_container_parent_serializable_iface; + +static void +eek_container_real_serialize (EekSerializable *self, + GVariantBuilder *builder) +{ + EekContainerPrivate *priv = EEK_CONTAINER_GET_PRIVATE(self); + GSList *head; + GVariantBuilder array; + + eek_container_parent_serializable_iface->serialize (self, builder); + + g_variant_builder_init (&array, G_VARIANT_TYPE("av")); + for (head = priv->children; head; head = g_slist_next (head)) { + GVariant *variant = + eek_serializable_serialize (EEK_SERIALIZABLE(head->data)); + g_variant_builder_add (&array, "v", variant); + } + g_variant_builder_add (builder, "v", g_variant_builder_end (&array)); +} + +static gsize +eek_container_real_deserialize (EekSerializable *self, + GVariant *variant, + gsize index) +{ + EekContainerPrivate *priv = EEK_CONTAINER_GET_PRIVATE(self); + GVariant *array, *child; + GVariantIter iter; + + index = eek_container_parent_serializable_iface->deserialize (self, + variant, + index); + + g_variant_get_child (variant, index++, "v", &array); + g_variant_iter_init (&iter, array); + while (g_variant_iter_next (&iter, "v", &child)) { + EekSerializable *serializable = eek_serializable_deserialize (child); + priv->children = g_slist_prepend (priv->children, serializable); + } + priv->children = g_slist_reverse (priv->children); + + return index; +} + +static void +eek_serializable_iface_init (EekSerializableIface *iface) +{ + eek_container_parent_serializable_iface = + g_type_interface_peek_parent (iface); + + iface->serialize = eek_container_real_serialize; + iface->deserialize = eek_container_real_deserialize; +} + static void eek_container_real_add_child (EekContainer *self, EekElement *child) diff --git a/eek/eek-element.c b/eek/eek-element.c index 8108dcef..d82f2cf8 100644 --- a/eek/eek-element.c +++ b/eek/eek-element.c @@ -34,6 +34,7 @@ #include "eek-element.h" #include "eek-container.h" +#include "eek-serializable.h" enum { PROP_0, @@ -42,7 +43,11 @@ enum { PROP_LAST }; -G_DEFINE_ABSTRACT_TYPE (EekElement, eek_element, G_TYPE_OBJECT); +static void eek_serializable_iface_init (EekSerializableIface *iface); + +G_DEFINE_ABSTRACT_TYPE_WITH_CODE (EekElement, eek_element, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (EEK_TYPE_SERIALIZABLE, + eek_serializable_iface_init)); #define EEK_ELEMENT_GET_PRIVATE(obj) \ (G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_ELEMENT, EekElementPrivate)) @@ -55,6 +60,61 @@ struct _EekElementPrivate EekElement *parent; }; +static GVariant * +_g_variant_new_bounds (EekBounds *bounds) +{ + GVariantBuilder builder; + + g_variant_builder_init (&builder, G_VARIANT_TYPE ("ad")); + g_variant_builder_add (&builder, "d", bounds->x); + g_variant_builder_add (&builder, "d", bounds->y); + g_variant_builder_add (&builder, "d", bounds->width); + g_variant_builder_add (&builder, "d", bounds->height); + + return g_variant_builder_end (&builder); +} + +static void +_g_variant_get_bounds (GVariant *variant, EekBounds *bounds) +{ + g_variant_get_child (variant, 0, "d", &bounds->x); + g_variant_get_child (variant, 1, "d", &bounds->y); + g_variant_get_child (variant, 2, "d", &bounds->width); + g_variant_get_child (variant, 3, "d", &bounds->height); +} + +static void +eek_element_real_serialize (EekSerializable *self, + GVariantBuilder *builder) +{ + EekElementPrivate *priv = EEK_ELEMENT_GET_PRIVATE(self); + + g_variant_builder_add (builder, "s", priv->name); + g_variant_builder_add (builder, "v", _g_variant_new_bounds (&priv->bounds)); +} + +static gsize +eek_element_real_deserialize (EekSerializable *self, + GVariant *variant, + gsize index) +{ + EekElementPrivate *priv = EEK_ELEMENT_GET_PRIVATE(self); + GVariant *bounds; + + g_variant_get_child (variant, index++, "s", &priv->name); + g_variant_get_child (variant, index++, "v", &bounds); + _g_variant_get_bounds (bounds, &priv->bounds); + + return index; +} + +static void +eek_serializable_iface_init (EekSerializableIface *iface) +{ + iface->serialize = eek_element_real_serialize; + iface->deserialize = eek_element_real_deserialize; +} + static void eek_element_real_set_parent (EekElement *self, EekElement *parent) diff --git a/eek/eek-key.c b/eek/eek-key.c index 65f6954d..77ee5fd5 100644 --- a/eek/eek-key.c +++ b/eek/eek-key.c @@ -38,6 +38,7 @@ #include "eek-section.h" #include "eek-keyboard.h" #include "eek-symbol.h" +#include "eek-serializable.h" enum { PROP_0, @@ -57,7 +58,11 @@ enum { static guint signals[LAST_SIGNAL] = { 0, }; -G_DEFINE_TYPE (EekKey, eek_key, EEK_TYPE_ELEMENT); +static void eek_serializable_iface_init (EekSerializableIface *iface); + +G_DEFINE_TYPE_WITH_CODE (EekKey, eek_key, EEK_TYPE_ELEMENT, + G_IMPLEMENT_INTERFACE (EEK_TYPE_SERIALIZABLE, + eek_serializable_iface_init)); #define EEK_KEY_GET_PRIVATE(obj) \ (G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_KEY, EekKeyPrivate)) @@ -73,6 +78,79 @@ struct _EekKeyPrivate gboolean is_pressed; }; +static EekSerializableIface *eek_key_parent_serializable_iface; + +static GVariant * +_g_variant_new_symbol_matrix (EekSymbolMatrix *symbol_matrix) +{ + GVariantBuilder builder, array; + gint i, num_symbols = symbol_matrix->num_groups * symbol_matrix->num_levels; + + g_variant_builder_init (&builder, G_VARIANT_TYPE ("iiav")); + g_variant_builder_add (&builder, "i", symbol_matrix->num_groups); + g_variant_builder_add (&builder, "i", symbol_matrix->num_levels); + g_variant_builder_init (&array, G_VARIANT_TYPE ("av")); + for (i = 0; i < num_symbols; i++) { + GVariant *symbol = eek_serializable_serialize + (EEK_SERIALIZABLE(symbol_matrix->data[i])); + g_variant_builder_add (&builder, "v", symbol); + } + g_variant_builder_add (&builder, "av", g_variant_builder_end (&array)); + return g_variant_builder_end (&builder); +} + +static EekSymbolMatrix * +_g_variant_get_symbol_matrix (GVariant *variant) +{ + g_return_val_if_reached (NULL); /* TODO */ +} + +static void +eek_key_real_serialize (EekSerializable *self, + GVariantBuilder *builder) +{ + EekKeyPrivate *priv = EEK_KEY_GET_PRIVATE(self); + + eek_key_parent_serializable_iface->serialize (self, builder); + + g_variant_builder_add (builder, "u", priv->keycode); + g_variant_builder_add (builder, "v", + _g_variant_new_symbol_matrix (priv->symbol_matrix)); + g_variant_builder_add (builder, "i", priv->column); + g_variant_builder_add (builder, "i", priv->row); +} + +static gsize +eek_key_real_deserialize (EekSerializable *self, + GVariant *variant, + gsize index) +{ + EekKeyPrivate *priv = EEK_KEY_GET_PRIVATE(self); + GVariant *symbol_matrix; + + index = eek_key_parent_serializable_iface->deserialize (self, + variant, + index); + + g_variant_get_child (variant, index++, "u", &priv->keycode); + g_variant_get_child (variant, index++, "v", &symbol_matrix); + priv->symbol_matrix = _g_variant_get_symbol_matrix (symbol_matrix); + g_variant_get_child (variant, index++, "i", &priv->column); + g_variant_get_child (variant, index++, "i", &priv->row); + + return index; +} + +static void +eek_serializable_iface_init (EekSerializableIface *iface) +{ + eek_key_parent_serializable_iface = + g_type_interface_peek_parent (iface); + + iface->serialize = eek_key_real_serialize; + iface->deserialize = eek_key_real_deserialize; +} + static void eek_key_real_set_keycode (EekKey *self, guint keycode) { diff --git a/eek/eek-serializable.c b/eek/eek-serializable.c new file mode 100644 index 00000000..e6baec64 --- /dev/null +++ b/eek/eek-serializable.c @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2008-2010 Peng Huang + * Copyright (C) 2008-2010 Red Hat, Inc. + * + * 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 License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#include "eek-serializable.h" + +GType +eek_serializable_get_type (void) +{ + static GType iface_type = 0; + if (iface_type == 0) { + static const GTypeInfo info = { + sizeof (EekSerializableIface), + NULL, + NULL, + }; + iface_type = g_type_register_static (G_TYPE_INTERFACE, + "EekSerializable", + &info, 0); + } + return iface_type; +} + +GVariant * +eek_serializable_serialize (EekSerializable *object) +{ + GVariantBuilder builder; + + g_return_val_if_fail (EEK_IS_SERIALIZABLE (object), FALSE); + + g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE); + g_variant_builder_add (&builder, "s", g_type_name (G_OBJECT_TYPE (object))); + EEK_SERIALIZABLE_GET_IFACE (object)->serialize (object, &builder); + + return g_variant_builder_end (&builder); +} + +EekSerializable * +eek_serializable_deserialize (GVariant *variant) +{ + GVariant *var = NULL; + gchar *type_name = NULL; + GType type; + EekSerializable *object; + + g_return_val_if_fail (variant != NULL, NULL); + + g_variant_get_child (var, 0, "&s", &type_name); + type = g_type_from_name (type_name); + + g_return_val_if_fail (g_type_is_a (type, EEK_TYPE_SERIALIZABLE), NULL); + + object = g_object_new (type, NULL); + + EEK_SERIALIZABLE_GET_IFACE (object)->deserialize (object, var, 1); + g_variant_unref (var); + + g_object_unref (object); + g_return_val_if_reached (NULL); +} diff --git a/eek/eek-serializable.h b/eek/eek-serializable.h new file mode 100644 index 00000000..7550a7f1 --- /dev/null +++ b/eek/eek-serializable.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2011 Daiki Ueno + * Copyright (C) 2011 Red Hat, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef EEK_SERIALIZABLE_H +#define EEK_SERIALIZABLE_H 1 + +#include + +G_BEGIN_DECLS + +#define EEK_TYPE_SERIALIZABLE (eek_serializable_get_type()) +#define EEK_SERIALIZABLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEK_TYPE_SERIALIZABLE, EekSerializable)) +#define EEK_IS_SERIALIZABLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEK_TYPE_SERIALIZABLE)) +#define EEK_SERIALIZABLE_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), EEK_TYPE_SERIALIZABLE, EekSerializableIface)) + +typedef struct _EekSerializable EekSerializable; +typedef struct _EekSerializableIface EekSerializableIface; + +struct _EekSerializableIface +{ + /*< private >*/ + GTypeInterface parent_iface; + + void (* serialize) (EekSerializable *object, + GVariantBuilder *builder); + gsize (* deserialize) (EekSerializable *object, + GVariant *variant, + gsize index); + void (* copy) (EekSerializable *dest, + const EekSerializable *src); + + /*< private >*/ + /* padding */ + gpointer pdummy[5]; +}; + +GType eek_serializable_get_type (void); + +EekSerializable *eek_serializable_copy (EekSerializable *object); +GVariant *eek_serializable_serialize (EekSerializable *object); +EekSerializable *eek_serializable_deserialize (GVariant *variant); + +G_END_DECLS +#endif /* EEK_SERIALIZABLE_H */ diff --git a/eek/eek-types.h b/eek/eek-types.h index cd0927d9..0186298f 100644 --- a/eek/eek-types.h +++ b/eek/eek-types.h @@ -122,9 +122,9 @@ typedef struct _EekColor EekColor; */ struct _EekSymbolMatrix { - EekSymbol **data; gint num_groups; gint num_levels; + EekSymbol **data; }; GType eek_symbol_matrix_get_type