Revert merge of master (dbus-1.5) into dbus-1.4
[platform/upstream/dbus.git] / dbus / dbus-marshal-basic.c
index 9b430a5..3cbc721 100644 (file)
@@ -1,11 +1,11 @@
-/* -*- mode: C; c-file-style: "gnu" -*- */
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 /* dbus-marshal-basic.c  Marshalling routines for basic (primitive) types
  *
  * Copyright (C) 2002 CodeFactory AB
- * Copyright (C) 2003, 2004 Red Hat, Inc.
+ * Copyright (C) 2003, 2004, 2005 Red Hat, Inc.
  *
  * 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
  * the Free Software Foundation; either version 2 of the License, or
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
  */
 
+#include <config.h>
 #include "dbus-internals.h"
-#define DBUS_CAN_USE_DBUS_STRING_PRIVATE 1
-#include "dbus-string-private.h"
-
 #include "dbus-marshal-basic.h"
+#include "dbus-signature.h"
 
 #include <string.h>
 
  * @{
  */
 
-static dbus_uint32_t
-unpack_4_octets (int                  byte_order,
-                 const unsigned char *data)
+static void
+pack_2_octets (dbus_uint16_t   value,
+               int             byte_order,
+               unsigned char  *data)
+{
+  _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 2) == data);
+
+  if ((byte_order) == DBUS_LITTLE_ENDIAN)
+    *((dbus_uint16_t*)(data)) = DBUS_UINT16_TO_LE (value);
+  else
+    *((dbus_uint16_t*)(data)) = DBUS_UINT16_TO_BE (value);
+}
+
+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_UINT32_FROM_LE (*(dbus_uint32_t*)data);
+
+  if ((byte_order) == DBUS_LITTLE_ENDIAN)
+    *((dbus_uint32_t*)(data)) = DBUS_UINT32_TO_LE (value);
   else
-    return DBUS_UINT32_FROM_BE (*(dbus_uint32_t*)data);
+    *((dbus_uint32_t*)(data)) = DBUS_UINT32_TO_BE (value);
+}
+
+static void
+pack_8_octets (DBusBasicValue     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.u64);
+  else
+    *((dbus_uint64_t*)(data)) = DBUS_UINT64_TO_BE (value.u64);
+#else
+  *(DBus8ByteStruct*)data = value.u64;
+  swap_8_octets ((DBusBasicValue*)data, byte_order);
+#endif
+}
+
+/**
+ * Packs a 32 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_uint32 (dbus_uint32_t   value,
+                   int             byte_order,
+                   unsigned char  *data)
+{
+  pack_4_octets (value, byte_order, data);
 }
 
 #ifndef DBUS_HAVE_INT64
@@ -78,321 +124,152 @@ swap_bytes (unsigned char *data,
 }
 #endif /* !DBUS_HAVE_INT64 */
 
-/**
- * Union used to manipulate 8 bytes as if they
- * were various types. 
- */
-typedef union
+static void
+swap_8_octets (DBusBasicValue    *value,
+               int                byte_order)
 {
+  if (byte_order != DBUS_COMPILER_BYTE_ORDER)
+    {
 #ifdef DBUS_HAVE_INT64
-  dbus_int64_t  s; /**< 64-bit integer */
-  dbus_uint64_t u; /**< 64-bit unsigned integer */
+      value->u64 = DBUS_UINT64_SWAP_LE_BE (value->u64);
+#else
+      swap_bytes ((unsigned char *)value, 8);
 #endif
-  double d;        /**< double */
-} DBusOctets8;
+    }
+}
 
-static DBusOctets8
+#if 0
+static DBusBasicValue
 unpack_8_octets (int                  byte_order,
                  const unsigned char *data)
 {
-  DBusOctets8 r;
-  
+  DBusBasicValue 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);
+    r.u64 = DBUS_UINT64_FROM_LE (*(dbus_uint64_t*)data);
   else
-    r.u = DBUS_UINT64_FROM_BE (*(dbus_uint64_t*)data);
+    r.u64 = 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));
+  r.u64 = *(DBus8ByteStruct*)data;
+  swap_8_octets (&r, byte_order);
 #endif
-  
+
   return r;
 }
+#endif
 
+#ifndef _dbus_unpack_uint16
 /**
- * Unpacks a 32 bit unsigned integer from a data pointer
+ * Unpacks a 16 bit unsigned integer from a data pointer
  *
  * @param byte_order The byte order to use
  * @param data the data pointer
  * @returns the integer
  */
-dbus_uint32_t
-_dbus_unpack_uint32 (int                  byte_order,
+dbus_uint16_t
+_dbus_unpack_uint16 (int                  byte_order,
                      const unsigned char *data)
 {
-  return unpack_4_octets (byte_order, data);
-}  
+  _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 2) == data);
 
-/**
- * Unpacks a 32 bit signed integer from a data pointer
- *
- * @param byte_order The byte order to use
- * @param data the data pointer
- * @returns the integer
- */
-dbus_int32_t
-_dbus_unpack_int32 (int                  byte_order,
-                    const unsigned char *data)
-{
-  return (dbus_int32_t) unpack_4_octets (byte_order, data);
+  if (byte_order == DBUS_LITTLE_ENDIAN)
+    return DBUS_UINT16_FROM_LE (*(dbus_uint16_t*)data);
+  else
+    return DBUS_UINT16_FROM_BE (*(dbus_uint16_t*)data);
 }
+#endif /* _dbus_unpack_uint16 */
 
-#ifdef DBUS_HAVE_INT64
+#ifndef _dbus_unpack_uint32
 /**
- * Unpacks a 64 bit unsigned integer from a data pointer
+ * Unpacks a 32 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,
+dbus_uint32_t
+_dbus_unpack_uint32 (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)                  
-    *((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); 
+  if (byte_order == DBUS_LITTLE_ENDIAN)
+    return DBUS_UINT32_FROM_LE (*(dbus_uint32_t*)data);
   else
-    *((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
+    return DBUS_UINT32_FROM_BE (*(dbus_uint32_t*)data);
 }
+#endif /* _dbus_unpack_uint32 */
 
-/**
- * Packs a 32 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_uint32 (dbus_uint32_t   value,
-                   int             byte_order,
-                   unsigned char  *data)
+static void
+set_2_octets (DBusString          *str,
+              int                  offset,
+              dbus_uint16_t        value,
+              int                  byte_order)
 {
-  pack_4_octets (value, byte_order, data);
-}
+  char *data;
 
-/**
- * Packs a 32 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_int32 (dbus_int32_t   value,
-                  int            byte_order,
-                  unsigned char *data)
-{
-  pack_4_octets ((dbus_uint32_t) value, byte_order, data);
-}
+  _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
+                byte_order == DBUS_BIG_ENDIAN);
 
-#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);
-}
+  data = _dbus_string_get_data_len (str, offset, 2);
 
-/**
- * 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);
+  pack_2_octets (value, byte_order, data);
 }
-#endif /* DBUS_HAVE_INT64 */
 
 static void
 set_4_octets (DBusString          *str,
-              int                  byte_order,
               int                  offset,
-              dbus_uint32_t        value)
+              dbus_uint32_t        value,
+              int                  byte_order)
 {
   char *data;
-  
+
   _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);
+  pack_4_octets (value, byte_order, data);
 }
 
 static void
 set_8_octets (DBusString          *str,
-              int                  byte_order,
               int                  offset,
-              DBusOctets8          value)
+              DBusBasicValue       value,
+              int                  byte_order)
 {
   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);
 }
 
 /**
- * Sets the 4 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_int32 (DBusString          *str,
-                         int                  byte_order,
-                         int                  offset,
-                         dbus_int32_t         value)
-{
-  set_4_octets (str, byte_order, offset, (dbus_uint32_t) value);
-}
-
-/**
  * Sets the 4 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 pos the byte offset where int should be written
  * @param value the value
- * 
- */
-void
-_dbus_marshal_set_uint32 (DBusString          *str,
-                          int                  byte_order,
-                          int                  offset,
-                          dbus_uint32_t        value)
-{
-  set_4_octets (str, byte_order, offset, value);
-}
-
-#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)
+_dbus_marshal_set_uint32 (DBusString          *str,
+                          int                  pos,
+                          dbus_uint32_t        value,
+                          int                  byte_order)
 {
-  DBusOctets8 r;
-  r.u = value;
-  set_8_octets (str, byte_order, offset, r);
+  set_4_octets (str, pos, value, byte_order);
 }
-#endif /* DBUS_HAVE_INT64 */
 
 /**
  * Sets the existing marshaled string at the given offset with
@@ -405,1969 +282,961 @@ _dbus_marshal_set_uint64 (DBusString          *str,
  * 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
+ * @param pos the position of the marshaled string length
  * @param value the value
- * @param len the length to use
- * @returns #TRUE on success
- * 
+ * @param byte_order the byte order to use
+ * @param old_end_pos place to store byte after the nul byte of the old value
+ * @param new_end_pos place to store byte after the nul byte of the new value
+ * @returns #TRUE on success, #FALSE if no memory
+ *
  */
-dbus_bool_t
-_dbus_marshal_set_string (DBusString          *str,
-                          int                  byte_order,
-                          int                  offset,
-                          const DBusString    *value,
-                         int                  len)
+static dbus_bool_t
+set_string (DBusString          *str,
+            int                  pos,
+            const char          *value,
+            int                  byte_order,
+            int                 *old_end_pos,
+            int                 *new_end_pos)
 {
-  int old_len;
-  
-  _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
-                byte_order == DBUS_BIG_ENDIAN);
-  
-  old_len = _dbus_demarshal_uint32 (str, byte_order,
-                                    offset, NULL);
+  int old_len, new_len;
+  DBusString dstr;
+
+  _dbus_string_init_const (&dstr, value);
+
+  _dbus_assert (_DBUS_ALIGN_VALUE (pos, 4) == (unsigned) pos);
+  old_len = _dbus_unpack_uint32 (byte_order,
+                                 _dbus_string_get_const_data_len (str, pos, 4));
+
+  new_len = _dbus_string_get_length (&dstr);
 
-  if (!_dbus_string_replace_len (value, 0, len,
-                                 str, offset + 4, old_len))
+  if (!_dbus_string_replace_len (&dstr, 0, new_len,
+                                 str, pos + 4, old_len))
     return FALSE;
 
-  _dbus_marshal_set_uint32 (str, byte_order,
-                            offset, len);
+  _dbus_marshal_set_uint32 (str, pos, new_len, byte_order);
+
+  if (old_end_pos)
+    *old_end_pos = pos + 4 + old_len + 1;
+  if (new_end_pos)
+    *new_end_pos = pos + 4 + new_len + 1;
 
   return TRUE;
 }
 
 /**
- * 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
+ * Sets the existing marshaled signature at the given offset to a new
+ * marshaled signature. Same basic ideas as set_string().
  *
- * @param str the string to write the marshalled path to
- * @param offset the byte offset where path should be written
+ * @param str the string to write the marshalled signature to
+ * @param pos the position of the marshaled signature length
+ * @param value the value
  * @param byte_order the byte order to use
- * @param path the new path
- * @param path_len number of elements in the path
+ * @param old_end_pos place to store byte after the nul byte of the old value
+ * @param new_end_pos place to store byte after the nul byte of the new value
+ * @returns #TRUE on success, #FALSE if no memory
+ *
  */
-void
-_dbus_marshal_set_object_path (DBusString         *str,
-                               int                 byte_order,
-                               int                 offset,
-                               const char        **path,
-                               int                 path_len)
+static dbus_bool_t
+set_signature (DBusString          *str,
+               int                  pos,
+               const char          *value,
+               int                  byte_order,
+               int                 *old_end_pos,
+               int                 *new_end_pos)
 {
+  int old_len, new_len;
+  DBusString dstr;
 
-  /* FIXME */
-}
+  _dbus_string_init_const (&dstr, value);
 
-static dbus_bool_t
-marshal_4_octets (DBusString   *str,
-                  int           insert_at,
-                  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);
+  old_len = _dbus_string_get_byte (str, pos);
+  new_len = _dbus_string_get_length (&dstr);
 
