X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gio%2Fgdbusutils.c;h=1ecc57b78e844b01e20f3fe9cb4e1879fa1f49b3;hb=6fcbc26e14f77401c3f2a389873b04299012c9fc;hp=d757f0326cf30d4f5154760e851332e7904d61b6;hpb=0729260141bb585943ad1c6efa8ab7ee9058b0aa;p=platform%2Fupstream%2Fglib.git diff --git a/gio/gdbusutils.c b/gio/gdbusutils.c index d757f03..1ecc57b 100644 --- a/gio/gdbusutils.c +++ b/gio/gdbusutils.c @@ -13,9 +13,7 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General - * Public License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307, USA. + * Public License along with this library; if not, see . * * Author: David Zeuthen */ @@ -32,7 +30,7 @@ /** * SECTION:gdbusutils * @title: D-Bus Utilities - * @short_description: Various utilities related to D-Bus. + * @short_description: Various utilities related to D-Bus * @include: gio/gio.h * * Various utility routines related to D-Bus. @@ -351,3 +349,352 @@ g_dbus_is_guid (const gchar *string) } /* ---------------------------------------------------------------------------------------------------- */ + +/** + * g_dbus_gvariant_to_gvalue: + * @value: A #GVariant. + * @out_gvalue: (out): Return location pointing to a zero-filled (uninitialized) #GValue. + * + * Converts a #GVariant to a #GValue. If @value is floating, it is consumed. + * + * The rules specified in the g_dbus_gvalue_to_gvariant() function are + * used - this function is essentially its reverse form. + * + * The conversion never fails - a valid #GValue is always returned in + * @out_gvalue. + * + * Since: 2.30 + */ +void +g_dbus_gvariant_to_gvalue (GVariant *value, + GValue *out_gvalue) +{ + const GVariantType *type; + gchar **array; + + g_return_if_fail (value != NULL); + g_return_if_fail (out_gvalue != NULL); + + memset (out_gvalue, '\0', sizeof (GValue)); + + switch (g_variant_classify (value)) + { + case G_VARIANT_CLASS_BOOLEAN: + g_value_init (out_gvalue, G_TYPE_BOOLEAN); + g_value_set_boolean (out_gvalue, g_variant_get_boolean (value)); + break; + + case G_VARIANT_CLASS_BYTE: + g_value_init (out_gvalue, G_TYPE_UCHAR); + g_value_set_uchar (out_gvalue, g_variant_get_byte (value)); + break; + + case G_VARIANT_CLASS_INT16: + g_value_init (out_gvalue, G_TYPE_INT); + g_value_set_int (out_gvalue, g_variant_get_int16 (value)); + break; + + case G_VARIANT_CLASS_UINT16: + g_value_init (out_gvalue, G_TYPE_UINT); + g_value_set_uint (out_gvalue, g_variant_get_uint16 (value)); + break; + + case G_VARIANT_CLASS_INT32: + g_value_init (out_gvalue, G_TYPE_INT); + g_value_set_int (out_gvalue, g_variant_get_int32 (value)); + break; + + case G_VARIANT_CLASS_UINT32: + g_value_init (out_gvalue, G_TYPE_UINT); + g_value_set_uint (out_gvalue, g_variant_get_uint32 (value)); + break; + + case G_VARIANT_CLASS_INT64: + g_value_init (out_gvalue, G_TYPE_INT64); + g_value_set_int64 (out_gvalue, g_variant_get_int64 (value)); + break; + + case G_VARIANT_CLASS_UINT64: + g_value_init (out_gvalue, G_TYPE_UINT64); + g_value_set_uint64 (out_gvalue, g_variant_get_uint64 (value)); + break; + + case G_VARIANT_CLASS_FLOAT: + g_value_init (out_gvalue, G_TYPE_FLOAT); + g_value_set_float (out_gvalue, g_variant_get_float (value)); + break; + + case G_VARIANT_CLASS_DOUBLE: + g_value_init (out_gvalue, G_TYPE_DOUBLE); + g_value_set_double (out_gvalue, g_variant_get_double (value)); + break; + + case G_VARIANT_CLASS_STRING: + g_value_init (out_gvalue, G_TYPE_STRING); + g_value_set_string (out_gvalue, g_variant_get_string (value, NULL)); + break; + + case G_VARIANT_CLASS_OBJECT_PATH: + g_value_init (out_gvalue, G_TYPE_STRING); + g_value_set_string (out_gvalue, g_variant_get_string (value, NULL)); + break; + + case G_VARIANT_CLASS_SIGNATURE: + g_value_init (out_gvalue, G_TYPE_STRING); + g_value_set_string (out_gvalue, g_variant_get_string (value, NULL)); + break; + + case G_VARIANT_CLASS_ARRAY: + type = g_variant_get_type (value); + switch (g_variant_type_peek_string (type)[1]) + { + case G_VARIANT_CLASS_BYTE: + g_value_init (out_gvalue, G_TYPE_STRING); + g_value_set_string (out_gvalue, g_variant_get_bytestring (value)); + break; + + case G_VARIANT_CLASS_STRING: + g_value_init (out_gvalue, G_TYPE_STRV); + array = g_variant_dup_strv (value, NULL); + g_value_take_boxed (out_gvalue, array); + break; + + case G_VARIANT_CLASS_OBJECT_PATH: + g_value_init (out_gvalue, G_TYPE_STRV); + array = g_variant_dup_objv (value, NULL); + g_value_take_boxed (out_gvalue, array); + break; + + case G_VARIANT_CLASS_ARRAY: + switch (g_variant_type_peek_string (type)[2]) + { + case G_VARIANT_CLASS_BYTE: + g_value_init (out_gvalue, G_TYPE_STRV); + array = g_variant_dup_bytestring_array (value, NULL); + g_value_take_boxed (out_gvalue, array); + break; + + default: + g_value_init (out_gvalue, G_TYPE_VARIANT); + g_value_set_variant (out_gvalue, value); + break; + } + break; + + default: + g_value_init (out_gvalue, G_TYPE_VARIANT); + g_value_set_variant (out_gvalue, value); + break; + } + break; + + case G_VARIANT_CLASS_HANDLE: + case G_VARIANT_CLASS_VARIANT: + case G_VARIANT_CLASS_MAYBE: + case G_VARIANT_CLASS_TUPLE: + case G_VARIANT_CLASS_DICT_ENTRY: + g_value_init (out_gvalue, G_TYPE_VARIANT); + g_value_set_variant (out_gvalue, value); + break; + } +} + + +/** + * g_dbus_gvalue_to_gvariant: + * @gvalue: A #GValue to convert to a #GVariant + * @type: A #GVariantType + * + * Converts a #GValue to a #GVariant of the type indicated by the @type + * parameter. + * + * The conversion is using the following rules: + * + * - #G_TYPE_STRING: 's', 'o', 'g' or 'ay' + * - #G_TYPE_STRV: 'as', 'ao' or 'aay' + * - #G_TYPE_BOOLEAN: 'b' + * - #G_TYPE_UCHAR: 'y' + * - #G_TYPE_INT: 'i', 'n' + * - #G_TYPE_UINT: 'u', 'q' + * - #G_TYPE_INT64 'x' + * - #G_TYPE_UINT64: 't' + * - #G_TYPE_DOUBLE: 'd' + * - #G_TYPE_VARIANT: Any #GVariantType + * + * This can fail if e.g. @gvalue is of type #G_TYPE_STRING and @type + * is ['i'][G-VARIANT-TYPE-INT32:CAPS]. It will also fail for any #GType + * (including e.g. #G_TYPE_OBJECT and #G_TYPE_BOXED derived-types) not + * in the table above. + * + * Note that if @gvalue is of type #G_TYPE_VARIANT and its value is + * %NULL, the empty #GVariant instance (never %NULL) for @type is + * returned (e.g. 0 for scalar types, the empty string for string types, + * '/' for object path types, the empty array for any array type and so on). + * + * See the g_dbus_gvariant_to_gvalue() function for how to convert a + * #GVariant to a #GValue. + * + * Returns: A #GVariant (never floating) of #GVariantType @type holding + * the data from @gvalue or %NULL in case of failure. Free with + * g_variant_unref(). + * + * Since: 2.30 + */ +GVariant * +g_dbus_gvalue_to_gvariant (const GValue *gvalue, + const GVariantType *type) +{ + GVariant *ret; + const gchar *s; + const gchar * const *as; + const gchar *empty_strv[1] = {NULL}; + + g_return_val_if_fail (gvalue != NULL, NULL); + g_return_val_if_fail (type != NULL, NULL); + + ret = NULL; + + /* @type can easily be e.g. "s" with the GValue holding a GVariant - for example this + * can happen when using the org.gtk.GDBus.C.ForceGVariant annotation with the + * gdbus-codegen(1) tool. + */ + if (G_VALUE_TYPE (gvalue) == G_TYPE_VARIANT) + { + ret = g_value_dup_variant (gvalue); + } + else + { + switch (g_variant_type_peek_string (type)[0]) + { + case G_VARIANT_CLASS_BOOLEAN: + ret = g_variant_ref_sink (g_variant_new_boolean (g_value_get_boolean (gvalue))); + break; + + case G_VARIANT_CLASS_BYTE: + ret = g_variant_ref_sink (g_variant_new_byte (g_value_get_uchar (gvalue))); + break; + + case G_VARIANT_CLASS_INT16: + ret = g_variant_ref_sink (g_variant_new_int16 (g_value_get_int (gvalue))); + break; + + case G_VARIANT_CLASS_UINT16: + ret = g_variant_ref_sink (g_variant_new_uint16 (g_value_get_uint (gvalue))); + break; + + case G_VARIANT_CLASS_INT32: + ret = g_variant_ref_sink (g_variant_new_int32 (g_value_get_int (gvalue))); + break; + + case G_VARIANT_CLASS_UINT32: + ret = g_variant_ref_sink (g_variant_new_uint32 (g_value_get_uint (gvalue))); + break; + + case G_VARIANT_CLASS_INT64: + ret = g_variant_ref_sink (g_variant_new_int64 (g_value_get_int64 (gvalue))); + break; + + case G_VARIANT_CLASS_UINT64: + ret = g_variant_ref_sink (g_variant_new_uint64 (g_value_get_uint64 (gvalue))); + break; + + case G_VARIANT_CLASS_FLOAT: + ret = g_variant_ref_sink (g_variant_new_float (g_value_get_float (gvalue))); + break; + + case G_VARIANT_CLASS_DOUBLE: + ret = g_variant_ref_sink (g_variant_new_double (g_value_get_double (gvalue))); + break; + + case G_VARIANT_CLASS_STRING: + s = g_value_get_string (gvalue); + if (s == NULL) + s = ""; + ret = g_variant_ref_sink (g_variant_new_string (s)); + break; + + case G_VARIANT_CLASS_OBJECT_PATH: + s = g_value_get_string (gvalue); + if (s == NULL) + s = "/"; + ret = g_variant_ref_sink (g_variant_new_object_path (s)); + break; + + case G_VARIANT_CLASS_SIGNATURE: + s = g_value_get_string (gvalue); + if (s == NULL) + s = ""; + ret = g_variant_ref_sink (g_variant_new_signature (s)); + break; + + case G_VARIANT_CLASS_ARRAY: + switch (g_variant_type_peek_string (type)[1]) + { + case G_VARIANT_CLASS_BYTE: + s = g_value_get_string (gvalue); + if (s == NULL) + s = ""; + ret = g_variant_ref_sink (g_variant_new_bytestring (s)); + break; + + case G_VARIANT_CLASS_STRING: + as = g_value_get_boxed (gvalue); + if (as == NULL) + as = empty_strv; + ret = g_variant_ref_sink (g_variant_new_strv (as, -1)); + break; + + case G_VARIANT_CLASS_OBJECT_PATH: + as = g_value_get_boxed (gvalue); + if (as == NULL) + as = empty_strv; + ret = g_variant_ref_sink (g_variant_new_objv (as, -1)); + break; + + case G_VARIANT_CLASS_ARRAY: + switch (g_variant_type_peek_string (type)[2]) + { + case G_VARIANT_CLASS_BYTE: + as = g_value_get_boxed (gvalue); + if (as == NULL) + as = empty_strv; + ret = g_variant_ref_sink (g_variant_new_bytestring_array (as, -1)); + break; + + default: + ret = g_value_dup_variant (gvalue); + break; + } + break; + + default: + ret = g_value_dup_variant (gvalue); + break; + } + break; + + case G_VARIANT_CLASS_HANDLE: + case G_VARIANT_CLASS_VARIANT: + case G_VARIANT_CLASS_MAYBE: + case G_VARIANT_CLASS_TUPLE: + case G_VARIANT_CLASS_DICT_ENTRY: + ret = g_value_dup_variant (gvalue); + break; + } + } + + /* Could be that the GValue is holding a NULL GVariant - in that case, + * we return an "empty" GVariant instead of a NULL GVariant + */ + if (ret == NULL) + { + GVariant *untrusted_empty; + untrusted_empty = g_variant_new_from_data (type, NULL, 0, FALSE, NULL, NULL); + ret = g_variant_ref_sink (g_variant_get_normal_form (untrusted_empty)); + g_variant_unref (untrusted_empty); + } + + g_assert (!g_variant_is_floating (ret)); + + return ret; +}