Blame src/ibusserializable.c

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