From ee09dbf058bec7edd55deb2dbca67e7f0885b160 Mon Sep 17 00:00:00 2001 From: Anders Carlsson Date: Thu, 6 Mar 2003 23:11:49 +0000 Subject: [PATCH] 2003-03-07 Anders Carlsson * dbus/Makefile.am: Add dbus-dict.[ch] * dbus/dbus-dict.c: (dbus_dict_entry_free), (dbus_dict_new), (dbus_dict_ref), (dbus_dict_unref), (dbus_dict_contains), (dbus_dict_remove), (dbus_dict_get_value_type), (dbus_dict_get_keys), (dbus_dict_put_boolean), (dbus_dict_put_int32), (dbus_dict_put_uint32), (dbus_dict_put_double), (dbus_dict_put_string), (dbus_dict_put_boolean_array), (dbus_dict_put_int32_array), (dbus_dict_put_uint32_array), (dbus_dict_put_double_array), (dbus_dict_put_string_array), (dbus_dict_get_boolean), (dbus_dict_get_int32), (dbus_dict_get_uint32), (dbus_dict_get_double), (dbus_dict_get_string), (dbus_dict_get_boolean_array), (dbus_dict_get_int32_array), (dbus_dict_get_uint32_array), (dbus_dict_get_double_array), (dbus_dict_get_string_array), (_dbus_dict_test): * dbus/dbus-dict.h: Add DBusDict implementation * dbus/dbus-test.c: (dbus_internal_do_not_use_run_tests): * dbus/dbus-test.h: Add _dbus_dict_test. --- ChangeLog | 26 ++ dbus/Makefile.am | 6 +- dbus/dbus-dict.c | 1172 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ dbus/dbus-dict.h | 131 ++++++ dbus/dbus-test.c | 10 +- dbus/dbus-test.h | 1 + 6 files changed, 1341 insertions(+), 5 deletions(-) create mode 100644 dbus/dbus-dict.c create mode 100644 dbus/dbus-dict.h diff --git a/ChangeLog b/ChangeLog index ab0abd9..a023a1c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,29 @@ +2003-03-07 Anders Carlsson + + * dbus/Makefile.am: + Add dbus-dict.[ch] + + * dbus/dbus-dict.c: (dbus_dict_entry_free), (dbus_dict_new), + (dbus_dict_ref), (dbus_dict_unref), (dbus_dict_contains), + (dbus_dict_remove), (dbus_dict_get_value_type), + (dbus_dict_get_keys), (dbus_dict_put_boolean), + (dbus_dict_put_int32), (dbus_dict_put_uint32), + (dbus_dict_put_double), (dbus_dict_put_string), + (dbus_dict_put_boolean_array), (dbus_dict_put_int32_array), + (dbus_dict_put_uint32_array), (dbus_dict_put_double_array), + (dbus_dict_put_string_array), (dbus_dict_get_boolean), + (dbus_dict_get_int32), (dbus_dict_get_uint32), + (dbus_dict_get_double), (dbus_dict_get_string), + (dbus_dict_get_boolean_array), (dbus_dict_get_int32_array), + (dbus_dict_get_uint32_array), (dbus_dict_get_double_array), + (dbus_dict_get_string_array), (_dbus_dict_test): + * dbus/dbus-dict.h: + Add DBusDict implementation + + * dbus/dbus-test.c: (dbus_internal_do_not_use_run_tests): + * dbus/dbus-test.h: + Add _dbus_dict_test + 2003-03-04 Havoc Pennington * test/data/auth/*: adapt to changes diff --git a/dbus/Makefile.am b/dbus/Makefile.am index dfcfb7d..622d964 100644 --- a/dbus/Makefile.am +++ b/dbus/Makefile.am @@ -10,6 +10,7 @@ dbusinclude_HEADERS= \ dbus-address.h \ dbus-bus.h \ dbus-connection.h \ + dbus-dict.h \ dbus-errors.h \ dbus-macros.h \ dbus-memory.h \ @@ -29,6 +30,7 @@ libdbus_1_la_SOURCES= \ dbus-bus.c \ dbus-connection.c \ dbus-connection-internal.h \ + dbus-dict.c \ dbus-errors.c \ dbus-keyring.c \ dbus-keyring.h \ @@ -97,7 +99,7 @@ libdbus_convenience_la_SOURCES= \ libdbus_1_la_LIBADD= $(DBUS_CLIENT_LIBS) libdbus-convenience.la ## don't export symbols that start with "_" (we use this ## convention for internal symbols) -libdbus_1_la_LDFLAGS= -export-symbols-regex "^[^_].*" +#libdbus_1_la_LDFLAGS= -export-symbols-regex "^[^_].*" ## FIXME it would be less annoying when hacking if we didn't have ## to relink these test binaries, so moving them to the test/* @@ -124,4 +126,4 @@ dbus_test_LDADD= $(DBUS_CLIENT_LIBS) libdbus-convenience.la libdbus-1.la ## mop up the gcov files clean-local: - /bin/rm *.bb *.bbg *.da *.gcov || true \ No newline at end of file + /bin/rm *.bb *.bbg *.da *.gcov || true diff --git a/dbus/dbus-dict.c b/dbus/dbus-dict.c new file mode 100644 index 0000000..334a874 --- /dev/null +++ b/dbus/dbus-dict.c @@ -0,0 +1,1172 @@ +/* -*- 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; + } boolean_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_BOOLEAN_ARRAY: + dbus_free (entry->v.boolean_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); + 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); + 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; +} + +/** + * 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_put_boolean (DBusDict *dict, + const char *key, + dbus_bool_t value) +{ + DBusDictEntry *entry; + char *tmp; + + entry = dbus_new0 (DBusDictEntry, 1); + + if (!entry) + return FALSE; + + entry->type = DBUS_TYPE_BOOLEAN; + entry->v.boolean_value = value; + + tmp = _dbus_strdup (key); + + if (!tmp) + { + dbus_dict_entry_free (entry); + 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 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_put_int32 (DBusDict *dict, + const char *key, + dbus_int32_t value) +{ + DBusDictEntry *entry; + char *tmp; + + entry = dbus_new0 (DBusDictEntry, 1); + + if (!entry) + return FALSE; + + entry->type = DBUS_TYPE_INT32; + entry->v.int32_value = value; + + tmp = _dbus_strdup (key); + + if (!tmp) + { + dbus_dict_entry_free (entry); + 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 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_put_uint32 (DBusDict *dict, + const char *key, + dbus_uint32_t value) +{ + DBusDictEntry *entry; + char *tmp; + + entry = dbus_new0 (DBusDictEntry, 1); + + if (!entry) + return FALSE; + + entry->type = DBUS_TYPE_UINT32; + entry->v.uint32_value = value; + + tmp = _dbus_strdup (key); + + if (!tmp) + { + dbus_dict_entry_free (entry); + 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 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_put_double (DBusDict *dict, + const char *key, + double value) +{ + DBusDictEntry *entry; + char *tmp; + + entry = dbus_new0 (DBusDictEntry, 1); + + if (!entry) + return FALSE; + + entry->type = DBUS_TYPE_DOUBLE; + entry->v.double_value = value; + + tmp = _dbus_strdup (key); + + if (!tmp) + { + dbus_dict_entry_free (entry); + 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 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_put_string (DBusDict *dict, + const char *key, + const char *value) +{ + DBusDictEntry *entry; + char *tmp; + + entry = dbus_new0 (DBusDictEntry, 1); + + if (!entry) + return FALSE; + + entry->type = DBUS_TYPE_STRING; + entry->v.string_value = _dbus_strdup (value); + + if (!entry->v.string_value) + { + dbus_dict_entry_free (entry); + return FALSE; + } + + tmp = _dbus_strdup (key); + + if (!tmp) + { + dbus_dict_entry_free (entry); + 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 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_put_boolean_array (DBusDict *dict, + const char *key, + unsigned const char *value, + int len) +{ + DBusDictEntry *entry; + char *tmp; + + entry = dbus_new0 (DBusDictEntry, 1); + + if (!entry) + return FALSE; + + entry->type = DBUS_TYPE_BOOLEAN_ARRAY; + + entry->v.boolean_array.value = dbus_malloc (len); + + if (!entry->v.boolean_array.value) + { + dbus_dict_entry_free (entry); + return FALSE; + } + memcpy (entry->v.boolean_array.value, value, len); + entry->v.boolean_array.len = len; + + tmp = _dbus_strdup (key); + + if (!tmp) + { + dbus_dict_entry_free (entry); + 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 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_put_int32_array (DBusDict *dict, + const char *key, + const dbus_int32_t *value, + int len) +{ + DBusDictEntry *entry; + char *tmp; + + entry = dbus_new0 (DBusDictEntry, 1); + + if (!entry) + return FALSE; + + entry->type = DBUS_TYPE_INT32_ARRAY; + entry->v.int32_array.value = dbus_malloc (len * sizeof (dbus_int32_t)); + + if (!entry->v.int32_array.value) + { + dbus_dict_entry_free (entry); + return FALSE; + } + memcpy (entry->v.int32_array.value, value, len * sizeof (dbus_int32_t)); + entry->v.int32_array.len = len; + + tmp = _dbus_strdup (key); + + if (!tmp) + { + dbus_dict_entry_free (entry); + 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 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_put_uint32_array (DBusDict *dict, + const char *key, + const dbus_uint32_t *value, + int len) +{ + DBusDictEntry *entry; + char *tmp; + + entry = dbus_new0 (DBusDictEntry, 1); + + if (!entry) + return FALSE; + + entry->type = DBUS_TYPE_UINT32_ARRAY; + entry->v.uint32_array.value = dbus_malloc (len * sizeof (dbus_uint32_t)); + + if (!entry->v.uint32_array.value) + { + dbus_dict_entry_free (entry); + return FALSE; + } + memcpy (entry->v.uint32_array.value, value, len * sizeof (dbus_uint32_t)); + entry->v.uint32_array.len = len; + + tmp = _dbus_strdup (key); + + if (!tmp) + { + dbus_dict_entry_free (entry); + 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 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_put_double_array (DBusDict *dict, + const char *key, + const double *value, + int len) +{ + DBusDictEntry *entry; + char *tmp; + + entry = dbus_new0 (DBusDictEntry, 1); + + if (!entry) + return FALSE; + + entry->type = DBUS_TYPE_DOUBLE_ARRAY; + entry->v.double_array.value = dbus_malloc (len * sizeof (double)); + + if (!entry->v.double_array.value) + { + dbus_dict_entry_free (entry); + return FALSE; + } + memcpy (entry->v.double_array.value, value, len * sizeof (double)); + entry->v.double_array.len = len; + + tmp = _dbus_strdup (key); + + if (!tmp) + { + dbus_dict_entry_free (entry); + 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 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_put_string_array (DBusDict *dict, + const char *key, + const char **value, + int len) +{ + DBusDictEntry *entry; + char *tmp; + int i; + + entry = dbus_new0 (DBusDictEntry, 1); + + if (!entry) + return FALSE; + + entry->type = DBUS_TYPE_STRING_ARRAY; + entry->v.string_array.value = dbus_new0 (char *, len + 1); + + if (!entry->v.string_array.value) + { + dbus_dict_entry_free (entry); + return FALSE; + } + + entry->v.string_array.len = len; + for (i = 0; i < len; i++) + { + entry->v.string_array.value[i] = _dbus_strdup (value[i]); + if (!entry->v.string_array.value[i]) + { + dbus_dict_entry_free (entry); + return FALSE; + } + } + + tmp = _dbus_strdup (key); + + if (!tmp) + { + dbus_dict_entry_free (entry); + return FALSE; + } + + if (!_dbus_hash_table_insert_string (dict->table, tmp, entry)) + { + dbus_free (tmp); + dbus_dict_entry_free (entry); + + return FALSE; + } + + return TRUE; +} + +/** + * 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.boolean_array.value; + *len = entry->v.boolean_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 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_put_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_put_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_put_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_put_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_put_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_put_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_put_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_put_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_put_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_put_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 */ diff --git a/dbus/dbus-dict.h b/dbus/dbus-dict.h new file mode 100644 index 0000000..8765ee2 --- /dev/null +++ b/dbus/dbus-dict.h @@ -0,0 +1,131 @@ +/* -*- 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 + * + */ +#if !defined (DBUS_INSIDE_DBUS_H) && !defined (DBUS_COMPILATION) +#error "Only can be included directly, this file may disappear or change contents." +#endif + +#ifndef DBUS_DICT_H +#define DBUS_DICT_H + +#include +#include + +DBUS_BEGIN_DECLS; + +typedef struct DBusDict DBusDict; + +DBusDict * dbus_dict_new (void); +void dbus_dict_ref (DBusDict *dict); +void dbus_dict_unref (DBusDict *dict); +dbus_bool_t dbus_dict_contains (DBusDict *dict, + const char *key); +dbus_bool_t dbus_dict_remove (DBusDict *dict, + const char *key); +int dbus_dict_get_value_type (DBusDict *dict, + const char *key); +dbus_bool_t dbus_dict_get_keys (DBusDict *dict, + char ***keys, + int *len); + +dbus_bool_t dbus_dict_put_boolean (DBusDict *dict, + const char *key, + dbus_bool_t value); +dbus_bool_t dbus_dict_put_int32 (DBusDict *dict, + const char *key, + dbus_int32_t value); +dbus_bool_t dbus_dict_put_uint32 (DBusDict *dict, + const char *key, + dbus_uint32_t value); +dbus_bool_t dbus_dict_put_double (DBusDict *dict, + const char *key, + double value); +dbus_bool_t dbus_dict_put_string (DBusDict *dict, + const char *key, + const char *value); +dbus_bool_t dbus_dict_put_boolean_array (DBusDict *dict, + const char *key, + unsigned const char *value, + int len); +dbus_bool_t dbus_dict_put_int32_array (DBusDict *dict, + const char *key, + const dbus_int32_t *value, + int len); +dbus_bool_t dbus_dict_put_uint32_array (DBusDict *dict, + const char *key, + const dbus_uint32_t *value, + int len); +dbus_bool_t dbus_dict_put_double_array (DBusDict *dict, + const char *key, + const double *value, + int len); +dbus_bool_t dbus_dict_put_byte_array (DBusDict *dict, + const char *key, + unsigned const char *value, + int len); +dbus_bool_t dbus_dict_put_string_array (DBusDict *dict, + const char *key, + const char **value, + int len); + +dbus_bool_t dbus_dict_get_boolean (DBusDict *dict, + const char *key, + dbus_bool_t *value); +dbus_bool_t dbus_dict_get_int32 (DBusDict *dict, + const char *key, + dbus_int32_t *value); +dbus_bool_t dbus_dict_get_uint32 (DBusDict *dict, + const char *key, + dbus_uint32_t *value); +dbus_bool_t dbus_dict_get_double (DBusDict *dict, + const char *key, + double *value); +dbus_bool_t dbus_dict_get_string (DBusDict *dict, + const char *key, + const char **value); +dbus_bool_t dbus_dict_get_boolean_array (DBusDict *dict, + const char *key, + unsigned const char **value, + int *len); +dbus_bool_t dbus_dict_get_int32_array (DBusDict *dict, + const char *key, + const dbus_int32_t **value, + int *len); +dbus_bool_t dbus_dict_get_uint32_array (DBusDict *dict, + const char *key, + const dbus_uint32_t **value, + int *len); +dbus_bool_t dbus_dict_get_double_array (DBusDict *dict, + const char *key, + const double **value, + int *len); +dbus_bool_t dbus_dict_get_byte_array (DBusDict *dict, + const char *key, + unsigned const char **value, + int *len); +dbus_bool_t dbus_dict_get_string_array (DBusDict *dict, + const char *key, + const char ***value, + int *len); + + +#endif /* DBUS_DICT_H */ diff --git a/dbus/dbus-test.c b/dbus/dbus-test.c index 9da24ba..466e8b8 100644 --- a/dbus/dbus-test.c +++ b/dbus/dbus-test.c @@ -54,7 +54,7 @@ dbus_internal_do_not_use_run_tests (const char *test_data_dir) printf ("Test data in %s\n", test_data_dir); else printf ("No test data!\n"); - + printf ("%s: running string tests\n", "dbus-test"); if (!_dbus_string_test ()) die ("strings"); @@ -66,7 +66,7 @@ dbus_internal_do_not_use_run_tests (const char *test_data_dir) printf ("%s: running keyring tests\n", "dbus-test"); if (!_dbus_keyring_test ()) die ("keyring"); - + #if 0 printf ("%s: running md5 tests\n", "dbus-test"); if (!_dbus_md5_test ()) @@ -104,7 +104,11 @@ dbus_internal_do_not_use_run_tests (const char *test_data_dir) printf ("%s: running hash table tests\n", "dbus-test"); if (!_dbus_hash_test ()) die ("hash tables"); - + + printf ("%s: running dict tests\n", "dbus-test"); + if (!_dbus_dict_test ()) + die ("dicts"); + printf ("%s: completed successfully\n", "dbus-test"); #else printf ("Not compiled with unit tests, not running any\n"); diff --git a/dbus/dbus-test.h b/dbus/dbus-test.h index 2fc2901..e4cb52d 100644 --- a/dbus/dbus-test.h +++ b/dbus/dbus-test.h @@ -36,6 +36,7 @@ typedef enum } DBusMessageValidity; dbus_bool_t _dbus_hash_test (void); +dbus_bool_t _dbus_dict_test (void); dbus_bool_t _dbus_list_test (void); dbus_bool_t _dbus_marshal_test (void); dbus_bool_t _dbus_mem_pool_test (void); -- 2.7.4