Update some paths in HACKING
[platform/upstream/dbus.git] / dbus / dbus-marshal.c
index 51c4ce1..00821da 100644 (file)
@@ -1,9 +1,10 @@
 /* -*- mode: C; c-file-style: "gnu" -*- */
 /* dbus-marshal.c  Marshalling routines
  *
- * Copyright (C) 2002  CodeFactory AB
+ * Copyright (C) 2002 CodeFactory AB
+ * Copyright (C) 2003, 2004 Red Hat, Inc.
  *
- * Licensed under the Academic Free License version 1.2
+ * Licensed under the Academic Free License version 2.1
  * 
  * 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
 
 #include <string.h>
 
+/**
+ * @defgroup DBusMarshal marshaling and unmarshaling
+ * @ingroup  DBusInternals
+ * @brief functions to marshal/unmarshal data from the wire
+ *
+ * Types and functions related to converting primitive data types from
+ * wire format to native machine format, and vice versa.
+ *
+ * @{
+ */
+
+static dbus_uint32_t
+unpack_4_octets (int                  byte_order,
+                 const unsigned char *data)
+{
+  _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
+  
+  if (byte_order == DBUS_LITTLE_ENDIAN)
+    return DBUS_UINT32_FROM_LE (*(dbus_uint32_t*)data);
+  else
+    return DBUS_UINT32_FROM_BE (*(dbus_uint32_t*)data);
+}
+
+#ifndef DBUS_HAVE_INT64
 /* from ORBit */
 static void
 swap_bytes (unsigned char *data,
@@ -46,17 +71,43 @@ swap_bytes (unsigned char *data,
       ++p1;
     }
 }
+#endif /* !DBUS_HAVE_INT64 */
 
 /**
- * @defgroup DBusMarshal marshaling and unmarshaling
- * @ingroup  DBusInternals
- * @brief functions to marshal/unmarshal data from the wire
- *
- * Types and functions related to converting primitive data types from
- * wire format to native machine format, and vice versa.
- *
- * @{
+ * Union used to manipulate 8 bytes as if they
+ * were various types. 
  */
+typedef union
+{
+#ifdef DBUS_HAVE_INT64
+  dbus_int64_t  s; /**< 64-bit integer */
+  dbus_uint64_t u; /**< 64-bit unsinged integer */
+#endif
+  double d;        /**< double */
+} DBusOctets8;
+
+static DBusOctets8
+unpack_8_octets (int                  byte_order,
+                 const unsigned char *data)
+{
+  DBusOctets8 r;
+  
+  _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 8) == data);
+  _dbus_assert (sizeof (r) == 8);
+  
+#ifdef DBUS_HAVE_INT64
+  if (byte_order == DBUS_LITTLE_ENDIAN)
+    r.u = DBUS_UINT64_FROM_LE (*(dbus_uint64_t*)data);
+  else
+    r.u = DBUS_UINT64_FROM_BE (*(dbus_uint64_t*)data);
+#else
+  r.d = *(double*)data;
+  if (byte_order != DBUS_COMPILER_BYTE_ORDER)
+    swap_bytes ((unsigned char*) &r, sizeof (r));
+#endif
+  
+  return r;
+}
 
 /**
  * Unpacks a 32 bit unsigned integer from a data pointer
@@ -69,12 +120,7 @@ dbus_uint32_t
 _dbus_unpack_uint32 (int                  byte_order,
                      const unsigned char *data)
 {
-  _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
-  
-  if (byte_order == DBUS_LITTLE_ENDIAN)
-    return DBUS_UINT32_FROM_LE (*(dbus_uint32_t*)data);
-  else
-    return DBUS_UINT32_FROM_BE (*(dbus_uint32_t*)data);
+  return unpack_4_octets (byte_order, data);
 }  
 
 /**
@@ -88,12 +134,78 @@ dbus_int32_t
 _dbus_unpack_int32 (int                  byte_order,
                     const unsigned char *data)
 {
+  return (dbus_int32_t) unpack_4_octets (byte_order, data);
+}
+
+#ifdef DBUS_HAVE_INT64
+/**
+ * Unpacks a 64 bit unsigned integer from a data pointer
+ *
+ * @param byte_order The byte order to use
+ * @param data the data pointer
+ * @returns the integer
+ */
+dbus_uint64_t
+_dbus_unpack_uint64 (int                  byte_order,
+                     const unsigned char *data)
+{
+  DBusOctets8 r;
+  
+  r = unpack_8_octets (byte_order, data);
+
+  return r.u;
+}  
+
+/**
+ * Unpacks a 64 bit signed integer from a data pointer
+ *
+ * @param byte_order The byte order to use
+ * @param data the data pointer
+ * @returns the integer
+ */
+dbus_int64_t
+_dbus_unpack_int64 (int                  byte_order,
+                    const unsigned char *data)
+{
+  DBusOctets8 r;
+  
+  r = unpack_8_octets (byte_order, data);
+
+  return r.s;
+}
+
+#endif /* DBUS_HAVE_INT64 */
+
+static void
+pack_4_octets (dbus_uint32_t   value,
+               int             byte_order,
+               unsigned char  *data)
+{
   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
   
-  if (byte_order == DBUS_LITTLE_ENDIAN)
-    return DBUS_INT32_FROM_LE (*(dbus_int32_t*)data);
+  if ((byte_order) == DBUS_LITTLE_ENDIAN)                  
+    *((dbus_uint32_t*)(data)) = DBUS_UINT32_TO_LE (value);       
+  else
+    *((dbus_uint32_t*)(data)) = DBUS_UINT32_TO_BE (value);
+}
+
+static void
+pack_8_octets (DBusOctets8     value,
+               int             byte_order,
+               unsigned char  *data)
+{
+  _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 8) == data);
+
+#ifdef DBUS_HAVE_INT64
+  if ((byte_order) == DBUS_LITTLE_ENDIAN)                  
+    *((dbus_uint64_t*)(data)) = DBUS_UINT64_TO_LE (value.u); 
   else
-    return DBUS_INT32_FROM_BE (*(dbus_int32_t*)data);
+    *((dbus_uint64_t*)(data)) = DBUS_UINT64_TO_BE (value.u);
+#else
+  memcpy (data, &value, 8);
+  if (byte_order != DBUS_COMPILER_BYTE_ORDER)
+    swap_bytes ((unsigned char *)data, 8);
+#endif
 }
 
 /**
@@ -108,12 +220,7 @@ _dbus_pack_uint32 (dbus_uint32_t   value,
                    int             byte_order,
                    unsigned char  *data)
 {
-  _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
-  
-  if ((byte_order) == DBUS_LITTLE_ENDIAN)                  
-    *((dbus_uint32_t*)(data)) = DBUS_UINT32_TO_LE (value);       
-  else
-    *((dbus_uint32_t*)(data)) = DBUS_UINT32_TO_BE (value);
+  pack_4_octets (value, byte_order, data);
 }
 
 /**
@@ -128,12 +235,75 @@ _dbus_pack_int32 (dbus_int32_t   value,
                   int            byte_order,
                   unsigned char *data)
 {
-  _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
+  pack_4_octets ((dbus_uint32_t) value, byte_order, data);
+}
+
+#ifdef DBUS_HAVE_INT64
+/**
+ * Packs a 64 bit unsigned integer into a data pointer.
+ *
+ * @param value the value
+ * @param byte_order the byte order to use
+ * @param data the data pointer
+ */
+void
+_dbus_pack_uint64 (dbus_uint64_t   value,
+                   int             byte_order,
+                   unsigned char  *data)
+{
+  DBusOctets8 r;
+  r.u = value;
+  pack_8_octets (r, byte_order, data);
+}
+
+/**
+ * Packs a 64 bit signed integer into a data pointer.
+ *
+ * @param value the value
+ * @param byte_order the byte order to use
+ * @param data the data pointer
+ */
+void
+_dbus_pack_int64 (dbus_int64_t   value,
+                  int            byte_order,
+                  unsigned char *data)
+{
+  DBusOctets8 r;
+  r.s = value;
+  pack_8_octets (r, byte_order, data);
+}
+#endif /* DBUS_HAVE_INT64 */
+
+static void
+set_4_octets (DBusString          *str,
+              int                  byte_order,
+              int                  offset,
+              dbus_uint32_t        value)
+{
+  char *data;
   
-  if ((byte_order) == DBUS_LITTLE_ENDIAN)                  
-    *((dbus_int32_t*)(data)) = DBUS_INT32_TO_LE (value);       
-  else
-    *((dbus_int32_t*)(data)) = DBUS_INT32_TO_BE (value);
+  _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
+                byte_order == DBUS_BIG_ENDIAN);
+  
+  data = _dbus_string_get_data_len (str, offset, 4);
+
+  _dbus_pack_uint32 (value, byte_order, data);
+}
+
+static void
+set_8_octets (DBusString          *str,
+              int                  byte_order,
+              int                  offset,
+              DBusOctets8          value)
+{
+  char *data;
+  
+  _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
+                byte_order == DBUS_BIG_ENDIAN);
+  
+  data = _dbus_string_get_data_len (str, offset, 8);
+
+  pack_8_octets (value, byte_order, data);
 }
 
 /**
@@ -152,14 +322,7 @@ _dbus_marshal_set_int32 (DBusString          *str,
                          int                  offset,
                          dbus_int32_t         value)
 {
-  char *data;
-  
-  _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
-                byte_order == DBUS_BIG_ENDIAN);
-  
-  _dbus_string_get_data_len (str, &data, offset, 4);
-
-  _dbus_pack_int32 (value, byte_order, data);
+  set_4_octets (str, byte_order, offset, (dbus_uint32_t) value);
 }
 
 /**
@@ -178,15 +341,53 @@ _dbus_marshal_set_uint32 (DBusString          *str,
                           int                  offset,
                           dbus_uint32_t        value)
 {
-  char *data;
-  
-  _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
-                byte_order == DBUS_BIG_ENDIAN);
-  
-  _dbus_string_get_data_len (str, &data, offset, 4);
+  set_4_octets (str, byte_order, offset, value);
+}
 
-  _dbus_pack_uint32 (value, byte_order, data);
+#ifdef DBUS_HAVE_INT64
+
+/**
+ * Sets the 8 bytes at the given offset to a marshaled signed integer,
+ * replacing anything found there previously.
+ *
+ * @param str the string to write the marshalled int to
+ * @param offset the byte offset where int should be written
+ * @param byte_order the byte order to use
+ * @param value the value
+ * 
+ */
+void
+_dbus_marshal_set_int64 (DBusString          *str,
+                         int                  byte_order,
+                         int                  offset,
+                         dbus_int64_t         value)
+{
+  DBusOctets8 r;
+  r.s = value;
+  set_8_octets (str, byte_order, offset, r);
+}
+
+/**
+ * Sets the 8 bytes at the given offset to a marshaled unsigned
+ * integer, replacing anything found there previously.
+ *
+ * @param str the string to write the marshalled int to
+ * @param offset the byte offset where int should be written
+ * @param byte_order the byte order to use
+ * @param value the value
+ * 
+ */
+void
+_dbus_marshal_set_uint64 (DBusString          *str,
+                          int                  byte_order,
+                          int                  offset,
+                          dbus_uint64_t        value)
+{
+  DBusOctets8 r;
+  r.u = value;
+  set_8_octets (str, byte_order, offset, r);
 }
