[gnome-builder] Adding persistent map



commit 103df38e8783af1235409b09bbeb961301fd01fc
Author: Anoop Chandu <anoopchandu96 gmail com>
Date:   Sat Aug 26 20:04:30 2017 +0530

    Adding persistent map
    
    This map associates a GVariant with a key. With
    IdePersistentMapBuilder a map can be built and stored on to disk.
    Using IdePersistentMap map on disk can be loaded and searched.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=786700

 plugins/code-index/ide-persistent-map-builder.c |  306 ++++++++++++++++++++
 plugins/code-index/ide-persistent-map-builder.h |   56 ++++
 plugins/code-index/ide-persistent-map.c         |  341 +++++++++++++++++++++++
 plugins/code-index/ide-persistent-map.h         |   46 +++
 4 files changed, 749 insertions(+), 0 deletions(-)
---
diff --git a/plugins/code-index/ide-persistent-map-builder.c b/plugins/code-index/ide-persistent-map-builder.c
new file mode 100644
index 0000000..574a19f
--- /dev/null
+++ b/plugins/code-index/ide-persistent-map-builder.c
@@ -0,0 +1,306 @@
+/* ide-persistent-map-builder.c
+ *
+ * Copyright (C) 2017 Anoop Chandu <anoopchandu96 gmail com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define G_LOG_DOMAIN "ide-persistent-map-builder"
+
+#include <ide.h>
+
+#include "ide-persistent-map-builder.h"
+
+struct _IdePersistentMapBuilder
+{
+  GObject      parent;
+
+  /* Array of keys. */
+  GByteArray   *keys;
+  /* Hash table of keys to remove duplicate keys. */
+  GHashTable   *keys_hash;
+  /* Array of 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;
+  /* Dictionary for metadata. */
+  GVariantDict *metadata;
+};
+
+typedef struct
+{
+  guint32 key;
+  guint32 value;
+} KVPair;
+
+G_DEFINE_TYPE (IdePersistentMapBuilder, ide_persistent_map_builder, G_TYPE_OBJECT)
+
+void
+ide_persistent_map_builder_insert (IdePersistentMapBuilder *self,
+                                   const gchar             *key,
+                                   GVariant                *value,
+                                   gboolean                 replace)
+{
+  g_autoptr(GVariant) local_value = NULL;
+  guint32 value_index;
+
+  g_return_if_fail (IDE_IS_PERSISTENT_MAP_BUILDER (self));
+  g_return_if_fail (key != NULL);
+  g_return_if_fail (value != NULL);
+
+  local_value = g_variant_ref_sink (value);
+
+  if ((value_index = GPOINTER_TO_UINT (g_hash_table_lookup (self->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);
+        }
+    }
+  else
+    {
+      KVPair kvpair;
+
+      kvpair.key = self->keys->len;
+      kvpair.value = self->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);
+
+      /*
+       * 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_strdup (key),
+                           GUINT_TO_POINTER (kvpair.value + 1));
+    }
+}
+
+void
+ide_persistent_map_builder_set_metadata_int64 (IdePersistentMapBuilder *self,
+                                               const gchar             *key,
+                                               gint64                   value)
+{
+  g_return_if_fail (IDE_IS_PERSISTENT_MAP_BUILDER (self));
+  g_return_if_fail (key != NULL);
+
+  g_variant_dict_insert (self->metadata,
+                         key,
+                         "x",
+                         value);
+}
+
+gint
+compare (KVPair       *a,
+         KVPair       *b,
+         gchar        *keys)
+{
+  return g_strcmp0 (keys + a->key, keys + b->key);
+}
+
+void
+ide_persistent_map_builder_write_worker (GTask        *task,
+                                         gpointer      source_object,
+                                         gpointer      task_data,
+                                         GCancellable *cancellable)
+{
+  IdePersistentMapBuilder *self = source_object;
+  GFile *destination = task_data;
+  GVariantDict dict;
+  g_autoptr(GVariant) data = NULL;
+  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 (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+  if (!self->keys->len)
+    g_task_return_boolean (task, TRUE);
+
+  g_variant_dict_init (&dict, NULL);
+
+  keys = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
+                                    self->keys->data,
+                                    self->keys->len,
+                                    sizeof (guint8));
+
+  values = g_variant_new_array (NULL,
+                                (GVariant * const *)(gpointer)self->values->pdata,
+                                self->values->len);
+
+  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,
+                                       sizeof (KVPair));
+
+  metadata = g_variant_dict_end (self->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_get_data (data),
+                               g_variant_get_size (data),
+                               NULL,
+                               FALSE,
+                               G_FILE_CREATE_NONE,
+                               NULL,
+                               cancellable,
+                               &error))
+    g_task_return_boolean (task, TRUE);
+  else
+    g_task_return_error (task, g_steal_pointer (&error));
+}
+
+gboolean
+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 (G_IS_FILE (destination), FALSE);
+  g_return_val_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable), FALSE);
+
+  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");
+
+  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)
+{
+  g_autoptr(GTask) task = NULL;
+
+  g_return_if_fail (IDE_IS_PERSISTENT_MAP_BUILDER (self));
+  g_return_if_fail (G_IS_FILE (destination));
+  g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+  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_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
+ *
+ * Returns: Whether file is written or not.
+ */
+gboolean
+ide_persistent_map_builder_write_finish (IdePersistentMapBuilder  *self,
+                                         GAsyncResult             *result,
+                                         GError                  **error)
+{
+  GTask *task = (GTask *)result;
+
+  g_assert (G_IS_TASK (task));
+
+  return g_task_propagate_boolean (task, error);
+}
+
+static void
+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_OBJECT_CLASS (ide_persistent_map_builder_parent_class)->finalize (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 ();
+  self->kvpairs = g_array_new (FALSE, FALSE, sizeof (KVPair));
+  self->metadata = g_variant_dict_new (NULL);
+}
+
+static void
+ide_persistent_map_builder_class_init (IdePersistentMapBuilderClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = ide_persistent_map_builder_finalize;
+}
+
+IdePersistentMapBuilder*
+ide_persistent_map_builder_new (void)
+{
+  return g_object_new (IDE_TYPE_PERSISTENT_MAP_BUILDER, NULL);
+}
diff --git a/plugins/code-index/ide-persistent-map-builder.h b/plugins/code-index/ide-persistent-map-builder.h
new file mode 100644
index 0000000..5c1c7f7
--- /dev/null
+++ b/plugins/code-index/ide-persistent-map-builder.h
@@ -0,0 +1,56 @@
+/* ide-persistent-map-builder.h
+ *
+ * Copyright (C) 2017 Anoop Chandu <anoopchandu96 gmail com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <glib-object.h>
+#include <gio/gio.h>
+
+#ifndef IDE_TYPE_PERSISTENT_MAP_BUILDER_H
+#define IDE_TYPE_PERSISTENT_MAP_BUILDER_H
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_PERSISTENT_MAP_BUILDER (ide_persistent_map_builder_get_type ())
+
+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);
+
+G_END_DECLS
+
+#endif /* IDE_TYPE_PERSISTENT_MAP_BUILDER_H */
diff --git a/plugins/code-index/ide-persistent-map.c b/plugins/code-index/ide-persistent-map.c
new file mode 100644
index 0000000..a3f4baf
--- /dev/null
+++ b/plugins/code-index/ide-persistent-map.c
@@ -0,0 +1,341 @@
+/* ide-persistent-map.c
+ *
+ * Copyright (C) 2017 Anoop Chandu <anoopchandu96 gmail com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define G_LOG_DOMAIN "ide-persistent-map"
+
+#include <ide.h>
+
+#include "ide-persistent-map.h"
+
+typedef struct
+{
+  guint32 key;
+  guint32 value;
+} KVPair;
+
+struct _IdePersistentMap
+{
+  GObject            parent;
+
+  GMappedFile       *mapped_file;
+
+  GVariant          *data;
+
+  GVariant          *keys_var;
+  const gchar       *keys;
+
+  GVariant          *values;
+
+  GVariant          *kvpairs_var;
+  const KVPair      *kvpairs;
+
+  GVariantDict      *metadata;
+
+  gsize              n_kvpairs;
+
+  gint32             byte_order;
+
+  guint              loaded : 1;
+};
+
+G_DEFINE_TYPE (IdePersistentMap, ide_persistent_map, G_TYPE_OBJECT)
+
+static void
+ide_persistent_map_load_file_worker (GTask        *task,
+                                     gpointer      source_object,
+                                     gpointer      task_data,
+                                     GCancellable *cancellable)
+{
+  IdePersistentMap *self = source_object;
+  GFile *file = task_data;
+  g_autofree gchar *path = NULL;
+  g_autoptr(GMappedFile) mapped_file = NULL;
+  g_autoptr(GVariant) data = NULL;
+  g_autoptr(GVariant) keys = NULL;
+  g_autoptr(GVariant) values = NULL;
+  g_autoptr(GVariant) metadata = NULL;
+  g_autoptr(GVariant) kvpairs = NULL;
+  g_autoptr(GVariant) value_size = NULL;
+  GVariantDict dict;
+  gint32 version;
+  gsize n_elements;
+  g_autoptr(GError) error = NULL;
+
+  g_assert (G_IS_TASK (task));
+  g_assert (IDE_IS_PERSISTENT_MAP (self));
+  g_assert (G_IS_FILE (file));
+  g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+  if (self->loaded)
+    {
+      g_task_return_new_error (task,
+                               G_IO_ERROR,
+                               G_IO_ERROR_INVAL,
+                               "Index already loaded");
+      return;
+    }
+
+  self->loaded = TRUE;
+
+  if (!g_file_is_native (file) || NULL == (path = g_file_get_path (file)))
+    {
+      g_task_return_new_error (task,
+                               G_IO_ERROR,
+                               G_IO_ERROR_INVALID_FILENAME,
+                               "Index must be a local file");
+      return;
+    }
+
+  if (NULL == (mapped_file = g_mapped_file_new (path, FALSE, &error)))
+    {
+      g_task_return_error (task, g_steal_pointer (&error));
+      return;
+    }
+
+  data = g_variant_new_from_data (G_VARIANT_TYPE_VARDICT,
+                                  g_mapped_file_get_contents (mapped_file),
+                                  g_mapped_file_get_length (mapped_file),
+                                  FALSE, NULL, NULL);
+
+  if (data == NULL)
+    {
+      g_task_return_new_error (task,
+                               G_IO_ERROR,
+                               G_IO_ERROR_INVAL,
+                               "Failed to parse GVariant");
+      return;
+    }
+
+  g_variant_ref_sink (data);
+
+  g_variant_dict_init (&dict, data);
+
+  if (!g_variant_dict_lookup (&dict, "version", "i", &version) || version != 2)
+    {
+      g_variant_dict_clear (&dict);
+      g_task_return_new_error (task,
+                               G_IO_ERROR,
+                               G_IO_ERROR_INVAL,
+                               "Version mismatch in gvariant. Got %d, expected 1",
+                               version);
+      return;
+    }
+
+  keys = g_variant_dict_lookup_value (&dict, "keys", G_VARIANT_TYPE_ARRAY);
+  values = g_variant_dict_lookup_value (&dict, "values", G_VARIANT_TYPE_ARRAY);
+  kvpairs = g_variant_dict_lookup_value (&dict, "kvpairs", G_VARIANT_TYPE_ARRAY);
+  metadata = g_variant_dict_lookup_value (&dict, "metadata", G_VARIANT_TYPE_VARDICT);
+
+  if (!g_variant_dict_lookup (&dict, "byte-order", "i", &self->byte_order))
+    self->byte_order = 0;
+
+  g_variant_dict_clear (&dict);
+
+  if (keys == NULL || values == NULL || kvpairs == NULL || metadata == NULL || !self->byte_order)
+    {
+      g_task_return_new_error (task,
+                               G_IO_ERROR,
+                               G_IO_ERROR_INVAL,
+                               "Invalid GVariant index");
+      return;
+    }
+
+  self->keys = g_variant_get_fixed_array (keys,
+                                          &n_elements,
+                                          sizeof (guint8));
+
+  self->kvpairs = g_variant_get_fixed_array (kvpairs,
+                                             &self->n_kvpairs,
+                                             sizeof (KVPair));
+
+  self->mapped_file = g_steal_pointer (&mapped_file);
+  self->data = g_steal_pointer (&data);
+  self->keys_var = g_steal_pointer (&keys);
+  self->values = g_steal_pointer (&values);
+  self->kvpairs_var = g_steal_pointer (&kvpairs);
+  self->metadata = g_variant_dict_new (metadata);
+
+  g_task_return_boolean (task, TRUE);
+}
+
+gboolean
+ide_persistent_map_load_file (IdePersistentMap *self,
+                              GFile            *file,
+                              GCancellable     *cancellable,
+                              GError          **error)
+{
+  g_autoptr(GTask) task = NULL;
+
+  g_return_val_if_fail (IDE_IS_PERSISTENT_MAP (self), FALSE);
+  g_return_val_if_fail (G_IS_FILE (file), FALSE);
+  g_return_val_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable), FALSE);
+
+  task = g_task_new (self, cancellable, NULL, NULL);
+
+  g_task_set_priority (task, G_PRIORITY_LOW);
+  g_task_set_source_tag (task, ide_persistent_map_load_file);
+  g_task_set_task_data (task, g_object_ref (file), g_object_unref);
+
+  ide_persistent_map_load_file_worker (task, self, file, cancellable);
+
+  return g_task_propagate_boolean (task, error);
+}
+
+void
+ide_persistent_map_load_file_async  (IdePersistentMap      *self,
+                                     GFile                 *file,
+                                     GCancellable          *cancellable,
+                                     GAsyncReadyCallback    callback,
+                                     gpointer               user_data)
+{
+  g_autoptr(GTask) task = NULL;
+
+  g_return_if_fail (IDE_IS_PERSISTENT_MAP (self));
+  g_return_if_fail (G_IS_FILE (file));
+  g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+  task = g_task_new (self, cancellable, callback, user_data);
+
+  g_task_set_priority (task, G_PRIORITY_LOW);
+  g_task_set_task_data (task, g_object_ref (file), g_object_unref);
+  g_task_set_source_tag (task, ide_persistent_map_load_file_async);
+
+  g_task_run_in_thread (task, ide_persistent_map_load_file_worker);
+}
+
+/**
+ * ide_persistent_map_load_file_finish:
+ * @self: An #IdePersistentMap instance.
+ * @result: result of loading process
+ * @error: error in loading process
+ *
+ * Returns: Whether file is loaded or not.
+ */
+gboolean
+ide_persistent_map_load_file_finish (IdePersistentMap   *self,
+                                     GAsyncResult      *result,
+                                     GError           **error)
+{
+  GTask *task = (GTask *)result;
+
+  g_return_val_if_fail (G_IS_TASK (task), FALSE);
+
+  return g_task_propagate_boolean (task, error);
+}
+
+/**
+ * ide_persistent_map_lookup_value:
+ * @self: An #IdePersistentMap instance.
+ * @key: key to lookup value
+ *
+ * Returns: (transfer full) : value associalted with @key.
+ */
+GVariant *
+ide_persistent_map_lookup_value (IdePersistentMap *self,
+                                 const gchar      *key)
+{
+  g_autoptr(GVariant) value = NULL;
+  gint64 l;
+  gint64 r;
+
+  g_return_val_if_fail (IDE_IS_PERSISTENT_MAP (self), NULL);
+  g_return_val_if_fail (key != NULL, NULL);
+
+  l = 0;
+  r = (gint64)self->n_kvpairs - 1; /* unsigned long to signed long */
+
+  while (l <= r)
+    {
+      gint64 m;
+      gint cmp;
+
+      m = (l + r)/2;
+
+      cmp = g_strcmp0 (key, &self->keys [self->kvpairs [m].key]);
+
+      if (cmp < 0)
+
+        r = m - 1;
+      else if (cmp > 0)
+        l = m + 1;
+      else
+        value = g_variant_get_child_value (self->values, self->kvpairs [m].value);
+    }
+
+  if (value != NULL && self->byte_order != G_BYTE_ORDER)
+    {
+      g_autoptr(GVariant) new_value = NULL;
+      GVariant *t;
+
+      new_value = g_variant_byteswap (value);
+      /* swap new_value with value */
+      t = value;
+      value = new_value;
+      new_value = t;
+    }
+
+  return g_steal_pointer (&value);
+}
+
+gint64
+ide_persistent_map_builder_get_metadata_int64 (IdePersistentMap *self,
+                                               const gchar      *key)
+{
+  guint64 value;
+
+  g_return_val_if_fail (IDE_IS_PERSISTENT_MAP (self), 0);
+  g_return_val_if_fail (key != NULL, 0);
+
+  if (g_variant_dict_lookup (self->metadata, key, "x", &value))
+    return value;
+
+  return 0;
+}
+
+static void
+ide_persistent_map_finalize (GObject *object)
+{
+  IdePersistentMap *self = (IdePersistentMap *)object;
+
+  g_clear_pointer (&self->mapped_file, g_mapped_file_unref);
+  g_clear_pointer (&self->keys_var, g_variant_unref);
+  g_clear_pointer (&self->values, g_variant_unref);
+  g_clear_pointer (&self->kvpairs_var, g_variant_unref);
+  g_clear_pointer (&self->metadata, g_variant_dict_unref);
+
+  G_OBJECT_CLASS (ide_persistent_map_parent_class)->finalize (object);
+}
+
+static void
+ide_persistent_map_init (IdePersistentMap *self)
+{
+}
+
+static void
+ide_persistent_map_class_init (IdePersistentMapClass *self)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (self);
+
+  object_class->finalize = ide_persistent_map_finalize;
+}
+
+IdePersistentMap*
+ide_persistent_map_new (void)
+{
+  return g_object_new (IDE_TYPE_PERSISTENT_MAP, NULL);
+}
diff --git a/plugins/code-index/ide-persistent-map.h b/plugins/code-index/ide-persistent-map.h
new file mode 100644
index 0000000..b2ee7f8
--- /dev/null
+++ b/plugins/code-index/ide-persistent-map.h
@@ -0,0 +1,46 @@
+/* ide-persistent-map.h
+ *
+ * Copyright (C) 2017 Anoop Chandu <anoopchandu96 gmail com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef IDE_TYPE_PERSISTENT_MAP_H
+#define IDE_TYPE_PERSISTENT_MAP_H
+
+#include <glib-object.h>
+
+#define IDE_TYPE_PERSISTENT_MAP (ide_persistent_map_get_type ())
+
+G_DECLARE_FINAL_TYPE (IdePersistentMap, ide_persistent_map, IDE, PERSISTENT_MAP, GObject)
+
+IdePersistentMap     *ide_persistent_map_new                           (void);
+gboolean              ide_persistent_map_load_file                     (IdePersistentMap    *self,
+                                                                        GFile               *file,
+                                                                        GCancellable        *cancellable,
+                                                                        GError             **error);
+void                  ide_persistent_map_load_file_async               (IdePersistentMap    *self,
+                                                                        GFile               *file,
+                                                                        GCancellable        *cancellable,
+                                                                        GAsyncReadyCallback  callback,
+                                                                        gpointer             user_data);
+gboolean              ide_persistent_map_load_file_finish              (IdePersistentMap    *self,
+                                                                        GAsyncResult        *result,
+                                                                        GError             **error);
+GVariant             *ide_persistent_map_lookup_value                  (IdePersistentMap    *self,
+                                                                        const gchar         *key);
+gint64                ide_persistent_map_builder_get_metadata_int64    (IdePersistentMap    *self,
+                                                                        const gchar         *key);
+
+#endif /* IDE_TYPE_PERSISTENT_MAP_H */


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]