Revert merge of master (dbus-1.5) into dbus-1.4
[platform/upstream/dbus.git] / dbus / dbus-marshal-basic.c
index bad7d11..3cbc721 100644 (file)
@@ -1,4 +1,4 @@
-/* -*- 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
  *
  * 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"
 #include "dbus-marshal-basic.h"
+#include "dbus-signature.h"
 
 #include <string.h>
 
  */
 
 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)
@@ -88,33 +103,6 @@ _dbus_pack_uint32 (dbus_uint32_t   value,
   pack_4_octets (value, byte_order, 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);
-}
-
-static dbus_uint32_t
-unpack_4_octets (int                  byte_order,
-                 const unsigned char *data)
-{
-  _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
-
-  if (byte_order == DBUS_LITTLE_ENDIAN)
-    return DBUS_UINT32_FROM_LE (*(dbus_uint32_t*)data);
-  else
-    return DBUS_UINT32_FROM_BE (*(dbus_uint32_t*)data);
-}
-
 #ifndef DBUS_HAVE_INT64
 /* from ORBit */
 static void
@@ -150,6 +138,7 @@ swap_8_octets (DBusBasicValue    *value,
     }
 }
 
+#if 0
 static DBusBasicValue
 unpack_8_octets (int                  byte_order,
                  const unsigned char *data)
@@ -171,33 +160,64 @@ unpack_8_octets (int                  byte_order,
 
   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);
+
+  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 */
 
+#ifndef _dbus_unpack_uint32
 /**
- * Unpacks a 32 bit signed 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_int32_t
-_dbus_unpack_int32 (int                  byte_order,
-                    const unsigned char *data)
+dbus_uint32_t
+_dbus_unpack_uint32 (int                  byte_order,
+                     const unsigned char *data)
 {
-  return (dbus_int32_t) unpack_4_octets (byte_order, data);
+  _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
+
+  if (byte_order == DBUS_LITTLE_ENDIAN)
+    return DBUS_UINT32_FROM_LE (*(dbus_uint32_t*)data);
+  else
+    return DBUS_UINT32_FROM_BE (*(dbus_uint32_t*)data);
+}
+#endif /* _dbus_unpack_uint32 */
+
+static void
+set_2_octets (DBusString          *str,
+              int                  offset,
+              dbus_uint16_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, 2);
+
+  pack_2_octets (value, byte_order, data);
 }
 
 static void