-  return _dbus_string_insert_4_aligned (str, insert_at,
-                                        (const unsigned char *)&value);
-}
+  if (!_dbus_string_replace_len (&dstr, 0, new_len,
+                                 str, pos + 1, old_len))
+    return FALSE;
 
-static dbus_bool_t
-marshal_8_octets (DBusString *str,
-                  int         insert_at,
-                  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 */
+  _dbus_string_set_byte (str, pos, new_len);
+
+  if (old_end_pos)
+    *old_end_pos = pos + 1 + old_len + 1;
+  if (new_end_pos)
+    *new_end_pos = pos + 1 + new_len + 1;
 
-  return _dbus_string_insert_8_aligned (str, insert_at,
-                                        (const unsigned char *)&value);
+  return TRUE;
 }
 
 /**
- * Marshals a double value.
+ * Sets an existing basic type value to a new value.
+ * Arguments work the same way as _dbus_marshal_basic_type().
  *
- * @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
+ * @param str the string
+ * @param pos location of the current value
+ * @param type the type of the current and new values
+ * @param value the address of the new value
+ * @param byte_order byte order for marshaling
+ * @param old_end_pos location to store end position of the old value, or #NULL
+ * @param new_end_pos location to store end position of the new value, or #NULL
+ * @returns #FALSE if no memory
  */
 dbus_bool_t
-_dbus_marshal_double (DBusString *str,
-                     int         byte_order,
-                     double      value)
+_dbus_marshal_set_basic (DBusString       *str,
+                         int               pos,
+                         int               type,
+                         const void       *value,
+                         int               byte_order,
+                         int              *old_end_pos,
+                         int              *new_end_pos)
 {
-  DBusOctets8 r;
-  r.d = value;
-  return marshal_8_octets (str, _dbus_string_get_length (str),
-                           byte_order, r);
-}
+  const DBusBasicValue *vp;
 
-/**
- * Marshals a 32 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_int32  (DBusString   *str,
-                     int           byte_order,
-                     dbus_int32_t  value)
-{
-  return marshal_4_octets (str, _dbus_string_get_length (str),
-                           byte_order, (dbus_uint32_t) value);
-}
-
-/**
- * Marshals a 32 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_uint32 (DBusString   *str,
-                      int           byte_order,
-                      dbus_uint32_t value)
-{
-  return marshal_4_octets (str, _dbus_string_get_length (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, _dbus_string_get_length (str),
-                           byte_order, r);
-}
-
-/**
- * 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, _dbus_string_get_length (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
- * @returns #TRUE on success
- */
-dbus_bool_t
-_dbus_marshal_string (DBusString    *str,
-                     int            byte_order,
-                     const char    *value)
-{
-  int len, old_string_len;
-
-  old_string_len = _dbus_string_get_length (str);
-  
-  len = strlen (value);
-
-  if (!_dbus_marshal_uint32 (str, byte_order, len))
-    {
-      /* Restore the previous length */
-      _dbus_string_set_length (str, old_string_len);
-
-      return FALSE;
-    }
-
-  return _dbus_string_append_len (str, value, len + 1);
-}
-
-/**
- * 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
- * @param len length of string to marshal in bytes
- * @returns #TRUE on success
- */
-dbus_bool_t
-_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 */
-      _dbus_string_set_length (str, old_string_len);
-
-      return FALSE;
-    }
-
-  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 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 number of elements in the array
- * @returns #TRUE on success
- */
-dbus_bool_t
-_dbus_marshal_byte_array (DBusString          *str,
-                         int                  byte_order,
-                         const unsigned 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 */
-      _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;
-
-  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;
-  
- error:
-  /* Restore previous length */
-  _dbus_string_set_length (str, old_string_len);
-  
-  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);
-
-  /*  The array length is the length in bytes of the array,
-   * *excluding* alignment padding.
-   */
-  if (!_dbus_marshal_uint32 (str, byte_order, len * 8))
-    goto error;
-
-  array_start = _dbus_string_get_length (str);
-
-  /* Note that we do alignment padding unconditionally
-   * even if the array is empty; this means that
-   * padding + len is always equal to the number of bytes
-   * in the array.
-   */
-  
-  if (!_dbus_string_align_length (str, 8))
-    goto error;
-  
-  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);
-}
-
-/**
- * Marshals a 32 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_uint32_array (DBusString          *str,
-                           int                  byte_order,
-                           const dbus_uint32_t  *value,
-                           int                  len)
-{
-  return marshal_4_octets_array (str, byte_order,
-                                 value,
-                                 len);
-}
-
-#ifdef DBUS_HAVE_INT64
-
-/**
- * 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);
-}
-
-/**
- * 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
- *
- * @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_double_array (DBusString          *str,
-                           int                  byte_order,
-                           const double        *value,
-                           int                  len)
-{
-  return marshal_8_octets_array (str, byte_order,
-                                 (const DBusOctets8*) value,
-                                 len);
-}
-
-/**
- * Marshals a string 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_string_array (DBusString  *str,
-                           int          byte_order,
-                           const char **value,
-                           int          len)
-{
-  int i, old_string_len, array_start;
-
-  old_string_len = _dbus_string_get_length (str);
-
-  /* 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:
-  /* Restore previous length */
-  _dbus_string_set_length (str, old_string_len);
-  
-  return FALSE;      
-}
-
-/**
- * Marshals an object path value.
- * 
- * @param str the string to append the marshalled value to
- * @param byte_order the byte order to use
- * @param path the path
- * @param path_len length of the path
- * @returns #TRUE on success
- */
-static dbus_bool_t
-_dbus_marshal_object_path (DBusString            *str,
-                           int                    byte_order,
-                           const char           **path,
-                           int                    path_len)
-{
-  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;
-
-  array_start = _dbus_string_get_length (str);
-  
-  i = 0;
-  while (i < path_len)
-    {
-      if (!_dbus_string_append_byte (str, '/'))
-        goto nomem;
-      
-      if (!_dbus_string_append (str, path[0]))
-        goto nomem;
-
-      ++i;
-    }
-
-  /* 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);
-  
-  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;
-  
-  pos = _DBUS_ALIGN_VALUE (pos, 4);
-  
-  if (new_pos)
-    *new_pos = pos + 4;
-
-  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.
- *
- * @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 double.
- */
-double
-_dbus_demarshal_double (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.d;
-}
-
-/**
- * Demarshals a 32 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_int32_t
-_dbus_demarshal_int32  (const DBusString *str,
-                       int               byte_order,
-                       int               pos,
-                       int              *new_pos)
-{
-  return (dbus_int32_t) demarshal_4_octets (str, byte_order, pos, new_pos);
-}
-
-/**
- * Demarshals a 32 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_uint32_t
-_dbus_demarshal_uint32  (const DBusString *str,
-                        int         byte_order,
-                        int         pos,
-                        int        *new_pos)
-{
-  return demarshal_4_octets (str, byte_order, pos, new_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);
+  vp = value;
 
   switch (type)
     {
     case DBUS_TYPE_BYTE:
-    case DBUS_TYPE_BOOLEAN:
-      *(unsigned char *) value = _dbus_string_get_byte (str, *pos);
-      (*pos)++;
+      _dbus_string_set_byte (str, pos, vp->byt);
+      if (old_end_pos)
+        *old_end_pos = pos + 1;
+      if (new_end_pos)
+        *new_end_pos = pos + 1;
+      return TRUE;
       break;
+    case DBUS_TYPE_INT16:
+    case DBUS_TYPE_UINT16:
+      pos = _DBUS_ALIGN_VALUE (pos, 2);
+      set_2_octets (str, pos, vp->u16, byte_order);
+      if (old_end_pos)
+        *old_end_pos = pos + 2;
+      if (new_end_pos)
+        *new_end_pos = pos + 2;
+      return TRUE;
+      break;
+    case DBUS_TYPE_BOOLEAN:
     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;
+    case DBUS_TYPE_UNIX_FD:
+      pos = _DBUS_ALIGN_VALUE (pos, 4);
+      set_4_octets (str, pos, vp->u32, byte_order);
+      if (old_end_pos)
+        *old_end_pos = pos + 4;
+      if (new_end_pos)
+        *new_end_pos = pos + 4;
+      return TRUE;
       break;
-#ifdef DBUS_HAVE_INT64
     case DBUS_TYPE_INT64:
-    case DBUS_TYPE_UINT64: 
-#endif /* DBUS_HAVE_INT64 */
+    case DBUS_TYPE_UINT64:
     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;
+      pos = _DBUS_ALIGN_VALUE (pos, 8);
+      set_8_octets (str, pos, *vp, byte_order);
+      if (old_end_pos)
+        *old_end_pos = pos + 8;
+      if (new_end_pos)
+        *new_end_pos = pos + 8;
+      return TRUE;
       break;
     case DBUS_TYPE_STRING:
-      _dbus_assert_not_reached ("FIXME string is a basic type");
-      break;
     case DBUS_TYPE_OBJECT_PATH:
-      _dbus_assert_not_reached ("FIXME object path is a basic type");
+      pos = _DBUS_ALIGN_VALUE (pos, 4);
+      _dbus_assert (vp->str != NULL);
+      return set_string (str, pos, vp->str, byte_order,
+                         old_end_pos, new_end_pos);
+      break;
+    case DBUS_TYPE_SIGNATURE:
+      _dbus_assert (vp->str != NULL);
+      return set_signature (str, pos, vp->str, byte_order,
+                            old_end_pos, new_end_pos);
       break;
     default:
-      _dbus_verbose ("type %s not a basic type\n",
-                     _dbus_type_to_string (type));
       _dbus_assert_not_reached ("not a basic type");
-      break;
-    }
-}
-
-/**
- * Demarshals an UTF-8 string.
- *
- * @todo Should we check the string to make sure
- * that it's  valid UTF-8, and maybe "fix" the string
- * if it's broken?
- *
- * @todo Should probably demarshal to a DBusString,
- * having memcpy() in here is Evil(tm).
- *
- * @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 string.
- */
-char *
-_dbus_demarshal_string (const DBusString *str,
-                       int               byte_order,
-                       int               pos,
-                       int              *new_pos)
-{
-  int len;
-  char *retval;
-  const char *data;
-  
-  len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
-
-  retval = dbus_malloc (len + 1);
-
-  if (!retval)
-    return NULL;
-
-  data = _dbus_string_get_const_data_len (str, pos, len + 1);
-
-  if (!data)
-    return NULL;
-
-  memcpy (retval, data, len + 1);
-
-  if (new_pos)
-    *new_pos = pos + len + 1;
-  
-  return retval;
-}
-
-/**
- * Demarshals a byte array.
- *
- * @todo Should probably demarshal to a DBusString,
- * having memcpy() in here is Evil(tm).
- *
- * @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_byte_array (const DBusString  *str,
-                           int                byte_order,
-                           int                pos,
-                           int               *new_pos,
-                           unsigned char    **array,
-                           int               *array_len)
-{
-  int len;
-  unsigned char *retval;
-  const char *data;
-
-  len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
-
-  if (len == 0)
-    {
-      *array_len = len;
-      *array = NULL;
-
-      if (new_pos)
-       *new_pos = pos;
-      
-      return TRUE;
-    }
-  
-  retval = dbus_malloc (len);
-
-  if (!retval)
-    return FALSE;
-
-  data = _dbus_string_get_const_data_len (str, pos, len);
-
-  if (!data)
-    {
-      dbus_free (retval);
       return FALSE;
-    }
-
-  memcpy (retval, data, len);
-
-  if (new_pos)
-    *new_pos = pos + len;
-
-  *array = retval;
-  *array_len = len;
-  
-  return TRUE;
-}
-
-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_uint32_t *retval;
-  int byte_len;
-  
-  byte_len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
-  len = byte_len / 4;
-
-  if (len == 0)
-    {
-      *array_len = 0;
-      *array = NULL;
-
-      if (new_pos)
-       *new_pos = pos;
-      
-      return TRUE;
-    }
-
-  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 + byte_len;
-
-  *array_len = len;
-  *array = retval;
-  
-  return TRUE;  
-}
-
-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;
-  DBusOctets8 *retval;
-  int byte_len;
-  
-  byte_len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
-
-  pos = _DBUS_ALIGN_VALUE (pos, 8);
-  
-  len = byte_len / 8;
-
-  if (len == 0)
-    {
-      *array_len = 0;
-      *array = NULL;
-
-      if (new_pos)
-       *new_pos = pos;
-      
-      return TRUE;
-    }
-
-  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++)
-        {
-#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 + byte_len;
-
-  *array_len = len;
-  *array = retval;
-  
-  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)
-{
-  return demarshal_4_octets_array (str, byte_order, pos, new_pos,
-                                   (dbus_uint32_t**) array, array_len);
+      break;
+    }
 }
 
 /**
- * Demarshals a 32 bit unsigned integer array.
+ * Convenience function to demarshal a 32 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
- * @param array the array
- * @param array_len length of the demarshaled data
- * @returns #TRUE on success
+ * @returns the demarshaled integer.
  */
