[gvdb] Support creating a GvdbReader from data



commit 73acf016185f323a8caa268b53284621d805fb15
Author: Alexander Larsson <alexl redhat com>
Date:   Fri Jan 13 15:59:56 2012 +0100

    Support creating a GvdbReader from data
    
    This is needed for the glib resource work.

 gvdb-reader.c |  146 +++++++++++++++++++++++++++++++++++++++++---------------
 gvdb-reader.h |   10 ++++
 2 files changed, 117 insertions(+), 39 deletions(-)
---
diff --git a/gvdb-reader.c b/gvdb-reader.c
index 5a1e26f..dfdb447 100644
--- a/gvdb-reader.c
+++ b/gvdb-reader.c
@@ -30,7 +30,10 @@ struct _GvdbTable {
   const gchar *data;
   gsize size;
 
-  GMappedFile *mapped;
+  gpointer user_data;
+  GvdbRefFunc ref_user_data;
+  GDestroyNotify unref_user_data;
+
   gboolean byteswapped;
   gboolean trusted;
 
@@ -123,43 +126,26 @@ gvdb_table_setup_root (GvdbTable                 *file,
   file->n_hash_items = size / sizeof (struct gvdb_hash_item);
 }
 
-/**
- * gvdb_table_new:
- * @filename: the path to the hash file
- * @trusted: if the contents of @filename are trusted
- * @error: %NULL, or a pointer to a %NULL #GError
- * @returns: a new #GvdbTable
- *
- * Creates a new #GvdbTable from the contents of the file found at
- * @filename.
- *
- * The only time this function fails is if the file cannot be opened.
- * In that case, the #GError that is returned will be an error from
- * g_mapped_file_new().
- *
- * An empty or otherwise corrupted file is considered to be a valid
- * #GvdbTable with no entries.
- *
- * You should call gvdb_table_unref() on the return result when you no
- * longer require it.
- **/
-GvdbTable *
-gvdb_table_new (const gchar  *filename,
-                gboolean      trusted,
-                GError      **error)
+static GvdbTable *
+new_from_data (const void    *data,
+	       gsize          data_len,
+	       gboolean       trusted,
+	       gpointer       user_data,
+	       GvdbRefFunc    ref,
+	       GDestroyNotify unref,
+	       const char    *filename,
+	       GError       **error)
 {
-  GMappedFile *mapped;
   GvdbTable *file;
 
-  if ((mapped = g_mapped_file_new (filename, FALSE, error)) == NULL)
-    return NULL;
-
   file = g_slice_new0 (GvdbTable);
-  file->data = g_mapped_file_get_contents (mapped);
-  file->size = g_mapped_file_get_length (mapped);
+  file->data = data;
+  file->size = data_len;
   file->trusted = trusted;
-  file->mapped = mapped;
   file->ref_count = 1;
+  file->ref_user_data = ref;
+  file->unref_user_data = unref;
+  file->user_data = user_data;
 
   if (sizeof (struct gvdb_header) <= file->size)
     {
@@ -177,10 +163,15 @@ gvdb_table_new (const gchar  *filename,
 
       else
         {
-          g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL,
-                       "%s: invalid header", filename);
+	  if (filename)
+	    g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL,
+			 "%s: invalid header", filename);
+	  else
+	    g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL,
+			 "invalid gvdb header");
           g_slice_free (GvdbTable, file);
-          g_mapped_file_unref (mapped);
+	  if (unref)
+	    unref (user_data);
 
           return NULL;
         }
@@ -191,6 +182,80 @@ gvdb_table_new (const gchar  *filename,
   return file;
 }
 
+/**
+ * gvdb_table_new:
+ * @filename: the path to the hash file
+ * @trusted: if the contents of @filename are trusted
+ * @error: %NULL, or a pointer to a %NULL #GError
+ * @returns: a new #GvdbTable
+ *
+ * Creates a new #GvdbTable from the contents of the file found at
+ * @filename.
+ *
+ * The only time this function fails is if the file cannot be opened.
+ * In that case, the #GError that is returned will be an error from
+ * g_mapped_file_new().
+ *
+ * An empty or otherwise corrupted file is considered to be a valid
+ * #GvdbTable with no entries.
+ *
+ * You should call gvdb_table_unref() on the return result when you no
+ * longer require it.
+ **/
+GvdbTable *
+gvdb_table_new (const gchar  *filename,
+                gboolean      trusted,
+                GError      **error)
+{
+  GMappedFile *mapped;
+
+  if ((mapped = g_mapped_file_new (filename, FALSE, error)) == NULL)
+    return NULL;
+
+  return new_from_data (g_mapped_file_get_contents (mapped),
+			g_mapped_file_get_length (mapped),
+			trusted,
+			mapped,
+			(GvdbRefFunc)g_mapped_file_ref,
+			(GDestroyNotify)g_mapped_file_unref,
+			filename,
+			error);
+}
+
+/**
+ * gvdb_table_new_from_data:
+ * @data: the data
+ * @data_len: the length of @data in bytes
+ * @trusted: if the contents of @data are trusted
+ * @user_data: User supplied data that owns @data
+ * @ref: Ref function for @user_data
+ * @unref: Unref function for @user_data
+ * @returns: a new #GvdbTable
+ *
+ * Creates a new #GvdbTable from the data in @data.
+ *
+ * An empty or otherwise corrupted data is considered to be a valid
+ * #GvdbTable with no entries.
+ *
+ * You should call gvdb_table_unref() on the return result when you no
+ * longer require it.
+ **/
+GvdbTable *
+gvdb_table_new_from_data (const void    *data,
+			  gsize          data_len,
+			  gboolean       trusted,
+			  gpointer       user_data,
+			  GvdbRefFunc    ref,
+			  GDestroyNotify unref,
+			  GError        **error)
+{
+  return new_from_data (data, data_len,
+			trusted,
+			user_data, ref, unref,
+			NULL,
+			error);
+}
+
 static gboolean
 gvdb_table_bloom_filter (GvdbTable *file,
                           guint32    hash_value)
@@ -408,8 +473,8 @@ gvdb_table_value_from_item (GvdbTable                   *table,
 
   variant = g_variant_new_from_data (G_VARIANT_TYPE_VARIANT,
                                      data, size, table->trusted,
-                                     (GDestroyNotify) g_mapped_file_unref,
-                                     g_mapped_file_ref (table->mapped));
+                                     table->unref_user_data,
+                                     table->ref_user_data ? table->ref_user_data (table->user_data) : table->user_data);
   value = g_variant_get_variant (variant);
   g_variant_unref (variant);
 
@@ -510,7 +575,9 @@ gvdb_table_get_table (GvdbTable   *file,
     return NULL;
 
   new = g_slice_new0 (GvdbTable);
-  new->mapped = g_mapped_file_ref (file->mapped);
+  new->user_data = file->ref_user_data ? file->ref_user_data (file->user_data) : file->user_data;
+  new->ref_user_data = file->ref_user_data;
+  new->unref_user_data = file->unref_user_data;
   new->byteswapped = file->byteswapped;
   new->trusted = file->trusted;
   new->data = file->data;
@@ -550,7 +617,8 @@ gvdb_table_unref (GvdbTable *file)
 {
   if (g_atomic_int_dec_and_test (&file->ref_count))
     {
-      g_mapped_file_unref (file->mapped);
+      if (file->unref_user_data)
+	file->unref_user_data (file->user_data);
       g_slice_free (GvdbTable, file);
     }
 }
diff --git a/gvdb-reader.h b/gvdb-reader.h
index e6921e9..e6878c3 100644
--- a/gvdb-reader.h
+++ b/gvdb-reader.h
@@ -26,6 +26,8 @@
 
 typedef struct _GvdbTable GvdbTable;
 
+typedef gpointer (*GvdbRefFunc) (gpointer data);
+
 G_BEGIN_DECLS
 
 G_GNUC_INTERNAL
@@ -33,6 +35,14 @@ GvdbTable *             gvdb_table_new                                  (const g
                                                                          gboolean      trusted,
                                                                          GError      **error);
 G_GNUC_INTERNAL
+GvdbTable *             gvdb_table_new_from_data                        (const void   *data,
+									 gsize         data_len,
+                                                                         gboolean      trusted,
+									 gpointer      user_data,
+									 GvdbRefFunc   ref,
+									 GDestroyNotify unref,
+									 GError      **error);
+G_GNUC_INTERNAL
 GvdbTable *             gvdb_table_ref                                  (GvdbTable    *table);
 G_GNUC_INTERNAL
 void                    gvdb_table_unref                                (GvdbTable    *table);



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