GVariant * CAGattCharacteristicGetProperties( GattCharacteristic1 * characteristic) { /** * Create a variant containing the @c GattCharacteristic1 * properties, of the form @c a{sa{sv}}. * * @note We don't care about the "Value" property here since it is * automatically made available by BlueZ on the client * side. * * @todo Should we care about "Notifying" property here? */ /* Populate the property table, and create the variant to be embedded in the results of the org.freedesktop.Dbus.ObjectManager.GetManagedObjects() method call. */ CADBusSkeletonProperty const properties[] = { { "UUID", g_variant_new_string( gatt_characteristic1_get_uuid(characteristic)) }, { "Service", g_variant_new_object_path( gatt_characteristic1_get_service(characteristic)) }, { "Flags", g_variant_new_strv( gatt_characteristic1_get_flags(characteristic), -1) }, { "Descriptors", g_variant_new_objv( gatt_characteristic1_get_descriptors(characteristic), -1) } }; return CAMakePropertyDictionary( BLUEZ_GATT_CHARACTERISTIC_INTERFACE, properties, sizeof(properties) / sizeof(properties[0])); }
/** * 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_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; }