Beispiel #1
0
// Simple wrapper for a common D-Bus pattern.
GVariant * g_dbus_simple_send(GDBusConnection *bus, GDBusMessage *msg, const gchar *type)
{
    GDBusMessage *reply;
    GVariant *body;
    gchar *fmt;

    if (!(reply = g_dbus_send(bus, msg, 0, -1, 0, 0, 0))) {
        g_object_unref(msg);
        return NULL;
    }

    body  = g_dbus_message_get_body(reply);
    fmt   = g_dbus_message_print(reply, 0);

    g_variant_ref(body);

    if (g_strcmp0(g_variant_type_peek_string(g_variant_get_type(body)), type) != 0) {
        g_message("body type %s does not match expected type %s, message: %s",
                  g_variant_type_peek_string(g_variant_get_type(body)),
                  type,
                  fmt);
        g_variant_unref(body);

        // return error
        body = NULL;
    }

    g_free(fmt);
    g_object_unref(reply);
    g_object_unref(msg);
    return body;
}
TYPE get_numeric_value(GVariant *variant_, const char *type_str, const char *fallback_type_str)
{
  GTYPE value = 0;

  if (!variant_)
    return static_cast<TYPE>(value);

  if (g_variant_is_of_type(variant_, G_VARIANT_TYPE(type_str)))
  {
    g_variant_get(variant_, type_str, &value);
  }
  else if (g_variant_is_of_type(variant_, G_VARIANT_TYPE(fallback_type_str)))
  {
    g_variant_get(variant_, fallback_type_str, &value);
  }
  else
  {
    auto const& variant = get_variant(variant_);
    if (variant)
      return get_numeric_value<TYPE, GTYPE>(static_cast<GVariant*>(variant), type_str, fallback_type_str);

    LOG_ERROR(logger) << "You're trying to extract a '" << type_str << "'"
                      << " from a variant which is of type '"
                      << g_variant_type_peek_string(g_variant_get_type(variant_))
                      << "'";
  }

  return static_cast<TYPE>(value);
}
std::string Variant::GetString() const
{
  const gchar *result = nullptr;

  if (!variant_)
    return "";

  if (g_variant_is_of_type(variant_, G_VARIANT_TYPE_STRING))
  {
    // g_variant_get_string doesn't duplicate the string
    result = g_variant_get_string(variant_, nullptr);
  }
  else if (g_variant_is_of_type(variant_, G_VARIANT_TYPE("(s)")))
  {
    // As we're using the '&' prefix we don't need to free the string!
    g_variant_get(variant_, "(&s)", &result);
  }
  else
  {
    auto const& variant = get_variant(variant_);
    if (variant)
      return variant.GetString();

    LOG_ERROR(logger) << "You're trying to extract a 's' from a variant which is of type '"
                      << g_variant_type_peek_string(g_variant_get_type(variant_)) << "'";
  }

  return result ? result : "";
}
/**
 * tp_variant_type_classify:
 * @type: a #GVariantType
 *
 * Classifies @type according to its top-level type.
 *
 * Returns: the #GVariantClass of @type
 * Since: 0.19.10
 **/