-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)
+dbus_uint32_t
+_dbus_marshal_read_uint32  (const DBusString *str,
+                            int               pos,
+                            int               byte_order,
+                            int              *new_pos)
 {
-  return demarshal_4_octets_array (str, byte_order, pos, new_pos,
-                                   array, array_len);
-}
+  pos = _DBUS_ALIGN_VALUE (pos, 4);
 
-#ifdef DBUS_HAVE_INT64
+  if (new_pos)
+    *new_pos = pos + 4;
 
-/**
- * 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);
+  _dbus_assert (pos + 4 <= _dbus_string_get_length (str));
+  
+  return _dbus_unpack_uint32 (byte_order,
+                              _dbus_string_get_const_data (str) + pos);
 }
 
 /**
- * Demarshals a 64 bit unsigned integer array.
+ * Demarshals a basic-typed value. The "value" pointer is always
+ * the address of a variable of the basic type. So e.g.
+ * if the basic type is "double" then the pointer is
+ * a double*, and if it's "char*" then the pointer is
+ * a "char**".
+ *
+ * A value of type #DBusBasicValue is guaranteed to be large enough to
+ * hold any of the types that may be returned, which is handy if you
+ * are trying to do things generically. For example you can pass
+ * a DBusBasicValue* in to this function, and then pass the same
+ * DBusBasicValue* in to _dbus_marshal_basic_type() in order to
+ * move a value from one place to another.
  *
  * @param str the string containing the data
+ * @param pos position in the string
+ * @param type type of value to demarshal
+ * @param value pointer to return value 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)
+ * @param new_pos pointer to update with new position, or #NULL
+ **/
+void
+_dbus_marshal_read_basic (const DBusString      *str,
+                          int                    pos,
+                          int                    type,
+                          void                  *value,
+                          int                    byte_order,
+                          int                   *new_pos)
 {
-  return demarshal_8_octets_array (str, byte_order, pos, new_pos,
-                                   (DBusOctets8**) array, array_len);
-}
-
-#endif /* DBUS_HAVE_INT64 */
+  const char *str_data;
 
-/**
- * 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);
-}
+  _dbus_assert (dbus_type_is_basic (type));
 
+  str_data = _dbus_string_get_const_data (str);
 
-/**
- * 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)
+  /* Below we volatile types to avoid aliasing issues;
+   * see http://bugs.freedesktop.org/show_bug.cgi?id=20137
+   */
+  
+  switch (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);
+      {
+      volatile unsigned char *vp = value;
+      *vp = (unsigned char) _dbus_string_get_byte (str, pos);
+      (pos)++;
+      }
+      break;
+    case DBUS_TYPE_INT16:
+    case DBUS_TYPE_UINT16:
+      {
+      volatile dbus_uint16_t *vp = value;
+      pos = _DBUS_ALIGN_VALUE (pos, 2);
+      *vp = *(dbus_uint16_t *)(str_data + pos);
+      if (byte_order != DBUS_COMPILER_BYTE_ORDER)
+       *vp = DBUS_UINT16_SWAP_LE_BE (*vp);
+      pos += 2;
+      }
       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);
+    case DBUS_TYPE_BOOLEAN:
+    case DBUS_TYPE_UNIX_FD:
+      {
+      volatile dbus_uint32_t *vp = value;
+      pos = _DBUS_ALIGN_VALUE (pos, 4);
+      *vp = *(dbus_uint32_t *)(str_data + pos);
+      if (byte_order != DBUS_COMPILER_BYTE_ORDER)
+       *vp = DBUS_UINT32_SWAP_LE_BE (*vp);
+      pos += 4;
+      }
       break;
-#ifdef DBUS_HAVE_INT64
     case DBUS_TYPE_INT64:
-    case DBUS_TYPE_UINT64: 
-#endif /* DBUS_HAVE_INT64 */
+    case DBUS_TYPE_UINT64:
     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");
+      {
+      volatile dbus_uint64_t *vp = value;
+      pos = _DBUS_ALIGN_VALUE (pos, 8);
+#ifdef DBUS_HAVE_INT64
+      if (byte_order != DBUS_COMPILER_BYTE_ORDER)
+        *vp = DBUS_UINT64_SWAP_LE_BE (*(dbus_uint64_t*)(str_data + pos));
+      else
+        *vp = *(dbus_uint64_t*)(str_data + pos);
+#else
+      *vp = *(DBus8ByteStruct*) (str_data + pos);
+      swap_8_octets (vp, byte_order);
+#endif
+      pos += 8;
+      }
       break;
-    }
-  return FALSE;
-}
+    case DBUS_TYPE_STRING:
+    case DBUS_TYPE_OBJECT_PATH:
+      {
+        int len;
+        volatile char **vp = value;
 
-/**
- * Demarshals a string 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 location for length of the demarshaled data or NULL
- * @returns #TRUE on success
- */
-dbus_bool_t
-_dbus_demarshal_string_array (const DBusString   *str,
-                             int                 byte_order,
-                             int                 pos,
-                             int                *new_pos,
-                             char             ***array,
-                             int                *array_len)
-{
-  int bytes_len, i;
-  int len, allocated;
-  int end_pos;
-  char **retval;
-  
-  bytes_len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
-  
-  if (bytes_len == 0)
-    {
-      *array_len = 0;
-      *array = NULL;
+        len = _dbus_marshal_read_uint32 (str, pos, byte_order, &pos);
 
-      if (new_pos)
-       *new_pos = pos;
-      
-      return TRUE;
-    }
+        *vp = (char*) str_data + pos;
 
-  len = 0;
-  allocated = 4;
-  end_pos = pos + bytes_len;
-  
-  retval = dbus_new (char *, allocated);
+        pos += len + 1; /* length plus nul */
+      }
+      break;
+    case DBUS_TYPE_SIGNATURE:
+      {
+        int len;
+        volatile char **vp = value;
 
-  if (!retval)
-    return FALSE;
+        len = _dbus_string_get_byte (str, pos);
+        pos += 1;
 
-  while (pos < end_pos)
-    {
-      retval[len] = _dbus_demarshal_string (str, byte_order, pos, &pos);
-      
-      if (retval[len] == NULL)
-       goto error;
-      
-      len += 1;
+        *vp = (char*) str_data + pos;
 
-      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;
-        }
+        pos += len + 1; /* length plus nul */
+      }
+      break;
+    default:
+      _dbus_warn_check_failed ("type %s %d not a basic type\n",
+                               _dbus_type_to_string (type), type);
+      _dbus_assert_not_reached ("not a basic type");
+      break;
     }
-      
-  retval[len] = NULL;
 
   if (new_pos)
     *new_pos = pos;
-  
-  *array = retval;
-  *array_len = len;
-  
-  return TRUE;
+}
 
- error:
-  for (i = 0; i < len; i++)
-    dbus_free (retval[i]);
-  dbus_free (retval);
+static dbus_bool_t
+marshal_2_octets (DBusString   *str,
+                  int           insert_at,
+                  dbus_uint16_t value,
+                  int           byte_order,
+                  int          *pos_after)
+{
+  dbus_bool_t retval;
+  int orig_len;
 
-  return FALSE;
-}
+  _dbus_assert (sizeof (value) == 2);
 
-/** Set to 1 to get a bunch of spew about disassembling the path string */
-#define VERBOSE_DECOMPOSE 0
+  if (byte_order != DBUS_COMPILER_BYTE_ORDER)
+    value = DBUS_UINT16_SWAP_LE_BE (value);
 
-/**
- * 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_decompose_path (const char*     data,
-                      int             len,
-                      char         ***path,
-                      int            *path_len)
-{
-  char **retval;
-  int n_components;
-  int i, j, comp;
+  orig_len = _dbus_string_get_length (str);
 
-  _dbus_assert (data != NULL);
+  retval = _dbus_string_insert_2_aligned (str, insert_at,
+                                          (const unsigned char *)&value);
 
-#if VERBOSE_DECOMPOSE
-  _dbus_verbose ("Decomposing path \"%s\"\n",
-                 data);
-#endif
-  
-  n_components = 0;
-  i = 0;
-  while (i < len)
+  if (pos_after)
     {
-      if (data[i] == '/')
-        n_components += 1;
-      ++i;
+      *pos_after = insert_at + (_dbus_string_get_length (str) - orig_len);
+      _dbus_assert (*pos_after <= _dbus_string_get_length (str));
     }
-  
-  retval = dbus_new0 (char*, n_components + 1);
 
-  if (retval == NULL)
-    return FALSE;
+  return retval;
+}
 
-  comp = 0;
-  i = 0;
-  while (i < len)
-    {
-      if (data[i] == '/')
-        ++i;
-      j = i;
+static dbus_bool_t
+marshal_4_octets (DBusString   *str,
+                  int           insert_at,
+                  dbus_uint32_t value,
+                  int           byte_order,
+                  int          *pos_after)
+{
+  dbus_bool_t retval;
+  int orig_len;
+
+  _dbus_assert (sizeof (value) == 4);
 
-      while (j < len && data[j] != '/')
-        ++j;
+  if (byte_order != DBUS_COMPILER_BYTE_ORDER)
+    value = DBUS_UINT32_SWAP_LE_BE (value);
 
-      /* Now [i, j) is the path component */
-      _dbus_assert (i < j);
-      _dbus_assert (data[i] != '/');
-      _dbus_assert (j == len || data[j] == '/');
+  orig_len = _dbus_string_get_length (str);
 
-#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
+  retval = _dbus_string_insert_4_aligned (str, insert_at,
+                                          (const unsigned char *)&value);
 
-      ++comp;
-      i = j;
+  if (pos_after)
+    {
+      *pos_after = insert_at + (_dbus_string_get_length (str) - orig_len);
+      _dbus_assert (*pos_after <= _dbus_string_get_length (str));
     }
-  _dbus_assert (i == len);
-  
-  *path = retval;
-  if (path_len)
-    *path_len = n_components;
-  
-  return TRUE;
+
+  return retval;
 }
 
