static GVariant * parse_json_tuple (JsonNode *node, const GVariantType *child_type, GError **error) { GVariant *result = NULL; GPtrArray *children; GVariant *value; JsonArray *array; guint length; guint i; children = g_ptr_array_new (); if (!check_type (node, JSON_NODE_ARRAY, 0, error)) goto out; array = json_node_get_array (node); length = json_array_get_length (array); for (i = 0; i < length; i++) { value = NULL; if (child_type == NULL) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, "Too many values in tuple/struct"); } else { value = parse_json (json_array_get_element (array, i), child_type, error); } if (!value) goto out; g_ptr_array_add (children, value); child_type = g_variant_type_next (child_type); } if (child_type) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, "Too few values in tuple/struct"); goto out; } result = g_variant_new_tuple ((GVariant *const *)children->pdata, children->len); children->len = 0; out: g_ptr_array_foreach (children, (GFunc)g_variant_unref, NULL); g_ptr_array_free (children, TRUE); return result; }
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 GConfValue * gconf_settings_backend_gvariant_to_gconf_value (GVariant *value) { const GVariantType *type; GConfValue *gconf_value = NULL; type = g_variant_get_type (value); if (g_variant_type_is_basic (type) && !g_variant_type_equal (type, G_VARIANT_TYPE_BASIC)) gconf_value = gconf_settings_backend_simple_gvariant_to_gconf_value (value, type); else if (g_variant_type_is_array (type)) { const GVariantType *array_type; array_type = g_variant_type_element (type); if (g_variant_type_is_basic (array_type) && !g_variant_type_equal (array_type, G_VARIANT_TYPE_BASIC)) { GConfValueType value_type; int i; GSList *list = NULL; for (i = 0; i < g_variant_n_children (value); i++) { GConfValue *l; l = gconf_settings_backend_simple_gvariant_to_gconf_value (g_variant_get_child_value (value, i), array_type); list = g_slist_prepend (list, l); } list = g_slist_reverse (list); value_type = gconf_settings_backend_simple_gvariant_type_to_gconf_value_type (array_type); gconf_value = gconf_value_new (GCONF_VALUE_LIST); gconf_value_set_list_type (gconf_value, value_type); gconf_value_set_list (gconf_value, list); g_slist_foreach (list, (GFunc) gconf_value_free, NULL); g_slist_free (list); } } else if (g_variant_type_is_tuple (type) && g_variant_type_n_items (type) == 2) { const GVariantType *first_type; const GVariantType *second_type; first_type = g_variant_type_first (type); second_type = g_variant_type_next (first_type); if (g_variant_type_is_basic (first_type) && !g_variant_type_equal (first_type, G_VARIANT_TYPE_BASIC) && g_variant_type_is_basic (second_type) && !g_variant_type_equal (second_type, G_VARIANT_TYPE_BASIC)) { GConfValue *car; GConfValue *cdr; gconf_value = gconf_value_new (GCONF_VALUE_PAIR); car = gconf_settings_backend_simple_gvariant_to_gconf_value (g_variant_get_child_value (value, 0), first_type); cdr = gconf_settings_backend_simple_gvariant_to_gconf_value (g_variant_get_child_value (value, 1), second_type); if (car) gconf_value_set_car_nocopy (gconf_value, car); if (cdr) gconf_value_set_cdr_nocopy (gconf_value, cdr); if (car == NULL || cdr == NULL) { gconf_value_free (gconf_value); gconf_value = NULL; } } } return gconf_value; }
static GVariant * gconf_settings_backend_gconf_value_to_gvariant (GConfValue *gconf_value, const GVariantType *expected_type) { switch (gconf_value->type) { case GCONF_VALUE_STRING: case GCONF_VALUE_INT: case GCONF_VALUE_FLOAT: case GCONF_VALUE_BOOL: if (!gconf_settings_backend_simple_gconf_value_type_is_compatible (gconf_value->type, expected_type)) return NULL; return gconf_settings_backend_simple_gconf_value_type_to_gvariant (gconf_value, expected_type); case GCONF_VALUE_LIST: { GConfValueType list_type; const GVariantType *array_type; GSList *list; GPtrArray *array; GVariant *result; if (!g_variant_type_is_array (expected_type)) return NULL; list_type = gconf_value_get_list_type (gconf_value); array_type = g_variant_type_element (expected_type); if (!gconf_settings_backend_simple_gconf_value_type_is_compatible (list_type, array_type)) return NULL; array = g_ptr_array_new (); for (list = gconf_value_get_list (gconf_value); list != NULL; list = list->next) { GVariant *variant; variant = gconf_settings_backend_simple_gconf_value_type_to_gvariant (list->data, array_type); g_ptr_array_add (array, variant); } result = g_variant_new_array (array_type, (GVariant **) array->pdata, array->len); g_ptr_array_free (array, TRUE); return result; } break; case GCONF_VALUE_PAIR: { GConfValue *car; GConfValue *cdr; const GVariantType *first_type; const GVariantType *second_type; GVariant *tuple[2]; GVariant *result; if (!g_variant_type_is_tuple (expected_type) || g_variant_type_n_items (expected_type) != 2) return NULL; car = gconf_value_get_car (gconf_value); cdr = gconf_value_get_cdr (gconf_value); first_type = g_variant_type_first (expected_type); second_type = g_variant_type_next (first_type); if (!gconf_settings_backend_simple_gconf_value_type_is_compatible (car->type, first_type) || !gconf_settings_backend_simple_gconf_value_type_is_compatible (cdr->type, second_type)) return NULL; tuple[0] = gconf_settings_backend_simple_gconf_value_type_to_gvariant (car, first_type); tuple[1] = gconf_settings_backend_simple_gconf_value_type_to_gvariant (cdr, second_type); result = g_variant_new_tuple (tuple, 2); return result; } break; default: return NULL; } g_assert_not_reached (); return NULL; }