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]));
}
Beispiel #2
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;
}