static Eina_Bool _eldbus_message_iter_arguments_vget(Eldbus_Message_Iter *iter, const char *signature, va_list *aq) { int iter_type; DBusSignatureIter sig_iter; ELDBUS_MESSAGE_ITERATOR_CHECK_RETVAL(iter, EINA_FALSE); EINA_SAFETY_ON_TRUE_RETURN_VAL(iter->writable, EINA_FALSE); EINA_SAFETY_ON_NULL_RETURN_VAL(signature, EINA_FALSE); EINA_SAFETY_ON_FALSE_RETURN_VAL(dbus_signature_validate(signature, NULL), EINA_FALSE); dbus_signature_iter_init(&sig_iter, signature); iter_type = dbus_message_iter_get_arg_type(&iter->dbus_iterator); while (iter_type != DBUS_TYPE_INVALID) { int sig_type = dbus_signature_iter_get_current_type(&sig_iter); if (sig_type == DBUS_TYPE_INVALID) break; if (sig_type != iter_type) { ERR("Type in iterator different of signature expected:%c got %c", iter_type, sig_type); return EINA_FALSE; } if (dbus_type_is_basic(iter_type)) get_basic(iter_type, &iter->dbus_iterator, aq); else { Eldbus_Message_Iter **user_itr = va_arg(*aq, Eldbus_Message_Iter **); Eldbus_Message_Iter *sub_itr; sub_itr = _message_iterator_new(EINA_FALSE); EINA_SAFETY_ON_NULL_RETURN_VAL(sub_itr, EINA_FALSE); dbus_message_iter_recurse(&iter->dbus_iterator, &sub_itr->dbus_iterator); iter->iterators = eina_inlist_append(iter->iterators, EINA_INLIST_GET(sub_itr)); *user_itr = sub_itr; } dbus_message_iter_next(&iter->dbus_iterator); dbus_signature_iter_next(&sig_iter); iter_type = dbus_message_iter_get_arg_type(&iter->dbus_iterator); } return dbus_signature_iter_get_current_type(&sig_iter) == DBUS_TYPE_INVALID; }
GType _dbus_gtype_from_signature_iter (DBusSignatureIter *iter, gboolean is_client) { int current_type; current_type = dbus_signature_iter_get_current_type (iter); if (dbus_typecode_maps_to_basic (current_type)) return _dbus_gtype_from_basic_typecode (current_type); else if (current_type == DBUS_TYPE_OBJECT_PATH) return DBUS_TYPE_G_OBJECT_PATH; else if (current_type == DBUS_TYPE_SIGNATURE) return DBUS_TYPE_G_SIGNATURE; else if (current_type == DBUS_TYPE_VARIANT || current_type == DBUS_TYPE_ARRAY || current_type == DBUS_TYPE_STRUCT) { DBusSignatureIter subiter; g_assert (dbus_type_is_container (current_type)); if (current_type == DBUS_TYPE_VARIANT) return G_TYPE_VALUE; dbus_signature_iter_recurse (iter, &subiter); if (current_type == DBUS_TYPE_ARRAY) { int elt_type = dbus_signature_iter_get_current_type (&subiter); if (elt_type == DBUS_TYPE_DICT_ENTRY) return signature_iter_to_g_type_dict (&subiter, is_client); else return signature_iter_to_g_type_array (&subiter, is_client); } else if (current_type == DBUS_TYPE_STRUCT) { return signature_iter_to_g_type_struct (&subiter, is_client); } else { g_assert_not_reached (); return G_TYPE_INVALID; } } else { /* dbus-glib does not handle DBUS_TYPE_UNIX_FD or DBUS_TYPE_MAYBE */ return G_TYPE_INVALID; } }
/** * Initialize a new iterator pointing to the first type current * container. It's an error to call this if the current type is a * non-container (i.e. if dbus_type_is_container returns FALSE). * * @param iter the current interator * @param subiter an iterator to initialize pointing to the first child */ void dbus_signature_iter_recurse (const DBusSignatureIter *iter, DBusSignatureIter *subiter) { DBusSignatureRealIter *real_iter = (DBusSignatureRealIter *) iter; DBusSignatureRealIter *real_sub_iter = (DBusSignatureRealIter *) subiter; _dbus_return_if_fail (dbus_type_is_container (dbus_signature_iter_get_current_type (iter))); *real_sub_iter = *real_iter; real_sub_iter->pos++; if (dbus_signature_iter_get_current_type (subiter) == DBUS_TYPE_ARRAY) real_sub_iter->in_array = TRUE; }
static Eina_Bool _eldbus_message_arguments_vappend(Eldbus_Message *msg, const char *signature, va_list *aq) { DBusSignatureIter signature_iter; Eldbus_Message_Iter *iter; int type; Eina_Bool r = EINA_TRUE; if (!signature[0]) return EINA_TRUE; EINA_SAFETY_ON_FALSE_RETURN_VAL(dbus_signature_validate(signature, NULL), EINA_FALSE); iter = eldbus_message_iter_get(msg); EINA_SAFETY_ON_FALSE_RETURN_VAL(iter->writable, EINA_FALSE); dbus_signature_iter_init(&signature_iter, signature); while ((type = dbus_signature_iter_get_current_type(&signature_iter))) { if (dbus_type_is_basic(type)) r = append_basic(type, aq, &iter->dbus_iterator); else { ERR("sig = %s | eldbus_message_arguments_append() and \ eldbus_message_arguments_vappend() only support basic types, \ to complex types use eldbus_message_iter_* functions", signature); r = EINA_FALSE; } if (!r || !dbus_signature_iter_next(&signature_iter)) break; } return r; }
//! Splits signature into atomic DBus object signatures PyObject * script_signature_each(const char *signature) { PyObject *py_list = PyList_New(0); DBusError error; DBusSignatureIter iter; dbus_signature_iter_init(&iter, signature); while (dbus_signature_iter_get_current_type(&iter) != DBUS_TYPE_INVALID) { char *sign = dbus_signature_iter_get_signature(&iter); dbus_error_init(&error); dbus_signature_validate(sign, &error); if (dbus_error_is_set(&error)) { dbus_error_free(&error); return NULL; } else { PyList_Append(py_list, PyString_FromString(sign)); } dbus_free(sign); dbus_signature_iter_next(&iter); } return py_list; }
static GType signature_iter_to_g_type_dict (const DBusSignatureIter *subiter, gboolean is_client) { DBusSignatureIter iter; GType key_gtype; GType value_gtype; g_assert (dbus_signature_iter_get_current_type (subiter) == DBUS_TYPE_DICT_ENTRY); dbus_signature_iter_recurse (subiter, &iter); key_gtype = _dbus_gtype_from_signature_iter (&iter, is_client); if (key_gtype == G_TYPE_INVALID) return G_TYPE_INVALID; dbus_signature_iter_next (&iter); value_gtype = _dbus_gtype_from_signature_iter (&iter, is_client); if (value_gtype == G_TYPE_INVALID) return G_TYPE_INVALID; if (!_dbus_gtype_is_valid_hash_key (key_gtype) || !_dbus_gtype_is_valid_hash_value (value_gtype)) /* Later we need to return DBUS_TYPE_G_VALUE */ return G_TYPE_INVALID; return dbus_g_type_get_map ("GHashTable", key_gtype, value_gtype); }
static add_function get_addfunc(DBusSignatureIter *type) { switch (dbus_signature_iter_get_current_type(type)) { case DBUS_TYPE_BOOLEAN: return add_boolean; case DBUS_TYPE_BYTE: return add_byte; case DBUS_TYPE_INT16: return add_int16; case DBUS_TYPE_UINT16: return add_uint16; case DBUS_TYPE_INT32: return add_int32; case DBUS_TYPE_UINT32: return add_uint32; case DBUS_TYPE_STRING: return add_string; case DBUS_TYPE_OBJECT_PATH: return add_object_path; case DBUS_TYPE_ARRAY: return add_array; } return add_not_implemented; }
/** * Convenience function for returning the element type of an array; * This function allows you to avoid initializing a sub-iterator and * getting its current type. * * Undefined behavior results if you invoke this function when the * current type of the iterator is not #DBUS_TYPE_ARRAY. * * @param iter pointer to an iterator * @returns current array element type */ int dbus_signature_iter_get_element_type (const DBusSignatureIter *iter) { DBusSignatureRealIter *real_iter = (DBusSignatureRealIter *) iter; _dbus_return_val_if_fail (dbus_signature_iter_get_current_type (iter) == DBUS_TYPE_ARRAY, DBUS_TYPE_INVALID); return _dbus_first_type_in_signature_c_str (real_iter->pos, 1); }
/** * Check that a type signature is both valid and contains exactly one * complete type. "One complete type" means a single basic type, * array, struct, or dictionary, though the struct or array may be * arbitrarily recursive and complex. More than one complete type * would mean for example "ii" or two integers in sequence. * * @param signature a potentially invalid type signature * @param error error return * @returns #TRUE if signature is valid and has exactly one complete type */ dbus_bool_t dbus_signature_validate_single (const char *signature, DBusError *error) { DBusSignatureIter iter; if (!dbus_signature_validate (signature, error)) return FALSE; dbus_signature_iter_init (&iter, signature); if (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_INVALID) goto lose; if (!dbus_signature_iter_next (&iter)) return TRUE; lose: dbus_set_error (error, DBUS_ERROR_INVALID_SIGNATURE, "Exactly one complete type required in signature"); return FALSE; }
int bridge_request_dbus_params_dict(bridge_request_t *self, struct json_object *element, DBusSignatureIter *sigIt, DBusMessageIter *it) { DBusMessageIter args; DBusSignatureIter sigArgs; int ret; dbus_signature_iter_recurse(sigIt, &sigArgs); if (dbus_signature_iter_get_current_type(&sigArgs) != DBUS_TYPE_STRING) { bridge_request_error(self, "string dict key type expected."); return EINVAL; } if (!dbus_signature_iter_next(&sigArgs) || (json_object_get_type(element) != json_type_object)) { bridge_request_error(self, "object expected."); return EINVAL; } #ifndef S_SPLINT_S json_object_object_foreach(element, key, tmp) #endif { if (!tmp) { bridge_request_error(self, "unexpected 'null' value in json object."); return EINVAL; } DBusSignatureIter tmpSigArgs = sigArgs; dbus_message_iter_open_container(it, DBUS_TYPE_DICT_ENTRY, 0,&args); dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &key); ret = bridge_request_dbus_params_element(self, tmp, &tmpSigArgs, &args); if (ret != 0) return ret; dbus_message_iter_close_container(it, &args); } return 0; }
GArray * _dbus_gtypes_from_arg_signature (const char *argsig, gboolean is_client) { GArray *ret; int current_type; DBusSignatureIter sigiter; ret = g_array_new (FALSE, FALSE, sizeof (GType)); dbus_signature_iter_init (&sigiter, argsig); while ((current_type = dbus_signature_iter_get_current_type (&sigiter)) != DBUS_TYPE_INVALID) { GType curtype; curtype = _dbus_gtype_from_signature_iter (&sigiter, is_client); g_array_append_val (ret, curtype); dbus_signature_iter_next (&sigiter); } return ret; }
/** * type_of: * @parent: parent object for new string, * @iter: D-Bus signature iterator. * * Converts the D-Bus basic type at the current element of the iterator * @iter into an appropriate C type to hold it. * * If @parent is not NULL, it should be a pointer to another object which * will be used as a parent for the returned string. When all parents * of the returned string are freed, the returned string will also be * freed. * * Returns: newly allocated string or NULL if allocation failed. **/ char * type_of (const void * parent, DBusSignatureIter *iter) { int dbus_type; nih_assert (iter != NULL); dbus_type = dbus_signature_iter_get_current_type (iter); switch (dbus_type) { case DBUS_TYPE_BYTE: return nih_strdup (parent, "uint8_t"); case DBUS_TYPE_BOOLEAN: return nih_strdup (parent, "int"); case DBUS_TYPE_INT16: return nih_strdup (parent, "int16_t"); case DBUS_TYPE_UINT16: return nih_strdup (parent, "uint16_t"); case DBUS_TYPE_INT32: return nih_strdup (parent, "int32_t"); case DBUS_TYPE_UINT32: return nih_strdup (parent, "uint32_t"); case DBUS_TYPE_INT64: return nih_strdup (parent, "int64_t"); case DBUS_TYPE_UINT64: return nih_strdup (parent, "uint64_t"); case DBUS_TYPE_DOUBLE: return nih_strdup (parent, "double"); case DBUS_TYPE_STRING: return nih_strdup (parent, "char *"); case DBUS_TYPE_OBJECT_PATH: return nih_strdup (parent, "char *"); case DBUS_TYPE_SIGNATURE: return nih_strdup (parent, "char *"); case DBUS_TYPE_UNIX_FD: return nih_strdup (parent, "int"); default: nih_assert_not_reached (); } }
/** * @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 {
int bridge_request_dbus_params_element(bridge_request_t *self, struct json_object *element, DBusSignatureIter *sigIt, DBusMessageIter *it) { int type; int ret = 0; type = dbus_signature_iter_get_current_type(sigIt); if (dbus_type_is_basic(type)) { if ((ret = bridge_request_dbus_params_basic(self, element, type, it)) != 0) { return ret; } } else if (type == DBUS_TYPE_VARIANT) { struct json_object *tmp; DBusMessageIter args; const char *vSig; if (json_object_get_type(element) != json_type_array) { bridge_request_error(self, "array expected."); return EINVAL; } tmp = json_object_array_get_idx(element, 0); if (!tmp) { bridge_request_error(self, "variant signature expected."); return EINVAL; } if (json_object_get_type(tmp) != json_type_string) { bridge_request_error(self, "variant signature expected."); return EINVAL; } vSig = json_object_get_string(tmp); if (!dbus_signature_validate_single(vSig, 0)) { bridge_request_error(self, "invalid variant signature."); return EINVAL; } dbus_message_iter_open_container(it, type, vSig, &args); ret = bridge_request_dbus_params_array(self, element, 1, vSig, &args); dbus_message_iter_close_container(it, &args); if (ret != 0) return EINVAL; } else if (type == DBUS_TYPE_STRUCT) { DBusMessageIter args; DBusSignatureIter sigArgs; if (json_object_get_type(element) != json_type_array) { bridge_request_error(self, "array expected."); return EINVAL; } dbus_signature_iter_recurse(sigIt, &sigArgs); dbus_message_iter_open_container(it, type, NULL, &args); ret = bridge_request_dbus_params_struct(self, element, &sigArgs, &args); dbus_message_iter_close_container(it, &args); if (ret != 0) return EINVAL; } else if (type == DBUS_TYPE_ARRAY) { DBusMessageIter args; DBusSignatureIter sigArgs; int cType; char *cSig; dbus_signature_iter_recurse(sigIt, &sigArgs); cType = dbus_signature_iter_get_current_type(&sigArgs); cSig = dbus_signature_iter_get_signature(&sigArgs); dbus_message_iter_open_container(it, type, cSig, &args); dbus_free(cSig); if (cType == DBUS_TYPE_DICT_ENTRY) { ret = bridge_request_dbus_params_dict(self, element, &sigArgs, &args); } else { int i, len; if (json_object_get_type(element) != json_type_array) { bridge_request_error(self, "array expected."); ret = EINVAL; } else { len = json_object_array_length(element); for (i = 0; i < len; ++i) { struct json_object *tmp; DBusSignatureIter tmpSigArgs = sigArgs; tmp = json_object_array_get_idx(element, i); if (!tmp) { bridge_request_error(self, "unexpected 'null' element in json array."); return EINVAL; } ret = bridge_request_dbus_params_element(self, tmp, &tmpSigArgs, &args); } } } dbus_message_iter_close_container(it, &args); } else { bridge_request_error(self, "unsupported json argument type."); return EINVAL; } return ret; }