-/**
- * 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)
+static dbus_bool_t
+marshal_8_octets (DBusString    *str,
+                  int            insert_at,
+                  DBusBasicValue value,
+                  int            byte_order,
+                  int           *pos_after)
 {
-  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_bool_t retval;
+  int orig_len;
 
-  if (!_dbus_decompose_path (data, len, path, path_len))
-    return FALSE;
+  _dbus_assert (sizeof (value) == 8);
 
-  if (new_pos)
-    *new_pos = pos + len + 1;
+  swap_8_octets (&value, byte_order);
 
-  return TRUE;
+  orig_len = _dbus_string_get_length (str);
+
+  retval = _dbus_string_insert_8_aligned (str, insert_at,
+                                          (const unsigned char *)&value);
+
+  if (pos_after)
+    *pos_after = insert_at + _dbus_string_get_length (str) - orig_len;
+
+  return retval;
 }
 
-/**
- * Skips over a basic type, reporting the following position.
- *
- * @param str the string containing the data
- * @param type type of value to demarshal
- * @param byte_order the byte order
- * @param pos pointer to position in the string,
- *            updated on return to new position
- **/
-void
-_dbus_marshal_skip_basic_type (const DBusString      *str,
-                               int                    type,
-                               int                    byte_order,
-                               int                   *pos)
-{
-  switch (type)
+enum
+  {
+    MARSHAL_AS_STRING,
+    MARSHAL_AS_SIGNATURE,
+    MARSHAL_AS_BYTE_ARRAY
+  };
+
+static dbus_bool_t
+marshal_len_followed_by_bytes (int                  marshal_as,
+                               DBusString          *str,
+                               int                  insert_at,
+                               const unsigned char *value,
+                               int                  data_len, /* doesn't include nul if any */
+                               int                  byte_order,
+                               int                 *pos_after)
+{
+  int pos;
+  DBusString value_str;
+  int value_len;
+
+  _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN || byte_order == DBUS_BIG_ENDIAN);
+  if (insert_at > _dbus_string_get_length (str))
+    _dbus_warn ("insert_at = %d string len = %d data_len = %d\n",
+                insert_at, _dbus_string_get_length (str), data_len);
+  
+  if (marshal_as == MARSHAL_AS_BYTE_ARRAY)
+    value_len = data_len;
+  else
+    value_len = data_len + 1; /* value has a nul */
+
+  _dbus_string_init_const_len (&value_str, value, value_len);
+
+  pos = insert_at;
+
+  if (marshal_as == MARSHAL_AS_SIGNATURE)
     {
-    case DBUS_TYPE_BYTE:
-    case DBUS_TYPE_BOOLEAN:
-      (*pos)++;
-      break;
-    case DBUS_TYPE_INT32:
-    case DBUS_TYPE_UINT32:
-      *pos = _DBUS_ALIGN_VALUE (*pos, 4);
-      *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);
-      *pos += 8;
-      break;
-    case DBUS_TYPE_STRING:
-      _dbus_assert_not_reached ("FIXME string is a basic type");
-      break;
-    case DBUS_TYPE_OBJECT_PATH:
-      _dbus_assert_not_reached ("FIXME object path is a basic type");
-      break;
-    default:
-      _dbus_verbose ("type %s not a basic type\n",
-                     _dbus_type_to_string (type));
-      _dbus_assert_not_reached ("not a basic type");
-      break;
+      _dbus_assert (data_len <= DBUS_MAXIMUM_SIGNATURE_LENGTH);
+      _dbus_assert (data_len <= 255); /* same as max sig len right now */
+      
+      if (!_dbus_string_insert_byte (str, pos, data_len))
+        goto oom;
+
+      pos += 1;
+    }
+  else
+    {
+      if (!marshal_4_octets (str, pos, data_len,
+                             byte_order, &pos))
+        goto oom;
     }
-}
 
-/**
- * Skips an array, returning the next position.
- *
- * @param str the string containing the data
- * @param byte_order the byte order
- * @param pos pointer to position in the string,
- *            updated on return to new position
- */
-void
-_dbus_marshal_skip_array (const DBusString  *str,
-                          int                byte_order,
-                          int               *pos)
-{
-  int len;
+  if (!_dbus_string_copy_len (&value_str, 0, value_len,
+                              str, pos))
+    goto oom;
+
+#if 0
+  /* too expensive */
+  _dbus_assert (_dbus_string_equal_substring (&value_str, 0, value_len,
+                                              str, pos));
+  _dbus_verbose_bytes_of_string (str, pos, value_len);
+#endif
+
+  pos += value_len;
+
+  if (pos_after)
+    *pos_after = pos;
+
+  return TRUE;
 
-  len = _dbus_demarshal_uint32 (str, byte_order, *pos, pos);
+ oom:
+  /* Delete what we've inserted */
+  _dbus_string_delete (str, insert_at, pos - insert_at);
 
-  /* FIXME we need to insert alignment padding according to array type */
-  
-  *pos += len;
+  return FALSE;
+}
+
+static dbus_bool_t
+marshal_string (DBusString    *str,
+                int            insert_at,
+                const char    *value,
+                int            byte_order,
+                int           *pos_after)
+{
+  return marshal_len_followed_by_bytes (MARSHAL_AS_STRING,
+                                        str, insert_at, value,
+                                        strlen (value),
+                                        byte_order, pos_after);
+}
+
+static dbus_bool_t
+marshal_signature (DBusString    *str,
+                   int            insert_at,
+                   const char    *value,
+                   int           *pos_after)
+{
+  return marshal_len_followed_by_bytes (MARSHAL_AS_SIGNATURE,
+                                        str, insert_at, value,
+                                        strlen (value),
+                                        DBUS_COMPILER_BYTE_ORDER, /* irrelevant */
+                                        pos_after);
 }
 
-/** 
- * Returns the position right after the end of an argument.  PERFORMS
- * NO VALIDATION WHATSOEVER. The message must have been previously
- * validated.
+/**
+ * Marshals a basic-typed value. The "value" pointer is always the
+ * address of a variable containing the basic type value.
+ * So for example for int32 it will be dbus_int32_t*, and
+ * for string it will be const char**. This is for symmetry
+ * with _dbus_marshal_read_basic() and to have a simple
+ * consistent rule.
  *
- * @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
- * @returns TRUE if more data exists after the arg
- */
+ * @param str string to marshal to
+ * @param insert_at where to insert the value
+ * @param type type of value
+ * @param value pointer to a variable containing the value
+ * @param byte_order byte order
+ * @param pos_after #NULL or the position after the type
+ * @returns #TRUE on success
+ **/
 dbus_bool_t
-_dbus_marshal_get_arg_end_pos (const DBusString *str,
-                               int               byte_order,
-                              int               type,
-                               int               pos,
-                               int              *end_pos)
+_dbus_marshal_write_basic (DBusString *str,
+                           int         insert_at,
+                           int         type,
+                           const void *value,
+                           int         byte_order,
+                           int        *pos_after)
 {
-  if (pos >= _dbus_string_get_length (str))
-    return FALSE;
+  const DBusBasicValue *vp;
+
+  _dbus_assert (dbus_type_is_basic (type));
+
+  vp = value;
 
   switch (type)
     {
-    case DBUS_TYPE_INVALID:
-      return FALSE;
-      break;
-
     case DBUS_TYPE_BYTE:
-      *end_pos = pos + 1;
+      if (!_dbus_string_insert_byte (str, insert_at, vp->byt))
+        return FALSE;
+      if (pos_after)
+        *pos_after = insert_at + 1;
+      return TRUE;
+      break;
+    case DBUS_TYPE_INT16:
+    case DBUS_TYPE_UINT16:
+      return marshal_2_octets (str, insert_at, vp->u16,
+                               byte_order, pos_after);
       break;
-      
     case DBUS_TYPE_BOOLEAN:
-      *end_pos = pos + 1;
+      return marshal_4_octets (str, insert_at, vp->u32 != FALSE,
+                               byte_order, pos_after);
       break;
-
     case DBUS_TYPE_INT32:
     case DBUS_TYPE_UINT32:
-      *end_pos = _DBUS_ALIGN_VALUE (pos, 4) + 4;
+    case DBUS_TYPE_UNIX_FD:
+      return marshal_4_octets (str, insert_at, vp->u32,
+                               byte_order, pos_after);
       break;
-
     case DBUS_TYPE_INT64:
     case DBUS_TYPE_UINT64:
     case DBUS_TYPE_DOUBLE:
-      
-      *end_pos = _DBUS_ALIGN_VALUE (pos, 8) + 8;
+      return marshal_8_octets (str, insert_at, *vp, byte_order, pos_after);
       break;
 
-    case DBUS_TYPE_OBJECT_PATH:
     case DBUS_TYPE_STRING:
-      {
-       int len;
-       
-       /* Demarshal the length */
-       len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
-
-       *end_pos = pos + len + 1;
-      }
+    case DBUS_TYPE_OBJECT_PATH:
+      _dbus_assert (vp->str != NULL);
+      return marshal_string (str, insert_at, vp->str, byte_order, pos_after);
       break;
-      
-    case DBUS_TYPE_ARRAY:
-      {
-       int len;
-
-       /* Demarshal the length  */
-       len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
-
-        /* FIXME needs to align to the right boundary for the array type */
-       *end_pos = _DBUS_ALIGN_VALUE (pos, 4) + len;
-      }
+    case DBUS_TYPE_SIGNATURE:
+      _dbus_assert (vp->str != NULL);
+      return marshal_signature (str, insert_at, vp->str, pos_after);
       break;
-      
     default:
-      _dbus_warn ("Unknown message arg type %d\n", type);
-      _dbus_assert_not_reached ("Unknown message argument type\n");
+      _dbus_assert_not_reached ("not a basic type");
       return FALSE;
+      break;
     }
+}
+
+static dbus_bool_t
+marshal_1_octets_array (DBusString          *str,
+                        int                  insert_at,
+                        const unsigned char *value,
+                        int                  n_elements,
+                        int                  byte_order,
+                        int                 *pos_after)
+{
+  int pos;
+  DBusString value_str;
+
+  _dbus_string_init_const_len (&value_str, value, n_elements);
 
-  if (*end_pos > _dbus_string_get_length (str))
+  pos = insert_at;
+
+  if (!_dbus_string_copy_len (&value_str, 0, n_elements,
+                              str, pos))
     return FALSE;
-  
+
+  pos += n_elements;
+
+  if (pos_after)
+    *pos_after = pos;
+
   return TRUE;
 }
 
 /**
- * Demarshals and validates a length; returns < 0 if the validation
- * fails. The length is required to be small enough that
- * len*sizeof(double) will not overflow, and small enough to fit in a
- * signed integer. DOES NOT check whether the length points
- * beyond the end of the string, because it doesn't know the
- * size of array elements.
+ * Swaps the elements of an array to the opposite byte order
  *
- * @param str the string
- * @param byte_order the byte order
- * @param pos the unaligned string position (snap to next aligned)
- * @param new_pos return location for new position.
+ * @param data start of array
+ * @param n_elements number of elements
+ * @param alignment size of each element
  */
-static int
-demarshal_and_validate_len (const DBusString *str,
-                            int               byte_order,
-                            int               pos,
-                            int              *new_pos)
+void
+_dbus_swap_array (unsigned char *data,
+                  int            n_elements,
+                  int            alignment)
 {
-  int align_4 = _DBUS_ALIGN_VALUE (pos, 4);
-  unsigned int len;
+  unsigned char *d;
+  unsigned char *end;
 
-  _dbus_assert (new_pos != NULL);
+  _dbus_assert (_DBUS_ALIGN_ADDRESS (data, alignment) == data);
+
+  /* we use const_data and cast it off so DBusString can be a const string
+   * for the unit tests. don't ask.
+   */
+  d = data;
+  end = d + (n_elements * alignment);
   
-  if ((align_4 + 4) > _dbus_string_get_length (str))
+  if (alignment == 8)
     {
-      _dbus_verbose ("not enough room in message for array length\n");
-      return -1;
+      while (d != end)
+        {
+#ifdef DBUS_HAVE_INT64
+          *((dbus_uint64_t*)d) = DBUS_UINT64_SWAP_LE_BE (*((dbus_uint64_t*)d));
+#else
+          swap_8_bytes ((DBusBasicValue*) d);
+#endif
+          d += 8;
+        }
     }
-  
-  if (!_dbus_string_validate_nul (str, pos,
-                                  align_4 - pos))
+  else if (alignment == 4)
+    {
+      while (d != end)
+        {
+          *((dbus_uint32_t*)d) = DBUS_UINT32_SWAP_LE_BE (*((dbus_uint32_t*)d));
+          d += 4;
+        }
+    }
+  else
     {
-      _dbus_verbose ("array length alignment padding not initialized to nul at %d\n", pos);
-      return -1;
+      _dbus_assert (alignment == 2);
+      
+      while (d != end)
+        {
+          *((dbus_uint16_t*)d) = DBUS_UINT16_SWAP_LE_BE (*((dbus_uint16_t*)d));
+          d += 2;
+        }
     }
+}
 
