+ * @param iter the iterator
+ * @param value return location for the array
+ * @param len return location for the array length
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_get_uint32_array (DBusMessageIter *iter,
+ dbus_uint32_t **value,
+ int *len)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+ int type, pos;
+
+ _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
+
+ pos = dbus_message_iter_get_data_start (real, &type);
+
+ _dbus_assert (type == DBUS_TYPE_ARRAY);
+
+ type = iter_get_array_type (real, NULL);
+ _dbus_assert (type == DBUS_TYPE_UINT32);
+
+ if (!_dbus_demarshal_uint32_array (&real->message->body, real->message->byte_order,
+ pos, NULL, value, len))
+ return FALSE;
+ else
+ return TRUE;
+}
+
+#ifdef DBUS_HAVE_INT64
+
+/**
+ * Returns the 64 bit signed integer array that the iterator may point
+ * to. Note that you need to check that the iterator points to an
+ * array of the correct type prior to using this function.
+ *
+ * This function only exists if #DBUS_HAVE_INT64 is defined.
+ *
+ * @param iter the iterator
+ * @param value return location for the array
+ * @param len return location for the array length
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_get_int64_array (DBusMessageIter *iter,
+ dbus_int64_t **value,
+ int *len)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+ int type, pos;
+
+ _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
+
+ pos = dbus_message_iter_get_data_start (real, &type);
+
+ _dbus_assert (type == DBUS_TYPE_ARRAY);
+
+ type = iter_get_array_type (real, NULL);
+
+ _dbus_assert (type == DBUS_TYPE_INT64);
+
+ if (!_dbus_demarshal_int64_array (&real->message->body, real->message->byte_order,
+ pos, NULL, value, len))
+ return FALSE;
+ else
+ return TRUE;
+}
+
+/**
+ * Returns the 64 bit unsigned integer array that the iterator may point
+ * to. Note that you need to check that the iterator points to an
+ * array of the correct type prior to using this function.
+ *
+ * This function only exists if #DBUS_HAVE_INT64 is defined.
+ *
+ * @param iter the iterator
+ * @param value return location for the array
+ * @param len return location for the array length
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_get_uint64_array (DBusMessageIter *iter,
+ dbus_uint64_t **value,
+ int *len)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+ int type, pos;
+
+ _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
+
+ pos = dbus_message_iter_get_data_start (real, &type);
+
+ _dbus_assert (type == DBUS_TYPE_ARRAY);
+
+ type = iter_get_array_type (real, NULL);
+ _dbus_assert (type == DBUS_TYPE_UINT64);
+
+ if (!_dbus_demarshal_uint64_array (&real->message->body, real->message->byte_order,
+ pos, NULL, value, len))
+ return FALSE;
+ else
+ return TRUE;
+}
+
+#endif /* DBUS_HAVE_INT64 */
+
+/**
+ * Returns the double array that the iterator may point to. Note that
+ * you need to check that the iterator points to an array of the
+ * correct type prior to using this function.
+ *
+ * @param iter the iterator
+ * @param value return location for the array
+ * @param len return location for the array length
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_get_double_array (DBusMessageIter *iter,
+ double **value,
+ int *len)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+ int type, pos;
+
+ _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
+
+ pos = dbus_message_iter_get_data_start (real, &type);
+
+ _dbus_assert (type == DBUS_TYPE_ARRAY);
+
+ type = iter_get_array_type (real, NULL);
+ _dbus_assert (type == DBUS_TYPE_DOUBLE);
+
+ if (!_dbus_demarshal_double_array (&real->message->body, real->message->byte_order,
+ pos, NULL, value, len))
+ return FALSE;
+ else
+ return TRUE;
+}
+
+/**
+ * Returns the string array that the iterator may point to.
+ * Note that you need to check that the iterator points
+ * to a byte array prior to using this function.
+ *
+ * The returned value is a #NULL-terminated array of strings.
+ * Each string is a separate malloc block, and the array
+ * itself is a malloc block. You can free this type of
+ * string array with dbus_free_string_array().
+ *
+ * @param iter the iterator
+ * @param value return location for string values
+ * @param len return location for length of byte array
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_get_string_array (DBusMessageIter *iter,
+ char ***value,
+ int *len)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+ int type, pos;
+
+ _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
+
+ pos = dbus_message_iter_get_data_start (real, &type);
+
+ _dbus_assert (type == DBUS_TYPE_ARRAY);
+
+ type = iter_get_array_type (real, NULL);
+ _dbus_assert (type == DBUS_TYPE_STRING);
+
+ if (!_dbus_demarshal_string_array (&real->message->body, real->message->byte_order,
+ pos, NULL, value, len))
+ return FALSE;
+ else
+ return TRUE;
+}
+
+/**
+ * Returns the key name fot the dict entry that an iterator
+ * may point to. Note that you need to check that the iterator
+ * points to a dict entry before using this function.
+ *
+ * @see dbus_message_iter_init_dict_iterator
+ * @param iter the message iter
+ * @returns the key name
+ */
+char *
+dbus_message_iter_get_dict_key (DBusMessageIter *iter)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ _dbus_return_val_if_fail (dbus_message_iter_check (real), NULL);
+
+ _dbus_assert (real->type == DBUS_MESSAGE_ITER_TYPE_DICT);
+
+ return _dbus_demarshal_string (&real->message->body, real->message->byte_order,
+ real->pos, NULL);
+}
+
+/**
+ * Initializes a DBusMessageIter pointing to the end of the
+ * message. This iterator can be used to append data to the
+ * message.
+ *
+ * @param message the message
+ * @param iter pointer to an iterator to initialize
+ */
+void
+dbus_message_append_iter_init (DBusMessage *message,
+ DBusMessageIter *iter)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ _dbus_return_if_fail (message != NULL);
+ _dbus_return_if_fail (iter != NULL);
+
+ real->message = message;
+ real->parent_iter = NULL;
+ real->changed_stamp = message->changed_stamp;
+
+ real->type = DBUS_MESSAGE_ITER_TYPE_MESSAGE;
+ real->end = _dbus_string_get_length (&real->message->body);
+ real->pos = real->end;
+
+ real->container_length_pos = 0;
+ real->wrote_dict_key = 0;
+}
+
+#ifndef DBUS_DISABLE_CHECKS
+static dbus_bool_t
+dbus_message_iter_append_check (DBusMessageRealIter *iter)
+{
+ if (iter == NULL)
+ {
+ _dbus_warn ("dbus iterator check failed: NULL iterator\n");
+ return FALSE;
+ }
+
+ if (iter->message->locked)
+ {
+ _dbus_warn ("dbus iterator check failed: message is locked (has already been sent)\n");
+ return FALSE;
+ }
+
+ if (iter->changed_stamp != iter->message->changed_stamp)
+ {
+ _dbus_warn ("dbus iterator check failed: invalid iterator, must re-initialize it after modifying the message");
+ return FALSE;
+ }
+
+ if (iter->pos != iter->end)
+ {
+ _dbus_warn ("dbus iterator check failed: can only append at end of message");
+ return FALSE;
+ }
+
+ if (iter->pos != _dbus_string_get_length (&iter->message->body))
+ {
+ _dbus_warn ("dbus iterator check failed: append pos not at end of message string");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+#endif /* DBUS_DISABLE_CHECKS */
+
+static dbus_bool_t
+dbus_message_iter_append_type (DBusMessageRealIter *iter,
+ int type)
+{
+ const char *data;
+ switch (iter->type)
+ {
+ case DBUS_MESSAGE_ITER_TYPE_MESSAGE:
+ if (!_dbus_string_append_byte (&iter->message->signature, type))
+ return FALSE;
+
+ if (!_dbus_string_append_byte (&iter->message->body, type))
+ {
+ _dbus_string_shorten (&iter->message->signature, 1);
+ return FALSE;
+ }
+ break;
+
+ case DBUS_MESSAGE_ITER_TYPE_ARRAY:
+ data = _dbus_string_get_const_data_len (&iter->message->body,
+ iter->array_type_pos, 1);
+ if (type != *data)
+ {
+ _dbus_warn ("Appended element of wrong type for array\n");
+ return FALSE;
+ }
+ break;
+
+ case DBUS_MESSAGE_ITER_TYPE_DICT:
+ if (!iter->wrote_dict_key)
+ {
+ _dbus_warn ("Appending dict data before key name\n");
+ return FALSE;
+ }
+
+ if (!_dbus_string_append_byte (&iter->message->body, type))
+ return FALSE;
+
+ break;
+
+ default:
+ _dbus_assert_not_reached ("Invalid iter type");
+ break;
+ }
+
+ return TRUE;
+}
+
+static void
+dbus_message_iter_update_after_change (DBusMessageRealIter *iter)
+{
+ iter->changed_stamp = iter->message->changed_stamp;
+
+ /* Set new end of iter */
+ iter->end = _dbus_string_get_length (&iter->message->body);
+ iter->pos = iter->end;
+
+ /* Set container length */
+ if (iter->type == DBUS_MESSAGE_ITER_TYPE_DICT ||
+ (iter->type == DBUS_MESSAGE_ITER_TYPE_ARRAY && iter->array_type_done))
+ _dbus_marshal_set_uint32 (&iter->message->body,
+ iter->message->byte_order,
+ iter->container_length_pos,
+ iter->end - iter->container_start);
+
+ if (iter->parent_iter)
+ dbus_message_iter_update_after_change (iter->parent_iter);
+}
+
+static void
+dbus_message_iter_append_done (DBusMessageRealIter *iter)
+{
+ iter->message->changed_stamp++;
+ dbus_message_iter_update_after_change (iter);
+ iter->wrote_dict_key = FALSE;
+}
+
+/**
+ * Appends a nil value to the message
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_nil (DBusMessageIter *iter)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
+
+ if (!dbus_message_iter_append_type (real, DBUS_TYPE_NIL))
+ return FALSE;
+
+ dbus_message_iter_append_done (real);
+
+ return TRUE;
+}
+
+/**
+ * Appends a boolean value to the message
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param value the boolean value
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_boolean (DBusMessageIter *iter,
+ dbus_bool_t value)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
+
+ if (!dbus_message_iter_append_type (real, DBUS_TYPE_BOOLEAN))
+ return FALSE;
+
+ if (!_dbus_string_append_byte (&real->message->body, (value != FALSE)))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ dbus_message_iter_append_done (real);
+
+ return TRUE;
+}
+
+/**
+ * Appends a byte to the message
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param value the byte value
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_byte (DBusMessageIter *iter,
+ unsigned char value)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
+
+ if (!dbus_message_iter_append_type (real, DBUS_TYPE_BYTE))
+ return FALSE;
+
+ if (!_dbus_string_append_byte (&real->message->body, value))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ dbus_message_iter_append_done (real);
+
+ return TRUE;
+}
+
+
+/**
+ * Appends a 32 bit signed integer to the message.
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param value the integer value
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_int32 (DBusMessageIter *iter,
+ dbus_int32_t value)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
+
+ if (!dbus_message_iter_append_type (real, DBUS_TYPE_INT32))
+ return FALSE;
+
+ if (!_dbus_marshal_int32 (&real->message->body, real->message->byte_order, value))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ dbus_message_iter_append_done (real);
+
+ return TRUE;
+}
+
+/**
+ * Appends a 32 bit unsigned integer to the message.
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param value the integer value
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_uint32 (DBusMessageIter *iter,
+ dbus_uint32_t value)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
+
+ if (!dbus_message_iter_append_type (real, DBUS_TYPE_UINT32))
+ return FALSE;
+
+ if (!_dbus_marshal_uint32 (&real->message->body, real->message->byte_order, value))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ dbus_message_iter_append_done (real);
+
+ return TRUE;
+}
+
+#ifdef DBUS_HAVE_INT64
+
+/**
+ * Appends a 64 bit signed integer to the message.
+ *
+ * This function only exists if #DBUS_HAVE_INT64 is defined.
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param value the integer value
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_int64 (DBusMessageIter *iter,
+ dbus_int64_t value)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
+
+ if (!dbus_message_iter_append_type (real, DBUS_TYPE_INT64))
+ return FALSE;
+
+ if (!_dbus_marshal_int64 (&real->message->body, real->message->byte_order, value))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ dbus_message_iter_append_done (real);
+
+ return TRUE;
+}
+
+/**
+ * Appends a 64 bit unsigned integer to the message.
+ *
+ * This function only exists if #DBUS_HAVE_INT64 is defined.
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param value the integer value
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_uint64 (DBusMessageIter *iter,
+ dbus_uint64_t value)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
+
+ if (!dbus_message_iter_append_type (real, DBUS_TYPE_UINT64))
+ return FALSE;
+
+ if (!_dbus_marshal_uint64 (&real->message->body, real->message->byte_order, value))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ dbus_message_iter_append_done (real);
+
+ return TRUE;
+}
+
+#endif /* DBUS_HAVE_INT64 */
+
+/**
+ * Appends a double value to the message.
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param value the double value
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_double (DBusMessageIter *iter,
+ double value)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
+
+ if (!dbus_message_iter_append_type (real, DBUS_TYPE_DOUBLE))
+ return FALSE;
+
+ if (!_dbus_marshal_double (&real->message->body, real->message->byte_order, value))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ dbus_message_iter_append_done (real);
+
+ return TRUE;
+}
+
+/**
+ * Appends a UTF-8 string to the message.
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param value the string
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_string (DBusMessageIter *iter,
+ const char *value)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
+
+ if (!dbus_message_iter_append_type (real, DBUS_TYPE_STRING))
+ return FALSE;
+
+ if (!_dbus_marshal_string (&real->message->body, real->message->byte_order, value))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ dbus_message_iter_append_done (real);
+
+ return TRUE;
+}
+
+/**
+ * Appends a named type data chunk to the message. A named
+ * type is simply an arbitrary UTF-8 string used as a type
+ * tag, plus an array of arbitrary bytes to be interpreted
+ * according to the type tag.
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param name the name of the type
+ * @param data the binary data used to store the value
+ * @param len the length of the binary data in bytes
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_named (DBusMessageIter *iter,
+ const char *name,
+ const unsigned char *data,
+ int len)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
+
+ if (!dbus_message_iter_append_type (real, DBUS_TYPE_NAMED))
+ return FALSE;
+
+ if (!_dbus_marshal_string (&real->message->body, real->message->byte_order, name))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ if (!_dbus_marshal_byte_array (&real->message->body, real->message->byte_order, data, len))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ dbus_message_iter_append_done (real);
+
+ return TRUE;
+}
+
+
+/**
+ * Appends a dict key name to the message. The iterator used
+ * must point to a dict.
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param value the string
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_dict_key (DBusMessageIter *iter,
+ const char *value)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
+ _dbus_assert (real->type == DBUS_MESSAGE_ITER_TYPE_DICT);
+
+ if (real->wrote_dict_key)
+ {
+ _dbus_warn ("Appendinging multiple dict key names\n");
+ return FALSE;
+ }
+
+ if (!_dbus_marshal_string (&real->message->body, real->message->byte_order, value))
+ {
+ return FALSE;
+ }
+
+ dbus_message_iter_append_done (real);
+ real->wrote_dict_key = TRUE;
+
+ return TRUE;
+}
+
+static dbus_bool_t
+array_iter_type_mark_done (DBusMessageRealIter *iter)
+{
+ int len_pos;
+
+ if (iter->type == DBUS_MESSAGE_ITER_TYPE_ARRAY)
+ array_iter_type_mark_done (iter->parent_iter);
+ else
+ return TRUE;
+
+ len_pos = _DBUS_ALIGN_VALUE (_dbus_string_get_length (&iter->message->body),
+ sizeof (dbus_uint32_t));
+
+ /* Empty length for now, backfill later */
+ if (!_dbus_marshal_uint32 (&iter->message->body, iter->message->byte_order, 0))
+ {
+ _dbus_string_set_length (&iter->message->body, iter->pos);
+ return FALSE;
+ }
+
+ iter->container_start = _dbus_string_get_length (&iter->message->body);
+ iter->container_length_pos = len_pos;
+ iter->array_type_done = TRUE;
+
+ return TRUE;
+}
+
+static dbus_bool_t
+append_array_type (DBusMessageRealIter *real,
+ int element_type,
+ dbus_bool_t *array_type_done,
+ int *array_type_pos)
+{
+ int existing_element_type;
+
+ if (!dbus_message_iter_append_type (real, DBUS_TYPE_ARRAY))
+ return FALSE;
+
+ if (real->type == DBUS_MESSAGE_ITER_TYPE_ARRAY &&
+ real->array_type_done)
+ {
+ existing_element_type = iter_get_array_type (real, array_type_pos);
+ if (existing_element_type != element_type)
+ {
+ _dbus_warn ("Appending array of %s, when expecting array of %s\n",
+ _dbus_type_to_string (element_type),
+ _dbus_type_to_string (existing_element_type));
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+ if (array_type_done != NULL)
+ *array_type_done = TRUE;
+ }
+ else
+ {
+ if (array_type_pos != NULL)
+ *array_type_pos = _dbus_string_get_length (&real->message->body);
+
+
+ if (!_dbus_string_append_byte (&real->message->signature, element_type))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ /* Append element type */
+ if (!_dbus_string_append_byte (&real->message->body, element_type))
+ {
+ _dbus_string_shorten (&real->message->signature, 1);
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ if (array_type_done != NULL)
+ *array_type_done = element_type != DBUS_TYPE_ARRAY;
+
+ if (element_type != DBUS_TYPE_ARRAY &&
+ !array_iter_type_mark_done (real))
+ {
+ _dbus_string_shorten (&real->message->signature, 1);
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+/**
+ * Appends an array to the message and initializes an iterator that
+ * can be used to append to the array.
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param array_iter pointer to an iter that will be initialized
+ * @param element_type the type of the array elements
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_array (DBusMessageIter *iter,
+ DBusMessageIter *array_iter,
+ int element_type)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+ DBusMessageRealIter *array_real = (DBusMessageRealIter *)array_iter;
+ int len_pos;
+ int array_type_pos;
+ dbus_bool_t array_type_done;
+
+ if (element_type == DBUS_TYPE_NIL)
+ {
+ _dbus_warn ("Can't create NIL arrays\n");
+ return FALSE;
+ }
+
+ _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
+
+ if (!append_array_type (real, element_type, &array_type_done, &array_type_pos))
+ return FALSE;
+
+ len_pos = _DBUS_ALIGN_VALUE (_dbus_string_get_length (&real->message->body), sizeof (dbus_uint32_t));
+
+ if (array_type_done)
+ {
+ /* Empty length for now, backfill later */
+ if (!_dbus_marshal_uint32 (&real->message->body, real->message->byte_order, 0))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+ }
+
+ array_real->parent_iter = real;
+ array_real->message = real->message;
+ array_real->changed_stamp = real->message->changed_stamp;
+
+ array_real->type = DBUS_MESSAGE_ITER_TYPE_ARRAY;
+ array_real->pos = _dbus_string_get_length (&real->message->body);
+ array_real->end = array_real->end;
+
+ array_real->container_start = array_real->pos;
+ array_real->container_length_pos = len_pos;
+ array_real->wrote_dict_key = 0;
+ array_real->array_type_done = array_type_done;
+ array_real->array_type_pos = array_type_pos;
+
+ dbus_message_iter_append_done (array_real);
+
+ return TRUE;
+}
+
+/**
+ * Appends a dict to the message and initializes an iterator that
+ * can be used to append to the dict.
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param dict_iter pointer to an iter that will be initialized
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_dict (DBusMessageIter *iter,
+ DBusMessageIter *dict_iter)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+ DBusMessageRealIter *dict_real = (DBusMessageRealIter *)dict_iter;
+ int len_pos;
+
+ _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
+
+ if (!dbus_message_iter_append_type (real, DBUS_TYPE_DICT))
+ return FALSE;
+
+ len_pos = _DBUS_ALIGN_VALUE (_dbus_string_get_length (&real->message->body), sizeof (dbus_uint32_t));
+
+ /* Empty length for now, backfill later */
+ if (!_dbus_marshal_uint32 (&real->message->body, real->message->byte_order, 0))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ dict_real->parent_iter = real;
+ dict_real->message = real->message;
+ dict_real->changed_stamp = real->message->changed_stamp;
+
+ dict_real->type = DBUS_MESSAGE_ITER_TYPE_DICT;
+ dict_real->pos = _dbus_string_get_length (&real->message->body);
+ dict_real->end = dict_real->end;
+
+ dict_real->container_start = dict_real->pos;
+ dict_real->container_length_pos = len_pos;
+ dict_real->wrote_dict_key = 0;
+
+ dbus_message_iter_append_done (dict_real);
+
+ return TRUE;
+}
+
+
+/**
+ * Appends a boolean array to the message.
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param value the array
+ * @param len the length of the array
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_boolean_array (DBusMessageIter *iter,
+ unsigned const char *value,
+ int len)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
+
+ if (!append_array_type (real, DBUS_TYPE_BOOLEAN, NULL, NULL))
+ return FALSE;
+
+ if (!_dbus_marshal_byte_array (&real->message->body, real->message->byte_order, value, len))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ dbus_message_iter_append_done (real);
+
+ return TRUE;
+}
+
+/**
+ * Appends a 32 bit signed integer array to the message.
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param value the array
+ * @param len the length of the array
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_int32_array (DBusMessageIter *iter,
+ const dbus_int32_t *value,
+ int len)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
+
+ if (!append_array_type (real, DBUS_TYPE_INT32, NULL, NULL))
+ return FALSE;
+
+ if (!_dbus_marshal_int32_array (&real->message->body, real->message->byte_order, value, len))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ dbus_message_iter_append_done (real);
+
+ return TRUE;
+}
+
+/**
+ * Appends a 32 bit unsigned integer array to the message.
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param value the array
+ * @param len the length of the array
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_uint32_array (DBusMessageIter *iter,
+ const dbus_uint32_t *value,
+ int len)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
+
+ if (!append_array_type (real, DBUS_TYPE_UINT32, NULL, NULL))
+ return FALSE;
+
+ if (!_dbus_marshal_uint32_array (&real->message->body, real->message->byte_order, value, len))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ dbus_message_iter_append_done (real);
+
+ return TRUE;
+}
+
+#ifdef DBUS_HAVE_INT64
+
+/**
+ * Appends a 64 bit signed integer array to the message.
+ *
+ * This function only exists if #DBUS_HAVE_INT64 is defined.
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param value the array
+ * @param len the length of the array
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_int64_array (DBusMessageIter *iter,
+ const dbus_int64_t *value,
+ int len)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
+
+ if (!append_array_type (real, DBUS_TYPE_INT64, NULL, NULL))
+ return FALSE;
+
+ if (!_dbus_marshal_int64_array (&real->message->body, real->message->byte_order, value, len))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ dbus_message_iter_append_done (real);
+
+ return TRUE;
+}
+
+/**
+ * Appends a 64 bit unsigned integer array to the message.
+ *
+ * This function only exists if #DBUS_HAVE_INT64 is defined.
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param value the array
+ * @param len the length of the array
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_uint64_array (DBusMessageIter *iter,
+ const dbus_uint64_t *value,
+ int len)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
+
+ if (!append_array_type (real, DBUS_TYPE_UINT64, NULL, NULL))
+ return FALSE;
+
+ if (!_dbus_marshal_uint64_array (&real->message->body, real->message->byte_order, value, len))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ dbus_message_iter_append_done (real);
+
+ return TRUE;
+}
+#endif /* DBUS_HAVE_INT64 */
+
+/**
+ * Appends a double array to the message.
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param value the array
+ * @param len the length of the array
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_double_array (DBusMessageIter *iter,
+ const double *value,
+ int len)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
+
+ if (!append_array_type (real, DBUS_TYPE_DOUBLE, NULL, NULL))
+ return FALSE;
+
+ if (!_dbus_marshal_double_array (&real->message->body, real->message->byte_order, value, len))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ dbus_message_iter_append_done (real);
+
+ return TRUE;
+}
+
+/**
+ * Appends a byte array to the message.
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param value the array
+ * @param len the length of the array
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_byte_array (DBusMessageIter *iter,
+ unsigned const char *value,
+ int len)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
+
+ if (!append_array_type (real, DBUS_TYPE_BYTE, NULL, NULL))
+ return FALSE;
+
+ if (!_dbus_marshal_byte_array (&real->message->body, real->message->byte_order, value, len))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ dbus_message_iter_append_done (real);
+
+ return TRUE;
+}
+
+/**
+ * Appends a string array to the message.
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param value the array
+ * @param len the length of the array
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_string_array (DBusMessageIter *iter,
+ const char **value,
+ int len)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
+
+ if (!append_array_type (real, DBUS_TYPE_STRING, NULL, NULL))
+ return FALSE;
+
+ if (!_dbus_marshal_string_array (&real->message->body, real->message->byte_order, value, len))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ dbus_message_iter_append_done (real);
+
+ return TRUE;
+}
+
+/**
+ * Sets the message sender.
+ *
+ * @param message the message
+ * @param sender the sender
+ * @returns #FALSE if not enough memory
+ */
+dbus_bool_t
+dbus_message_set_sender (DBusMessage *message,
+ const char *sender)
+{
+ _dbus_return_val_if_fail (message != NULL, FALSE);
+ _dbus_return_val_if_fail (!message->locked, FALSE);
+
+ if (sender == NULL)
+ {
+ delete_field (message, DBUS_HEADER_FIELD_SENDER_SERVICE);
+ return TRUE;
+ }
+ else
+ {
+ return set_string_field (message,
+ DBUS_HEADER_FIELD_SENDER_SERVICE,
+ DBUS_TYPE_STRING,
+ sender);
+ }
+}
+
+/**
+ * Sets a flag indicating that the message does not want a reply; if
+ * this flag is set, the other end of the connection may (but is not
+ * required to) optimize by not sending method return or error
+ * replies. If this flag is set, there is no way to know whether the
+ * message successfully arrived at the remote end.
+ *
+ * @param message the message
+ * @param no_reply #TRUE if no reply is desired
+ */
+void
+dbus_message_set_no_reply (DBusMessage *message,
+ dbus_bool_t no_reply)
+{
+ char *header;
+
+ _dbus_return_if_fail (message != NULL);
+ _dbus_return_if_fail (!message->locked);
+
+ header = _dbus_string_get_data_len (&message->header, FLAGS_OFFSET, 1);
+
+ if (no_reply)
+ *header |= DBUS_HEADER_FLAG_NO_REPLY_EXPECTED;
+ else
+ *header &= ~DBUS_HEADER_FLAG_NO_REPLY_EXPECTED;
+}
+
+/**
+ * Returns #TRUE if the message does not expect
+ * a reply.
+ *
+ * @param message the message
+ * @returns #TRUE if the message sender isn't waiting for a reply
+ */
+dbus_bool_t
+dbus_message_get_no_reply (DBusMessage *message)
+{
+ const char *header;
+
+ _dbus_return_val_if_fail (message != NULL, FALSE);
+
+ header = _dbus_string_get_const_data_len (&message->header, FLAGS_OFFSET, 1);
+
+ return (*header & DBUS_HEADER_FLAG_NO_REPLY_EXPECTED) != 0;
+}
+
+/**
+ * Gets the service which originated this message,
+ * or #NULL if unknown or inapplicable.
+ *
+ * @param message the message