+#endif /* DBUS_HAVE_INT64 */
 
 /**
  * Sets the existing marshaled string at the given offset with
@@ -194,6 +395,10 @@ _dbus_marshal_set_uint32 (DBusString          *str,
  * an existing string or the wrong length will be deleted
  * and replaced with the new string.
  *
+ * Note: no attempt is made by this function to re-align
+ * any data which has been already marshalled after this
+ * string. Use with caution.
+ *
  * @param str the string to write the marshalled string to
  * @param offset the byte offset where string should be written
  * @param byte_order the byte order to use
@@ -228,6 +433,58 @@ _dbus_marshal_set_string (DBusString          *str,
 }
 
 /**
+ * Sets the existing marshaled object path at the given offset to a new
+ * value. The given offset must point to an existing object path or this
+ * function doesn't make sense.
+ *
+ * @todo implement this function
+ *
+ * @param str the string to write the marshalled path to
+ * @param offset the byte offset where path should be written
+ * @param byte_order the byte order to use
+ * @param path the new path
+ * @param path_len number of elements in the path
+ */
+void
+_dbus_marshal_set_object_path (DBusString         *str,
+                               int                 byte_order,
+                               int                 offset,
+                               const char        **path,
+                               int                 path_len)
+{
+
+  /* FIXME */
+}
+
+static dbus_bool_t
+marshal_4_octets (DBusString   *str,
+                  int           byte_order,
+                  dbus_uint32_t value)
+{
+  _dbus_assert (sizeof (value) == 4);
+  
+  if (byte_order != DBUS_COMPILER_BYTE_ORDER)
+    value = DBUS_UINT32_SWAP_LE_BE (value);
+
+  return _dbus_string_append_4_aligned (str,
+                                        (const unsigned char *)&value);
+}
+
+static dbus_bool_t
+marshal_8_octets (DBusString *str,
+                  int         byte_order,
+                  DBusOctets8 value)
+{
+  _dbus_assert (sizeof (value) == 8);
+  
+  if (byte_order != DBUS_COMPILER_BYTE_ORDER)
+    pack_8_octets (value, byte_order, (unsigned char*) &value); /* pack into self, swapping as we go */
+
+  return _dbus_string_append_8_aligned (str,
+                                        (const unsigned char *)&value);
+}
+
+/**
  * Marshals a double value.
  *
  * @param str the string to append the marshalled value to
@@ -240,15 +497,9 @@ _dbus_marshal_double (DBusString *str,
                      int         byte_order,
                      double      value)
 {
-  _dbus_assert (sizeof (double) == 8);
-
-  if (!_dbus_string_align_length (str, sizeof (double)))
-    return FALSE;
-  
-  if (byte_order != DBUS_COMPILER_BYTE_ORDER)
-    swap_bytes ((unsigned char *)&value, sizeof (double));
-
-  return _dbus_string_append_len (str, (const char *)&value, sizeof (double));
+  DBusOctets8 r;
+  r.d = value;
+  return marshal_8_octets (str, byte_order, r);
 }
 
 /**
@@ -264,13 +515,7 @@ _dbus_marshal_int32  (DBusString   *str,
                      int           byte_order,
                      dbus_int32_t  value)
 {
-  if (!_dbus_string_align_length (str, sizeof (dbus_int32_t)))
-    return FALSE;
-  
-  if (byte_order != DBUS_COMPILER_BYTE_ORDER)
-    value = DBUS_INT32_SWAP_LE_BE (value);
-
-  return _dbus_string_append_len (str, (const char *)&value, sizeof (dbus_int32_t));
+  return marshal_4_octets (str, byte_order, (dbus_uint32_t) value);
 }
 
 /**
@@ -286,18 +531,55 @@ _dbus_marshal_uint32 (DBusString    *str,
                      int            byte_order,
                      dbus_uint32_t  value)
 {
-  if (!_dbus_string_align_length (str, sizeof (dbus_uint32_t)))
-    return FALSE;
-  
-  if (byte_order != DBUS_COMPILER_BYTE_ORDER)
-    value = DBUS_UINT32_SWAP_LE_BE (value);
+  return marshal_4_octets (str, byte_order, value);
+}
+
+
+#ifdef DBUS_HAVE_INT64
+/**
+ * Marshals a 64 bit signed integer value.
+ *
+ * @param str the string to append the marshalled value to
+ * @param byte_order the byte order to use
+ * @param value the value
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+_dbus_marshal_int64  (DBusString   *str,
+                     int           byte_order,
+                     dbus_int64_t  value)
+{
+  DBusOctets8 r;
+  r.s = value;
+  return marshal_8_octets (str, byte_order, r);
+}
 
-  return _dbus_string_append_len (str, (const char *)&value, sizeof (dbus_uint32_t));
+/**
+ * Marshals a 64 bit unsigned integer value.
+ *
+ * @param str the string to append the marshalled value to
+ * @param byte_order the byte order to use
+ * @param value the value
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+_dbus_marshal_uint64 (DBusString    *str,
+                     int            byte_order,
+                     dbus_uint64_t  value)
+{
+  DBusOctets8 r;
+  r.u = value;
+  return marshal_8_octets (str, byte_order, r);
 }
 
+#endif /* DBUS_HAVE_INT64 */
+
 /**
  * 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
@@ -326,24 +608,27 @@ _dbus_marshal_string (DBusString    *str,
 }
 
 /**
- * Marshals a byte array
+ * 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 array
- * @param len number of elements in the array
+ * @param value the string
+ * @param len length of string to marshal in bytes
  * @returns #TRUE on success
  */
 dbus_bool_t
