diff options
Diffstat (limited to 'src/gdbusgi.c')
-rw-r--r-- | src/gdbusgi.c | 214 |
1 files changed, 178 insertions, 36 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); |