summaryrefslogtreecommitdiff
path: root/src/gdbusgi.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gdbusgi.c')
-rw-r--r--src/gdbusgi.c214
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);