diff options
author | Ryan Lortie <desrt@desrt.ca> | 2012-07-05 23:15:20 -0400 |
---|---|---|
committer | Ryan Lortie <desrt@desrt.ca> | 2012-07-05 23:15:20 -0400 |
commit | e47d1137ed79f10178ef901a8a2f1232266a2745 (patch) | |
tree | 52c40d1c9ea546a7fa4041de79bec53b4a4e0d71 | |
parent | cc3221d143889375683a63ed888d984fe8aabe9a (diff) | |
parent | a9551ccf92fb046a92573fb4a5b42a4d43e2abec (diff) | |
download | dconf-e47d1137ed79f10178ef901a8a2f1232266a2745.tar.gz |
Merge remote-tracking branch 'gvdb/master' into wip/reorg
-rw-r--r-- | gvdb/gvdb-builder.c | 7 | ||||
-rw-r--r-- | gvdb/gvdb-reader.c | 152 | ||||
-rw-r--r-- | gvdb/gvdb-reader.h | 10 |
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); |