Merge remote branch 'gvdb/master'

This commit is contained in:
Ryan Lortie
2010-06-10 13:35:25 -04:00
5 changed files with 150 additions and 102 deletions

View File

@@ -36,7 +36,6 @@ struct _GvdbItem
GvdbItem *parent;
GvdbItem *sibling;
GvdbItem *next;
GVariant *options;
/* one of:
* this:
@@ -60,9 +59,6 @@ gvdb_item_free (gpointer data)
if (item->value)
g_variant_unref (item->value);
if (item->options)
g_variant_unref (item->options);
if (item->table)
g_hash_table_unref (item->table);
@@ -135,15 +131,6 @@ gvdb_item_set_value (GvdbItem *item,
item->value = g_variant_ref_sink (value);
}
void
gvdb_item_set_options (GvdbItem *item,
GVariant *options)
{
g_return_if_fail (!item->options);
item->options = g_variant_ref_sink (options);
}
void
gvdb_item_set_hash_table (GvdbItem *item,
GHashTable *table)
@@ -178,7 +165,7 @@ typedef struct
gint n_buckets;
} HashTable;
HashTable *
static HashTable *
hash_table_new (gint n_buckets)
{
HashTable *table;
@@ -281,33 +268,6 @@ file_builder_add_value (FileBuilder *fb,
g_variant_unref (normal);
}
static void
file_builder_add_options (FileBuilder *fb,
GVariant *options,
struct gvdb_pointer *pointer)
{
GVariant *normal;
gpointer data;
gsize size;
if (options)
{
if (fb->byteswap)
{
options = g_variant_byteswap (options);
normal = g_variant_get_normal_form (options);
g_variant_unref (options);
}
else
normal = g_variant_get_normal_form (options);
size = g_variant_get_size (normal);
data = file_builder_allocate (fb, 8, size, pointer);
g_variant_store (normal, data);
g_variant_unref (normal);
}
}
static void
file_builder_add_string (FileBuilder *fb,
const gchar *string,
@@ -424,13 +384,12 @@ file_builder_add_hash (FileBuilder *fb,
g_assert (item->child == NULL && item->table == NULL);
file_builder_add_value (fb, item->value, &entry->value.pointer);
file_builder_add_options (fb, item->options, &entry->options);
entry->type = 'v';
}
if (item->child != NULL)
{
guint32 children = 0;
guint32 children = 0, i = 0;
guint32_le *offsets;
GvdbItem *child;
@@ -444,9 +403,9 @@ file_builder_add_hash (FileBuilder *fb,
entry->type = 'L';
for (child = item->child; child; child = child->sibling)
offsets[--children] = child->assigned_index;
offsets[i++] = child->assigned_index;
g_assert (children == 0);
g_assert (children == i);
}
if (item->table != NULL)

View File

@@ -42,9 +42,6 @@ G_GNUC_INTERNAL
void gvdb_item_set_value (GvdbItem *item,
GVariant *value);
G_GNUC_INTERNAL
void gvdb_item_set_options (GvdbItem *item,
GVariant *options);
G_GNUC_INTERNAL
void gvdb_item_set_hash_table (GvdbItem *item,
GHashTable *table);
G_GNUC_INTERNAL

View File

@@ -51,8 +51,6 @@ struct gvdb_hash_item {
struct gvdb_pointer pointer;
gchar direct[8];
} value;
struct gvdb_pointer options;
};
struct gvdb_header {

View File

@@ -241,10 +241,10 @@ gvdb_table_check_name (GvdbTable *file,
return FALSE;
}
const struct gvdb_hash_item *
static const struct gvdb_hash_item *
gvdb_table_lookup (GvdbTable *file,
const gchar *key,
gchar type)
const gchar *key,
gchar type)
{
guint32 hash_value = 5381;
guint key_length;
@@ -283,6 +283,37 @@ gvdb_table_lookup (GvdbTable *file,
return NULL;
}
static const struct gvdb_hash_item *
gvdb_table_get_item (GvdbTable *table,
guint32_le item_no)
{
guint32 item_no_native = guint32_from_le (item_no);
if G_LIKELY (item_no_native < table->n_hash_items)
return table->hash_items + item_no_native;
return NULL;
}
static gboolean
gvdb_table_list_from_item (GvdbTable *table,
const struct gvdb_hash_item *item,
const guint32_le **list,
guint *length)
{
gsize size;
*list = gvdb_table_dereference (table, &item->value.pointer, 4, &size);
if G_LIKELY (*list == NULL || size % 4)
return FALSE;
*length = size / 4;
return TRUE;
}
/**
* gvdb_table_list:
* @file: a #GvdbTable
@@ -308,21 +339,17 @@ gvdb_table_list (GvdbTable *file,
const struct gvdb_hash_item *item;
const guint32_le *list;
gchar **strv;
gsize size;
guint length;
gint i;
if ((item = gvdb_table_lookup (file, key, 'L')) == NULL)
return NULL;
list = gvdb_table_dereference (file, &item->value.pointer, 4, &size);
if G_UNLIKELY (list == NULL || size % 4)
if (!gvdb_table_list_from_item (file, item, &list, &length))
return NULL;
size /= 4;
strv = g_new (gchar *, size + 1);
for (i = 0; i < size; i++)
strv = g_new (gchar *, length + 1);
for (i = 0; i < length; i++)
{
guint32 itemno = guint32_from_le (list[i]);
@@ -368,11 +395,33 @@ gvdb_table_has_value (GvdbTable *file,
return gvdb_table_lookup (file, key, 'v') != NULL;
}
static GVariant *
gvdb_table_value_from_item (GvdbTable *table,
const struct gvdb_hash_item *item)
{
GVariant *variant, *value;
gconstpointer data;
gsize size;
data = gvdb_table_dereference (table, &item->value.pointer, 8, &size);
if G_UNLIKELY (data == NULL)
return NULL;
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));
value = g_variant_get_variant (variant);
g_variant_unref (variant);
return value;
}
/**
* gvdb_table_get_value:
* @file: a #GvdbTable
* @key: a string
* @options: a pointer to a #GVariant, or %NULL
* @returns: a #GVariant, or %NULL
*
* Looks up a value named @key in @file.
@@ -381,55 +430,19 @@ gvdb_table_has_value (GvdbTable *file,
* #GVariant instance is returned. The #GVariant does not depend on the
* continued existence of @file.
*
* If @options is non-%NULL then it will be set either to %NULL in the
* case of no options or a #GVariant containing a dictionary mapping
* strings to variants.
*
* You should call g_variant_unref() on the return result when you no
* longer require it.
**/
GVariant *
gvdb_table_get_value (GvdbTable *file,
const gchar *key,
GVariant **options)
const gchar *key)
{
const struct gvdb_hash_item *item;
GVariant *variant, *value;
gconstpointer data;
gsize size;
if ((item = gvdb_table_lookup (file, key, 'v')) == NULL)
return NULL;
data = gvdb_table_dereference (file, &item->value.pointer, 8, &size);
if G_UNLIKELY (data == NULL)
return NULL;
variant = g_variant_new_from_data (G_VARIANT_TYPE_VARIANT,
data, size, file->trusted,
(GDestroyNotify) g_mapped_file_unref,
g_mapped_file_ref (file->mapped));
value = g_variant_get_variant (variant);
g_variant_unref (variant);
if (options != NULL)
{
data = gvdb_table_dereference (file, &item->options, 8, &size);
if (data != NULL && size > 0)
{
*options = g_variant_new_from_data (G_VARIANT_TYPE ("a{sv}"),
data, size, file->trusted,
(GDestroyNotify) g_mapped_file_unref,
g_mapped_file_ref (file->mapped));
g_variant_ref_sink (*options);
}
else
*options = NULL;
}
return value;
return gvdb_table_value_from_item (file, item);
}
/**
@@ -508,3 +521,69 @@ gvdb_table_unref (GvdbTable *file)
g_slice_free (GvdbTable, file);
}
}
void
gvdb_table_walk (GvdbTable *table,
const gchar *key,
GvdbWalkOpenFunc open_func,
GvdbWalkValueFunc value_func,
GvdbWalkCloseFunc close_func,
gpointer user_data)
{
const struct gvdb_hash_item *item;
const guint32_le *pointers[64];
const guint32_le *enders[64];
gint index = 0;
item = gvdb_table_lookup (table, key, 'L');
pointers[0] = NULL;
enders[0] = NULL;
goto start_here;
while (index)
{
close_func (user_data);
index--;
while (pointers[index] < enders[index])
{
const gchar *name;
gsize name_len;
item = gvdb_table_get_item (table, *pointers[index]++);
start_here:
if (item != NULL &&
(name = gvdb_table_item_get_key (table, item, &name_len)))
{
if (item->type == 'L')
{
if (open_func (name, name_len, user_data))
{
guint length;
index++;
g_assert (index < 64);
gvdb_table_list_from_item (table, item,
&pointers[index],
&length);
enders[index] = pointers[index] + length;
}
}
else if (item->type == 'v')
{
GVariant *value;
value = gvdb_table_value_from_item (table, item);
if (value != NULL)
{
value_func (name, name_len, value, user_data);
g_variant_unref (value);
}
}
}
}
}
}

View File

@@ -43,12 +43,27 @@ GvdbTable * gvdb_table_get_table (GvdbTab
const gchar *key);
G_GNUC_INTERNAL
GVariant * gvdb_table_get_value (GvdbTable *table,
const gchar *key,
GVariant **options);
const gchar *key);
G_GNUC_INTERNAL
gboolean gvdb_table_has_value (GvdbTable *table,
const gchar *key);
typedef void (*GvdbWalkValueFunc) (const gchar *name,
gsize name_len,
GVariant *value,
gpointer user_data);
typedef gboolean (*GvdbWalkOpenFunc) (const gchar *name,
gsize name_len,
gpointer user_data);
typedef void (*GvdbWalkCloseFunc) (gpointer user_data);
void gvdb_table_walk (GvdbTable *table,
const gchar *key,
GvdbWalkOpenFunc open_func,
GvdbWalkValueFunc value_func,
GvdbWalkCloseFunc close_func,
gpointer user_data);
#endif /* __gvdb_reader_h__ */