/** * @ingroup DBusSignatureInternals * Unit test for DBusSignature. * * @returns #TRUE on success. */ dbus_bool_t _dbus_signature_test (void) { DBusSignatureIter iter; DBusSignatureIter subiter; DBusSignatureIter subsubiter; DBusSignatureIter subsubsubiter; const char *sig; dbus_bool_t boolres; _dbus_assert (sizeof (DBusSignatureIter) >= sizeof (DBusSignatureRealIter)); sig = ""; _dbus_assert (dbus_signature_validate (sig, NULL)); _dbus_assert (!dbus_signature_validate_single (sig, NULL)); dbus_signature_iter_init (&iter, sig); _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_INVALID); sig = DBUS_TYPE_STRING_AS_STRING; _dbus_assert (dbus_signature_validate (sig, NULL)); _dbus_assert (dbus_signature_validate_single (sig, NULL)); dbus_signature_iter_init (&iter, sig); _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_STRING); sig = DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_BYTE_AS_STRING; _dbus_assert (dbus_signature_validate (sig, NULL)); dbus_signature_iter_init (&iter, sig); _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_STRING); boolres = dbus_signature_iter_next (&iter); _dbus_assert (boolres); _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_BYTE); sig = DBUS_TYPE_UINT16_AS_STRING DBUS_STRUCT_BEGIN_CHAR_AS_STRING DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_UINT32_AS_STRING DBUS_TYPE_VARIANT_AS_STRING DBUS_TYPE_DOUBLE_AS_STRING DBUS_STRUCT_END_CHAR_AS_STRING; _dbus_assert (dbus_signature_validate (sig, NULL)); dbus_signature_iter_init (&iter, sig); _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_UINT16); boolres = dbus_signature_iter_next (&iter); _dbus_assert (boolres); _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_STRUCT); dbus_signature_iter_recurse (&iter, &subiter); _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_STRING); boolres = dbus_signature_iter_next (&subiter); _dbus_assert (boolres); _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_UINT32); boolres = dbus_signature_iter_next (&subiter); _dbus_assert (boolres); _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_VARIANT); boolres = dbus_signature_iter_next (&subiter); _dbus_assert (boolres); _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_DOUBLE); sig = DBUS_TYPE_UINT16_AS_STRING DBUS_STRUCT_BEGIN_CHAR_AS_STRING DBUS_TYPE_UINT32_AS_STRING DBUS_TYPE_BYTE_AS_STRING DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_DOUBLE_AS_STRING DBUS_STRUCT_BEGIN_CHAR_AS_STRING DBUS_TYPE_BYTE_AS_STRING DBUS_STRUCT_END_CHAR_AS_STRING DBUS_STRUCT_END_CHAR_AS_STRING; _dbus_assert (dbus_signature_validate (sig, NULL)); dbus_signature_iter_init (&iter, sig); _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_UINT16); boolres = dbus_signature_iter_next (&iter); _dbus_assert (boolres); _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_STRUCT); dbus_signature_iter_recurse (&iter, &subiter); _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_UINT32); boolres = dbus_signature_iter_next (&subiter); _dbus_assert (boolres); _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_BYTE); boolres = dbus_signature_iter_next (&subiter); _dbus_assert (boolres); _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_ARRAY); _dbus_assert (dbus_signature_iter_get_element_type (&subiter) == DBUS_TYPE_ARRAY); dbus_signature_iter_recurse (&subiter, &subsubiter); _dbus_assert (dbus_signature_iter_get_current_type (&subsubiter) == DBUS_TYPE_ARRAY); _dbus_assert (dbus_signature_iter_get_element_type (&subsubiter) == DBUS_TYPE_DOUBLE); dbus_signature_iter_recurse (&subsubiter, &subsubsubiter); _dbus_assert (dbus_signature_iter_get_current_type (&subsubsubiter) == DBUS_TYPE_DOUBLE); boolres = dbus_signature_iter_next (&subiter); _dbus_assert (boolres); _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_STRUCT); dbus_signature_iter_recurse (&subiter, &subsubiter); _dbus_assert (dbus_signature_iter_get_current_type (&subsubiter) == DBUS_TYPE_BYTE); sig = DBUS_TYPE_ARRAY_AS_STRING DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING DBUS_TYPE_INT16_AS_STRING DBUS_TYPE_STRING_AS_STRING DBUS_DICT_ENTRY_END_CHAR_AS_STRING DBUS_TYPE_VARIANT_AS_STRING; _dbus_assert (dbus_signature_validate (sig, NULL)); _dbus_assert (!dbus_signature_validate_single (sig, NULL)); dbus_signature_iter_init (&iter, sig); _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_ARRAY); _dbus_assert (dbus_signature_iter_get_element_type (&iter) == DBUS_TYPE_DICT_ENTRY); dbus_signature_iter_recurse (&iter, &subiter); dbus_signature_iter_recurse (&subiter, &subsubiter); _dbus_assert (dbus_signature_iter_get_current_type (&subsubiter) == DBUS_TYPE_INT16); boolres = dbus_signature_iter_next (&subsubiter); _dbus_assert (boolres); _dbus_assert (dbus_signature_iter_get_current_type (&subsubiter) == DBUS_TYPE_STRING); boolres = dbus_signature_iter_next (&subsubiter); _dbus_assert (!boolres); boolres = dbus_signature_iter_next (&iter); _dbus_assert (boolres); _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_VARIANT); boolres = dbus_signature_iter_next (&iter); _dbus_assert (!boolres); sig = DBUS_TYPE_DICT_ENTRY_AS_STRING; _dbus_assert (!dbus_signature_validate (sig, NULL)); sig = DBUS_TYPE_ARRAY_AS_STRING; _dbus_assert (!dbus_signature_validate (sig, NULL)); sig = DBUS_TYPE_UINT32_AS_STRING DBUS_TYPE_ARRAY_AS_STRING; _dbus_assert (!dbus_signature_validate (sig, NULL)); sig = DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_DICT_ENTRY_AS_STRING; _dbus_assert (!dbus_signature_validate (sig, NULL)); sig = DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING; _dbus_assert (!dbus_signature_validate (sig, NULL)); sig = DBUS_DICT_ENTRY_END_CHAR_AS_STRING; _dbus_assert (!dbus_signature_validate (sig, NULL)); sig = DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING DBUS_TYPE_INT32_AS_STRING; _dbus_assert (!dbus_signature_validate (sig, NULL)); sig = DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING DBUS_TYPE_INT32_AS_STRING DBUS_TYPE_STRING_AS_STRING; _dbus_assert (!dbus_signature_validate (sig, NULL)); sig = DBUS_STRUCT_END_CHAR_AS_STRING DBUS_STRUCT_BEGIN_CHAR_AS_STRING; _dbus_assert (!dbus_signature_validate (sig, NULL)); sig = DBUS_STRUCT_BEGIN_CHAR_AS_STRING DBUS_TYPE_BOOLEAN_AS_STRING; _dbus_assert (!dbus_signature_validate (sig, NULL)); return TRUE; #if 0 oom: _dbus_assert_not_reached ("out of memory"); return FALSE; #endif }
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 {