mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-12-03 23:31:12 +01:00
GSettings: Big Endian fixes
Backport a bunch of fixes from master, squashed together into this one commit.
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user