|
Packit |
3ff832 |
/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
|
|
Packit |
3ff832 |
/* vim:set et sts=4: */
|
|
Packit |
3ff832 |
/* ibus - The Input Bus
|
|
Packit |
3ff832 |
* Copyright (C) 2008-2010 Peng Huang <shawn.p.huang@gmail.com>
|
|
Packit |
3ff832 |
* Copyright (C) 2018 Takao Fujiwara <takao.fujiwara1@gmail.com>
|
|
Packit |
3ff832 |
* Copyright (C) 2008-2018 Red Hat, Inc.
|
|
Packit |
3ff832 |
*
|
|
Packit |
3ff832 |
* This library is free software; you can redistribute it and/or
|
|
Packit |
3ff832 |
* modify it under the terms of the GNU Lesser General Public
|
|
Packit |
3ff832 |
* License as published by the Free Software Foundation; either
|
|
Packit |
3ff832 |
* version 2.1 of the License, or (at your option) any later version.
|
|
Packit |
3ff832 |
*
|
|
Packit |
3ff832 |
* This library is distributed in the hope that it will be useful,
|
|
Packit |
3ff832 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
3ff832 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
3ff832 |
* Lesser General Public License for more details.
|
|
Packit |
3ff832 |
*
|
|
Packit |
3ff832 |
* You should have received a copy of the GNU Lesser General Public
|
|
Packit |
3ff832 |
* License along with this library; if not, write to the Free Software
|
|
Packit |
3ff832 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
|
Packit |
3ff832 |
* USA
|
|
Packit |
3ff832 |
*/
|
|
Packit |
3ff832 |
#include "ibusinternal.h"
|
|
Packit |
3ff832 |
#include "ibusserializable.h"
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
#define IBUS_SERIALIZABLE_GET_PRIVATE(o) \
|
|
Packit |
3ff832 |
(G_TYPE_INSTANCE_GET_PRIVATE ((o), IBUS_TYPE_SERIALIZABLE, IBusSerializablePrivate))
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
enum {
|
|
Packit |
3ff832 |
LAST_SIGNAL,
|
|
Packit |
3ff832 |
};
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
struct _IBusSerializablePrivate {
|
|
Packit |
3ff832 |
GData *attachments;
|
|
Packit |
3ff832 |
};
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
// static guint object_signals[LAST_SIGNAL] = { 0 };
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
/* functions prototype */
|
|
Packit |
3ff832 |
static void ibus_serializable_base_init (IBusSerializableClass *class);
|
|
Packit |
3ff832 |
static void ibus_serializable_base_fini (IBusSerializableClass *class);
|
|
Packit |
3ff832 |
static void ibus_serializable_class_init (IBusSerializableClass *class);
|
|
Packit |
3ff832 |
static void ibus_serializable_init (IBusSerializable *object);
|
|
Packit |
3ff832 |
static void ibus_serializable_destroy (IBusSerializable *object);
|
|
Packit |
3ff832 |
static gboolean ibus_serializable_real_serialize (IBusSerializable *object,
|
|
Packit |
3ff832 |
GVariantBuilder *builder);
|
|
Packit |
3ff832 |
static gint ibus_serializable_real_deserialize (IBusSerializable *object,
|
|
Packit |
3ff832 |
GVariant *variant);
|
|
Packit |
3ff832 |
static gboolean ibus_serializable_real_copy (IBusSerializable *dest,
|
|
Packit |
3ff832 |
const IBusSerializable *src);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static IBusObjectClass *parent_class = NULL;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
GType
|
|
Packit |
3ff832 |
ibus_serializable_get_type (void)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
static GType type = 0;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static const GTypeInfo type_info = {
|
|
Packit |
3ff832 |
sizeof (IBusSerializableClass),
|
|
Packit |
3ff832 |
(GBaseInitFunc) ibus_serializable_base_init,
|
|
Packit |
3ff832 |
(GBaseFinalizeFunc) ibus_serializable_base_fini,
|
|
Packit |
3ff832 |
(GClassInitFunc) ibus_serializable_class_init,
|
|
Packit |
3ff832 |
NULL, /* class finialize */
|
|
Packit |
3ff832 |
NULL, /* class data */
|
|
Packit |
3ff832 |
sizeof (IBusSerializable),
|
|
Packit |
3ff832 |
0,
|
|
Packit |
3ff832 |
(GInstanceInitFunc) ibus_serializable_init,
|
|
Packit |
3ff832 |
};
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (type == 0) {
|
|
Packit |
3ff832 |
type = g_type_register_static (IBUS_TYPE_OBJECT,
|
|
Packit |
3ff832 |
"IBusSerializable",
|
|
Packit |
3ff832 |
&type_info,
|
|
Packit |
3ff832 |
0);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
return type;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
IBusSerializable *
|
|
Packit |
3ff832 |
ibus_serializable_new (void)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
return IBUS_SERIALIZABLE (g_object_new (IBUS_TYPE_SERIALIZABLE, NULL));
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static void
|
|
Packit |
3ff832 |
ibus_serializable_base_init (IBusSerializableClass *class)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static void
|
|
Packit |
3ff832 |
ibus_serializable_base_fini (IBusSerializableClass *class)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static void
|
|
Packit |
3ff832 |
ibus_serializable_class_init (IBusSerializableClass *class)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
IBusObjectClass *object_class = IBUS_OBJECT_CLASS (class);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
parent_class = (IBusObjectClass *) g_type_class_peek_parent (class);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
g_type_class_add_private (class, sizeof (IBusSerializablePrivate));
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
object_class->destroy = (IBusObjectDestroyFunc) ibus_serializable_destroy;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
class->serialize = ibus_serializable_real_serialize;
|
|
Packit |
3ff832 |
class->deserialize = ibus_serializable_real_deserialize;
|
|
Packit |
3ff832 |
class->copy = ibus_serializable_real_copy;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static void
|
|
Packit |
3ff832 |
ibus_serializable_init (IBusSerializable *serializable)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
serializable->priv = IBUS_SERIALIZABLE_GET_PRIVATE (serializable);
|
|
Packit |
3ff832 |
serializable->priv->attachments = NULL;
|
|
Packit |
3ff832 |
g_datalist_init (&serializable->priv->attachments);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static void
|
|
Packit |
3ff832 |
ibus_serializable_destroy (IBusSerializable *serializable)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
g_datalist_clear (&serializable->priv->attachments);
|
|
Packit |
3ff832 |
parent_class->destroy (IBUS_OBJECT (serializable));
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static void
|
|
Packit |
3ff832 |
_serialize_cb (GQuark key,
|
|
Packit |
3ff832 |
GVariant *value,
|
|
Packit |
3ff832 |
GVariantBuilder *array)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
g_variant_builder_add (array, "{sv}",
|
|
Packit |
3ff832 |
g_quark_to_string (key), g_variant_new_variant (value));
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static gboolean
|
|
Packit |
3ff832 |
ibus_serializable_real_serialize (IBusSerializable *serializable,
|
|
Packit |
3ff832 |
GVariantBuilder *builder)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
GVariantBuilder array;
|
|
Packit |
3ff832 |
g_variant_builder_init (&array, G_VARIANT_TYPE ("a{sv}"));
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
g_datalist_foreach (&serializable->priv->attachments,
|
|
Packit |
3ff832 |
(GDataForeachFunc) _serialize_cb,
|
|
Packit |
3ff832 |
&array);
|
|
Packit |
3ff832 |
g_variant_builder_add (builder, "a{sv}", &array);
|
|
Packit |
3ff832 |
return TRUE;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static gint
|
|
Packit |
3ff832 |
ibus_serializable_real_deserialize (IBusSerializable *object,
|
|
Packit |
3ff832 |
GVariant *variant)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
const gchar *key;
|
|
Packit |
3ff832 |
GVariant *value;
|
|
Packit |
3ff832 |
GVariantIter *iter = NULL;
|
|
Packit |
3ff832 |
g_variant_get_child (variant, 1, "a{sv}", &iter);
|
|
Packit |
3ff832 |
while (g_variant_iter_loop (iter, "{&sv}", &key, &value)) {
|
|
Packit |
3ff832 |
GVariant *attachment = g_variant_get_variant (value);
|
|
Packit |
3ff832 |
ibus_serializable_set_attachment (object,
|
|
Packit |
3ff832 |
key,
|
|
Packit |
3ff832 |
attachment);
|
|
Packit |
3ff832 |
g_variant_unref (attachment);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
g_variant_iter_free (iter);
|
|
Packit |
3ff832 |
return 2;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static void
|
|
Packit |
3ff832 |
_copy_cb (GQuark key,
|
|
Packit |
3ff832 |
GVariant *value,
|
|
Packit |
3ff832 |
GData **datalist)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
g_datalist_id_set_data_full (datalist,
|
|
Packit |
3ff832 |
key,
|
|
Packit |
3ff832 |
g_variant_ref (value),
|
|
Packit |
3ff832 |
(GDestroyNotify) g_variant_unref);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
static gboolean
|
|
Packit |
3ff832 |
ibus_serializable_real_copy (IBusSerializable *dest,
|
|
Packit |
3ff832 |
const IBusSerializable *src)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
IBusSerializablePrivate *src_priv;
|
|
Packit |
3ff832 |
IBusSerializablePrivate *dest_priv;
|
|
Packit |
3ff832 |
src_priv = IBUS_SERIALIZABLE_GET_PRIVATE (src);
|
|
Packit |
3ff832 |
dest_priv = IBUS_SERIALIZABLE_GET_PRIVATE (dest);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
g_datalist_foreach (&src_priv->attachments,
|
|
Packit |
3ff832 |
(GDataForeachFunc) _copy_cb,
|
|
Packit |
3ff832 |
&dest_priv->attachments);
|
|
Packit |
3ff832 |
return TRUE;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
void
|
|
Packit |
3ff832 |
ibus_serializable_set_qattachment (IBusSerializable *serializable,
|
|
Packit |
3ff832 |
GQuark key,
|
|
Packit |
3ff832 |
GVariant *value)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
g_return_if_fail (IBUS_IS_SERIALIZABLE (serializable));
|
|
Packit |
3ff832 |
g_return_if_fail (key != 0);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
g_datalist_id_set_data_full (&serializable->priv->attachments,
|
|
Packit |
3ff832 |
key,
|
|
Packit |
3ff832 |
value ? g_variant_ref_sink (value) : NULL,
|
|
Packit |
3ff832 |
(GDestroyNotify) g_variant_unref);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
GVariant *
|
|
Packit |
3ff832 |
ibus_serializable_get_qattachment (IBusSerializable *serializable,
|
|
Packit |
3ff832 |
GQuark key)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
g_return_val_if_fail (IBUS_IS_SERIALIZABLE (serializable), NULL);
|
|
Packit |
3ff832 |
g_return_val_if_fail (key != 0, NULL);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
return (GVariant *) g_datalist_id_get_data (
|
|
Packit |
3ff832 |
&serializable->priv->attachments, key);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
void
|
|
Packit |
3ff832 |
ibus_serializable_remove_qattachment (IBusSerializable *serializable,
|
|
Packit |
3ff832 |
GQuark key)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
g_return_if_fail (IBUS_IS_SERIALIZABLE (serializable));
|
|
Packit |
3ff832 |
g_return_if_fail (key != 0);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
g_datalist_id_set_data (&serializable->priv->attachments, key, NULL);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
IBusSerializable *
|
|
Packit |
3ff832 |
ibus_serializable_copy (IBusSerializable *object)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
g_return_val_if_fail (IBUS_IS_SERIALIZABLE (object), NULL);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
GType type;
|
|
Packit |
3ff832 |
IBusSerializable *new_object;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
type = G_OBJECT_TYPE (object);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
new_object = g_object_new (type, NULL);
|
|
Packit |
3ff832 |
g_return_val_if_fail (new_object != NULL, NULL);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
if (IBUS_SERIALIZABLE_GET_CLASS (new_object)->copy (new_object, object)) {
|
|
Packit |
3ff832 |
return new_object;
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
g_object_unref (new_object);
|
|
Packit |
3ff832 |
g_return_val_if_reached (NULL);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
GVariant *
|
|
Packit |
3ff832 |
ibus_serializable_serialize_object (IBusSerializable *object)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
g_return_val_if_fail (IBUS_IS_SERIALIZABLE (object), FALSE);
|
|
Packit |
3ff832 |
gboolean retval;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
GVariantBuilder builder;
|
|
Packit |
3ff832 |
g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
g_variant_builder_add (&builder, "s", g_type_name (G_OBJECT_TYPE (object)));
|
|
Packit |
3ff832 |
retval = IBUS_SERIALIZABLE_GET_CLASS (object)->serialize (object, &builder);
|
|
Packit |
3ff832 |
g_assert (retval);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
return g_variant_builder_end (&builder);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
IBusSerializable *
|
|
Packit |
3ff832 |
ibus_serializable_deserialize_object (GVariant *variant)
|
|
Packit |
3ff832 |
{
|
|
Packit |
3ff832 |
g_return_val_if_fail (variant != NULL, NULL);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
GVariant *var = NULL;
|
|
Packit |
3ff832 |
switch (g_variant_classify (variant)) {
|
|
Packit |
3ff832 |
case G_VARIANT_CLASS_VARIANT:
|
|
Packit |
3ff832 |
var = g_variant_get_variant (variant);
|
|
Packit |
3ff832 |
break;
|
|
Packit |
3ff832 |
case G_VARIANT_CLASS_TUPLE:
|
|
Packit |
3ff832 |
var = g_variant_ref (variant);
|
|
Packit |
3ff832 |
break;
|
|
Packit |
3ff832 |
default:
|
|
Packit |
3ff832 |
g_return_val_if_reached (NULL);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
gchar *type_name = NULL;
|
|
Packit |
3ff832 |
g_variant_get_child (var, 0, "&s", &type_name);
|
|
Packit |
3ff832 |
GType type = g_type_from_name (type_name);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
g_return_val_if_fail (g_type_is_a (type, IBUS_TYPE_SERIALIZABLE), NULL);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
IBusSerializable *object = g_object_new (type, NULL);
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
gint retval = IBUS_SERIALIZABLE_GET_CLASS (object)->deserialize (object, var);
|
|
Packit |
3ff832 |
g_variant_unref (var);
|
|
Packit |
3ff832 |
if (retval)
|
|
Packit |
3ff832 |
return object;
|
|
Packit |
3ff832 |
|
|
Packit |
3ff832 |
g_object_unref (object);
|
|
Packit |
3ff832 |
g_return_val_if_reached (NULL);
|
|
Packit |
3ff832 |
}
|
|
Packit |
3ff832 |
|