diff options
author | David Zeuthen <davidz@redhat.com> | 2010-06-16 15:17:17 -0400 |
---|---|---|
committer | David Zeuthen <davidz@redhat.com> | 2010-06-16 15:17:17 -0400 |
commit | 4384036f5bb77c02292c7fb6e1091bc5233a1eff (patch) | |
tree | e55a207264d69370a405465204148a2e41a14652 | |
parent | ca054efa1b317a219b2b83652c16e6017b789f30 (diff) |
Handle C arrays with length argument
-rw-r--r-- | src/gdbusgi.c | 214 | ||||
-rw-r--r-- | src/myfrobnicator.c | 18 | ||||
-rw-r--r-- | src/myfrobnicator.h | 8 | ||||
-rw-r--r-- | src/test.c | 8 |
4 files changed, 200 insertions, 48 deletions
diff --git a/src/gdbusgi.c b/src/gdbusgi.c index 138e00d..65b339e 100644 --- a/src/gdbusgi.c +++ b/src/gdbusgi.c @@ -154,7 +154,7 @@ get_gvariant_type_for_gi_type (GITypeInfo *gi_type, g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Element type `%s' in C array can't be used with zero-terminated", + "Element type `%s' in C array can't be used with zero-terminated=1", g_type_tag_to_string (element_type_tag)); goto out; } @@ -375,6 +375,61 @@ convert_gi_to_gvariant (GArgument *gi_value, /* ---------------------------------------------------------------------------------------------------- */ +static void +argument_put_number (GArgument *arg, + GITypeInfo *type, + guint64 val) +{ + g_return_if_fail (arg != NULL); + g_return_if_fail (type != NULL); + + switch (g_type_info_get_tag (type)) + { + case GI_TYPE_TAG_INT8: + arg->v_int8 = val; + break; + + case GI_TYPE_TAG_UINT8: + arg->v_uint8 = val; + break; + + case GI_TYPE_TAG_INT16: + arg->v_int16 = val; + break; + + case GI_TYPE_TAG_UINT16: + arg->v_uint16 = val; + break; + + case GI_TYPE_TAG_INT32: + arg->v_int32 = val; + break; + + case GI_TYPE_TAG_UINT32: + arg->v_uint32 = val; + break; + + case GI_TYPE_TAG_INT64: + arg->v_int64 = val; + break; + + case GI_TYPE_TAG_UINT64: + arg->v_uint64 = val; + break; + + case GI_TYPE_TAG_INT: + arg->v_int = val; + break; + + case GI_TYPE_TAG_UINT: + arg->v_uint = val; + break; + + default: + g_assert_not_reached (); + } +} + /* g_error()'s if type is not a scalar type */ static guint get_scalar_element_size (GITypeInfo *type) @@ -443,74 +498,91 @@ get_scalar_element_size (GITypeInfo *type) return ret; } +/** + * convert_gvariant_to_gi: + * @variant: A #GVariant + * @value: The #GArgument to write the converted value to. + * @type: The type of @value. + * @array_len_value: The #GArgument to write the array length to or %NULL. + * @array_len_type: The type of @array_len_value or %NULL. + * @transfer: Transfer semantics. + * + * Converts the value in @variant into the type specified by @type + * and stores the value in @value. + * + * If @type is an array and @array_len_value and @array_len_type are + * not %NULL, then the length will be written there. + */ static void convert_gvariant_to_gi (GVariant *variant, - GArgument *out_gi_value, - GITypeInfo *gi_type, - GITransfer transfer) + GArgument *value, + GITypeInfo *type, + GITransfer transfer, + GArgument *array_len_value, + GITypeInfo *array_len_type) { GITypeTag tag; const GVariantType *gvariant_type; g_return_if_fail (variant != NULL); - g_return_if_fail (out_gi_value != NULL); - g_return_if_fail (gi_type != NULL); + g_return_if_fail (value != NULL); + g_return_if_fail (type != NULL); gvariant_type = g_variant_get_type (variant); - tag = g_type_info_get_tag (gi_type); + tag = g_type_info_get_tag (type); switch (tag) { case GI_TYPE_TAG_BOOLEAN: g_assert (g_variant_type_equal (gvariant_type, G_VARIANT_TYPE_BOOLEAN)); - out_gi_value->v_boolean = g_variant_get_boolean (variant); + value->v_boolean = g_variant_get_boolean (variant); break; case GI_TYPE_TAG_INT8: g_assert (g_variant_type_equal (gvariant_type, G_VARIANT_TYPE_BYTE)); - out_gi_value->v_int8 = g_variant_get_byte (variant); + value->v_int8 = g_variant_get_byte (variant); break; case GI_TYPE_TAG_UINT8: g_assert (g_variant_type_equal (gvariant_type, G_VARIANT_TYPE_BYTE)); - out_gi_value->v_uint8 = g_variant_get_byte (variant); + value->v_uint8 = g_variant_get_byte (variant); break; case GI_TYPE_TAG_INT16: g_assert (g_variant_type_equal (gvariant_type, G_VARIANT_TYPE_INT16)); - out_gi_value->v_int16 = g_variant_get_int16 (variant); + value->v_int16 = g_variant_get_int16 (variant); break; case GI_TYPE_TAG_UINT16: g_assert (g_variant_type_equal (gvariant_type, G_VARIANT_TYPE_UINT16)); - out_gi_value->v_uint16 = g_variant_get_uint16 (variant); + value->v_uint16 = g_variant_get_uint16 (variant); break; case GI_TYPE_TAG_INT: case GI_TYPE_TAG_INT32: g_assert (g_variant_type_equal (gvariant_type, G_VARIANT_TYPE_INT32)); - out_gi_value->v_int32 = g_variant_get_int32 (variant); + value->v_int32 = g_variant_get_int32 (variant); break; case GI_TYPE_TAG_UINT: case GI_TYPE_TAG_UINT32: g_assert (g_variant_type_equal (gvariant_type, G_VARIANT_TYPE_UINT32)); - out_gi_value->v_uint32 = g_variant_get_uint32 (variant); + value->v_uint32 = g_variant_get_uint32 (variant); break; case GI_TYPE_TAG_INT64: g_assert (g_variant_type_equal (gvariant_type, G_VARIANT_TYPE_INT64)); - out_gi_value->v_int64 = g_variant_get_int64 (variant); + value->v_int64 = g_variant_get_int64 (variant); break; case GI_TYPE_TAG_UINT64: g_assert (g_variant_type_equal (gvariant_type, G_VARIANT_TYPE_UINT64)); - out_gi_value->v_uint64 = g_variant_get_uint64 (variant); + value->v_uint64 = g_variant_get_uint64 (variant); break; case GI_TYPE_TAG_DOUBLE: g_assert (g_variant_type_equal (gvariant_type, G_VARIANT_TYPE_DOUBLE)); - out_gi_value->v_double = g_variant_get_double (variant); + value->v_double = g_variant_get_double (variant); break; case GI_TYPE_TAG_UTF8: @@ -520,13 +592,13 @@ convert_gvariant_to_gi (GVariant *variant, switch (transfer) { case GI_TRANSFER_NOTHING: - out_gi_value->v_string = (gchar *) g_variant_get_string (variant, NULL); + value->v_string = (gchar *) g_variant_get_string (variant, NULL); break; case GI_TRANSFER_CONTAINER: g_assert_not_reached (); break; case GI_TRANSFER_EVERYTHING: - out_gi_value->v_string = g_variant_dup_string (variant, NULL); + value->v_string = g_variant_dup_string (variant, NULL); break; } break; @@ -541,7 +613,7 @@ convert_gvariant_to_gi (GVariant *variant, g_assert (g_variant_is_of_type (variant, G_VARIANT_TYPE_ARRAY)); - element_type = g_type_info_get_param_type (gi_type, 0); + element_type = g_type_info_get_param_type (type, 0); element_transfer = GI_TRANSFER_NOTHING; if (transfer == GI_TRANSFER_EVERYTHING) @@ -549,18 +621,18 @@ convert_gvariant_to_gi (GVariant *variant, num_elems = g_variant_n_children (variant); - switch (g_type_info_get_array_type (gi_type)) + switch (g_type_info_get_array_type (type)) { case GI_ARRAY_TYPE_C: { -#if 0 +#if 1 g_print ("fixed_size=%d array_length=%d zero_terminated=%d\n", - g_type_info_get_array_fixed_size (gi_type), - g_type_info_get_array_length (gi_type), - g_type_info_is_zero_terminated (gi_type)); + g_type_info_get_array_fixed_size (type), + g_type_info_get_array_length (type), + g_type_info_is_zero_terminated (type)); #endif - if (g_type_info_is_zero_terminated (gi_type)) + if (g_type_info_is_zero_terminated (type)) { gpointer *p; p = g_new0 (gpointer, num_elems + 1); @@ -574,10 +646,64 @@ convert_gvariant_to_gi (GVariant *variant, convert_gvariant_to_gi (item, &a, element_type, - element_transfer); + element_transfer, + NULL, + NULL); p[n] = a.v_pointer; } - out_gi_value->v_pointer = p; + value->v_pointer = p; + } + else if (g_type_info_get_array_length (type) != -1) + { + + g_assert (array_len_value != NULL && array_len_type); + argument_put_number (array_len_value, array_len_type, num_elems); + + /* We only support scalar types and strings here */ + if (g_type_info_get_tag (element_type) == GI_TYPE_TAG_UTF8) + { + gpointer *p; + p = g_new0 (gpointer, num_elems); + g_variant_iter_init (&iter, variant); + for (n = 0; n < num_elems; n++) + { + GArgument a = {0}; + GVariant *item; + item = g_variant_iter_next_value (&iter); + g_assert (item != NULL); + convert_gvariant_to_gi (item, + &a, + element_type, + element_transfer, + NULL, + NULL); + p[n] = a.v_pointer; + } + value->v_pointer = p; + } + else + { + guint element_size; + gpointer p; + + element_size = get_scalar_element_size (element_type); + p = g_new0 (guchar, element_size * num_elems); + + g_variant_iter_init (&iter, variant); + for (n = 0; n < num_elems; n++) + { + GVariant *item; + item = g_variant_iter_next_value (&iter); + g_assert (item != NULL); + convert_gvariant_to_gi (item, + (GArgument *) ((guchar *) p + n * element_size), + element_type, + element_transfer, + NULL, + NULL); + } + value->v_pointer = p; + } } else { @@ -606,10 +732,12 @@ convert_gvariant_to_gi (GVariant *variant, convert_gvariant_to_gi (item, &a, element_type, - element_transfer); + element_transfer, + NULL, + NULL); g_array_append_vals (p, &a, 1); } - out_gi_value->v_pointer = p; + value->v_pointer = p; } break; @@ -628,10 +756,12 @@ convert_gvariant_to_gi (GVariant *variant, convert_gvariant_to_gi (item, &a, element_type, - element_transfer); + element_transfer, + NULL, + NULL); g_ptr_array_add (p, a.v_pointer); } - out_gi_value->v_pointer = p; + value->v_pointer = p; } break; } @@ -759,7 +889,7 @@ arg_data_print (ArgData *data) str = g_string_new (NULL); g_string_append_printf (str, - "alp=%02d ialfp=%02d ioiao=%02d ", + "alp=%2d ialfp=%2d ioiao=%2d ", data->array_len_position, data->is_array_len_for_position, data->inout_in_arg_offset); @@ -801,7 +931,7 @@ method_data_print (MethodData *data, ArgData *a = data->in_args->pdata[n]; s = arg_data_print (a); g_string_append_printf (str, - "%*s in_arg[%02d]: %s\n", + "%*s in_arg[%2d]: %s\n", indent, "", n, s); g_free (s); } @@ -810,7 +940,7 @@ method_data_print (MethodData *data, ArgData *a = data->out_args->pdata[n]; s = arg_data_print (a); g_string_append_printf (str, - "%*s out_arg[%02d]: %s\n", + "%*s out_arg[%2d]: %s\n", indent, "", n, s); g_free (s); } @@ -854,6 +984,8 @@ prepare_args (GVariant *parameters, { ArgData *ad; GVariant *item; + GArgument *array_len_arg; + GITypeInfo *array_len_arg_type; ad = data->in_args->pdata[n]; if (ad->dbus_arg_info == NULL) @@ -862,10 +994,20 @@ prepare_args (GVariant *parameters, item = g_variant_iter_next_value (&iter); g_assert (item != NULL); + array_len_arg = NULL; + array_len_arg_type = NULL; + if (ad->array_len_position != -1) + { + array_len_arg = &in_args[ad->array_len_position]; + array_len_arg_type = ((ArgData *) data->in_args->pdata[ad->array_len_position])->type_info; + } + convert_gvariant_to_gi (item, &in_args[n], ad->type_info, - ad->transfer); + ad->transfer, + array_len_arg, + array_len_arg_type); } g_assert (g_variant_iter_next_value (&iter) == NULL); diff --git a/src/myfrobnicator.c b/src/myfrobnicator.c index 399ada5..0ed7065 100644 --- a/src/myfrobnicator.c +++ b/src/myfrobnicator.c @@ -285,7 +285,8 @@ my_frobnicator_poke_path (MyFrobnicator *frobnicator, * @garray_ai: (element-type gint): * @garray_ad: (element-type gdouble): * @gptrarray_as: (element-type utf8): - * @error: + * @carray_as_nzt_len: + * @carray_as_nzt: : (element-type utf8) (array length=carray_as_nzt_len): * * Returns: The sum of all elements. * @@ -293,21 +294,23 @@ my_frobnicator_poke_path (MyFrobnicator *frobnicator, */ gdouble my_frobnicator_test_arrays (MyFrobnicator *frobnicator, - //gint *carray_ai, - //gint carray_ai_len, + gint *carray_ai, + guint carray_ai_len, const gchar *const *carray_as, GByteArray *gbytearray_ay, GArray *garray_ai, GArray *garray_ad, - GPtrArray *gptrarray_as) + GPtrArray *gptrarray_as, + guint carray_as_nzt_len, + const gchar *const *carray_as_nzt) { gdouble ret; guint n; ret = 0.0; - //for (n = 0; n < carray_ai_len; n++) - // ret += carray_ai[n]; + for (n = 0; n < carray_ai_len; n++) + ret += carray_ai[n]; for (n = 0; carray_as[n] != NULL; n++) ret += atof (carray_as[n]); @@ -324,5 +327,8 @@ my_frobnicator_test_arrays (MyFrobnicator *frobnicator, for (n = 0; n < gptrarray_as->len; n++) ret += atof (gptrarray_as->pdata[n]); + for (n = 0; n < carray_as_nzt_len; n++) + ret += atof (carray_as_nzt[n]); + return ret; } diff --git a/src/myfrobnicator.h b/src/myfrobnicator.h index 039f853..f7bb72c 100644 --- a/src/myfrobnicator.h +++ b/src/myfrobnicator.h @@ -107,13 +107,15 @@ gchar *my_frobnicator_poke_path (MyFrobnicator *frobnicator, const gchar *object_path); gdouble my_frobnicator_test_arrays (MyFrobnicator *frobnicator, - //gint *carray_ai, - //gint carray_ai_len, + gint *carray_ai, + guint carray_ai_len, const gchar *const *carray_as, GByteArray *gbytearray_ay, GArray *garray_ai, GArray *garray_ad, - GPtrArray *gptrarray_as); + GPtrArray *gptrarray_as, + guint carray_as_nzt_len, + const gchar *const *carray_as_nzt); G_END_DECLS @@ -65,11 +65,13 @@ run_array_test (GDBusConnection *connection) "/org/My/Frobnicator", "org.MyProject.Frobnicator", "TestArrays", - g_variant_new_parsed ("(['100', '200', '300'], " + g_variant_new_parsed ("([1000, 2000, 3000], " + " ['100', '200', '300'], " " [@y 10, 20, 30], " " [1, 2, 3], " " [0.1, 0.2, 0.3], " - " ['0.01', '0.02', '0.03'])"), + " ['0.01', '0.02', '0.03'], " + " ['0.001', '0.002', '0.003'])"), G_VARIANT_TYPE ("(d)"), G_DBUS_CALL_FLAGS_NONE, -1, @@ -77,7 +79,7 @@ run_array_test (GDBusConnection *connection) &error); g_assert_no_error (error); g_variant_get (ret, "(d)", &d); - g_assert_cmpfloat (fabs (d - 666.66), <, 1e-10); + g_assert_cmpfloat (fabs (d - 6666.666), <, 1e-10); g_variant_unref (ret); } |