2003-03-07 Anders Carlsson <andersca@codefactory.se>
authorAnders Carlsson <andersca@codefactory.se>
Thu, 6 Mar 2003 23:11:49 +0000 (23:11 +0000)
committerAnders Carlsson <andersca@codefactory.se>
Thu, 6 Mar 2003 23:11:49 +0000 (23:11 +0000)
* 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
dbus/Makefile.am
dbus/dbus-dict.c [new file with mode: 0644]
dbus/dbus-dict.h [new file with mode: 0644]
dbus/dbus-test.c
dbus/dbus-test.h

index ab0abd9..a023a1c 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,29 @@
+2003-03-07  Anders Carlsson  <andersca@codefactory.se>
+
+       * 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  <hp@pobox.com>
 
        * test/data/auth/*: adapt to changes
index dfcfb7d..622d964 100644 (file)
@@ -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 (file)
index 0000000..334a874
--- /dev/null
@@ -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 (file)
index 0000000..8765ee2
--- /dev/null
@@ -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 <dbus/dbus.h> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef DBUS_DICT_H
+#define DBUS_DICT_H
+
+#include <dbus/dbus-macros.h>
+#include <dbus/dbus-types.h>
+
+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 */
index 9da24ba..466e8b8 100644 (file)
@@ -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");
index 2fc2901..e4cb52d 100644 (file)
@@ -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);