Created
July 12, 2019 20:35
-
-
Save geoffjay/47de7983bed90a262ffc663166f36da5 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* compile: | |
* gcc -g -o json-hashtable `pkg-config --cflags --libs json-glib-1.0` json-hashtable.c | |
* | |
* memcheck: | |
* G_SLICE=always-malloc G_DEBUG=gc-friendly valgrind --tool=memcheck \ | |
* --leak-check=full --show-leak-kinds=definite --errors-for-leak-kinds=definite \ | |
* --leak-resolution=high --num-callers=20 \ | |
* --suppressions=/usr/share/glib-2.0/valgrind/glib.supp \ | |
* ./json-hashtable | |
*/ | |
#include <json-glib/json-glib.h> | |
#define FOO_TYPE_OBJECT foo_object_get_type () | |
G_DECLARE_FINAL_TYPE (FooObject, foo_object, FOO, OBJECT, GObject) | |
GHashTable *foo_object_get_list (FooObject *self); | |
void foo_object_set_list (FooObject *self, | |
GHashTable *list); | |
struct _FooObject | |
{ | |
GObject parent; | |
GHashTable *list; | |
}; | |
enum { | |
PROP_0, | |
PROP_LIST, | |
N_PROPS | |
}; | |
static GParamSpec *properties [N_PROPS]; | |
static void json_serializable_iface_init (gpointer g_iface); | |
G_DEFINE_TYPE_WITH_CODE (FooObject, foo_object, G_TYPE_OBJECT, | |
G_IMPLEMENT_INTERFACE (JSON_TYPE_SERIALIZABLE, | |
json_serializable_iface_init)); | |
static JsonNode * | |
foo_object_serialize_property (JsonSerializable *serializable, | |
const gchar *name, | |
const GValue *value, | |
GParamSpec *pspec) | |
{ | |
if (g_strcmp0 (name, "list") == 0) | |
{ | |
JsonNode *retval; | |
JsonObject *obj; | |
GHashTable *list; | |
GHashTableIter iter; | |
gpointer key, val; | |
retval = json_node_new (JSON_NODE_OBJECT); | |
g_return_val_if_fail (value != NULL, retval); | |
g_return_val_if_fail (G_VALUE_HOLDS_POINTER (value), retval); | |
list = g_value_get_pointer (value); | |
g_return_val_if_fail (list != NULL, retval); | |
obj = json_object_new (); | |
if (list != NULL) | |
{ | |
g_hash_table_iter_init (&iter, list); | |
while (g_hash_table_iter_next (&iter, &key, &val)) | |
{ | |
json_object_set_double_member (obj, | |
(const gchar *) key, | |
g_strtod ((const gchar *) val, NULL)); | |
} | |
} | |
json_node_take_object (retval, obj); | |
return retval; | |
} | |
return json_serializable_default_serialize_property (serializable, name, value, pspec); | |
} | |
static gboolean | |
foo_object_deserialize_property (JsonSerializable *serializable, | |
const gchar *name, | |
GValue *value, | |
GParamSpec *pspec, | |
JsonNode *property_node) | |
{ | |
if (g_strcmp0 (name, "list") == 0) | |
{ | |
g_autoptr (GHashTable) list = NULL; | |
JsonObject *obj; | |
JsonObjectIter iter; | |
const gchar *key; | |
JsonNode *val; | |
list = g_hash_table_new_full (g_str_hash, | |
g_str_equal, | |
g_free, | |
g_free); | |
obj = json_node_dup_object (property_node); | |
json_object_iter_init (&iter, obj); | |
while (json_object_iter_next (&iter, &key, &val)) | |
{ | |
g_hash_table_insert (list, | |
g_strdup (key), | |
g_strdup_printf ("%.9f", json_node_get_double (val))); | |
json_node_free (val); | |
} | |
g_value_set_pointer (value, list); | |
g_hash_table_ref (list); | |
return TRUE; | |
} | |
return json_serializable_default_deserialize_property (serializable, name, value, pspec, property_node); | |
} | |
static void | |
json_serializable_iface_init (gpointer g_iface) | |
{ | |
JsonSerializableIface *iface = g_iface; | |
iface->serialize_property = foo_object_serialize_property; | |
iface->deserialize_property = foo_object_deserialize_property; | |
} | |
static void | |
foo_object_dispose (GObject *object) | |
{ | |
G_GNUC_UNUSED FooObject *self = (FooObject *)object; | |
g_debug ("dispose"); | |
G_OBJECT_CLASS (foo_object_parent_class)->dispose (object); | |
} | |
static void | |
foo_object_finalize (GObject *object) | |
{ | |
FooObject *self = (FooObject *)object; | |
g_clear_pointer (&self->list, g_hash_table_unref); | |
G_OBJECT_CLASS (foo_object_parent_class)->finalize (object); | |
} | |
static void | |
foo_object_get_property (GObject *object, | |
guint prop_id, | |
GValue *value, | |
GParamSpec *pspec) | |
{ | |
FooObject *self = FOO_OBJECT (object); | |
switch (prop_id) | |
{ | |
case PROP_LIST: | |
g_value_set_pointer (value, self->list); | |
break; | |
default: | |
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | |
} | |
} | |
static void | |
foo_object_set_property (GObject *object, | |
guint prop_id, | |
const GValue *value, | |
GParamSpec *pspec) | |
{ | |
FooObject *self = FOO_OBJECT (object); | |
switch (prop_id) | |
{ | |
case PROP_LIST: | |
foo_object_set_list (self, g_value_get_pointer (value)); | |
break; | |
default: | |
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | |
} | |
} | |
static void | |
foo_object_class_init (FooObjectClass *klass) | |
{ | |
GObjectClass *object_class = G_OBJECT_CLASS (klass); | |
object_class->finalize = foo_object_dispose; | |
object_class->finalize = foo_object_finalize; | |
object_class->get_property = foo_object_get_property; | |
object_class->set_property = foo_object_set_property; | |
properties [PROP_LIST] = | |
g_param_spec_pointer ("list", | |
"List", | |
"List of things.", | |
(G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_CONSTRUCT)); | |
g_object_class_install_properties (object_class, N_PROPS, properties); | |
} | |
static void | |
foo_object_init (FooObject *self) | |
{ | |
} | |
FooObject * | |
foo_object_new () | |
{ | |
return g_object_new (FOO_TYPE_OBJECT, NULL); | |
} | |
gchar * | |
foo_object_serialize (FooObject *self) | |
{ | |
g_return_val_if_fail (FOO_IS_OBJECT (self), NULL); | |
return json_gobject_to_data (G_OBJECT (self), NULL); | |
} | |
void | |
foo_object_deserialize (FooObject *self, | |
const gchar *data) | |
{ | |
g_autoptr (GObject) object = NULL; | |
g_autoptr (GHashTable) list = NULL; | |
GError *err = NULL; | |
object = json_gobject_from_data (FOO_TYPE_OBJECT, | |
data, | |
-1, | |
&err); | |
if (err != NULL) | |
{ | |
g_critical ("%s", err->message); | |
g_error_free (err); | |
} | |
g_return_if_fail (object != NULL); | |
g_return_if_fail (FOO_IS_OBJECT (object)); | |
list = foo_object_get_list (FOO_OBJECT (object)); | |
foo_object_set_list (self, list); | |
g_clear_object (&object); | |
} | |
GObject * | |
foo_gobject_from_data (const gchar *data) | |
{ | |
GError *err = NULL; | |
GObject *object = json_gobject_from_data (FOO_TYPE_OBJECT, | |
data, | |
-1, | |
&err); | |
if (err != NULL) | |
{ | |
g_critical ("%s", err->message); | |
g_error_free (err); | |
} | |
g_return_val_if_fail (object != NULL, NULL); | |
g_return_val_if_fail (FOO_IS_OBJECT (object), NULL); | |
return object; | |
} | |
void | |
foo_object_dummy_data (FooObject *self) | |
{ | |
g_autoptr (GHashTable) list = NULL; | |
g_return_if_fail (FOO_IS_OBJECT (self)); | |
list = g_hash_table_new_full (g_str_hash, | |
g_str_equal, | |
g_free, | |
g_free); | |
g_hash_table_insert (list, g_strdup ("a"), g_strdup ("0.0")); | |
g_hash_table_insert (list, g_strdup ("b"), g_strdup ("1.0")); | |
g_hash_table_insert (list, g_strdup ("c"), g_strdup ("2.0")); | |
g_hash_table_insert (list, g_strdup ("d"), g_strdup ("3.0")); | |
foo_object_set_list (self, list); | |
} | |
GHashTable * | |
foo_object_get_list (FooObject *self) | |
{ | |
GHashTable *list; | |
g_return_val_if_fail (FOO_IS_OBJECT (self), NULL); | |
g_object_get (self, "list", &list, NULL); | |
return list; | |
} | |
void | |
foo_object_set_list (FooObject *self, | |
GHashTable *list) | |
{ | |
g_return_if_fail (FOO_IS_OBJECT (self)); | |
if (self->list == list) | |
return; | |
if (list) | |
g_hash_table_ref (list); | |
if (self->list) | |
g_hash_table_unref (self->list); | |
self->list = list; | |
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_LIST]); | |
} | |
static const gchar *json = "{ \ | |
\"list\": { \ | |
\"a\": 0.0, \ | |
\"b\": 1.0, \ | |
\"c\": 2.0, \ | |
\"d\": 3.0 \ | |
} \ | |
}"; | |
gint | |
main (gint argc, gchar *argv[]) | |
{ | |
{ | |
g_autoptr (FooObject) obj = NULL; | |
g_autofree gchar *data = NULL; | |
obj = foo_object_new (); | |
foo_object_dummy_data (obj); | |
data = foo_object_serialize (obj); | |
g_print ("%s\n", data); | |
} | |
{ | |
g_autoptr (FooObject) obj = NULL; | |
g_autofree gchar *data = NULL; | |
obj = foo_object_new (); | |
foo_object_deserialize (obj, json); | |
/*obj = foo_gobject_from_data (json);*/ | |
/*obj = FOO_OBJECT (json_gobject_from_data (FOO_TYPE_OBJECT, json, -1, NULL));*/ | |
data = foo_object_serialize (obj); | |
g_print ("%s\n", data); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment