summaryrefslogtreecommitdiff
path: root/gvdb
diff options
context:
space:
mode:
Diffstat (limited to 'gvdb')
-rw-r--r--gvdb/gvdb-reader.c105
-rw-r--r--gvdb/gvdb-reader.h8
2 files changed, 96 insertions, 17 deletions
diff --git a/gvdb/gvdb-reader.c b/gvdb/gvdb-reader.c
index 4749ebf..b675a16 100644
--- a/gvdb/gvdb-reader.c
+++ b/gvdb/gvdb-reader.c
@@ -340,12 +340,11 @@ gvdb_table_check_name (GvdbTable *file,
}
static const struct gvdb_hash_item *
-gvdb_table_lookup (GvdbTable *file,
- const gchar *key,
- gchar type)
+gvdb_table_lookup_with_hash_internal (GvdbTable *file,
+ const gchar *key,
+ guint key_length,
+ guint32 hash_value)
{
- guint32 hash_value = 5381;
- guint key_length;
guint32 bucket;
guint32 lastno;
guint32 itemno;
@@ -353,9 +352,6 @@ gvdb_table_lookup (GvdbTable *file,
if G_UNLIKELY (file->n_buckets == 0 || file->n_hash_items == 0)
return NULL;
- for (key_length = 0; key[key_length]; key_length++)
- hash_value = (hash_value * 33) + ((signed char *) key)[key_length];
-
if (!gvdb_table_bloom_filter (file, hash_value))
return NULL;
@@ -372,8 +368,7 @@ gvdb_table_lookup (GvdbTable *file,
if (hash_value == guint32_from_le (item->hash_value))
if G_LIKELY (gvdb_table_check_name (file, item, key, key_length))
- if G_LIKELY (item->type == type)
- return item;
+ return item;
itemno++;
}
@@ -381,6 +376,48 @@ gvdb_table_lookup (GvdbTable *file,
return NULL;
}
+static const struct gvdb_hash_item *
+gvdb_table_lookup_path_internal (GvdbTable *file,
+ GvdbPath *path)
+{
+ guint32 hash_value = path->hashes[path->components - 1];
+ guint length = path->lengths[path->components - 1];
+
+ return gvdb_table_lookup_with_hash_internal (file, path->string, length, hash_value);
+}
+
+static const struct gvdb_hash_item *
+gvdb_table_lookup_best_internal (GvdbTable *file,
+ GvdbPath *path)
+{
+ const struct gvdb_hash_item *result = NULL;
+ guint i;
+
+ for (i = path->components - 1; i != -1u; i--)
+ {
+ guint32 hash_value = path->hashes[i];
+ guint length = path->lengths[i];
+
+ result = gvdb_table_lookup_with_hash_internal (file, path->string, length, hash_value);
+
+ if (result)
+ break;
+ }
+
+ return result;
+}
+
+static const struct gvdb_hash_item *
+gvdb_table_lookup (GvdbTable *file,
+ const gchar *key)
+{
+ GvdbPath path;
+
+ gvdb_path_init (&path, key, '\0'); /* never needs to be cleared */
+
+ return gvdb_table_lookup_path_internal (file, &path);
+}
+
static gboolean
gvdb_table_list_from_item (GvdbTable *table,
const struct gvdb_hash_item *item,
@@ -577,7 +614,10 @@ gvdb_table_list (GvdbTable *file,
guint length;
guint i;
- if ((item = gvdb_table_lookup (file, key, 'L')) == NULL)
+ if ((item = gvdb_table_lookup (file, key)) == NULL)
+ return NULL;
+
+ if (item->type != 'L')
return NULL;
if (!gvdb_table_list_from_item (file, item, &list, &length))
@@ -630,9 +670,9 @@ gvdb_table_has_value (GvdbTable *file,
static const struct gvdb_hash_item *item;
gsize size;
- item = gvdb_table_lookup (file, key, 'v');
+ item = gvdb_table_lookup (file, key);
- if (item == NULL)
+ if (item == NULL || item->type != 'v')
return FALSE;
return gvdb_table_dereference (file, &item->value.pointer, 8, &size) != NULL;
@@ -647,6 +687,9 @@ gvdb_table_value_from_item (GvdbTable *table,
GBytes *bytes;
gsize size;
+ if (item->type != 'v')
+ return NULL;
+
data = gvdb_table_dereference (table, &item->value.pointer, 8, &size);
if G_UNLIKELY (data == NULL)
@@ -683,7 +726,7 @@ gvdb_table_get_value (GvdbTable *file,
const struct gvdb_hash_item *item;
GVariant *value;
- if ((item = gvdb_table_lookup (file, key, 'v')) == NULL)
+ if ((item = gvdb_table_lookup (file, key)) == NULL)
return NULL;
value = gvdb_table_value_from_item (file, item);
@@ -717,7 +760,35 @@ gvdb_table_get_raw_value (GvdbTable *table,
{
const struct gvdb_hash_item *item;
- if ((item = gvdb_table_lookup (table, key, 'v')) == NULL)
+ if ((item = gvdb_table_lookup (table, key)) == NULL)
+ return NULL;
+
+ return gvdb_table_value_from_item (table, item);
+}
+
+GVariant *
+gvdb_table_get_value_for_path (GvdbTable *table,
+ GvdbPath *path)
+{
+ const struct gvdb_hash_item *item = item;
+
+ item = gvdb_table_lookup_path_internal (table, path);
+
+ if (item == NULL)
+ return NULL;
+
+ return gvdb_table_value_from_item (table, item);
+}
+
+GVariant *
+gvdb_table_get_best_value_for_path (GvdbTable *table,
+ GvdbPath *path)
+{
+ const struct gvdb_hash_item *item = item;
+
+ item = gvdb_table_lookup_best_internal (table, path);
+
+ if (item == NULL)
return NULL;
return gvdb_table_value_from_item (table, item);
@@ -749,9 +820,9 @@ gvdb_table_get_table (GvdbTable *file,
const struct gvdb_hash_item *item;
GvdbTable *new;
- item = gvdb_table_lookup (file, key, 'H');
+ item = gvdb_table_lookup (file, key);
- if (item == NULL)
+ if (item == NULL || item->type != 'H')
return NULL;
new = g_slice_new0 (GvdbTable);
diff --git a/gvdb/gvdb-reader.h b/gvdb/gvdb-reader.h
index 1e5f270..e567a5b 100644
--- a/gvdb/gvdb-reader.h
+++ b/gvdb/gvdb-reader.h
@@ -76,6 +76,14 @@ gboolean gvdb_table_has_value (GvdbTab
G_GNUC_INTERNAL
gboolean gvdb_table_is_valid (GvdbTable *table);
+G_GNUC_INTERNAL
+GVariant * gvdb_table_get_value_for_path (GvdbTable *table,
+ GvdbPath *path);
+
+G_GNUC_INTERNAL
+GVariant * gvdb_table_get_best_value_for_path (GvdbTable *table,
+ GvdbPath *path);
+
G_END_DECLS
#endif /* __gvdb_reader_h__ */