summaryrefslogtreecommitdiff
path: root/gvdb
diff options
context:
space:
mode:
authorRyan Lortie <desrt@desrt.ca>2012-07-05 23:15:20 -0400
committerRyan Lortie <desrt@desrt.ca>2012-07-05 23:15:20 -0400
commite47d1137ed79f10178ef901a8a2f1232266a2745 (patch)
tree52c40d1c9ea546a7fa4041de79bec53b4a4e0d71 /gvdb
parentcc3221d143889375683a63ed888d984fe8aabe9a (diff)
parenta9551ccf92fb046a92573fb4a5b42a4d43e2abec (diff)
downloaddconf-e47d1137ed79f10178ef901a8a2f1232266a2745.tar.gz
Merge remote-tracking branch 'gvdb/master' into wip/reorg
Diffstat (limited to 'gvdb')
-rw-r--r--gvdb/gvdb-builder.c7
-rw-r--r--gvdb/gvdb-reader.c152
-rw-r--r--gvdb/gvdb-reader.h10
3 files changed, 128 insertions, 41 deletions
diff --git a/gvdb/gvdb-builder.c b/gvdb/gvdb-builder.c
index 91adec6..c63d117 100644
--- a/gvdb/gvdb-builder.c
+++ b/gvdb/gvdb-builder.c
@@ -340,6 +340,13 @@ file_builder_allocate_for_hash (FileBuilder *fb,
#undef chunk
memset (*bloom_filter, 0, n_bloom_words * sizeof (guint32_le));
+
+ /* NOTE - the code to actually fill in the bloom filter here is missing.
+ * Patches welcome!
+ *
+ * http://en.wikipedia.org/wiki/Bloom_filter
+ * http://0pointer.de/blog/projects/bloom.html
+ */
}
static void
diff --git a/gvdb/gvdb-reader.c b/gvdb/gvdb-reader.c
index 57816af..c04630d 100644
--- a/gvdb/gvdb-reader.c
+++ b/gvdb/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,6 +126,64 @@ gvdb_table_setup_root (GvdbTable *file,
file->n_hash_items = size / sizeof (struct gvdb_hash_item);
}
+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)
+{
+ const struct gvdb_header *header;
+ GvdbTable *file;
+
+ file = g_slice_new0 (GvdbTable);
+ file->data = data;
+ file->size = data_len;
+ file->trusted = trusted;
+ file->ref_count = 1;
+ file->ref_user_data = ref;
+ file->unref_user_data = unref;
+ file->user_data = user_data;
+
+ if (file->size < sizeof (struct gvdb_header))
+ goto invalid;
+
+ header = (gpointer) file->data;
+
+ if (header->signature[0] == GVDB_SIGNATURE0 &&
+ header->signature[1] == GVDB_SIGNATURE1 &&
+ guint32_from_le (header->version) == 0)
+ file->byteswapped = FALSE;
+
+ else if (header->signature[0] == GVDB_SWAPPED_SIGNATURE0 &&
+ header->signature[1] == GVDB_SWAPPED_SIGNATURE1 &&
+ guint32_from_le (header->version) == 0)
+ file->byteswapped = TRUE;
+
+ else
+ goto invalid;
+
+ gvdb_table_setup_root (file, &header->root);
+
+ return file;
+
+invalid:
+ if (filename)
+ g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL, "%s: invalid header", filename);
+ else
+ g_set_error_literal (error, G_FILE_ERROR, G_FILE_ERROR_INVAL, "invalid gvdb header");
+
+ g_slice_free (GvdbTable, file);
+
+ if (unref)
+ unref (user_data);
+
+ return NULL;
+}
+
/**
* gvdb_table_new:
* @filename: the path to the hash file
@@ -133,7 +194,7 @@ gvdb_table_setup_root (GvdbTable *file,
* Creates a new #GvdbTable from the contents of the file found at
* @filename.
*
- * The only time this function fails is if the file can not be opened.
+ * 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().
*
@@ -149,46 +210,52 @@ gvdb_table_new (const gchar *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->trusted = trusted;
- file->mapped = mapped;
- file->ref_count = 1;
-
- if (sizeof (struct gvdb_header) <= file->size)
- {
- const struct gvdb_header *header = (gpointer) file->data;
-
- if (header->signature[0] == GVDB_SIGNATURE0 &&
- header->signature[1] == GVDB_SIGNATURE1 &&
- guint32_from_le (header->version) == 0)
- file->byteswapped = FALSE;
-
- else if (header->signature[0] == GVDB_SWAPPED_SIGNATURE0 &&
- header->signature[1] == GVDB_SWAPPED_SIGNATURE1 &&
- guint32_from_le (header->version) == 0)
- file->byteswapped = TRUE;
-
- else
- {
- g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL,
- "%s: invalid header", filename);
- g_slice_free (GvdbTable, file);
- g_mapped_file_unref (mapped);
-
- return NULL;
- }
-
- gvdb_table_setup_root (file, &header->root);
- }
+ 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);
+}
- return file;
+/**
+ * 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
@@ -408,8 +475,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 +577,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 +619,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/gvdb-reader.h b/gvdb/gvdb-reader.h
index e6921e9..2a50c10 100644
--- a/gvdb/gvdb-reader.h
+++ b/gvdb/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);