@@ -213,7 +233,7 @@ set_4_octets (DBusString          *str,
 
   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
@@ -283,7 +303,9 @@ set_string (DBusString          *str,
 
   _dbus_string_init_const (&dstr, value);
 
-  old_len = _dbus_marshal_read_uint32 (str, pos, byte_order, NULL);
+  _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);
 
@@ -373,7 +395,6 @@ _dbus_marshal_set_basic (DBusString       *str,
   switch (type)
     {
     case DBUS_TYPE_BYTE:
-    case DBUS_TYPE_BOOLEAN:
       _dbus_string_set_byte (str, pos, vp->byt);
       if (old_end_pos)
         *old_end_pos = pos + 1;
@@ -381,8 +402,21 @@ _dbus_marshal_set_basic (DBusString       *str,
         *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:
+    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;
@@ -393,21 +427,23 @@ _dbus_marshal_set_basic (DBusString       *str,
     case DBUS_TYPE_INT64:
     case DBUS_TYPE_UINT64:
     case DBUS_TYPE_DOUBLE:
-      {
-        set_8_octets (str, pos, *vp, byte_order);
-        if (old_end_pos)
+      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;
-      }
+      if (new_end_pos)
+        *new_end_pos = pos + 8;
+      return TRUE;
       break;
     case DBUS_TYPE_STRING:
     case DBUS_TYPE_OBJECT_PATH:
+      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;
@@ -418,21 +454,6 @@ _dbus_marshal_set_basic (DBusString       *str,
     }
 }
 
-static dbus_uint32_t
-read_4_octets (const DBusString *str,
-               int               pos,
-               int               byte_order,
-               int              *new_pos)
-{
-  pos = _DBUS_ALIGN_VALUE (pos, 4);
-
-  if (new_pos)
-    *new_pos = pos + 4;
-
-  return unpack_4_octets (byte_order,
-                          _dbus_string_get_const_data (str) + pos);
-}
-
 /**
  * Convenience function to demarshal a 32 bit unsigned integer.
  *
@@ -448,7 +469,15 @@ _dbus_marshal_read_uint32  (const DBusString *str,
                             int               byte_order,
                             int              *new_pos)
 {
-  return read_4_octets (str, pos, byte_order, new_pos);
+  pos = _DBUS_ALIGN_VALUE (pos, 4);
+
+  if (new_pos)
+    *new_pos = pos + 4;
+
+  _dbus_assert (pos + 4 <= _dbus_string_get_length (str));
+  
+  return _dbus_unpack_uint32 (byte_order,
+                              _dbus_string_get_const_data (str) + pos);
 }
 
 /**
@@ -481,51 +510,75 @@ _dbus_marshal_read_basic (const DBusString      *str,
                           int                   *new_pos)
 {
   const char *str_data;
-  DBusBasicValue *vp;
 
-  _dbus_assert (_dbus_type_is_basic (type));
+  _dbus_assert (dbus_type_is_basic (type));
 
   str_data = _dbus_string_get_const_data (str);
-  vp = value;
 
+  /* Below we volatile types to avoid aliasing issues;
+   * see http://bugs.freedesktop.org/show_bug.cgi?id=20137
+   */
+  
   switch (type)
     {
     case DBUS_TYPE_BYTE:
-    case DBUS_TYPE_BOOLEAN:
-      vp->byt = _dbus_string_get_byte (str, pos);
+      {
+      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:
+    case DBUS_TYPE_BOOLEAN:
+    case DBUS_TYPE_UNIX_FD:
+      {
+      volatile dbus_uint32_t *vp = value;
       pos = _DBUS_ALIGN_VALUE (pos, 4);
-      vp->u32 = *(dbus_uint32_t *)(str_data + pos);
+      *vp = *(dbus_uint32_t *)(str_data + pos);
       if (byte_order != DBUS_COMPILER_BYTE_ORDER)
-       vp->u32 = DBUS_UINT32_SWAP_LE_BE (vp->u32);
+       *vp = DBUS_UINT32_SWAP_LE_BE (*vp);
       pos += 4;
+      }
       break;
     case DBUS_TYPE_INT64:
     case DBUS_TYPE_UINT64:
     case DBUS_TYPE_DOUBLE:
+      {
+      volatile dbus_uint64_t *vp = value;
       pos = _DBUS_ALIGN_VALUE (pos, 8);
 #ifdef DBUS_HAVE_INT64
       if (byte_order != DBUS_COMPILER_BYTE_ORDER)
-        vp->u64 = DBUS_UINT64_SWAP_LE_BE (*(dbus_uint64_t*)(str_data + pos));
+        *vp = DBUS_UINT64_SWAP_LE_BE (*(dbus_uint64_t*)(str_data + pos));
       else
-        vp->u64 = *(dbus_uint64_t*)(str_data + pos);
+        *vp = *(dbus_uint64_t*)(str_data + pos);
 #else
-      vp->u64 = *(DBus8ByteStruct*) (str_data + pos);
+      *vp = *(DBus8ByteStruct*) (str_data + pos);
       swap_8_octets (vp, byte_order);
 #endif
       pos += 8;
+      }
       break;
     case DBUS_TYPE_STRING:
     case DBUS_TYPE_OBJECT_PATH:
       {
         int len;
+        volatile char **vp = value;
 
         len = _dbus_marshal_read_uint32 (str, pos, byte_order, &pos);
 
-        vp->str = (char*) str_data + pos;
+        *vp = (char*) str_data + pos;
 
         pos += len + 1; /* length plus nul */
       }
@@ -533,18 +586,19 @@ _dbus_marshal_read_basic (const DBusString      *str,
     case DBUS_TYPE_SIGNATURE:
       {
         int len;
+        volatile char **vp = value;
 
         len = _dbus_string_get_byte (str, pos);
         pos += 1;
 
-        vp->str = (char*) str_data + pos;
+        *vp = (char*) str_data + pos;
 
         pos += len + 1; /* length plus nul */
       }
       break;
     default:
-      _dbus_warn ("type %s not a basic type\n",
-                  _dbus_type_to_string (type));
+      _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;
     }
@@ -554,6 +608,35 @@ _dbus_marshal_read_basic (const DBusString      *str,
 }
 
 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;
+
+  _dbus_assert (sizeof (value) == 2);
+
+  if (byte_order != DBUS_COMPILER_BYTE_ORDER)
+    value = DBUS_UINT16_SWAP_LE_BE (value);
+
+  orig_len = _dbus_string_get_length (str);
+
+  retval = _dbus_string_insert_2_aligned (str, insert_at,
+                                          (const unsigned char *)&value);
+
+  if (pos_after)
+    {
+      *pos_after = insert_at + (_dbus_string_get_length (str) - orig_len);
+      _dbus_assert (*pos_after <= _dbus_string_get_length (str));
+    }
+
+  return retval;
+}
+
+static dbus_bool_t
 marshal_4_octets (DBusString   *str,
                   int           insert_at,
                   dbus_uint32_t value,
@@ -631,22 +714,21 @@ marshal_len_followed_by_bytes (int                  marshal_as,
   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 */
 
-  /* FIXME this is probably broken for byte arrays because
-   * DBusString wants strings to be nul-terminated?
-   * Maybe I planned on this when writing init_const_len though
-   */
   _dbus_string_init_const_len (&value_str, value, value_len);
 
   pos = insert_at;
 
   if (marshal_as == MARSHAL_AS_SIGNATURE)
     {
+      _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;
 
@@ -663,7 +745,7 @@ marshal_len_followed_by_bytes (int                  marshal_as,
                               str, pos))
     goto oom;
 
-#if 1
+#if 0
   /* too expensive */
   _dbus_assert (_dbus_string_equal_substring (&value_str, 0, value_len,
                                               str, pos));
@@ -736,22 +818,31 @@ _dbus_marshal_write_basic (DBusString *str,
 {
   const DBusBasicValue *vp;
 
-  _dbus_assert (_dbus_type_is_basic (type));
+  _dbus_assert (dbus_type_is_basic (type));
 
   vp = value;
 
   switch (type)
     {
     case DBUS_TYPE_BYTE:
-    case DBUS_TYPE_BOOLEAN:
       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:
+      return marshal_4_octets (str, insert_at, vp->u32 != FALSE,
+                               byte_order, pos_after);
+      break;
     case DBUS_TYPE_INT32:
     case DBUS_TYPE_UINT32:
+    case DBUS_TYPE_UNIX_FD:
       return marshal_4_octets (str, insert_at, vp->u32,
                                byte_order, pos_after);
       break;
@@ -763,9 +854,11 @@ _dbus_marshal_write_basic (DBusString *str,
 
     case DBUS_TYPE_STRING:
     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_SIGNATURE:
+      _dbus_assert (vp->str != NULL);
       return marshal_signature (str, insert_at, vp->str, pos_after);
       break;
     default:
@@ -779,175 +872,213 @@ static dbus_bool_t
 marshal_1_octets_array (DBusString          *str,
                         int                  insert_at,
                         const unsigned char *value,
-                        int                  len,
+                        int                  n_elements,
                         int                  byte_order,
                         int                 *pos_after)
 {
-  return marshal_len_followed_by_bytes (MARSHAL_AS_BYTE_ARRAY,
-                                        str, insert_at, value, len,
-                                        byte_order, pos_after);
-}
+  int pos;
+  DBusString value_str;
 
-static dbus_bool_t
-marshal_4_octets_array (DBusString          *str,
-                        int                  insert_at,
-                        const dbus_uint32_t *value,
-                        int                  len,
-                        int                  byte_order)
-{
-  int old_string_len;
-  int array_start;
+  _dbus_string_init_const_len (&value_str, value, n_elements);
 
-  _dbus_assert_not_reached ("FIXME insert_at");
+  pos = insert_at;
 
-  old_string_len = _dbus_string_get_length (str);
+  if (!_dbus_string_copy_len (&value_str, 0, n_elements,
+                              str, pos))
+    return FALSE;
 
-  if (!marshal_4_octets (str, insert_at, len*4, byte_order, NULL))
-    goto error;
+  pos += n_elements;
 
-  array_start = _dbus_string_get_length (str);
+  if (pos_after)
+    *pos_after = pos;
 
-  if (!_dbus_string_append_len (str, (const unsigned char*) value,
-                                len * 4))
-    goto error;
+  return TRUE;
+}
 
-  if (byte_order != DBUS_COMPILER_BYTE_ORDER)
-    {
-      const unsigned char *d;
-      const unsigned char *end;
+/**
+ * Swaps the elements of an array to the opposite byte order
+ *
+ * @param data start of array
+ * @param n_elements number of elements
+ * @param alignment size of each element
+ */
+void
+_dbus_swap_array (unsigned char *data,
+                  int            n_elements,
+                  int            alignment)
+{
+  unsigned char *d;
+  unsigned char *end;
+
+  _dbus_assert (_DBUS_ALIGN_ADDRESS (data, alignment) == data);
 
-      d = _dbus_string_get_data (str) + array_start;
-      end = d + len * 4;
+  /* 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 (alignment == 8)
+    {
+      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;
+        }
+    }
+  else if (alignment == 4)
+    {
       while (d != end)
         {
           *((dbus_uint32_t*)d) = DBUS_UINT32_SWAP_LE_BE (*((dbus_uint32_t*)d));
           d += 4;
         }
     }
+  else
+    {
+      _dbus_assert (alignment == 2);
+      
+      while (d != end)
+        {
+          *((dbus_uint16_t*)d) = DBUS_UINT16_SWAP_LE_BE (*((dbus_uint16_t*)d));
+          d += 2;
+        }
+    }
+}
 
-  return TRUE;
-
- error:
-  /* Restore previous length */
-  _dbus_string_set_length (str, old_string_len);
+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);
 
-  return FALSE;
+  if (byte_order != DBUS_COMPILER_BYTE_ORDER)
+    {
+      /* 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);
+    }
 }
 
 static dbus_bool_t
-marshal_8_octets_array (DBusString           *str,
-                        int                   insert_at,
-                        const DBusBasicValue *value,
-                        int                   len,
-                        int                   byte_order)
+marshal_fixed_multi (DBusString           *str,
+                     int                   insert_at,
+                     const DBusBasicValue *value,
+                     int                   n_elements,
+                     int                   byte_order,
+                     int                   alignment,
+                     int                  *pos_after)
 {
   int old_string_len;
   int array_start;
+  DBusString t;
+  int len_in_bytes;
 
-  _dbus_assert_not_reached ("FIXME insert_at");
-
+  _dbus_assert (n_elements <= DBUS_MAXIMUM_ARRAY_LENGTH / alignment);
+  
   old_string_len = _dbus_string_get_length (str);
 
-  /*  The array length is the length in bytes of the array,
-   * *excluding* alignment padding.
-   */
-  if (!marshal_4_octets (str, insert_at, len*8, byte_order, NULL))
-    goto error;
-
-  array_start = _dbus_string_get_length (str);
-
+  len_in_bytes = n_elements * alignment;
+  array_start = insert_at;
+  
   /* 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))
+  if (!_dbus_string_insert_alignment (str, &array_start, alignment))
     goto error;
 
-  if (!_dbus_string_append_len (str, (const unsigned char*) value,
-                                len * 8))
+  _dbus_string_init_const_len (&t,
+                               (const unsigned char*) value,
+                               len_in_bytes);
+
+  if (!_dbus_string_copy (&t, 0,
+                          str, array_start))
     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_8_bytes ((DBusBasicValue*) d);
-#endif
-          d += 8;
-        }
-    }
+  swap_array (str, array_start, n_elements, byte_order, alignment);
 
+  if (pos_after)
+    *pos_after = array_start + len_in_bytes;
+  
   return TRUE;
 
  error:
-  /* Restore previous length */
-  _dbus_string_set_length (str, old_string_len);
+  _dbus_string_delete (str, insert_at,
+                       _dbus_string_get_length (str) - old_string_len);
 
   return FALSE;
 }
 
 /**
- * Marshals a basic type array
+ * 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.
+ *
+ * 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 pointer to value
- * @param len length of value data in 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_write_basic_array (DBusString *str,
+_dbus_marshal_write_fixed_multi (DBusString *str,
                                  int         insert_at,
                                  int         element_type,
                                  const void *value,
-                                 int         len,
+                                 int         n_elements,
                                  int         byte_order,
                                  int        *pos_after)
 {
-  /* FIXME use the insert_at arg and fill in 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
+  
   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 marshal_1_octets_array (str, insert_at, value, len, byte_order, pos_after);
+      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:
-      return marshal_4_octets_array (str, insert_at, value, len, byte_order);
+    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_8_octets_array (str, insert_at, value, len, byte_order);
-      break;
-
-    case DBUS_TYPE_STRING:
-    case DBUS_TYPE_OBJECT_PATH:
-      _dbus_assert_not_reached ("handle string arrays");
-      break;
-
-    case DBUS_TYPE_SIGNATURE:
-      _dbus_assert_not_reached ("handle signature");
+      return marshal_fixed_multi (str, insert_at, vp, n_elements, byte_order, 8, pos_after);
       break;
 
     default:
-      _dbus_assert_not_reached ("non basic type in array");
+      _dbus_assert_not_reached ("non fixed type in array write");
       break;
     }
 
@@ -970,14 +1101,23 @@ _dbus_marshal_skip_basic (const DBusString      *str,
                           int                    byte_order,
                           int                   *pos)
 {
+  _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
+                byte_order == DBUS_BIG_ENDIAN);
+  
   switch (type)
     {
     case DBUS_TYPE_BYTE:
-    case DBUS_TYPE_BOOLEAN:
       (*pos)++;
       break;
+    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:
+    case DBUS_TYPE_UNIX_FD:
       *pos = _DBUS_ALIGN_VALUE (*pos, 4);
       *pos += 4;
       break;
@@ -993,7 +1133,7 @@ _dbus_marshal_skip_basic (const DBusString      *str,
         int len;
 
         len = _dbus_marshal_read_uint32 (str, *pos, byte_order, pos);
-
+        
         *pos += len + 1; /* length plus nul */
       }
       break;
@@ -1057,12 +1197,16 @@ _dbus_type_get_alignment (int typecode)
   switch (typecode)
     {
     case DBUS_TYPE_BYTE:
-    case DBUS_TYPE_BOOLEAN:
     case DBUS_TYPE_VARIANT:
     case DBUS_TYPE_SIGNATURE:
       return 1;
+    case DBUS_TYPE_INT16:
+    case DBUS_TYPE_UINT16:
+      return 2;
+    case DBUS_TYPE_BOOLEAN:
     case DBUS_TYPE_INT32:
     case DBUS_TYPE_UINT32:
+    case DBUS_TYPE_UNIX_FD:
       /* this stuff is 4 since it starts with a length */
     case DBUS_TYPE_STRING:
     case DBUS_TYPE_OBJECT_PATH:
@@ -1075,8 +1219,10 @@ _dbus_type_get_alignment (int typecode)
        * 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;
 
     default:
@@ -1101,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:
@@ -1111,7 +1259,9 @@ _dbus_type_is_valid (int typecode)
     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:
@@ -1119,85 +1269,69 @@ _dbus_type_is_valid (int typecode)
     }
 }
 
-#define TYPE_IS_CONTAINER(typecode)             \
-    ((typecode) == DBUS_TYPE_STRUCT ||          \
-     (typecode) == DBUS_TYPE_VARIANT ||         \
-     (typecode) == DBUS_TYPE_ARRAY)
-
-/**
- * A "container type" can contain basic types, or nested
- * container types. #DBUS_TYPE_INVALID is not a container type.
- * This function will crash if passed a typecode that isn't
- * in dbus-protocol.h
- *
- * @returns #TRUE if type is a container
- */
-dbus_bool_t
-_dbus_type_is_container (int typecode)
-{
-  /* only reasonable (non-line-noise) typecodes are allowed */
-  _dbus_assert (_dbus_type_is_valid (typecode) || typecode == DBUS_TYPE_INVALID);
-  return TYPE_IS_CONTAINER (typecode);
-}
-
-/**
- * A "basic type" is a somewhat arbitrary concept, but the intent
- * is to include those types that are fully-specified by a single
- * typecode, with no additional type information or nested
- * values. So all numbers and strings are basic types and
- * structs, arrays, and variants are not basic types.
- * #DBUS_TYPE_INVALID is not a basic type.
- *
- * This function is defined to return #TRUE for exactly those
- * types that can be written with _dbus_marshal_basic_type()
- * and read with _dbus_marshal_read_basic().
- *
- * This function will crash if passed a typecode that isn't
- * in dbus-protocol.h
- *
- * @returns #TRUE if type is basic
- */
-dbus_bool_t
-_dbus_type_is_basic (int typecode)
-{
-  /* only reasonable (non-line-noise) typecodes are allowed */
-  _dbus_assert (_dbus_type_is_valid (typecode) || typecode == DBUS_TYPE_INVALID);
-
-  /* everything that isn't invalid or a container */
-  return !(typecode == DBUS_TYPE_INVALID || TYPE_IS_CONTAINER (typecode));
-}
-
 /**
- * Tells you whether values of this type can change length if you set
- * them to some other value. For this purpose, you assume that the
- * first byte of the old and new value would be in the same location,
- * so alignment padding is not a factor.
+ * Returns a string describing the given type.
  *
- * @returns #TRUE if the type can occupy different lengths
+ * @param typecode the type to describe
+ * @returns a constant string describing the type
  */
-dbus_bool_t
-_dbus_type_length_varies (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:
+      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:
+      return "uint32";
     case DBUS_TYPE_INT64:
+      return "int64";
     case DBUS_TYPE_UINT64:
+      return "uint64";      
     case DBUS_TYPE_DOUBLE:
-      return FALSE;
+      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 "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:
-      return TRUE;
+      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
@@ -1212,6 +1346,9 @@ _dbus_verbose_bytes (const unsigned char *data,
 
   _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)
@@ -1220,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 ("    ");
@@ -1257,6 +1394,10 @@ _dbus_verbose_bytes (const unsigned char *data,
           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]);
             }
@@ -1306,12 +1447,123 @@ _dbus_verbose_bytes_of_string (const DBusString    *str,
   _dbus_verbose_bytes (d, len, start);
 }
 
+static int
+map_type_char_to_type (int t)
+{
+  if (t == DBUS_STRUCT_BEGIN_CHAR)
+    return DBUS_TYPE_STRUCT;
+  else if (t == DBUS_DICT_ENTRY_BEGIN_CHAR)
+    return DBUS_TYPE_DICT_ENTRY;
+  else
+    {
+      _dbus_assert (t != DBUS_STRUCT_END_CHAR);
+      _dbus_assert (t != DBUS_DICT_ENTRY_END_CHAR);
+      return t;
+    }
+}
+
+/**
+ * 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 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)
+{
+  return map_type_char_to_type (str[pos]);
+}
+
 /** @} */
 
 #ifdef DBUS_BUILD_TESTS
 #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;                                            \
@@ -1324,7 +1576,7 @@ _dbus_verbose_bytes_of_string (const DBusString    *str,
 #define DEMARSHAL_BASIC(typename, byte_order)                                   \
   do {                                                                          \
     _dbus_marshal_read_basic (&str, pos, DBUS_TYPE_##typename, &v_##typename,   \
-                                byte_order, &pos);                              \
+                              byte_order, &pos);                                \
   } while (0)
 
 #define DEMARSHAL_BASIC_AND_CHECK(typename, byte_order, literal)                        \
@@ -1359,28 +1611,86 @@ _dbus_verbose_bytes_of_string (const DBusString    *str,
       }                                                                                 \
   } 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;
   int pos, dump_pos;
-#if 0
-  dbus_int32_t array1[3] = { 0x123, 0x456, 0x789 }, *array2;
+  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_t array8[3] = { DBUS_INT64_CONSTANT (0x123ffffffff),
                              DBUS_INT64_CONSTANT (0x456ffffffff),
-                             DBUS_INT64_CONSTANT (0x789ffffffff) }, *array4;
-#endif
+                             DBUS_INT64_CONSTANT (0x789ffffffff) };
+  dbus_int64_t *v_ARRAY_INT64;
 #endif
+  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;
-  unsigned char v_BOOLEAN;
+  dbus_bool_t v_BOOLEAN;
   const char *v_STRING;
   const char *v_SIGNATURE;
   const char *v_OBJECT_PATH;
@@ -1404,6 +1714,14 @@ _dbus_marshal_test (void)
   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 */
   MARSHAL_TEST (INT32, DBUS_BIG_ENDIAN, -12345678);
   MARSHAL_TEST (INT32, DBUS_LITTLE_ENDIAN, -12345678);
@@ -1448,6 +1766,25 @@ _dbus_marshal_test (void)
   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_TEST_FIXED_ARRAY (INT64, DBUS_BIG_ENDIAN, array8);
+  MARSHAL_TEST_FIXED_ARRAY (INT64, DBUS_LITTLE_ENDIAN, array8);
+#endif
+
 #if 0
 
   /*
@@ -1565,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,