-_dbus_marshal_byte_array (DBusString          *str,
-                         int                  byte_order,
-                         const unsigned char *value,
-                         int                  len)
+_dbus_marshal_string_len (DBusString    *str,
+                          int            byte_order,
+                          const char    *value,
+                          int            len)
 {
   int old_string_len;
 
   old_string_len = _dbus_string_get_length (str);
-  
+
   if (!_dbus_marshal_uint32 (str, byte_order, len))
     {
       /* Restore the previous length */
@@ -352,37 +637,82 @@ _dbus_marshal_byte_array (DBusString          *str,
       return FALSE;
     }
 
-  if (len == 0)
-    return TRUE;
-  else
-    return _dbus_string_append_len (str, value, len);
+  if (!_dbus_string_append_len (str, value, len))
+    return FALSE;
+
+  /* add a nul byte */
+  if (!_dbus_string_lengthen (str, 1))
+    return FALSE;
+
+  return TRUE;
 }
 
 /**
- * Marshals a 32 bit signed integer array
+ * Marshals a byte array
  *
  * @param str the string to append the marshalled value to
  * @param byte_order the byte order to use
  * @param value the array
- * @param len the length of the array
+ * @param len number of elements in the array
  * @returns #TRUE on success
  */
 dbus_bool_t
-_dbus_marshal_int32_array (DBusString         *str,
-                          int                 byte_order,
-                          const dbus_int32_t *value,
-                          int                 len)
+_dbus_marshal_byte_array (DBusString          *str,
+                         int                  byte_order,
+                         const unsigned char *value,
+                         int                  len)
 {
-  int i, old_string_len;
+  int old_string_len;
 
   old_string_len = _dbus_string_get_length (str);
-
+  
   if (!_dbus_marshal_uint32 (str, byte_order, len))
+    {
+      /* Restore the previous length */
+      _dbus_string_set_length (str, old_string_len);
+
+      return FALSE;
+    }
+
+  if (len == 0)
+    return TRUE;
+  else
+    return _dbus_string_append_len (str, value, len);
+}
+
+static dbus_bool_t
+marshal_4_octets_array (DBusString          *str,
+                        int                  byte_order,
+                        const dbus_uint32_t *value,
+                        int                  len)
+{
+  int old_string_len;
+  int array_start;
+
+  old_string_len = _dbus_string_get_length (str);
+
+  if (!_dbus_marshal_uint32 (str, byte_order, len * 4))
     goto error;
 
-  for (i = 0; i < len; i++)
-    if (!_dbus_marshal_int32 (str, byte_order, value[i]))
-      goto error;
+  array_start = _dbus_string_get_length (str);
+  
+  if (!_dbus_string_append_len (str, (const unsigned char*) value,
+                                len * 4))
+    goto error;
+  
+  if (byte_order != DBUS_COMPILER_BYTE_ORDER)
+    {
+      const unsigned char *d;
+      const unsigned char *end;
+      
+      d = _dbus_string_get_data (str) + array_start;
+      end = d + len * 4;
+      while (d != end)
+        {
+          *((dbus_uint32_t*)d) = DBUS_UINT32_SWAP_LE_BE (*((dbus_uint32_t*)d));
+          d += 4;
+        }
+    }
 
   return TRUE;
   
@@ -390,7 +720,74 @@ _dbus_marshal_int32_array (DBusString         *str,
   /* Restore previous length */
   _dbus_string_set_length (str, old_string_len);
   
-  return FALSE;
+  return FALSE;  
+}
+
+static dbus_bool_t
+marshal_8_octets_array (DBusString          *str,
+                        int                  byte_order,
+                        const DBusOctets8   *value,
+                        int                  len)
+{
+  int old_string_len;
+  int array_start;
+
+  old_string_len = _dbus_string_get_length (str);
+
+  if (!_dbus_marshal_uint32 (str, byte_order, len * 8))
+    goto error;
+
+  array_start = _dbus_string_get_length (str);
+  
+  if (!_dbus_string_append_len (str, (const unsigned char*) value,
+                                len * 8))
+    goto error;
+  
+  if (byte_order != DBUS_COMPILER_BYTE_ORDER)
+    {
+      const unsigned char *d;
+      const unsigned char *end;
+      
+      d = _dbus_string_get_data (str) + array_start;
+      end = d + len * 8;
+      while (d != end)
+        {
+#ifdef DBUS_HAVE_INT64
+          *((dbus_uint64_t*)d) = DBUS_UINT64_SWAP_LE_BE (*((dbus_uint64_t*)d));
+#else
+          swap_bytes ((unsigned char*) d, 8);
+#endif
+          d += 8;
+        }
+    }
+
+  return TRUE;
+  
+ error:
+  /* Restore previous length */
+  _dbus_string_set_length (str, old_string_len);
+  
+  return FALSE;  
+}
+
+/**
+ * Marshals a 32 bit signed integer array
+ *
+ * @param str the string to append the marshalled value to
+ * @param byte_order the byte order to use
+ * @param value the array
+ * @param len the length of the array
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+_dbus_marshal_int32_array (DBusString         *str,
+                          int                 byte_order,
+                          const dbus_int32_t *value,
+                          int                 len)
+{
+  return marshal_4_octets_array (str, byte_order,
+                                 (const dbus_uint32_t*) value,
+                                 len);
 }
 
 /**
@@ -408,26 +805,55 @@ _dbus_marshal_uint32_array (DBusString          *str,
                            const dbus_uint32_t  *value,
                            int                  len)
 {
-  int i, old_string_len;
-
-  old_string_len = _dbus_string_get_length (str);
+  return marshal_4_octets_array (str, byte_order,
+                                 value,
+                                 len);
+}
 
-  if (!_dbus_marshal_uint32 (str, byte_order, len))
-    goto error;
+#ifdef DBUS_HAVE_INT64
 
-  for (i = 0; i < len; i++)
-    if (!_dbus_marshal_uint32 (str, byte_order, value[i]))
-      goto error;
+/**
+ * Marshals a 64 bit signed integer array
+ *
+ * @param str the string to append the marshalled value to
+ * @param byte_order the byte order to use
+ * @param value the array
+ * @param len the length of the array
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+_dbus_marshal_int64_array (DBusString         *str,
+                          int                 byte_order,
+                          const dbus_int64_t *value,
+                          int                 len)
+{
+  return marshal_8_octets_array (str, byte_order,
+                                 (const DBusOctets8*) value,
+                                 len);
+}
 
-  return TRUE;
-  
- error:
-  /* Restore previous length */
-  _dbus_string_set_length (str, old_string_len);
-  
-  return FALSE;  
+/**
+ * Marshals a 64 bit unsigned integer array
+ *
+ * @param str the string to append the marshalled value to
+ * @param byte_order the byte order to use
+ * @param value the array
+ * @param len the length of the array
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+_dbus_marshal_uint64_array (DBusString          *str,
+                           int                  byte_order,
+                           const dbus_uint64_t  *value,
+                           int                  len)
+{
+  return marshal_8_octets_array (str, byte_order,
+                                 (const DBusOctets8*) value,
+                                 len);
 }
 
+#endif /* DBUS_HAVE_INT64 */
+
 /**
  * Marshals a double array
  *
@@ -443,24 +869,9 @@ _dbus_marshal_double_array (DBusString          *str,
                            const double        *value,
                            int                  len)
 {
-  int i, old_string_len;
-
-  old_string_len = _dbus_string_get_length (str);
-
-  if (!_dbus_marshal_uint32 (str, byte_order, len))
-    goto error;
-
-  for (i = 0; i < len; i++)
-    if (!_dbus_marshal_double (str, byte_order, value[i]))
-      goto error;
-
-  return TRUE;
-  
- error:
-  /* Restore previous length */
-  _dbus_string_set_length (str, old_string_len);
-  
-  return FALSE;    
+  return marshal_8_octets_array (str, byte_order,
+                                 (const DBusOctets8*) value,
+                                 len);
 }
 
 /**
@@ -478,17 +889,25 @@ _dbus_marshal_string_array (DBusString  *str,
                            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:
@@ -498,192 +917,89 @@ _dbus_marshal_string_array (DBusString  *str,
   return FALSE;      
 }
 
-
 /**
- * Marshals a dict
+ * Marshals an object path value.
+ * 
  * @param str the string to append the marshalled value to
  * @param byte_order the byte order to use
- * @param dict the dict
+ * @param path the path
+ * @param path_len length of the path
  * @returns #TRUE on success
  */
 dbus_bool_t
-_dbus_marshal_dict (DBusString *str,
-                   int         byte_order,
-                   DBusDict   *dict)
+_dbus_marshal_object_path (DBusString            *str,
+                           int                    byte_order,
+                           const char           **path,
+                           int                    path_len)
 {
-  int old_string_len;
-  int i, len;
-  char **keys;
+  int array_start, old_string_len;
+  int i;
   
   old_string_len = _dbus_string_get_length (str);
+  
+  /* Set the length to 0 temporarily */
+  if (!_dbus_marshal_uint32 (str, byte_order, 0))
+    goto nomem;
 
-  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++)
+  array_start = _dbus_string_get_length (str);
+  
+  i = 0;
+  while (i < path_len)
     {
-      int value_type;
-
-      value_type = dbus_dict_get_value_type (dict, keys[i]);
-
-      if (!_dbus_string_append_byte (str, value_type))
-       goto error;
+      if (!_dbus_string_append_byte (str, '/'))
+        goto nomem;
       
-      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_string_append (str, path[0]))
+        goto nomem;
 
-           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");
-       }
+      ++i;
     }
 
-  dbus_free_string_array (keys);
+  /* 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;
+
+ nomem:
+  /* Restore the previous length */
+  _dbus_string_set_length (str, old_string_len);
   
- error:
+  return FALSE;
+}
+
+static dbus_uint32_t
+demarshal_4_octets (const DBusString *str,
+                    int               byte_order,
+                    int               pos,
+                    int              *new_pos)
+{
+  const DBusRealString *real = (const DBusRealString*) str;
   
-  dbus_free_string_array (keys);
+  pos = _DBUS_ALIGN_VALUE (pos, 4);
   
-  /* Restore previous length */
-  _dbus_string_set_length (str, old_string_len);
+  if (new_pos)
+    *new_pos = pos + 4;
 
-  return FALSE;
+  return unpack_4_octets (byte_order, real->str + pos);
 }
 