-  len = _dbus_demarshal_uint32 (str, byte_order, align_4, new_pos);
+static void
+swap_array (DBusString *str,
+            int         array_start,
+            int         n_elements,
+            int         byte_order,
+            int         alignment)
+{
+  _dbus_assert (_DBUS_ALIGN_VALUE (array_start, alignment) == (unsigned) array_start);
 
-  /* 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.
-   */  
-#define MAX_ARRAY_LENGTH (((unsigned int)_DBUS_INT_MAX) / 32)
-  if (len > MAX_ARRAY_LENGTH)
+  if (byte_order != DBUS_COMPILER_BYTE_ORDER)
     {
-      _dbus_verbose ("array length %u exceeds maximum of %u at pos %d\n",
-                     len, MAX_ARRAY_LENGTH, pos);
-      return -1;
+      /* we use const_data and cast it off so DBusString can be a const string
+       * for the unit tests. don't ask.
+       */
+      _dbus_swap_array ((unsigned char*) (_dbus_string_get_const_data (str) + array_start),
+                        n_elements, alignment);
     }
-  else
-    return (int) len;
 }
 
 static dbus_bool_t
-validate_string (const DBusString *str,
-                 int               pos,
-                 int               len_without_nul,
-                 int              *end_pos)
+marshal_fixed_multi (DBusString           *str,
+                     int                   insert_at,
+                     const DBusBasicValue *value,
+                     int                   n_elements,
+                     int                   byte_order,
+                     int                   alignment,
+                     int                  *pos_after)
 {
-  *end_pos = pos + len_without_nul + 1;
-  
-  if (*end_pos > _dbus_string_get_length (str))
-    {
-      _dbus_verbose ("string length outside length of the message\n");
-      return FALSE;
-    }
+  int old_string_len;
+  int array_start;
+  DBusString t;
+  int len_in_bytes;
+
+  _dbus_assert (n_elements <= DBUS_MAXIMUM_ARRAY_LENGTH / alignment);
   
-  if (_dbus_string_get_byte (str, pos + len_without_nul) != '\0')
-    {
-      _dbus_verbose ("string arg not nul-terminated\n");
-      return FALSE;
-    }
+  old_string_len = _dbus_string_get_length (str);
+
+  len_in_bytes = n_elements * alignment;
+  array_start = insert_at;
   
-  if (!_dbus_string_validate_utf8 (str, pos, len_without_nul))
-    {
-      _dbus_verbose ("string is not valid UTF-8\n");
-      return FALSE;
-    }
+  /* Note that we do alignment padding unconditionally
+   * even if the array is empty; this means that
+   * padding + len is always equal to the number of bytes
+   * in the array.
+   */
+
+  if (!_dbus_string_insert_alignment (str, &array_start, alignment))
+    goto error;
+
+  _dbus_string_init_const_len (&t,
+                               (const unsigned char*) value,
+                               len_in_bytes);
+
+  if (!_dbus_string_copy (&t, 0,
+                          str, array_start))
+    goto error;
+
+  swap_array (str, array_start, n_elements, byte_order, alignment);
 
+  if (pos_after)
+    *pos_after = array_start + len_in_bytes;
+  
   return TRUE;
-}   
+
+ error:
+  _dbus_string_delete (str, insert_at,
+                       _dbus_string_get_length (str) - old_string_len);
+
+  return FALSE;
+}
 
 /**
- * Validates and returns a typecode at a specific position
- * in the message
+ * Marshals a block of values of fixed-length type all at once, as an
+ * optimization.  dbus_type_is_fixed() returns #TRUE for fixed-length
+ * types, which are the basic types minus the string-like types.
  *
- * @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.
- */
+ * The value argument should be the adddress of an
+ * array, so e.g. "const dbus_uint32_t**"
+ *
+ * @param str string to marshal to
+ * @param insert_at where to insert the value
+ * @param element_type type of array elements
+ * @param value address of an array to marshal
+ * @param n_elements number of elements in the array
+ * @param byte_order byte order
+ * @param pos_after #NULL or the position after the type
+ * @returns #TRUE on success
+ **/
 dbus_bool_t
-_dbus_marshal_validate_type   (const DBusString *str,
-                              int               pos,
-                              int              *type,
-                              int              *end_pos)
-{
-  const char *data;
+_dbus_marshal_write_fixed_multi (DBusString *str,
+                                 int         insert_at,
+                                 int         element_type,
+                                 const void *value,
+                                 int         n_elements,
+                                 int         byte_order,
+                                 int        *pos_after)
+{
+  const void* vp = *(const DBusBasicValue**)value;
+  
+  _dbus_assert (dbus_type_is_fixed (element_type));
+  _dbus_assert (n_elements >= 0);
+
+#if 0
+  _dbus_verbose ("writing %d elements of %s\n",
+                 n_elements, _dbus_type_to_string (element_type));
+#endif
   
-  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))
+  switch (element_type)
     {
-      *type = *data;
-      if (end_pos != NULL)
-       *end_pos = pos + 1;
-      return TRUE;
+    case DBUS_TYPE_BYTE:
+      return marshal_1_octets_array (str, insert_at, vp, n_elements, byte_order, pos_after);
+      break;
+    case DBUS_TYPE_INT16:
+    case DBUS_TYPE_UINT16:
+      return marshal_fixed_multi (str, insert_at, vp, n_elements, byte_order, 2, pos_after);
+    case DBUS_TYPE_BOOLEAN:
+    case DBUS_TYPE_INT32:
+    case DBUS_TYPE_UINT32:
+    case DBUS_TYPE_UNIX_FD:
+      return marshal_fixed_multi (str, insert_at, vp, n_elements, byte_order, 4, pos_after);
+      break;
+    case DBUS_TYPE_INT64:
+    case DBUS_TYPE_UINT64:
+    case DBUS_TYPE_DOUBLE:
+      return marshal_fixed_multi (str, insert_at, vp, n_elements, byte_order, 8, pos_after);
+      break;
+
+    default:
+      _dbus_assert_not_reached ("non fixed type in array write");
+      break;
     }
 
-  _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)
+
+/**
+ * Skips over a basic-typed value, reporting the following position.
+ *
+ * @param str the string containing the data
+ * @param type type of value to read
+ * @param byte_order the byte order
+ * @param pos pointer to position in the string,
+ *            updated on return to new position
+ **/
+void
+_dbus_marshal_skip_basic (const DBusString      *str,
+                          int                    type,
+                          int                    byte_order,
+                          int                   *pos)
 {
+  _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
+                byte_order == DBUS_BIG_ENDIAN);
+  
   switch (type)
     {
-    case DBUS_TYPE_INVALID:
-      return FALSE;
-      break;
-
-    case DBUS_TYPE_OBJECT_PATH:
-    case DBUS_TYPE_STRING:
-    case DBUS_TYPE_ARRAY:
-      /* 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;
+      (*pos)++;
       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;
-        }
+    case DBUS_TYPE_INT16:
+    case DBUS_TYPE_UINT16:
+      *pos = _DBUS_ALIGN_VALUE (*pos, 2);
+      *pos += 2;
       break;
-      
+    case DBUS_TYPE_BOOLEAN:
     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);
+    case DBUS_TYPE_UNIX_FD:
+      *pos = _DBUS_ALIGN_VALUE (*pos, 4);
+      *pos += 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);
+      *pos = _DBUS_ALIGN_VALUE (*pos, 8);
+      *pos += 8;
       break;
-      
-    default:
-      _dbus_verbose ("Unknown message arg type %d\n", type);
-      return FALSE;
-    }
+    case DBUS_TYPE_STRING:
+    case DBUS_TYPE_OBJECT_PATH:
+      {
+        int len;
 
-  *new_pos = pos;
+        len = _dbus_marshal_read_uint32 (str, *pos, byte_order, pos);
+        
+        *pos += len + 1; /* length plus nul */
+      }
+      break;
+    case DBUS_TYPE_SIGNATURE:
+      {
+        int len;
 
-  return TRUE;
+        len = _dbus_string_get_byte (str, *pos);
+
+        *pos += len + 2; /* length byte plus length plus nul */
+      }
+      break;
+    default:
+      _dbus_warn ("type %s not a basic type\n",
+                  _dbus_type_to_string (type));
+      _dbus_assert_not_reached ("not a basic type");
+      break;
+    }
 }
 
-/** 
- * 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"
+/**
+ * Skips an array, returning the next position.
  *
- * @todo security: need to audit this function.
- * 
- * @param str a string
- * @param byte_order the byte order to use
- * @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.
+ * @param str the string containing the data
+ * @param element_type the type of array elements
+ * @param byte_order the byte order
+ * @param pos pointer to position in the string,
+ *            updated on return to new position
  */
-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)
+void
+_dbus_marshal_skip_array (const DBusString  *str,
+                          int                element_type,
+                          int                byte_order,
+                          int               *pos)
 {
-  if (pos > _dbus_string_get_length (str))
-    {
-      _dbus_verbose ("Validation went off the end of the message\n");
-      return FALSE;
-    }
+  dbus_uint32_t array_len;
+  int i;
+  int alignment;
 
-#define MAX_VALIDATION_DEPTH 32
-  
-  if (depth > MAX_VALIDATION_DEPTH)
-    {
-      _dbus_verbose ("Maximum recursion depth reached validating message\n");
-      return FALSE;
-    }
-  
-  switch (type)
+  i = _DBUS_ALIGN_VALUE (*pos, 4);
+
+  array_len = _dbus_marshal_read_uint32 (str, i, byte_order, &i);
+
+  alignment = _dbus_type_get_alignment (element_type);
+
+  i = _DBUS_ALIGN_VALUE (i, alignment);
+
+  *pos = i + array_len;
+}
+
+/**
+ * Gets the alignment requirement for the given type;
+ * will be 1, 4, or 8.
+ *
+ * @param typecode the type
+ * @returns alignment of 1, 4, or 8
+ */
+int
+_dbus_type_get_alignment (int typecode)
+{
+  switch (typecode)
     {
-    case DBUS_TYPE_INVALID:
-      return FALSE;
-      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_VARIANT:
+    case DBUS_TYPE_SIGNATURE:
+      return 1;
+    case DBUS_TYPE_INT16:
+    case DBUS_TYPE_UINT16:
+      return 2;
     case DBUS_TYPE_BOOLEAN:
-      {
-       unsigned char c;
-
-        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);
-
-       if (!(c == 0 || c == 1))
-         {
-           _dbus_verbose ("boolean value must be either 0 or 1, not %d\n", c);
-           return FALSE;
-         }
-       
-        *end_pos = pos + 1;
-      }
-      break;
-      
     case DBUS_TYPE_INT32:
     case DBUS_TYPE_UINT32:
-      {
-        int align_4 = _DBUS_ALIGN_VALUE (pos, 4);
-        
-        if (!_dbus_string_validate_nul (str, pos,
-                                        align_4 - pos))
-          {
-            _dbus_verbose ("int32/uint32 alignment padding not initialized to nul\n");
-            return FALSE;
-          }
-
-        *end_pos = align_4 + 4;
-      }
-      break;
-
-    case DBUS_TYPE_INT64:
-    case DBUS_TYPE_UINT64:      
-    case DBUS_TYPE_DOUBLE:
-      {
-        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,
-                                        align_8 - pos))
-          {
-            _dbus_verbose ("double/int64/uint64/objid alignment padding not initialized to nul at %d\n", pos);
-            return FALSE;
-          }
-
-        *end_pos = align_8 + 8;
-      }
-      break;
-
-    case DBUS_TYPE_OBJECT_PATH:
+    case DBUS_TYPE_UNIX_FD:
+      /* this stuff is 4 since it starts with a length */
     case DBUS_TYPE_STRING:
-      {
-       int len;
-
-       /* Demarshal the length, which does NOT include
-         * nul termination
-         */
-       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;
-
-        if (type == DBUS_TYPE_OBJECT_PATH)
-          {
-            if (!_dbus_string_validate_path (str, pos, len))
-              return FALSE;
-          }
-      }
-      break;
-      
+    case DBUS_TYPE_OBJECT_PATH:
     case DBUS_TYPE_ARRAY:
