+++ /dev/null
-/* -*- mode: C; c-file-style: "gnu" -*- */
-/* dbus-dict.h Dict object for key-value data.
- *
- * Copyright (C) 2003 CodeFactory AB
- *
- * Licensed under the Academic Free License version 1.2
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-#include "dbus-dict.h"
-#include "dbus-hash.h"
-#include "dbus-internals.h"
-#include "dbus-protocol.h"
-
-/**
- * @defgroup DBusDict DBusDict
- * @ingroup DBus
- * @brief key/value data structure.
- *
- * A DBusDict is a data structure that can store and lookup different
- * values by name.
- *
- * @{
- */
-
-struct DBusDict
-{
- int refcount;
-
- DBusHashTable *table;
-};
-
-typedef struct
-{
- int type;
- union {
- dbus_bool_t boolean_value;
- dbus_int32_t int32_value;
- dbus_uint32_t uint32_value;
- double double_value;
- char *string_value;
- struct {
- unsigned char *value;
- int len;
- } byte_array;
- struct {
- dbus_int32_t *value;
- int len;
- } int32_array;
- struct {
- dbus_uint32_t *value;
- int len;
- } uint32_array;
- struct {
- double *value;
- int len;
- } double_array;
- struct {
- char **value;
- int len;
- } string_array;
- } v;
-} DBusDictEntry;
-
-static void
-dbus_dict_entry_free (DBusDictEntry *entry)
-{
- if (!entry)
- return;
-
- switch (entry->type)
- {
- case DBUS_TYPE_INVALID:
- case DBUS_TYPE_BOOLEAN:
- case DBUS_TYPE_INT32:
- case DBUS_TYPE_UINT32:
- case DBUS_TYPE_DOUBLE:
- break;
- case DBUS_TYPE_STRING:
- dbus_free (entry->v.string_value);
- break;
- case DBUS_TYPE_BYTE_ARRAY:
- case DBUS_TYPE_BOOLEAN_ARRAY:
- dbus_free (entry->v.byte_array.value);
- break;
- case DBUS_TYPE_INT32_ARRAY:
- dbus_free (entry->v.int32_array.value);
- break;
- case DBUS_TYPE_UINT32_ARRAY:
- dbus_free (entry->v.uint32_array.value);
- break;
- case DBUS_TYPE_DOUBLE_ARRAY:
- dbus_free (entry->v.uint32_array.value);
- break;
- case DBUS_TYPE_STRING_ARRAY:
- dbus_free_string_array (entry->v.string_array.value);
- break;
- default:
- _dbus_assert_not_reached ("Unknown or invalid dict entry type\n");
- }
-
- dbus_free (entry);
-}
-
-/**
- * Constructs a new DBusDict. Returns #NULL if memory can't be
- * allocated.
- *
- * @returns a new DBusDict or #NULL.
- */
-DBusDict *
-dbus_dict_new (void)
-{
- DBusDict *dict;
-
- dict = dbus_new0 (DBusDict, 1);
-
- if (!dict)
- return NULL;
-
- dict->table = _dbus_hash_table_new (DBUS_HASH_STRING, dbus_free, (DBusFreeFunction)dbus_dict_entry_free);
-
- if (!dict->table)
- {
- dbus_free (dict);
- return NULL;
- }
-
- dict->refcount = 1;
-
- return dict;
-}
-
-/**
- * Increments the reference count of a DBusDict.
- *
- * @param dict the dict.
- * @see dbus_dict_unref
- */
-void
-dbus_dict_ref (DBusDict *dict)
-{
- dict->refcount += 1;
-
- _dbus_assert (dict->refcount > 1);
-}
-
-/**
- * Decrements the reference count of a DBusDict
- *
- * @param dict the dict
- * @see dbus_dict_ref
- */
-void
-dbus_dict_unref (DBusDict *dict)
-{
- dict->refcount -= 1;
-
- _dbus_assert (dict->refcount >= 0);
-
- if (dict->refcount == 0)
- {
- _dbus_hash_table_unref (dict->table);
- dbus_free (dict);
- }
-}
-
-/**
- * Checks if the dict contains the specified key.
- *
- * @param dict the dict.
- * @param key the key
- * @returns #TRUE if the dict contains the specified key.
- */
-dbus_bool_t
-dbus_dict_contains (DBusDict *dict,
- const char *key)
-{
- return (_dbus_hash_table_lookup_string (dict->table, key) != NULL);
-}
-
-/**
- * Removes the dict entry for the given key. If no dict entry for the
- * key exists, this function does nothing.
- *
- * @param dict the dict
- * @param key the key
- * @returns #TRUE if the entry existed
- */
-dbus_bool_t
-dbus_dict_remove (DBusDict *dict,
- const char *key)
-{
- return _dbus_hash_table_remove_string (dict->table, key);
-}
-
-/**
- * Returns the type of the value in the dict entry specified by the key.
- *
- * @param dict the dict
- * @param key the key
- * @returns the value type or DBUS_TYPE_NIL if the key wasn't found.
- */
-int
-dbus_dict_get_value_type (DBusDict *dict,
- const char *key)
-{
- DBusDictEntry *entry;
-
- entry = _dbus_hash_table_lookup_string (dict->table, key);
-
- if (!entry)
- return DBUS_TYPE_NIL;
- else
- return entry->type;
-}
-
-/**
- * Returns the keys in the dict as a string array.
- *
- * @param dict the dict
- * @param keys return location for string array
- * @param len return location for string array length
- * ®returns #TRUE on success
- */
-dbus_bool_t
-dbus_dict_get_keys (DBusDict *dict,
- char ***keys,
- int *len)
-{
- int size, i;
- char **tmp;
- char *key;
- DBusHashIter iter;
-
- size = _dbus_hash_table_get_n_entries (dict->table);
- *len = size;
-
- if (size == 0)
- {
- *keys = NULL;
- return TRUE;
- }
-
- tmp = dbus_new0 (char *, size + 1);
- if (!tmp)
- return FALSE;
-
-
- i = 0;
- _dbus_hash_iter_init (dict->table, &iter);
-
- while (_dbus_hash_iter_next (&iter))
- {
- key = _dbus_strdup (_dbus_hash_iter_get_string_key (&iter));
-
- if (!key)
- {
- dbus_free_string_array (tmp);
- return FALSE;
- }
-
- tmp[i] = key;
- i++;
- }
-
- *keys = tmp;
-
- return TRUE;
-}
-
-static dbus_bool_t
-insert_entry (DBusDict *dict,
- const char *key,
- DBusDictEntry **entry)
-{
- char *tmp;
-
- tmp = _dbus_strdup (key);
-
- if (!tmp)
- return FALSE;
-
- *entry = dbus_new0 (DBusDictEntry, 1);
-
- if (!*entry)
- {
- dbus_free (tmp);
- return FALSE;
- }
-
- if (!_dbus_hash_table_insert_string (dict->table, tmp, *entry))
- {
- dbus_free (tmp);
- dbus_dict_entry_free (*entry);
-
- return FALSE;
- }
-
- return TRUE;
-}
-
-/**
- * Adds a boolean value to the dict. If a value with the same key
- * already exists, then it will be replaced by the new value.
- *
- * @param dict the dict
- * @param key the key
- * @param value the value
- * @returns #TRUE on success
- */
-dbus_bool_t
-dbus_dict_set_boolean (DBusDict *dict,
- const char *key,
- dbus_bool_t value)
-{
- DBusDictEntry *entry;
-
- if (insert_entry (dict, key, &entry))
- {
- entry->type = DBUS_TYPE_BOOLEAN;
- entry->v.boolean_value = value;
-
- return TRUE;
- }
- else
- return FALSE;
-}
-
-/**
- * Adds a 32 bit signed integer value to the dict. If a value with the
- * same key already exists, then it will be replaced by the new value.
- *
- * @param dict the dict
- * @param key the key
- * @param value the value
- * @returns #TRUE on success
- */
-dbus_bool_t
-dbus_dict_set_int32 (DBusDict *dict,
- const char *key,
- dbus_int32_t value)
-{
- DBusDictEntry *entry;
-
- if (insert_entry (dict, key, &entry))
- {
- entry->type = DBUS_TYPE_INT32;
- entry->v.int32_value = value;
-
- return TRUE;
- }
- else
- return FALSE;
-}
-
-/**
- * Adds a 32 bit unsigned integer value to the dict. If a value with
- * the same key already exists, then it will be replaced by the new
- * value.
- *
- * @param dict the dict
- * @param key the key
- * @param value the value
- * @returns #TRUE on success
- */
-dbus_bool_t
-dbus_dict_set_uint32 (DBusDict *dict,
- const char *key,
- dbus_uint32_t value)
-{
- DBusDictEntry *entry;
-
- if (insert_entry (dict, key, &entry))
- {
- entry->type = DBUS_TYPE_UINT32;
- entry->v.uint32_value = value;
-
- return TRUE;
- }
- else
- return FALSE;
-}
-
-/**
- * Adds a 32 bit double value to the dict. If a value with the same
- * key already exists, then it will be replaced by the new value.
- *
- * @param dict the dict
- * @param key the key
- * @param value the value
- * @returns #TRUE on success
- */
-dbus_bool_t
-dbus_dict_set_double (DBusDict *dict,
- const char *key,
- double value)
-{
- DBusDictEntry *entry;
-
- if (insert_entry (dict, key, &entry))
- {
- entry->type = DBUS_TYPE_DOUBLE;
- entry->v.double_value = value;
-
- return TRUE;
- }
- else
- return FALSE;
-}
-
-/**
- * Adds a string to the dict. If a value with the same key already
- * exists, then it will be replaced by the new value.
- *
- * @param dict the dict
- * @param key the key
- * @param value the value
- * @returns #TRUE on success
- */
-dbus_bool_t
-dbus_dict_set_string (DBusDict *dict,
- const char *key,
- const char *value)
-{
- DBusDictEntry *entry;
- char *tmp;
-
- tmp = _dbus_strdup (value);
-
- if (!tmp)
- return FALSE;
-
- if (insert_entry (dict, key, &entry))
- {
- entry->type = DBUS_TYPE_STRING;
- entry->v.string_value = tmp;
-
- return TRUE;
- }
- else
- return FALSE;
-}
-
-/**
- * Adds a boolean array to the dict. If a value with the same key
- * already exists, then it will be replaced by the new value.
- *
- * @param dict the dict
- * @param key the key
- * @param value the value
- * @param len the array length
- * @returns #TRUE on success
- */
-dbus_bool_t
-dbus_dict_set_boolean_array (DBusDict *dict,
- const char *key,
- unsigned const char *value,
- int len)
-{
- DBusDictEntry *entry;
- unsigned char *tmp;
-
- if (len == 0)
- tmp = NULL;
- else
- {
- tmp = dbus_malloc (len);
-
- if (!tmp)
- return FALSE;
-
- memcpy (tmp, value, len);
- }
-
- if (insert_entry (dict, key, &entry))
- {
- entry->type = DBUS_TYPE_BOOLEAN_ARRAY;
- entry->v.byte_array.value = tmp;
- entry->v.byte_array.len = len;
-
- return TRUE;
- }
- else
- return FALSE;
-}
-
-/**
- * Adds a 32 bit signed integer array to the dict. If a value with the
- * same key already exists, then it will be replaced by the new value.
- *
- * @param dict the dict
- * @param key the key
- * @param value the value
- * @param len the array length
- * @returns #TRUE on success
- */
-dbus_bool_t
-dbus_dict_set_int32_array (DBusDict *dict,
- const char *key,
- const dbus_int32_t *value,
- int len)
-{
- DBusDictEntry *entry;
- dbus_int32_t *tmp;
-
- if (len == 0)
- tmp = NULL;
- else
- {
- tmp = dbus_new (dbus_int32_t, len);
-
- if (!tmp)
- return FALSE;
- }
-
- memcpy (tmp, value, len * sizeof (dbus_int32_t));
-
- if (insert_entry (dict, key, &entry))
- {
- entry->type = DBUS_TYPE_INT32_ARRAY;
- entry->v.int32_array.value = tmp;
- entry->v.int32_array.len = len;
-
- return TRUE;
- }
- else
- return FALSE;
-}
-
-/**
- * Adds a 32 bit unsigned integer array to the dict. If a value with
- * the same key already exists, then it will be replaced by the new
- * value.
- *
- * @param dict the dict
- * @param key the key
- * @param value the value
- * @param len the array length
- * @returns #TRUE on success
- */
-dbus_bool_t
-dbus_dict_set_uint32_array (DBusDict *dict,
- const char *key,
- const dbus_uint32_t *value,
- int len)
-{
- DBusDictEntry *entry;
- dbus_uint32_t *tmp;
-
- if (len == 0)
- tmp = NULL;
- else
- {
- tmp = dbus_new (dbus_uint32_t, len);
-
- if (!tmp)
- return FALSE;
-
- memcpy (tmp, value, len * sizeof (dbus_uint32_t));
- }
-
- if (insert_entry (dict, key, &entry))
- {
- entry->type = DBUS_TYPE_UINT32_ARRAY;
- entry->v.uint32_array.value = tmp;
- entry->v.int32_array.len = len;
-
- return TRUE;
- }
- else
- return FALSE;
-}
-
-/**
- * Adds a double array to the dict. If a value with the same key
- * already exists, then it will be replaced by the new value.
- *
- * @param dict the dict
- * @param key the key
- * @param value the value
- * @param len the array length
- * @returns #TRUE on success
- */
-dbus_bool_t
-dbus_dict_set_double_array (DBusDict *dict,
- const char *key,
- const double *value,
- int len)
-{
- DBusDictEntry *entry;
- double *tmp;
-
- if (len == 0)
- tmp = NULL;
- else
- {
- tmp = dbus_new (double, len);
-
- if (!tmp)
- return FALSE;
-
- memcpy (tmp, value, len * sizeof (double));
- }
-
- if (insert_entry (dict, key, &entry))
- {
- entry->type = DBUS_TYPE_DOUBLE_ARRAY;
- entry->v.double_array.value = tmp;
- entry->v.double_array.len = len;
-
- return TRUE;
- }
- else
- return FALSE;
-}
-
-/**
- * Adds a byte array to the dict. If a value with the same key
- * already exists, then it will be replaced by the new value.
- *
- * @param dict the dict
- * @param key the key
- * @param value the value
- * @param len the array length
- * @returns #TRUE on success
- */
-dbus_bool_t
-dbus_dict_set_byte_array (DBusDict *dict,
- const char *key,
- unsigned const char *value,
- int len)
-{
- DBusDictEntry *entry;
- unsigned char *tmp;
-
- if (len == 0)
- tmp = NULL;
- else
- {
- tmp = dbus_malloc (len);
-
- if (!tmp)
- return FALSE;
-
- memcpy (tmp, value, len);
- }
-
- if (insert_entry (dict, key, &entry))
- {
- entry->type = DBUS_TYPE_BYTE_ARRAY;
- entry->v.byte_array.value = tmp;
- entry->v.byte_array.len = len;
-
- return TRUE;
- }
- else
- return FALSE;
-}
-
-
-/**
- * Adds a string array to the dict. If a value with the same key
- * already exists, then it will be replaced by the new value.
- *
- * @param dict the dict
- * @param key the key
- * @param value the value
- * @param len the array length
- * @returns #TRUE on success
- */
-dbus_bool_t
-dbus_dict_set_string_array (DBusDict *dict,
- const char *key,
- const char **value,
- int len)
-{
- DBusDictEntry *entry;
- char **tmp;
- int i;
-
- tmp = dbus_new0 (char *, len + 1);
- if (!tmp)
- return FALSE;
-
- tmp[len] = NULL;
-
- for (i = 0; i < len; i++)
- {
- tmp[i] = _dbus_strdup (value[i]);
- if (!tmp[i])
- {
- dbus_free_string_array (tmp);
- return FALSE;
- }
- }
-
- if (insert_entry (dict, key, &entry))
- {
- entry->type = DBUS_TYPE_STRING_ARRAY;
- entry->v.string_array.value = tmp;
- entry->v.string_array.len = len;
-
- return TRUE;
- }
- else
- return FALSE;
-}
-
-/**
- * Gets a boolean value from a dict using a key.
- *
- * @param dict the dict
- * @param key the key
- * @param value return location for the value
- * @returns #TRUE if the key exists and the value is of the correct
- * type
- */
-dbus_bool_t
-dbus_dict_get_boolean (DBusDict *dict,
- const char *key,
- dbus_bool_t *value)
-{
- DBusDictEntry *entry;
-
- entry = _dbus_hash_table_lookup_string (dict->table, key);
-
- if (!entry || entry->type != DBUS_TYPE_BOOLEAN)
- return FALSE;
-
- *value = entry->v.boolean_value;
-
- return TRUE;
-}
-
-/**
- * Gets a 32 bit signed integer value from a dict using a key.
- *
- * @param dict the dict
- * @param key the key
- * @param value return location for the value
- * @returns #TRUE if the key exists and the value is of the correct
- * type
- */
-dbus_bool_t
-dbus_dict_get_int32 (DBusDict *dict,
- const char *key,
- dbus_int32_t *value)
-{
- DBusDictEntry *entry;
-
- entry = _dbus_hash_table_lookup_string (dict->table, key);
-
- if (!entry || entry->type != DBUS_TYPE_INT32)
- return FALSE;
-
- *value = entry->v.int32_value;
-
- return TRUE;
-}
-
-/**
- * Gets a 32 bit unsigned integer value from a dict using a key.
- *
- * @param dict the dict
- * @param key the key
- * @param value return location for the value
- * @returns #TRUE if the key exists and the value is of the correct
- * type
- */
-dbus_bool_t
-dbus_dict_get_uint32 (DBusDict *dict,
- const char *key,
- dbus_uint32_t *value)
-{
- DBusDictEntry *entry;
-
- entry = _dbus_hash_table_lookup_string (dict->table, key);
-
- if (!entry || entry->type != DBUS_TYPE_UINT32)
- return FALSE;
-
- *value = entry->v.uint32_value;
-
- return TRUE;
-}
-
-/**
- * Gets a double value from a dict using a key.
- *
- * @param dict the dict
- * @param key the key
- * @param value return location for the value
- * @returns #TRUE if the key exists and the value is of the correct
- * type
- */
-dbus_bool_t
-dbus_dict_get_double (DBusDict *dict,
- const char *key,
- double *value)
-{
- DBusDictEntry *entry;
-
- entry = _dbus_hash_table_lookup_string (dict->table, key);
-
- if (!entry || entry->type != DBUS_TYPE_DOUBLE)
- return FALSE;
-
- *value = entry->v.double_value;
-
- return TRUE;
-}
-
-/**
- * Gets a string from a dict using a key.
- *
- * @param dict the dict
- * @param key the key
- * @param value return location for the value
- * @returns #TRUE if the key exists and the value is of the correct
- * type
- */
-dbus_bool_t
-dbus_dict_get_string (DBusDict *dict,
- const char *key,
- const char **value)
-{
- DBusDictEntry *entry;
-
- entry = _dbus_hash_table_lookup_string (dict->table, key);
-
- if (!entry || entry->type != DBUS_TYPE_STRING)
- return FALSE;
-
- *value = entry->v.string_value;
-
- return TRUE;
-}
-
-/**
- * Gets a boolean array from a dict using a key.
- *
- * @param dict the dict
- * @param key the key
- * @param value return location for the value
- * @param len return location for the array length
- * @returns #TRUE if the key exists and the value is of the correct
- * type
- */
-dbus_bool_t
-dbus_dict_get_boolean_array (DBusDict *dict,
- const char *key,
- unsigned const char **value,
- int *len)
-{
- DBusDictEntry *entry;
-
- entry = _dbus_hash_table_lookup_string (dict->table, key);
-
- if (!entry || entry->type != DBUS_TYPE_BOOLEAN_ARRAY)
- return FALSE;
-
- *value = entry->v.byte_array.value;
- *len = entry->v.byte_array.len;
-
- return TRUE;
-}
-
-/**
- * Gets a 32 bit signed integer array from a dict using a key.
- *
- * @param dict the dict
- * @param key the key
- * @param value return location for the value
- * @param len return location for the array length
- * @returns #TRUE if the key exists and the value is of the correct
- * type
- */
-dbus_bool_t
-dbus_dict_get_int32_array (DBusDict *dict,
- const char *key,
- const dbus_int32_t **value,
- int *len)
-{
- DBusDictEntry *entry;
-
- entry = _dbus_hash_table_lookup_string (dict->table, key);
-
- if (!entry || entry->type != DBUS_TYPE_INT32_ARRAY)
- return FALSE;
-
- *value = entry->v.int32_array.value;
- *len = entry->v.int32_array.len;
-
- return TRUE;
-}
-
-/**
- * Gets a 32 bit unsigned integer array from a dict using a key.
- *
- * @param dict the dict
- * @param key the key
- * @param value return location for the value
- * @param len return location for the array length
- * @returns #TRUE if the key exists and the value is of the correct
- * type
- */
-dbus_bool_t
-dbus_dict_get_uint32_array (DBusDict *dict,
- const char *key,
- const dbus_uint32_t **value,
- int *len)
-{
- DBusDictEntry *entry;
-
- entry = _dbus_hash_table_lookup_string (dict->table, key);
-
- if (!entry || entry->type != DBUS_TYPE_UINT32_ARRAY)
- return FALSE;
-
- *value = entry->v.uint32_array.value;
- *len = entry->v.uint32_array.len;
-
- return TRUE;
-}
-
-/**
- * Gets a double array from a dict using a key.
- *
- * @param dict the dict
- * @param key the key
- * @param value return location for the value
- * @param len return location for the array length
- * @returns #TRUE if the key exists and the value is of the correct
- * type
- */
-dbus_bool_t
-dbus_dict_get_double_array (DBusDict *dict,
- const char *key,
- const double **value,
- int *len)
-{
- DBusDictEntry *entry;
-
- entry = _dbus_hash_table_lookup_string (dict->table, key);
-
- if (!entry || entry->type != DBUS_TYPE_DOUBLE_ARRAY)
- return FALSE;
-
- *value = entry->v.double_array.value;
- *len = entry->v.double_array.len;
-
- return TRUE;
-}
-
-/**
- * Gets a byte array from a dict using a key.
- *
- * @param dict the dict
- * @param key the key
- * @param value return location for the value
- * @param len return location for the array length
- * @returns #TRUE if the key exists and the value is of the correct
- * type
- */
-dbus_bool_t
-dbus_dict_get_byte_array (DBusDict *dict,
- const char *key,
- unsigned const char **value,
- int *len)
-{
- DBusDictEntry *entry;
-
- entry = _dbus_hash_table_lookup_string (dict->table, key);
-
- if (!entry || entry->type != DBUS_TYPE_BYTE_ARRAY)
- return FALSE;
-
- *value = entry->v.byte_array.value;
- *len = entry->v.byte_array.len;
-
- return TRUE;
-}
-
-/**
- * Gets a string array from a dict using a key.
- *
- * @param dict the dict
- * @param key the key
- * @param value return location for the value
- * @param len return location for the array length
- * @returns #TRUE if the key exists and the value is of the correct
- * type
- */
-dbus_bool_t
-dbus_dict_get_string_array (DBusDict *dict,
- const char *key,
- const char ***value,
- int *len)
-{
- DBusDictEntry *entry;
-
- entry = _dbus_hash_table_lookup_string (dict->table, key);
-
- if (!entry || entry->type != DBUS_TYPE_STRING_ARRAY)
- return FALSE;
-
- *value = (const char **)entry->v.string_array.value;
- *len = entry->v.string_array.len;
-
- return TRUE;
-}
-
-/** @} */
-
-#ifdef DBUS_BUILD_TESTS
-#include "dbus-test.h"
-
-dbus_bool_t
-_dbus_dict_test (void)
-{
- DBusDict *dict;
- dbus_bool_t our_bool;
- dbus_int32_t our_int;
- dbus_uint32_t our_uint;
- double our_double;
- const char *our_string;
- const unsigned char boolean_array[] = { TRUE, FALSE, FALSE, TRUE };
- const unsigned char *our_boolean_array;
- const dbus_int32_t int32_array[] = { 0x12345678, -1911, 0, 0xaffe, 0xedd1e };
- const dbus_int32_t *our_int32_array;
- const dbus_uint32_t uint32_array[] = { 0x12345678, 0, 0xdeadbeef, 0x87654321, 0xffffffff };
- const dbus_uint32_t *our_uint32_array;
- const double double_array[] = { 3.14159, 1.2345, 6.7890 };
- const double *our_double_array;
- const char *string_array[] = { "This", "Is", "A", "Test" };
- const char **our_string_array;
- int i, len;
-
- /* We don't test much here since the hash table tests cover a great
- deal of the functionality. */
-
- dict = dbus_dict_new ();
-
- if (dbus_dict_get_value_type (dict, "foo") != DBUS_TYPE_NIL)
- _dbus_assert_not_reached ("didn't return DBUS_TYPE_NIL for non-existant entry");
-
- if (!dbus_dict_set_boolean (dict, "boolean", TRUE))
- _dbus_assert_not_reached ("could not add boolean value");
-
- if (!dbus_dict_get_boolean (dict, "boolean", &our_bool) ||
- !our_bool)
- _dbus_assert_not_reached ("could not get boolean value");
-
- if (!dbus_dict_set_int32 (dict, "int32", 0x12345678))
- _dbus_assert_not_reached ("could not add int32 value");
-
- if (!dbus_dict_get_int32 (dict, "int32", &our_int) || our_int != 0x12345678)
- _dbus_assert_not_reached ("could not get int32 value or int32 values differ");
-
- if (!dbus_dict_set_uint32 (dict, "uint32", 0x87654321))
- _dbus_assert_not_reached ("could not add uint32 value");
-
- if (!dbus_dict_get_uint32 (dict, "uint32", &our_uint) || our_uint != 0x87654321)
- _dbus_assert_not_reached ("could not get uint32 value or uint32 values differ");
-
- if (!dbus_dict_set_double (dict, "double", 3.14159))
- _dbus_assert_not_reached ("could not add double value");
-
- if (!dbus_dict_get_double (dict, "double", &our_double) || our_double != 3.14159)
- _dbus_assert_not_reached ("could not get double value or double values differ");
-
- if (!dbus_dict_set_string (dict, "string", "test string"))
- _dbus_assert_not_reached ("could not add string value");
-
- if (!dbus_dict_get_string (dict, "string", &our_string) || strcmp (our_string, "test string") != 0)
- _dbus_assert_not_reached ("could not get string value or string values differ");
-
- if (!dbus_dict_set_boolean_array (dict, "boolean_array", boolean_array, 4))
- _dbus_assert_not_reached ("could not add boolean array");
-
- if (!dbus_dict_get_boolean_array (dict, "boolean_array", &our_boolean_array, &len) ||
- len != 4 || memcmp (boolean_array, our_boolean_array, 4) != 0)
- _dbus_assert_not_reached ("could not get boolean array value or boolean array values differ");
-
- if (!dbus_dict_set_int32_array (dict, "int32_array", int32_array, 5))
- _dbus_assert_not_reached ("could not add int32 array");
-
- if (!dbus_dict_get_int32_array (dict, "int32_array", &our_int32_array, &len) ||
- len != 5 || memcmp (int32_array, our_int32_array, 5 * sizeof (dbus_int32_t)) != 0)
- _dbus_assert_not_reached ("could not get int32 array value or int32 array values differ");
-
- if (!dbus_dict_set_uint32_array (dict, "uint32_array", uint32_array, 5))
- _dbus_assert_not_reached ("could not add uint32 array");
-
- if (!dbus_dict_get_uint32_array (dict, "uint32_array", &our_uint32_array, &len) ||
- len != 5 || memcmp (uint32_array, our_uint32_array, 5 * sizeof (dbus_uint32_t) ) != 0)
- _dbus_assert_not_reached ("could not get uint32 array value or uint32 array values differ");
-
- if (!dbus_dict_set_double_array (dict, "double_array", double_array, 3))
- _dbus_assert_not_reached ("could not add double array");
-
- if (!dbus_dict_get_double_array (dict, "double_array", &our_double_array, &len) ||
- len != 3 || memcmp (double_array, our_double_array, 3 * sizeof (double)) != 0)
- _dbus_assert_not_reached ("could not get double array value or double array values differ");
-
- if (!dbus_dict_set_string_array (dict, "string_array", string_array, 4))
- _dbus_assert_not_reached ("could not add string array");
-
- if (!dbus_dict_get_string_array (dict, "string_array", &our_string_array, &len))
- _dbus_assert_not_reached ("could not get string array value");
-
- if (len != 4)
- _dbus_assert_not_reached ("string array lengths differ");
-
- for (i = 0; i < len; i++)
- {
- if (strcmp (our_string_array[i], string_array[i]) != 0)
- _dbus_assert_not_reached ("string array fields differ");
- }
-
- dbus_dict_unref (dict);
-
- return TRUE;
-}
-#endif /* DBUS_BUILD_TESTS */
/**
* Marshals a UTF-8 string
*
+ * @todo: If the string append fails we need to restore
+ * the old length. (also for other marshallers)
+ *
* @param str the string to append the marshalled value to
* @param byte_order the byte order to use
* @param value the string
old_string_len = _dbus_string_get_length (str);
- if (!_dbus_marshal_uint32 (str, byte_order, len))
+ if (!_dbus_marshal_uint32 (str, byte_order, len * sizeof (dbus_int32_t)))
goto error;
for (i = 0; i < len; i++)
old_string_len = _dbus_string_get_length (str);
- if (!_dbus_marshal_uint32 (str, byte_order, len))
+ if (!_dbus_marshal_uint32 (str, byte_order, len * sizeof (dbus_uint32_t)))
goto error;
for (i = 0; i < len; i++)
const double *value,
int len)
{
- int i, old_string_len;
+ int i, old_string_len, array_start;
old_string_len = _dbus_string_get_length (str);
- if (!_dbus_marshal_uint32 (str, byte_order, len))
+ /* Set the length to 0 temporarily */
+ if (!_dbus_marshal_uint32 (str, byte_order, 0))
goto error;
-
+
+ array_start = _dbus_string_get_length (str);
+
for (i = 0; i < len; i++)
if (!_dbus_marshal_double (str, byte_order, value[i]))
goto error;
+ /* Write the length now that we know it */
+ _dbus_marshal_set_uint32 (str, byte_order,
+ _DBUS_ALIGN_VALUE (old_string_len, sizeof(dbus_uint32_t)),
+ _dbus_string_get_length (str) - array_start);
+
return TRUE;
error:
const char **value,
int len)
{
- int i, old_string_len;
+ int i, old_string_len, array_start;
old_string_len = _dbus_string_get_length (str);
- if (!_dbus_marshal_uint32 (str, byte_order, len))
+ /* Set the length to 0 temporarily */
+ if (!_dbus_marshal_uint32 (str, byte_order, 0))
goto error;
+ array_start = _dbus_string_get_length (str);
+
for (i = 0; i < len; i++)
if (!_dbus_marshal_string (str, byte_order, value[i]))
goto error;
+ /* Write the length now that we know it */
+ _dbus_marshal_set_uint32 (str, byte_order,
+ _DBUS_ALIGN_VALUE (old_string_len, sizeof(dbus_uint32_t)),
+ _dbus_string_get_length (str) - array_start);
+
return TRUE;
error:
}
-/**
- * Marshals a dict
- * @param str the string to append the marshalled value to
- * @param byte_order the byte order to use
- * @param dict the dict
- * @returns #TRUE on success
- */
-dbus_bool_t
-_dbus_marshal_dict (DBusString *str,
- int byte_order,
- DBusDict *dict)
-{
- int old_string_len;
- int i, len;
- char **keys;
-
- old_string_len = _dbus_string_get_length (str);
-
- if (!dbus_dict_get_keys (dict, &keys, &len))
- goto error;
-
- if (len == 0)
- return TRUE;
-
- if (!_dbus_marshal_string_array (str, byte_order,
- (const char **)keys, len))
- goto error;
-
- for (i = 0; i < len; i++)
- {
- int value_type;
-
- value_type = dbus_dict_get_value_type (dict, keys[i]);
-
- if (!_dbus_string_append_byte (str, value_type))
- goto error;
-
- switch (dbus_dict_get_value_type (dict, keys[i]))
- {
- case DBUS_TYPE_BOOLEAN:
- {
- dbus_bool_t value;
-
- if (!dbus_dict_get_boolean (dict, keys[i], &value))
- goto error;
-
- if (!_dbus_string_append_byte (str, (value != FALSE)))
- goto error;
-
- break;
- }
-
- case DBUS_TYPE_INT32:
- {
- dbus_int32_t value;
-
- if (!dbus_dict_get_int32 (dict, keys[i], &value))
- goto error;
-
- if (!_dbus_marshal_int32 (str, byte_order, value))
- goto error;
-
- break;
- }
- case DBUS_TYPE_UINT32:
- {
- dbus_uint32_t value;
-
- if (!dbus_dict_get_uint32 (dict, keys[i], &value))
- goto error;
-
- if (!_dbus_marshal_uint32 (str, byte_order, value))
- goto error;
-
- break;
- }
- case DBUS_TYPE_DOUBLE:
- {
- double value;
-
- if (!dbus_dict_get_double (dict, keys[i], &value))
- goto error;
-
- if (!_dbus_marshal_double (str, byte_order, value))
- goto error;
-
- break;
- }
- case DBUS_TYPE_INT32_ARRAY:
- {
- const dbus_int32_t *value;
- int len;
-
- if (!dbus_dict_get_int32_array (dict, keys[i], &value, &len))
- goto error;
-
- if (!_dbus_marshal_int32_array (str, byte_order, value, len))
- goto error;
-
- break;
- }
- case DBUS_TYPE_STRING:
- {
- const char *value;
-
- if (!dbus_dict_get_string (dict, keys[i], &value))
- goto error;
-
- if (!_dbus_marshal_string (str, byte_order, value))
- goto error;
-
- break;
- }
- case DBUS_TYPE_BOOLEAN_ARRAY:
- {
- const unsigned char *value;
- int len;
-
- if (!dbus_dict_get_boolean_array (dict, keys[i], &value, &len))
- goto error;
-
- if (!_dbus_marshal_byte_array (str, byte_order, value, len))
- goto error;
-
- break;
- }
- case DBUS_TYPE_UINT32_ARRAY:
- {
- const dbus_uint32_t *value;
- int len;
-
- if (!dbus_dict_get_uint32_array (dict, keys[i], &value, &len))
- goto error;
-
- if (!_dbus_marshal_uint32_array (str, byte_order, value, len))
- goto error;
-
- break;
- }
- case DBUS_TYPE_DOUBLE_ARRAY:
- {
- const double *value;
- int len;
-
- if (!dbus_dict_get_double_array (dict, keys[i], &value, &len))
- goto error;
-
- if (!_dbus_marshal_double_array (str, byte_order, value, len))
- goto error;
-
- break;
- }
- case DBUS_TYPE_STRING_ARRAY:
- {
- const char **value;
- int len;
-
- if (!dbus_dict_get_string_array (dict, keys[i], &value, &len))
- goto error;
-
- if (!_dbus_marshal_string_array (str, byte_order, (const char **)value, len))
- goto error;
-
- break;
- }
- default:
- _dbus_warn ("unkown value type %d\n", dbus_dict_get_value_type (dict, keys[i]));
- _dbus_assert_not_reached ("unknown value type in dict");
- }
- }
-
- dbus_free_string_array (keys);
-
- return TRUE;
-
- error:
-
- dbus_free_string_array (keys);
-
- /* Restore previous length */
- _dbus_string_set_length (str, old_string_len);
-
- return FALSE;
-}
-
-
/**
* Demarshals a double.
*
if (!retval)
return NULL;
- data = _dbus_string_get_const_data_len (str, pos, len);
+ data = _dbus_string_get_const_data_len (str, pos, len + 1);
if (!data)
return NULL;
int len, i;
dbus_int32_t *retval;
- len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
+ len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos) / sizeof (dbus_int32_t);
if (len == 0)
{
int len, i;
dbus_uint32_t *retval;
- len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
+ len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos) / sizeof (dbus_uint32_t);
if (len == 0)
{
int len, i;
double *retval;
- len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
+ len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos) / sizeof (double);
if (len == 0)
{
return FALSE;
}
-/**
- * Demarshals a dict
- *
- * @param str the string containing the data
- * @param byte_order the byte order
- * @param pos the position in the string
- * @param new_pos the new position in the string
- * @param dict the dict
- * @returns #TRUE on success.
- */
-dbus_bool_t
-_dbus_demarshal_dict (const DBusString *str,
- int byte_order,
- int pos,
- int *new_pos,
- DBusDict **dict)
-{
- char **keys;
- int i, len;
-
- *dict = dbus_dict_new ();
- if (!*dict)
- return FALSE;
-
- if (!_dbus_demarshal_string_array (str, byte_order, pos, &pos, &keys, &len))
- goto error;
-
- for (i = 0; i < len; i++)
- {
- int value_type;
-
- switch ((value_type = _dbus_string_get_byte (str, pos ++)))
- {
- case DBUS_TYPE_BOOLEAN:
- {
- dbus_bool_t value;
-
- value = _dbus_string_get_byte (str, pos ++);
-
- if (!dbus_dict_set_boolean (*dict, keys[i], value))
- goto error;
- break;
- }
- case DBUS_TYPE_INT32:
- {
- dbus_int32_t value;
-
- value = _dbus_demarshal_int32 (str, byte_order, pos, &pos);
-
- if (!dbus_dict_set_int32 (*dict, keys[i], value))
- goto error;
-
- break;
- }
- case DBUS_TYPE_UINT32:
- {
- dbus_uint32_t value;
-
- value = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
-
- if (!dbus_dict_set_uint32 (*dict, keys[i], value))
- goto error;
-
- break;
- }
- case DBUS_TYPE_DOUBLE:
- {
- double value;
-
- value = _dbus_demarshal_double (str, byte_order, pos, &pos);
-
- if (!dbus_dict_set_double (*dict, keys[i], value))
- goto error;
-
- break;
- }
- case DBUS_TYPE_STRING:
- {
- char *value;
-
- value = _dbus_demarshal_string (str, byte_order, pos, &pos);
-
- if (!value)
- goto error;
-
- if (!dbus_dict_set_string (*dict, keys[i], value))
- {
- dbus_free (value);
- goto error;
- }
-
- dbus_free (value);
-
- break;
- }
- case DBUS_TYPE_BOOLEAN_ARRAY:
- {
- unsigned char *value;
- int len;
-
- if (!_dbus_demarshal_byte_array (str, byte_order, pos, &pos, &value, &len))
- goto error;
-
- if (!dbus_dict_set_boolean_array (*dict, keys[i], value, len))
- {
- dbus_free (value);
- goto error;
- }
-
- dbus_free (value);
- break;
- }
- case DBUS_TYPE_INT32_ARRAY:
- {
- dbus_int32_t *value;
- int len;
-
- if (!_dbus_demarshal_int32_array (str, byte_order, pos, &pos, &value, &len))
- goto error;
-
- if (!dbus_dict_set_int32_array (*dict, keys[i], value, len))
- {
- dbus_free (value);
- goto error;
- }
-
- dbus_free (value);
- break;
- }
- case DBUS_TYPE_UINT32_ARRAY:
- {
- dbus_uint32_t *value;
- int len;
-
- if (!_dbus_demarshal_uint32_array (str, byte_order, pos, &pos, &value, &len))
- goto error;
-
- if (!dbus_dict_set_uint32_array (*dict, keys[i], value, len))
- {
- dbus_free (value);
- goto error;
- }
-
- dbus_free (value);
- break;
- }
- case DBUS_TYPE_DOUBLE_ARRAY:
- {
- double *value;
- int len;
-
- if (!_dbus_demarshal_double_array (str, byte_order, pos, &pos, &value, &len))
- goto error;
-
- if (!dbus_dict_set_double_array (*dict, keys[i], value, len))
- {
- dbus_free (value);
- goto error;
- }
-
- dbus_free (value);
- break;
- }
- case DBUS_TYPE_BYTE_ARRAY:
- {
- unsigned char *value;
- int len;
-
- if (!_dbus_demarshal_byte_array (str, byte_order, pos, &pos, &value, &len))
- goto error;
-
- if (!dbus_dict_set_byte_array (*dict, keys[i], value, len))
- {
- dbus_free (value);
- goto error;
- }
-
- dbus_free (value);
- break;
- }
- case DBUS_TYPE_STRING_ARRAY:
- {
- char **value;
- int len;
-
- if (!_dbus_demarshal_string_array (str, byte_order, pos, &pos, &value, &len))
- goto error;
-
- if (!dbus_dict_set_string_array (*dict, keys[i], (const char **)value, len))
- {
- dbus_free_string_array (value);
- goto error;
- }
-
- dbus_free_string_array (value);
- break;
- }
- default:
- _dbus_warn ("unknown value type %d\n", value_type);
- _dbus_assert_not_reached ("unknown value arg");
- }
- }
-
- dbus_free_string_array (keys);
- return TRUE;
-
- error:
- dbus_free_string_array (keys);
- dbus_dict_unref (*dict);
-
- return FALSE;
-}
-
/**
* Returns the position right after the end of an argument. PERFORMS
* NO VALIDATION WHATSOEVER. The message must have been previously
*
* @param str a string
* @param byte_order the byte order to use
+ * @param type the type of the argument
* @param pos the pos where the arg starts
* @param end_pos pointer where the position right
* after the end position will follow
dbus_bool_t
_dbus_marshal_get_arg_end_pos (const DBusString *str,
int byte_order,
+ int type,
int pos,
int *end_pos)
{
- const char *data;
-
if (pos >= _dbus_string_get_length (str))
return FALSE;
- data = _dbus_string_get_const_data_len (str, pos, 1);
-
- switch (*data)
+ switch (type)
{
case DBUS_TYPE_INVALID:
return FALSE;
break;
case DBUS_TYPE_NIL:
- *end_pos = pos + 1;
+ *end_pos = pos;
break;
- case DBUS_TYPE_BOOLEAN:
- *end_pos = pos + 2;
+ case DBUS_TYPE_BYTE:
+ *end_pos = pos + 1;
break;
+ case DBUS_TYPE_BOOLEAN:
+ *end_pos = pos + 1;
+ break;
+
case DBUS_TYPE_INT32:
- *end_pos = _DBUS_ALIGN_VALUE (pos + 1, sizeof (dbus_int32_t)) + sizeof (dbus_int32_t);
+ *end_pos = _DBUS_ALIGN_VALUE (pos, sizeof (dbus_int32_t)) + sizeof (dbus_int32_t);
break;
case DBUS_TYPE_UINT32:
- *end_pos = _DBUS_ALIGN_VALUE (pos + 1, sizeof (dbus_uint32_t)) + sizeof (dbus_uint32_t);
+ *end_pos = _DBUS_ALIGN_VALUE (pos, sizeof (dbus_uint32_t)) + sizeof (dbus_uint32_t);
break;
case DBUS_TYPE_DOUBLE:
- *end_pos = _DBUS_ALIGN_VALUE (pos + 1, sizeof (double)) + sizeof (double);
+ *end_pos = _DBUS_ALIGN_VALUE (pos, sizeof (double)) + sizeof (double);
break;
case DBUS_TYPE_STRING:
{
int len;
-
+
/* Demarshal the length */
- len = _dbus_demarshal_uint32 (str, byte_order, pos + 1, &pos);
+ len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
*end_pos = pos + len + 1;
}
break;
- case DBUS_TYPE_BOOLEAN_ARRAY:
- case DBUS_TYPE_BYTE_ARRAY:
+ case DBUS_TYPE_NAMED:
{
int len;
-
- /* Demarshal the length */
- len = _dbus_demarshal_uint32 (str, byte_order, pos + 1, &pos);
- *end_pos = pos + len;
- }
- break;
+ /* Demarshal the string length */
+ len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
- case DBUS_TYPE_INT32_ARRAY:
- {
- int len, new_pos;
-
- /* Demarshal the length */
- len = _dbus_demarshal_uint32 (str, byte_order, pos + 1, &new_pos);
-
- *end_pos = _DBUS_ALIGN_VALUE (new_pos, sizeof (dbus_int32_t))
- + (len * sizeof (dbus_int32_t));
- }
- break;
-
- case DBUS_TYPE_UINT32_ARRAY:
- {
- int len, new_pos;
-
- /* Demarshal the length */
- len = _dbus_demarshal_uint32 (str, byte_order, pos + 1, &new_pos);
-
- *end_pos = _DBUS_ALIGN_VALUE (new_pos, sizeof (dbus_uint32_t))
- + (len * sizeof (dbus_uint32_t));
- }
- break;
-
- case DBUS_TYPE_DOUBLE_ARRAY:
- {
- int len, new_pos;
+ *end_pos = pos + len + 1;
- /* Demarshal the length */
- len = _dbus_demarshal_uint32 (str, byte_order, pos + 1, &new_pos);
+ /* Demarshal the data length */
+ len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
- *end_pos = _DBUS_ALIGN_VALUE (new_pos, sizeof (double))
- + (len * sizeof (double));
+ *end_pos = pos + len;
}
break;
- case DBUS_TYPE_STRING_ARRAY:
+ case DBUS_TYPE_ARRAY:
{
- int len, i;
-
- /* Demarshal the length */
- len = _dbus_demarshal_uint32 (str, byte_order, pos + 1, &pos);
-
- for (i = 0; i < len; i++)
- {
- int str_len;
-
- /* Demarshal string length */
- str_len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
- pos += str_len + 1;
- }
+ int len;
- *end_pos = pos;
+ /* Demarshal the length (element type is at pos + 0 */
+ len = _dbus_demarshal_uint32 (str, byte_order, pos + 1, &pos);
+
+ *end_pos = pos + len;
}
break;
case DBUS_TYPE_DICT:
{
- int len, i;
+ int len;
/* Demarshal the length */
- len = _dbus_demarshal_uint32 (str, byte_order, pos + 1, &pos);
-
- for (i = 0; i < len; i++)
- {
- int str_len;
-
- /* Demarshal string length */
- str_len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
- pos += str_len + 1;
- }
-
- /* Now check the values */
- for (i = 0; i < len; i++)
- {
- if (!_dbus_marshal_get_arg_end_pos (str, byte_order, pos, &pos))
- return FALSE;
- }
-
- *end_pos = pos;
+ len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
- break;
+ *end_pos = pos + len;
}
+ break;
+
default:
- _dbus_warn ("Unknown message arg type %d\n", *data);
+ _dbus_warn ("Unknown message arg type %d\n", type);
_dbus_assert_not_reached ("Unknown message argument type\n");
return FALSE;
}
len = _dbus_demarshal_uint32 (str, byte_order, align_4, new_pos);
- /* note that the len may be a number of doubles, so we need it to be
- * at least SIZE_T_MAX / 8, but make it smaller just to keep things
+ /* note that the len is the number of bytes, so we need it to be
+ * at least SIZE_T_MAX, but make it smaller just to keep things
* sane. We end up using ints for most sizes to avoid unsigned mess
* so limit to maximum 32-bit signed int divided by at least 8, more
* for a bit of paranoia margin. INT_MAX/32 is about 65 megabytes.
return TRUE;
}
+/**
+ * Validates and returns a typecode at a specific position
+ * in the message
+ *
+ * @param str a string
+ * @param type the type of the argument
+ * @param pos the pos where the typecode starts
+ * @param end_pos pointer where the position right
+ * after the end position will follow
+ * @returns #TRUE if the type is valid.
+ */
+dbus_bool_t
+_dbus_marshal_validate_type (const DBusString *str,
+ int pos,
+ int *type,
+ int *end_pos)
+{
+ const char *data;
+
+ if (pos >= _dbus_string_get_length (str))
+ return FALSE;
+
+ data = _dbus_string_get_const_data_len (str, pos, 1);
+
+ if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_LAST)
+ {
+ *type = *data;
+ *end_pos = pos + 1;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
/**
- * Validates an argument, checking that it is well-formed, for example
- * no ludicrous length fields, strings are nul-terminated, etc.
+ * Validates an argument of a specific type, checking that it
+ * is well-formed, for example no ludicrous length fields, strings
+ * are nul-terminated, etc.
* Returns the end position of the argument in end_pos, and
* returns #TRUE if a valid arg begins at "pos"
*
*
* @param str a string
* @param byte_order the byte order to use
- * @param pos the pos where the arg starts (offset of its typecode)
+ * @param type the type of the argument
+ * @param pos the pos where the arg starts
* @param end_pos pointer where the position right
* after the end position will follow
* @returns #TRUE if the arg is valid.
dbus_bool_t
_dbus_marshal_validate_arg (const DBusString *str,
int byte_order,
+ int type,
int pos,
int *end_pos)
{
- const char *data;
-
- if (pos >= _dbus_string_get_length (str))
+ if (pos > _dbus_string_get_length (str))
return FALSE;
- data = _dbus_string_get_const_data_len (str, pos, 1);
-
- switch (*data)
+ switch (type)
{
case DBUS_TYPE_INVALID:
return FALSE;
break;
case DBUS_TYPE_NIL:
- *end_pos = pos + 1;
+ *end_pos = pos;
break;
+ case DBUS_TYPE_BYTE:
+ if (1 > _dbus_string_get_length (str) - pos)
+ {
+ _dbus_verbose ("no room for boolean value\n");
+ return FALSE;
+ }
+
+ *end_pos = pos + 1;
+ break;
+
case DBUS_TYPE_BOOLEAN:
{
unsigned char c;
- if (2 > _dbus_string_get_length (str) - pos)
+ if (1 > _dbus_string_get_length (str) - pos)
{
_dbus_verbose ("no room for boolean value\n");
return FALSE;
}
- c = _dbus_string_get_byte (str, pos + 1);
+ c = _dbus_string_get_byte (str, pos);
if (c != 0 && c != 1)
{
return FALSE;
}
- *end_pos = pos + 2;
+ *end_pos = pos + 1;
break;
}
case DBUS_TYPE_INT32:
case DBUS_TYPE_UINT32:
{
- int align_4 = _DBUS_ALIGN_VALUE (pos + 1, 4);
+ int align_4 = _DBUS_ALIGN_VALUE (pos, 4);
- if (!_dbus_string_validate_nul (str, pos + 1,
- align_4 - pos - 1))
+ if (!_dbus_string_validate_nul (str, pos,
+ align_4 - pos))
{
_dbus_verbose ("int32/uint32 alignment padding not initialized to nul\n");
return FALSE;
case DBUS_TYPE_DOUBLE:
{
- int align_8 = _DBUS_ALIGN_VALUE (pos + 1, 8);
+ int align_8 = _DBUS_ALIGN_VALUE (pos, 8);
_dbus_verbose_bytes_of_string (str, pos, (align_8 + 8 - pos));
- if (!_dbus_string_validate_nul (str, pos + 1,
- align_8 - pos - 1))
+ if (!_dbus_string_validate_nul (str, pos,
+ align_8 - pos))
{
_dbus_verbose ("double alignment padding not initialized to nul\n");
return FALSE;
/* Demarshal the length, which does NOT include
* nul termination
*/
- len = demarshal_and_validate_len (str, byte_order, pos + 1, &pos);
+ len = demarshal_and_validate_len (str, byte_order, pos, &pos);
if (len < 0)
return FALSE;
}
break;
- case DBUS_TYPE_BOOLEAN_ARRAY:
+ case DBUS_TYPE_NAMED:
{
- int len, i;
+ int len;
- len = demarshal_and_validate_len (str, byte_order, pos + 1, &pos);
+ /* Demarshal the string length, which does NOT include
+ * nul termination
+ */
+ len = demarshal_and_validate_len (str, byte_order, pos, &pos);
if (len < 0)
return FALSE;
- if (len > _dbus_string_get_length (str) - pos)
- {
- _dbus_verbose ("boolean array length outside length of the message\n");
- return FALSE;
- }
-
- i = 0;
- while (i < len)
- {
- unsigned char c = _dbus_string_get_byte (str, pos + i);
-
- if (c != 0 && c != 1)
- {
- _dbus_verbose ("boolean value must be either 0 or 1, not %d (pos %d)\n", c, pos);
- return FALSE;
- }
-
- i++;
- }
- *end_pos = pos + len;
- break;
- }
- case DBUS_TYPE_BYTE_ARRAY:
- {
- int len;
+ if (!validate_string (str, pos, len, &pos))
+ return FALSE;
- len = demarshal_and_validate_len (str, byte_order, pos + 1, &pos);
+ /* Validate data */
+ len = demarshal_and_validate_len (str, byte_order, pos, &pos);
if (len < 0)
return FALSE;
-
+
*end_pos = pos + len;
}
break;
-
- case DBUS_TYPE_INT32_ARRAY:
- case DBUS_TYPE_UINT32_ARRAY:
+
+ case DBUS_TYPE_ARRAY:
{
int len;
+ int end;
+ int array_type;
- len = demarshal_and_validate_len (str, byte_order, pos + 1, &pos);
+ if (!_dbus_marshal_validate_type (str, pos, &array_type, &pos))
+ {
+ _dbus_verbose ("invalid array type\n");
+ return FALSE;
+ }
+
+ len = demarshal_and_validate_len (str, byte_order, pos, &pos);
if (len < 0)
return FALSE;
- _dbus_assert (_DBUS_ALIGN_VALUE (pos, 4) == (unsigned int) pos);
-
- *end_pos = pos + len * 4;
+ if (len > _dbus_string_get_length (str) - pos)
+ {
+ _dbus_verbose ("array length outside length of the message\n");
+ return FALSE;
+ }
+
+ end = pos + len;
+
+ while (pos < end)
+ {
+ if (!_dbus_marshal_validate_arg (str, byte_order,
+ array_type, pos, &pos))
+ return FALSE;
+ }
+
+ if (pos > end)
+ {
+ _dbus_verbose ("array contents exceeds array length\n");
+ return FALSE;
+ }
+
+ *end_pos = pos;
}
break;
- case DBUS_TYPE_DOUBLE_ARRAY:
+ case DBUS_TYPE_DICT:
{
+ int dict_type;
int len;
- int align_8;
-
- len = demarshal_and_validate_len (str, byte_order, pos + 1, &pos);
+ int end;
+
+ len = demarshal_and_validate_len (str, byte_order, pos, &pos);
if (len < 0)
return FALSE;
- if (len == 0)
- *end_pos = pos;
- else
+ if (len > _dbus_string_get_length (str) - pos)
+ {
+ _dbus_verbose ("dict length outside length of the message\n");
+ return FALSE;
+ }
+
+ end = pos + len;
+
+ while (pos < end)
{
- align_8 = _DBUS_ALIGN_VALUE (pos, 8);
- if (!_dbus_string_validate_nul (str, pos,
- align_8 - pos))
+ /* Validate name */
+ if (!_dbus_marshal_validate_arg (str, byte_order,
+ DBUS_TYPE_STRING, pos, &pos))
+ return FALSE;
+
+ if (!_dbus_marshal_validate_type (str, pos, &dict_type, &pos))
{
- _dbus_verbose ("double array alignment padding not initialized to nul\n");
+ _dbus_verbose ("invalid dict entry type at offset %d\n", pos);
return FALSE;
}
-
- *end_pos = align_8 + len * 8;
+
+ /* Validate element */
+ if (!_dbus_marshal_validate_arg (str, byte_order,
+ dict_type, pos, &pos))
+ return FALSE;
}
- }
- break;
-
- case DBUS_TYPE_STRING_ARRAY:
- {
- int len;
- int i;
-
- len = demarshal_and_validate_len (str, byte_order, pos + 1, &pos);
- if (len < 0)
- return FALSE;
-
- for (i = 0; i < len; i++)
+
+ if (pos > end)
{
- int str_len;
-
- str_len = demarshal_and_validate_len (str, byte_order,
- pos, &pos);
- if (str_len < 0)
- return FALSE;
-
- if (!validate_string (str, pos, str_len, &pos))
- return FALSE;
+ _dbus_verbose ("dict contents exceeds array length\n");
+ return FALSE;
}
-
*end_pos = pos;
}
break;
-
- case DBUS_TYPE_DICT:
- {
- int len;
- int i;
-
- len = demarshal_and_validate_len (str, byte_order, pos + 1, &pos);
- if (len < 0)
- return FALSE;
-
- for (i = 0; i < len; i++)
- {
- int str_len;
-
- str_len = demarshal_and_validate_len (str, byte_order,
- pos, &pos);
- if (str_len < 0)
- return FALSE;
-
- if (!validate_string (str, pos, str_len, &pos))
- return FALSE;
- }
-
- /* Now validate each argument */
- for (i = 0; i < len; i++)
- {
- if (pos >= _dbus_string_get_length (str))
- {
- _dbus_verbose ("not enough values in dict\n");
- return FALSE;
- }
-
- if (_dbus_string_get_byte (str, pos) == DBUS_TYPE_NIL)
- {
- _dbus_verbose ("can't have NIL values in dicts\n");
- return FALSE;
- }
-
- if (!_dbus_marshal_validate_arg (str, byte_order, pos, &pos))
- return FALSE;
- }
-
- *end_pos = pos;
-
- break;
- }
-
+
default:
- _dbus_verbose ("Unknown message arg type %d\n", *data);
+ _dbus_verbose ("Unknown message arg type %d\n", type);
return FALSE;
}
DBusString str;
char *tmp1, *tmp2;
dbus_int32_t array1[3] = { 0x123, 0x456, 0x789 }, *array2;
- int pos = 0, i, len;
- dbus_bool_t our_bool;
- dbus_int32_t our_int;
- dbus_uint32_t our_uint;
- double our_double;
- const char *our_string;
- const unsigned char boolean_array[] = { TRUE, FALSE, FALSE, TRUE };
- const unsigned char *our_boolean_array;
- const dbus_int32_t int32_array[] = { 0x12345678, -1911, 0, 0xaffe, 0xedd1e };
- const dbus_int32_t *our_int32_array;
- const dbus_uint32_t uint32_array[] = { 0x12345678, 0, 0xdeadbeef, 0x87654321, 0xffffffff };
- const dbus_uint32_t *our_uint32_array;
- const double double_array[] = { 3.14159, 1.2345, 6.7890 };
- const double *our_double_array;
- const char *string_array[] = { "This", "Is", "A", "Test" };
- const char **our_string_array;
- DBusDict *dict;
+ int pos = 0, len;
if (!_dbus_string_init (&str))
_dbus_assert_not_reached ("failed to init string");
_dbus_assert_not_reached ("Signed integer array lengths differ!\n");
dbus_free (array2);
-
- /* Marshal dicts */
- dict = dbus_dict_new ();
-
- if (dbus_dict_get_value_type (dict, "foo") != DBUS_TYPE_NIL)
- _dbus_assert_not_reached ("didn't return DBUS_TYPE_NIL for non-existant entry");
-
- if (!dbus_dict_set_boolean (dict, "boolean", TRUE))
- _dbus_assert_not_reached ("could not add boolean value");
-
- if (!dbus_dict_set_int32 (dict, "int32", 0x12345678))
- _dbus_assert_not_reached ("could not add int32 value");
-
- if (!dbus_dict_set_uint32 (dict, "uint32", 0x87654321))
- _dbus_assert_not_reached ("could not add uint32 value");
-
- if (!dbus_dict_set_double (dict, "double", 3.14159))
- _dbus_assert_not_reached ("could not add double value");
-
- if (!dbus_dict_set_string (dict, "string", "test string"))
- _dbus_assert_not_reached ("could not add string value");
-
- if (!dbus_dict_set_boolean_array (dict, "boolean_array", boolean_array, 4))
- _dbus_assert_not_reached ("could not add boolean array");
-
- if (!dbus_dict_set_int32_array (dict, "int32_array", int32_array, 5))
- _dbus_assert_not_reached ("could not add int32 array");
-
- if (!dbus_dict_set_uint32_array (dict, "uint32_array", uint32_array, 5))
- _dbus_assert_not_reached ("could not add uint32 array");
-
- if (!dbus_dict_set_double_array (dict, "double_array", double_array, 3))
- _dbus_assert_not_reached ("could not add double array");
-
- if (!dbus_dict_set_string_array (dict, "string_array", string_array, 4))
- _dbus_assert_not_reached ("could not add string array");
-
- if (!_dbus_marshal_dict (&str, DBUS_BIG_ENDIAN, dict))
- _dbus_assert_not_reached ("could not marshal dict");
-
- dbus_dict_unref (dict);
-
- if (!_dbus_demarshal_dict (&str, DBUS_BIG_ENDIAN, pos, &pos, &dict))
- _dbus_assert_not_reached ("could not demarshal dict");
-
- if (!dbus_dict_get_boolean (dict, "boolean", &our_bool) ||
- !our_bool)
- _dbus_assert_not_reached ("could not get boolean value");
-
- if (!dbus_dict_get_int32 (dict, "int32", &our_int) || our_int != 0x12345678)
- _dbus_assert_not_reached ("could not get int32 value or int32 values differ");
-
- if (!dbus_dict_get_uint32 (dict, "uint32", &our_uint) || our_uint != 0x87654321)
- _dbus_assert_not_reached ("could not get uint32 value or uint32 values differ");
-
- if (!dbus_dict_get_double (dict, "double", &our_double)
- || our_double != 3.14159)
- _dbus_assert_not_reached ("could not get double value or double values differ");
-
- if (!dbus_dict_get_string (dict, "string", &our_string) || strcmp (our_string, "test string") != 0)
- _dbus_assert_not_reached ("could not get string value or string values differ");
-
- if (!dbus_dict_get_boolean_array (dict, "boolean_array", &our_boolean_array, &len) ||
- len != 4 || memcmp (boolean_array, our_boolean_array, 4) != 0)
- _dbus_assert_not_reached ("could not get boolean array value or boolean array values differ");
-
- if (!dbus_dict_get_int32_array (dict, "int32_array", &our_int32_array, &len) ||
- len != 5 || memcmp (int32_array, our_int32_array, 5 * sizeof (dbus_int32_t)) != 0)
- _dbus_assert_not_reached ("could not get int32 array value or int32 array values differ");
-
- if (!dbus_dict_get_uint32_array (dict, "uint32_array", &our_uint32_array, &len) ||
- len != 5 || memcmp (uint32_array, our_uint32_array, 5 * sizeof (dbus_uint32_t) ) != 0)
- _dbus_assert_not_reached ("could not get uint32 array value or uint32 array values differ");
-
- if (!dbus_dict_get_double_array (dict, "double_array", &our_double_array, &len) ||
- len != 3 || memcmp (double_array, our_double_array, 3 * sizeof (double)) != 0)
- _dbus_assert_not_reached ("could not get double array value or double array values differ");
-
- if (!dbus_dict_get_string_array (dict, "string_array", &our_string_array, &len))
- _dbus_assert_not_reached ("could not get string array value");
-
- if (len != 4)
- _dbus_assert_not_reached ("string array lengths differ");
-
- for (i = 0; i < len; i++)
- {
- if (strcmp (our_string_array[i], string_array[i]) != 0)
- _dbus_assert_not_reached ("string array fields differ");
- }
-
- dbus_dict_unref (dict);
-
_dbus_string_free (&str);
DBusCounter *size_counter; /**< Counter for the size of the message, or #NULL */
long size_counter_delta; /**< Size we incremented the size counter by. */
+
+ dbus_uint32_t changed_stamp;
unsigned int locked : 1; /**< Message being sent, no modifications allowed. */
};
+enum {
+ DBUS_MESSAGE_ITER_TYPE_MESSAGE,
+ DBUS_MESSAGE_ITER_TYPE_ARRAY,
+ DBUS_MESSAGE_ITER_TYPE_DICT
+};
+
+typedef struct DBusMessageRealIter DBusMessageRealIter;
+
/**
* @brief Internals of DBusMessageIter
*
* Object representing a position in a message. All fields are internal.
*/
-struct DBusMessageIter
+struct DBusMessageRealIter
{
- int refcount; /**< Reference count */
-
- int pos; /**< Current position in the string */
-
+ DBusMessageRealIter *parent_iter; /**< parent iter, or NULL */
DBusMessage *message; /**< Message used */
+ dbus_uint32_t changed_stamp; /**< stamp to detect invalid iters */
+
+ /* This is an int instead of an enum to get a guaranteed size for the dummy: */
+ int type; /**< type of iter */
+
+ int pos; /**< Current position in the string */
+ int end; /**< position right after the container */
+ int container_type; /**< type of the items in the container (used for arrays) */
+ int container_start; /**< offset of the start of the container */
+ int container_length_pos; /**< offset of the length of the container */
+ int wrote_dict_key; /**< whether we wrote the dict key for the current dict element */
};
/**
{
DBusMessage *message;
const char *sender;
+ DBusMessageIter iter;
sender = get_string_field (original_message,
FIELD_SENDER, NULL);
return NULL;
}
- if (!dbus_message_append_string (message, error_message))
+ dbus_message_append_iter_init (message, &iter);
+ if (!dbus_message_iter_append_string (&iter, error_message))
{
dbus_message_unref (message);
return NULL;
/**
* Appends fields to a message given a variable argument
* list. The variable argument list should contain the type
- * of the argument followed by the value to add. Array values
- * are specified by a pointer to the array followed by an int
- * giving the length of the array. The list is terminated
- * with 0.
+ * of the argument followed by the value to add.
+ * Array values are specified by a int typecode followed by a pointer
+ * to the array followed by an int giving the length of the array.
+ * The argument list must be terminated with 0.
+ *
+ * This function doesn't support dicts or non-fundamental arrays.
*
* @param message the message
* @param first_arg_type type of the first argument
/**
* This function takes a va_list for use by language bindings
*
+ * @todo: Shouldn't this function clean up the changes to the message
+ * on failures?
+
* @see dbus_message_append_args.
* @param message the message
* @param first_arg_type type of first argument
va_list var_args)
{
int type, old_len;
+ DBusMessageIter iter;
old_len = _dbus_string_get_length (&message->body);
type = first_arg_type;
+ dbus_message_append_iter_init (message, &iter);
+
while (type != 0)
{
switch (type)
{
case DBUS_TYPE_NIL:
- if (!dbus_message_append_nil (message))
- goto enomem;
+ if (!dbus_message_iter_append_nil (&iter))
+ goto errorout;
+ break;
case DBUS_TYPE_BOOLEAN:
- if (!dbus_message_append_boolean (message, va_arg (var_args, dbus_bool_t)))
- goto enomem;
+ if (!dbus_message_iter_append_boolean (&iter, va_arg (var_args, dbus_bool_t)))
+ goto errorout;
break;
case DBUS_TYPE_INT32:
- if (!dbus_message_append_int32 (message, va_arg (var_args, dbus_int32_t)))
- goto enomem;
+ if (!dbus_message_iter_append_int32 (&iter, va_arg (var_args, dbus_int32_t)))
+ goto errorout;
break;
case DBUS_TYPE_UINT32:
- if (!dbus_message_append_uint32 (message, va_arg (var_args, dbus_uint32_t)))
- goto enomem;
+ if (!dbus_message_iter_append_uint32 (&iter, va_arg (var_args, dbus_uint32_t)))
+ goto errorout;
break;
case DBUS_TYPE_DOUBLE:
- if (!dbus_message_append_double (message, va_arg (var_args, double)))
- goto enomem;
+ if (!dbus_message_iter_append_double (&iter, va_arg (var_args, double)))
+ goto errorout;
break;
case DBUS_TYPE_STRING:
- if (!dbus_message_append_string (message, va_arg (var_args, const char *)))
- goto enomem;
+ if (!dbus_message_iter_append_string (&iter, va_arg (var_args, const char *)))
+ goto errorout;
break;
- case DBUS_TYPE_BOOLEAN_ARRAY:
+ case DBUS_TYPE_NAMED:
{
- int len;
+ const char *name;
unsigned char *data;
-
- data = va_arg (var_args, unsigned char *);
- len = va_arg (var_args, int);
-
- if (!dbus_message_append_boolean_array (message, data, len))
- goto enomem;
- }
- break;
- case DBUS_TYPE_INT32_ARRAY:
- {
- int len;
- dbus_int32_t *data;
-
- data = va_arg (var_args, dbus_int32_t *);
- len = va_arg (var_args, int);
-
- if (!dbus_message_append_int32_array (message, data, len))
- goto enomem;
- }
- break;
- case DBUS_TYPE_UINT32_ARRAY:
- {
- int len;
- dbus_uint32_t *data;
-
- data = va_arg (var_args, dbus_uint32_t *);
- len = va_arg (var_args, int);
-
- if (!dbus_message_append_uint32_array (message, data, len))
- goto enomem;
- }
- break;
- case DBUS_TYPE_DOUBLE_ARRAY:
- {
- int len;
- double *data;
-
- data = va_arg (var_args, double *);
- len = va_arg (var_args, int);
-
- if (!dbus_message_append_double_array (message, data, len))
- goto enomem;
- }
- break;
- case DBUS_TYPE_BYTE_ARRAY:
- {
int len;
- unsigned char *data;
-
+
+ name = va_arg (var_args, const char *);
data = va_arg (var_args, unsigned char *);
len = va_arg (var_args, int);
- if (!dbus_message_append_byte_array (message, data, len))
- goto enomem;
+ if (!dbus_message_iter_append_named (&iter, name, data, len))
+ goto errorout;
+ break;
}
- break;
- case DBUS_TYPE_STRING_ARRAY:
+ case DBUS_TYPE_ARRAY:
{
- int len;
- const char **data;
-
- data = va_arg (var_args, const char **);
+ void *data;
+ int len, type;
+
+ type = va_arg (var_args, int);
+ data = va_arg (var_args, void *);
len = va_arg (var_args, int);
- if (!dbus_message_append_string_array (message, data, len))
- goto enomem;
+ switch (type)
+ {
+ case DBUS_TYPE_BYTE:
+ if (!dbus_message_iter_append_byte_array (&iter, (unsigned char *)data, len))
+ goto errorout;
+ break;
+ case DBUS_TYPE_BOOLEAN:
+ if (!dbus_message_iter_append_boolean_array (&iter, (unsigned char *)data, len))
+ goto errorout;
+ break;
+ case DBUS_TYPE_INT32:
+ if (!dbus_message_iter_append_int32_array (&iter, (dbus_int32_t *)data, len))
+ goto errorout;
+ break;
+ case DBUS_TYPE_UINT32:
+ if (!dbus_message_iter_append_uint32_array (&iter, (dbus_uint32_t *)data, len))
+ goto errorout;
+ break;
+ case DBUS_TYPE_DOUBLE:
+ if (!dbus_message_iter_append_double_array (&iter, (double *)data, len))
+ goto errorout;
+ break;
+ case DBUS_TYPE_STRING:
+ if (!dbus_message_iter_append_string_array (&iter, (const char **)data, len))
+ goto errorout;
+ break;
+ case DBUS_TYPE_NIL:
+ case DBUS_TYPE_ARRAY:
+ case DBUS_TYPE_NAMED:
+ case DBUS_TYPE_DICT:
+ _dbus_warn ("dbus_message_append_args_valist doesn't support recursive arrays\n");
+ goto errorout;
+ default:
+ _dbus_warn ("Unknown field type %d\n", type);
+ goto errorout;
+ }
}
break;
+
case DBUS_TYPE_DICT:
- {
- DBusDict *dict;
-
- dict = va_arg (var_args, DBusDict *);
-
- if (!dbus_message_append_dict (message, dict))
- goto enomem;
- break;
- }
+ _dbus_warn ("dbus_message_append_args_valist doesn't support dicts\n");
+ goto errorout;
default:
_dbus_warn ("Unknown field type %d\n", type);
+ goto errorout;
}
type = va_arg (var_args, int);
return TRUE;
- enomem:
+ errorout:
return FALSE;
}
-/**
- * Appends a nil value to the message
- *
- * @param message the message
- * @returns #TRUE on success
- */
-dbus_bool_t
-dbus_message_append_nil (DBusMessage *message)
-{
- _dbus_assert (!message->locked);
-
- if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_NIL))
- return FALSE;
- else
- return TRUE;
-}
/**
- * Appends a boolean value to the message
+ * Gets arguments from a message given a variable argument list.
+ * The variable argument list should contain the type of the
+ * argumen followed by a pointer to where the value should be
+ * stored. The list is terminated with 0.
*
* @param message the message
- * @param value the boolean value
- * @returns #TRUE on success
+ * @param error error to be filled in on failure
+ * @param first_arg_type the first argument type
+ * @param ... location for first argument value, then list of type-location pairs
+ * @returns #FALSE if the error was set
*/
dbus_bool_t
-dbus_message_append_boolean (DBusMessage *message,
- dbus_bool_t value)
+dbus_message_get_args (DBusMessage *message,
+ DBusError *error,
+ int first_arg_type,
+ ...)
{
- _dbus_assert (!message->locked);
-
- if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_BOOLEAN))
- return FALSE;
+ dbus_bool_t retval;
+ va_list var_args;
- if (!_dbus_string_append_byte (&message->body, (value != FALSE)))
- {
- _dbus_string_shorten (&message->body, 1);
- return FALSE;
- }
+ _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+ va_start (var_args, first_arg_type);
+ retval = dbus_message_get_args_valist (message, error, first_arg_type, var_args);
+ va_end (var_args);
- return TRUE;
+ return retval;
}
/**
- * Appends a 32 bit signed integer to the message.
+ * This function takes a va_list for use by language bindings
+ *
+ * @todo We need to free the argument data when an error occurs.
*
+ * @see dbus_message_get_args
* @param message the message
- * @param value the integer value
- * @returns #TRUE on success
+ * @param error error to be filled in
+ * @param first_arg_type type of the first argument
+ * @param var_args return location for first argument, followed by list of type/location pairs
+ * @returns #FALSE if error was set
*/
dbus_bool_t
-dbus_message_append_int32 (DBusMessage *message,
- dbus_int32_t value)
+dbus_message_get_args_valist (DBusMessage *message,
+ DBusError *error,
+ int first_arg_type,
+ va_list var_args)
{
- _dbus_assert (!message->locked);
-
- if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_INT32))
- return FALSE;
-
- if (!_dbus_marshal_int32 (&message->body, message->byte_order, value))
- {
- _dbus_string_shorten (&message->body, 1);
- return FALSE;
- }
+ DBusMessageIter iter;
- return TRUE;
+ dbus_message_iter_init (message, &iter);
+ return dbus_message_iter_get_args_valist (&iter, error, first_arg_type, var_args);
}
/**
- * Appends a 32 bit unsigned integer to the message.
+ * Gets arguments from a message iterator given a variable argument list.
+ * The variable argument list should contain the type of the
+ * argumen followed by a pointer to where the value should be
+ * stored. The list is terminated with 0.
*
- * @param message the message
- * @param value the integer value
- * @returns #TRUE on success
+ * @param iter the message iterator
+ * @param error error to be filled in on failure
+ * @param first_arg_type the first argument type
+ * @param ... location for first argument value, then list of type-location pairs
+ * @returns #FALSE if the error was set
*/
dbus_bool_t
-dbus_message_append_uint32 (DBusMessage *message,
- dbus_uint32_t value)
+dbus_message_iter_get_args (DBusMessageIter *iter,
+ DBusError *error,
+ int first_arg_type,
+ ...)
{
- _dbus_assert (!message->locked);
+ dbus_bool_t retval;
+ va_list var_args;
- if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_UINT32))
- return FALSE;
+ _DBUS_ASSERT_ERROR_IS_CLEAR (error);
- if (!_dbus_marshal_uint32 (&message->body, message->byte_order, value))
- {
- _dbus_string_shorten (&message->body, 1);
- return FALSE;
- }
+ va_start (var_args, first_arg_type);
+ retval = dbus_message_iter_get_args_valist (iter, error, first_arg_type, var_args);
+ va_end (var_args);
- return TRUE;
+ return retval;
}
/**
- * Appends a double value to the message.
+ * This function takes a va_list for use by language bindings
*
- * @param message the message
- * @param value the double value
- * @returns #TRUE on success
+ * @todo this function (or some lower-level non-convenience function)
+ * needs better error handling; should allow the application to
+ * distinguish between out of memory, and bad data from the remote
+ * app. It also needs to not leak a bunch of args when it gets
+ * to the arg that's bad, as that would be a security hole
+ * (allow one app to force another to leak memory)
+ *
+ * @todo We need to free the argument data when an error occurs.
+ *
+ * @see dbus_message_get_args
+ * @param iter the message iter
+ * @param error error to be filled in
+ * @param first_arg_type type of the first argument
+ * @param var_args return location for first argument, followed by list of type/location pairs
+ * @returns #FALSE if error was set
*/
dbus_bool_t
-dbus_message_append_double (DBusMessage *message,
- double value)
+dbus_message_iter_get_args_valist (DBusMessageIter *iter,
+ DBusError *error,
+ int first_arg_type,
+ va_list var_args)
{
- _dbus_assert (!message->locked);
+ int spec_type, msg_type, i;
+ dbus_bool_t retval;
- if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_DOUBLE))
- return FALSE;
+ _DBUS_ASSERT_ERROR_IS_CLEAR (error);
- if (!_dbus_marshal_double (&message->body, message->byte_order, value))
- {
- _dbus_string_shorten (&message->body, 1);
- return FALSE;
- }
+ retval = FALSE;
- return TRUE;
-}
-
-/**
- * Appends a UTF-8 string to the message.
- *
- * @param message the message
- * @param value the string
- * @returns #TRUE on success
- */
-dbus_bool_t
-dbus_message_append_string (DBusMessage *message,
- const char *value)
-{
- _dbus_assert (!message->locked);
-
- if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_STRING))
- return FALSE;
+ spec_type = first_arg_type;
+ i = 0;
- if (!_dbus_marshal_string (&message->body, message->byte_order, value))
+ while (spec_type != 0)
{
- _dbus_string_shorten (&message->body, 1);
- return FALSE;
- }
+ msg_type = dbus_message_iter_get_arg_type (iter);
+
+ if (msg_type != spec_type)
+ {
+ dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
+ "Argument %d is specified to be of type \"%s\", but "
+ "is actually of type \"%s\"\n", i,
+ _dbus_type_to_string (spec_type),
+ _dbus_type_to_string (msg_type));
- return TRUE;
-}
+ goto out;
+ }
-/**
- * Appends a boolean array to the message.
- *
- * @param message the message
- * @param value the array
- * @param len the length of the array
- * @returns #TRUE on success
- */
-dbus_bool_t
-dbus_message_append_boolean_array (DBusMessage *message,
- unsigned const char *value,
- int len)
-{
- _dbus_assert (!message->locked);
+ switch (spec_type)
+ {
+ case DBUS_TYPE_NIL:
+ break;
+ case DBUS_TYPE_BYTE:
+ {
+ unsigned char *ptr;
- if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_BOOLEAN_ARRAY))
- return FALSE;
+ ptr = va_arg (var_args, unsigned char *);
- if (!_dbus_marshal_byte_array (&message->body, message->byte_order, value, len))
- {
- _dbus_string_shorten (&message->body, 1);
- return FALSE;
- }
+ *ptr = dbus_message_iter_get_byte (iter);
+ break;
+ }
+ case DBUS_TYPE_BOOLEAN:
+ {
+ dbus_bool_t *ptr;
- return TRUE;
-}
+ ptr = va_arg (var_args, dbus_bool_t *);
-/**
- * Appends a 32 bit signed integer array to the message.
- *
- * @param message the message
- * @param value the array
- * @param len the length of the array
- * @returns #TRUE on success
- */
-dbus_bool_t
-dbus_message_append_int32_array (DBusMessage *message,
- const dbus_int32_t *value,
- int len)
-{
- _dbus_assert (!message->locked);
+ *ptr = dbus_message_iter_get_boolean (iter);
+ break;
+ }
+ case DBUS_TYPE_INT32:
+ {
+ dbus_int32_t *ptr;
- if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_INT32_ARRAY))
- return FALSE;
+ ptr = va_arg (var_args, dbus_int32_t *);
- if (!_dbus_marshal_int32_array (&message->body, message->byte_order,
- value, len))
- {
- _dbus_string_shorten (&message->body, 1);
- return FALSE;
- }
+ *ptr = dbus_message_iter_get_int32 (iter);
+ break;
+ }
+ case DBUS_TYPE_UINT32:
+ {
+ dbus_uint32_t *ptr;
+
+ ptr = va_arg (var_args, dbus_uint32_t *);
+
+ *ptr = dbus_message_iter_get_uint32 (iter);
+ break;
+ }
+
+ case DBUS_TYPE_DOUBLE:
+ {
+ double *ptr;
+
+ ptr = va_arg (var_args, double *);
+
+ *ptr = dbus_message_iter_get_double (iter);
+ break;
+ }
+
+ case DBUS_TYPE_STRING:
+ {
+ char **ptr;
+
+ ptr = va_arg (var_args, char **);
+
+ *ptr = dbus_message_iter_get_string (iter);
+
+ if (!*ptr)
+ {
+ dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+ goto out;
+ }
+
+ break;
+ }
+
+ case DBUS_TYPE_NAMED:
+ {
+ char **name;
+ unsigned char **data;
+ int *len;
+
+ name = va_arg (var_args, char **);
+ data = va_arg (var_args, unsigned char **);
+ len = va_arg (var_args, int *);
+
+ *name = dbus_message_iter_get_named (iter, data, len);
+ if (*name == NULL)
+ {
+ dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+ goto out;
+ }
+ }
+ break;
+ case DBUS_TYPE_ARRAY:
+ {
+ void **data;
+ int *len, type;
+
+ type = va_arg (var_args, int);
+ data = va_arg (var_args, void *);
+ len = va_arg (var_args, int *);
+
+ if (dbus_message_iter_get_array_type (iter) != type)
+ {
+ dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
+ "Argument %d is specified to be of type \"array of %s\", but "
+ "is actually of type \"array of %s\"\n", i,
+ _dbus_type_to_string (type),
+ _dbus_type_to_string (dbus_message_iter_get_array_type (iter)));
+ goto out;
+ }
+
+ switch (type)
+ {
+ case DBUS_TYPE_BYTE:
+ if (!dbus_message_iter_get_byte_array (iter, (unsigned char **)data, len))
+ {
+ dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+ goto out;
+ }
+ break;
+ case DBUS_TYPE_BOOLEAN:
+ if (!dbus_message_iter_get_boolean_array (iter, (unsigned char **)data, len))
+ {
+ dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+ goto out;
+ }
+ break;
+ case DBUS_TYPE_INT32:
+ if (!dbus_message_iter_get_int32_array (iter, (dbus_int32_t **)data, len))
+ {
+ dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+ goto out;
+ }
+ break;
+ case DBUS_TYPE_UINT32:
+ if (!dbus_message_iter_get_uint32_array (iter, (dbus_uint32_t **)data, len))
+ {
+ dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+ goto out;
+ }
+ break;
+ case DBUS_TYPE_DOUBLE:
+ if (!dbus_message_iter_get_double_array (iter, (double **)data, len))
+ {
+ dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+ goto out;
+ }
+ break;
+ case DBUS_TYPE_STRING:
+ if (!dbus_message_iter_get_string_array (iter, (char ***)data, len))
+ {
+ dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+ goto out;
+ }
+ break;
+ case DBUS_TYPE_NIL:
+ case DBUS_TYPE_ARRAY:
+ case DBUS_TYPE_NAMED:
+ case DBUS_TYPE_DICT:
+ _dbus_warn ("dbus_message_get_args_valist doesn't support recursive arrays\n");
+ dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
+ goto out;
+ default:
+ _dbus_warn ("Unknown field type %d\n", type);
+ dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
+ goto out;
+ }
+ }
+ break;
+ case DBUS_TYPE_DICT:
+ _dbus_warn ("dbus_message_get_args_valist doesn't support dicts\n");
+ dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
+ goto out;
+ default:
+ dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
+ _dbus_warn ("Unknown field type %d\n", spec_type);
+ goto out;
+ }
+
+ spec_type = va_arg (var_args, int);
+ if (spec_type != 0 && !dbus_message_iter_next (iter))
+ {
+ dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
+ "Message has only %d arguments, but more were expected", i);
+ goto out;
+ }
+
+ i++;
+ }
+
+ retval = TRUE;
+
+ out:
+
+ return retval;
+}
- return TRUE;
-}
/**
- * Appends a 32 bit unsigned integer array to the message.
+ * Initializes a DBusMessageIter representing the arguments of the
+ * message passed in.
*
* @param message the message
- * @param value the array
- * @param len the length of the array
- * @returns #TRUE on success
+ * @param _iter pointer to an iterator to initialize
*/
-dbus_bool_t
-dbus_message_append_uint32_array (DBusMessage *message,
- const dbus_uint32_t *value,
- int len)
+void
+dbus_message_iter_init (DBusMessage *message,
+ DBusMessageIter *iter)
{
- _dbus_assert (!message->locked);
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ real->message = message;
+ real->parent_iter = NULL;
+ real->changed_stamp = message->changed_stamp;
+
+ real->type = DBUS_MESSAGE_ITER_TYPE_MESSAGE;
+ real->pos = 0;
+ real->end = _dbus_string_get_length (&message->body);
+
+ real->container_type = 0;
+ real->container_start = 0;
+ real->container_length_pos = 0;
+ real->wrote_dict_key = 0;
+}
- if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_UINT32_ARRAY))
- return FALSE;
+static void
+dbus_message_iter_check (DBusMessageRealIter *iter)
+{
+ if (iter->changed_stamp != iter->message->changed_stamp)
+ _dbus_warn ("dbus iterator check failed: invalid iterator\n");
+ if (iter->pos < 0 || iter->pos > iter->end)
+ _dbus_warn ("dbus iterator check failed: invalid position\n");
+}
- if (!_dbus_marshal_uint32_array (&message->body, message->byte_order,
- value, len))
+static int
+dbus_message_iter_get_data_start (DBusMessageRealIter *iter, int *type)
+{
+ const char *data;
+ int pos, len;
+
+ switch (iter->type)
{
- _dbus_string_shorten (&message->body, 1);
- return FALSE;
+ case DBUS_MESSAGE_ITER_TYPE_MESSAGE:
+ data = _dbus_string_get_const_data_len (&iter->message->body,
+ iter->pos, 1);
+ if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_LAST)
+ *type = *data;
+ else
+ *type = DBUS_TYPE_INVALID;
+
+ return iter->pos + 1;
+
+ case DBUS_MESSAGE_ITER_TYPE_ARRAY:
+ *type = iter->container_type;
+ return iter->pos;
+
+
+ case DBUS_MESSAGE_ITER_TYPE_DICT:
+ /* Get the length of the string */
+ len = _dbus_demarshal_uint32 (&iter->message->body,
+ iter->message->byte_order,
+ iter->pos, &pos);
+ pos = pos + len + 1;
+ data = _dbus_string_get_const_data_len (&iter->message->body,
+ pos, 1);
+ if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_LAST)
+ *type = *data;
+ else
+ *type = DBUS_TYPE_INVALID;
+ return pos + 1;
+ default:
+ _dbus_assert_not_reached ("Invalid iter type");
+ break;
}
-
- return TRUE;
+ *type = DBUS_TYPE_INVALID;
+ return iter->pos;
}
+
/**
- * Appends a double array to the message.
+ * Checks if an iterator has any more fields.
*
- * @param message the message
- * @param value the array
- * @param len the length of the array
- * @returns #TRUE on success
+ * @param iter the message iter
+ * @returns #TRUE if there are more fields
+ * following
*/
dbus_bool_t
-dbus_message_append_double_array (DBusMessage *message,
- const double *value,
- int len)
+dbus_message_iter_has_next (DBusMessageIter *iter)
{
- _dbus_assert (!message->locked);
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+ int end_pos;
+ int type, pos;
- if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_DOUBLE_ARRAY))
- return FALSE;
+ dbus_message_iter_check (real);
- if (!_dbus_marshal_double_array (&message->body, message->byte_order,
- value, len))
- {
- _dbus_string_shorten (&message->body, 1);
- return FALSE;
- }
+ if (real->pos >= real->end)
+ return FALSE;
+
+ pos = dbus_message_iter_get_data_start (real, &type);
+
+ if (!_dbus_marshal_get_arg_end_pos (&real->message->body,
+ real->message->byte_order,
+ type, pos, &end_pos))
+ return FALSE;
+
+ if (end_pos >= real->end)
+ return FALSE;
- return TRUE;
+ return TRUE;
}
/**
- * Appends a byte array to the message.
+ * Moves the iterator to the next field.
*
- * @param message the message
- * @param value the array
- * @param len the length of the array
- * @returns #TRUE on success
+ * @param _iter The message iter
+ * @returns #TRUE if the iterator was moved to the next field
*/
dbus_bool_t
-dbus_message_append_byte_array (DBusMessage *message,
- unsigned const char *value,
- int len)
+dbus_message_iter_next (DBusMessageIter *iter)
{
- _dbus_assert (!message->locked);
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+ int end_pos;
+ int type, pos;
- if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_BYTE_ARRAY))
- return FALSE;
+ dbus_message_iter_check (real);
+
+ pos = dbus_message_iter_get_data_start (real, &type);
- if (!_dbus_marshal_byte_array (&message->body, message->byte_order, value, len))
- {
- _dbus_string_shorten (&message->body, 1);
- return FALSE;
- }
-
+ if (!_dbus_marshal_get_arg_end_pos (&real->message->body,
+ real->message->byte_order,
+ type, pos, &end_pos))
+ return FALSE;
+
+ if (end_pos >= real->end)
+ return FALSE;
+
+ real->pos = end_pos;
+
return TRUE;
}
/**
- * Appends a string array to the message.
+ * Returns the argument type of the argument that the
+ * message iterator points at.
*
- * @param message the message
- * @param value the array
- * @param len the length of the array
- * @returns #TRUE on success
+ * @param iter the message iter
+ * @returns the field type
*/
-dbus_bool_t
-dbus_message_append_string_array (DBusMessage *message,
- const char **value,
- int len)
+int
+dbus_message_iter_get_arg_type (DBusMessageIter *iter)
{
- _dbus_assert (!message->locked);
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+ int type, pos;
- if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_STRING_ARRAY))
- return FALSE;
+ dbus_message_iter_check (real);
- if (!_dbus_marshal_string_array (&message->body, message->byte_order,
- (const char **)value, len))
- {
- _dbus_string_shorten (&message->body, 1);
- return FALSE;
- }
+ if (real->pos >= real->end)
+ return DBUS_TYPE_INVALID;
- return TRUE;
+ pos = dbus_message_iter_get_data_start (real, &type);
+
+ return type;
}
/**
- * Appends a dict to the message.
+ * Returns the element type of the array that the
+ * message iterator points at. Note that you need
+ * to check that the iterator points to an array
+ * prior to using this function.
*
- * @param message the message
- * @param dict the dict
- * @returns #TRUE on success
+ * @param iter the message iter
+ * @returns the field type
*/
-dbus_bool_t
-dbus_message_append_dict (DBusMessage *message,
- DBusDict *dict)
+int
+dbus_message_iter_get_array_type (DBusMessageIter *iter)
{
- _dbus_assert (!message->locked);
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+ int type, pos;
+ const char *data;
- if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_DICT))
- return FALSE;
+ dbus_message_iter_check (real);
- if (!_dbus_marshal_dict (&message->body, message->byte_order, dict))
- {
- _dbus_string_shorten (&message->body, 1);
- return FALSE;
- }
+ if (real->pos >= real->end)
+ return DBUS_TYPE_INVALID;
- return TRUE;
+ pos = dbus_message_iter_get_data_start (real, &type);
+
+ _dbus_assert (type == DBUS_TYPE_ARRAY);
+
+ data = _dbus_string_get_const_data_len (&real->message->body,
+ pos,
+ 1);
+ if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_LAST)
+ return *data;
+
+ return DBUS_TYPE_INVALID;
}
+
/**
- * Gets arguments from a message given a variable argument list.
- * The variable argument list should contain the type of the
- * argumen followed by a pointer to where the value should be
- * stored. The list is terminated with 0.
+ * Returns the string value that an iterator may point to.
+ * Note that you need to check that the iterator points to
+ * a string value before using this function.
*
- * @param message the message
- * @param error error to be filled in on failure
- * @param first_arg_type the first argument type
- * @param ... location for first argument value, then list of type-location pairs
- * @returns #FALSE if the error was set
+ * @see dbus_message_iter_get_arg_type
+ * @param iter the message iter
+ * @returns the string
*/
-dbus_bool_t
-dbus_message_get_args (DBusMessage *message,
- DBusError *error,
- int first_arg_type,
- ...)
+char *
+dbus_message_iter_get_string (DBusMessageIter *iter)
{
- dbus_bool_t retval;
- va_list var_args;
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+ int type, pos;
- _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+ dbus_message_iter_check (real);
+
+ pos = dbus_message_iter_get_data_start (real, &type);
- va_start (var_args, first_arg_type);
- retval = dbus_message_get_args_valist (message, error, first_arg_type, var_args);
- va_end (var_args);
+ _dbus_assert (type == DBUS_TYPE_STRING);
- return retval;
+ return _dbus_demarshal_string (&real->message->body, real->message->byte_order,
+ pos, NULL);
}
/**
- * This function takes a va_list for use by language bindings
- *
- * @todo this function (or some lower-level non-convenience function)
- * needs better error handling; should allow the application to
- * distinguish between out of memory, and bad data from the remote
- * app. It also needs to not leak a bunch of args when it gets
- * to the arg that's bad, as that would be a security hole
- * (allow one app to force another to leak memory)
- *
- * @todo We need to free the argument data when an error occurs.
+ * Returns the name and data from a named type that an
+ * iterator may point to.Note that you need to check that
+ * the iterator points to a named type before using this
+ * function.
*
- * @see dbus_message_get_args
- * @param message the message
- * @param error error to be filled in
- * @param first_arg_type type of the first argument
- * @param var_args return location for first argument, followed by list of type/location pairs
- * @returns #FALSE if error was set
+ * @see dbus_message_iter_get_arg_type
+ * @param iter the message iter
+ * @param value return location for data
+ * @param len return location for length of data
+ * @returns the named type name as a string
+ *
*/
-dbus_bool_t
-dbus_message_get_args_valist (DBusMessage *message,
- DBusError *error,
- int first_arg_type,
- va_list var_args)
+char *
+dbus_message_iter_get_named (DBusMessageIter *iter,
+ unsigned char **value,
+ int *len)
{
- int spec_type, msg_type, i;
- DBusMessageIter *iter;
- dbus_bool_t retval;
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+ int type, pos;
+ char *name;
- _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+ dbus_message_iter_check (real);
+
+ pos = dbus_message_iter_get_data_start (real, &type);
+
+ _dbus_assert (type == DBUS_TYPE_NAMED);
- iter = dbus_message_get_args_iter (message);
+ name = _dbus_demarshal_string (&real->message->body, real->message->byte_order,
+ pos, &pos);
- if (iter == NULL)
+ if (name == NULL)
+ return NULL;
+
+ if (!_dbus_demarshal_byte_array (&real->message->body, real->message->byte_order,
+ pos + 1, NULL, value, len))
{
- dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
- return FALSE;
+ dbus_free (name);
+ return NULL;
}
+ else
+ return name;
+}
- retval = FALSE;
+/**
+ * Returns the byte value that an iterator may point to.
+ * Note that you need to check that the iterator points to
+ * a byte value before using this function.
+ *
+ * @see dbus_message_iter_get_arg_type
+ * @param iter the message iter
+ * @returns the byte value
+ */
+unsigned char
+dbus_message_iter_get_byte (DBusMessageIter *iter)
+{
+ unsigned char value;
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+ int type, pos;
+
+ dbus_message_iter_check (real);
+
+ pos = dbus_message_iter_get_data_start (real, &type);
- spec_type = first_arg_type;
- i = 0;
+ _dbus_assert (type == DBUS_TYPE_BYTE);
+
+ value = _dbus_string_get_byte (&real->message->body, pos);
- while (spec_type != 0)
- {
- msg_type = dbus_message_iter_get_arg_type (iter);
-
- if (msg_type != spec_type)
- {
- dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
- "Argument %d is specified to be of type \"%s\", but "
- "is actually of type \"%s\"\n", i,
- _dbus_type_to_string (spec_type),
- _dbus_type_to_string (msg_type));
+ return value;
+}
- goto out;
- }
- switch (spec_type)
- {
- case DBUS_TYPE_NIL:
- break;
- case DBUS_TYPE_BOOLEAN:
- {
- dbus_bool_t *ptr;
+/**
+ * Returns the boolean value that an iterator may point to.
+ * Note that you need to check that the iterator points to
+ * a boolean value before using this function.
+ *
+ * @see dbus_message_iter_get_arg_type
+ * @param iter the message iter
+ * @returns the boolean value
+ */
+dbus_bool_t
+dbus_message_iter_get_boolean (DBusMessageIter *iter)
+{
+ unsigned char value;
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+ int type, pos;
- ptr = va_arg (var_args, dbus_bool_t *);
+ dbus_message_iter_check (real);
- *ptr = dbus_message_iter_get_boolean (iter);
- break;
- }
- case DBUS_TYPE_INT32:
- {
- dbus_int32_t *ptr;
+ pos = dbus_message_iter_get_data_start (real, &type);
+
+ _dbus_assert (type == DBUS_TYPE_BOOLEAN);
- ptr = va_arg (var_args, dbus_int32_t *);
+ value = _dbus_string_get_byte (&real->message->body, pos);
+
+ return value;
+}
- *ptr = dbus_message_iter_get_int32 (iter);
- break;
- }
- case DBUS_TYPE_UINT32:
- {
- dbus_uint32_t *ptr;
+/**
+ * Returns the 32 bit signed integer value that an iterator may point to.
+ * Note that you need to check that the iterator points to
+ * an integer value before using this function.
+ *
+ * @see dbus_message_iter_get_arg_type
+ * @param iter the message iter
+ * @returns the integer
+ */
+dbus_int32_t
+dbus_message_iter_get_int32 (DBusMessageIter *iter)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+ int type, pos;
- ptr = va_arg (var_args, dbus_uint32_t *);
+ dbus_message_iter_check (real);
- *ptr = dbus_message_iter_get_uint32 (iter);
- break;
- }
+ pos = dbus_message_iter_get_data_start (real, &type);
+
+ _dbus_assert (type == DBUS_TYPE_INT32);
+
+ return _dbus_demarshal_int32 (&real->message->body, real->message->byte_order,
+ pos, NULL);
+}
- case DBUS_TYPE_DOUBLE:
- {
- double *ptr;
+/**
+ * Returns the 32 bit unsigned integer value that an iterator may point to.
+ * Note that you need to check that the iterator points to
+ * an unsigned integer value before using this function.
+ *
+ * @see dbus_message_iter_get_arg_type
+ * @param iter the message iter
+ * @returns the integer
+ */
+dbus_uint32_t
+dbus_message_iter_get_uint32 (DBusMessageIter *iter)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+ int type, pos;
- ptr = va_arg (var_args, double *);
+ dbus_message_iter_check (real);
- *ptr = dbus_message_iter_get_double (iter);
- break;
- }
+ pos = dbus_message_iter_get_data_start (real, &type);
+
+ _dbus_assert (type == DBUS_TYPE_UINT32);
+
+ return _dbus_demarshal_uint32 (&real->message->body, real->message->byte_order,
+ pos, NULL);
+}
- case DBUS_TYPE_STRING:
- {
- char **ptr;
+/**
+ * Returns the double value that an iterator may point to.
+ * Note that you need to check that the iterator points to
+ * a string value before using this function.
+ *
+ * @see dbus_message_iter_get_arg_type
+ * @param iter the message iter
+ * @returns the double
+ */
+double
+dbus_message_iter_get_double (DBusMessageIter *iter)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+ int type, pos;
- ptr = va_arg (var_args, char **);
+ dbus_message_iter_check (real);
- *ptr = dbus_message_iter_get_string (iter);
+ pos = dbus_message_iter_get_data_start (real, &type);
+
+ _dbus_assert (type == DBUS_TYPE_DOUBLE);
+
+ return _dbus_demarshal_double (&real->message->body, real->message->byte_order,
+ pos, NULL);
+}
- if (!*ptr)
- {
- dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
- goto out;
- }
-
- break;
- }
+/**
+ * Initializes an iterator for the array that the iterator
+ * may point to. Note that you need to check that the iterator
+ * points to an array prior to using this function.
+ *
+ * The array element type is returned in array_type, and the array
+ * iterator can only be used to get that type of data.
+ *
+ * @param iter the iterator
+ * @param array_iter pointer to an iterator to initialize
+ * @param array_type gets set to the type of the array elements
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_init_array_iterator (DBusMessageIter *iter,
+ DBusMessageIter *array_iter,
+ int *array_type)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+ DBusMessageRealIter *array_real = (DBusMessageRealIter *)array_iter;
+ int type, pos, len_pos, len;
+ int _array_type;
+ const char *data;
- case DBUS_TYPE_BOOLEAN_ARRAY:
- {
- unsigned char **ptr;
- int *len;
+ dbus_message_iter_check (real);
- ptr = va_arg (var_args, unsigned char **);
- len = va_arg (var_args, int *);
+ pos = dbus_message_iter_get_data_start (real, &type);
+
+ _dbus_assert (type == DBUS_TYPE_ARRAY);
- if (!dbus_message_iter_get_boolean_array (iter, ptr, len))
- {
- dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
- goto out;
- }
- break;
- }
-
- case DBUS_TYPE_INT32_ARRAY:
- {
- dbus_int32_t **ptr;
- int *len;
+ data = _dbus_string_get_const_data_len (&real->message->body,
+ pos,
+ 1);
+ if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_LAST)
+ _array_type = *data;
+ else
+ return FALSE;
- ptr = va_arg (var_args, dbus_int32_t **);
- len = va_arg (var_args, int *);
+ len_pos = _DBUS_ALIGN_VALUE (pos + 1, sizeof (dbus_uint32_t));
+ len = _dbus_demarshal_uint32 (&real->message->body, real->message->byte_order,
+ pos + 1, &pos);
+
+ 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 = pos;
+ array_real->end = pos + len;
+
+ array_real->container_type = _array_type;
+ array_real->container_start = pos;
+ array_real->container_length_pos = len_pos;
+ array_real->wrote_dict_key = 0;
- if (!dbus_message_iter_get_int32_array (iter, ptr, len))
- {
- dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
- goto out;
- }
-
- break;
- }
+ if (array_type != NULL)
+ *array_type = _array_type;
+
+ return TRUE;
+}
- case DBUS_TYPE_UINT32_ARRAY:
- {
- dbus_uint32_t **ptr;
- int *len;
- ptr = va_arg (var_args, dbus_uint32_t **);
- len = va_arg (var_args, int *);
+/**
+ * Initializes an iterator for the dict that the iterator
+ * may point to. Note that you need to check that the iterator
+ * points to a dict prior to using this function.
+ *
+ * @param iter the iterator
+ * @param dict_iter pointer to an iterator to initialize
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_init_dict_iterator (DBusMessageIter *iter,
+ DBusMessageIter *dict_iter)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+ DBusMessageRealIter *dict_real = (DBusMessageRealIter *)dict_iter;
+ int type, pos, len_pos, len;
- if (!dbus_message_iter_get_uint32_array (iter, ptr, len))
- {
- dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
- goto out;
- }
-
- break;
- }
+ dbus_message_iter_check (real);
- case DBUS_TYPE_DOUBLE_ARRAY:
- {
- double **ptr;
- int *len;
+ pos = dbus_message_iter_get_data_start (real, &type);
+
+ _dbus_assert (type == DBUS_TYPE_DICT);
- ptr = va_arg (var_args, double **);
- len = va_arg (var_args, int *);
+ len_pos = _DBUS_ALIGN_VALUE (pos, sizeof (dbus_uint32_t));
+ len = _dbus_demarshal_uint32 (&real->message->body, real->message->byte_order,
+ pos, &pos);
+
+ 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 = pos;
+ dict_real->end = pos + len;
+
+ dict_real->container_type = 0;
+ dict_real->container_start = pos;
+ dict_real->container_length_pos = len_pos;
+ dict_real->wrote_dict_key = 0;
- if (!dbus_message_iter_get_double_array (iter, ptr, len))
- {
- dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
- goto out;
- }
- break;
- }
-
- case DBUS_TYPE_BYTE_ARRAY:
- {
- unsigned char **ptr;
- int *len;
+ return TRUE;
+}
- ptr = va_arg (var_args, unsigned char **);
- len = va_arg (var_args, int *);
+/**
+ * Returns the byte 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.
+ *
+ * @param iter the iterator
+ * @param value return location for array values
+ * @param len return location for length of byte array
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_get_byte_array (DBusMessageIter *iter,
+ unsigned char **value,
+ int *len)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+ int type, pos;
+ const char *data;
- if (!dbus_message_iter_get_byte_array (iter, ptr, len))
- {
- dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
- goto out;
- }
- break;
- }
- case DBUS_TYPE_STRING_ARRAY:
- {
- char ***ptr;
- int *len;
+ dbus_message_iter_check (real);
- ptr = va_arg (var_args, char ***);
- len = va_arg (var_args, int *);
+ pos = dbus_message_iter_get_data_start (real, &type);
+
+ _dbus_assert (type == DBUS_TYPE_ARRAY);
- if (!dbus_message_iter_get_string_array (iter, ptr, len))
- {
- dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
- goto out;
- }
- break;
- }
- case DBUS_TYPE_DICT:
- {
- DBusDict **dict;
+ data = _dbus_string_get_const_data_len (&real->message->body,
+ pos,
+ 1);
- dict = va_arg (var_args, DBusDict **);
+ _dbus_assert (*data == DBUS_TYPE_BYTE);
- if (!dbus_message_iter_get_dict (iter, dict))
- {
- dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
- goto out;
- }
- break;
- }
- default:
- _dbus_warn ("Unknown field type %d\n", spec_type);
- }
-
- spec_type = va_arg (var_args, int);
- if (spec_type != 0 && !dbus_message_iter_next (iter))
- {
- dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
- "Message has only %d arguments, but more were expected", i);
- goto out;
- }
+ if (!_dbus_demarshal_byte_array (&real->message->body, real->message->byte_order,
+ pos + 1, NULL, value, len))
+ return FALSE;
+ else
+ return TRUE;
+}
- i++;
- }
+/**
+ * Returns the boolean 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_boolean_array (DBusMessageIter *iter,
+ unsigned char **value,
+ int *len)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+ int type, pos;
+ const char *data;
+
+ dbus_message_iter_check (real);
+
+ pos = dbus_message_iter_get_data_start (real, &type);
- retval = TRUE;
+ _dbus_assert (type == DBUS_TYPE_ARRAY);
+
+ data = _dbus_string_get_const_data_len (&real->message->body,
+ pos,
+ 1);
+
+ _dbus_assert (*data == DBUS_TYPE_BOOLEAN);
+
+ if (!_dbus_demarshal_byte_array (&real->message->body, real->message->byte_order,
+ pos + 1, NULL, value, len))
+ return FALSE;
+ else
+ return TRUE;
+}
+
+/**
+ * Returns the 32 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.
+ *
+ * @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_int32_array (DBusMessageIter *iter,
+ dbus_int32_t **value,
+ int *len)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+ int type, pos;
+ const char *data;
+
+ dbus_message_iter_check (real);
+
+ pos = dbus_message_iter_get_data_start (real, &type);
- out:
- dbus_message_iter_unref (iter);
- return retval;
+ _dbus_assert (type == DBUS_TYPE_ARRAY);
+
+ data = _dbus_string_get_const_data_len (&real->message->body,
+ pos,
+ 1);
+
+ _dbus_assert (*data == DBUS_TYPE_INT32);
+
+ if (!_dbus_demarshal_int32_array (&real->message->body, real->message->byte_order,
+ pos + 1, NULL, value, len))
+ return FALSE;
+ else
+ return TRUE;
}
/**
- * Returns a DBusMessageIter representing the arguments of the
- * message passed in.
+ * Returns the 32 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.
+ *
+ * @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;
+ const char *data;
+
+ dbus_message_iter_check (real);
+
+ pos = dbus_message_iter_get_data_start (real, &type);
+
+ _dbus_assert (type == DBUS_TYPE_ARRAY);
+
+ data = _dbus_string_get_const_data_len (&real->message->body,
+ pos,
+ 1);
+
+ _dbus_assert (*data == DBUS_TYPE_UINT32);
+
+ if (!_dbus_demarshal_uint32_array (&real->message->body, real->message->byte_order,
+ pos + 1, NULL, value, len))
+ return FALSE;
+ else
+ return TRUE;
+}
+
+/**
+ * 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.
*
- * @todo IMO the message iter should follow the GtkTextIter pattern,
- * a static object with a "stamp" value used to detect invalid
- * iter uses (uninitialized or after changing the message).
- * ref/unref is kind of annoying to deal with, and slower too.
- * This implies not ref'ing the message from the iter.
+ * @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;
+ const char *data;
+
+ dbus_message_iter_check (real);
+
+ pos = dbus_message_iter_get_data_start (real, &type);
+
+ _dbus_assert (type == DBUS_TYPE_ARRAY);
+
+ data = _dbus_string_get_const_data_len (&real->message->body,
+ pos,
+ 1);
+
+ _dbus_assert (*data == DBUS_TYPE_DOUBLE);
+
+ if (!_dbus_demarshal_double_array (&real->message->body, real->message->byte_order,
+ pos + 1, 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.
*
- * @todo I'd also name this dbus_message_iter_new() or
- * for the static object dbus_message_iter_init() rather
- * than making it a method on the message
+ * 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;
+ const char *data;
+
+ dbus_message_iter_check (real);
+
+ pos = dbus_message_iter_get_data_start (real, &type);
+
+ _dbus_assert (type == DBUS_TYPE_ARRAY);
+
+ data = _dbus_string_get_const_data_len (&real->message->body,
+ pos,
+ 1);
+
+ _dbus_assert (*data == DBUS_TYPE_STRING);
+
+ if (!_dbus_demarshal_string_array (&real->message->body, real->message->byte_order,
+ pos + 1, 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_message_iter_check (real);
+
+ _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
- * @returns a new iter.
+ * @param _iter pointer to an iterator to initialize
*/
-DBusMessageIter *
-dbus_message_get_args_iter (DBusMessage *message)
+void
+dbus_message_append_iter_init (DBusMessage *message,
+ DBusMessageIter *iter)
{
- DBusMessageIter *iter;
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ 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;
- iter = dbus_new (DBusMessageIter, 1);
+ real->container_type = 0;
+ real->container_length_pos = 0;
+ real->wrote_dict_key = 0;
+}
- if (iter != NULL)
- {
- dbus_message_ref (message);
+static void
+dbus_message_iter_append_check (DBusMessageRealIter *iter)
+{
+ _dbus_assert (!iter->message->locked);
- iter->refcount = 1;
- iter->message = message;
- iter->pos = 0;
+ if (iter->changed_stamp != iter->message->changed_stamp)
+ _dbus_warn ("dbus iterator check failed: invalid iterator");
+
+ if (iter->pos != iter->end)
+ _dbus_warn ("dbus iterator check failed: can only append at end of message");
+
+ if (iter->pos != _dbus_string_get_length (&iter->message->body))
+ _dbus_warn ("dbus iterator check failed: append pos not at end of message string");
+}
+
+static dbus_bool_t
+dbus_message_iter_append_type (DBusMessageRealIter *iter,
+ int type)
+{
+ switch (iter->type)
+ {
+ case DBUS_MESSAGE_ITER_TYPE_MESSAGE:
+ if (!_dbus_string_append_byte (&iter->message->body, type))
+ return FALSE;
+ break;
+
+ case DBUS_MESSAGE_ITER_TYPE_ARRAY:
+ if (type != iter->container_type)
+ {
+ _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 iter;
+ 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)
+ _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;
}
/**
- * Increments the reference count of a DBusMessageIter.
+ * Appends a nil value to the message
*
- * @param iter the message iter
- * @see dbus_message_iter_unref
+ * @param iter an iterator pointing to the end of the message
+ * @returns #TRUE on success
*/
-void
-dbus_message_iter_ref (DBusMessageIter *iter)
+dbus_bool_t
+dbus_message_iter_append_nil (DBusMessageIter *iter)
{
- _dbus_assert (iter->refcount > 0);
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ dbus_message_iter_append_check (real);
+
+ if (!dbus_message_iter_append_type (real, DBUS_TYPE_NIL))
+ return FALSE;
+
+ dbus_message_iter_append_done (real);
- iter->refcount += 1;
+ return TRUE;
}
/**
- * Decrements the reference count of a DBusMessageIter.
+ * Appends a boolean value to the message
*
- * @param iter The message iter
- * @see dbus_message_iter_ref
+ * @param iter an iterator pointing to the end of the message
+ * @param value the boolean value
+ * @returns #TRUE on success
*/
-void
-dbus_message_iter_unref (DBusMessageIter *iter)
+dbus_bool_t
+dbus_message_iter_append_boolean (DBusMessageIter *iter,
+ dbus_bool_t value)
{
- _dbus_assert (iter->refcount > 0);
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
- iter->refcount -= 1;
+ dbus_message_iter_append_check (real);
- if (iter->refcount == 0)
+ if (!dbus_message_iter_append_type (real, DBUS_TYPE_BOOLEAN))
+ return FALSE;
+
+ if (!_dbus_string_append_byte (&real->message->body, (value != FALSE)))
{
- dbus_message_unref (iter->message);
-
- dbus_free (iter);
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
}
+
+ dbus_message_iter_append_done (real);
+
+ return TRUE;
}
/**
- * Checks if an iterator has any more fields.
+ * Appends a byte to the message
*
- * @param iter the message iter
- * @returns #TRUE if there are more fields
- * following
+ * @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_has_next (DBusMessageIter *iter)
+dbus_message_iter_append_byte (DBusMessageIter *iter,
+ unsigned char value)
{
- int end_pos;
-
- if (!_dbus_marshal_get_arg_end_pos (&iter->message->body,
- iter->message->byte_order,
- iter->pos, &end_pos))
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ dbus_message_iter_append_check (real);
+
+ if (!dbus_message_iter_append_type (real, DBUS_TYPE_BOOLEAN))
return FALSE;
- if (end_pos >= _dbus_string_get_length (&iter->message->body))
- 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;
+ return TRUE;
}
+
/**
- * Moves the iterator to the next field.
+ * Appends a 32 bit signed integer to the message.
*
- * @param iter The message iter
- * @returns #TRUE if the iterator was moved to the next field
+ * @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_next (DBusMessageIter *iter)
+dbus_message_iter_append_int32 (DBusMessageIter *iter,
+ dbus_int32_t value)
{
- int end_pos;
-
- if (!_dbus_marshal_get_arg_end_pos (&iter->message->body,
- iter->message->byte_order,
- iter->pos, &end_pos))
- return FALSE;
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
- if (end_pos >= _dbus_string_get_length (&iter->message->body))
- return FALSE;
+ dbus_message_iter_append_check (real);
- iter->pos = end_pos;
+ 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;
}
/**
- * Returns the argument type of the argument that the
- * message iterator points at.
+ * Appends a 32 bit unsigned integer to the message.
*
- * @param iter the message iter
- * @returns the field type
+ * @param iter an iterator pointing to the end of the message
+ * @param value the integer value
+ * @returns #TRUE on success
*/
-int
-dbus_message_iter_get_arg_type (DBusMessageIter *iter)
+dbus_bool_t
+dbus_message_iter_append_uint32 (DBusMessageIter *iter,
+ dbus_uint32_t value)
{
- const char *data;
-
- if (iter->pos >= _dbus_string_get_length (&iter->message->body))
- return DBUS_TYPE_INVALID;
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
- data = _dbus_string_get_const_data_len (&iter->message->body, iter->pos, 1);
+ dbus_message_iter_append_check (real);
- if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_DICT)
- return *data;
+ 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;
+ }
- return DBUS_TYPE_INVALID;
+ dbus_message_iter_append_done (real);
+
+ return TRUE;
}
/**
- * Returns the string value that an iterator may point to.
- * Note that you need to check that the iterator points to
- * a string value before using this function.
+ * Appends a double value to the message.
*
- * @see dbus_message_iter_get_arg_type
- * @param iter the message iter
- * @returns the string
+ * @param iter an iterator pointing to the end of the message
+ * @param value the double value
+ * @returns #TRUE on success
*/
-char *
-dbus_message_iter_get_string (DBusMessageIter *iter)
+dbus_bool_t
+dbus_message_iter_append_double (DBusMessageIter *iter,
+ double value)
{
- _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_STRING);
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ dbus_message_iter_append_check (real);
+
+ 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;
+ }
- return _dbus_demarshal_string (&iter->message->body, iter->message->byte_order,
- iter->pos + 1, NULL);
+ dbus_message_iter_append_done (real);
+
+ return TRUE;
}
/**
- * Returns the boolean value that an iterator may point to.
- * Note that you need to check that the iterator points to
- * a boolean value before using this function.
+ * Appends a UTF-8 string to the message.
*
- * @see dbus_message_iter_get_arg_type
- * @param iter the message iter
- * @returns the string
+ * @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_get_boolean (DBusMessageIter *iter)
+dbus_message_iter_append_string (DBusMessageIter *iter,
+ const char *value)
{
- unsigned char value;
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ dbus_message_iter_append_check (real);
+
+ if (!dbus_message_iter_append_type (real, DBUS_TYPE_STRING))
+ return FALSE;
- _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_BOOLEAN);
+ if (!_dbus_marshal_string (&real->message->body, real->message->byte_order, value))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
- value = _dbus_string_get_byte (&iter->message->body, iter->pos + 1);
+ dbus_message_iter_append_done (real);
- return value;
+ return TRUE;
}
/**
- * Returns the 32 bit signed integer value that an iterator may point to.
- * Note that you need to check that the iterator points to
- * an integer value before using this function.
+ * Appends a named type data chunk to the message.
*
- * @see dbus_message_iter_get_arg_type
- * @param iter the message iter
- * @returns the integer
+ * @param iter an iterator pointing to the end of the message
+ * @param name the name of the type
+ * @parame
+ * @returns #TRUE on success
*/
-int
-dbus_message_iter_get_int32 (DBusMessageIter *iter)
+dbus_bool_t
+dbus_message_iter_append_named (DBusMessageIter *iter,
+ const char *name,
+ const unsigned char *data,
+ int len)
{
- _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_INT32);
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ dbus_message_iter_append_check (real);
+
+ if (!dbus_message_iter_append_type (real, DBUS_TYPE_NAMED))
+ return FALSE;
+
+ if (!_dbus_marshal_string (&real->message->body, real->message->byte_order, data))
+ {
+ _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 _dbus_demarshal_int32 (&iter->message->body, iter->message->byte_order,
- iter->pos + 1, NULL);
+ return TRUE;
}
+
/**
- * Returns the 32 bit unsigned integer value that an iterator may point to.
- * Note that you need to check that the iterator points to
- * an unsigned integer value before using this function.
+ * Appends a dict key name to the message. The iterator used
+ * must point to a dict.
*
- * @see dbus_message_iter_get_arg_type
- * @param iter the message iter
- * @returns the integer
+ * @param iter an iterator pointing to the end of the message
+ * @param value the string
+ * @returns #TRUE on success
*/
-int
-dbus_message_iter_get_uint32 (DBusMessageIter *iter)
+dbus_bool_t
+dbus_message_iter_append_dict_key (DBusMessageIter *iter,
+ const char *value)
{
- _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_UINT32);
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ dbus_message_iter_append_check (real);
+ _dbus_assert (real->type == DBUS_MESSAGE_ITER_TYPE_DICT);
+
+ if (real->wrote_dict_key)
+ {
+ _dbus_warn ("Appendinging multiple dict key names\n");
+ return FALSE;
+ }
- return _dbus_demarshal_uint32 (&iter->message->body, iter->message->byte_order,
- iter->pos + 1, NULL);
+ 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;
}
/**
- * Returns the double value that an iterator may point to.
- * Note that you need to check that the iterator points to
- * a string value before using this function.
+ * Appends an array to the message and initializes an iterator that
+ * can be used to append to the array.
*
- * @see dbus_message_iter_get_arg_type
- * @param iter the message iter
- * @returns the double
+ * @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
*/
-double
-dbus_message_iter_get_double (DBusMessageIter *iter)
+dbus_bool_t
+dbus_message_iter_append_array (DBusMessageIter *iter,
+ DBusMessageIter *array_iter,
+ int element_type)
{
- _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_DOUBLE);
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+ DBusMessageRealIter *array_real = (DBusMessageRealIter *)array_iter;
+ int len_pos;
+
+ dbus_message_iter_append_check (real);
+
+ if (!dbus_message_iter_append_type (real, DBUS_TYPE_ARRAY))
+ return FALSE;
+
+ if (!_dbus_string_append_byte (&real->message->body, element_type))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ 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;
+ }
+
+ 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_type = element_type;
+ array_real->container_start = array_real->pos;
+ array_real->container_length_pos = len_pos;
+ array_real->wrote_dict_key = 0;
+
+ dbus_message_iter_append_done (array_real);
- return _dbus_demarshal_double (&iter->message->body, iter->message->byte_order,
- iter->pos + 1, NULL);
+ return TRUE;
}
/**
- * Returns the boolean 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.
+ * Appends a dict to the message and initializes an iterator that
+ * can be used to append to the dict.
*
- * @param iter the iterator
- * @param value return location for the array
- * @param len return location for the array length
+ * @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_get_boolean_array (DBusMessageIter *iter,
- unsigned char **value,
- int *len)
+dbus_message_iter_append_dict (DBusMessageIter *iter,
+ DBusMessageIter *dict_iter)
{
- _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_BOOLEAN_ARRAY);
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+ DBusMessageRealIter *dict_real = (DBusMessageRealIter *)dict_iter;
+ int len_pos;
- if (!_dbus_demarshal_byte_array (&iter->message->body, iter->message->byte_order,
- iter->pos + 1, NULL, value, len))
+ dbus_message_iter_append_check (real);
+
+ if (!dbus_message_iter_append_type (real, DBUS_TYPE_DICT))
return FALSE;
- else
- return TRUE;
+
+ 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_type = 0;
+ 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;
}
+
/**
- * Returns the 32 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.
+ * Appends a boolean array to the message.
*
- * @param iter the iterator
- * @param value return location for the array
- * @param len return location for the array length
+ * @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_get_int32_array (DBusMessageIter *iter,
- dbus_int32_t **value,
- int *len)
+dbus_message_iter_append_boolean_array (DBusMessageIter *iter,
+ unsigned const char *value,
+ int len)
{
- _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_INT32_ARRAY);
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ dbus_message_iter_append_check (real);
- if (!_dbus_demarshal_int32_array (&iter->message->body, iter->message->byte_order,
- iter->pos + 1, NULL, value, len))
+ if (!dbus_message_iter_append_type (real, DBUS_TYPE_ARRAY))
return FALSE;
- else
- return TRUE;
+
+ if (!_dbus_string_append_byte (&real->message->body, DBUS_TYPE_BOOLEAN))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ 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;
}
/**
- * Returns the 32 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.
+ * Appends a 32 bit signed integer array to the message.
*
- * @param iter the iterator
- * @param value return location for the array
- * @param len return location for the array length
+ * @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_get_uint32_array (DBusMessageIter *iter,
- dbus_uint32_t **value,
- int *len)
+dbus_bool_t
+dbus_message_iter_append_int32_array (DBusMessageIter *iter,
+ const dbus_int32_t *value,
+ int len)
{
- _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_UINT32_ARRAY);
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ dbus_message_iter_append_check (real);
- if (!_dbus_demarshal_uint32_array (&iter->message->body, iter->message->byte_order,
- iter->pos + 1, NULL, value, len))
+ if (!dbus_message_iter_append_type (real, DBUS_TYPE_ARRAY))
return FALSE;
- else
- return TRUE;
+
+ if (!_dbus_string_append_byte (&real->message->body, DBUS_TYPE_INT32))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ 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;
}
/**
- * 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.
+ * Appends a 32 bit unsigned integer array to the message.
*
- * @param iter the iterator
- * @param value return location for the array
- * @param len return location for the array length
+ * @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_get_double_array (DBusMessageIter *iter,
- double **value,
- int *len)
+dbus_message_iter_append_uint32_array (DBusMessageIter *iter,
+ const dbus_uint32_t *value,
+ int len)
{
- _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_DOUBLE_ARRAY);
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ dbus_message_iter_append_check (real);
- if (!_dbus_demarshal_double_array (&iter->message->body, iter->message->byte_order,
- iter->pos + 1, NULL, value, len))
+ if (!dbus_message_iter_append_type (real, DBUS_TYPE_ARRAY))
return FALSE;
- else
- return TRUE;
+
+ if (!_dbus_string_append_byte (&real->message->body, DBUS_TYPE_UINT32))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ 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;
}
/**
- * Returns the byte 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.
+ * Appends a double array to the message.
*
- * @param iter the iterator
- * @param value return location for array values
- * @param len return location for length of byte array
+ * @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_get_byte_array (DBusMessageIter *iter,
- unsigned char **value,
- int *len)
+dbus_message_iter_append_double_array (DBusMessageIter *iter,
+ const double *value,
+ int len)
{
- _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_BYTE_ARRAY);
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ dbus_message_iter_append_check (real);
- if (!_dbus_demarshal_byte_array (&iter->message->body, iter->message->byte_order,
- iter->pos + 1, NULL, value, len))
+ if (!dbus_message_iter_append_type (real, DBUS_TYPE_ARRAY))
return FALSE;
- else
- return TRUE;
+
+ if (!_dbus_string_append_byte (&real->message->body, DBUS_TYPE_DOUBLE))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ 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;
}
/**
- * 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().
+ * Appends a byte array to the message.
*
- * @param iter the iterator
- * @param value return location for string values
- * @param len return location for length of byte array
+ * @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_get_string_array (DBusMessageIter *iter,
- char ***value,
- int *len)
+dbus_message_iter_append_byte_array (DBusMessageIter *iter,
+ unsigned const char *value,
+ int len)
{
- _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_STRING_ARRAY);
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
- if (!_dbus_demarshal_string_array (&iter->message->body, iter->message->byte_order,
- iter->pos + 1, NULL, value, len))
+ dbus_message_iter_append_check (real);
+
+ if (!dbus_message_iter_append_type (real, DBUS_TYPE_ARRAY))
return FALSE;
- else
- return TRUE;
+
+ if (!_dbus_string_append_byte (&real->message->body, DBUS_TYPE_BYTE))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ 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;
}
/**
- * Returns the dict that the iterator may point to.
- * Note that you need to check that the iterator points
- * to a dict prior to using this function.
+ * Appends a string array to the message.
*
- * @param iter the iterator
- * @param dict return location for dict
+ * @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_get_dict (DBusMessageIter *iter,
- DBusDict **dict)
+dbus_message_iter_append_string_array (DBusMessageIter *iter,
+ const char **value,
+ int len)
{
- _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_DICT);
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ dbus_message_iter_append_check (real);
- if (!_dbus_demarshal_dict (&iter->message->body, iter->message->byte_order,
- iter->pos + 1, NULL, dict))
+ if (!dbus_message_iter_append_type (real, DBUS_TYPE_ARRAY))
return FALSE;
- else
- return TRUE;
+
+ if (!_dbus_string_append_byte (&real->message->body, DBUS_TYPE_BYTE))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ 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;
}
/**
const char *field;
int pos, new_pos;
int i;
+ int type;
if (header_len < 16)
return FALSE;
field[0], field[1], field[2], field[3], pos);
}
- if (!_dbus_marshal_validate_arg (data, byte_order, pos, &new_pos))
+ if (!_dbus_marshal_validate_type (data, pos, &type, &pos))
+ {
+ _dbus_verbose ("Failed to validate type of named header field\n");
+ return FALSE;
+ }
+
+ if (!_dbus_marshal_validate_arg (data, byte_order, type, pos, &new_pos))
{
_dbus_verbose ("Failed to validate argument to named header field\n");
return FALSE;
next_arg = header_len;
while (next_arg < (header_len + body_len))
{
+ int type;
int prev = next_arg;
+ if (!_dbus_marshal_validate_type (&loader->data, next_arg,
+ &type, &next_arg))
+ {
+ _dbus_verbose ("invalid typecode at offset %d\n", prev);
+ loader->corrupted = TRUE;
+ return TRUE;
+ }
+
if (!_dbus_marshal_validate_arg (&loader->data,
byte_order,
+ type,
next_arg,
&next_arg))
{
+ _dbus_verbose ("invalid type data at %d, next_arg\n", next_arg);
loader->corrupted = TRUE;
return TRUE;
}
static void
message_iter_test (DBusMessage *message)
{
- DBusMessageIter *iter;
+ DBusMessageIter iter, dict, array;
char *str;
- iter = dbus_message_get_args_iter (message);
+ dbus_message_iter_init (message, &iter);
/* String tests */
- if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_STRING)
+ if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING)
_dbus_assert_not_reached ("Argument type isn't string");
- str = dbus_message_iter_get_string (iter);
+ str = dbus_message_iter_get_string (&iter);
if (strcmp (str, "Test string") != 0)
_dbus_assert_not_reached ("Strings differ");
dbus_free (str);
- if (!dbus_message_iter_next (iter))
+ if (!dbus_message_iter_next (&iter))
_dbus_assert_not_reached ("Reached end of arguments");
/* Signed integer tests */
- if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_INT32)
+ if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INT32)
_dbus_assert_not_reached ("Argument type isn't int32");
- if (dbus_message_iter_get_int32 (iter) != -0x12345678)
+ if (dbus_message_iter_get_int32 (&iter) != -0x12345678)
_dbus_assert_not_reached ("Signed integers differ");
- if (!dbus_message_iter_next (iter))
+ if (!dbus_message_iter_next (&iter))
_dbus_assert_not_reached ("Reached end of fields");
/* Unsigned integer tests */
- if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_UINT32)
+ if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_UINT32)
_dbus_assert_not_reached ("Argument type isn't int32");
- if (dbus_message_iter_get_uint32 (iter) != 0xedd1e)
+ if (dbus_message_iter_get_uint32 (&iter) != 0xedd1e)
_dbus_assert_not_reached ("Unsigned integers differ");
- if (!dbus_message_iter_next (iter))
+ if (!dbus_message_iter_next (&iter))
_dbus_assert_not_reached ("Reached end of arguments");
/* Double tests */
- if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_DOUBLE)
+ if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_DOUBLE)
_dbus_assert_not_reached ("Argument type isn't double");
- if (dbus_message_iter_get_double (iter) != 3.14159)
+ if (dbus_message_iter_get_double (&iter) != 3.14159)
_dbus_assert_not_reached ("Doubles differ");
- if (dbus_message_iter_next (iter))
+ if (!dbus_message_iter_next (&iter))
+ _dbus_assert_not_reached ("Reached end of arguments");
+
+ if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY)
+ _dbus_assert_not_reached ("Argument type not an array");
+
+ if (dbus_message_iter_get_array_type (&iter) != DBUS_TYPE_UINT32)
+ _dbus_assert_not_reached ("Array type not uint32");
+
+
+ if (!dbus_message_iter_init_array_iterator (&iter, &array, NULL))
+ _dbus_assert_not_reached ("Array init failed");
+
+ if (dbus_message_iter_get_arg_type (&array) != DBUS_TYPE_UINT32)
+ _dbus_assert_not_reached ("Argument type isn't int32");
+
+ if (dbus_message_iter_get_uint32 (&array) != 0x12345678)
+ _dbus_assert_not_reached ("Unsigned integers differ");
+
+ if (!dbus_message_iter_next (&array))
+ _dbus_assert_not_reached ("Reached end of arguments");
+
+ if (dbus_message_iter_get_arg_type (&array) != DBUS_TYPE_UINT32)
+ _dbus_assert_not_reached ("Argument type isn't int32");
+
+ if (dbus_message_iter_get_uint32 (&array) != 0x23456781)
+ _dbus_assert_not_reached ("Unsigned integers differ");
+
+ if (dbus_message_iter_next (&array))
_dbus_assert_not_reached ("Didn't reach end of arguments");
- dbus_message_iter_unref (iter);
+ if (!dbus_message_iter_next (&iter))
+ _dbus_assert_not_reached ("Reached end of arguments");
+
+ if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_DICT)
+ _dbus_assert_not_reached ("not dict type");
+
+ if (!dbus_message_iter_init_dict_iterator (&iter, &dict))
+ _dbus_assert_not_reached ("dict iter failed");
+
+ str = dbus_message_iter_get_dict_key (&dict);
+ if (str == NULL || strcmp (str, "test") != 0)
+ _dbus_assert_not_reached ("wrong dict key");
+ dbus_free (str);
+
+ if (dbus_message_iter_get_arg_type (&dict) != DBUS_TYPE_UINT32)
+ _dbus_assert_not_reached ("wrong dict entry type");
+
+ if (dbus_message_iter_get_uint32 (&dict) != 0xDEADBEEF)
+ _dbus_assert_not_reached ("wrong dict entry value");
+
+ if (dbus_message_iter_next (&dict))
+ _dbus_assert_not_reached ("Didn't reach end of dict");
+
+ if (!dbus_message_iter_next (&iter))
+ _dbus_assert_not_reached ("Reached end of arguments");
+
+ if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_UINT32)
+ _dbus_assert_not_reached ("wrong type after dict");
+
+ if (dbus_message_iter_get_uint32 (&iter) != 0xCAFEBABE)
+ _dbus_assert_not_reached ("wrong value after dict");
+
+ if (dbus_message_iter_next (&iter))
+ _dbus_assert_not_reached ("Didn't reach end of arguments");
}
+
+static dbus_bool_t
+check_message_handling_type (DBusMessageIter *iter,
+ int type)
+{
+ DBusMessageIter child_iter;
+
+ switch (type)
+ {
+ case DBUS_TYPE_NIL:
+ break;
+ case DBUS_TYPE_BYTE:
+ dbus_message_iter_get_byte (iter);
+ break;
+ case DBUS_TYPE_BOOLEAN:
+ dbus_message_iter_get_boolean (iter);
+ break;
+ case DBUS_TYPE_INT32:
+ dbus_message_iter_get_int32 (iter);
+ break;
+ case DBUS_TYPE_UINT32:
+ dbus_message_iter_get_uint32 (iter);
+ break;
+ case DBUS_TYPE_DOUBLE:
+ dbus_message_iter_get_double (iter);
+ break;
+ case DBUS_TYPE_STRING:
+ {
+ char *str;
+ str = dbus_message_iter_get_string (iter);
+ if (str == NULL)
+ {
+ _dbus_warn ("NULL string int message\n");
+ return FALSE;
+ }
+ dbus_free (str);
+ }
+ break;
+ case DBUS_TYPE_NAMED:
+ {
+ char *name;
+ unsigned char *data;
+ int len;
+
+ name = dbus_message_iter_get_named (iter, &data, &len);
+ if (name == NULL)
+ {
+ _dbus_warn ("error reading name from named type\n");
+ return FALSE;
+ }
+ dbus_free (data);
+ dbus_free (name);
+ }
+ break;
+ case DBUS_TYPE_ARRAY:
+ {
+ int array_type;
+
+ if (!dbus_message_iter_init_array_iterator (iter, &child_iter, &array_type))
+ {
+ _dbus_warn ("Failed to init array iterator\n");
+ return FALSE;
+ }
+
+ while (dbus_message_iter_has_next (&child_iter))
+ {
+ if (!check_message_handling_type (&child_iter, array_type))
+ {
+ _dbus_warn ("error in array element\n");
+ return FALSE;
+ }
+
+ if (!dbus_message_iter_next (&child_iter))
+ break;
+ }
+ }
+ break;
+ case DBUS_TYPE_DICT:
+ {
+ int entry_type;
+ char *key;
+
+ if (!dbus_message_iter_init_dict_iterator (iter, &child_iter))
+ {
+ _dbus_warn ("Failed to init dict iterator\n");
+ return FALSE;
+ }
+
+ while ((entry_type = dbus_message_iter_get_arg_type (&child_iter)) != DBUS_TYPE_INVALID)
+ {
+ key = dbus_message_iter_get_dict_key (&child_iter);
+ if (key == NULL)
+ {
+ _dbus_warn ("error reading dict key\n");
+ return FALSE;
+ }
+ dbus_free (key);
+
+ if (!check_message_handling_type (&child_iter, entry_type))
+ {
+ _dbus_warn ("error in dict value\n");
+ return FALSE;
+ }
+
+ if (!dbus_message_iter_next (&child_iter))
+ break;
+ }
+ }
+ break;
+
+ default:
+ _dbus_warn ("unknown type %d\n", type);
+ return FALSE;
+ break;
+ }
+ return TRUE;
+}
+
+
static dbus_bool_t
check_message_handling (DBusMessage *message)
{
- DBusMessageIter *iter;
+ DBusMessageIter iter;
int type;
dbus_bool_t retval;
dbus_int32_t client_serial;
retval = FALSE;
- iter = NULL;
client_serial = dbus_message_get_serial (message);
* then we would want to test it here
*/
- iter = dbus_message_get_args_iter (message);
- while ((type = dbus_message_iter_get_arg_type (iter)) != DBUS_TYPE_INVALID)
+ dbus_message_iter_init (message, &iter);
+ while ((type = dbus_message_iter_get_arg_type (&iter)) != DBUS_TYPE_INVALID)
{
- switch (type)
- {
- case DBUS_TYPE_NIL:
- break;
- case DBUS_TYPE_INT32:
- dbus_message_iter_get_int32 (iter);
- break;
- case DBUS_TYPE_UINT32:
- dbus_message_iter_get_uint32 (iter);
- break;
- case DBUS_TYPE_DOUBLE:
- dbus_message_iter_get_double (iter);
- break;
- case DBUS_TYPE_STRING:
- {
- char *str;
- str = dbus_message_iter_get_string (iter);
- dbus_free (str);
- }
- break;
- case DBUS_TYPE_BOOLEAN_ARRAY:
- {
- unsigned char *values;
- int len;
-
- if (!dbus_message_iter_get_boolean_array (iter, &values, &len))
- return FALSE;
- dbus_free (values);
- }
- break;
- case DBUS_TYPE_INT32_ARRAY:
- {
- dbus_int32_t *values;
- int len;
-
- if (!dbus_message_iter_get_int32_array (iter, &values, &len))
- return FALSE;
-
- dbus_free (values);
- }
- break;
- case DBUS_TYPE_UINT32_ARRAY:
- {
- dbus_uint32_t *values;
- int len;
-
- if (!dbus_message_iter_get_uint32_array (iter, &values, &len))
- return FALSE;
-
- dbus_free (values);
- }
- break;
- case DBUS_TYPE_DOUBLE_ARRAY:
- {
- double *values;
- int len;
-
- if (!dbus_message_iter_get_double_array (iter, &values, &len))
- return FALSE;
-
- dbus_free (values);
- }
- break;
- case DBUS_TYPE_STRING_ARRAY:
- {
- char **values;
- int len;
-
- if (!dbus_message_iter_get_string_array (iter, &values, &len))
- return FALSE;
-
- dbus_free_string_array (values);
- }
- break;
-
- case DBUS_TYPE_DICT:
- {
- DBusDict *dict;
-
- if (!dbus_message_iter_get_dict (iter, &dict))
- return FALSE;
- dbus_dict_unref (dict);
- }
- break;
+ if (!check_message_handling_type (&iter, type))
+ goto failed;
- default:
- break;
- }
-
- if (!dbus_message_iter_next (iter))
+ if (!dbus_message_iter_next (&iter))
break;
}
-
+
retval = TRUE;
failed:
- if (iter)
- dbus_message_iter_unref (iter);
-
return retval;
}
{
DBusError error;
+ _dbus_verbose ("Loading raw %s\n", _dbus_string_get_const_data (filename));
dbus_error_init (&error);
if (!_dbus_file_get_contents (data, filename, &error))
{
char *our_str;
double our_double;
dbus_bool_t our_bool;
-
- if (!dbus_message_get_args (message, NULL,
- DBUS_TYPE_INT32, &our_int,
- DBUS_TYPE_STRING, &our_str,
- DBUS_TYPE_DOUBLE, &our_double,
- DBUS_TYPE_BOOLEAN, &our_bool,
- 0))
- _dbus_assert_not_reached ("Could not get arguments");
+ dbus_int32_t *our_int_array;
+ int our_int_array_len;
+ DBusMessageIter iter, dict;
+ DBusError error;
+
+ dbus_message_iter_init (message, &iter);
+
+ dbus_error_init (&error);
+ if (!dbus_message_iter_get_args (&iter, &error,
+ DBUS_TYPE_INT32, &our_int,
+ DBUS_TYPE_STRING, &our_str,
+ DBUS_TYPE_DOUBLE, &our_double,
+ DBUS_TYPE_BOOLEAN, &our_bool,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &our_int_array, &our_int_array_len,
+ 0))
+ {
+ _dbus_verbose ("error: %s - %s\n", error.name, (error.message != NULL)?error.message: "no message");
+ _dbus_assert_not_reached ("Could not get arguments");
+ }
if (our_int != -0x12345678)
_dbus_assert_not_reached ("integers differ!");
if (strcmp (our_str, "Test string") != 0)
_dbus_assert_not_reached ("strings differ!");
+ dbus_free (our_str);
if (!our_bool)
_dbus_assert_not_reached ("booleans differ");
-
+
+ if (our_int_array_len != 4 ||
+ our_int_array[0] != 0x12345678 ||
+ our_int_array[1] != 0x23456781 ||
+ our_int_array[2] != 0x34567812 ||
+ our_int_array[3] != 0x45678123)
+ _dbus_assert_not_reached ("array differ");
+ dbus_free (our_int_array);
+
+ if (!dbus_message_iter_next (&iter))
+ _dbus_assert_not_reached ("Reached end of arguments");
+
+ if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_DICT)
+ _dbus_assert_not_reached ("not dict type");
+
+ if (!dbus_message_iter_init_dict_iterator (&iter, &dict))
+ _dbus_assert_not_reached ("dict iter failed");
+
+ our_str = dbus_message_iter_get_dict_key (&dict);
+ if (our_str == NULL || strcmp (our_str, "test") != 0)
+ _dbus_assert_not_reached ("wrong dict key");
dbus_free (our_str);
+
+ if (dbus_message_iter_get_arg_type (&dict) != DBUS_TYPE_UINT32)
+ {
+ _dbus_verbose ("dict entry type: %d\n", dbus_message_iter_get_arg_type (&dict));
+ _dbus_assert_not_reached ("wrong dict entry type");
+ }
+
+ if (dbus_message_iter_get_uint32 (&dict) != 0xDEADBEEF)
+ _dbus_assert_not_reached ("wrong dict entry value");
+
+ if (dbus_message_iter_next (&dict))
+ _dbus_assert_not_reached ("Didn't reach end of dict");
+
+ if (!dbus_message_iter_next (&iter))
+ _dbus_assert_not_reached ("Reached end of arguments");
+
+ if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_UINT32)
+ _dbus_assert_not_reached ("wrong type after dict");
+
+ if (dbus_message_iter_get_uint32 (&iter) != 0xCAFEBABE)
+ _dbus_assert_not_reached ("wrong value after dict");
+
+ if (dbus_message_iter_next (&iter))
+ _dbus_assert_not_reached ("Didn't reach end of arguments");
}
/**
{
DBusMessage *message;
DBusMessageLoader *loader;
+ DBusMessageIter iter, child_iter;
int i;
const char *data;
DBusMessage *copy;
const char *name1;
const char *name2;
-
+ const dbus_uint32_t our_int32_array[] = { 0x12345678, 0x23456781, 0x34567812, 0x45678123 };
+
+
+ _dbus_assert (sizeof (DBusMessageRealIter) == sizeof (DBusMessageIter));
+
/* Test the vararg functions */
message = dbus_message_new ("org.freedesktop.DBus.Test", "testMessage");
_dbus_message_set_serial (message, 1);
DBUS_TYPE_STRING, "Test string",
DBUS_TYPE_DOUBLE, 3.14159,
DBUS_TYPE_BOOLEAN, TRUE,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, our_int32_array, 4,
0);
+
+ dbus_message_append_iter_init (message, &iter);
+ dbus_message_iter_append_dict (&iter, &child_iter);
+ dbus_message_iter_append_dict_key (&child_iter, "test");
+ dbus_message_iter_append_uint32 (&child_iter, 0xDEADBEEF);
+ dbus_message_iter_append_uint32 (&iter, 0xCAFEBABE);
+
_dbus_verbose_bytes_of_string (&message->header, 0,
_dbus_string_get_length (&message->header));
_dbus_verbose_bytes_of_string (&message->body, 0,
_dbus_message_set_serial (message, 1);
dbus_message_set_reply_serial (message, 0x12345678);
- dbus_message_append_string (message, "Test string");
- dbus_message_append_int32 (message, -0x12345678);
- dbus_message_append_uint32 (message, 0xedd1e);
- dbus_message_append_double (message, 3.14159);
+ dbus_message_append_iter_init (message, &iter);
+ dbus_message_iter_append_string (&iter, "Test string");
+ dbus_message_iter_append_int32 (&iter, -0x12345678);
+ dbus_message_iter_append_uint32 (&iter, 0xedd1e);
+ dbus_message_iter_append_double (&iter, 3.14159);
+ dbus_message_iter_append_array (&iter, &child_iter, DBUS_TYPE_UINT32);
+ dbus_message_iter_append_uint32 (&child_iter, 0x12345678);
+ dbus_message_iter_append_uint32 (&child_iter, 0x23456781);
+
+ dbus_message_iter_append_dict (&iter, &child_iter);
+ dbus_message_iter_append_dict_key (&child_iter, "test");
+ dbus_message_iter_append_uint32 (&child_iter, 0xDEADBEEF);
+ dbus_message_iter_append_uint32 (&iter, 0xCAFEBABE);
+
message_iter_test (message);
/* Message loader test */