GSettings: Big Endian fixes

Backport a bunch of fixes from master, squashed together into this one
commit.
This commit is contained in:
Ryan Lortie
2010-11-12 10:57:05 -05:00
parent 1d35eb6e55
commit fe225e7e7c
8 changed files with 133 additions and 39 deletions

View File

@@ -623,12 +623,18 @@ key_state_serialise (KeyState *state)
if (state->strinfo->len)
{
GVariant *array;
guint32 *words;
gpointer data;
gsize size;
gint i;
data = state->strinfo->str;
size = state->strinfo->len;
words = data;
for (i = 0; i < size / sizeof (guint32); i++)
words[i] = GUINT32_TO_LE (words[i]);
array = g_variant_new_from_data (G_VARIANT_TYPE ("au"),
data, size, TRUE,
g_free, data);

View File

@@ -813,6 +813,18 @@ typedef struct
GVariant *default_value;
} GSettingsKeyInfo;
static inline void
endian_fixup (GVariant **value)
{
#if G_BYTE_ORDER == G_BIG_ENDIAN
GVariant *tmp;
tmp = g_variant_byteswap (*value);
g_variant_unref (*value);
*value = tmp;
#endif
}
static void
g_settings_get_key_info (GSettingsKeyInfo *info,
GSettings *settings,
@@ -827,6 +839,7 @@ g_settings_get_key_info (GSettingsKeyInfo *info,
iter = g_settings_schema_get_value (settings->priv->schema, key);
info->default_value = g_variant_iter_next_value (iter);
endian_fixup (&info->default_value);
info->type = g_variant_get_type (info->default_value);
info->settings = g_object_ref (settings);
info->key = g_intern_string (key);
@@ -859,6 +872,8 @@ g_settings_get_key_info (GSettingsKeyInfo *info,
case 'r':
g_variant_get (data, "(**)", &info->minimum, &info->maximum);
endian_fixup (&info->minimum);
endian_fixup (&info->maximum);
break;
default:

View File

@@ -181,7 +181,7 @@ g_settings_schema_get_string (GSettingsSchema *schema,
const gchar *result = NULL;
GVariant *value;
if ((value = gvdb_table_get_value (schema->priv->table, key)))
if ((value = gvdb_table_get_raw_value (schema->priv->table, key)))
{
result = g_variant_get_string (value, NULL);
g_variant_unref (value);
@@ -231,21 +231,11 @@ g_settings_schema_get_value (GSettingsSchema *schema,
GVariantIter *iter;
GVariant *value;
value = gvdb_table_get_value (schema->priv->table, key);
value = gvdb_table_get_raw_value (schema->priv->table, key);
if G_UNLIKELY (value == NULL)
g_error ("schema does not contain a key named '%s'", key);
#if G_BYTE_ORDER == G_BIG_ENDIAN
{
GVariant *tmp;
tmp = g_variant_byteswap (value);
g_variant_unref (value);
value = tmp;
}
#endif
iter = g_variant_iter_new (value);
g_variant_unref (value);

View File

@@ -34,11 +34,11 @@ struct _GvdbTable {
gboolean byteswapped;
gboolean trusted;
const guint32 *bloom_words;
const guint32_le *bloom_words;
guint32 n_bloom_words;
guint bloom_shift;
const guint32 *hash_buckets;
const guint32_le *hash_buckets;
guint32 n_buckets;
struct gvdb_hash_item *hash_items;
@@ -206,7 +206,7 @@ gvdb_table_bloom_filter (GvdbTable *file,
mask = 1 << (hash_value & 31);
mask |= 1 << ((hash_value >> file->bloom_shift) & 31);
return (file->bloom_words[word] & mask) == mask;
return (guint32_from_le (file->bloom_words[word]) & mask) == mask;
}
static gboolean
@@ -262,10 +262,10 @@ gvdb_table_lookup (GvdbTable *file,
return NULL;
bucket = hash_value % file->n_buckets;
itemno = file->hash_buckets[bucket];
itemno = guint32_from_le (file->hash_buckets[bucket]);
if (bucket == file->n_buckets - 1 ||
(lastno = file->hash_buckets[bucket + 1]) > file->n_hash_items)
(lastno = guint32_from_le(file->hash_buckets[bucket + 1])) > file->n_hash_items)
lastno = file->n_hash_items;
while G_LIKELY (itemno < lastno)
@@ -438,11 +438,46 @@ gvdb_table_get_value (GvdbTable *file,
const gchar *key)
{
const struct gvdb_hash_item *item;
GVariant *value;
if ((item = gvdb_table_lookup (file, key, 'v')) == NULL)
return NULL;
return gvdb_table_value_from_item (file, item);
value = gvdb_table_value_from_item (file, item);
if (value && file->byteswapped)
{
GVariant *tmp;
tmp = g_variant_byteswap (value);
g_variant_unref (value);
value = tmp;
}
return value;
}
/**
* gvdb_table_get_raw_value:
* @table: a #GvdbTable
* @key: a string
* @returns: a #GVariant, or %NULL
*
* Looks up a value named @key in @file.
*
* This call is equivalent to gvdb_table_get_value() except that it
* never byteswaps the value.
**/
GVariant *
gvdb_table_get_raw_value (GvdbTable *table,
const gchar *key)
{
const struct gvdb_hash_item *item;
if ((item = gvdb_table_lookup (table, key, 'v')) == NULL)
return NULL;
return gvdb_table_value_from_item (table, item);
}
/**
@@ -522,6 +557,23 @@ gvdb_table_unref (GvdbTable *file)
}
}
/**
* gvdb_table_is_valid:
* @table: a #GvdbTable
* @returns: %TRUE if @table is still valid
*
* Checks if the table is still valid.
*
* An on-disk GVDB can be marked as invalid. This happens when the file
* has been replaced. The appropriate action is typically to reopen the
* file.
**/
gboolean
gvdb_table_is_valid (GvdbTable *table)
{
return !!*table->data;
}
void
gvdb_table_walk (GvdbTable *table,
const gchar *key,
@@ -579,6 +631,15 @@ gvdb_table_walk (GvdbTable *table,
if (value != NULL)
{
if (table->byteswapped)
{
GVariant *tmp;
tmp = g_variant_byteswap (value);
g_variant_unref (value);
value = tmp;
}
value_func (name, name_len, value, user_data);
g_variant_unref (value);
}

View File

@@ -42,6 +42,9 @@ G_GNUC_INTERNAL
GvdbTable * gvdb_table_get_table (GvdbTable *table,
const gchar *key);
G_GNUC_INTERNAL
GVariant * gvdb_table_get_raw_value (GvdbTable *table,
const gchar *key);
G_GNUC_INTERNAL
GVariant * gvdb_table_get_value (GvdbTable *table,
const gchar *key);
@@ -49,6 +52,9 @@ G_GNUC_INTERNAL
gboolean gvdb_table_has_value (GvdbTable *table,
const gchar *key);
G_GNUC_INTERNAL
gboolean gvdb_table_is_valid (GvdbTable *table);
typedef void (*GvdbWalkValueFunc) (const gchar *name,
gsize name_len,
GVariant *value,

View File

@@ -193,7 +193,7 @@ strinfo_find_integer (const guint32 *strinfo,
guint i;
for (i = 0; i < length; i++)
if (strinfo[i] == value)
if (strinfo[i] == GUINT32_TO_LE (value))
{
const guchar *charinfo = (const guchar *) &strinfo[i];
@@ -226,7 +226,7 @@ strinfo_enum_from_string (const guint32 *strinfo,
if (index < 0)
return FALSE;
*result = strinfo[index];
*result = GUINT32_FROM_LE (strinfo[index]);
return TRUE;
}

View File

@@ -942,6 +942,8 @@ test_simple_binding (void)
gint i;
gint16 n;
guint16 q;
gint n2;
guint q2;
gint64 i64;
guint64 u64;
gdouble d;
@@ -991,9 +993,9 @@ test_simple_binding (void)
g_assert_cmpint (n, ==, 1234);
g_settings_set (settings, "int16", "n", 4321);
n = 1111;
g_object_get (obj, "int16", &n, NULL);
g_assert_cmpint (n, ==, 4321);
n2 = 1111;
g_object_get (obj, "int16", &n2, NULL);
g_assert_cmpint (n2, ==, 4321);
g_settings_bind (settings, "uint16", obj, "uint16", G_SETTINGS_BIND_DEFAULT);
@@ -1003,9 +1005,9 @@ test_simple_binding (void)
g_assert_cmpuint (q, ==, G_MAXUINT16);
g_settings_set (settings, "uint16", "q", (guint16) G_MAXINT16);
q = 1111;
g_object_get (obj, "uint16", &q, NULL);
g_assert_cmpuint (q, ==, (guint16) G_MAXINT16);
q2 = 1111;
g_object_get (obj, "uint16", &q2, NULL);
g_assert_cmpuint (q2, ==, (guint16) G_MAXINT16);
g_settings_bind (settings, "int", obj, "int", G_SETTINGS_BIND_DEFAULT);

View File

@@ -4566,23 +4566,37 @@ g_variant_get_normal_form (GVariant *value)
GVariant *
g_variant_byteswap (GVariant *value)
{
GVariantSerialised serialised;
GVariant *trusted;
GBuffer *buffer;
GVariantTypeInfo *type_info;
guint alignment;
GVariant *new;
trusted = g_variant_get_normal_form (value);
serialised.type_info = g_variant_get_type_info (trusted);
serialised.size = g_variant_get_size (trusted);
serialised.data = g_malloc (serialised.size);
g_variant_store (trusted, serialised.data);
g_variant_unref (trusted);
type_info = g_variant_get_type_info (value);
g_variant_serialised_byteswap (serialised);
g_variant_type_info_query (type_info, &alignment, NULL);
buffer = g_buffer_new_take_data (serialised.data, serialised.size);
new = g_variant_new_from_buffer (g_variant_get_type (value), buffer, TRUE);
g_buffer_unref (buffer);
if (alignment)
/* (potentially) contains multi-byte numeric data */
{
GVariantSerialised serialised;
GVariant *trusted;
GBuffer *buffer;
trusted = g_variant_get_normal_form (value);
serialised.type_info = g_variant_get_type_info (trusted);
serialised.size = g_variant_get_size (trusted);
serialised.data = g_malloc (serialised.size);
g_variant_store (trusted, serialised.data);
g_variant_unref (trusted);
g_variant_serialised_byteswap (serialised);
buffer = g_buffer_new_take_data (serialised.data, serialised.size);
new = g_variant_new_from_buffer (g_variant_get_type (value), buffer, TRUE);
g_buffer_unref (buffer);
}
else
/* contains no multi-byte data */
new = value;
return g_variant_ref_sink (new);
}