-      {
-       int len;
-       int end;
-       int array_type;
-
-       if (array_type_pos == -1)
-         {
-           array_type_pos = pos;
-
-           do
-             {
-               if (!_dbus_marshal_validate_type (str, pos, &array_type, &pos))
-                 {
-                   _dbus_verbose ("invalid array type\n");
-                   return FALSE;
-                 }
-             }
-           while (array_type == DBUS_TYPE_ARRAY);
-         }
-       else
-         array_type_pos++;
-
-       if (!_dbus_marshal_validate_type (str, array_type_pos, &array_type, NULL))
-         {
-           _dbus_verbose ("invalid array type\n");
-           return FALSE;
-         }
-        
-       len = demarshal_and_validate_len (str, byte_order, pos, &pos);
-        if (len < 0)
-         {
-           _dbus_verbose ("invalid array length (<0)\n");
-           return FALSE;
-         }
-
-        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))
-         {
-           _dbus_verbose ("invalid array data\n");
-           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;
-         }
+      return 4;
+    case DBUS_TYPE_INT64:
+    case DBUS_TYPE_UINT64:
+    case DBUS_TYPE_DOUBLE:
+      /* struct is 8 since it could contain an 8-aligned item
+       * and it's simpler to just always align structs to 8;
+       * we want the amount of padding in a struct of a given
+       * type to be predictable, not location-dependent.
+       * DICT_ENTRY is always the same as struct.
+       */
+    case DBUS_TYPE_STRUCT:
+    case DBUS_TYPE_DICT_ENTRY:
+      return 8;
 
-       *end_pos = pos;
-      }
-      break;
-      
     default:
-      _dbus_verbose ("Unknown message arg type %d\n", type);
-      return FALSE;
+      _dbus_assert_not_reached ("unknown typecode in _dbus_type_get_alignment()");
+      return 0;
     }
-
-  if (*end_pos > _dbus_string_get_length (str))
-    return FALSE;
-  
-  return TRUE;
 }
 
+
 /**
- * Return #TRUE if the typecode is a valid typecode
+ * Return #TRUE if the typecode is a valid typecode.
+ * #DBUS_TYPE_INVALID surprisingly enough is not considered valid, and
+ * random unknown bytes aren't either. This function is safe with
+ * untrusted data.
  *
  * @returns #TRUE if valid
  */
@@ -2378,6 +1247,8 @@ _dbus_type_is_valid (int typecode)
     {
     case DBUS_TYPE_BYTE:
     case DBUS_TYPE_BOOLEAN:
+    case DBUS_TYPE_INT16:
+    case DBUS_TYPE_UINT16:
     case DBUS_TYPE_INT32:
     case DBUS_TYPE_UINT32:
     case DBUS_TYPE_INT64:
@@ -2385,62 +1256,82 @@ _dbus_type_is_valid (int typecode)
     case DBUS_TYPE_DOUBLE:
     case DBUS_TYPE_STRING:
     case DBUS_TYPE_OBJECT_PATH:
+    case DBUS_TYPE_SIGNATURE:
     case DBUS_TYPE_ARRAY:
     case DBUS_TYPE_STRUCT:
+    case DBUS_TYPE_DICT_ENTRY:
     case DBUS_TYPE_VARIANT:
+    case DBUS_TYPE_UNIX_FD:
       return TRUE;
-      
+
     default:
       return FALSE;
     }
 }
 
 /**
- * Gets the alignment requirement for the given type;
- * will be 1, 4, or 8.
+ * Returns a string describing the given type.
  *
- * @param typecode the type
- * @returns alignment of 1, 4, or 8
+ * @param typecode the type to describe
+ * @returns a constant string describing the type
  */
-int
-_dbus_type_get_alignment (int typecode)
+const char *
+_dbus_type_to_string (int typecode)
 {
   switch (typecode)
     {
-    case DBUS_TYPE_BYTE:
+    case DBUS_TYPE_INVALID:
+      return "invalid";
     case DBUS_TYPE_BOOLEAN:
-    case DBUS_TYPE_VARIANT:
-    case DBUS_TYPE_SIGNATURE:
-      return 1;
+      return "boolean";
+    case DBUS_TYPE_BYTE:
+      return "byte";
+    case DBUS_TYPE_INT16:
+      return "int16";
+    case DBUS_TYPE_UINT16:
+      return "uint16";
     case DBUS_TYPE_INT32:
+      return "int32";
     case DBUS_TYPE_UINT32:
-      /* this stuff is 4 since it starts with a length */
-    case DBUS_TYPE_STRING:
-    case DBUS_TYPE_OBJECT_PATH:
-    case DBUS_TYPE_ARRAY:
-      return 4;
+      return "uint32";
     case DBUS_TYPE_INT64:
+      return "int64";
     case DBUS_TYPE_UINT64:
+      return "uint64";      
     case DBUS_TYPE_DOUBLE:
-      /* struct is 8 since it could contain an 8-aligned item
-       * and it's simpler to just always align structs to 8;
-       * we want the amount of padding in a struct of a given
-       * type to be predictable, not location-dependent.
-       */
+      return "double";
+    case DBUS_TYPE_STRING:
+      return "string";
+    case DBUS_TYPE_OBJECT_PATH:
+      return "object_path";
+    case DBUS_TYPE_SIGNATURE:
+      return "signature";
     case DBUS_TYPE_STRUCT:
-      return 8;
-      
+      return "struct";
+    case DBUS_TYPE_DICT_ENTRY:
+      return "dict_entry";
+    case DBUS_TYPE_ARRAY:
+      return "array";
+    case DBUS_TYPE_VARIANT:
+      return "variant";
+    case DBUS_STRUCT_BEGIN_CHAR:
+      return "begin_struct";
+    case DBUS_STRUCT_END_CHAR:
+      return "end_struct";
+    case DBUS_DICT_ENTRY_BEGIN_CHAR:
+      return "begin_dict_entry";
+    case DBUS_DICT_ENTRY_END_CHAR:
+      return "end_dict_entry";
+    case DBUS_TYPE_UNIX_FD:
+      return "unix_fd";
     default:
-      _dbus_assert_not_reached ("unknown typecode in _dbus_type_get_alignment()");
-      return 0;
+      return "unknown";
     }
 }
 
 /**
  * If in verbose mode, print a block of binary data.
  *
- * @todo right now it prints even if not in verbose mode
- * 
  * @param data the data
  * @param len the length of the data
  * @param offset where to start counting for byte indexes
@@ -2454,7 +1345,10 @@ _dbus_verbose_bytes (const unsigned char *data,
   const unsigned char *aligned;
 
   _dbus_assert (len >= 0);
-  
+
+  if (!_dbus_is_verbose())
+    return;
+
   /* Print blanks on first row if appropriate */
   aligned = _DBUS_ALIGN_ADDRESS (data, 4);
   if (aligned > data)
@@ -2463,7 +1357,7 @@ _dbus_verbose_bytes (const unsigned char *data,
 
   if (aligned != data)
     {
-      _dbus_verbose ("%4d\t%p: ", - (data - aligned), aligned); 
+      _dbus_verbose ("%4ld\t%p: ", - (long)(data - aligned), aligned);
       while (aligned != data)
         {
           _dbus_verbose ("    ");
@@ -2480,7 +1374,7 @@ _dbus_verbose_bytes (const unsigned char *data,
           _dbus_verbose ("%4d\t%p: ",
                          offset + i, &data[i]);
         }
-      
+
       if (data[i] >= 32 &&
           data[i] <= 126)
         _dbus_verbose (" '%c' ", data[i]);
@@ -2497,13 +1391,17 @@ _dbus_verbose_bytes (const unsigned char *data,
                            _dbus_unpack_uint32 (DBUS_BIG_ENDIAN, &data[i-4]),
                            _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN, &data[i-4]));
 
-          if (i > 7 && 
+          if (i > 7 &&
               _DBUS_ALIGN_ADDRESS (&data[i], 8) == &data[i])
             {
+#ifdef DBUS_INT64_PRINTF_MODIFIER
+              _dbus_verbose (" u64: 0x%" DBUS_INT64_PRINTF_MODIFIER "x",
+                             *(dbus_uint64_t*)&data[i-8]);
+#endif
               _dbus_verbose (" dbl: %g",
                              *(double*)&data[i-8]);
             }
-          
+
           _dbus_verbose ("\n");
         }
     }
@@ -2529,7 +1427,7 @@ _dbus_verbose_bytes_of_string (const DBusString    *str,
   real_len = _dbus_string_get_length (str);
 
   _dbus_assert (start >= 0);
-  
+
   if (start > real_len)
     {
       _dbus_verbose ("  [%d,%d) is not inside string of length %d\n",
@@ -2543,111 +1441,57 @@ _dbus_verbose_bytes_of_string (const DBusString    *str,
                      start, len, real_len);
       len = real_len - start;
     }
-  
+
   d = _dbus_string_get_const_data_len (str, start, len);
 
   _dbus_verbose_bytes (d, len, start);
 }
 
-/**
- * Marshals a basic type
- *
- * @param str string to marshal to
- * @param insert_at where to insert the value
- * @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,
-                          int         insert_at,
-                         char        type,
-                         const void *value,
-                         int         byte_order)
+static int
+map_type_char_to_type (int t)
 {
-  dbus_bool_t retval;
-
-  switch (type)
+  if (t == DBUS_STRUCT_BEGIN_CHAR)
+    return DBUS_TYPE_STRUCT;
+  else if (t == DBUS_DICT_ENTRY_BEGIN_CHAR)
+    return DBUS_TYPE_DICT_ENTRY;
+  else
     {
-    case DBUS_TYPE_BYTE:
-    case DBUS_TYPE_BOOLEAN:
-      retval = _dbus_string_insert_byte (str, insert_at, *(const unsigned char *)value);
-      break;
-    case DBUS_TYPE_INT32:
-    case DBUS_TYPE_UINT32:
-      return marshal_4_octets (str, insert_at, byte_order, *(const dbus_uint32_t *)value);
-      break;
-#ifdef DBUS_HAVE_INT64
-    case DBUS_TYPE_INT64:
-    case DBUS_TYPE_UINT64:
-      {
-        DBusOctets8 r;
-        r.u = *(const dbus_uint64_t *)value;
-        retval = marshal_8_octets (str, insert_at, byte_order, r);
-      }
-      break;
-#endif /* DBUS_HAVE_INT64 */
-    case DBUS_TYPE_DOUBLE:
-      {
-        DBusOctets8 r;
-        r.d = *(const double *)value;
-        retval = marshal_8_octets (str, insert_at, byte_order, r);
-      }
-      break;
-    default:
-      _dbus_assert_not_reached ("not a basic type");
-      retval = FALSE;
-      break;
+      _dbus_assert (t != DBUS_STRUCT_END_CHAR);
+      _dbus_assert (t != DBUS_DICT_ENTRY_END_CHAR);
+      return t;
     }
-  return retval;
 }
 
 /**
- * Marshals a basic type array
+ * Get the first type in the signature. The difference between this
+ * and just getting the first byte of the signature is that you won't
+ * get DBUS_STRUCT_BEGIN_CHAR, you'll get DBUS_TYPE_STRUCT
+ * instead.
+ *
+ * @param str string containing signature
+ * @param pos where the signature starts
+ * @returns the first type in the signature
+ */
+int
+_dbus_first_type_in_signature (const DBusString *str,
+                               int               pos)
+{
+  return map_type_char_to_type (_dbus_string_get_byte (str, pos));
+}
+
+/**
+ * Similar to #_dbus_first_type_in_signature, but operates
+ * on a C string buffer.
  *
- * @param str string to marshal to
- * @param insert_at where to insert the value
- * @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,
-                                int         insert_at,
-                               char        element_type,
-                               const void *value,
-                               int         len,
-                               int         byte_order)
+ * @param str a C string buffer
+ * @param pos where the signature starts
+ * @returns the first type in the signature
+ */
+int
+_dbus_first_type_in_signature_c_str (const char       *str,
+                                    int               pos)
 {
-  /* FIXME use the insert_at arg */
-  
-  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;
+  return map_type_char_to_type (str[pos]);
 }
 
 /** @} */