+static DBusOctets8
+demarshal_8_octets (const DBusString *str,
+                    int               byte_order,
+                    int               pos,
+                    int              *new_pos)
+{
+  const DBusRealString *real = (const DBusRealString*) str;
+  
+  pos = _DBUS_ALIGN_VALUE (pos, 8);
+  
+  if (new_pos)
+    *new_pos = pos + 8;
+
+  return unpack_8_octets (byte_order, real->str + pos);
+}
 
 /**
  * Demarshals a double.
@@ -696,26 +1012,15 @@ _dbus_marshal_dict (DBusString *str,
  */
 double
 _dbus_demarshal_double (const DBusString  *str,
-                       int          byte_order,
-                       int          pos,
-                       int         *new_pos)
+                       int                byte_order,
+                       int                pos,
+                       int               *new_pos)
 {
-  double retval;
-  const char *buffer;
+  DBusOctets8 r;
 
-  pos = _DBUS_ALIGN_VALUE (pos, sizeof (double));
+  r = demarshal_8_octets (str, byte_order, pos, new_pos);
 
-  _dbus_string_get_const_data_len (str, &buffer, pos, sizeof (double));
-
-  retval = *(double *)buffer;
-  
-  if (byte_order != DBUS_COMPILER_BYTE_ORDER)
-    swap_bytes ((unsigned char *)&retval, sizeof (double));
-
-  if (new_pos)
-    *new_pos = pos + sizeof (double);
-  
-  return retval;  
+  return r.d;
 }
 
 /**
@@ -733,17 +1038,7 @@ _dbus_demarshal_int32  (const DBusString *str,
                        int               pos,
                        int              *new_pos)
 {
-  const DBusRealString *real = (const DBusRealString*) str;
-  
-  pos = _DBUS_ALIGN_VALUE (pos, sizeof (dbus_int32_t));
-  
-  if (new_pos)
-    *new_pos = pos + sizeof (dbus_int32_t);
-
-  if (byte_order == DBUS_LITTLE_ENDIAN)
-    return DBUS_INT32_FROM_LE (*(dbus_int32_t*)(real->str + pos));
-  else
-    return DBUS_INT32_FROM_BE (*(dbus_int32_t*)(real->str + pos));
+  return (dbus_int32_t) demarshal_4_octets (str, byte_order, pos, new_pos);
 }
 
 /**
@@ -761,17 +1056,110 @@ _dbus_demarshal_uint32  (const DBusString *str,
                         int         pos,
                         int        *new_pos)
 {
-  const DBusRealString *real = (const DBusRealString*) str;
-  
-  pos = _DBUS_ALIGN_VALUE (pos, sizeof (dbus_uint32_t));
-  
-  if (new_pos)
-    *new_pos = pos + sizeof (dbus_uint32_t);
+  return demarshal_4_octets (str, byte_order, pos, new_pos);
+}
 
-  if (byte_order == DBUS_LITTLE_ENDIAN)
-    return DBUS_UINT32_FROM_LE (*(dbus_uint32_t*)(real->str + pos));
-  else
-    return DBUS_UINT32_FROM_BE (*(dbus_uint32_t*)(real->str + pos));
+#ifdef DBUS_HAVE_INT64
+
+/**
+ * Demarshals a 64 bit signed integer.
+ *
+ * @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 of the string
+ * @returns the demarshaled integer.
+ */
+dbus_int64_t
+_dbus_demarshal_int64  (const DBusString *str,
+                       int               byte_order,
+                       int               pos,
+                       int              *new_pos)
+{
+  DBusOctets8 r;
+
+  r = demarshal_8_octets (str, byte_order, pos, new_pos);
+
+  return r.s;
+}
+
+/**
+ * Demarshals a 64 bit unsigned integer.
+ *
+ * @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 of the string
+ * @returns the demarshaled integer.
+ */
+dbus_uint64_t
+_dbus_demarshal_uint64  (const DBusString *str,
+                        int         byte_order,
+                        int         pos,
+                        int        *new_pos)
+{
+  DBusOctets8 r;
+
+  r = demarshal_8_octets (str, byte_order, pos, new_pos);
+
+  return r.u;
+}
+
+#endif /* DBUS_HAVE_INT64 */
+
+/**
+ * Demarshals a basic type
+ *
+ * @param str the string containing the data
+ * @param type type of value to demarshal
+ * @param value pointer to return value data
+ * @param byte_order the byte order
+ * @param pos pointer to position in the string,
+ *            updated on return to new position
+ **/
+void
+_dbus_demarshal_basic_type (const DBusString      *str,
+                           int                    type,
+                           void                  *value,
+                           int                    byte_order,
+                           int                   *pos)
+{
+  const char *str_data = _dbus_string_get_const_data (str);
+
+  switch (type)
+    {
+    case DBUS_TYPE_BYTE:
+    case DBUS_TYPE_BOOLEAN:
+      *(unsigned char *) value = _dbus_string_get_byte (str, *pos);
+      (*pos)++;
+      break;
+    case DBUS_TYPE_INT32:
+    case DBUS_TYPE_UINT32:
+      *pos = _DBUS_ALIGN_VALUE (*pos, 4);
+      *(dbus_uint32_t *) value = *(dbus_uint32_t *)(str_data + *pos);
+      if (byte_order != DBUS_COMPILER_BYTE_ORDER)
+       *(dbus_uint32_t *) value = DBUS_UINT32_SWAP_LE_BE (*(dbus_uint32_t *) value);
+      *pos += 4;
+      break;
+#ifdef DBUS_HAVE_INT64
+    case DBUS_TYPE_INT64:
+    case DBUS_TYPE_UINT64: 
+#endif /* DBUS_HAVE_INT64 */
+    case DBUS_TYPE_DOUBLE:
+      *pos = _DBUS_ALIGN_VALUE (*pos, 8);
+      memcpy (value, str_data + *pos, 8);
+      if (byte_order != DBUS_COMPILER_BYTE_ORDER)
+#ifdef DBUS_HAVE_INT64
+       *(dbus_uint64_t *) value = DBUS_UINT64_SWAP_LE_BE (*(dbus_uint64_t *) value);
+#else  
+       swap_bytes (value, 8);
+#endif
+      *pos += 8;
+      break;
+    default:
+      _dbus_assert_not_reached ("not a basic type");
+      break;
+    }
 }
 
 /**
@@ -792,9 +1180,9 @@ _dbus_demarshal_uint32  (const DBusString *str,
  */
 char *
 _dbus_demarshal_string (const DBusString *str,
-                       int         byte_order,
-                       int         pos,
-                       int        *new_pos)
+                       int               byte_order,
+                       int               pos,
+                       int              *new_pos)
 {
   int len;
   char *retval;
@@ -807,7 +1195,7 @@ _dbus_demarshal_string (const DBusString *str,
   if (!retval)
     return NULL;
 
-  _dbus_string_get_const_data_len (str, &data, pos, len);
+  data = _dbus_string_get_const_data_len (str, pos, len + 1);
 
   if (!data)
     return NULL;
@@ -865,7 +1253,7 @@ _dbus_demarshal_byte_array (const DBusString  *str,
   if (!retval)
     return FALSE;
 
-  _dbus_string_get_const_data_len (str, &data, pos, len);
+  data = _dbus_string_get_const_data_len (str, pos, len);
 
   if (!data)
     {
@@ -884,29 +1272,20 @@ _dbus_demarshal_byte_array (const DBusString  *str,
   return TRUE;
 }
 
-/**
- * Demarshals a 32 bit signed integer array.
- *
- * @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 of the string
- * @param array the array
- * @param array_len length of the demarshaled data
- * @returns #TRUE on success
- */
-dbus_bool_t
-_dbus_demarshal_int32_array (const DBusString  *str,
-                            int                byte_order,
-                            int                pos,
-                            int               *new_pos,
-                            dbus_int32_t     **array,
-                            int               *array_len)
+static dbus_bool_t
+demarshal_4_octets_array (const DBusString  *str,
+                          int                byte_order,
+                          int                pos,
+                          int               *new_pos,
+                          dbus_uint32_t    **array,
+                          int               *array_len)
 {
   int len, i;
-  dbus_int32_t *retval;
+  dbus_uint32_t *retval;
+  int byte_len;
   
-  len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
+  byte_len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
+  len = byte_len / 4;
 
   if (len == 0)
     {
@@ -918,47 +1297,40 @@ _dbus_demarshal_int32_array (const DBusString  *str,
       
       return TRUE;
     }
-  
-  retval = dbus_new (dbus_int32_t, len);
-  
-  if (!retval)
-    return FALSE;
 
-  for (i = 0; i < len; i++)
-    retval[i] = _dbus_demarshal_int32 (str, byte_order, pos, &pos);
+  if (!_dbus_string_copy_data_len (str, (char**) &retval,
+                                   pos, byte_len))
+    return FALSE;
+  
+  if (byte_order != DBUS_COMPILER_BYTE_ORDER)
+    {
+      for (i = 0; i < len; i++)
+        retval[i] = DBUS_UINT32_SWAP_LE_BE (retval[i]);
+    }
 
   if (new_pos)
-    *new_pos = pos;
+    *new_pos = pos + byte_len;
 
   *array_len = len;
   *array = retval;
   
-  return TRUE;
+  return TRUE;  
 }
 
-/**
- * Demarshals a 32 bit unsigned integer array.
- *
- * @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 of the string
- * @param array the array
- * @param array_len length of the demarshaled data
- * @returns #TRUE on success
- */
-dbus_bool_t
-_dbus_demarshal_uint32_array (const DBusString  *str,
-                             int                byte_order,
-                             int                pos,
-                             int               *new_pos,
-                             dbus_uint32_t    **array,
-                             int               *array_len)
+static dbus_bool_t
+demarshal_8_octets_array (const DBusString  *str,
+                          int                byte_order,
+                          int                pos,
+                          int               *new_pos,
+                          DBusOctets8      **array,
+                          int               *array_len)
 {
   int len, i;
-  dbus_uint32_t *retval;
+  DBusOctets8 *retval;
+  int byte_len;
   
-  len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
+  byte_len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
+  len = byte_len / 8;
 
   if (len == 0)
     {
@@ -970,17 +1342,25 @@ _dbus_demarshal_uint32_array (const DBusString  *str,
       
       return TRUE;
     }
-  
-  retval = dbus_new (dbus_uint32_t, len);
 
-  if (!retval)
+  if (!_dbus_string_copy_data_len (str, (char**) &retval,
+                                   pos, byte_len))
     return FALSE;
-
-  for (i = 0; i < len; i++)
-    retval[i] = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
+  
+  if (byte_order != DBUS_COMPILER_BYTE_ORDER)
+    {
+      for (i = 0; i < len; i++)
+        {
+#ifdef DBUS_HAVE_INT64
+          retval[i].u = DBUS_UINT64_SWAP_LE_BE (retval[i].u);
+#else
+          swap_bytes ((unsigned char *) &retval[i], 8);
+#endif
+        }
+    }
 
   if (new_pos)
-    *new_pos = pos;
+    *new_pos = pos + byte_len;
 
   *array_len = len;
   *array = retval;
@@ -989,7 +1369,7 @@ _dbus_demarshal_uint32_array (const DBusString  *str,
 }
 
 /**
- * Demarshals a double array.
+ * Demarshals a 32 bit signed integer array.
  *
  * @param str the string containing the data
  * @param byte_order the byte order
@@ -1000,44 +1380,158 @@ _dbus_demarshal_uint32_array (const DBusString  *str,
  * @returns #TRUE on success
  */
 dbus_bool_t
-_dbus_demarshal_double_array (const DBusString  *str,
+_dbus_demarshal_int32_array (const DBusString  *str,
+                            int                byte_order,
+                            int                pos,
+                            int               *new_pos,
+                            dbus_int32_t     **array,
+                            int               *array_len)
+{
+  return demarshal_4_octets_array (str, byte_order, pos, new_pos,
+                                   (dbus_uint32_t**) array, array_len);
+}
+
+/**
+ * Demarshals a 32 bit unsigned integer array.
+ *
+ * @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 of the string
+ * @param array the array
+ * @param array_len length of the demarshaled data
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+_dbus_demarshal_uint32_array (const DBusString  *str,
                              int                byte_order,
                              int                pos,
                              int               *new_pos,
-                             double           **array,
+                             dbus_uint32_t    **array,
                              int               *array_len)
 {
-  int len, i;
-  double *retval;
-  
-  len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
+  return demarshal_4_octets_array (str, byte_order, pos, new_pos,
+                                   array, array_len);
+}
 
-  if (len == 0)
-    {
-      *array_len = 0;
-      *array = NULL;
+#ifdef DBUS_HAVE_INT64
 
-      if (new_pos)
-       *new_pos = pos;
-      
-      return TRUE;
-    }
-  
-  retval = dbus_new (double, len);
+/**
+ * Demarshals a 64 bit signed integer array.
+ *
+ * @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 of the string
+ * @param array the array
+ * @param array_len length of the demarshaled data
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+_dbus_demarshal_int64_array (const DBusString  *str,
+                            int                byte_order,
+                            int                pos,
+                            int               *new_pos,
+                            dbus_int64_t     **array,
+                            int               *array_len)
+{
+  return demarshal_8_octets_array (str, byte_order, pos, new_pos,
+                                   (DBusOctets8**) array, array_len);
+}
 
-  if (!retval)
-    return FALSE;
+/**
+ * Demarshals a 64 bit unsigned integer array.
+ *
+ * @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 of the string
+ * @param array the array
+ * @param array_len length of the demarshaled data
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+_dbus_demarshal_uint64_array (const DBusString  *str,
+                             int                byte_order,
+                             int                pos,
+                             int               *new_pos,
+                             dbus_uint64_t    **array,
+                             int               *array_len)
+{
+  return demarshal_8_octets_array (str, byte_order, pos, new_pos,
+                                   (DBusOctets8**) array, array_len);
+}
 
-  for (i = 0; i < len; i++)
-    retval[i] = _dbus_demarshal_double (str, byte_order, pos, &pos);
+#endif /* DBUS_HAVE_INT64 */
 
-  if (new_pos)
-    *new_pos = pos;
+/**
+ * Demarshals a double array.
+ *
+ * @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 of the string
+ * @param array the array
+ * @param array_len length of the demarshaled data
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+_dbus_demarshal_double_array (const DBusString  *str,
+                             int                byte_order,
+                             int                pos,
+                             int               *new_pos,
+                             double           **array,
+                             int               *array_len)
+{
+  return demarshal_8_octets_array (str, byte_order, pos, new_pos,
+                                   (DBusOctets8**) array, array_len);
+}
 
-  *array_len = len;
-  *array = retval;
-  
-  return TRUE; 
+
+/**
+ * Demarshals an array of basic types
+ *
+ * @param str the string containing the data
+ * @param element_type type of array elements to demarshal
+ * @param array pointer to pointer to array data
+ * @param array_len pointer to array length
+ * @param byte_order the byte order
+ * @param pos pointer to position in the string,
+ *            updated on return to new position
+ **/
+dbus_bool_t
+_dbus_demarshal_basic_type_array (const DBusString      *str,
+                                 int                    element_type,
+                                 void                 **array,
+                                 int                   *array_len,
+                                 int                    byte_order,
+                                 int                   *pos)
+{
+  switch (element_type)
+    {
+    case DBUS_TYPE_BOOLEAN:
+      /* FIXME: do we want to post-normalize these ? */
+    case DBUS_TYPE_BYTE:
+      return _dbus_demarshal_byte_array (str, byte_order, *pos, pos,
+                                        (unsigned char **)array, array_len);
+      break;
+    case DBUS_TYPE_INT32:
+    case DBUS_TYPE_UINT32:
+      return demarshal_4_octets_array (str, byte_order, *pos, pos,
+                                      (dbus_uint32_t **)array, array_len);
+      break;
+#ifdef DBUS_HAVE_INT64
+    case DBUS_TYPE_INT64:
+    case DBUS_TYPE_UINT64: 
+#endif /* DBUS_HAVE_INT64 */
+    case DBUS_TYPE_DOUBLE:
+      return demarshal_8_octets_array (str, byte_order, *pos, pos,
+                                      (DBusOctets8**) array, array_len);
+    default:
+      _dbus_assert_not_reached ("not a basic type");
+      break;
+    }
+  return FALSE;
 }
 
 /**
@@ -1048,7 +1542,7 @@ _dbus_demarshal_double_array (const DBusString  *str,
  * @param pos the position in the string
  * @param new_pos the new position of the string
  * @param array the array
- * @param array_len length of the demarshaled data
+ * @param array_len location for length of the demarshaled data or NULL
  * @returns #TRUE on success
  */
 dbus_bool_t
@@ -1059,12 +1553,14 @@ _dbus_demarshal_string_array (const DBusString   *str,
                              char             ***array,
                              int                *array_len)
 {
-  int len, i, j;
+  int bytes_len, i;
+  int len, allocated;
+  int end_pos;
   char **retval;
-
-  len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
-
-  if (len == 0)
+  
+  bytes_len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
+  
+  if (bytes_len == 0)
     {
       *array_len = 0;
       *array = NULL;
@@ -1074,249 +1570,176 @@ _dbus_demarshal_string_array (const DBusString   *str,
       
       return TRUE;
     }
+
+  len = 0;
+  allocated = 4;
+  end_pos = pos + bytes_len;
   
-  retval = dbus_new (char *, len + 1);
+  retval = dbus_new (char *, allocated);
 
   if (!retval)
     return FALSE;
 
-  retval[len] = NULL;
-  
-  for (i = 0; i < len; i++)
+  while (pos < end_pos)
     {
-      retval[i] = _dbus_demarshal_string (str, byte_order, pos, &pos);
-
-      if (retval[i] == 0)
+      retval[len] = _dbus_demarshal_string (str, byte_order, pos, &pos);
+      
+      if (retval[len] == NULL)
        goto error;
+      
+      len += 1;
+
+      if (len >= allocated - 1) /* -1 for NULL termination */
+        {
+          char **newp;
+          newp = dbus_realloc (retval,
+                               sizeof (char*) * allocated * 2);
+          if (newp == NULL)
+            goto error;
+
+          allocated *= 2;
+          retval = newp;
+        }
     }
+      
+  retval[len] = NULL;
 
- if (new_pos)
 if (new_pos)
     *new_pos = pos;
-
- *array = retval;
- *array_len = len;
+  
 *array = retval;
 *array_len = len;
   
   return TRUE;
 
  error:
-  for (j = 0; j < i; j++)
+  for (i = 0; i < len; i++)
     dbus_free (retval[i]);
   dbus_free (retval);
 
   return FALSE;
 }
 
+/** Set to 1 to get a bunch of spew about disassembling the path string */
+#define VERBOSE_DECOMPOSE 0
+
 /**
- * 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.
+ * Decompose an object path.  A path of just "/" is
+ * represented as an empty vector of strings.
+ * 
+ * @param data the path data
+ * @param len  the length of the path string
+ * @param path address to store new object path
+ * @param path_len length of stored path
  */
 dbus_bool_t
-_dbus_demarshal_dict (const DBusString *str,
-                     int               byte_order,
-                     int               pos,
-                     int              *new_pos,
-                     DBusDict       **dict)
+_dbus_decompose_path (const char*     data,
+                      int             len,
+                      char         ***path,
+                      int            *path_len)
 {
-  char **keys;
-  int i, len;
-  
-  *dict = dbus_dict_new ();
-  if (!*dict)
-    return FALSE;
+  char **retval;
+  int n_components;
+  int i, j, comp;
 
-  if (!_dbus_demarshal_string_array (str, byte_order, pos, &pos, &keys, &len))
-    goto error;
+  _dbus_assert (data != NULL);
 
-  for (i = 0; i < len; i++)
+#if VERBOSE_DECOMPOSE
+  _dbus_verbose ("Decomposing path \"%s\"\n",
+                 data);
+#endif
+  
+  n_components = 0;
+  i = 0;
+  while (i < len)
     {
-      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 (data[i] == '/')
+        n_components += 1;
+      ++i;
+    }
+  
+  retval = dbus_new0 (char*, n_components + 1);
 
-           if (!dbus_dict_set_double_array (*dict, keys[i], value, len))
-             {
-               dbus_free (value);
-               goto error;
-             }
+  if (retval == NULL)
+    return FALSE;
 
-           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;
+  comp = 0;
+  i = 0;
+  while (i < len)
+    {
+      if (data[i] == '/')
+        ++i;
+      j = i;
+
+      while (j < len && data[j] != '/')
+        ++j;
+
+      /* Now [i, j) is the path component */
+      _dbus_assert (i < j);
+      _dbus_assert (data[i] != '/');
+      _dbus_assert (j == len || data[j] == '/');
+
+#if VERBOSE_DECOMPOSE
+      _dbus_verbose ("  (component in [%d,%d))\n",
+                     i, j);
+#endif
+      
+      retval[comp] = _dbus_memdup (&data[i], j - i + 1);
+      if (retval[comp] == NULL)
+        {
+          dbus_free_string_array (retval);
+          return FALSE;
+        }
+      retval[comp][j-i] = '\0';
+#if VERBOSE_DECOMPOSE
+      _dbus_verbose ("  (component %d = \"%s\")\n",
+                     comp, retval[comp]);
+#endif
+
+      ++comp;
+      i = j;
+    }
+  _dbus_assert (i == len);
+  
+  *path = retval;
+  if (path_len)
+    *path_len = n_components;
+  
+  return TRUE;
+}
 
-           if (!dbus_dict_set_byte_array (*dict, keys[i], value, len))
-             {
-               dbus_free (value);
-               goto error;
-             }
+/**
+ * Demarshals an object path.  A path of just "/" is
+ * represented as an empty vector of strings.
+ * 
+ * @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 of the string
+ * @param path address to store new object path
+ * @param path_len length of stored path
+ */
+dbus_bool_t
+_dbus_demarshal_object_path (const DBusString *str,
+                             int               byte_order,
+                             int               pos,
+                             int              *new_pos,
+                             char           ***path,
+                             int              *path_len)
+{
+  int len;
+  const char *data;
+  
+  len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
+  data = _dbus_string_get_const_data_len (str, pos, len + 1);
 
-           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_decompose_path (data, len, path, path_len))
+    return FALSE;
 
-           if (!dbus_dict_set_string_array (*dict, keys[i], (const char **)value, len))
-             {
-               dbus_free_string_array (value);
-               goto error;
-             }
+  if (new_pos)
+    *new_pos = pos + len + 1;
 
-           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;
 }
 
 /** 
@@ -1326,6 +1749,7 @@ _dbus_demarshal_dict (const DBusString *str,
  *
  * @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
@@ -1334,153 +1758,95 @@ _dbus_demarshal_dict (const DBusString *str,
 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;
 
-  _dbus_string_get_const_data_len (str, &data, 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_INT32:
-      *end_pos = _DBUS_ALIGN_VALUE (pos + 1, sizeof (dbus_int32_t)) + sizeof (dbus_int32_t);
-
+    case DBUS_TYPE_BOOLEAN:
+      *end_pos = pos + 1;
       break;
 
+    case DBUS_TYPE_INT32:
     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, 4) + 4;
       break;
 
+    case DBUS_TYPE_INT64:
+    case DBUS_TYPE_UINT64:
     case DBUS_TYPE_DOUBLE:
-      *end_pos = _DBUS_ALIGN_VALUE (pos + 1, sizeof (double)) + sizeof (double);
-
+      
+      *end_pos = _DBUS_ALIGN_VALUE (pos, 8) + 8;
       break;
 
+    case DBUS_TYPE_OBJECT_PATH:
     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_CUSTOM:
       {
        int len;
-
-       /* Demarshal the length */
-       len = _dbus_demarshal_uint32 (str, byte_order, pos + 1, &pos);
-       
-       *end_pos = pos + len;
-      }
-      break;
-
-    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 string length */
+       len = _dbus_demarshal_uint32 (str, byte_order, pos, &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;
+       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  */
+       len = _dbus_demarshal_uint32 (str, byte_order, pos, &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;
     }
@@ -1524,14 +1890,14 @@ demarshal_and_validate_len (const DBusString *str,
   if (!_dbus_string_validate_nul (str, pos,
                                   align_4 - pos))
     {
-      _dbus_verbose ("array length alignment padding not initialized to nul\n");
+      _dbus_verbose ("array length alignment padding not initialized to nul at %d\n", pos);
       return -1;
     }
 
   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.
@@ -1539,8 +1905,8 @@ demarshal_and_validate_len (const DBusString *str,
 #define MAX_ARRAY_LENGTH (((unsigned int)_DBUS_INT_MAX) / 32)
   if (len > MAX_ARRAY_LENGTH)
     {
-      _dbus_verbose ("array length %u exceeds maximum of %u\n",
-                     len, MAX_ARRAY_LENGTH);
+      _dbus_verbose ("array length %u exceeds maximum of %u at pos %d\n",
+                     len, MAX_ARRAY_LENGTH, pos);
       return -1;
     }
   else
@@ -1574,11 +1940,144 @@ validate_string (const DBusString *str,
     }
 
   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 (_dbus_type_is_valid (*data))
+    {
+      *type = *data;
+      if (end_pos != NULL)
+       *end_pos = pos + 1;
+      return TRUE;
+    }
+
+  _dbus_verbose ("'%c' %d invalid type code\n", (int) *data, (int) *data);
+  
+  return FALSE;
+}
+
+/* Faster validator for array data that doesn't call
+ * validate_arg for each value
+ */
+static dbus_bool_t
+validate_array_data (const DBusString *str,
+                     int              byte_order,
+                     int               depth,
+                     int               type,
+                     int               array_type_pos,
+                     int               pos,
+                     int              *new_pos,
+                     int               end)
+{
+  switch (type)
+    {
+    case DBUS_TYPE_INVALID:
+      return FALSE;
+      break;
+
+    case DBUS_TYPE_NIL:
+      break;
+
+    case DBUS_TYPE_OBJECT_PATH:
+    case DBUS_TYPE_STRING:
+    case DBUS_TYPE_CUSTOM:
+    case DBUS_TYPE_ARRAY:
+    case DBUS_TYPE_DICT:
+      /* This clean recursion to validate_arg is what we
+       * are doing logically for all types, but we don't
+       * really want to call validate_arg for every byte
+       * in a byte array, so the primitive types are
+       * special-cased.
+       */
+      while (pos < end)
+        {
+          if (!_dbus_marshal_validate_arg (str, byte_order, depth,
+                                           type, array_type_pos, pos, &pos))
+            return FALSE;
+        }
+      break;
+      
+    case DBUS_TYPE_BYTE:
+      pos = end;
+      break;
+      
+    case DBUS_TYPE_BOOLEAN:
+      while (pos < end)
+        {
+          unsigned char c;
+          
+          c = _dbus_string_get_byte (str, pos);
+          
+          if (!(c == 0 || c == 1))
+            {
+              _dbus_verbose ("boolean value must be either 0 or 1, not %d\n", c);
+              return FALSE;
+            }
+          
+          ++pos;
+        }
+      break;
+      
+    case DBUS_TYPE_INT32:
+    case DBUS_TYPE_UINT32:
+      /* Call validate arg one time to check alignment padding
+       * at start of array
+       */
+      if (!_dbus_marshal_validate_arg (str, byte_order, depth,
+                                       type, array_type_pos, pos, &pos))
+        return FALSE;
+      pos = _DBUS_ALIGN_VALUE (end, 4);
+      break;
+
+    case DBUS_TYPE_INT64:
+    case DBUS_TYPE_UINT64:
+    case DBUS_TYPE_DOUBLE:
+      /* Call validate arg one time to check alignment padding
+       * at start of array
+       */
+      if (!_dbus_marshal_validate_arg (str, byte_order, depth,
+                                       type, array_type_pos, pos, &pos))
+        return FALSE;
+      pos = _DBUS_ALIGN_VALUE (end, 8);
+      break;
+      
+    default:
+      _dbus_verbose ("Unknown message arg type %d\n", type);
+      return FALSE;
+    }
+
+  *new_pos = pos;
+
+  return TRUE;
+}
 
 /** 
- * 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"
  *
@@ -1586,7 +2085,11 @@ validate_string (const DBusString *str,
  * 
  * @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 depth current recursion depth, to prevent excessive recursion
+ * @param type the type of the argument
+ * @param array_type_pos the position of the current array type, or
+ *        -1 if not in an array
+ * @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.
@@ -1594,54 +2097,75 @@ validate_string (const DBusString *str,
 dbus_bool_t
 _dbus_marshal_validate_arg (const DBusString *str,
                             int                      byte_order,
+                            int               depth,
+                           int               type,
+                           int               array_type_pos,
                             int               pos,
                             int              *end_pos)
 {
-  const char *data;
-
-  if (pos >= _dbus_string_get_length (str))
-    return FALSE;
+  if (pos > _dbus_string_get_length (str))
+    {
+      _dbus_verbose ("Validation went off the end of the message\n");
+      return FALSE;
+    }
 
-  _dbus_string_get_const_data_len (str, &data, pos, 1);
+#define MAX_VALIDATION_DEPTH 32
+  
+  if (depth > MAX_VALIDATION_DEPTH)
+    {
+      _dbus_verbose ("Maximum recursion depth reached validating message\n");
+      return FALSE;
+    }
   
-  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 byte 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)
+       if (!(c == 0 || c == 1))
          {
            _dbus_verbose ("boolean value must be either 0 or 1, not %d\n", c);
            return FALSE;
          }
        
-      *end_pos = pos + 2;
-      break;
+        *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;
@@ -1651,16 +2175,18 @@ _dbus_marshal_validate_arg (const DBusString *str,
       }
       break;
 
+    case DBUS_TYPE_INT64:
+    case DBUS_TYPE_UINT64:      
     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");
+            _dbus_verbose ("double/int64/uint64/objid alignment padding not initialized to nul at %d\n", pos);
             return FALSE;
           }
 
@@ -1668,6 +2194,7 @@ _dbus_marshal_validate_arg (const DBusString *str,
       }
       break;
 
+    case DBUS_TYPE_OBJECT_PATH:
     case DBUS_TYPE_STRING:
       {
        int len;
@@ -1675,172 +2202,178 @@ _dbus_marshal_validate_arg (const DBusString *str,
        /* 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;
 
         if (!validate_string (str, pos, len, end_pos))
           return FALSE;
-      }
-      break;
-
-    case DBUS_TYPE_BOOLEAN_ARRAY:
-      {
-       int len, i;
-
-       len = demarshal_and_validate_len (str, byte_order, pos + 1, &pos);
-        if (len < 0)
-          return FALSE;
 
-        if (len > _dbus_string_get_length (str) - pos)
+        if (type == DBUS_TYPE_OBJECT_PATH)
           {
-            _dbus_verbose ("boolean array length outside length of the message\n");
-            return FALSE;
+            if (!_dbus_string_validate_path (str, pos, len))
+              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:
+      break;
+
+    case DBUS_TYPE_CUSTOM:
       {
        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;
-       
-       *end_pos = pos + len;
-      }
-      break;
 
-    case DBUS_TYPE_INT32_ARRAY:
-    case DBUS_TYPE_UINT32_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;
 
-        _dbus_assert (_DBUS_ALIGN_VALUE (pos, 4) == (unsigned int) pos);
-        
-       *end_pos = pos + len * 4;
+       *end_pos = pos + len;
       }
       break;
-
-    case DBUS_TYPE_DOUBLE_ARRAY:
+      
+    case DBUS_TYPE_ARRAY:
       {
        int len;
-        int align_8;
-
-        len = demarshal_and_validate_len (str, byte_order, pos + 1, &pos);
-        if (len < 0)
-          return FALSE;
+       int end;
+       int array_type;
 
-       if (len == 0)
-         *end_pos = pos;
-       else
+       if (array_type_pos == -1)
          {
-           align_8 = _DBUS_ALIGN_VALUE (pos, 8);
-           if (!_dbus_string_validate_nul (str, pos,
-                                           align_8 - pos))
+           array_type_pos = pos;
+
+           do
              {
-               _dbus_verbose ("double array alignment padding not initialized to nul\n");
-               return FALSE;
+               if (!_dbus_marshal_validate_type (str, pos, &array_type, &pos))
+                 {
+                   _dbus_verbose ("invalid array type\n");
+                   return FALSE;
+                 }
+               
+               /* NIL values take up no space, so you couldn't iterate over an array of them.
+                * array of nil seems useless anyway; the useful thing might be array of
+                * (nil OR string) but we have no framework for that.
+                */
+               if (array_type == DBUS_TYPE_NIL)
+                 {
+                   _dbus_verbose ("array of NIL is not allowed\n");
+                   return FALSE;
+                 }
              }
+           while (array_type == DBUS_TYPE_ARRAY);
+         }
+       else
+         array_type_pos++;
 
-           *end_pos = align_8 + len * 8;
+       if (!_dbus_marshal_validate_type (str, array_type_pos, &array_type, NULL))
+         {
+           _dbus_verbose ("invalid array type\n");
+           return FALSE;
          }
-      }
-      break;
-      
-    case DBUS_TYPE_STRING_ARRAY:
-      {
-        int len;
-        int i;
         
-        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;
+         {
+           _dbus_verbose ("invalid array length (<0)\n");
+           return FALSE;
+         }
 
-       for (i = 0; i < len; i++)
+        if (len > _dbus_string_get_length (str) - pos)
+          {
+            _dbus_verbose ("array length outside length of the message\n");
+            return FALSE;
+          }
+       
+       end = pos + len;
+
+        if (len > 0 && !validate_array_data (str, byte_order, depth + 1,
+                                            array_type, array_type_pos,
+                                            pos, &pos, end))
          {
-           int str_len;
-           
-           str_len = demarshal_and_validate_len (str, byte_order,
-                                                  pos, &pos);
-            if (str_len < 0)
-              return FALSE;
+           _dbus_verbose ("invalid array data\n");
+           return FALSE;
+         }
 
-            if (!validate_string (str, pos, str_len, &pos))
-              return FALSE;            
+        if (pos < end)
+          {
+            /* This should not be able to happen, as long as validate_arg moves forward;
+             * but the check is here just to be paranoid.
+             */
+            _dbus_verbose ("array length %d specified was longer than actual array contents by %d\n",
+                           len, end - pos);
+            return FALSE;
+          }
+        
+       if (pos > end)
+         {
+           _dbus_verbose ("array contents exceeds array length %d by %d\n", len, pos - end);
+           return FALSE;
          }
 
        *end_pos = pos;
       }
       break;
 
-      case DBUS_TYPE_DICT:
-       {
-         int len;
-         int i;
+    case DBUS_TYPE_DICT:
+      {
+       int dict_type;
+       int len;
+       int end;
+       
+       len = demarshal_and_validate_len (str, byte_order, pos, &pos);
+        if (len < 0)
+          return FALSE;
 
-         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)
+        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)
+         {
+           /* Validate name */
+           if (!_dbus_marshal_validate_arg (str, byte_order, depth + 1,
+                                            DBUS_TYPE_STRING, -1, pos, &pos))
+             return FALSE;
+           
+           if (!_dbus_marshal_validate_type (str, pos, &dict_type, &pos))
+             {
+               _dbus_verbose ("invalid dict entry type at offset %d\n", pos);
                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))
+             }
+           
+           /* Validate element */
+           if (!_dbus_marshal_validate_arg (str, byte_order, depth + 1,
+                                            dict_type, -1, pos, &pos))
+             {
+               _dbus_verbose ("dict arg invalid at offset %d\n", pos);
                return FALSE;
-           }
-
-         *end_pos = pos;
-
-         break;
-       }
+             }
+         }
        
+       if (pos > end)
+         {
+           _dbus_verbose ("dict contents exceed stated dict length\n");
+           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;
     }
 
@@ -1850,6 +2383,35 @@ _dbus_marshal_validate_arg (const DBusString *str,
   return TRUE;
 }
 
+/**
+ * Return #TRUE if the typecode is a valid typecode
+ *
+ * @returns #TRUE if valid
+ */
+dbus_bool_t
+_dbus_type_is_valid (int typecode)
+{
+  switch (typecode)
+    {
+    case DBUS_TYPE_NIL:
+    case DBUS_TYPE_BYTE:
+    case DBUS_TYPE_BOOLEAN:
+    case DBUS_TYPE_INT32:
+    case DBUS_TYPE_UINT32:
+    case DBUS_TYPE_INT64:
+    case DBUS_TYPE_UINT64:
+    case DBUS_TYPE_DOUBLE:
+    case DBUS_TYPE_STRING:
+    case DBUS_TYPE_CUSTOM:
+    case DBUS_TYPE_ARRAY:
+    case DBUS_TYPE_DICT:
+    case DBUS_TYPE_OBJECT_PATH:
+      return TRUE;
+      
+    default:
+      return FALSE;
+    }
+}
 
 /**
  * If in verbose mode, print a block of binary data.
@@ -1957,12 +2519,98 @@ _dbus_verbose_bytes_of_string (const DBusString    *str,
       len = real_len - start;
     }
   
-  
-  _dbus_string_get_const_data_len (str, &d, start, len);
+  d = _dbus_string_get_const_data_len (str, start, len);
 
   _dbus_verbose_bytes (d, len);
 }
 
+/**
+ * Marshals a basic type
+ *
+ * @param str string to marshal to
+ * @param type type of value
+ * @param value pointer to value
+ * @param byte_order byte order
+ * @returns #TRUE on success
+ **/
+dbus_bool_t
+_dbus_marshal_basic_type (DBusString *str,
+                         char        type,
+                         void       *value,
+                         int         byte_order)
+{
+  dbus_bool_t retval;
+
+  switch (type)
+    {
+    case DBUS_TYPE_BYTE:
+    case DBUS_TYPE_BOOLEAN:
+      retval = _dbus_string_append_byte (str, *(unsigned char *)value);
+      break;
+    case DBUS_TYPE_INT32:
+    case DBUS_TYPE_UINT32:
+      return marshal_4_octets (str, byte_order, *(dbus_uint32_t *)value);
+      break;
+#ifdef DBUS_HAVE_INT64
+    case DBUS_TYPE_INT64:
+    case DBUS_TYPE_UINT64: 
+      retval = _dbus_marshal_uint64 (str, byte_order, *(dbus_uint64_t *)value);
+      break;
+#endif /* DBUS_HAVE_INT64 */
+    case DBUS_TYPE_DOUBLE:
+      retval = _dbus_marshal_double (str, byte_order, *(double *)value);
+      break;
+    default:
+      _dbus_assert_not_reached ("not a basic type");
+      retval = FALSE;
+      break;
+    }
+  return retval;
+}
+
+/**
+ * Marshals a basic type array
+ *
+ * @param str string to marshal to
+ * @param element_type type of array elements
+ * @param value pointer to value
+ * @param len length of value data in elements
+ * @param byte_order byte order
+ * @returns #TRUE on success
+ **/
+dbus_bool_t
+_dbus_marshal_basic_type_array (DBusString *str,
+                               char        element_type,
+                               const void *value,
+                               int         len,
+                               int         byte_order)
+{
+  switch (element_type)
+    {
+    case DBUS_TYPE_BOOLEAN:
+      /* FIXME: we canonicalize to 0 or 1 for the single boolean case 
+       * should we here too ? */
+    case DBUS_TYPE_BYTE:
+      return _dbus_marshal_byte_array (str, byte_order, value, len);
+      break;
+    case DBUS_TYPE_INT32:
+    case DBUS_TYPE_UINT32:
+      return marshal_4_octets_array (str, byte_order, value, len);
+      break;
+#ifdef DBUS_HAVE_INT64
+    case DBUS_TYPE_INT64:
+    case DBUS_TYPE_UINT64: 
+#endif /* DBUS_HAVE_INT64 */
+    case DBUS_TYPE_DOUBLE:
+      return marshal_8_octets_array (str, byte_order, value, len);
+      break;
+    default:
+      _dbus_assert_not_reached ("non basic type in array");
+      break;
+    }
+  return FALSE;
+}
+
 /** @} */
 
 #ifdef DBUS_BUILD_TESTS
@@ -1974,26 +2622,17 @@ _dbus_marshal_test (void)
 {
   DBusString str;
   char *tmp1, *tmp2;
+  int pos = 0, len;
   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;
-  
-  if (!_dbus_string_init (&str, _DBUS_INT_MAX))
+#ifdef DBUS_HAVE_INT64
+  dbus_int64_t array3[3] = { DBUS_INT64_CONSTANT (0x123ffffffff), 
+                             DBUS_INT64_CONSTANT (0x456ffffffff), 
+                             DBUS_INT64_CONSTANT (0x789ffffffff) }, *array4;
+#endif
+  char *s;
+  DBusString t;
+  
+  if (!_dbus_string_init (&str))
     _dbus_assert_not_reached ("failed to init string");
 
   /* Marshal doubles */
@@ -2029,6 +2668,30 @@ _dbus_marshal_test (void)
   if (!_dbus_demarshal_uint32 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == 0x12345678)
     _dbus_assert_not_reached ("demarshal failed");
 
+#ifdef DBUS_HAVE_INT64
+  /* Marshal signed integers */
+  if (!_dbus_marshal_int64 (&str, DBUS_BIG_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7)))
+    _dbus_assert_not_reached ("could not marshal signed integer value");
+  if (_dbus_demarshal_int64 (&str, DBUS_BIG_ENDIAN, pos, &pos) != DBUS_INT64_CONSTANT (-0x123456789abc7))
+    _dbus_assert_not_reached ("demarshal failed");
+
+  if (!_dbus_marshal_int64 (&str, DBUS_LITTLE_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7)))
+    _dbus_assert_not_reached ("could not marshal signed integer value");
+  if (_dbus_demarshal_int64 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) != DBUS_INT64_CONSTANT (-0x123456789abc7))
+    _dbus_assert_not_reached ("demarshal failed");
+  
+  /* Marshal unsigned integers */
+  if (!_dbus_marshal_uint64 (&str, DBUS_BIG_ENDIAN, DBUS_UINT64_CONSTANT (0x123456789abc7)))
+    _dbus_assert_not_reached ("could not marshal signed integer value");
+  if (!(_dbus_demarshal_uint64 (&str, DBUS_BIG_ENDIAN, pos, &pos) == DBUS_UINT64_CONSTANT (0x123456789abc7)))
+    _dbus_assert_not_reached ("demarshal failed");
+  
+  if (!_dbus_marshal_uint64 (&str, DBUS_LITTLE_ENDIAN, DBUS_UINT64_CONSTANT (0x123456789abc7)))
+    _dbus_assert_not_reached ("could not marshal signed integer value");
+  if (!(_dbus_demarshal_uint64 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == DBUS_UINT64_CONSTANT (0x123456789abc7)))
+    _dbus_assert_not_reached ("demarshal failed");
+#endif /* DBUS_HAVE_INT64 */
+  
   /* Marshal strings */
   tmp1 = "This is the dbus test string";
   if (!_dbus_marshal_string (&str, DBUS_BIG_ENDIAN, tmp1))
