Exemplo n.º 1
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();
}
Exemplo n.º 2
0
gboolean js_to_dbus(JSContextRef ctx, const JSValueRef jsvalue,
    DBusMessageIter *iter, const char* sig, JSValueRef* exception)
{
    DBusSignatureIter s_iter;
    dbus_signature_iter_init(&s_iter, sig);

    int type;
    switch (type = dbus_signature_iter_get_current_type(&s_iter)) {
        case DBUS_TYPE_BOOLEAN:
            {
                dbus_bool_t value = JSValueToBoolean(ctx, jsvalue);
                if (!dbus_message_iter_append_basic(iter, type, (void*)&value)) {
                    g_warning("signatuer:%c error!", type);
                    return FALSE;
                }  else {
                    return TRUE;
                }
            }
        case DBUS_TYPE_DOUBLE:
            CASE_NUMBER
            {
                if (!JSValueIsNumber(ctx, jsvalue)) {
                    js_fill_exception(ctx, exception, "jsvalue is not an number!");
                    return FALSE;
                }
                double value = JSValueToNumber(ctx, jsvalue, NULL);
                if (!dbus_message_iter_append_basic(iter, type, (void*)&value)) {
                    g_warning("signatuer:%c error!", type);
                    return FALSE;
                } else {
                    return TRUE;
                }
            }
            CASE_STRING
            {
                char* value = jsvalue_to_cstr(ctx, jsvalue);
                if (value == NULL ||
                        !dbus_message_iter_append_basic(iter, type, (void*)&value)) {
                    g_free(value);
                    js_fill_exception(ctx, exception, "jsvalue is not an string or memory not enough!");
                    return FALSE;
                } else {
                    g_free(value);
                    return TRUE;
                }
            }

        case DBUS_TYPE_STRUCT:
            {
                if (!jsvalue_instanceof(ctx, jsvalue, "Array")) {
                    js_fill_exception(ctx, exception, "jsvalue should an array");
                    return FALSE;
                }

                JSPropertyNameArrayRef prop_names =
                    JSObjectCopyPropertyNames(ctx, (JSObjectRef)jsvalue);
                int p_num = JSPropertyNameArrayGetCount(prop_names);
                if (p_num == 0) {
                    JSPropertyNameArrayRelease(prop_names);
                    js_fill_exception(ctx, exception, "Struct at least have one element!");
                    return FALSE;
                }

                DBusMessageIter sub_iter;
                OPEN_CONTAINER(iter, type, NULL, &sub_iter);

                DBusSignatureIter sub_s_iter;
                dbus_signature_iter_recurse(&s_iter, &sub_s_iter);

                for (int i=0; i<p_num; i++) {
                    JSValueRef value = JSObjectGetProperty(ctx,
                            (JSObjectRef)jsvalue,
                            JSPropertyNameArrayGetNameAtIndex(prop_names, i),
                            NULL);

                    char *sig = dbus_signature_iter_get_signature(&sub_s_iter);
                    if (!js_to_dbus(ctx, value, &sub_iter, sig, exception)) {
                        js_fill_exception(ctx, exception, "Failed append struct with sig:%sTODO");
                        dbus_free(sig);
                        return FALSE;
                    }
                    dbus_free(sig);

                    if (i != p_num-1 && !dbus_signature_iter_next(&sub_s_iter)) {
                        JSPropertyNameArrayRelease(prop_names);
                        CLOSE_CONTAINER(iter, &sub_iter);
                        js_fill_exception(ctx, exception, "to many params filled to struct");
                        return FALSE;
                    }
                }

                if (dbus_signature_iter_next(&sub_s_iter)) {
                    JSPropertyNameArrayRelease(prop_names);
                    CLOSE_CONTAINER(iter, &sub_iter);
                    js_fill_exception(ctx, exception, "need more params by this struct");
                    return FALSE;
                }
                JSPropertyNameArrayRelease(prop_names);
                CLOSE_CONTAINER(iter, &sub_iter);
                return TRUE;
            }
        case DBUS_TYPE_ARRAY:
            if (dbus_signature_iter_get_element_type(&s_iter) ==
                    DBUS_TYPE_DICT_ENTRY) {

                DBusSignatureIter dict_s_iter;
                dbus_signature_iter_recurse(&s_iter, &dict_s_iter);
                char *d_sig = dbus_signature_iter_get_signature(&dict_s_iter);

                DBusMessageIter sub_iter;
                OPEN_CONTAINER(iter, type, d_sig, &sub_iter);
                dbus_free(d_sig);

                JSPropertyNameArrayRef prop_names = JSObjectCopyPropertyNames(ctx,
                        (JSObjectRef)jsvalue);
                int p_num = JSPropertyNameArrayGetCount(prop_names);

                DBusSignatureIter dict_sub_s_iter;
                dbus_signature_iter_recurse(&dict_s_iter, &dict_sub_s_iter);

                int key_type = dbus_signature_iter_get_current_type(&dict_sub_s_iter);
                dbus_signature_iter_next(&dict_sub_s_iter);
                char *val_sig = dbus_signature_iter_get_signature(&dict_sub_s_iter);


                for (int i=0; i<p_num; i++) {
                    DBusMessageIter dict_iter;
                    OPEN_CONTAINER(&sub_iter, DBUS_TYPE_DICT_ENTRY,
                            NULL, &dict_iter);

                    JSStringRef key_str = JSPropertyNameArrayGetNameAtIndex(prop_names, i);

                    //TODO: fetch key type
                    switch (key_type) {
                        CASE_STRING
                        {
                            char *value = jsstring_to_cstr(ctx, key_str);
                            dbus_message_iter_append_basic(&dict_iter, key_type, (void*)&value);
                            g_free(value);
                            break;
                        }
                        case DBUS_TYPE_DOUBLE:
                        CASE_NUMBER
                        {
                            //TODO detect illegal number format
                            JSValueRef excp;
                            double value = JSValueToNumber(ctx,
                                    JSValueMakeString(ctx, key_str), &excp);

                            if (excp != NULL) {
                                js_fill_exception(ctx, exception, "dict_entry's key must be an number to match the signature!");
                                return FALSE;
                            }

                            dbus_message_iter_append_basic(&dict_iter, key_type,
                                    (void*)&value);
                            break;
                        }
                        default:
                        {
                            js_fill_exception(ctx, exception, "DICT_ENTRY's key must basic type, and you should not see this warning in javascript runtime");
                            dbus_free(val_sig);
                            JSPropertyNameArrayRelease(prop_names);
                            CLOSE_CONTAINER(iter, &sub_iter);
                            return FALSE;
                        }
                    }



                    js_to_dbus(ctx,
                            JSObjectGetProperty(ctx, (JSObjectRef)jsvalue,
                                key_str, NULL),
                            &dict_iter, val_sig,
                            exception);

                    CLOSE_CONTAINER(&sub_iter, &dict_iter);
                }
                dbus_free(val_sig);
                JSPropertyNameArrayRelease(prop_names);

                CLOSE_CONTAINER(iter, &sub_iter);
                return TRUE;
            } else {