@@ -2656,126 +1500,305 @@ _dbus_marshal_basic_type_array (DBusString *str,
 #include "dbus-test.h"
 #include <stdio.h>
 
+/**
+ * Reads a block of fixed-length basic values, as an optimization
+ * vs. reading each one individually into a new buffer.
+ *
+ * This function returns the data in-place; it does not make a copy,
+ * and it does not swap the bytes.
+ *
+ * If you ask for #DBUS_TYPE_DOUBLE you will get a "const double*" back
+ * and the "value" argument should be a "const double**" and so on.
+ *
+ * @param str the string to read from
+ * @param pos position to read from
+ * @param element_type type of array elements
+ * @param value place to return the array
+ * @param n_elements number of array elements to read
+ * @param byte_order the byte order, used to read the array length
+ * @param new_pos #NULL or location to store a position after the elements
+ */
+void
+_dbus_marshal_read_fixed_multi  (const DBusString *str,
+                                 int               pos,
+                                 int               element_type,
+                                 void             *value,
+                                 int               n_elements,
+                                 int               byte_order,
+                                 int              *new_pos)
+{
+  int array_len;
+  int alignment;
+
+  _dbus_assert (dbus_type_is_fixed (element_type));
+  _dbus_assert (dbus_type_is_basic (element_type));
+
+#if 0
+  _dbus_verbose ("reading %d elements of %s\n",
+                 n_elements, _dbus_type_to_string (element_type));
+#endif
+  
+  alignment = _dbus_type_get_alignment (element_type);
+
+  pos = _DBUS_ALIGN_VALUE (pos, alignment);
+  
+  array_len = n_elements * alignment;
+
+  *(const DBusBasicValue**) value = (void*) _dbus_string_get_const_data_len (str, pos, array_len);
+  if (new_pos)
+    *new_pos = pos + array_len;
+}
+
+static void
+swap_test_array (void *array,
+                 int   len_bytes,
+                 int   byte_order,
+                 int   alignment)
+{
+  DBusString t;
+
+  if (alignment == 1)
+    return;
+  
+  _dbus_string_init_const_len (&t, array, len_bytes);
+  swap_array (&t, 0, len_bytes / alignment, byte_order, alignment);
+}
+
+#define MARSHAL_BASIC(typename, byte_order, literal)                    \
+  do {                                                                  \
+     v_##typename = literal;                                            \
+     if (!_dbus_marshal_write_basic (&str, pos, DBUS_TYPE_##typename,   \
+                                    &v_##typename,                      \
+                                    byte_order, NULL))                  \
+       _dbus_assert_not_reached ("no memory");                          \
+   } while (0)
+
+#define DEMARSHAL_BASIC(typename, byte_order)                                   \
+  do {                                                                          \
+    _dbus_marshal_read_basic (&str, pos, DBUS_TYPE_##typename, &v_##typename,   \
+                              byte_order, &pos);                                \
+  } while (0)
+
+#define DEMARSHAL_BASIC_AND_CHECK(typename, byte_order, literal)                        \
+  do {                                                                                  \
+    DEMARSHAL_BASIC (typename, byte_order);                                             \
+    if (literal != v_##typename)                                                        \
+      {                                                                                 \
+        _dbus_verbose_bytes_of_string (&str, dump_pos,                                  \
+                                     _dbus_string_get_length (&str) - dump_pos);        \
+        _dbus_assert_not_reached ("demarshaled wrong value");                           \
+      }                                                                                 \
+  } while (0)
+
+#define MARSHAL_TEST(typename, byte_order, literal)             \
+  do {                                                          \
+    MARSHAL_BASIC (typename, byte_order, literal);              \
+    dump_pos = pos;                                             \
+    DEMARSHAL_BASIC_AND_CHECK (typename, byte_order, literal);  \
+  } while (0)
+
+#define MARSHAL_TEST_STRCMP(typename, byte_order, literal)                              \
+  do {                                                                                  \
+    MARSHAL_BASIC (typename, byte_order, literal);                                      \
+    dump_pos = pos;                                                                     \
+    DEMARSHAL_BASIC (typename, byte_order);                                             \
+    if (strcmp (literal, v_##typename) != 0)                                            \
+      {                                                                                 \
+        _dbus_verbose_bytes_of_string (&str, dump_pos,                                  \
+                                       _dbus_string_get_length (&str) - dump_pos);      \
+        _dbus_warn ("literal '%s'\nvalue  '%s'\n", literal, v_##typename);              \
+        _dbus_assert_not_reached ("demarshaled wrong value");                           \
+      }                                                                                 \
+  } while (0)
+
+#define MARSHAL_FIXED_ARRAY(typename, byte_order, literal)                                      \
+  do {                                                                                          \
+     int next;                                                                                  \
+     v_UINT32 = sizeof(literal);                                                                \
+     if (!_dbus_marshal_write_basic (&str, pos, DBUS_TYPE_UINT32, &v_UINT32,                    \
+                                     byte_order, &next))                                        \
+       _dbus_assert_not_reached ("no memory");                                                  \
+     v_ARRAY_##typename = literal;                                                              \
+     if (!_dbus_marshal_write_fixed_multi (&str, next, DBUS_TYPE_##typename,                    \
+                                           &v_ARRAY_##typename, _DBUS_N_ELEMENTS(literal),      \
+                                           byte_order, NULL))                                   \
+       _dbus_assert_not_reached ("no memory");                                                  \
+   } while (0)
+
+#define DEMARSHAL_FIXED_ARRAY(typename, byte_order)                                             \
+  do {                                                                                          \
+    int next;                                                                                   \
+    alignment = _dbus_type_get_alignment (DBUS_TYPE_##typename);                                \
+    v_UINT32 = _dbus_marshal_read_uint32 (&str, dump_pos, byte_order, &next);                   \
+    _dbus_marshal_read_fixed_multi (&str, next, DBUS_TYPE_##typename, &v_ARRAY_##typename,      \
+                                    v_UINT32/alignment,                                         \
+                                    byte_order, NULL);                                          \
+    swap_test_array (v_ARRAY_##typename, v_UINT32,                                              \
+                     byte_order, alignment);                                                    \
+  } while (0)
+
+#define DEMARSHAL_FIXED_ARRAY_AND_CHECK(typename, byte_order, literal)                  \
+  do {                                                                                  \
+    DEMARSHAL_FIXED_ARRAY (typename, byte_order);                                       \
+    if (memcmp (literal, v_ARRAY_##typename, sizeof (literal) != 0))                    \
+      {                                                                                 \
+        _dbus_verbose ("MARSHALED DATA\n");                                             \
+        _dbus_verbose_bytes_of_string (&str, dump_pos,                                  \
+                                      _dbus_string_get_length (&str) - dump_pos);       \
+        _dbus_verbose ("LITERAL DATA\n");                                               \
+        _dbus_verbose_bytes ((char*)literal, sizeof (literal), 0);                      \
+        _dbus_verbose ("READ DATA\n");                                                  \
+        _dbus_verbose_bytes ((char*)v_ARRAY_##typename, sizeof (literal), 0);           \
+        _dbus_assert_not_reached ("demarshaled wrong fixed array value");               \
+      }                                                                                 \
+  } while (0)
+
+#define MARSHAL_TEST_FIXED_ARRAY(typename, byte_order, literal)         \
+  do {                                                                  \
+    MARSHAL_FIXED_ARRAY (typename, byte_order, literal);                \
+    dump_pos = pos;                                                     \
+    DEMARSHAL_FIXED_ARRAY_AND_CHECK (typename, byte_order, literal);    \
+  } while (0)
+
 dbus_bool_t
 _dbus_marshal_test (void)
 {
+  int alignment;
   DBusString str;
-  char *tmp1, *tmp2;
-  int pos = 0, len;
-  dbus_int32_t array1[3] = { 0x123, 0x456, 0x789 }, *array2;
+  int pos, dump_pos;
+  unsigned char array1[5] = { 3, 4, 0, 1, 9 };
+  dbus_int16_t array2[3] = { 124, 457, 780 };
+  dbus_int32_t array4[3] = { 123, 456, 789 };
 #ifdef DBUS_HAVE_INT64
-  dbus_int64_t array3[3] = { DBUS_INT64_CONSTANT (0x123ffffffff), 
-                             DBUS_INT64_CONSTANT (0x456ffffffff), 
-                             DBUS_INT64_CONSTANT (0x789ffffffff) }, *array4;
+  dbus_int64_t array8[3] = { DBUS_INT64_CONSTANT (0x123ffffffff),
+                             DBUS_INT64_CONSTANT (0x456ffffffff),
+                             DBUS_INT64_CONSTANT (0x789ffffffff) };
+  dbus_int64_t *v_ARRAY_INT64;
 #endif
-  char *s;
+  unsigned char *v_ARRAY_BYTE;
+  dbus_int16_t *v_ARRAY_INT16;
+  dbus_uint16_t *v_ARRAY_UINT16;
+  dbus_int32_t *v_ARRAY_INT32;
+  dbus_uint32_t *v_ARRAY_UINT32;
   DBusString t;
-  
+  double v_DOUBLE;
+  double t_DOUBLE;
+  dbus_int16_t v_INT16;
+  dbus_uint16_t v_UINT16;
+  dbus_int32_t v_INT32;
+  dbus_uint32_t v_UINT32;
+  dbus_int64_t v_INT64;
+  dbus_uint64_t v_UINT64;
+  unsigned char v_BYTE;
+  dbus_bool_t v_BOOLEAN;
+  const char *v_STRING;
+  const char *v_SIGNATURE;
+  const char *v_OBJECT_PATH;
+  int byte_order;
+
   if (!_dbus_string_init (&str))
     _dbus_assert_not_reached ("failed to init string");
 
+  pos = 0;
+
   /* Marshal doubles */
-  if (!_dbus_marshal_double (&str, DBUS_BIG_ENDIAN, 3.14))
-    _dbus_assert_not_reached ("could not marshal double value");
-  if (!_dbus_demarshal_double (&str, DBUS_BIG_ENDIAN, pos, &pos) == 3.14)
-    _dbus_assert_not_reached ("demarshal failed");
-
-  if (!_dbus_marshal_double (&str, DBUS_LITTLE_ENDIAN, 3.14))
-    _dbus_assert_not_reached ("could not marshal double value");
-  if (!_dbus_demarshal_double (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == 3.14)
-    _dbus_assert_not_reached ("demarshal failed");
+  MARSHAL_BASIC (DOUBLE, DBUS_BIG_ENDIAN, 3.14);
+  DEMARSHAL_BASIC (DOUBLE, DBUS_BIG_ENDIAN);
+  t_DOUBLE = 3.14;
+  if (!_DBUS_DOUBLES_BITWISE_EQUAL (t_DOUBLE, v_DOUBLE))
+    _dbus_assert_not_reached ("got wrong double value");
+
+  MARSHAL_BASIC (DOUBLE, DBUS_LITTLE_ENDIAN, 3.14);
+  DEMARSHAL_BASIC (DOUBLE, DBUS_LITTLE_ENDIAN);
+  t_DOUBLE = 3.14;
+  if (!_DBUS_DOUBLES_BITWISE_EQUAL (t_DOUBLE, v_DOUBLE))
+    _dbus_assert_not_reached ("got wrong double value");
+
+  /* Marshal signed 16 integers */
+  MARSHAL_TEST (INT16, DBUS_BIG_ENDIAN, -12345);
+  MARSHAL_TEST (INT16, DBUS_LITTLE_ENDIAN, -12345);
+
+  /* Marshal unsigned 16 integers */
+  MARSHAL_TEST (UINT16, DBUS_BIG_ENDIAN, 0x1234);
+  MARSHAL_TEST (UINT16, DBUS_LITTLE_ENDIAN, 0x1234);
   
   /* Marshal signed integers */
-  if (!_dbus_marshal_int32 (&str, DBUS_BIG_ENDIAN, -12345678))
-    _dbus_assert_not_reached ("could not marshal signed integer value");
-  if (!_dbus_demarshal_int32 (&str, DBUS_BIG_ENDIAN, pos, &pos) == -12345678)
-    _dbus_assert_not_reached ("demarshal failed");
-
-  if (!_dbus_marshal_int32 (&str, DBUS_LITTLE_ENDIAN, -12345678))
-    _dbus_assert_not_reached ("could not marshal signed integer value");
-  if (!_dbus_demarshal_int32 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == -12345678)
-    _dbus_assert_not_reached ("demarshal failed");
-  
+  MARSHAL_TEST (INT32, DBUS_BIG_ENDIAN, -12345678);
+  MARSHAL_TEST (INT32, DBUS_LITTLE_ENDIAN, -12345678);
+
   /* Marshal unsigned integers */
-  if (!_dbus_marshal_uint32 (&str, DBUS_BIG_ENDIAN, 0x12345678))
-    _dbus_assert_not_reached ("could not marshal signed integer value");
-  if (!_dbus_demarshal_uint32 (&str, DBUS_BIG_ENDIAN, pos, &pos) == 0x12345678)
-    _dbus_assert_not_reached ("demarshal failed");
-  
-  if (!_dbus_marshal_uint32 (&str, DBUS_LITTLE_ENDIAN, 0x12345678))
-    _dbus_assert_not_reached ("could not marshal signed integer value");
-  if (!_dbus_demarshal_uint32 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == 0x12345678)
-    _dbus_assert_not_reached ("demarshal failed");
+  MARSHAL_TEST (UINT32, DBUS_BIG_ENDIAN, 0x12345678);
+  MARSHAL_TEST (UINT32, DBUS_LITTLE_ENDIAN, 0x12345678);
 
 #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_TEST (INT64, DBUS_BIG_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7));
+  MARSHAL_TEST (INT64, DBUS_LITTLE_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7));
+
   /* 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");
+  MARSHAL_TEST (UINT64, DBUS_BIG_ENDIAN, DBUS_UINT64_CONSTANT (0x123456789abc7));
+  MARSHAL_TEST (UINT64, DBUS_LITTLE_ENDIAN, DBUS_UINT64_CONSTANT (0x123456789abc7));
 #endif /* DBUS_HAVE_INT64 */
-  
-  /* Marshal strings */
-  tmp1 = "This is the dbus test string";
-  if (!_dbus_marshal_string (&str, DBUS_BIG_ENDIAN, tmp1))
-    _dbus_assert_not_reached ("could not marshal string");
-  tmp2 = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, pos, &pos);
-  if (!strcmp (tmp1, tmp2) == 0)
-    _dbus_assert_not_reached ("demarshal failed");
-  dbus_free (tmp2);
-
-  tmp1 = "This is the dbus test string";
-  if (!_dbus_marshal_string (&str, DBUS_LITTLE_ENDIAN, tmp1))
-    _dbus_assert_not_reached ("could not marshal string");
-  tmp2 = _dbus_demarshal_string (&str, DBUS_LITTLE_ENDIAN, pos, &pos);
-  if (!strcmp (tmp1, tmp2) == 0)
-    _dbus_assert_not_reached ("demarshal failed");
-  dbus_free (tmp2);
-
-  /* Marshal signed integer arrays */
-  if (!_dbus_marshal_int32_array (&str, DBUS_BIG_ENDIAN, array1, 3))
-    _dbus_assert_not_reached ("could not marshal integer array");
-  if (!_dbus_demarshal_int32_array (&str, DBUS_BIG_ENDIAN, pos, &pos, &array2, &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 (array2);
 
+  /* Marshal byte */
+  MARSHAL_TEST (BYTE, DBUS_BIG_ENDIAN, 5);
+  MARSHAL_TEST (BYTE, DBUS_LITTLE_ENDIAN, 5);
+
+  /* Marshal all possible bools! */
+  MARSHAL_TEST (BOOLEAN, DBUS_BIG_ENDIAN, FALSE);
+  MARSHAL_TEST (BOOLEAN, DBUS_LITTLE_ENDIAN, FALSE);
+  MARSHAL_TEST (BOOLEAN, DBUS_BIG_ENDIAN, TRUE);
+  MARSHAL_TEST (BOOLEAN, DBUS_LITTLE_ENDIAN, TRUE);
+
+  /* Marshal strings */
+  MARSHAL_TEST_STRCMP (STRING, DBUS_BIG_ENDIAN, "");
+  MARSHAL_TEST_STRCMP (STRING, DBUS_LITTLE_ENDIAN, "");
+  MARSHAL_TEST_STRCMP (STRING, DBUS_BIG_ENDIAN, "This is the dbus test string");
+  MARSHAL_TEST_STRCMP (STRING, DBUS_LITTLE_ENDIAN, "This is the dbus test string");
+
+  /* object paths */
+  MARSHAL_TEST_STRCMP (OBJECT_PATH, DBUS_BIG_ENDIAN, "/a/b/c");
+  MARSHAL_TEST_STRCMP (OBJECT_PATH, DBUS_LITTLE_ENDIAN, "/a/b/c");
+
+  /* signatures */
+  MARSHAL_TEST_STRCMP (SIGNATURE, DBUS_BIG_ENDIAN, "");
+  MARSHAL_TEST_STRCMP (SIGNATURE, DBUS_LITTLE_ENDIAN, "");
+  MARSHAL_TEST_STRCMP (SIGNATURE, DBUS_BIG_ENDIAN, "a(ii)");
+  MARSHAL_TEST_STRCMP (SIGNATURE, DBUS_LITTLE_ENDIAN, "a(ii)");
+
+  /* Arrays */
+  MARSHAL_TEST_FIXED_ARRAY (INT16, DBUS_BIG_ENDIAN, array2);
+  MARSHAL_TEST_FIXED_ARRAY (INT16, DBUS_LITTLE_ENDIAN, array2);
+  MARSHAL_TEST_FIXED_ARRAY (UINT16, DBUS_BIG_ENDIAN, array2);
+  MARSHAL_TEST_FIXED_ARRAY (UINT16, DBUS_LITTLE_ENDIAN, array2);
+  
+  MARSHAL_TEST_FIXED_ARRAY (INT32, DBUS_BIG_ENDIAN, array4);
+  MARSHAL_TEST_FIXED_ARRAY (INT32, DBUS_LITTLE_ENDIAN, array4);
+  MARSHAL_TEST_FIXED_ARRAY (UINT32, DBUS_BIG_ENDIAN, array4);
+  MARSHAL_TEST_FIXED_ARRAY (UINT32, DBUS_LITTLE_ENDIAN, array4);
+
+  MARSHAL_TEST_FIXED_ARRAY (BYTE, DBUS_BIG_ENDIAN, array1);
+  MARSHAL_TEST_FIXED_ARRAY (BYTE, DBUS_LITTLE_ENDIAN, array1);
+  
 #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");
+  MARSHAL_TEST_FIXED_ARRAY (INT64, DBUS_BIG_ENDIAN, array8);
+  MARSHAL_TEST_FIXED_ARRAY (INT64, DBUS_LITTLE_ENDIAN, array8);
+#endif
 
-  if (len != 3)
-    _dbus_assert_not_reached ("Signed integer array lengths differ!\n");
-  dbus_free (array4);
+#if 0
+
+  /*
+   * FIXME restore the set/pack tests
+   */
 
+#ifdef DBUS_HAVE_INT64
   /* 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)));
@@ -2792,7 +1815,7 @@ _dbus_marshal_test (void)
   _dbus_pack_int64 (DBUS_INT64_CONSTANT (-0x123456789abc7),
                     DBUS_LITTLE_ENDIAN,
                     _dbus_string_get_data (&str));
-  
+
   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
                 _dbus_unpack_int64 (DBUS_LITTLE_ENDIAN,
                                     _dbus_string_get_const_data (&str)));
@@ -2809,7 +1832,7 @@ _dbus_marshal_test (void)
   /* 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)));
@@ -2826,7 +1849,7 @@ _dbus_marshal_test (void)
   _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)));
@@ -2839,8 +1862,7 @@ _dbus_marshal_test (void)
   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
                 _dbus_unpack_uint64 (DBUS_BIG_ENDIAN,
                                      _dbus_string_get_const_data (&str)));
-  
-#endif
+#endif /* DBUS_HAVE_INT64 */
 
   /* set/pack 32-bit integers */
   _dbus_string_set_length (&str, 4);
@@ -2848,7 +1870,7 @@ _dbus_marshal_test (void)
   /* signed little */
   _dbus_marshal_set_int32 (&str, DBUS_LITTLE_ENDIAN,
                            0, -0x123456);
-  
+
   _dbus_assert (-0x123456 ==
                 _dbus_unpack_int32 (DBUS_LITTLE_ENDIAN,
                                     _dbus_string_get_const_data (&str)));
@@ -2865,7 +1887,7 @@ _dbus_marshal_test (void)
   _dbus_pack_int32 (-0x123456,
                     DBUS_LITTLE_ENDIAN,
                     _dbus_string_get_data (&str));
-  
+
   _dbus_assert (-0x123456 ==
                 _dbus_unpack_int32 (DBUS_LITTLE_ENDIAN,
                                     _dbus_string_get_const_data (&str)));
@@ -2880,16 +1902,18 @@ _dbus_marshal_test (void)
                                     _dbus_string_get_const_data (&str)));
 
   /* unsigned little */
-  _dbus_marshal_set_uint32 (&str, DBUS_LITTLE_ENDIAN,
-                            0, 0x123456);
-  
+  _dbus_marshal_set_uint32 (&str,
+                            0, 0x123456,
+                            DBUS_LITTLE_ENDIAN);
+
   _dbus_assert (0x123456 ==
                 _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN,
                                      _dbus_string_get_const_data (&str)));
 
   /* unsigned big */
-  _dbus_marshal_set_uint32 (&str, DBUS_BIG_ENDIAN,
-                            0, 0x123456);
+  _dbus_marshal_set_uint32 (&str,
+                            0, 0x123456,
+                            DBUS_BIG_ENDIAN);
 
   _dbus_assert (0x123456 ==
                 _dbus_unpack_uint32 (DBUS_BIG_ENDIAN,
@@ -2899,7 +1923,7 @@ _dbus_marshal_test (void)
   _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)));
@@ -2913,67 +1937,53 @@ _dbus_marshal_test (void)
                 _dbus_unpack_uint32 (DBUS_BIG_ENDIAN,
                                      _dbus_string_get_const_data (&str)));
 
+#endif /* set/pack tests for integers */
 
-  /* Strings */
-  
-  _dbus_string_set_length (&str, 0);
+  /* Strings in-place set */
+  byte_order = DBUS_LITTLE_ENDIAN;
+  while (TRUE)
+    {
+      /* Init a string */
+      _dbus_string_set_length (&str, 0);
 
-  _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);
+      /* reset pos for the macros */
+      pos = 0;
 
-  _dbus_string_init_const (&t, "Hello world foo");
-  
-  _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 world foo") == 0);
-  dbus_free (s);
+      MARSHAL_TEST_STRCMP (STRING, byte_order, "Hello world");
 
-  _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);
+      /* Set it to something longer */
+      _dbus_string_init_const (&t, "Hello world foo");
 
-  /* Strings (big endian) */
-  
-  _dbus_string_set_length (&str, 0);
+      v_STRING = _dbus_string_get_const_data (&t);
+      _dbus_marshal_set_basic (&str, 0, DBUS_TYPE_STRING,
+                               &v_STRING, byte_order, NULL, NULL);
 
-  _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_marshal_read_basic (&str, 0, DBUS_TYPE_STRING,
+                                &v_STRING, byte_order,
+                                NULL);
+      _dbus_assert (strcmp (v_STRING, "Hello world foo") == 0);
 
-  _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);
+      /* Set it to something shorter */
+      _dbus_string_init_const (&t, "Hello");
 
-  _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);
-  
+      v_STRING = _dbus_string_get_const_data (&t);
+      _dbus_marshal_set_basic (&str, 0, DBUS_TYPE_STRING,
+                               &v_STRING, byte_order, NULL, NULL);
+      _dbus_marshal_read_basic (&str, 0, DBUS_TYPE_STRING,
+                                &v_STRING, byte_order,
+                                NULL);
+      _dbus_assert (strcmp (v_STRING, "Hello") == 0);
+
+      /* Do the other byte order */
+      if (byte_order == DBUS_LITTLE_ENDIAN)
+        byte_order = DBUS_BIG_ENDIAN;
+      else
+        break;
+    }
+
+  /* Clean up */
   _dbus_string_free (&str);
-      
+
   return TRUE;
 }