From 5a95e19a462712010fece9c71079d5c311c77304 Mon Sep 17 00:00:00 2001 From: Stef Walter Date: Fri, 23 Sep 2011 10:57:55 +0200 Subject: [PATCH] gvariant: Add g_variant_get_fixed_array() Using g_variant_new_from_data() for creating new byte arrays is non-obvious. This patch adds a g_variant_new_fixed_array() function. https://bugzilla.gnome.org/show_bug.cgi?id=659923 --- docs/reference/glib/glib-sections.txt | 1 + glib/glib.symbols | 1 + glib/gvariant.c | 65 +++++++++++++++++++++++++++ glib/gvariant.h | 5 ++- glib/tests/gvariant.c | 16 ++++++- 5 files changed, 86 insertions(+), 2 deletions(-) diff --git a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt index b5b30b281..046e9559c 100644 --- a/docs/reference/glib/glib-sections.txt +++ b/docs/reference/glib/glib-sections.txt @@ -3060,6 +3060,7 @@ g_variant_new_maybe g_variant_new_array g_variant_new_tuple g_variant_new_dict_entry +g_variant_new_fixed_array g_variant_get_maybe diff --git a/glib/glib.symbols b/glib/glib.symbols index 6c19c221b..879da0367 100644 --- a/glib/glib.symbols +++ b/glib/glib.symbols @@ -1460,6 +1460,7 @@ g_variant_new_int64 g_variant_new_uint64 g_variant_new_handle g_variant_new_double +g_variant_new_fixed_array g_variant_new_string g_variant_new_object_path g_variant_is_object_path diff --git a/glib/gvariant.c b/glib/gvariant.c index 571d29c14..94383ae18 100644 --- a/glib/gvariant.c +++ b/glib/gvariant.c @@ -1114,6 +1114,71 @@ g_variant_get_fixed_array (GVariant *value, return NULL; } +/** + * g_variant_new_fixed_array: + * @element_type: the #GVariantType of each element + * @elements: a pointer to the fixed array of contiguous elements + * @n_elements: the number of elements + * @element_size: the size of each element + * @returns: (transfer none): a floating reference to a new array #GVariant instance + * + * Provides access to the serialised data for an array of fixed-sized + * items. + * + * @value must be an array with fixed-sized elements. Numeric types are + * fixed-size as are tuples containing only other fixed-sized types. + * + * @element_size must be the size of a single element in the array. For + * example, if calling this function for an array of 32 bit integers, + * you might say sizeof (gint32). This value isn't used + * except for the purpose of a double-check that the form of the + * seralised data matches the caller's expectation. + * + * @n_elements, which must be non-%NULL is set equal to the number of + * items in the array. + * + * Since: 2.32 + **/ +GVariant * +g_variant_new_fixed_array (const GVariantType *element_type, + gconstpointer elements, + gsize n_elements, + gsize element_size) +{ + GVariantType *array_type; + gsize array_element_size; + GVariantTypeInfo *array_info; + GVariant *value; + gpointer data; + + g_return_val_if_fail (g_variant_type_is_definite (element_type), NULL); + g_return_val_if_fail (element_size > 0, NULL); + + array_type = g_variant_type_new_array (element_type); + array_info = g_variant_type_info_get (array_type); + g_variant_type_info_query_element (array_info, NULL, &array_element_size); + if G_UNLIKELY (array_element_size != element_size) + { + if (array_element_size) + g_critical ("g_variant_new_fixed_array: array size %" G_GSIZE_FORMAT + " does not match given element_size %" G_GSIZE_FORMAT ".", + array_element_size, element_size); + else + g_critical ("g_variant_get_fixed_array: array does not have fixed size."); + return NULL; + } + + data = g_memdup (elements, n_elements * element_size); + value = g_variant_new_from_data (array_type, data, + n_elements * element_size, + FALSE, g_free, data); + + g_variant_type_free (array_type); + g_variant_type_info_unref (array_info); + + return value; +} + /* String type constructor/getters/validation {{{1 */ /** * g_variant_new_string: diff --git a/glib/gvariant.h b/glib/gvariant.h index 7f3af9886..bd24ef65c 100644 --- a/glib/gvariant.h +++ b/glib/gvariant.h @@ -91,7 +91,10 @@ GVariant * g_variant_new_objv (const g GVariant * g_variant_new_bytestring (const gchar *string); GVariant * g_variant_new_bytestring_array (const gchar * const *strv, gssize length); - +GVariant * g_variant_new_fixed_array (const GVariantType *element_type, + gconstpointer elements, + gsize num_elements, + gsize element_size); gboolean g_variant_get_boolean (GVariant *value); guchar g_variant_get_byte (GVariant *value); gint16 g_variant_get_int16 (GVariant *value); diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c index e943bb279..29ca17b1b 100644 --- a/glib/tests/gvariant.c +++ b/glib/tests/gvariant.c @@ -4078,15 +4078,29 @@ static void test_fixed_array (void) { GVariant *a; + gint32 values[5]; const gint32 *elts; gsize n_elts; gint i; + n_elts = 0; a = g_variant_new_parsed ("[1,2,3,4,5]"); elts = g_variant_get_fixed_array (a, &n_elts, sizeof (gint32)); g_assert (n_elts == 5); for (i = 0; i < 5; i++) - g_assert (elts[i] == i + 1); + g_assert_cmpint (elts[i], ==, i + 1); + g_variant_unref (a); + + n_elts = 0; + for (i = 0; i < 5; i++) + values[i] = i + 1; + a = g_variant_new_fixed_array (G_VARIANT_TYPE_INT32, values, + G_N_ELEMENTS (values), sizeof (values[0])); + g_assert_cmpstr (g_variant_get_type_string (a), ==, "ai"); + elts = g_variant_get_fixed_array (a, &n_elts, sizeof (gint32)); + g_assert (n_elts == 5); + for (i = 0; i < 5; i++) + g_assert_cmpint (elts[i], ==, i + 1); g_variant_unref (a); }