@@ -2055,101 +2718,222 @@ _dbus_marshal_test (void)
   if (len != 3)
     _dbus_assert_not_reached ("Signed integer array lengths differ!\n");
   dbus_free (array2);
+
+#ifdef DBUS_HAVE_INT64
+  /* Marshal 64-bit signed integer arrays */
+  if (!_dbus_marshal_int64_array (&str, DBUS_BIG_ENDIAN, array3, 3))
+    _dbus_assert_not_reached ("could not marshal integer array");
+  if (!_dbus_demarshal_int64_array (&str, DBUS_BIG_ENDIAN, pos, &pos, &array4, &len))
+    _dbus_assert_not_reached ("could not demarshal integer array");
+
+  if (len != 3)
+    _dbus_assert_not_reached ("Signed integer array lengths differ!\n");
+  dbus_free (array4);
+
+  /* set/pack 64-bit integers */
+  _dbus_string_set_length (&str, 8);
+
+  /* signed little */
+  _dbus_marshal_set_int64 (&str, DBUS_LITTLE_ENDIAN,
+                           0, DBUS_INT64_CONSTANT (-0x123456789abc7));
   
+  _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
+                _dbus_unpack_int64 (DBUS_LITTLE_ENDIAN,
+                                    _dbus_string_get_const_data (&str)));
+
+  /* signed big */
+  _dbus_marshal_set_int64 (&str, DBUS_BIG_ENDIAN,
+                           0, DBUS_INT64_CONSTANT (-0x123456789abc7));
 
