diff --git a/glib/garray.c b/glib/garray.c index 0db46bf5f..ee4b859fe 100644 --- a/glib/garray.c +++ b/glib/garray.c @@ -509,8 +509,14 @@ array_free (GRealArray *array, * size automatically if necessary. * * g_array_append_val() is a macro which uses a reference to the value - * parameter @v. This means that you cannot use it with literal values - * such as "27". You must use variables. + * parameter @v. + * Until version 2.76 this meant that you could not use it with literal + * values such as `27`. You had to use variables. + * + * Starting with version 2.76, if the compiler supports the `typeof` operator + * you can use it with both variables and literal values. + * However, it may be required to use the proper suffix (such as `15L` + * or `55UL`) or to explicitly cast the value to the #GArray elements type. * * Returns: the #GArray */ diff --git a/glib/garray.h b/glib/garray.h index 2300e5f58..5b9c6752a 100644 --- a/glib/garray.h +++ b/glib/garray.h @@ -32,6 +32,7 @@ #endif #include +#include G_BEGIN_DECLS @@ -63,9 +64,35 @@ struct _GPtrArray * order by moving the last element to the position of the removed. */ -#define g_array_append_val(a,v) g_array_append_vals (a, &(v), 1) -#define g_array_prepend_val(a,v) g_array_prepend_vals (a, &(v), 1) -#define g_array_insert_val(a,i,v) g_array_insert_vals (a, i, &(v), 1) +#if defined (glib_typeof) && GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_76 + #define g_array_append_val(a, v) \ + (G_GNUC_EXTENSION ({ \ + glib_typeof ((v)) gaa_val_ = (v); \ + g_array_append_vals ((a), &gaa_val_, 1); \ + })) + + #define g_array_prepend_val(a, v) \ + (G_GNUC_EXTENSION ({ \ + glib_typeof ((v)) gap_val_ = (v); \ + g_array_prepend_vals ((a), &gap_val_, 1); \ + })) + + #define g_array_insert_val(a, i, v) \ + (G_GNUC_EXTENSION ({ \ + glib_typeof ((v)) gai_val_ = (v); \ + g_array_insert_vals ((a), (i), &gai_val_, 1); \ + })) +#else /* !defined (glib_typeof) || GLIB_VERSION_MIN_REQUIRED < GLIB_VERSION_2_76 */ + #define g_array_append_val(a, v) \ + g_array_append_vals ((a), &((v)), 1) + + #define g_array_prepend_val(a, v) \ + g_array_prepend_vals ((a), &((v)), 1) + + #define g_array_insert_val(a, i, v) \ + g_array_insert_vals ((a), (i), &((v)), 1) +#endif + #define g_array_index(a,t,i) (((t*) (void *) (a)->data) [(i)]) GLIB_AVAILABLE_IN_ALL diff --git a/glib/tests/array-test.c b/glib/tests/array-test.c index cd617200a..9826d3e33 100644 --- a/glib/tests/array-test.c +++ b/glib/tests/array-test.c @@ -31,6 +31,7 @@ #include #include "glib.h" + /* Test data to be passed to any function which calls g_array_new(), providing * the parameters for that call. Most #GArray tests should be repeated for all * possible values of #ArrayTestData. */ @@ -204,8 +205,16 @@ array_append_val (gconstpointer test_data) gint *segment; garray = g_array_new (config->zero_terminated, config->clear_, sizeof (gint)); - for (i = 0; i < 10000; i++) + for (i = 0; i < 10000 - 1; i++) g_array_append_val (garray, i); + +#if defined (glib_typeof) + g_array_append_val (garray, 10000 - 1); +#else + i = 10000 - 1; + g_array_append_val (garray, i); +#endif + assert_int_array_zero_terminated (config, garray); for (i = 0; i < 10000; i++) @@ -218,6 +227,17 @@ array_append_val (gconstpointer test_data) g_assert_cmpint (segment[10000], ==, 0); g_free (segment); + + garray = g_array_new (config->zero_terminated, config->clear_, sizeof (gsize)); +#if defined (glib_typeof) + g_array_append_val (garray, (gsize) 123); +#else + i = 123; + g_array_append_val (garray, i); +#endif + + g_assert_cmpuint (g_array_index (garray, gsize, 0), ==, 123); + g_array_unref (garray); } /* Check that g_array_prepend_val() works correctly for various #GArray @@ -230,8 +250,16 @@ array_prepend_val (gconstpointer test_data) gint i; garray = g_array_new (config->zero_terminated, config->clear_, sizeof (gint)); - for (i = 0; i < 100; i++) + for (i = 0; i < 99; i++) g_array_prepend_val (garray, i); + +#if defined (glib_typeof) + g_array_prepend_val (garray, 99); +#else + i = 99; + g_array_prepend_val (garray, i); +#endif + assert_int_array_zero_terminated (config, garray); for (i = 0; i < 100; i++) @@ -302,7 +330,7 @@ array_insert_vals (gconstpointer test_data) const gint expected_vals2[] = { 0, 2, 3, 1 }; const gint expected_vals3[] = { 0, 2, 3, 1, 4 }; const gint expected_vals4[] = { 5, 0, 2, 3, 1, 4 }; - const gint expected_vals5[] = { 5, 0, 2, 3, 1, 4, 0, 0, 0, 0, 6, 7 }; + const gint expected_vals5[] = { 5, 0, 2, 55, 3, 1, 4, 0, 0, 0, 0, 6, 7 }; /* Set up an array. */ garray = g_array_new (config->zero_terminated, config->clear_, sizeof (gint)); @@ -344,6 +372,14 @@ array_insert_vals (gconstpointer test_data) assert_int_array_equal (garray, expected_vals4, G_N_ELEMENTS (expected_vals4)); assert_int_array_zero_terminated (config, garray); + /* Insert an element in the middle */ +#if defined (glib_typeof) + g_array_insert_val (garray, garray->len / 2, 55); +#else + i = 55; + g_array_insert_val (garray, garray->len / 2, i); +#endif + /* Insert some elements off the end of the array. The behaviour here depends * on whether the array clears entries. */ garray_out = g_array_insert_vals (garray, garray->len + 4, vals + 6, 2); @@ -733,7 +769,13 @@ test_array_binary_search (void) /* Testing array of size 1 */ garray = g_array_sized_new (FALSE, FALSE, sizeof (guint), 1); +#if defined (glib_typeof) + g_array_prepend_val (garray, 1u); +#else i = 1; + g_array_prepend_val (garray, i); +#endif + g_array_append_val (garray, i); g_assert_true (g_array_binary_search (garray, &i, cmpint, NULL));