GVariantClass
tp_variant_type_classify (const GVariantType *type)
{
  /* Same as g_variant_classify() but for a GVariantType. This returns the first
   * letter of the dbus type and cast it to an enum where elements have the
   * ascii value of the type letters. */
  return g_variant_type_peek_string (type)[0];
}
Beispiel #5
0
static void
parse_not_supported (const GVariantType *type,
                     GError **error)
{
  g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA,
               "DBus type '%.*s' is unknown or not supported",
               (int)g_variant_type_get_string_length (type),
               g_variant_type_peek_string (type));
}
static void
typecheck_response (GVariant           **response,
                    const GVariantType  *reply_type,
                    GError             **error)
{
	if (*response && reply_type && !g_variant_is_of_type (*response, reply_type)) {
		/* This is the same error code that g_dbus_connection_call() returns if
		 * @reply_type doesn't match.
		 */
		g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
		             _("Method returned type '%s', but expected '%s'"),
		             g_variant_get_type_string (*response),
		             g_variant_type_peek_string (reply_type));
		g_clear_pointer (response, g_variant_unref);
	}
}
Variant Variant::GetVariant() const
{
  Variant value;

  if (!variant_)
    return value;

  value = get_variant(variant_);

  if (!value)
  {
    LOG_ERROR(logger) << "You're trying to extract a 'v' from a variant which is of type '"
                      << g_variant_type_peek_string(g_variant_get_type(variant_)) << "'";
  }

  return value;
}
Beispiel #8
0
GVariant* js_to_dbus(JSContextRef ctx, const JSValueRef jsvalue, const GVariantType* sig, JSValueRef *exception)
{
    if (g_variant_type_is_array(sig)) {
        GVariantBuilder builder;
        g_variant_builder_init(&builder, sig);
        JSPropertyNameArrayRef array = JSObjectCopyPropertyNames(ctx, (JSObjectRef)jsvalue);

        const GVariantType* child_sig = g_variant_type_element(sig);

        if (g_variant_type_is_dict_entry(child_sig)) {

            const GVariantType* key_sig = g_variant_type_first(child_sig);
            const GVariantType* value_sig = g_variant_type_next(key_sig);
            for (size_t i=0; i < JSPropertyNameArrayGetCount(array); i++) {
                if (filter_function_child(ctx, jsvalue, i)) continue;

                g_variant_builder_open(&builder, child_sig);
                JSValueRef key = JSValueMakeString(ctx, JSPropertyNameArrayGetNameAtIndex(array, i));
                JSValueRef value = JSObjectGetPropertyAtIndex(ctx, (JSObjectRef)jsvalue, i, NULL);
                g_variant_builder_add_value(&builder, js_to_dbus(ctx, key, key_sig, exception));
                g_variant_builder_add_value(&builder, js_to_dbus(ctx, value, value_sig, exception));
                g_variant_builder_close(&builder);
            }
            return g_variant_builder_end(&builder);

	} else {
	    GVariantBuilder builder;
	    g_variant_builder_init(&builder, sig);
	    JSPropertyNameArrayRef array = JSObjectCopyPropertyNames(ctx, (JSObjectRef)jsvalue);
	    const GVariantType* child_sig = g_variant_type_element(sig);
	    for (size_t i=0; i < JSPropertyNameArrayGetCount(array); i++) {
		if (filter_array_child(ctx, array, i)) continue;
		g_variant_builder_add_value(&builder, js_to_dbus(ctx, JSObjectGetPropertyAtIndex(ctx, (JSObjectRef)jsvalue, i, NULL), child_sig, exception));
	    }
	    JSPropertyNameArrayRelease(array);
	    return g_variant_builder_end(&builder);
	}
    } else if (g_variant_type_is_tuple(sig)) {
	    GVariantBuilder builder;
	    g_variant_builder_init(&builder, sig);
	    JSPropertyNameArrayRef array = JSObjectCopyPropertyNames(ctx, (JSObjectRef)jsvalue);
	    const GVariantType* current_sig = g_variant_type_first(sig);
            for (size_t i=0; i < JSPropertyNameArrayGetCount(array); i++) {
                if (filter_array_child(ctx, array, i)) continue;
                g_variant_builder_add_value(&builder, js_to_dbus(ctx, JSObjectGetPropertyAtIndex(ctx, (JSObjectRef)jsvalue, i, NULL), current_sig, exception));
		current_sig = g_variant_type_next(current_sig);
            }
            JSPropertyNameArrayRelease(array);
            return g_variant_builder_end(&builder);
    } else {
        switch (g_variant_type_peek_string(sig)[0]) {
            case 'y':
                return g_variant_new_byte(JSValueToNumber(ctx, jsvalue, exception));
            case 'n':
                return g_variant_new_int16(JSValueToNumber(ctx, jsvalue, exception));
            case 'q':
                return g_variant_new_uint16(JSValueToNumber(ctx, jsvalue, exception));
            case 'i':
                return g_variant_new_int32(JSValueToNumber(ctx, jsvalue, exception));
            case 'u':
                return g_variant_new_uint32(JSValueToNumber(ctx, jsvalue, exception));
            case 'x':
                return g_variant_new_int64(JSValueToNumber(ctx, jsvalue, exception));
            case 't':
                return g_variant_new_uint64(JSValueToNumber(ctx, jsvalue, exception));
            case 'd':
                return g_variant_new_double(JSValueToNumber(ctx, jsvalue, exception));
            case 'h':
                return g_variant_new_handle(JSValueToNumber(ctx, jsvalue, exception));
            case 'b':
                return g_variant_new_boolean(JSValueToBoolean(ctx, jsvalue));
            case 's':
                {
                    char* v = jsvalue_to_cstr(ctx, jsvalue);
                    GVariant* r = g_variant_new_string(v);
                    g_free(v);
                    return r;
                }
            case 'v':
                {
                    //TODO:
                    /*g_variant_new_variant()*/
                    g_assert_not_reached();
                }
        }
    }
    g_assert_not_reached();
}
static void
dbus_signal_meta_marshal (GClosure     *closure,
                          GValue       *return_value,
                          guint         n_param_values,
                          const GValue *param_values,
                          gpointer      invocation_hint,
                          gpointer      marshal_data)
{
	NMDBusSignalData *sd = marshal_data;
	const char *signal_name;
	GVariant *parameters, *param;
	GValue *closure_params;
	gsize n_params, i;

	g_return_if_fail (n_param_values == 4);

	signal_name = g_value_get_string (&param_values[2]);
	parameters = g_value_get_variant (&param_values[3]);

	if (strcmp (signal_name, sd->signal_name) != 0)
		return;

	if (sd->signature) {
		if (!g_variant_is_of_type (parameters, sd->signature)) {
			g_warning ("%p: got signal '%s' but parameters were of type '%s', not '%s'",
			           g_value_get_object (&param_values[0]),
			           signal_name, g_variant_get_type_string (parameters),
			           g_variant_type_peek_string (sd->signature));
			return;
		}

		n_params = g_variant_n_children (parameters) + 1;
	} else
		n_params = 1;

	closure_params = g_new0 (GValue, n_params);
	g_value_init (&closure_params[0], G_TYPE_OBJECT);
	g_value_copy (&param_values[0], &closure_params[0]);

	for (i = 1; i < n_params; i++) {
		param = g_variant_get_child_value (parameters, i - 1);
		if (   g_variant_is_of_type (param, G_VARIANT_TYPE ("ay"))
		    || g_variant_is_of_type (param, G_VARIANT_TYPE ("aay"))) {
			/* g_dbus_gvariant_to_gvalue() thinks 'ay' means "non-UTF-8 NUL-terminated string" */
			g_value_init (&closure_params[i], G_TYPE_VARIANT);
			g_value_set_variant (&closure_params[i], param);
		} else
			g_dbus_gvariant_to_gvalue (param, &closure_params[i]);
		g_variant_unref (param);
	}

	g_cclosure_marshal_generic (closure,
	                            NULL,
	                            n_params,
	                            closure_params,
	                            invocation_hint,
	                            NULL);

	for (i = 0; i < n_params; i++)
		g_value_unset (&closure_params[i]);
	g_free (closure_params);
}
Beispiel #10
0
static void test_compare(CVariant *cv, GVariant *gv) {
        const GVariantType *gvt;
        GVariantIter gvi[C_VARIANT_MAX_VARG];
        GVariant *gvig[C_VARIANT_MAX_VARG];
        CVariantVarg varg;
        const char *s, *type;
        uint64_t val_64;
        uint32_t val_32;
        uint16_t val_16;
        uint8_t val_8;
        double val_f;
        size_t n, nest;
        GVariant *g;
        int r, c;

        type = c_variant_peek_type(cv, &n);
        gvt = g_variant_get_type(gv);

        assert(n == g_variant_type_get_string_length(gvt));
        assert(!memcmp(type, g_variant_type_peek_string(gvt), n));

        nest = 0;
        g = gv;
        for (c = c_variant_varg_init(&varg, type, n);
             c;
             c = c_variant_varg_next(&varg)) {
                if (c == -1) {
                        r = c_variant_exit(cv, NULL);
                        assert(r >= 0);

                        assert(nest-- > 0);
                        g_variant_unref(gvig[nest]);
                        continue;
                }

                if (nest > 0)
                        g = g_variant_iter_next_value(&gvi[nest - 1]);
                else
                        g = g_variant_ref(gv);
                assert(g);

                switch (c) {
                case C_VARIANT_VARIANT:
                        c_variant_enter(cv, "v");
                        type = c_variant_peek_type(cv, &n);
                        c_variant_varg_push(&varg, type, n, -1);

                        g_variant_iter_init(&gvi[nest], g);
                        gvig[nest] = g_variant_ref(g);
                        ++nest;
                        break;
                case C_VARIANT_MAYBE:
                        c_variant_enter(cv, "m");
                        n = c_variant_peek_count(cv);
                        c_variant_varg_enter_bound(&varg, cv, n);

                        g_variant_iter_init(&gvi[nest], g);
                        gvig[nest] = g_variant_ref(g);
                        ++nest;
                        break;
                case C_VARIANT_ARRAY:
                        c_variant_enter(cv, "a");
                        n = c_variant_peek_count(cv);
                        c_variant_varg_enter_bound(&varg, cv, n);

                        g_variant_iter_init(&gvi[nest], g);
                        gvig[nest] = g_variant_ref(g);
                        ++nest;
                        break;
                case C_VARIANT_TUPLE_OPEN:
                        c_variant_enter(cv, "(");
                        c_variant_varg_enter_unbound(&varg, cv, ')');

                        g_variant_iter_init(&gvi[nest], g);
                        gvig[nest] = g_variant_ref(g);
                        ++nest;
                        break;
                case C_VARIANT_PAIR_OPEN:
                        c_variant_enter(cv, "{");
                        c_variant_varg_enter_unbound(&varg, cv, '}');

                        g_variant_iter_init(&gvi[nest], g);
                        gvig[nest] = g_variant_ref(g);
                        ++nest;
                        break;
                case C_VARIANT_INT64:
                        c_variant_read(cv, "x", &val_64);
                        assert((int64_t)val_64 == g_variant_get_int64(g));
                        break;
                case C_VARIANT_UINT64:
                        c_variant_read(cv, "t", &val_64);
                        assert((uint64_t)val_64 == g_variant_get_uint64(g));
                        break;
                case C_VARIANT_DOUBLE:
                        c_variant_read(cv, "d", &val_f);
                        assert(!(val_f > g_variant_get_double(g)) &&
                               !(val_f < g_variant_get_double(g)));
                        break;
                case C_VARIANT_INT32:
                        c_variant_read(cv, "i", &val_32);
                        assert((int32_t)val_32 == g_variant_get_int32(g));
                        break;
                case C_VARIANT_UINT32:
                        c_variant_read(cv, "u", &val_32);
                        assert((uint32_t)val_32 == g_variant_get_uint32(g));
                        break;
                case C_VARIANT_HANDLE:
                        c_variant_read(cv, "h", &val_32);
                        assert((int32_t)val_32 == g_variant_get_handle(g));
                        break;
                case C_VARIANT_INT16:
                        c_variant_read(cv, "n", &val_16);
                        assert((int16_t)val_16 == g_variant_get_int16(g));
                        break;
                case C_VARIANT_UINT16:
                        c_variant_read(cv, "q", &val_16);
                        assert((uint16_t)val_16 == g_variant_get_uint16(g));
                        break;
                case C_VARIANT_BOOL:
                        c_variant_read(cv, "b", &val_8);
                        assert((bool)val_8 == g_variant_get_boolean(g));
                        break;
                case C_VARIANT_BYTE:
                        c_variant_read(cv, "y", &val_8);
                        assert((guchar)val_8 == g_variant_get_byte(g));
                        break;
                case C_VARIANT_STRING:
                        c_variant_read(cv, "s", &s);
                        assert(!strcmp(s, g_variant_get_string(g, NULL)));
                        break;
                case C_VARIANT_PATH:
                        c_variant_read(cv, "o", &s);
                        assert(!strcmp(s, g_variant_get_string(g, NULL)));
                        break;
                case C_VARIANT_SIGNATURE:
                        c_variant_read(cv, "g", &s);
                        assert(!strcmp(s, g_variant_get_string(g, NULL)));
                        break;
                default:
                        assert(0);
                        break;
                }

                r = c_variant_return_poison(cv);
                assert(r >= 0);

                g_variant_unref(g);
        }
}
Beispiel #11
0
static GString *
g_menu_markup_print_string (GString    *string,
                            GMenuModel *model,
                            gint        indent,
                            gint        tabstop)
{
  gboolean need_nl = FALSE;
  gint i, n;

  if G_UNLIKELY (string == NULL)
    string = g_string_new (NULL);

  n = g_menu_model_get_n_items (model);

  for (i = 0; i < n; i++)
    {
      GMenuAttributeIter *attr_iter;
      GMenuLinkIter *link_iter;
      GString *contents;
      GString *attrs;

      attr_iter = g_menu_model_iterate_item_attributes (model, i);
      link_iter = g_menu_model_iterate_item_links (model, i);
      contents = g_string_new (NULL);
      attrs = g_string_new (NULL);

      while (g_menu_attribute_iter_next (attr_iter))
        {
          const char *name = g_menu_attribute_iter_get_name (attr_iter);
          GVariant *value = g_menu_attribute_iter_get_value (attr_iter);

          if (g_variant_is_of_type (value, G_VARIANT_TYPE_STRING))
            {
              gchar *str;
              str = g_markup_printf_escaped (" %s='%s'", name, g_variant_get_string (value, NULL));
              g_string_append (attrs, str);
              g_free (str);
            }

          else
            {
              gchar *printed;
              gchar *str;
              const gchar *type;

              printed = g_variant_print (value, TRUE);
              type = g_variant_type_peek_string (g_variant_get_type (value));
              str = g_markup_printf_escaped ("<attribute name='%s' type='%s'>%s</attribute>\n", name, type, printed);
              indent_string (contents, indent + tabstop);
              g_string_append (contents, str);
              g_free (printed);
              g_free (str);
            }

          g_variant_unref (value);
        }
      g_object_unref (attr_iter);

      while (g_menu_link_iter_next (link_iter))
        {
          const gchar *name = g_menu_link_iter_get_name (link_iter);
          GMenuModel *menu = g_menu_link_iter_get_value (link_iter);
          gchar *str;

          if (contents->str[0])
            g_string_append_c (contents, '\n');

          str = g_markup_printf_escaped ("<link name='%s'>\n", name);
          indent_string (contents, indent + tabstop);
          g_string_append (contents, str);
          g_free (str);

          g_menu_markup_print_string (contents, menu, indent + 2 * tabstop, tabstop);

          indent_string (contents, indent + tabstop);
          g_string_append (contents, "</link>\n");
          g_object_unref (menu);
        }
      g_object_unref (link_iter);

      if (contents->str[0])
        {
          indent_string (string, indent);
          g_string_append_printf (string, "<item%s>\n", attrs->str);
          g_string_append (string, contents->str);
          indent_string (string, indent);
          g_string_append (string, "</item>\n");
          need_nl = TRUE;
        }

      else
        {
          if (need_nl)
            g_string_append_c (string, '\n');

          indent_string (string, indent);
          g_string_append_printf (string, "<item%s/>\n", attrs->str);
          need_nl = FALSE;
        }

      g_string_free (contents, TRUE);
      g_string_free (attrs, TRUE);
    }

  return string;
}
Beispiel #12
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;
}
Beispiel #13
0
/**
 * 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_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;
    }
}
Beispiel #14
0
static GVariant *
parse_json (JsonNode *node,
            const GVariantType *type,
            GError **error)
{
  const GVariantType *element_type;
  const gchar *str;

  if (!g_variant_type_is_definite (type))
    {
      g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA,
                   "Indefinite type '%.*s' is not supported",
                   (int)g_variant_type_get_string_length (type),
                   g_variant_type_peek_string (type));
      return NULL;
    }

  if (g_variant_type_is_basic (type))
    {
      if (g_variant_type_equal (type, G_VARIANT_TYPE_BOOLEAN))
        {
          if (check_type (node, JSON_NODE_VALUE, G_TYPE_BOOLEAN, error))
            return g_variant_new_boolean (json_node_get_boolean (node));
        }
      else if (g_variant_type_equal (type, G_VARIANT_TYPE_BYTE))
        {
          if (check_type (node, JSON_NODE_VALUE, G_TYPE_INT64, error))
            return g_variant_new_byte (json_node_get_int (node));
        }
      else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT16))
        {
          if (check_type (node, JSON_NODE_VALUE, G_TYPE_INT64, error))
            return g_variant_new_int16 (json_node_get_int (node));
        }
      else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT16))
        {
          if (check_type (node, JSON_NODE_VALUE, G_TYPE_INT64, error))
            return g_variant_new_uint16 (json_node_get_int (node));
        }
      else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT32))
        {
          if (check_type (node, JSON_NODE_VALUE, G_TYPE_INT64, error))
            return g_variant_new_int32 (json_node_get_int (node));
        }
      else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT32))
        {
          if (check_type (node, JSON_NODE_VALUE, G_TYPE_INT64, error))
            return g_variant_new_uint32 (json_node_get_int (node));
        }
      else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT64))
        {
          if (check_type (node, JSON_NODE_VALUE, G_TYPE_INT64, error))
            return g_variant_new_int64 (json_node_get_int (node));
        }
      else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT64))
        {
          if (check_type (node, JSON_NODE_VALUE, G_TYPE_INT64, error))
            return g_variant_new_uint64 (json_node_get_int (node));
        }
      else if (g_variant_type_equal (type, G_VARIANT_TYPE_DOUBLE))
        {
          if (check_type (node, JSON_NODE_VALUE, G_TYPE_INT64, NULL))
            return g_variant_new_double (json_node_get_int (node));
          else if (check_type (node, JSON_NODE_VALUE, G_TYPE_DOUBLE, error))
            return g_variant_new_double (json_node_get_double (node));
        }
      else if (g_variant_type_equal (type, G_VARIANT_TYPE_STRING))
        {
          if (check_type (node, JSON_NODE_VALUE, G_TYPE_STRING, error))
            return g_variant_new_string (json_node_get_string (node));
        }
      else if (g_variant_type_equal (type, G_VARIANT_TYPE_OBJECT_PATH))
        {
          if (check_type (node, JSON_NODE_VALUE, G_TYPE_STRING, error))
            {
              str = json_node_get_string (node);
              if (g_variant_is_object_path (str))
                return g_variant_new_object_path (str);
              else
                {
                  g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA,
                               "Invalid object path '%s'", str);
                  return NULL;
                }
            }
        }
      else if (g_variant_type_equal (type, G_VARIANT_TYPE_SIGNATURE))
        {
          if (check_type (node, JSON_NODE_VALUE, G_TYPE_STRING, error))
            {
              str = json_node_get_string (node);
              if (g_variant_is_signature (str))
                return g_variant_new_signature (str);
              else
                {
                  g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA,
                               "Invalid signature '%s'", str);
                  return NULL;
                }
            }
        }
      else
        {
          parse_not_supported (type, error);
        }
    }
  else if (g_variant_type_is_variant (type))
    {
      return parse_json_variant (node, error);
    }
  else if (g_variant_type_is_array (type))
    {
      element_type = g_variant_type_element (type);
      if (g_variant_type_is_dict_entry (element_type))
        return parse_json_dictionary (node, element_type, error);
      else
        return parse_json_array (node, element_type, error);
    }
  else if (g_variant_type_is_tuple (type))
    {
      return parse_json_tuple (node, g_variant_type_first (type), error);
    }
  else
    {
      parse_not_supported (type, error);
    }

  return NULL;
}