-  /* Marshal dicts */
-  dict = dbus_dict_new ();
+  _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
+                _dbus_unpack_int64 (DBUS_BIG_ENDIAN,
+                                    _dbus_string_get_const_data (&str)));
 
-  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");
+  /* signed little pack */
+  _dbus_pack_int64 (DBUS_INT64_CONSTANT (-0x123456789abc7),
+                    DBUS_LITTLE_ENDIAN,
+                    _dbus_string_get_data (&str));
   
-  if (!dbus_dict_set_boolean (dict, "boolean", TRUE))
-    _dbus_assert_not_reached ("could not add boolean value");
+  _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
+                _dbus_unpack_int64 (DBUS_LITTLE_ENDIAN,
+                                    _dbus_string_get_const_data (&str)));
 
-  if (!dbus_dict_set_int32 (dict, "int32", 0x12345678))
-    _dbus_assert_not_reached ("could not add int32 value");
+  /* signed big pack */
+  _dbus_pack_int64 (DBUS_INT64_CONSTANT (-0x123456789abc7),
+                    DBUS_BIG_ENDIAN,
+                    _dbus_string_get_data (&str));
 
-  if (!dbus_dict_set_uint32 (dict, "uint32", 0x87654321))
-    _dbus_assert_not_reached ("could not add uint32 value");
+  _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
+                _dbus_unpack_int64 (DBUS_BIG_ENDIAN,
+                                    _dbus_string_get_const_data (&str)));
 
