[glib/glib-2-26] GSettings: Big Endian fixes
- From: Ryan Lortie <ryanl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib/glib-2-26] GSettings: Big Endian fixes
- Date: Fri, 12 Nov 2010 15:58:02 +0000 (UTC)
commit fe225e7e7c7424fbfbdeb63c41db63c21f8f7751
Author: Ryan Lortie <desrt desrt ca>
Date: Fri Nov 12 10:57:05 2010 -0500
GSettings: Big Endian fixes
Backport a bunch of fixes from master, squashed together into this one
commit.
gio/glib-compile-schemas.c | 6 +++
gio/gsettings.c | 15 +++++++++
gio/gsettingsschema.c | 14 +-------
gio/gvdb/gvdb-reader.c | 73 ++++++++++++++++++++++++++++++++++++++++---
gio/gvdb/gvdb-reader.h | 6 +++
gio/strinfo.c | 4 +-
gio/tests/gsettings.c | 14 +++++---
glib/gvariant.c | 40 ++++++++++++++++--------
8 files changed, 133 insertions(+), 39 deletions(-)
---
diff --git a/gio/glib-compile-schemas.c b/gio/glib-compile-schemas.c
index 22681d0..f75ae08 100644
--- a/gio/glib-compile-schemas.c
+++ b/gio/glib-compile-schemas.c
@@ -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);
diff --git a/gio/gsettings.c b/gio/gsettings.c
index 2365fa9..94d1f3a 100644
--- a/gio/gsettings.c
+++ b/gio/gsettings.c
@@ -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:
diff --git a/gio/gsettingsschema.c b/gio/gsettingsschema.c
index 6d8d77a..45572a3 100644
--- a/gio/gsettingsschema.c
+++ b/gio/gsettingsschema.c
@@ -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);
diff --git a/gio/gvdb/gvdb-reader.c b/gio/gvdb/gvdb-reader.c
index 1cd3206..d25e537 100644
--- a/gio/gvdb/gvdb-reader.c
+++ b/gio/gvdb/gvdb-reader.c
@@ -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);
}
diff --git a/gio/gvdb/gvdb-reader.h b/gio/gvdb/gvdb-reader.h
index a29c16e..9f302c0 100644
--- a/gio/gvdb/gvdb-reader.h
+++ b/gio/gvdb/gvdb-reader.h
@@ -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,
diff --git a/gio/strinfo.c b/gio/strinfo.c
index 84e4acf..6836b59 100644
--- a/gio/strinfo.c
+++ b/gio/strinfo.c
@@ -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;
}
diff --git a/gio/tests/gsettings.c b/gio/tests/gsettings.c
index fdadf96..271617a 100644
--- a/gio/tests/gsettings.c
+++ b/gio/tests/gsettings.c
@@ -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);
diff --git a/glib/gvariant.c b/glib/gvariant.c
index f9eb851..e333597 100644
--- a/glib/gvariant.c
+++ b/glib/gvariant.c
@@ -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);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]