Same case as last GApplication patch, but kept split for easier understanding. Signed-off-by: Eduardo Lima (Etrunko) <etrunko@xxxxxxxxxx> --- src/virt-glib-compat.c | 204 +++++++++++++++++++++++++++++++++++++++++++++++++ src/virt-glib-compat.h | 32 ++++++++ 2 files changed, 236 insertions(+) diff --git a/src/virt-glib-compat.c b/src/virt-glib-compat.c index 4748993..a61a3a6 100644 --- a/src/virt-glib-compat.c +++ b/src/virt-glib-compat.c @@ -399,4 +399,208 @@ g_application_real_local_command_line (GApplication *application, return TRUE; } + +struct stack_dict +{ + GHashTable *values; + gsize magic; +}; + +G_STATIC_ASSERT (sizeof (struct stack_dict) <= sizeof (GVariantDict)); + +struct heap_dict +{ + struct stack_dict dict; + gint ref_count; + gsize magic; +}; + +#define GVSD(d) ((struct stack_dict *) (d)) +#define GVHD(d) ((struct heap_dict *) (d)) +#define GVSD_MAGIC ((gsize) 2579507750u) +#define GVHD_MAGIC ((gsize) 2450270775u) +#define is_valid_dict(d) (d != NULL && \ + GVSD(d)->magic == GVSD_MAGIC) +#define is_valid_heap_dict(d) (GVHD(d)->magic == GVHD_MAGIC) + +GVariantDict * +g_variant_dict_new (GVariant *from_asv) +{ + GVariantDict *dict; + + dict = g_slice_alloc (sizeof (struct heap_dict)); + g_variant_dict_init (dict, from_asv); + GVHD(dict)->magic = GVHD_MAGIC; + GVHD(dict)->ref_count = 1; + + return dict; +} + +void +g_variant_dict_init (GVariantDict *dict, + GVariant *from_asv) +{ + GVariantIter iter; + gchar *key; + GVariant *value; + + GVSD(dict)->values = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_variant_unref); + GVSD(dict)->magic = GVSD_MAGIC; + + if (from_asv) + { + g_variant_iter_init (&iter, from_asv); + while (g_variant_iter_next (&iter, "{sv}", &key, &value)) + g_hash_table_insert (GVSD(dict)->values, key, value); + } +} + +gboolean +g_variant_dict_lookup (GVariantDict *dict, + const gchar *key, + const gchar *format_string, + ...) +{ + GVariant *value; + va_list ap; + + g_return_val_if_fail (is_valid_dict (dict), FALSE); + g_return_val_if_fail (key != NULL, FALSE); + g_return_val_if_fail (format_string != NULL, FALSE); + + value = g_hash_table_lookup (GVSD(dict)->values, key); + + if (value == NULL || !g_variant_check_format_string (value, format_string, FALSE)) + return FALSE; + + va_start (ap, format_string); + g_variant_get_va (value, format_string, NULL, &ap); + va_end (ap); + + return TRUE; +} + +GVariant * +g_variant_dict_lookup_value (GVariantDict *dict, + const gchar *key, + const GVariantType *expected_type) +{ + GVariant *result; + + g_return_val_if_fail (is_valid_dict (dict), NULL); + g_return_val_if_fail (key != NULL, NULL); + + result = g_hash_table_lookup (GVSD(dict)->values, key); + + if (result && (!expected_type || g_variant_is_of_type (result, expected_type))) + return g_variant_ref (result); + + return NULL; +} + +gboolean +g_variant_dict_contains (GVariantDict *dict, + const gchar *key) +{ + g_return_val_if_fail (is_valid_dict (dict), FALSE); + g_return_val_if_fail (key != NULL, FALSE); + + return g_hash_table_contains (GVSD(dict)->values, key); +} + +void +g_variant_dict_insert (GVariantDict *dict, + const gchar *key, + const gchar *format_string, + ...) +{ + va_list ap; + + g_return_if_fail (is_valid_dict (dict)); + g_return_if_fail (key != NULL); + g_return_if_fail (format_string != NULL); + + va_start (ap, format_string); + g_variant_dict_insert_value (dict, key, g_variant_new_va (format_string, NULL, &ap)); + va_end (ap); +} + +void +g_variant_dict_insert_value (GVariantDict *dict, + const gchar *key, + GVariant *value) +{ + g_return_if_fail (is_valid_dict (dict)); + g_return_if_fail (key != NULL); + g_return_if_fail (value != NULL); + + g_hash_table_insert (GVSD(dict)->values, g_strdup (key), g_variant_ref_sink (value)); +} + +gboolean +g_variant_dict_remove (GVariantDict *dict, + const gchar *key) +{ + g_return_val_if_fail (is_valid_dict (dict), FALSE); + g_return_val_if_fail (key != NULL, FALSE); + + return g_hash_table_remove (GVSD(dict)->values, key); +} + +void +g_variant_dict_clear (GVariantDict *dict) +{ + if (GVSD(dict)->magic == 0) + /* all-zeros case */ + return; + + g_return_if_fail (is_valid_dict (dict)); + + g_hash_table_unref (GVSD(dict)->values); + GVSD(dict)->values = NULL; + + GVSD(dict)->magic = 0; +} + +GVariant * +g_variant_dict_end (GVariantDict *dict) +{ + GVariantBuilder builder; + GHashTableIter iter; + gpointer key, value; + + g_return_val_if_fail (is_valid_dict (dict), NULL); + + g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT); + + g_hash_table_iter_init (&iter, GVSD(dict)->values); + while (g_hash_table_iter_next (&iter, &key, &value)) + g_variant_builder_add (&builder, "{sv}", (const gchar *) key, (GVariant *) value); + + g_variant_dict_clear (dict); + + return g_variant_builder_end (&builder); +} + +GVariantDict * +g_variant_dict_ref (GVariantDict *dict) +{ + g_return_val_if_fail (is_valid_heap_dict (dict), NULL); + + GVHD(dict)->ref_count++; + + return dict; +} + +void +g_variant_dict_unref (GVariantDict *dict) +{ + g_return_if_fail (is_valid_heap_dict (dict)); + + if (--GVHD(dict)->ref_count == 0) + { + g_variant_dict_clear (dict); + g_slice_free (struct heap_dict, (struct heap_dict *) dict); + } +} #endif diff --git a/src/virt-glib-compat.h b/src/virt-glib-compat.h index 29fcdef..26add80 100644 --- a/src/virt-glib-compat.h +++ b/src/virt-glib-compat.h @@ -87,6 +87,38 @@ void g_application_add_option_group (GApplication *application, gboolean g_application_real_local_command_line (GApplication *application, gchar ***arguments, int *exit_status); + +typedef struct _GVariantDict GVariantDict; +struct _GVariantDict { + /*< private >*/ + gsize x[16]; +}; + +GVariantDict * g_variant_dict_new (GVariant *from_asv); +void g_variant_dict_init (GVariantDict *dict, + GVariant *from_asv); +gboolean g_variant_dict_lookup (GVariantDict *dict, + const gchar *key, + const gchar *format_string, + ...); +GVariant * g_variant_dict_lookup_value (GVariantDict *dict, + const gchar *key, + const GVariantType *expected_type); +gboolean g_variant_dict_contains (GVariantDict *dict, + const gchar *key); +void g_variant_dict_insert (GVariantDict *dict, + const gchar *key, + const gchar *format_string, + ...); +void g_variant_dict_insert_value (GVariantDict *dict, + const gchar *key, + GVariant *value); +gboolean g_variant_dict_remove (GVariantDict *dict, + const gchar *key); +void g_variant_dict_clear (GVariantDict *dict); +GVariant * g_variant_dict_end (GVariantDict *dict); +GVariantDict * g_variant_dict_ref (GVariantDict *dict); +void g_variant_dict_unref (GVariantDict *dict); #endif G_END_DECLS -- 2.5.0 _______________________________________________ virt-tools-list mailing list virt-tools-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/virt-tools-list