-  if (!dbus_dict_set_double (dict, "double", 3.14159))
-    _dbus_assert_not_reached ("could not add double value");
+  /* unsigned little */
+  _dbus_marshal_set_uint64 (&str, DBUS_LITTLE_ENDIAN,
+                            0, DBUS_UINT64_CONSTANT (0x123456789abc7));
+  
+  _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
+                _dbus_unpack_uint64 (DBUS_LITTLE_ENDIAN,
+                                     _dbus_string_get_const_data (&str)));
 
-  if (!dbus_dict_set_string (dict, "string", "test string"))
-    _dbus_assert_not_reached ("could not add string value");
+  /* unsigned big */
+  _dbus_marshal_set_uint64 (&str, DBUS_BIG_ENDIAN,
+                            0, DBUS_UINT64_CONSTANT (0x123456789abc7));
 
-  if (!dbus_dict_set_boolean_array (dict, "boolean_array", boolean_array, 4))
-    _dbus_assert_not_reached ("could not add boolean array");
+  _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
+                _dbus_unpack_uint64 (DBUS_BIG_ENDIAN,
+                                     _dbus_string_get_const_data (&str)));
 
-  if (!dbus_dict_set_int32_array (dict, "int32_array", int32_array, 5))
-    _dbus_assert_not_reached ("could not add int32 array");
+  /* unsigned little pack */
+  _dbus_pack_uint64 (DBUS_UINT64_CONSTANT (0x123456789abc7),
+                     DBUS_LITTLE_ENDIAN,
+                     _dbus_string_get_data (&str));
+  
+  _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
+                _dbus_unpack_uint64 (DBUS_LITTLE_ENDIAN,
+                                     _dbus_string_get_const_data (&str)));
 
