static GVariant * gconf_settings_backend_simple_gconf_value_type_to_gvariant (GConfValue *gconf_value, const GVariantType *expected_type) { /* Note: it's guaranteed that the types are compatible */ GVariant *variant = NULL; if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_BOOLEAN)) variant = g_variant_new_boolean (gconf_value_get_bool (gconf_value)); else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_BYTE)) { int value = gconf_value_get_int (gconf_value); if (value < 0 || value > 255) return NULL; variant = g_variant_new_byte (value); } else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_INT16)) { int value = gconf_value_get_int (gconf_value); if (value < G_MINSHORT || value > G_MAXSHORT) return NULL; variant = g_variant_new_int16 (value); } else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_UINT16)) { int value = gconf_value_get_int (gconf_value); if (value < 0 || value > G_MAXUSHORT) return NULL; variant = g_variant_new_uint16 (value); } else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_INT32)) variant = g_variant_new_int32 (gconf_value_get_int (gconf_value)); else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_UINT32)) { int value = gconf_value_get_int (gconf_value); if (value < 0) return NULL; variant = g_variant_new_uint32 (value); } else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_INT64)) variant = g_variant_new_int64 ((gint64) gconf_value_get_int (gconf_value)); else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_UINT64)) { int value = gconf_value_get_int (gconf_value); if (value < 0) return NULL; variant = g_variant_new_uint64 (value); } else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_HANDLE)) { int value = gconf_value_get_int (gconf_value); if (value < 0) return NULL; variant = g_variant_new_handle (value); } else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_DOUBLE)) variant = g_variant_new_double (gconf_value_get_float (gconf_value)); else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_STRING)) variant = g_variant_new_string (gconf_value_get_string (gconf_value)); else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_OBJECT_PATH)) variant = g_variant_new_object_path (gconf_value_get_string (gconf_value)); else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_SIGNATURE)) variant = g_variant_new_signature (gconf_value_get_string (gconf_value)); return variant; }
GVariant * g_settings_set_mapping (const GValue *value, const GVariantType *expected_type, gpointer user_data) { gchar *type_string; if (G_VALUE_HOLDS_BOOLEAN (value)) { if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_BOOLEAN)) return g_variant_new_boolean (g_value_get_boolean (value)); } else if (G_VALUE_HOLDS_CHAR (value) || G_VALUE_HOLDS_UCHAR (value)) { if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_BYTE)) { if (G_VALUE_HOLDS_CHAR (value)) return g_variant_new_byte (g_value_get_char (value)); else return g_variant_new_byte (g_value_get_uchar (value)); } } else if (G_VALUE_HOLDS_INT (value) || G_VALUE_HOLDS_INT64 (value)) return g_settings_set_mapping_int (value, expected_type); else if (G_VALUE_HOLDS_DOUBLE (value)) return g_settings_set_mapping_float (value, expected_type); else if (G_VALUE_HOLDS_UINT (value) || G_VALUE_HOLDS_UINT64 (value)) return g_settings_set_mapping_unsigned_int (value, expected_type); else if (G_VALUE_HOLDS_STRING (value)) { if (g_value_get_string (value) == NULL) return NULL; else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_STRING)) return g_variant_new_string (g_value_get_string (value)); else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_BYTESTRING)) return g_variant_new_bytestring (g_value_get_string (value)); else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_OBJECT_PATH)) return g_variant_new_object_path (g_value_get_string (value)); else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_SIGNATURE)) return g_variant_new_signature (g_value_get_string (value)); } else if (G_VALUE_HOLDS (value, G_TYPE_STRV)) { if (g_value_get_boxed (value) == NULL) return NULL; return g_variant_new_strv ((const gchar **) g_value_get_boxed (value), -1); } else if (G_VALUE_HOLDS_ENUM (value)) { GEnumValue *enumval; GEnumClass *eclass; /* GParamSpecEnum holds a ref on the class so we just peek... */ eclass = g_type_class_peek (G_VALUE_TYPE (value)); enumval = g_enum_get_value (eclass, g_value_get_enum (value)); if (enumval) return g_variant_new_string (enumval->value_nick); else return NULL; } else if (G_VALUE_HOLDS_FLAGS (value)) { GVariantBuilder builder; GFlagsValue *flagsval; GFlagsClass *fclass; guint flags; fclass = g_type_class_peek (G_VALUE_TYPE (value)); flags = g_value_get_flags (value); g_variant_builder_init (&builder, G_VARIANT_TYPE ("as")); while (flags) { flagsval = g_flags_get_first_value (fclass, flags); if (flagsval == NULL) { g_variant_builder_clear (&builder); return NULL; } g_variant_builder_add (&builder, "s", flagsval->value_nick); flags &= ~flagsval->value; } return g_variant_builder_end (&builder); } type_string = g_variant_type_dup_string (expected_type); g_critical ("No GSettings bind handler for type \"%s\".", type_string); g_free (type_string); return NULL; }
/** * 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; }
static GVariant * dconf_dbus_to_gv (DBusMessageIter *iter, GError **error) { gint arg_type; arg_type = dbus_message_iter_get_arg_type (iter); switch (dbus_message_iter_get_arg_type (iter)) { case DBUS_TYPE_BOOLEAN: { dbus_bool_t value; dbus_message_iter_get_basic (iter, &value); return g_variant_new_boolean (value); } case DBUS_TYPE_BYTE: { guchar value; dbus_message_iter_get_basic (iter, &value); return g_variant_new_byte (value); } case DBUS_TYPE_INT16: { gint16 value; dbus_message_iter_get_basic (iter, &value); return g_variant_new_int16 (value); } case DBUS_TYPE_UINT16: { guint16 value; dbus_message_iter_get_basic (iter, &value); return g_variant_new_uint16 (value); } case DBUS_TYPE_INT32: { gint32 value; dbus_message_iter_get_basic (iter, &value); return g_variant_new_int32 (value); } case DBUS_TYPE_UINT32: { guint32 value; dbus_message_iter_get_basic (iter, &value); return g_variant_new_uint32 (value); } case DBUS_TYPE_INT64: { gint64 value; dbus_message_iter_get_basic (iter, &value); return g_variant_new_int64 (value); } case DBUS_TYPE_UINT64: { guint64 value; dbus_message_iter_get_basic (iter, &value); return g_variant_new_uint64 (value); } case DBUS_TYPE_DOUBLE: { gdouble value; dbus_message_iter_get_basic (iter, &value); return g_variant_new_double (value); } case DBUS_TYPE_STRING: { const gchar *value; dbus_message_iter_get_basic (iter, &value); return g_variant_new_string (value); } case DBUS_TYPE_OBJECT_PATH: { const gchar *value; dbus_message_iter_get_basic (iter, &value); return g_variant_new_object_path (value); } case DBUS_TYPE_SIGNATURE: { const gchar *value; dbus_message_iter_get_basic (iter, &value); return g_variant_new_signature (value); } case DBUS_TYPE_VARIANT: { GVariantBuilder *builder; GVariantClass class; DBusMessageIter sub; char *type; GVariant *val; dbus_message_iter_recurse (iter, &sub); class = dbus_message_iter_get_arg_type (iter); type = dbus_message_iter_get_signature (&sub); builder = g_variant_builder_new (G_VARIANT_TYPE_VARIANT); dbus_free (type); while (dbus_message_iter_get_arg_type (&sub)) { val = dconf_dbus_to_gv (&sub, error); if (val == NULL) { g_variant_builder_cancel (builder); goto fail; } g_variant_builder_add_value (builder, val); dbus_message_iter_next (&sub); } return g_variant_builder_end (builder); } case DBUS_TYPE_ARRAY: case DBUS_TYPE_STRUCT: case DBUS_TYPE_DICT_ENTRY: { GVariantBuilder *builder; GVariantClass class; DBusMessageIter sub; char *type; GVariant *val; dbus_message_iter_recurse (iter, &sub); class = dbus_message_iter_get_arg_type (iter); type = dbus_message_iter_get_signature (iter); builder = g_variant_builder_new (G_VARIANT_TYPE (type)); dbus_free (type); while (dbus_message_iter_get_arg_type (&sub)) { val = dconf_dbus_to_gv (&sub, error); if (val == NULL) { g_variant_builder_cancel (builder); goto fail; } g_variant_builder_add_value (builder, val); dbus_message_iter_next (&sub); } return g_variant_builder_end (builder); } default: g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_CONVERSION_FAILED, _("Error serializing D-Bus message to GVariant. Unsupported arg type `%c' (%d)"), arg_type, arg_type); goto fail; } g_assert_not_reached (); fail: return NULL; }
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; }