From ac9dfac13cef34288440a2ecdf067cd827fb2f8f Mon Sep 17 00:00:00 2001 From: Peng Huang Date: Fri, 19 Aug 2011 08:23:33 -0400 Subject: [PATCH] Use GVariant as attachment for IBusSerializable. BUG=None TEST=Linux desktop Review URL: http://codereview.appspot.com/4902051 --- src/ibusserializable.c | 176 +++++++----------------------------------- src/ibusserializable.h | 81 ++++++++++--------- src/tests/ibus-serializable.c | 47 +++++++---- 3 files changed, 98 insertions(+), 206 deletions(-) diff --git a/src/ibusserializable.c b/src/ibusserializable.c index ed89534..6251c89 100644 --- a/src/ibusserializable.c +++ b/src/ibusserializable.c @@ -124,114 +124,13 @@ ibus_serializable_destroy (IBusSerializable *serializable) parent_class->destroy (IBUS_OBJECT (serializable)); } -static GValue * -ibus_g_value_dup (const GValue *value) -{ - GValue *new_value; - - new_value = g_slice_new0 (GValue); - g_value_init (new_value, G_VALUE_TYPE (value)); - g_value_copy (value, new_value); - - return new_value; -} - -static void -ibus_g_value_free (GValue *value) -{ - g_value_unset (value); - g_slice_free (GValue, value); -} - -static GVariant * -_g_value_serialize (GValue *value) -{ - GType type; - - type = G_VALUE_TYPE (value); - g_return_val_if_fail (type != G_TYPE_INVALID, FALSE); - - if (g_type_is_a (type, IBUS_TYPE_SERIALIZABLE)) { - IBusSerializable *object; - object = IBUS_SERIALIZABLE (g_value_get_object (value)); - return ibus_serializable_serialize (object); - } - - typedef const gchar *gstring; - switch (type) { -#define CASE_ENTRY(TYPE, _type, signature) \ - case G_TYPE_##TYPE: \ - { \ - g##_type v; \ - v = g_value_get_##_type (value); \ - return g_variant_new (signature, v); \ - } - CASE_ENTRY(CHAR, char, "y"); - CASE_ENTRY(BOOLEAN, boolean, "b"); - CASE_ENTRY(INT, int, "i"); - CASE_ENTRY(UINT, uint, "u"); - CASE_ENTRY(INT64, int64, "x"); - CASE_ENTRY(UINT64, uint64, "t"); - CASE_ENTRY(FLOAT, float, "d"); - CASE_ENTRY(DOUBLE, double, "d"); - CASE_ENTRY(STRING, string, "s"); -#undef CASE_ENTRY - } - - g_assert_not_reached (); -} - -static GValue * -_g_value_deserialize (GVariant *variant) -{ - GValue *value = NULL; - const GVariantType *type; - - type = g_variant_get_type (variant); - if (type == G_VARIANT_TYPE_TUPLE) { - IBusSerializable *object; - object = ibus_serializable_deserialize (variant); - value = g_slice_new0 (GValue); - g_value_init (value, G_OBJECT_TYPE (object)); - g_value_take_object (value, object); - return value; - } - - typedef gchar *gstring; -#define IF_ENTRY(TYPE, _type, signature) \ - if (g_variant_type_equal(type, G_VARIANT_TYPE_##TYPE)) { \ - g##_type v; \ - g_variant_get (variant, signature, &v); \ - value = g_slice_new0 (GValue); \ - g_value_init (value, G_TYPE_##TYPE); \ - g_value_set_##_type (value, v); \ - return value; \ - } -#define G_VARIANT_TYPE_CHAR G_VARIANT_TYPE_BYTE - IF_ENTRY(CHAR, char, "y"); -#undef G_VARIANT_TYPE_CHAR - IF_ENTRY(BOOLEAN, boolean, "b"); -#define G_VARIANT_TYPE_INT G_VARIANT_TYPE_INT32 -#define G_VARIANT_TYPE_UINT G_VARIANT_TYPE_UINT32 - IF_ENTRY(INT, int, "i"); - IF_ENTRY(UINT, uint, "u"); -#undef G_VARIANT_TYPE_INT -#undef G_VARIANT_TYPE_UINT - IF_ENTRY(INT64, int64, "x"); - IF_ENTRY(UINT64, uint64, "t"); - IF_ENTRY(DOUBLE, double, "d"); - IF_ENTRY(STRING, string, "s"); - - g_return_val_if_reached (NULL); -} - static void _serialize_cb (GQuark key, - GValue *value, + GVariant *value, GVariantBuilder *array) { g_variant_builder_add (array, "{sv}", - g_quark_to_string (key), _g_value_serialize (value)); + g_quark_to_string (key), g_variant_new_variant (value)); } static gboolean @@ -257,21 +156,26 @@ ibus_serializable_real_deserialize (IBusSerializable *object, GVariantIter *iter = NULL; g_variant_get_child (variant, 1, "a{sv}", &iter); while (g_variant_iter_loop (iter, "{&sv}", &key, &value)) { - ibus_serializable_set_attachment (object, key, _g_value_deserialize (value)); + GVariant *attachment = g_variant_get_variant (value); + ibus_serializable_set_attachment (object, + key, + attachment); + g_variant_unref (attachment); + g_variant_unref (value); } g_variant_iter_free (iter); return 2; } static void -_copy_cb (GQuark key, - GValue *value, - GData **datalist) +_copy_cb (GQuark key, + GVariant *value, + GData **datalist) { g_datalist_id_set_data_full (datalist, key, - ibus_g_value_dup (value), - (GDestroyNotify) ibus_g_value_free); + g_variant_ref (value), + (GDestroyNotify) g_variant_unref); } static gboolean @@ -289,50 +193,21 @@ ibus_serializable_real_copy (IBusSerializable *dest, return TRUE; } -gboolean -ibus_serializable_set_qattachment (IBusSerializable *object, +void +ibus_serializable_set_qattachment (IBusSerializable *serializable, GQuark key, - const GValue *value) + GVariant *value) { - g_return_val_if_fail (IBUS_IS_SERIALIZABLE (object), FALSE); - g_return_val_if_fail (key != 0, FALSE); - g_return_val_if_fail (G_IS_VALUE (value), FALSE); - - IBusSerializablePrivate *priv; - priv = IBUS_SERIALIZABLE_GET_PRIVATE (object); - - GType type = G_VALUE_TYPE (value); - - switch (type) { - case G_TYPE_CHAR: - case G_TYPE_INT: - case G_TYPE_INT64: - case G_TYPE_UINT: - case G_TYPE_UINT64: - case G_TYPE_BOOLEAN: - case G_TYPE_DOUBLE: - case G_TYPE_FLOAT: - case G_TYPE_STRING: - g_datalist_id_set_data_full (&priv->attachments, - key, - ibus_g_value_dup (value), - (GDestroyNotify) ibus_g_value_free); - return TRUE; - } - - if (g_type_is_a (type, IBUS_TYPE_SERIALIZABLE)) { - g_datalist_id_set_data_full (&priv->attachments, - key, - ibus_g_value_dup (value), - (GDestroyNotify) ibus_g_value_free); - return TRUE; - } + g_return_if_fail (IBUS_IS_SERIALIZABLE (serializable)); + g_return_if_fail (key != 0); - g_warning ("The value of %s is not support serializing", g_type_name (type)); - return FALSE; + g_datalist_id_set_data_full (&serializable->priv->attachments, + key, + value ? g_variant_ref_sink (value) : NULL, + (GDestroyNotify) g_variant_unref); } -const GValue * +GVariant * ibus_serializable_get_qattachment (IBusSerializable *serializable, GQuark key) { @@ -340,7 +215,8 @@ ibus_serializable_get_qattachment (IBusSerializable *serializable, g_return_val_if_fail (IBUS_IS_SERIALIZABLE (serializable), NULL); g_return_val_if_fail (key != 0, NULL); - return (const GValue *) g_datalist_id_get_data (&serializable->priv->attachments, key); + return (GVariant *) g_datalist_id_get_data ( + &serializable->priv->attachments, key); } void @@ -351,7 +227,7 @@ ibus_serializable_remove_qattachment (IBusSerializable *serializable, g_return_if_fail (IBUS_IS_SERIALIZABLE (serializable)); g_return_if_fail (key != 0); - g_datalist_id_remove_no_notify (&serializable->priv->attachments, key); + g_datalist_id_set_data (&serializable->priv->attachments, key, NULL); } IBusSerializable * diff --git a/src/ibusserializable.h b/src/ibusserializable.h index 8fd9f8a..7a100c2 100644 --- a/src/ibusserializable.h +++ b/src/ibusserializable.h @@ -126,39 +126,40 @@ struct _IBusSerializable { /** * IBusSerializableSerializeFunc: - * @object: An IBusSerializable. - * @iter: An IBusMessageIter. - * @returns: TRUE if succeed; FALSE otherwise. + * @serializable: An #IBusSerializable. + * @builder: A #GVariantBuilder. + * @returns: %TRUE if succeed; %FALSE otherwise. * * Prototype of serialize function. * Serialize function convert an IBusSerializable to IBusMessageIter. * Returns a gboolean value which indicates whether the conversion is success. - * Return TRUE if succeed. + * Return %TRUE if succeed. */ -typedef gboolean (* IBusSerializableSerializeFunc) (IBusSerializable *object, +typedef gboolean (* IBusSerializableSerializeFunc) (IBusSerializable *serializable, GVariantBuilder *builder); /** * IBusSerializableDeserializeFunc: - * @object: An IBusSerializable. - * @iter: An IBusMessageIter. - * @returns: TRUE if succeed; FALSE otherwise. + * @serializable: An #IBusSerializable. + * @variant: A #GVariant contains a tuple. + * @returns: The number of values in the variant(tuple) are consumed. * * Prototype of deserialize function. * Deserialize function convert an IBusMessageIter to IBusSerializable. - * Returns a gboolean value which indicates whether the conversion is success. + * Returns an integer value which indicates how many values in + * the variant(tuple) are consumed. */ -typedef gint (* IBusSerializableDeserializeFunc) (IBusSerializable *object, +typedef gint (* IBusSerializableDeserializeFunc) (IBusSerializable *serializable, GVariant *variant); /** * IBusSerializableCopyFunc: - * @dest: The destination IBusSerializable. - * @src: A source IBusMessageIter. - * @returns: TRUE if succeed; FALSE otherwise. + * @dest: The destination #IBusSerializable. + * @src: A source #IBusMessageIter. + * @returns: %TRUE if succeed; %FALSE otherwise. * * Prototype of copy function. - * Copy function copy from source IBusSerializable to the destination one. + * Copy function copy from source #IBusSerializable to the destination one. * Returns a gboolean value which indicates whether the copying is success. */ typedef gboolean (* IBusSerializableCopyFunc) (IBusSerializable *dest, @@ -188,79 +189,77 @@ GType ibus_serializable_get_type (void); * * Returns: a new instance of #IBusSerializable. */ -IBusSerializable * ibus_serializable_new (void); +IBusSerializable *ibus_serializable_new (void); /** * ibus_serializable_set_qattachment: - * @object: An IBusSerializable. + * @serializable: An #IBusSerializable. * @key: String formatted key for indexing value. - * @value: Value to be attached. Should be also serializable. - * @returns: TRUE if succeed; FALSE otherwise. + * @value: Value to be attached or %NULL to remove any prevoius value. * - * Attach a value to an IBusSerializable. The value should be serializable as well. - * Basic type such as integer, string are deemed to be serializable. + * Attach a value to an IBusSerializable. If the value is floating, + * the serializable will take the ownership. * * @see_also: ibus_serializable_set_attachment(). */ -gboolean ibus_serializable_set_qattachment (IBusSerializable *object, +void ibus_serializable_set_qattachment (IBusSerializable *serializable, GQuark key, - const GValue *value); + GVariant *value); /** * ibus_serializable_get_qattachment: - * @object: An IBusSerializable. + * @serializable: An #IBusSerializable. * @key: String formatted key for indexing value. - * @returns: The attached value; or NULL if fail to retrieve the value. + * @returns: The attached value; or %NULL if fail to retrieve the value. * - * Get a value from attachment of an IBusSerializable. + * Get a value from attachment of an #IBusSerializable. * @see_also: ibus_serializable_set_attachment(). */ -const GValue *ibus_serializable_get_qattachment (IBusSerializable *object, +GVariant *ibus_serializable_get_qattachment (IBusSerializable *serializable, GQuark key); /** * ibus_serializable_remove_qattachment: - * @object: An IBusSerializable. + * @serializable: An #IBusSerializable. * @key: String formatted key for indexing value. * - * Remove a value from attachment of an IBusSerializable. + * Remove a value from attachment of an #IBusSerializable. * @see_also: ibus_serializable_remove_attachment(). */ void ibus_serializable_remove_qattachment - (IBusSerializable *object, + (IBusSerializable *serializable, GQuark key); /** * ibus_serializable_copy: - * @object: An IBusSerializable. - * @returns: A newly allocated clone object; or NULL if @object is not serializable. + * @serializable: An #IBusSerializable. + * @returns: A newly allocated clone object; or %NULL if @object is not serializable. * - * Clone an IBusSerializable. + * Clone an #IBusSerializable. * The copy method should be implemented in extended class. * * @see_also: IBusSerializableCopyFunc(). */ -IBusSerializable *ibus_serializable_copy (IBusSerializable *object); +IBusSerializable *ibus_serializable_copy (IBusSerializable *serializable); /** * ibus_serializable_serialize: - * @object: An IBusSerializable. - * @iter: An IBusMessageIter. - * @returns: TRUE if succeed; FALSE otherwise. + * @serializable: An #IBusSerializable. + * @returns: A #GVariant. * - * Serialize an IBusSerializable to an IBusMessageIter. + * Serialize an #IBusSerializable to a #GVariant. * The serialize method should be implemented in extended class. * * @see_also: IBusSerializableCopyFunc(). */ -GVariant *ibus_serializable_serialize (IBusSerializable *object); +GVariant *ibus_serializable_serialize (IBusSerializable *serializable); /** * ibus_serializable_deserialize: - * @iter: An IBusMessageIter. - * @returns: The deserialized IBusSerializable. + * @variant: A #GVariant. + * @returns: The deserialized #IBusSerializable. * - * Deserialize an IBusMessageIter to an IBusSerializable/ + * Deserialize a #GVariant to an #IBusSerializable/ * The deserialize method should be implemented in extended class. * * @see_also: IBusSerializableCopyFunc(). diff --git a/src/tests/ibus-serializable.c b/src/tests/ibus-serializable.c index e2541ec..d2bd61a 100644 --- a/src/tests/ibus-serializable.c +++ b/src/tests/ibus-serializable.c @@ -12,7 +12,7 @@ void test_serializable (IBusSerializable *object) g_variant_get_data (variant); s1 = g_variant_print (variant, TRUE); - object = (IBusSerializable *) ibus_serializable_deserialize (variant); + object = ibus_serializable_deserialize (variant); g_variant_unref (variant); variant = ibus_serializable_serialize (object); @@ -131,34 +131,51 @@ test_property (void) static void test_attachment (void) { - IBusText *text = ibus_text_new_from_string ("main text"); + IBusText *text = ibus_text_new_from_static_string ("main text"); - GValue value1 = { 0 }; - g_value_init(&value1, G_TYPE_INT); - g_value_set_int(&value1, 100); - ibus_serializable_set_attachment ((IBusSerializable *)text, "key1", &value1); + ibus_serializable_set_attachment ((IBusSerializable *)text, + "key1", + g_variant_new_int32 (100)); - GValue value2 = { 0 }; - g_value_init(&value2, G_TYPE_STRING); - g_value_set_string(&value2, "value string"); - ibus_serializable_set_attachment ((IBusSerializable *)text, "key2", &value2); + ibus_serializable_set_attachment ((IBusSerializable *)text, + "key2", + g_variant_new_string ("value string")); + + ibus_serializable_set_attachment ((IBusSerializable *)text, + "key3", + g_variant_new ("(iuds)",1, 2, 3.333, "test value")); GVariant *variant = ibus_serializable_serialize ((IBusSerializable *)text); g_object_unref ((IBusSerializable *)text); - IBusSerializable *object = (IBusSerializable *) ibus_serializable_deserialize (variant); + IBusSerializable *object = ibus_serializable_deserialize (variant); g_variant_unref (variant); g_assert_cmpstr (((IBusText *)object)->text, ==, "main text"); - const GValue *newvalue1 = ibus_serializable_get_attachment (object, "key1"); + GVariant *newvalue1 = ibus_serializable_get_attachment (object, "key1"); g_assert (newvalue1 != NULL); - g_assert (g_value_get_int (newvalue1) == 100); + g_assert_cmpint (g_variant_get_int32 (newvalue1), ==, 100); - const GValue *newvalue2 = ibus_serializable_get_attachment (object, "key2"); + GVariant *newvalue2 = ibus_serializable_get_attachment (object, "key2"); g_assert (newvalue2 != NULL); - g_assert_cmpstr (g_value_get_string (newvalue2), ==, "value string"); + g_assert_cmpstr (g_variant_get_string (newvalue2, NULL), ==, "value string"); + + { + GVariant *newvalue3 = ibus_serializable_get_attachment (object, "key3"); + g_assert (newvalue3 != NULL); + gint32 i; + guint32 u; + gdouble d; + const gchar *s; + g_variant_get (newvalue3, "(iud&s)", &i, &u, &d, &s); + g_assert_cmpint (i, ==, 1); + g_assert_cmpuint (u, ==, 2); + g_assert_cmpfloat (d, ==, 3.333); + g_assert_cmpstr (s, ==, "test value"); + } + g_object_unref (object); g_variant_type_info_assert_no_infos (); } -- 2.7.4