-  if (!dbus_dict_set_uint32_array (dict, "uint32_array", uint32_array, 5))
-    _dbus_assert_not_reached ("could not add uint32 array");
+  /* unsigned big pack */
+  _dbus_pack_uint64 (DBUS_UINT64_CONSTANT (0x123456789abc7),
+                     DBUS_BIG_ENDIAN,
+                     _dbus_string_get_data (&str));
 
-  if (!dbus_dict_set_double_array (dict, "double_array", double_array, 3))
-    _dbus_assert_not_reached ("could not add double array");
+  _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
+                _dbus_unpack_uint64 (DBUS_BIG_ENDIAN,
+                                     _dbus_string_get_const_data (&str)));
+  
+#endif
 
-  if (!dbus_dict_set_string_array (dict, "string_array", string_array, 4))
-    _dbus_assert_not_reached ("could not add string array");
+  /* set/pack 32-bit integers */
+  _dbus_string_set_length (&str, 4);
 
-  if (!_dbus_marshal_dict (&str, DBUS_BIG_ENDIAN, dict))
-    _dbus_assert_not_reached ("could not marshal dict");
+  /* signed little */
+  _dbus_marshal_set_int32 (&str, DBUS_LITTLE_ENDIAN,
+                           0, -0x123456);
   
-  dbus_dict_unref (dict);
+  _dbus_assert (-0x123456 ==
+                _dbus_unpack_int32 (DBUS_LITTLE_ENDIAN,
+                                    _dbus_string_get_const_data (&str)));
+
+  /* signed big */
+  _dbus_marshal_set_int32 (&str, DBUS_BIG_ENDIAN,
+                           0, -0x123456);
+
+  _dbus_assert (-0x123456 ==
+                _dbus_unpack_int32 (DBUS_BIG_ENDIAN,
+                                    _dbus_string_get_const_data (&str)));
+
+  /* signed little pack */
+  _dbus_pack_int32 (-0x123456,
+                    DBUS_LITTLE_ENDIAN,
+                    _dbus_string_get_data (&str));
   
-  if (!_dbus_demarshal_dict (&str, DBUS_BIG_ENDIAN, pos, &pos, &dict))
-    _dbus_assert_not_reached ("could not demarshal dict");
+  _dbus_assert (-0x123456 ==
+                _dbus_unpack_int32 (DBUS_LITTLE_ENDIAN,
+                                    _dbus_string_get_const_data (&str)));
 
-  if (!dbus_dict_get_boolean (dict, "boolean", &our_bool) ||
-      !our_bool)
-    _dbus_assert_not_reached ("could not get boolean value");
+  /* signed big pack */
+  _dbus_pack_int32 (-0x123456,
+                    DBUS_BIG_ENDIAN,
+                    _dbus_string_get_data (&str));
 
-  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");
+  _dbus_assert (-0x123456 ==
+                _dbus_unpack_int32 (DBUS_BIG_ENDIAN,
+                                    _dbus_string_get_const_data (&str)));
+
+  /* unsigned little */
+  _dbus_marshal_set_uint32 (&str, DBUS_LITTLE_ENDIAN,
+                            0, 0x123456);
   
-  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");
+  _dbus_assert (0x123456 ==
+                _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN,
+                                     _dbus_string_get_const_data (&str)));
 
-  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");
+  /* unsigned big */
+  _dbus_marshal_set_uint32 (&str, DBUS_BIG_ENDIAN,
+                            0, 0x123456);
 
-  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");
+  _dbus_assert (0x123456 ==
+                _dbus_unpack_uint32 (DBUS_BIG_ENDIAN,
+                                     _dbus_string_get_const_data (&str)));
 
-  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");
+  /* unsigned little pack */
+  _dbus_pack_uint32 (0x123456,
+                     DBUS_LITTLE_ENDIAN,
+                     _dbus_string_get_data (&str));
+  
+  _dbus_assert (0x123456 ==
+                _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN,
+                                     _dbus_string_get_const_data (&str)));
 
-  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");
+  /* unsigned big pack */
+  _dbus_pack_uint32 (0x123456,
+                     DBUS_BIG_ENDIAN,
+                     _dbus_string_get_data (&str));
 
-  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");
+  _dbus_assert (0x123456 ==
+                _dbus_unpack_uint32 (DBUS_BIG_ENDIAN,
+                                     _dbus_string_get_const_data (&str)));
 
-  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");
+  /* Strings */
+  
+  _dbus_string_set_length (&str, 0);
 
-  if (len != 4)
-    _dbus_assert_not_reached ("string array lengths differ");
+  _dbus_marshal_string (&str, DBUS_LITTLE_ENDIAN,
+                        "Hello world");
+  
+  s = _dbus_demarshal_string (&str, DBUS_LITTLE_ENDIAN, 0, NULL);
+  _dbus_assert (strcmp (s, "Hello world") == 0);
+  dbus_free (s);
 
-  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_string_init_const (&t, "Hello world foo");
   
-  dbus_dict_unref (dict);
+  _dbus_marshal_set_string (&str, DBUS_LITTLE_ENDIAN, 0,
+                            &t, _dbus_string_get_length (&t));
   
-  _dbus_string_free (&str);
+  s = _dbus_demarshal_string (&str, DBUS_LITTLE_ENDIAN, 0, NULL);
+  _dbus_assert (strcmp (s, "Hello world foo") == 0);
+  dbus_free (s);
+
+  _dbus_string_init_const (&t, "Hello");
+  
+  _dbus_marshal_set_string (&str, DBUS_LITTLE_ENDIAN, 0,
+                            &t, _dbus_string_get_length (&t));
+  
+  s = _dbus_demarshal_string (&str, DBUS_LITTLE_ENDIAN, 0, NULL);
+  _dbus_assert (strcmp (s, "Hello") == 0);
+  dbus_free (s);
+
+  /* Strings (big endian) */
+  
+  _dbus_string_set_length (&str, 0);
+
+  _dbus_marshal_string (&str, DBUS_BIG_ENDIAN,
+                        "Hello world");
   
+  s = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, 0, NULL);
+  _dbus_assert (strcmp (s, "Hello world") == 0);
+  dbus_free (s);
+
+  _dbus_string_init_const (&t, "Hello world foo");
+  
+  _dbus_marshal_set_string (&str, DBUS_BIG_ENDIAN, 0,
+                            &t, _dbus_string_get_length (&t));
+  
+  s = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, 0, NULL);
+  _dbus_assert (strcmp (s, "Hello world foo") == 0);
+  dbus_free (s);
+
+  _dbus_string_init_const (&t, "Hello");
+  
+  _dbus_marshal_set_string (&str, DBUS_BIG_ENDIAN, 0,
+                            &t, _dbus_string_get_length (&t));
+  
+  s = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, 0, NULL);
+  _dbus_assert (strcmp (s, "Hello") == 0);
+  dbus_free (s);
+  
+  _dbus_string_free (&str);
       
   return TRUE;
 }