summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Zeuthen <davidz@redhat.com>2010-06-16 15:17:17 -0400
committerDavid Zeuthen <davidz@redhat.com>2010-06-16 15:17:17 -0400
commit4384036f5bb77c02292c7fb6e1091bc5233a1eff (patch)
treee55a207264d69370a405465204148a2e41a14652
parentca054efa1b317a219b2b83652c16e6017b789f30 (diff)
Handle C arrays with length argument
-rw-r--r--src/gdbusgi.c214
-rw-r--r--src/myfrobnicator.c18
-rw-r--r--src/myfrobnicator.h8
-rw-r--r--src/test.c8
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
diff --git a/src/test.c b/src/test.c
index b17434c..3ac77e9 100644
--- a/src/test.c
+++ b/src/test.c
@@ -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);
}