Commit 0c37e2de authored by Christian Hergert's avatar Christian Hergert
Browse files

code-index: code style cleanup for map builder

parent f23579d3
......@@ -23,24 +23,28 @@
#include "ide-persistent-map-builder.h"
struct _IdePersistentMapBuilder
typedef struct
{
GObject parent;
/* Array of keys. */
GByteArray *keys;
GByteArray *keys;
/* Hash table of keys to remove duplicate keys. */
GHashTable *keys_hash;
GHashTable *keys_hash;
/* Array of values. */
GPtrArray *values;
GPtrArray *values;
/*
* Array of key value pairs. This is pair of offset of
* key in keys array and index of value in values array.
*/
GArray *kvpairs;
GArray *kvpairs;
/* Dictionary for metadata. */
GVariantDict *metadata;
};
/* Where to write the file */
GFile *destination;
} BuildState;
typedef struct
{
......@@ -48,8 +52,40 @@ typedef struct
guint32 value;
} KVPair;
struct _IdePersistentMapBuilder
{
GObject parent;
/* Owning thread for assertions */
GThread *thread;
/*
* The build state lets us keep all the contents together, and then
* pass it to the worker thread so the main thread can no longer access
* the existing state.
*/
BuildState *state;
};
G_STATIC_ASSERT (sizeof (KVPair) == 8);
G_DEFINE_TYPE (IdePersistentMapBuilder, ide_persistent_map_builder, G_TYPE_OBJECT)
static void
build_state_free (gpointer data)
{
BuildState *state = data;
g_clear_pointer (&state->keys, g_byte_array_unref);
g_clear_pointer (&state->keys_hash, g_hash_table_unref);
g_clear_pointer (&state->values, g_ptr_array_unref);
g_clear_pointer (&state->kvpairs, g_array_unref);
g_clear_pointer (&state->metadata, g_variant_dict_unref);
g_clear_object (&state->destination);
g_slice_free (BuildState, state);
}
void
ide_persistent_map_builder_insert (IdePersistentMapBuilder *self,
const gchar *key,
......@@ -62,35 +98,38 @@ ide_persistent_map_builder_insert (IdePersistentMapBuilder *self,
g_return_if_fail (IDE_IS_PERSISTENT_MAP_BUILDER (self));
g_return_if_fail (key != NULL);
g_return_if_fail (value != NULL);
g_return_if_fail (self->state != NULL);
g_return_if_fail (self->state->keys_hash != NULL);
g_return_if_fail (self->state->values != NULL);
g_return_if_fail (self->state->kvpairs != NULL);
local_value = g_variant_ref_sink (value);
if ((value_index = GPOINTER_TO_UINT (g_hash_table_lookup (self->keys_hash, key))))
if (0 != (value_index = GPOINTER_TO_UINT (g_hash_table_lookup (self->state->keys_hash, key))))
{
value_index--;
if (replace)
{
g_clear_pointer (&g_ptr_array_index (self->values, value_index), g_variant_unref);
g_ptr_array_index (self->values, value_index) = g_steal_pointer (&local_value);
g_variant_unref (g_ptr_array_index (self->state->values, value_index - 1));
g_ptr_array_index (self->state->values, value_index - 1) = g_steal_pointer (&local_value);
}
}
else
{
KVPair kvpair;
kvpair.key = self->keys->len;
kvpair.value = self->values->len;
kvpair.key = self->state->keys->len;
kvpair.value = self->state->values->len;
g_byte_array_append (self->keys, (const guchar *)key, strlen (key) + 1);
g_ptr_array_add (self->values, g_steal_pointer (&local_value));
g_array_append_val (self->kvpairs, kvpair);
g_byte_array_append (self->state->keys, (const guchar *)key, strlen (key) + 1);
g_ptr_array_add (self->state->values, g_steal_pointer (&local_value));
g_array_append_val (self->state->kvpairs, kvpair);
/*
* Key in hashtable is the actual key in our map.
* Value in hash table will point to element in values array
* where actual value of key in our map is there.
*/
g_hash_table_insert (self->keys_hash,
g_hash_table_insert (self->state->keys_hash,
g_strdup (key),
GUINT_TO_POINTER (kvpair.value + 1));
}
......@@ -103,17 +142,16 @@ ide_persistent_map_builder_set_metadata_int64 (IdePersistentMapBuilder *self,
{
g_return_if_fail (IDE_IS_PERSISTENT_MAP_BUILDER (self));
g_return_if_fail (key != NULL);
g_return_if_fail (self->state != NULL);
g_return_if_fail (self->state->metadata != NULL);
g_variant_dict_insert (self->metadata,
key,
"x",
value);
g_variant_dict_insert (self->state->metadata, key, "x", value);
}
gint
compare (KVPair *a,
KVPair *b,
gchar *keys)
static gint
compare_keys (KVPair *a,
KVPair *b,
const gchar *keys)
{
return g_strcmp0 (keys + a->key, keys + b->key);
}
......@@ -125,65 +163,73 @@ ide_persistent_map_builder_write_worker (GTask *task,
GCancellable *cancellable)
{
IdePersistentMapBuilder *self = source_object;
GFile *destination = task_data;
GVariantDict dict;
BuildState *state = task_data;
g_autoptr(GError) error = NULL;
g_autoptr(GVariant) data = NULL;
GVariantDict dict;
GVariant *keys;
GVariant *values;
GVariant *kvpairs;
GVariant *metadata;
g_autoptr(GError) error = NULL;
g_assert (G_IS_TASK (task));
g_assert (IDE_IS_PERSISTENT_MAP_BUILDER (self));
g_assert (G_IS_FILE (destination));
g_assert (state != NULL);
g_assert (state->keys != NULL);
g_assert (state->keys_hash != NULL);
g_assert (state->values != NULL);
g_assert (state->kvpairs != NULL);
g_assert (state->metadata != NULL);
g_assert (G_IS_FILE (state->destination));
g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
if (!self->keys->len)
g_task_return_boolean (task, TRUE);
if (g_task_return_error_if_cancelled (task))
return;
if (state->keys->len == 0)
{
g_task_return_new_error (task,
G_IO_ERROR,
G_IO_ERROR_INVALID_DATA,
"No entries to write");
return;
}
g_variant_dict_init (&dict, NULL);
keys = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
self->keys->data,
self->keys->len,
state->keys->data,
state->keys->len,
sizeof (guint8));
values = g_variant_new_array (NULL,
(GVariant * const *)(gpointer)self->values->pdata,
self->values->len);
(GVariant * const *)(gpointer)state->values->pdata,
state->values->len);
g_array_sort_with_data (state->kvpairs,
(GCompareDataFunc)compare_keys,
state->keys->data);
g_array_sort_with_data (self->kvpairs, (GCompareDataFunc)compare, self->keys->data);
kvpairs = g_variant_new_fixed_array (G_VARIANT_TYPE ("(uu)"),
self->kvpairs->data,
self->kvpairs->len,
state->kvpairs->data,
state->kvpairs->len,
sizeof (KVPair));
metadata = g_variant_dict_end (self->metadata);
metadata = g_variant_dict_end (state->metadata);
/* Insert Keys. */
g_variant_dict_insert_value (&dict, "keys", keys);
/* Insert values. */
g_variant_dict_insert_value (&dict, "values", values);
/* Insert key value pairs. */
g_variant_dict_insert_value (&dict, "kvpairs", kvpairs);
/* Insert metadata. */
g_variant_dict_insert_value (&dict, "metadata", metadata);
/* Insert verion number. */
g_variant_dict_insert (&dict,
"version",
"i",
2);
/* Insert byte order*/
g_variant_dict_insert (&dict,
"byte-order",
"i",
G_BYTE_ORDER);
/* Write to file. */
data = g_variant_ref_sink (g_variant_dict_end (&dict));
if (g_file_replace_contents (destination,
g_variant_dict_insert (&dict, "version", "i", 2);
g_variant_dict_insert (&dict, "byte-order", "i", G_BYTE_ORDER);
data = g_variant_take_ref (g_variant_dict_end (&dict));
if (g_task_return_error_if_cancelled (task))
return;
if (g_file_replace_contents (state->destination,
g_variant_get_data (data),
g_variant_get_size (data),
NULL,
......@@ -198,74 +244,78 @@ ide_persistent_map_builder_write_worker (GTask *task,
}
gboolean
ide_persistent_map_builder_write (IdePersistentMapBuilder *self,
GFile *destination,
gint io_priority,
GCancellable *cancellable,
GError **error)
ide_persistent_map_builder_write (IdePersistentMapBuilder *self,
GFile *destination,
gint io_priority,
GCancellable *cancellable,
GError **error)
{
g_autoptr(GTask) task = NULL;
g_return_val_if_fail (IDE_IS_PERSISTENT_MAP_BUILDER (self), FALSE);
g_return_val_if_fail (self->thread == g_thread_self (), FALSE);
g_return_val_if_fail (G_IS_FILE (destination), FALSE);
g_return_val_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable), FALSE);
g_return_val_if_fail (self->state != NULL, FALSE);
g_return_val_if_fail (self->state->destination != NULL, FALSE);
self->state->destination = g_object_ref (destination);
task = g_task_new (self, cancellable, NULL, NULL);
g_task_set_source_tag (task, ide_persistent_map_builder_write);
g_task_set_priority (task, io_priority);
g_task_set_task_data (task, g_object_ref (destination), g_object_unref);
if (self->values->len)
ide_persistent_map_builder_write_worker (task, self, destination, cancellable);
else
g_task_return_new_error (task,
G_IO_ERROR,
G_IO_ERROR_INVALID_DATA,
"No entries to write");
g_task_set_task_data (task, g_steal_pointer (&self->state), build_state_free);
g_task_run_in_thread_sync (task, ide_persistent_map_builder_write_worker);
return g_task_propagate_boolean (task, error);
}
void
ide_persistent_map_builder_write_async (IdePersistentMapBuilder *self,
GFile *destination,
gint io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
ide_persistent_map_builder_write_async (IdePersistentMapBuilder *self,
GFile *destination,
gint io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
g_autoptr(GTask) task = NULL;
g_return_if_fail (IDE_IS_PERSISTENT_MAP_BUILDER (self));
g_return_if_fail (self->thread == g_thread_self ());
g_return_if_fail (G_IS_FILE (destination));
g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
g_return_if_fail (self->thread == g_thread_self ());
g_return_if_fail (self->state != NULL);
g_return_if_fail (self->state->destination != NULL);
self->state->destination = g_object_ref (destination);
task = g_task_new (self, cancellable, callback, user_data);
g_task_set_priority (task, io_priority);
g_task_set_task_data (task, g_object_ref (destination), g_object_unref);
g_task_set_source_tag (task, ide_persistent_map_builder_write_async);
g_task_set_task_data (task, g_steal_pointer (&self->state), build_state_free);
g_task_run_in_thread (task, ide_persistent_map_builder_write_worker);
}
/**
* ide_persistent_map_builder_write_finish:
* @self: An #IdePersistentMapBuilder instance.
* @result: result of writing process
* @error: error in writing process
* @self: an #IdePersistentMapBuilder
* @result: a #GAsyncResult provided to callback
* @error: location for a #GError, or %NULL
*
* Returns: Whether file is written or not.
* Returns: %TRUE if the while was written successfully; otherwise %FALSE
* and @error is set.
*/
gboolean
ide_persistent_map_builder_write_finish (IdePersistentMapBuilder *self,
GAsyncResult *result,
GError **error)
{
GTask *task = (GTask *)result;
g_assert (G_IS_TASK (task));
g_return_val_if_fail (IDE_IS_PERSISTENT_MAP_BUILDER (self), FALSE);
g_return_val_if_fail (G_IS_TASK (result), FALSE);
g_return_val_if_fail (self->thread == g_thread_self (), FALSE);
return g_task_propagate_boolean (task, error);
return g_task_propagate_boolean (G_TASK (result), error);
}
static void
......@@ -273,11 +323,8 @@ ide_persistent_map_builder_finalize (GObject *object)
{
IdePersistentMapBuilder *self = (IdePersistentMapBuilder *)object;
g_clear_pointer (&self->keys, g_byte_array_unref);
g_clear_pointer (&self->keys_hash, g_hash_table_unref);
g_clear_pointer (&self->values, g_ptr_array_unref);
g_clear_pointer (&self->kvpairs, g_array_unref);
g_clear_pointer (&self->metadata, g_variant_dict_unref);
g_clear_pointer (&self->state, build_state_free);
self->thread = NULL;
G_OBJECT_CLASS (ide_persistent_map_builder_parent_class)->finalize (object);
}
......@@ -285,11 +332,14 @@ ide_persistent_map_builder_finalize (GObject *object)
static void
ide_persistent_map_builder_init (IdePersistentMapBuilder *self)
{
self->keys = g_byte_array_new ();
self->keys_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
self->values = g_ptr_array_new_with_free_func ((GDestroyNotify)g_variant_unref);
self->kvpairs = g_array_new (FALSE, FALSE, sizeof (KVPair));
self->metadata = g_variant_dict_new (NULL);
self->thread = g_thread_self ();
self->state = g_slice_new0 (BuildState);
self->state->keys = g_byte_array_new ();
self->state->keys_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
self->state->values = g_ptr_array_new_with_free_func ((GDestroyNotify)g_variant_unref);
self->state->kvpairs = g_array_new (FALSE, FALSE, sizeof (KVPair));
self->state->metadata = g_variant_dict_new (NULL);
}
static void
......@@ -300,7 +350,7 @@ ide_persistent_map_builder_class_init (IdePersistentMapBuilderClass *klass)
object_class->finalize = ide_persistent_map_builder_finalize;
}
IdePersistentMapBuilder*
IdePersistentMapBuilder *
ide_persistent_map_builder_new (void)
{
return g_object_new (IDE_TYPE_PERSISTENT_MAP_BUILDER, NULL);
......
......@@ -27,27 +27,27 @@ G_BEGIN_DECLS
G_DECLARE_FINAL_TYPE (IdePersistentMapBuilder, ide_persistent_map_builder, IDE, PERSISTENT_MAP_BUILDER, GObject)
IdePersistentMapBuilder *ide_persistent_map_builder_new (void);
void ide_persistent_map_builder_insert (IdePersistentMapBuilder *self,
const gchar *key,
GVariant *value,
gboolean replace);
gboolean ide_persistent_map_builder_write (IdePersistentMapBuilder *self,
GFile *destination,
gint io_priority,
GCancellable *cancellable,
GError **error);
void ide_persistent_map_builder_write_async (IdePersistentMapBuilder *self,
GFile *destination,
gint io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean ide_persistent_map_builder_write_finish (IdePersistentMapBuilder *self,
GAsyncResult *result,
GError **error);
void ide_persistent_map_builder_set_metadata_int64 (IdePersistentMapBuilder *self,
const gchar *key,
gint64 value);
IdePersistentMapBuilder *ide_persistent_map_builder_new (void);
void ide_persistent_map_builder_insert (IdePersistentMapBuilder *self,
const gchar *key,
GVariant *value,
gboolean replace);
void ide_persistent_map_builder_set_metadata_int64 (IdePersistentMapBuilder *self,
const gchar *key,
gint64 value);
gboolean ide_persistent_map_builder_write (IdePersistentMapBuilder *self,
GFile *destination,
gint io_priority,
GCancellable *cancellable,
GError **error);
void ide_persistent_map_builder_write_async (IdePersistentMapBuilder *self,
GFile *destination,
gint io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean ide_persistent_map_builder_write_finish (IdePersistentMapBuilder *self,
GAsyncResult *result,
GError **error);
G_END_DECLS
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment