back up some files I'm working on that don't do anything yet
authorHavoc Pennington <hp@redhat.com>
Sun, 19 Dec 2004 00:11:49 +0000 (00:11 +0000)
committerHavoc Pennington <hp@redhat.com>
Sun, 19 Dec 2004 00:11:49 +0000 (00:11 +0000)
dbus/dbus-marshal-basic.c [new file with mode: 0644]
dbus/dbus-marshal-basic.h [new file with mode: 0644]
dbus/dbus-marshal-recursive.c [new file with mode: 0644]
dbus/dbus-marshal-recursive.h [new file with mode: 0644]
dbus/dbus-protocol-new.h [new file with mode: 0644]

diff --git a/dbus/dbus-marshal-basic.c b/dbus/dbus-marshal-basic.c
new file mode 100644 (file)
index 0000000..7647727
--- /dev/null
@@ -0,0 +1,2945 @@
+/* -*- mode: C; c-file-style: "gnu" -*- */
+/* dbus-marshal-basic.c  Marshalling routines for basic (primitive) types
+ *
+ * Copyright (C) 2002 CodeFactory AB
+ * Copyright (C) 2003, 2004 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
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "dbus-marshal-basic.h"
+#include "dbus-internals.h"
+#define DBUS_CAN_USE_DBUS_STRING_PRIVATE 1
+#include "dbus-string-private.h"
+
+#include <string.h>
+
+/**
+ * @defgroup DBusMarshal marshaling and unmarshaling
+ * @ingroup  DBusInternals
+ * @brief functions to marshal/unmarshal data from the wire
+ *
+ * Types and functions related to converting primitive data types from
+ * wire format to native machine format, and vice versa.
+ *
+ * A signature is just a string with multiple types one after the other.
+ * for example a type is "i" or "(ii)", a signature is "i(ii)"
+ * where i is int and (ii) is struct { int; int; }
+ *
+ * @{
+ */
+
+static dbus_uint32_t
+unpack_4_octets (int                  byte_order,
+                 const unsigned char *data)
+{
+  _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
+  
+  if (byte_order == DBUS_LITTLE_ENDIAN)
+    return DBUS_UINT32_FROM_LE (*(dbus_uint32_t*)data);
+  else
+    return DBUS_UINT32_FROM_BE (*(dbus_uint32_t*)data);
+}
+
+#ifndef DBUS_HAVE_INT64
+/* from ORBit */
+static void
+swap_bytes (unsigned char *data,
+            unsigned int   len)
+{
+  unsigned char *p1 = data;
+  unsigned char *p2 = data + len - 1;
+
+  while (p1 < p2)
+    {
+      unsigned char tmp = *p1;
+      *p1 = *p2;
+      *p2 = tmp;
+
+      --p2;
+      ++p1;
+    }
+}
+#endif /* !DBUS_HAVE_INT64 */
+
+/**
+ * Union used to manipulate 8 bytes as if they
+ * were various types. 
+ */
+typedef union
+{
+#ifdef DBUS_HAVE_INT64
+  dbus_int64_t  s; /**< 64-bit integer */
+  dbus_uint64_t u; /**< 64-bit unsinged integer */
+#endif
+  double d;        /**< double */
+} DBusOctets8;
+
+static DBusOctets8
+unpack_8_octets (int                  byte_order,
+                 const unsigned char *data)
+{
+  DBusOctets8 r;
+  
+  _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 8) == data);
+  _dbus_assert (sizeof (r) == 8);
+  
+#ifdef DBUS_HAVE_INT64
+  if (byte_order == DBUS_LITTLE_ENDIAN)
+    r.u = DBUS_UINT64_FROM_LE (*(dbus_uint64_t*)data);
+  else
+    r.u = DBUS_UINT64_FROM_BE (*(dbus_uint64_t*)data);
+#else
+  r.d = *(double*)data;
+  if (byte_order != DBUS_COMPILER_BYTE_ORDER)
+    swap_bytes ((unsigned char*) &r, sizeof (r));
+#endif
+  
+  return r;
+}
+
+/**
+ * Unpacks a 32 bit unsigned integer from a data pointer
+ *
+ * @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,
+                     const unsigned char *data)
+{
+  return unpack_4_octets (byte_order, 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);
+}
+
+#ifdef DBUS_HAVE_INT64
+/**
+ * Unpacks a 64 bit unsigned integer from a data pointer
+ *
+ * @param byte_order The byte order to use
+ * @param data the data pointer
+ * @returns the integer
+ */
+dbus_uint64_t
+_dbus_unpack_uint64 (int                  byte_order,
+                     const unsigned char *data)
+{
+  DBusOctets8 r;
+  
+  r = unpack_8_octets (byte_order, data);
+
+  return r.u;
+}  
+
+/**
+ * Unpacks a 64 bit signed integer from a data pointer
+ *
+ * @param byte_order The byte order to use
+ * @param data the data pointer
+ * @returns the integer
+ */
+dbus_int64_t
+_dbus_unpack_int64 (int                  byte_order,
+                    const unsigned char *data)
+{
+  DBusOctets8 r;
+  
+  r = unpack_8_octets (byte_order, data);
+
+  return r.s;
+}
+
+#endif /* DBUS_HAVE_INT64 */
+
+static void
+pack_4_octets (dbus_uint32_t   value,
+               int             byte_order,
+               unsigned char  *data)
+{
+  _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
+  
+  if ((byte_order) == DBUS_LITTLE_ENDIAN)                  
+    *((dbus_uint32_t*)(data)) = DBUS_UINT32_TO_LE (value);       
+  else
+    *((dbus_uint32_t*)(data)) = DBUS_UINT32_TO_BE (value);
+}
+
+static void
+pack_8_octets (DBusOctets8     value,
+               int             byte_order,
+               unsigned char  *data)
+{
+  _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 8) == data);
+
+#ifdef DBUS_HAVE_INT64
+  if ((byte_order) == DBUS_LITTLE_ENDIAN)                  
+    *((dbus_uint64_t*)(data)) = DBUS_UINT64_TO_LE (value.u); 
+  else
+    *((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
+}
+
+/**
+ * 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);
+}
+
+/**
+ * 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);
+}
+
+#ifdef DBUS_HAVE_INT64
+/**
+ * Packs a 64 bit unsigned integer into a data pointer.
+ *
+ * @param value the value
+ * @param byte_order the byte order to use
+ * @param data the data pointer
+ */
+void
+_dbus_pack_uint64 (dbus_uint64_t   value,
+                   int             byte_order,
+                   unsigned char  *data)
+{
+  DBusOctets8 r;
+  r.u = value;
+  pack_8_octets (r, byte_order, data);
+}
+
+/**
+ * Packs a 64 bit signed integer into a data pointer.
+ *
+ * @param value the value
+ * @param byte_order the byte order to use
+ * @param data the data pointer
+ */
+void
+_dbus_pack_int64 (dbus_int64_t   value,
+                  int            byte_order,
+                  unsigned char *data)
+{
+  DBusOctets8 r;
+  r.s = value;
+  pack_8_octets (r, byte_order, data);
+}
+#endif /* DBUS_HAVE_INT64 */
+
+static void
+set_4_octets (DBusString          *str,
+              int                  byte_order,
+              int                  offset,
+              dbus_uint32_t        value)
+{
+  char *data;
+  
+  _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
+                byte_order == DBUS_BIG_ENDIAN);
+  
+  data = _dbus_string_get_data_len (str, offset, 4);
+
+  _dbus_pack_uint32 (value, byte_order, data);
+}
+
+static void
+set_8_octets (DBusString          *str,
+              int                  byte_order,
+              int                  offset,
+              DBusOctets8          value)
+{
+  char *data;
+  
+  _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
+                byte_order == DBUS_BIG_ENDIAN);
+  
+  data = _dbus_string_get_data_len (str, offset, 8);
+
+  pack_8_octets (value, byte_order, data);
+}
+
+/**
+ * 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 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)
+{
+  DBusOctets8 r;
+  r.u = value;
+  set_8_octets (str, byte_order, offset, r);
+}
+#endif /* DBUS_HAVE_INT64 */
+
+/**
+ * Sets the existing marshaled string at the given offset with
+ * a new marshaled string. The given offset must point to
+ * an existing string or the wrong length will be deleted
+ * and replaced with the new string.
+ *
+ * Note: no attempt is made by this function to re-align
+ * any data which has been already marshalled after this
+ * string. Use with caution.
+ *
+ * @param str the string to write the marshalled string to
+ * @param offset the byte offset where string should be written
+ * @param byte_order the byte order to use
+ * @param value the value
+ * @param len the length to use
+ * @returns #TRUE on success
+ * 
+ */
+dbus_bool_t
+_dbus_marshal_set_string (DBusString          *str,
+                          int                  byte_order,
+                          int                  offset,
+                          const DBusString    *value,
+                         int                  len)
+{
+  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);
+
+  if (!_dbus_string_replace_len (value, 0, len,
+                                 str, offset + 4, old_len))
+    return FALSE;
+
+  _dbus_marshal_set_uint32 (str, byte_order,
+                            offset, len);
+
+  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
+ *
+ * @param str the string to write the marshalled path to
+ * @param offset the byte offset where path should be written
+ * @param byte_order the byte order to use
+ * @param path the new path
+ * @param path_len number of elements in the path
+ */
+void
+_dbus_marshal_set_object_path (DBusString         *str,
+                               int                 byte_order,
+                               int                 offset,
+                               const char        **path,
+                               int                 path_len)
+{
+
+  /* FIXME */
+}
+
+static dbus_bool_t
+marshal_4_octets (DBusString   *str,
+                  int           byte_order,
+                  dbus_uint32_t value)
+{
+  _dbus_assert (sizeof (value) == 4);
+  
+  if (byte_order != DBUS_COMPILER_BYTE_ORDER)
+    value = DBUS_UINT32_SWAP_LE_BE (value);
+
+  return _dbus_string_append_4_aligned (str,
+                                        (const unsigned char *)&value);
+}
+
+static dbus_bool_t
+marshal_8_octets (DBusString *str,
+                  int         byte_order,
+                  DBusOctets8 value)
+{
+  _dbus_assert (sizeof (value) == 8);
+  
+  if (byte_order != DBUS_COMPILER_BYTE_ORDER)
+    pack_8_octets (value, byte_order, (unsigned char*) &value); /* pack into self, swapping as we go */
+
+  return _dbus_string_append_8_aligned (str,
+                                        (const unsigned char *)&value);
+}
+
+/**
+ * Marshals a double value.
+ *
+ * @param str the string to append the marshalled value to
+ * @param byte_order the byte order to use
+ * @param value the value
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+_dbus_marshal_double (DBusString *str,
+                     int         byte_order,
+                     double      value)
+{
+  DBusOctets8 r;
+  r.d = value;
+  return marshal_8_octets (str, byte_order, r);
+}
+
+/**
+ * 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, 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, byte_order, value);
+}
+
+
+#ifdef DBUS_HAVE_INT64
+/**
+ * Marshals a 64 bit signed integer value.
+ *
+ * @param str the string to append the marshalled value to
+ * @param byte_order the byte order to use
+ * @param value the value
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+_dbus_marshal_int64  (DBusString   *str,
+                     int           byte_order,
+                     dbus_int64_t  value)
+{
+  DBusOctets8 r;
+  r.s = value;
+  return marshal_8_octets (str, byte_order, r);
+}
+
+/**
+ * Marshals a 64 bit unsigned integer value.
+ *
+ * @param str the string to append the marshalled value to
+ * @param byte_order the byte order to use
+ * @param value the value
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+_dbus_marshal_uint64 (DBusString    *str,
+                     int            byte_order,
+                     dbus_uint64_t  value)
+{
+  DBusOctets8 r;
+  r.u = value;
+  return marshal_8_octets (str, byte_order, r);
+}
+
+#endif /* DBUS_HAVE_INT64 */
+
+/**
+ * Marshals a UTF-8 string
+ *
+ * @todo: If the string append fails we need to restore
+ * the old length. (also for other marshallers)
+ * 
+ * @param str the string to append the marshalled value to
+ * @param byte_order the byte order to use
+ * @param value the string
+ * @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);
+
+  if (!_dbus_marshal_uint32 (str, byte_order, len * 8))
+    goto error;
+
+  array_start = _dbus_string_get_length (str);
+  
+  if (!_dbus_string_append_len (str, (const unsigned char*) value,
+                                len * 8))
+    goto error;
+  
+  if (byte_order != DBUS_COMPILER_BYTE_ORDER)
+    {
+      const unsigned char *d;
+      const unsigned char *end;
+      
+      d = _dbus_string_get_data (str) + array_start;
+      end = d + len * 8;
+      while (d != end)
+        {
+#ifdef DBUS_HAVE_INT64
+          *((dbus_uint64_t*)d) = DBUS_UINT64_SWAP_LE_BE (*((dbus_uint64_t*)d));
+#else
+          swap_bytes ((unsigned char*) d, 8);
+#endif
+          d += 8;
+        }
+    }
+
+  return TRUE;
+  
+ error:
+  /* Restore previous length */
+  _dbus_string_set_length (str, old_string_len);
+  
+  return FALSE;  
+}
+
+/**
+ * Marshals a 32 bit signed integer array
+ *
+ * @param str the string to append the marshalled value to
+ * @param byte_order the byte order to use
+ * @param value the array
+ * @param len the length of the array
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+_dbus_marshal_int32_array (DBusString         *str,
+                          int                 byte_order,
+                          const dbus_int32_t *value,
+                          int                 len)
+{
+  return marshal_4_octets_array (str, byte_order,
+                                 (const dbus_uint32_t*) value,
+                                 len);
+}
+
+/**
+ * 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
+ */
+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);
+
+  switch (type)
+    {
+    case DBUS_TYPE_BYTE:
+    case DBUS_TYPE_BOOLEAN:
+      *(unsigned char *) value = _dbus_string_get_byte (str, *pos);
+      (*pos)++;
+      break;
+    case DBUS_TYPE_INT32:
+    case DBUS_TYPE_UINT32:
+      *pos = _DBUS_ALIGN_VALUE (*pos, 4);
+      *(dbus_uint32_t *) value = *(dbus_uint32_t *)(str_data + *pos);
+      if (byte_order != DBUS_COMPILER_BYTE_ORDER)
+       *(dbus_uint32_t *) value = DBUS_UINT32_SWAP_LE_BE (*(dbus_uint32_t *) value);
+      *pos += 4;
+      break;
+#ifdef DBUS_HAVE_INT64
+    case DBUS_TYPE_INT64:
+    case DBUS_TYPE_UINT64: 
+#endif /* DBUS_HAVE_INT64 */
+    case DBUS_TYPE_DOUBLE:
+      *pos = _DBUS_ALIGN_VALUE (*pos, 8);
+      memcpy (value, str_data + *pos, 8);
+      if (byte_order != DBUS_COMPILER_BYTE_ORDER)
+#ifdef DBUS_HAVE_INT64
+       *(dbus_uint64_t *) value = DBUS_UINT64_SWAP_LE_BE (*(dbus_uint64_t *) value);
+#else  
+       swap_bytes (value, 8);
+#endif
+      *pos += 8;
+      break;
+    default:
+      _dbus_assert_not_reached ("not a basic type");
+      break;
+    }
+}
+
+/**
+ * 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);
+  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);
+}
+
+/**
+ * Demarshals a 32 bit unsigned integer array.
+ *
+ * @param str the string containing the data
+ * @param byte_order the byte order
+ * @param pos the position in the string
+ * @param new_pos the new position of the string
+ * @param array the array
+ * @param array_len length of the demarshaled data
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+_dbus_demarshal_uint32_array (const DBusString  *str,
+                             int                byte_order,
+                             int                pos,
+                             int               *new_pos,
+                             dbus_uint32_t    **array,
+                             int               *array_len)
+{
+  return demarshal_4_octets_array (str, byte_order, pos, new_pos,
+                                   array, array_len);
+}
+
+#ifdef DBUS_HAVE_INT64
+
+/**
+ * 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);
+}
+
+/**
+ * Demarshals a 64 bit unsigned integer array.
+ *
+ * @param str the string containing the data
+ * @param byte_order the byte order
+ * @param pos the position in the string
+ * @param new_pos the new position of the string
+ * @param array the array
+ * @param array_len length of the demarshaled data
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+_dbus_demarshal_uint64_array (const DBusString  *str,
+                             int                byte_order,
+                             int                pos,
+                             int               *new_pos,
+                             dbus_uint64_t    **array,
+                             int               *array_len)
+{
+  return demarshal_8_octets_array (str, byte_order, pos, new_pos,
+                                   (DBusOctets8**) array, array_len);
+}
+
+#endif /* DBUS_HAVE_INT64 */
+
+/**
+ * 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);
+}
+
+
+/**
+ * Demarshals an array of basic types
+ *
+ * @param str the string containing the data
+ * @param element_type type of array elements to demarshal
+ * @param array pointer to pointer to array data
+ * @param array_len pointer to array length
+ * @param byte_order the byte order
+ * @param pos pointer to position in the string,
+ *            updated on return to new position
+ **/
+dbus_bool_t
+_dbus_demarshal_basic_type_array (const DBusString      *str,
+                                 int                    element_type,
+                                 void                 **array,
+                                 int                   *array_len,
+                                 int                    byte_order,
+                                 int                   *pos)
+{
+  switch (element_type)
+    {
+    case DBUS_TYPE_BOOLEAN:
+      /* FIXME: do we want to post-normalize these ? */
+    case DBUS_TYPE_BYTE:
+      return _dbus_demarshal_byte_array (str, byte_order, *pos, pos,
+                                        (unsigned char **)array, array_len);
+      break;
+    case DBUS_TYPE_INT32:
+    case DBUS_TYPE_UINT32:
+      return demarshal_4_octets_array (str, byte_order, *pos, pos,
+                                      (dbus_uint32_t **)array, array_len);
+      break;
+#ifdef DBUS_HAVE_INT64
+    case DBUS_TYPE_INT64:
+    case DBUS_TYPE_UINT64: 
+#endif /* DBUS_HAVE_INT64 */
+    case DBUS_TYPE_DOUBLE:
+      return demarshal_8_octets_array (str, byte_order, *pos, pos,
+                                      (DBusOctets8**) array, array_len);
+    default:
+      _dbus_assert_not_reached ("not a basic type");
+      break;
+    }
+  return FALSE;
+}
+
+/**
+ * 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;
+
+      if (new_pos)
+       *new_pos = pos;
+      
+      return TRUE;
+    }
+
+  len = 0;
+  allocated = 4;
+  end_pos = pos + bytes_len;
+  
+  retval = dbus_new (char *, allocated);
+
+  if (!retval)
+    return FALSE;
+
+  while (pos < end_pos)
+    {
+      retval[len] = _dbus_demarshal_string (str, byte_order, pos, &pos);
+      
+      if (retval[len] == NULL)
+       goto error;
+      
+      len += 1;
+
+      if (len >= allocated - 1) /* -1 for NULL termination */
+        {
+          char **newp;
+          newp = dbus_realloc (retval,
+                               sizeof (char*) * allocated * 2);
+          if (newp == NULL)
+            goto error;
+
+          allocated *= 2;
+          retval = newp;
+        }
+    }
+      
+  retval[len] = NULL;
+
+  if (new_pos)
+    *new_pos = pos;
+  
+  *array = retval;
+  *array_len = len;
+  
+  return TRUE;
+
+ error:
+  for (i = 0; i < len; i++)
+    dbus_free (retval[i]);
+  dbus_free (retval);
+
+  return FALSE;
+}
+
+/** Set to 1 to get a bunch of spew about disassembling the path string */
+#define VERBOSE_DECOMPOSE 0
+
+/**
+ * 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;
+
+  _dbus_assert (data != NULL);
+
+#if VERBOSE_DECOMPOSE
+  _dbus_verbose ("Decomposing path \"%s\"\n",
+                 data);
+#endif
+  
+  n_components = 0;
+  i = 0;
+  while (i < len)
+    {
+      if (data[i] == '/')
+        n_components += 1;
+      ++i;
+    }
+  
+  retval = dbus_new0 (char*, n_components + 1);
+
+  if (retval == NULL)
+    return FALSE;
+
+  comp = 0;
+  i = 0;
+  while (i < len)
+    {
+      if (data[i] == '/')
+        ++i;
+      j = i;
+
+      while (j < len && data[j] != '/')
+        ++j;
+
+      /* Now [i, j) is the path component */
+      _dbus_assert (i < j);
+      _dbus_assert (data[i] != '/');
+      _dbus_assert (j == len || data[j] == '/');
+
+#if VERBOSE_DECOMPOSE
+      _dbus_verbose ("  (component in [%d,%d))\n",
+                     i, j);
+#endif
+      
+      retval[comp] = _dbus_memdup (&data[i], j - i + 1);
+      if (retval[comp] == NULL)
+        {
+          dbus_free_string_array (retval);
+          return FALSE;
+        }
+      retval[comp][j-i] = '\0';
+#if VERBOSE_DECOMPOSE
+      _dbus_verbose ("  (component %d = \"%s\")\n",
+                     comp, retval[comp]);
+#endif
+
+      ++comp;
+      i = j;
+    }
+  _dbus_assert (i == len);
+  
+  *path = retval;
+  if (path_len)
+    *path_len = n_components;
+  
+  return TRUE;
+}
+
+/**
+ * Demarshals an object path.  A path of just "/" is
+ * represented as an empty vector of strings.
+ * 
+ * @param str the string containing the data
+ * @param byte_order the byte order
+ * @param pos the position in the string
+ * @param new_pos the new position of the string
+ * @param path address to store new object path
+ * @param path_len length of stored path
+ */
+dbus_bool_t
+_dbus_demarshal_object_path (const DBusString *str,
+                             int               byte_order,
+                             int               pos,
+                             int              *new_pos,
+                             char           ***path,
+                             int              *path_len)
+{
+  int len;
+  const char *data;
+  
+  len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
+  data = _dbus_string_get_const_data_len (str, pos, len + 1);
+
+  if (!_dbus_decompose_path (data, len, path, path_len))
+    return FALSE;
+
+  if (new_pos)
+    *new_pos = pos + len + 1;
+
+  return TRUE;
+}
+
+/** 
+ * Returns the position right after the end of an argument.  PERFORMS
+ * NO VALIDATION WHATSOEVER. The message must have been previously
+ * validated.
+ *
+ * @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
+ */
+dbus_bool_t
+_dbus_marshal_get_arg_end_pos (const DBusString *str,
+                               int               byte_order,
+                              int               type,
+                               int               pos,
+                               int              *end_pos)
+{
+  if (pos >= _dbus_string_get_length (str))
+    return FALSE;
+
+  switch (type)
+    {
+    case DBUS_TYPE_INVALID:
+      return FALSE;
+      break;
+
+    case DBUS_TYPE_NIL:
+      *end_pos = pos;
+      break;
+
+    case DBUS_TYPE_BYTE:
+      *end_pos = pos + 1;
+      break;
+      
+    case DBUS_TYPE_BOOLEAN:
+      *end_pos = pos + 1;
+      break;
+
+    case DBUS_TYPE_INT32:
+    case DBUS_TYPE_UINT32:
+      *end_pos = _DBUS_ALIGN_VALUE (pos, 4) + 4;
+      break;
+
+    case DBUS_TYPE_INT64:
+    case DBUS_TYPE_UINT64:
+    case DBUS_TYPE_DOUBLE:
+      
+      *end_pos = _DBUS_ALIGN_VALUE (pos, 8) + 8;
+      break;
+
+    case DBUS_TYPE_OBJECT_PATH:
+    case DBUS_TYPE_STRING:
+      {
+       int len;
+       
+       /* Demarshal the length */
+       len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
+
+       *end_pos = pos + len + 1;
+      }
+      break;
+
+    case DBUS_TYPE_CUSTOM:
+      {
+       int len;
+       
+       /* Demarshal the string length */
+       len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
+
+       pos += len + 1;
+       
+       /* Demarshal the data length */
+       len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
+
+       *end_pos = pos + len;
+      }
+      break;
+      
+    case DBUS_TYPE_ARRAY:
+      {
+       int len;
+
+       /* Demarshal the length  */
+       len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
+       
+       *end_pos = pos + len;
+      }
+      break;
+
+    case DBUS_TYPE_DICT:
+      {
+       int len;
+
+       /* Demarshal the length */
+       len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
+       
+       *end_pos = pos + len;
+      }
+      break;
+      
+    default:
+      _dbus_warn ("Unknown message arg type %d\n", type);
+      _dbus_assert_not_reached ("Unknown message argument type\n");
+      return FALSE;
+    }
+
+  if (*end_pos > _dbus_string_get_length (str))
+    return FALSE;
+  
+  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.
+ *
+ * @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.
+ */
+static int
+demarshal_and_validate_len (const DBusString *str,
+                            int               byte_order,
+                            int               pos,
+                            int              *new_pos)
+{
+  int align_4 = _DBUS_ALIGN_VALUE (pos, 4);
+  unsigned int len;
+
+  _dbus_assert (new_pos != NULL);
+  
+  if ((align_4 + 4) > _dbus_string_get_length (str))
+    {
+      _dbus_verbose ("not enough room in message for array length\n");
+      return -1;
+    }
+  
+  if (!_dbus_string_validate_nul (str, pos,
+                                  align_4 - pos))
+    {
+      _dbus_verbose ("array length alignment padding not initialized to nul at %d\n", pos);
+      return -1;
+    }
+
+  len = _dbus_demarshal_uint32 (str, byte_order, align_4, new_pos);
+
+  /* note that the len 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)
+    {
+      _dbus_verbose ("array length %u exceeds maximum of %u at pos %d\n",
+                     len, MAX_ARRAY_LENGTH, pos);
+      return -1;
+    }
+  else
+    return (int) len;
+}
+
+static dbus_bool_t
+validate_string (const DBusString *str,
+                 int               pos,
+                 int               len_without_nul,
+                 int              *end_pos)
+{
+  *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;
+    }
+  
+  if (_dbus_string_get_byte (str, pos + len_without_nul) != '\0')
+    {
+      _dbus_verbose ("string arg not nul-terminated\n");
+      return FALSE;
+    }
+  
+  if (!_dbus_string_validate_utf8 (str, pos, len_without_nul))
+    {
+      _dbus_verbose ("string is not valid UTF-8\n");
+      return FALSE;
+    }
+
+  return TRUE;
+}   
+
+/**
+ * Validates and returns a typecode at a specific position
+ * in the message
+ *
+ * @param str a string
+ * @param type the type of the argument
+ * @param pos the pos where the typecode starts
+ * @param end_pos pointer where the position right
+ * after the end position will follow
+ * @returns #TRUE if the type is valid.
+ */
+dbus_bool_t
+_dbus_marshal_validate_type   (const DBusString *str,
+                              int               pos,
+                              int              *type,
+                              int              *end_pos)
+{
+  const char *data;
+  
+  if (pos >= _dbus_string_get_length (str))
+    return FALSE;
+
+  data = _dbus_string_get_const_data_len (str, pos, 1);
+
+  if (_dbus_type_is_valid (*data))
+    {
+      *type = *data;
+      if (end_pos != NULL)
+       *end_pos = pos + 1;
+      return TRUE;
+    }
+
+  _dbus_verbose ("'%c' %d invalid type code\n", (int) *data, (int) *data);
+  
+  return FALSE;
+}
+
+/* Faster validator for array data that doesn't call
+ * validate_arg for each value
+ */
+static dbus_bool_t
+validate_array_data (const DBusString *str,
+                     int              byte_order,
+                     int               depth,
+                     int               type,
+                     int               array_type_pos,
+                     int               pos,
+                     int              *new_pos,
+                     int               end)
+{
+  switch (type)
+    {
+    case DBUS_TYPE_INVALID:
+      return FALSE;
+      break;
+
+    case DBUS_TYPE_NIL:
+      break;
+
+    case DBUS_TYPE_OBJECT_PATH:
+    case DBUS_TYPE_STRING:
+    case DBUS_TYPE_CUSTOM:
+    case DBUS_TYPE_ARRAY:
+    case DBUS_TYPE_DICT:
+      /* This clean recursion to validate_arg is what we
+       * are doing logically for all types, but we don't
+       * really want to call validate_arg for every byte
+       * in a byte array, so the primitive types are
+       * special-cased.
+       */
+      while (pos < end)
+        {
+          if (!_dbus_marshal_validate_arg (str, byte_order, depth,
+                                           type, array_type_pos, pos, &pos))
+            return FALSE;
+        }
+      break;
+      
+    case DBUS_TYPE_BYTE:
+      pos = end;
+      break;
+      
+    case DBUS_TYPE_BOOLEAN:
+      while (pos < end)
+        {
+          unsigned char c;
+          
+          c = _dbus_string_get_byte (str, pos);
+          
+          if (!(c == 0 || c == 1))
+            {
+              _dbus_verbose ("boolean value must be either 0 or 1, not %d\n", c);
+              return FALSE;
+            }
+          
+          ++pos;
+        }
+      break;
+      
+    case DBUS_TYPE_INT32:
+    case DBUS_TYPE_UINT32:
+      /* Call validate arg one time to check alignment padding
+       * at start of array
+       */
+      if (!_dbus_marshal_validate_arg (str, byte_order, depth,
+                                       type, array_type_pos, pos, &pos))
+        return FALSE;
+      pos = _DBUS_ALIGN_VALUE (end, 4);
+      break;
+
+    case DBUS_TYPE_INT64:
+    case DBUS_TYPE_UINT64:
+    case DBUS_TYPE_DOUBLE:
+      /* Call validate arg one time to check alignment padding
+       * at start of array
+       */
+      if (!_dbus_marshal_validate_arg (str, byte_order, depth,
+                                       type, array_type_pos, pos, &pos))
+        return FALSE;
+      pos = _DBUS_ALIGN_VALUE (end, 8);
+      break;
+      
+    default:
+      _dbus_verbose ("Unknown message arg type %d\n", type);
+      return FALSE;
+    }
+
+  *new_pos = pos;
+
+  return TRUE;
+}
+
+/** 
+ * Validates an argument 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"
+ *
+ * @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.
+ */
+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)
+{
+  if (pos > _dbus_string_get_length (str))
+    {
+      _dbus_verbose ("Validation went off the end of the message\n");
+      return FALSE;
+    }
+
+#define MAX_VALIDATION_DEPTH 32
+  
+  if (depth > MAX_VALIDATION_DEPTH)
+    {
+      _dbus_verbose ("Maximum recursion depth reached validating message\n");
+      return FALSE;
+    }
+  
+  switch (type)
+    {
+    case DBUS_TYPE_INVALID:
+      return FALSE;
+      break;
+
+    case DBUS_TYPE_NIL:
+      *end_pos = pos;
+      break;
+
+    case DBUS_TYPE_BYTE:
+      if (1 > _dbus_string_get_length (str) - pos)
+       {
+         _dbus_verbose ("no room for byte value\n");
+         return FALSE;
+       }
+       
+      *end_pos = pos + 1;
+      break;
+      
+    case DBUS_TYPE_BOOLEAN:
+      {
+       unsigned char c;
+
+        if (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_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_CUSTOM:
+      {
+       int len;
+
+       /* Demarshal the string length, which does NOT include
+         * nul termination
+         */
+       len = demarshal_and_validate_len (str, byte_order, pos, &pos);
+        if (len < 0)
+          return FALSE;
+
+        if (!validate_string (str, pos, len, &pos))
+          return FALSE;
+
+       /* Validate data */
+       len = demarshal_and_validate_len (str, byte_order, pos, &pos);
+        if (len < 0)
+          return FALSE;
+
+       *end_pos = pos + len;
+      }
+      break;
+      
+    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;
+                 }
+               
+               /* NIL values take up no space, so you couldn't iterate over an array of them.
+                * array of nil seems useless anyway; the useful thing might be array of
+                * (nil OR string) but we have no framework for that.
+                */
+               if (array_type == DBUS_TYPE_NIL)
+                 {
+                   _dbus_verbose ("array of NIL is not allowed\n");
+                   return FALSE;
+                 }
+             }
+           while (array_type == DBUS_TYPE_ARRAY);
+         }
+       else
+         array_type_pos++;
+
+       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;
+         }
+
+       *end_pos = pos;
+      }
+      break;
+
+    case DBUS_TYPE_DICT:
+      {
+       int dict_type;
+       int len;
+       int end;
+       
+       len = demarshal_and_validate_len (str, byte_order, pos, &pos);
+        if (len < 0)
+          return FALSE;
+
+        if (len > _dbus_string_get_length (str) - pos)
+          {
+            _dbus_verbose ("dict length outside length of the message\n");
+            return FALSE;
+          }
+       
+       end = pos + len;
+       
+       while (pos < end)
+         {
+           /* Validate name */
+           if (!_dbus_marshal_validate_arg (str, byte_order, depth + 1,
+                                            DBUS_TYPE_STRING, -1, pos, &pos))
+             return FALSE;
+           
+           if (!_dbus_marshal_validate_type (str, pos, &dict_type, &pos))
+             {
+               _dbus_verbose ("invalid dict entry type at offset %d\n", pos);
+               return FALSE;
+             }
+           
+           /* Validate element */
+           if (!_dbus_marshal_validate_arg (str, byte_order, depth + 1,
+                                            dict_type, -1, pos, &pos))
+             {
+               _dbus_verbose ("dict arg invalid at offset %d\n", pos);
+               return FALSE;
+             }
+         }
+       
+       if (pos > end)
+         {
+           _dbus_verbose ("dict contents exceed stated dict length\n");
+           return FALSE;
+         }
+        
+       *end_pos = pos;
+      }
+      break;
+      
+    default:
+      _dbus_verbose ("Unknown message arg type %d\n", type);
+      return FALSE;
+    }
+
+  if (*end_pos > _dbus_string_get_length (str))
+    return FALSE;
+  
+  return TRUE;
+}
+
+/**
+ * Return #TRUE if the typecode is a valid typecode
+ *
+ * @returns #TRUE if valid
+ */
+dbus_bool_t
+_dbus_type_is_valid (int typecode)
+{
+  switch (typecode)
+    {
+    case DBUS_TYPE_NIL:
+    case DBUS_TYPE_BYTE:
+    case DBUS_TYPE_BOOLEAN:
+    case DBUS_TYPE_INT32:
+    case DBUS_TYPE_UINT32:
+    case DBUS_TYPE_INT64:
+    case DBUS_TYPE_UINT64:
+    case DBUS_TYPE_DOUBLE:
+    case DBUS_TYPE_STRING:
+    case DBUS_TYPE_CUSTOM:
+    case DBUS_TYPE_ARRAY:
+    case DBUS_TYPE_DICT:
+    case DBUS_TYPE_OBJECT_PATH:
+      return TRUE;
+      
+    default:
+      return FALSE;
+    }
+}
+
+/**
+ * If in verbose mode, print a block of binary data.
+ *
+ * @todo right now it prints even if not in verbose mode
+ * 
+ * @param data the data
+ * @param len the length of the data
+ */
+void
+_dbus_verbose_bytes (const unsigned char *data,
+                     int                  len)
+{
+  int i;
+  const unsigned char *aligned;
+
+  _dbus_assert (len >= 0);
+  
+  /* Print blanks on first row if appropriate */
+  aligned = _DBUS_ALIGN_ADDRESS (data, 4);
+  if (aligned > data)
+    aligned -= 4;
+  _dbus_assert (aligned <= data);
+
+  if (aligned != data)
+    {
+      _dbus_verbose ("%4d\t%p: ", - (data - aligned), aligned); 
+      while (aligned != data)
+        {
+          _dbus_verbose ("    ");
+          ++aligned;
+        }
+    }
+
+  /* now print the bytes */
+  i = 0;
+  while (i < len)
+    {
+      if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
+        {
+          _dbus_verbose ("%4d\t%p: ",
+                   i, &data[i]);
+        }
+      
+      if (data[i] >= 32 &&
+          data[i] <= 126)
+        _dbus_verbose (" '%c' ", data[i]);
+      else
+        _dbus_verbose ("0x%s%x ",
+                 data[i] <= 0xf ? "0" : "", data[i]);
+
+      ++i;
+
+      if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
+        {
+          if (i > 3)
+            _dbus_verbose ("BE: %d LE: %d",
+                           _dbus_unpack_uint32 (DBUS_BIG_ENDIAN, &data[i-4]),
+                           _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN, &data[i-4]));
+
+          if (i > 7 && 
+              _DBUS_ALIGN_ADDRESS (&data[i], 8) == &data[i])
+            {
+              _dbus_verbose (" dbl: %g",
+                             *(double*)&data[i-8]);
+            }
+          
+          _dbus_verbose ("\n");
+        }
+    }
+
+  _dbus_verbose ("\n");
+}
+
+/**
+ * Dump the given part of the string to verbose log.
+ *
+ * @param str the string
+ * @param start the start of range to dump
+ * @param len length of range
+ */
+void
+_dbus_verbose_bytes_of_string (const DBusString    *str,
+                               int                  start,
+                               int                  len)
+{
+  const char *d;
+  int real_len;
+
+  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",
+                     start, len, real_len);
+      return;
+    }
+
+  if ((start + len) > real_len)
+    {
+      _dbus_verbose ("  [%d,%d) extends outside string of length %d\n",
+                     start, len, real_len);
+      len = real_len - start;
+    }
+  
+  d = _dbus_string_get_const_data_len (str, start, len);
+
+  _dbus_verbose_bytes (d, len);
+}
+
+/**
+ * Marshals a basic type
+ *
+ * @param str string to marshal to
+ * @param type type of value
+ * @param value pointer to value
+ * @param byte_order byte order
+ * @returns #TRUE on success
+ **/
+dbus_bool_t
+_dbus_marshal_basic_type (DBusString *str,
+                         char        type,
+                         void       *value,
+                         int         byte_order)
+{
+  dbus_bool_t retval;
+
+  switch (type)
+    {
+    case DBUS_TYPE_BYTE:
+    case DBUS_TYPE_BOOLEAN:
+      retval = _dbus_string_append_byte (str, *(unsigned char *)value);
+      break;
+    case DBUS_TYPE_INT32:
+    case DBUS_TYPE_UINT32:
+      return marshal_4_octets (str, byte_order, *(dbus_uint32_t *)value);
+      break;
+#ifdef DBUS_HAVE_INT64
+    case DBUS_TYPE_INT64:
+    case DBUS_TYPE_UINT64: 
+      retval = _dbus_marshal_uint64 (str, byte_order, *(dbus_uint64_t *)value);
+      break;
+#endif /* DBUS_HAVE_INT64 */
+    case DBUS_TYPE_DOUBLE:
+      retval = _dbus_marshal_double (str, byte_order, *(double *)value);
+      break;
+    default:
+      _dbus_assert_not_reached ("not a basic type");
+      retval = FALSE;
+      break;
+    }
+  return retval;
+}
+
+/**
+ * Marshals a basic type array
+ *
+ * @param str string to marshal to
+ * @param element_type type of array elements
+ * @param value pointer to value
+ * @param len length of value data in elements
+ * @param byte_order byte order
+ * @returns #TRUE on success
+ **/
+dbus_bool_t
+_dbus_marshal_basic_type_array (DBusString *str,
+                               char        element_type,
+                               const void *value,
+                               int         len,
+                               int         byte_order)
+{
+  switch (element_type)
+    {
+    case DBUS_TYPE_BOOLEAN:
+      /* FIXME: we canonicalize to 0 or 1 for the single boolean case 
+       * should we here too ? */
+    case DBUS_TYPE_BYTE:
+      return _dbus_marshal_byte_array (str, byte_order, value, len);
+      break;
+    case DBUS_TYPE_INT32:
+    case DBUS_TYPE_UINT32:
+      return marshal_4_octets_array (str, byte_order, value, len);
+      break;
+#ifdef DBUS_HAVE_INT64
+    case DBUS_TYPE_INT64:
+    case DBUS_TYPE_UINT64: 
+#endif /* DBUS_HAVE_INT64 */
+    case DBUS_TYPE_DOUBLE:
+      return marshal_8_octets_array (str, byte_order, value, len);
+      break;
+    default:
+      _dbus_assert_not_reached ("non basic type in array");
+      break;
+    }
+  return FALSE;
+}
+
+/** @} */
+
+#ifdef DBUS_BUILD_TESTS
+#include "dbus-test.h"
+#include <stdio.h>
+
+dbus_bool_t
+_dbus_marshal_test (void)
+{
+  DBusString str;
+  char *tmp1, *tmp2;
+  int pos = 0, len;
+  dbus_int32_t array1[3] = { 0x123, 0x456, 0x789 }, *array2;
+#ifdef DBUS_HAVE_INT64
+  dbus_int64_t array3[3] = { DBUS_INT64_CONSTANT (0x123ffffffff), 
+                             DBUS_INT64_CONSTANT (0x456ffffffff), 
+                             DBUS_INT64_CONSTANT (0x789ffffffff) }, *array4;
+#endif
+  char *s;
+  DBusString t;
+  
+  if (!_dbus_string_init (&str))
+    _dbus_assert_not_reached ("failed to init string");
+
+  /* Marshal doubles */
+  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 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 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");
+
+#ifdef DBUS_HAVE_INT64
+  /* Marshal signed integers */
+  if (!_dbus_marshal_int64 (&str, DBUS_BIG_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7)))
+    _dbus_assert_not_reached ("could not marshal signed integer value");
+  if (_dbus_demarshal_int64 (&str, DBUS_BIG_ENDIAN, pos, &pos) != DBUS_INT64_CONSTANT (-0x123456789abc7))
+    _dbus_assert_not_reached ("demarshal failed");
+
+  if (!_dbus_marshal_int64 (&str, DBUS_LITTLE_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7)))
+    _dbus_assert_not_reached ("could not marshal signed integer value");
+  if (_dbus_demarshal_int64 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) != DBUS_INT64_CONSTANT (-0x123456789abc7))
+    _dbus_assert_not_reached ("demarshal failed");
+  
+  /* Marshal unsigned integers */
+  if (!_dbus_marshal_uint64 (&str, DBUS_BIG_ENDIAN, DBUS_UINT64_CONSTANT (0x123456789abc7)))
+    _dbus_assert_not_reached ("could not marshal signed integer value");
+  if (!(_dbus_demarshal_uint64 (&str, DBUS_BIG_ENDIAN, pos, &pos) == DBUS_UINT64_CONSTANT (0x123456789abc7)))
+    _dbus_assert_not_reached ("demarshal failed");
+  
+  if (!_dbus_marshal_uint64 (&str, DBUS_LITTLE_ENDIAN, DBUS_UINT64_CONSTANT (0x123456789abc7)))
+    _dbus_assert_not_reached ("could not marshal signed integer value");
+  if (!(_dbus_demarshal_uint64 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == DBUS_UINT64_CONSTANT (0x123456789abc7)))
+    _dbus_assert_not_reached ("demarshal failed");
+#endif /* DBUS_HAVE_INT64 */
+  
+  /* Marshal strings */
+  tmp1 = "This is the dbus test string";
+  if (!_dbus_marshal_string (&str, DBUS_BIG_ENDIAN, tmp1))
+    _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);
+
+#ifdef DBUS_HAVE_INT64
+  /* Marshal 64-bit signed integer arrays */
+  if (!_dbus_marshal_int64_array (&str, DBUS_BIG_ENDIAN, array3, 3))
+    _dbus_assert_not_reached ("could not marshal integer array");
+  if (!_dbus_demarshal_int64_array (&str, DBUS_BIG_ENDIAN, pos, &pos, &array4, &len))
+    _dbus_assert_not_reached ("could not demarshal integer array");
+
+  if (len != 3)
+    _dbus_assert_not_reached ("Signed integer array lengths differ!\n");
+  dbus_free (array4);
+
+  /* set/pack 64-bit integers */
+  _dbus_string_set_length (&str, 8);
+
+  /* signed little */
+  _dbus_marshal_set_int64 (&str, DBUS_LITTLE_ENDIAN,
+                           0, DBUS_INT64_CONSTANT (-0x123456789abc7));
+  
+  _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
+                _dbus_unpack_int64 (DBUS_LITTLE_ENDIAN,
+                                    _dbus_string_get_const_data (&str)));
+
+  /* signed big */
+  _dbus_marshal_set_int64 (&str, DBUS_BIG_ENDIAN,
+                           0, DBUS_INT64_CONSTANT (-0x123456789abc7));
+
+  _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
+                _dbus_unpack_int64 (DBUS_BIG_ENDIAN,
+                                    _dbus_string_get_const_data (&str)));
+
+  /* signed little pack */
+  _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)));
+
+  /* signed big pack */
+  _dbus_pack_int64 (DBUS_INT64_CONSTANT (-0x123456789abc7),
+                    DBUS_BIG_ENDIAN,
+                    _dbus_string_get_data (&str));
+
+  _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
+                _dbus_unpack_int64 (DBUS_BIG_ENDIAN,
+                                    _dbus_string_get_const_data (&str)));
+
+  /* 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)));
+
+  /* unsigned big */
+  _dbus_marshal_set_uint64 (&str, DBUS_BIG_ENDIAN,
+                            0, DBUS_UINT64_CONSTANT (0x123456789abc7));
+
+  _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
+                _dbus_unpack_uint64 (DBUS_BIG_ENDIAN,
+                                     _dbus_string_get_const_data (&str)));
+
+  /* unsigned little pack */
+  _dbus_pack_uint64 (DBUS_UINT64_CONSTANT (0x123456789abc7),
+                     DBUS_LITTLE_ENDIAN,
+                     _dbus_string_get_data (&str));
+  
+  _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
+                _dbus_unpack_uint64 (DBUS_LITTLE_ENDIAN,
+                                     _dbus_string_get_const_data (&str)));
+
+  /* unsigned big pack */
+  _dbus_pack_uint64 (DBUS_UINT64_CONSTANT (0x123456789abc7),
+                     DBUS_BIG_ENDIAN,
+                     _dbus_string_get_data (&str));
+
+  _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
+                _dbus_unpack_uint64 (DBUS_BIG_ENDIAN,
+                                     _dbus_string_get_const_data (&str)));
+  
+#endif
+
+  /* set/pack 32-bit integers */
+  _dbus_string_set_length (&str, 4);
+
+  /* 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)));
+
+  /* signed big */
+  _dbus_marshal_set_int32 (&str, DBUS_BIG_ENDIAN,
+                           0, -0x123456);
+
+  _dbus_assert (-0x123456 ==
+                _dbus_unpack_int32 (DBUS_BIG_ENDIAN,
+                                    _dbus_string_get_const_data (&str)));
+
+  /* signed little pack */
+  _dbus_pack_int32 (-0x123456,
+                    DBUS_LITTLE_ENDIAN,
+                    _dbus_string_get_data (&str));
+  
+  _dbus_assert (-0x123456 ==
+                _dbus_unpack_int32 (DBUS_LITTLE_ENDIAN,
+                                    _dbus_string_get_const_data (&str)));
+
+  /* signed big pack */
+  _dbus_pack_int32 (-0x123456,
+                    DBUS_BIG_ENDIAN,
+                    _dbus_string_get_data (&str));
+
+  _dbus_assert (-0x123456 ==
+                _dbus_unpack_int32 (DBUS_BIG_ENDIAN,
+                                    _dbus_string_get_const_data (&str)));
+
+  /* unsigned little */
+  _dbus_marshal_set_uint32 (&str, DBUS_LITTLE_ENDIAN,
+                            0, 0x123456);
+  
+  _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_assert (0x123456 ==
+                _dbus_unpack_uint32 (DBUS_BIG_ENDIAN,
+                                     _dbus_string_get_const_data (&str)));
+
+  /* unsigned little pack */
+  _dbus_pack_uint32 (0x123456,
+                     DBUS_LITTLE_ENDIAN,
+                     _dbus_string_get_data (&str));
+  
+  _dbus_assert (0x123456 ==
+                _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN,
+                                     _dbus_string_get_const_data (&str)));
+
+  /* unsigned big pack */
+  _dbus_pack_uint32 (0x123456,
+                     DBUS_BIG_ENDIAN,
+                     _dbus_string_get_data (&str));
+
+  _dbus_assert (0x123456 ==
+                _dbus_unpack_uint32 (DBUS_BIG_ENDIAN,
+                                     _dbus_string_get_const_data (&str)));
+
+
+  /* Strings */
+  
+  _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);
+
+  _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);
+
+  _dbus_string_init_const (&t, "Hello");
+  
+  _dbus_marshal_set_string (&str, DBUS_LITTLE_ENDIAN, 0,
+                            &t, _dbus_string_get_length (&t));
+  
+  s = _dbus_demarshal_string (&str, DBUS_LITTLE_ENDIAN, 0, NULL);
+  _dbus_assert (strcmp (s, "Hello") == 0);
+  dbus_free (s);
+
+  /* Strings (big endian) */
+  
+  _dbus_string_set_length (&str, 0);
+
+  _dbus_marshal_string (&str, DBUS_BIG_ENDIAN,
+                        "Hello world");
+  
+  s = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, 0, NULL);
+  _dbus_assert (strcmp (s, "Hello world") == 0);
+  dbus_free (s);
+
+  _dbus_string_init_const (&t, "Hello world foo");
+  
+  _dbus_marshal_set_string (&str, DBUS_BIG_ENDIAN, 0,
+                            &t, _dbus_string_get_length (&t));
+  
+  s = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, 0, NULL);
+  _dbus_assert (strcmp (s, "Hello world foo") == 0);
+  dbus_free (s);
+
+  _dbus_string_init_const (&t, "Hello");
+  
+  _dbus_marshal_set_string (&str, DBUS_BIG_ENDIAN, 0,
+                            &t, _dbus_string_get_length (&t));
+  
+  s = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, 0, NULL);
+  _dbus_assert (strcmp (s, "Hello") == 0);
+  dbus_free (s);
+  
+  _dbus_string_free (&str);
+      
+  return TRUE;
+}
+
+#endif /* DBUS_BUILD_TESTS */
diff --git a/dbus/dbus-marshal-basic.h b/dbus/dbus-marshal-basic.h
new file mode 100644 (file)
index 0000000..25db7cc
--- /dev/null
@@ -0,0 +1,400 @@
+/* -*- mode: C; c-file-style: "gnu" -*- */
+/* dbus-marshal-basic.h  Marshalling routines for basic (primitive) types
+ *
+ * Copyright (C) 2002  CodeFactory AB
+ * Copyright (C) 2004  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
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef DBUS_MARSHAL_H
+#define DBUS_MARSHAL_H
+
+#include <config.h>
+#include <dbus/dbus-protocol.h>
+#include <dbus/dbus-types.h>
+#include <dbus/dbus-arch-deps.h>
+#include <dbus/dbus-string.h>
+
+#ifndef PACKAGE
+#error "config.h not included here"
+#endif
+
+/****************************************************** Remove later */
+#undef DBUS_TYPE_INVALID
+#undef DBUS_TYPE_BYTE
+#undef DBUS_TYPE_INT32
+#undef DBUS_TYPE_UINT32
+#undef DBUS_TYPE_INT64
+#undef DBUS_TYPE_UINT64
+#undef DBUS_TYPE_DOUBLE
+#undef DBUS_TYPE_STRING
+#undef DBUS_TYPE_OBJECT_PATH
+#undef DBUS_TYPE_ARRAY
+#undef DBUS_TYPE_DICT
+#undef DBUS_TYPE_VARIANT
+#undef DBUS_TYPE_STRUCT
+#undef DBUS_NUMBER_OF_TYPES
+
+/* Never a legitimate type */
+#define DBUS_TYPE_INVALID       ((int) '\0')
+
+/* Primitive types */
+#define DBUS_TYPE_BYTE          ((int) 'y')
+#define DBUS_TYPE_BOOLEAN       ((int) 'b')
+#define DBUS_TYPE_INT32         ((int) 'i')
+
+#define DBUS_TYPE_UINT32        ((int) 'u')
+#define DBUS_TYPE_INT64         ((int) 'x')
+#define DBUS_TYPE_UINT64        ((int) 't')
+
+#define DBUS_TYPE_DOUBLE        ((int) 'd')
+#define DBUS_TYPE_STRING        ((int) 's')
+#define DBUS_TYPE_OBJECT_PATH   ((int) 'o')
+
+/* Compound types */
+#define DBUS_TYPE_ARRAY         ((int) 'a')
+#define DBUS_TYPE_DICT          ((int) 'm')
+#define DBUS_TYPE_VARIANT       ((int) 'v')
+
+/* STRUCT is sort of special since its code can't appear in a type string,
+ * instead DBUS_STRUCT_BEGIN_CHAR has to appear
+ */
+#define DBUS_TYPE_STRUCT        ((int) 'r')
+
+/* Does not count INVALID */
+#define DBUS_NUMBER_OF_TYPES    (13)
+
+/* characters other than typecodes that appear in type signatures */
+#define DBUS_STRUCT_BEGIN_CHAR   ((int) '(')
+#define DBUS_STRUCT_END_CHAR     ((int) ')')
+#define DBUS_NAME_DELIMITER_CHAR ((int) '\'')
+/****************************************************** Remove later */
+
+#ifdef WORDS_BIGENDIAN
+#define DBUS_COMPILER_BYTE_ORDER DBUS_BIG_ENDIAN
+#else
+#define DBUS_COMPILER_BYTE_ORDER DBUS_LITTLE_ENDIAN
+#endif
+
+#define DBUS_UINT32_SWAP_LE_BE_CONSTANT(val)   ((dbus_uint32_t) (      \
+    (((dbus_uint32_t) (val) & (dbus_uint32_t) 0x000000ffU) << 24) |     \
+    (((dbus_uint32_t) (val) & (dbus_uint32_t) 0x0000ff00U) <<  8) |     \
+    (((dbus_uint32_t) (val) & (dbus_uint32_t) 0x00ff0000U) >>  8) |     \
+    (((dbus_uint32_t) (val) & (dbus_uint32_t) 0xff000000U) >> 24)))
+
+#ifdef DBUS_HAVE_INT64
+
+#define DBUS_UINT64_SWAP_LE_BE_CONSTANT(val)   ((dbus_uint64_t) (              \
+      (((dbus_uint64_t) (val) &                                                 \
+       (dbus_uint64_t) DBUS_UINT64_CONSTANT (0x00000000000000ff)) << 56) |    \
+      (((dbus_uint64_t) (val) &                                                 \
+       (dbus_uint64_t) DBUS_UINT64_CONSTANT (0x000000000000ff00)) << 40) |    \
+      (((dbus_uint64_t) (val) &                                                 \
+       (dbus_uint64_t) DBUS_UINT64_CONSTANT (0x0000000000ff0000)) << 24) |    \
+      (((dbus_uint64_t) (val) &                                                 \
+       (dbus_uint64_t) DBUS_UINT64_CONSTANT (0x00000000ff000000)) <<  8) |    \
+      (((dbus_uint64_t) (val) &                                                 \
+       (dbus_uint64_t) DBUS_UINT64_CONSTANT (0x000000ff00000000)) >>  8) |    \
+      (((dbus_uint64_t) (val) &                                                 \
+       (dbus_uint64_t) DBUS_UINT64_CONSTANT (0x0000ff0000000000)) >> 24) |    \
+      (((dbus_uint64_t) (val) &                                                 \
+       (dbus_uint64_t) DBUS_UINT64_CONSTANT (0x00ff000000000000)) >> 40) |    \
+      (((dbus_uint64_t) (val) &                                                 \
+       (dbus_uint64_t) DBUS_UINT64_CONSTANT (0xff00000000000000)) >> 56)))
+#endif /* DBUS_HAVE_INT64 */
+
+#define DBUS_UINT32_SWAP_LE_BE(val) (DBUS_UINT32_SWAP_LE_BE_CONSTANT (val))
+#define DBUS_INT32_SWAP_LE_BE(val)  ((dbus_int32_t)DBUS_UINT32_SWAP_LE_BE_CONSTANT (val))
+
+#ifdef DBUS_HAVE_INT64
+#define DBUS_UINT64_SWAP_LE_BE(val) (DBUS_UINT64_SWAP_LE_BE_CONSTANT (val))
+#define DBUS_INT64_SWAP_LE_BE(val)  ((dbus_int64_t)DBUS_UINT64_SWAP_LE_BE_CONSTANT (val))
+#endif /* DBUS_HAVE_INT64 */
+
+#ifdef WORDS_BIGENDIAN
+#define DBUS_INT32_TO_BE(val)  ((dbus_int32_t) (val))
+#define DBUS_UINT32_TO_BE(val) ((dbus_uint32_t) (val))
+#define DBUS_INT32_TO_LE(val)  (DBUS_INT32_SWAP_LE_BE (val))
+#define DBUS_UINT32_TO_LE(val) (DBUS_UINT32_SWAP_LE_BE (val))
+#  ifdef DBUS_HAVE_INT64
+#define DBUS_INT64_TO_BE(val)  ((dbus_int64_t) (val))
+#define DBUS_UINT64_TO_BE(val) ((dbus_uint64_t) (val))
+#define DBUS_INT64_TO_LE(val)  (DBUS_INT64_SWAP_LE_BE (val))
+#define DBUS_UINT64_TO_LE(val) (DBUS_UINT64_SWAP_LE_BE (val))
+#  endif /* DBUS_HAVE_INT64 */
+#else
+#define DBUS_INT32_TO_LE(val)  ((dbus_int32_t) (val))
+#define DBUS_UINT32_TO_LE(val) ((dbus_uint32_t) (val))
+#define DBUS_INT32_TO_BE(val)  ((dbus_int32_t) DBUS_UINT32_SWAP_LE_BE (val))
+#define DBUS_UINT32_TO_BE(val) (DBUS_UINT32_SWAP_LE_BE (val))
+#  ifdef DBUS_HAVE_INT64
+#define DBUS_INT64_TO_LE(val)  ((dbus_int64_t) (val))
+#define DBUS_UINT64_TO_LE(val) ((dbus_uint64_t) (val))
+#define DBUS_INT64_TO_BE(val)  ((dbus_int64_t) DBUS_UINT64_SWAP_LE_BE (val))
+#define DBUS_UINT64_TO_BE(val) (DBUS_UINT64_SWAP_LE_BE (val))
+#  endif /* DBUS_HAVE_INT64 */
+#endif
+
+/* The transformation is symmetric, so the FROM just maps to the TO. */
+#define DBUS_INT32_FROM_LE(val)         (DBUS_INT32_TO_LE (val))
+#define DBUS_UINT32_FROM_LE(val) (DBUS_UINT32_TO_LE (val))
+#define DBUS_INT32_FROM_BE(val)         (DBUS_INT32_TO_BE (val))
+#define DBUS_UINT32_FROM_BE(val) (DBUS_UINT32_TO_BE (val))
+#ifdef DBUS_HAVE_INT64
+#define DBUS_INT64_FROM_LE(val)         (DBUS_INT64_TO_LE (val))
+#define DBUS_UINT64_FROM_LE(val) (DBUS_UINT64_TO_LE (val))
+#define DBUS_INT64_FROM_BE(val)         (DBUS_INT64_TO_BE (val))
+#define DBUS_UINT64_FROM_BE(val) (DBUS_UINT64_TO_BE (val))
+#endif /* DBUS_HAVE_INT64 */
+
+void          _dbus_pack_int32    (dbus_int32_t         value,
+                                   int                  byte_order,
+                                   unsigned char       *data);
+dbus_int32_t  _dbus_unpack_int32  (int                  byte_order,
+                                   const unsigned char *data);
+void          _dbus_pack_uint32   (dbus_uint32_t        value,
+                                   int                  byte_order,
+                                   unsigned char       *data);
+dbus_uint32_t _dbus_unpack_uint32 (int                  byte_order,
+                                   const unsigned char *data);
+#ifdef DBUS_HAVE_INT64
+void          _dbus_pack_int64    (dbus_int64_t         value,
+                                   int                  byte_order,
+                                   unsigned char       *data);
+dbus_int64_t  _dbus_unpack_int64  (int                  byte_order,
+                                   const unsigned char *data);
+void          _dbus_pack_uint64   (dbus_uint64_t        value,
+                                   int                  byte_order,
+                                   unsigned char       *data);
+dbus_uint64_t _dbus_unpack_uint64 (int                  byte_order,
+                                   const unsigned char *data);
+#endif /* DBUS_HAVE_INT64 */
+
+void        _dbus_marshal_set_int32  (DBusString       *str,
+                                      int               byte_order,
+                                      int               offset,
+                                      dbus_int32_t      value);
+void        _dbus_marshal_set_uint32 (DBusString       *str,
+                                      int               byte_order,
+                                      int               offset,
+                                      dbus_uint32_t     value);
+#ifdef DBUS_HAVE_INT64
+void        _dbus_marshal_set_int64  (DBusString       *str,
+                                      int               byte_order,
+                                      int               offset,
+                                      dbus_int64_t      value);
+void        _dbus_marshal_set_uint64 (DBusString       *str,
+                                      int               byte_order,
+                                      int               offset,
+                                      dbus_uint64_t     value);
+#endif /* DBUS_HAVE_INT64 */
+
+dbus_bool_t _dbus_marshal_set_string      (DBusString         *str,
+                                           int                 byte_order,
+                                           int                 offset,
+                                           const DBusString   *value,
+                                           int                 len);
+void        _dbus_marshal_set_object_path (DBusString         *str,
+                                           int                 byte_order,
+                                           int                 offset,
+                                           const char        **path,
+                                           int                 path_len);
+
+dbus_bool_t   _dbus_marshal_int32          (DBusString            *str,
+                                           int                    byte_order,
+                                           dbus_int32_t           value);
+dbus_bool_t   _dbus_marshal_uint32         (DBusString            *str,
+                                           int                    byte_order,
+                                           dbus_uint32_t          value);
+#ifdef DBUS_HAVE_INT64
+dbus_bool_t   _dbus_marshal_int64          (DBusString            *str,
+                                           int                    byte_order,
+                                           dbus_int64_t           value);
+dbus_bool_t   _dbus_marshal_uint64         (DBusString            *str,
+                                           int                    byte_order,
+                                           dbus_uint64_t          value);
+#endif /* DBUS_HAVE_INT64 */
+dbus_bool_t   _dbus_marshal_double         (DBusString            *str,
+                                           int                    byte_order,
+                                           double                 value);
+dbus_bool_t   _dbus_marshal_string         (DBusString            *str,
+                                           int                    byte_order,
+                                           const char            *value);
+dbus_bool_t   _dbus_marshal_string_len     (DBusString            *str,
+                                           int                    byte_order,
+                                           const char            *value,
+                                            int                    len);
+dbus_bool_t   _dbus_marshal_basic_type     (DBusString            *str,
+                                           char                   type,
+                                           void                  *value,
+                                           int                    byte_order);
+dbus_bool_t   _dbus_marshal_byte_array     (DBusString            *str,
+                                           int                    byte_order,
+                                           const unsigned char   *value,
+                                           int                    len);
+dbus_bool_t   _dbus_marshal_int32_array    (DBusString            *str,
+                                           int                    byte_order,
+                                           const dbus_int32_t    *value,
+                                           int                    len);
+dbus_bool_t   _dbus_marshal_uint32_array   (DBusString            *str,
+                                           int                    byte_order,
+                                           const dbus_uint32_t   *value,
+                                           int                    len);
+#ifdef DBUS_HAVE_INT64
+dbus_bool_t   _dbus_marshal_int64_array    (DBusString            *str,
+                                           int                    byte_order,
+                                           const dbus_int64_t    *value,
+                                           int                    len);
+dbus_bool_t   _dbus_marshal_uint64_array   (DBusString            *str,
+                                           int                    byte_order,
+                                           const dbus_uint64_t   *value,
+                                           int                    len);
+#endif /* DBUS_HAVE_INT64 */
+dbus_bool_t   _dbus_marshal_double_array   (DBusString            *str,
+                                           int                    byte_order,
+                                           const double          *value,
+                                           int                    len);
+dbus_bool_t   _dbus_marshal_basic_type_array (DBusString            *str,
+                                             char                   element_type,
+                                             const void            *value,
+                                             int                    len,
+                                             int                    byte_order);
+
+dbus_bool_t   _dbus_marshal_string_array   (DBusString            *str,
+                                           int                    byte_order,
+                                           const char           **value,
+                                           int                    len);
+dbus_bool_t   _dbus_marshal_object_path    (DBusString            *str,
+                                           int                    byte_order,
+                                            const char           **path,
+                                            int                    path_len);
+
+double        _dbus_demarshal_double       (const DBusString      *str,
+                                           int                    byte_order,
+                                           int                    pos,
+                                           int                   *new_pos);
+dbus_int32_t  _dbus_demarshal_int32        (const DBusString      *str,
+                                           int                    byte_order,
+                                           int                    pos,
+                                           int                   *new_pos);
+dbus_uint32_t _dbus_demarshal_uint32       (const DBusString      *str,
+                                           int                    byte_order,
+                                           int                    pos,
+                                           int                   *new_pos);
+#ifdef DBUS_HAVE_INT64
+dbus_int64_t  _dbus_demarshal_int64        (const DBusString      *str,
+                                           int                    byte_order,
+                                           int                    pos,
+                                           int                   *new_pos);
+dbus_uint64_t _dbus_demarshal_uint64       (const DBusString      *str,
+                                           int                    byte_order,
+                                           int                    pos,
+                                           int                   *new_pos);
+#endif /* DBUS_HAVE_INT64 */
+void          _dbus_demarshal_basic_type   (const DBusString      *str,
+                                           int                    type,
+                                           void                  *value,
+                                           int                    byte_order,
+                                           int                   *pos);
+char *        _dbus_demarshal_string       (const DBusString      *str,
+                                           int                    byte_order,
+                                           int                    pos,
+                                           int                   *new_pos);
+dbus_bool_t   _dbus_demarshal_byte_array   (const DBusString      *str,
+                                           int                    byte_order,
+                                           int                    pos,
+                                           int                   *new_pos,
+                                           unsigned char        **array,
+                                           int                   *array_len);
+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);
+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);
+#ifdef DBUS_HAVE_INT64
+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);
+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);
+#endif /* DBUS_HAVE_INT64 */
+dbus_bool_t   _dbus_demarshal_double_array (const DBusString      *str,
+                                           int                    byte_order,
+                                           int                    pos,
+                                           int                   *new_pos,
+                                           double               **array,
+                                           int                   *array_len);
+dbus_bool_t   _dbus_demarshal_basic_type_array (const DBusString      *str,
+                                               int                    type,
+                                               void                 **array,
+                                               int                   *array_len,
+                                               int                    byte_order,
+                                               int                   *pos);
+
+dbus_bool_t   _dbus_demarshal_string_array (const DBusString      *str,
+                                           int                    byte_order,
+                                           int                    pos,
+                                           int                   *new_pos,
+                                           char                ***array,
+                                           int                   *array_len);
+dbus_bool_t   _dbus_decompose_path         (const char*            data,
+                                           int                    len,
+                                           char                ***path,
+                                           int                   *path_len);
+dbus_bool_t   _dbus_demarshal_object_path  (const DBusString      *str,
+                                           int                    byte_order,
+                                           int                    pos,
+                                            int                   *new_pos,
+                                            char                ***path,
+                                            int                   *path_len);
+
+dbus_bool_t _dbus_marshal_get_arg_end_pos (const DBusString *str,
+                                           int               byte_order,
+                                          int               type,
+                                           int               pos,
+                                           int              *end_pos);
+dbus_bool_t _dbus_marshal_validate_type   (const DBusString *str,
+                                           int               pos,
+                                          int              *type,
+                                           int              *end_pos);
+dbus_bool_t _dbus_marshal_validate_arg    (const DBusString *str,
+                                           int               depth,
+                                           int               byte_order,
+                                          int               type,
+                                          int               array_type_pos,
+                                           int               pos,
+                                           int              *end_pos);
+
+dbus_bool_t _dbus_type_is_valid           (int               typecode);
+
+#endif /* DBUS_MARSHAL_H */
diff --git a/dbus/dbus-marshal-recursive.c b/dbus/dbus-marshal-recursive.c
new file mode 100644 (file)
index 0000000..eb85a2c
--- /dev/null
@@ -0,0 +1,713 @@
+/* -*- mode: C; c-file-style: "gnu" -*- */
+/* dbus-marshal-recursive.c  Marshalling routines for recursive types
+ *
+ * Copyright (C) 2004 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
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "dbus-marshal-recursive.h"
+#include "dbus-internals.h"
+
+/**
+ * @addtogroup DBusMarshal
+ * @{
+ */
+
+void
+_dbus_type_reader_init (DBusTypeReader    *reader,
+                        int                byte_order,
+                        const DBusString  *type_str,
+                        int                type_pos,
+                        const DBusString  *value_str,
+                        int                value_pos)
+{
+     
+
+}
+
+int
+_dbus_type_reader_get_value_end (DBusTypeReader    *reader)
+{
+
+
+}
+
+int
+_dbus_type_reader_get_type_end (DBusTypeReader    *reader)
+{
+
+
+}
+
+int
+_dbus_type_reader_get_current_type (DBusTypeReader *reader)
+{
+
+
+}
+
+int
+_dbus_type_reader_get_array_type (DBusTypeReader    *reader)
+{
+
+
+}
+
+void
+_dbus_type_reader_read_basic (DBusTypeReader    *reader,
+                              void              *value)
+{
+
+
+}
+
+dbus_bool_t
+_dbus_type_reader_read_array (DBusTypeReader    *reader,
+                              int                type,
+                              void             **array,
+                              int               *array_len)
+{
+
+
+}
+
+void
+_dbus_type_reader_recurse (DBusTypeReader    *reader)
+{
+
+
+}
+
+void
+_dbus_type_reader_unrecurse (DBusTypeReader    *reader)
+{
+
+
+}
+
+dbus_bool_t
+_dbus_type_reader_next (DBusTypeReader    *reader)
+{
+
+
+
+}
+
+void
+_dbus_type_writer_init (DBusTypeWriter *writer,
+                        int             byte_order,
+                        DBusString     *type_str,
+                        int             type_pos,
+                        DBusString     *value_str,
+                        int             value_pos)
+{
+
+
+}
+
+dbus_bool_t
+_dbus_type_writer_write_basic (DBusTypeWriter *writer,
+                               int             type,
+                               const void     *value)
+{
+
+
+}
+
+dbus_bool_t
+_dbus_type_writer_write_array (DBusTypeWriter *writer,
+                               int             type,
+                               const void     *array,
+                               int             array_len)
+{
+
+
+}
+
+dbus_bool_t
+_dbus_type_writer_recurse (DBusTypeWriter *writer,
+                           int             container_type)
+{
+
+
+}
+
+dbus_bool_t
+_dbus_type_writer_unrecurse (DBusTypeWriter *writer)
+{
+
+
+}
+
+/** @} */ /* end of DBusMarshal group */
+
+#ifdef DBUS_BUILD_TESTS
+#include "dbus-test.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+typedef struct
+{
+  DBusString signature;
+  DBusString body;
+} DataBlock;
+
+typedef struct
+{
+  int saved_sig_len;
+  int saved_body_len;
+} DataBlockState;
+
+static dbus_bool_t
+data_block_init (DataBlock *block)
+{
+  if (!_dbus_string_init (&block->signature))
+    return FALSE;
+
+  if (!_dbus_string_init (&block->body))
+    {
+      _dbus_string_free (&block->signature);
+      return FALSE;
+    }
+  
+  return TRUE;
+}
+
+static void
+data_block_free (DataBlock *block)
+{
+  _dbus_string_free (&block->signature);
+  _dbus_string_free (&block->body);
+}
+
+static void
+data_block_save (DataBlock      *block,
+                 DataBlockState *state)
+{
+  state->saved_sig_len = _dbus_string_get_length (&block->signature);
+  state->saved_body_len = _dbus_string_get_length (&block->body);
+}
+
+static void
+data_block_restore (DataBlock      *block,
+                    DataBlockState *state)
+{
+  /* These set_length should be shortening things so should always work */
+  
+  if (!_dbus_string_set_length (&block->signature,
+                                state->saved_sig_len))
+    _dbus_assert_not_reached ("could not restore signature length");
+  
+  if (!_dbus_string_set_length (&block->body,
+                                state->saved_body_len))
+    _dbus_assert_not_reached ("could not restore body length");
+}
+
+static void
+data_block_init_reader_writer (DataBlock      *block,
+                               int             byte_order,
+                               DBusTypeReader *reader,
+                               DBusTypeWriter *writer)
+{
+  _dbus_type_reader_init (reader,
+                          byte_order,
+                          &block->signature,
+                          _dbus_string_get_length (&block->signature),
+                          &block->body,
+                          _dbus_string_get_length (&block->body));
+  
+  _dbus_type_writer_init (writer,
+                          byte_order,
+                          &block->signature,
+                          _dbus_string_get_length (&block->signature),
+                          &block->body,
+                          _dbus_string_get_length (&block->body));
+}
+
+#define SAMPLE_INT32           12345678
+#define SAMPLE_INT32_ALTERNATE 53781429
+static dbus_bool_t
+write_int32 (DataBlock      *block,
+             DBusTypeWriter *writer)
+{
+  dbus_int32_t v = SAMPLE_INT32;
+
+  return _dbus_type_writer_write_basic (writer,
+                                        DBUS_TYPE_INT32,
+                                        &v);
+}
+
+static void
+check_expected_type (DBusTypeReader *reader,
+                     int             expected)
+{
+  int t;
+
+  t = _dbus_type_reader_get_current_type (reader);
+  
+  if (t != expected)
+    {
+      _dbus_warn ("Read type %s while expecting %s\n",
+                  _dbus_type_to_string (t),
+                  _dbus_type_to_string (expected));
+      exit (1);
+    }
+}
+
+static dbus_bool_t
+read_int32 (DataBlock      *block,
+            DBusTypeReader *reader)
+{
+  dbus_int32_t v;
+
+  check_expected_type (reader, DBUS_TYPE_INT32);
+  
+  _dbus_type_reader_read_basic (reader,
+                                (dbus_int32_t*) &v);
+
+  _dbus_assert (v == SAMPLE_INT32);
+
+  return TRUE;
+}
+
+static dbus_bool_t
+write_struct_with_int32s (DataBlock      *block,
+                          DBusTypeWriter *writer)
+{
+  dbus_int32_t v;
+  DataBlockState saved;
+
+  data_block_save (block, &saved);
+  
+  if (!_dbus_type_writer_recurse (writer,
+                                  DBUS_TYPE_STRUCT))
+    return FALSE;
+
+  v = SAMPLE_INT32;
+  if (!_dbus_type_writer_write_basic (writer,
+                                      DBUS_TYPE_INT32,
+                                      &v))
+    {
+      data_block_restore (block, &saved);
+      return FALSE;
+    }
+
+  v = SAMPLE_INT32_ALTERNATE;
+  if (!_dbus_type_writer_write_basic (writer,
+                                      DBUS_TYPE_INT32,
+                                      &v))
+    {
+      data_block_restore (block, &saved);
+      return FALSE;
+    }
+
+  if (!_dbus_type_writer_unrecurse (writer))
+    {
+      data_block_restore (block, &saved);
+      return FALSE;
+    }
+  
+  return TRUE;
+}
+
+static dbus_bool_t
+read_struct_with_int32s (DataBlock      *block,
+                         DBusTypeReader *reader)
+{
+  dbus_int32_t v;
+
+  check_expected_type (reader, DBUS_TYPE_STRUCT);
+  
+  _dbus_type_reader_recurse (reader);
+
+  check_expected_type (reader, DBUS_TYPE_INT32);
+  
+  _dbus_type_reader_read_basic (reader,
+                                (dbus_int32_t*) &v);
+
+  _dbus_assert (v == SAMPLE_INT32);
+
+  _dbus_type_reader_next (reader);
+  check_expected_type (reader, DBUS_TYPE_INT32);
+  
+  _dbus_type_reader_read_basic (reader,
+                                (dbus_int32_t*) &v);
+
+  _dbus_assert (v == SAMPLE_INT32_ALTERNATE);
+
+  _dbus_type_reader_unrecurse (reader);
+  
+  return TRUE;
+}
+
+static dbus_bool_t
+write_struct_of_structs (DataBlock      *block,
+                         DBusTypeWriter *writer)
+{
+  DataBlockState saved;
+
+  data_block_save (block, &saved);
+  
+  if (!_dbus_type_writer_recurse (writer,
+                                  DBUS_TYPE_STRUCT))
+    return FALSE;
+
+  if (!write_struct_with_int32s (block, writer))
+    {
+      data_block_restore (block, &saved);
+      return FALSE;
+    }
+  if (!write_struct_with_int32s (block, writer))
+    {
+      data_block_restore (block, &saved);
+      return FALSE;
+    }
+  if (!write_struct_with_int32s (block, writer))
+    {
+      data_block_restore (block, &saved);
+      return FALSE;
+    }
+
+  if (!_dbus_type_writer_unrecurse (writer))
+    {
+      data_block_restore (block, &saved);
+      return FALSE;
+    }
+  
+  return TRUE;
+}
+
+static dbus_bool_t
+read_struct_of_structs (DataBlock      *block,
+                        DBusTypeReader *reader)
+{
+  check_expected_type (reader, DBUS_TYPE_STRUCT);
+  
+  _dbus_type_reader_recurse (reader);
+
+  if (!read_struct_with_int32s (block, reader))
+    return FALSE;
+  _dbus_type_reader_next (reader);
+  if (!read_struct_with_int32s (block, reader))
+    return FALSE;
+  _dbus_type_reader_next (reader);
+  if (!read_struct_with_int32s (block, reader))
+    return FALSE;
+
+  _dbus_type_reader_unrecurse (reader);
+  
+  return TRUE;
+}
+
+static dbus_bool_t
+write_struct_of_structs_of_structs (DataBlock      *block,
+                                    DBusTypeWriter *writer)
+{
+  DataBlockState saved;
+
+  data_block_save (block, &saved);
+  
+  if (!_dbus_type_writer_recurse (writer,
+                                  DBUS_TYPE_STRUCT))
+    return FALSE;
+
+  if (!write_struct_of_structs (block, writer))
+    {
+      data_block_restore (block, &saved);
+      return FALSE;
+    }
+  if (!write_struct_of_structs (block, writer))
+    {
+      data_block_restore (block, &saved);
+      return FALSE;
+    }
+
+  if (!_dbus_type_writer_unrecurse (writer))
+    {
+      data_block_restore (block, &saved);
+      return FALSE;
+    }
+  
+  return TRUE;
+}
+
+static dbus_bool_t
+read_struct_of_structs_of_structs (DataBlock      *block,
+                                   DBusTypeReader *reader)
+{
+  check_expected_type (reader, DBUS_TYPE_STRUCT);
+  
+  _dbus_type_reader_recurse (reader);
+
+  if (!read_struct_of_structs (block, reader))
+    return FALSE;
+  _dbus_type_reader_next (reader);
+  if (!read_struct_of_structs (block, reader))
+    return FALSE;
+
+  _dbus_type_reader_unrecurse (reader);
+  
+  return TRUE;
+}
+
+typedef enum {
+  ITEM_INVALID = -1,
+  ITEM_INT32 = 0,
+  ITEM_STRUCT_WITH_INT32S,
+  ITEM_STRUCT_OF_STRUCTS,
+  ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS,
+  ITEM_LAST
+} WhichItem;
+
+
+typedef dbus_bool_t (* WriteItemFunc) (DataBlock      *block,
+                                       DBusTypeWriter *writer);
+typedef dbus_bool_t (* ReadItemFunc)  (DataBlock      *block,
+                                       DBusTypeReader *reader);
+
+typedef struct
+{
+  WhichItem which;
+  WriteItemFunc write_item_func;
+  ReadItemFunc read_item_func;
+} CheckMarshalItem;
+
+static CheckMarshalItem items[] = {
+  { ITEM_INT32, write_int32, read_int32 },
+  { ITEM_STRUCT_WITH_INT32S, write_struct_with_int32s, read_struct_with_int32s },
+  { ITEM_STRUCT_OF_STRUCTS, write_struct_of_structs, read_struct_of_structs },
+  { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS,
+    write_struct_of_structs_of_structs,
+    read_struct_of_structs_of_structs }
+};
+
+typedef struct
+{
+  /* Array of items in the above items[]; -1 terminated */
+  int items[20];
+} TestRun;
+
+static TestRun runs[] = {
+  { { ITEM_INVALID } },
+
+  /* INT32 */
+  { { ITEM_INT32, ITEM_INVALID } },
+  { { ITEM_INT32, ITEM_INT32, ITEM_INVALID } },
+  { { ITEM_INT32, ITEM_INT32, ITEM_INT32, ITEM_INT32, ITEM_INT32, ITEM_INVALID } },
+
+  /* STRUCT_WITH_INT32S */
+  { { ITEM_STRUCT_WITH_INT32S, ITEM_INVALID } },
+  { { ITEM_STRUCT_WITH_INT32S, ITEM_STRUCT_WITH_INT32S, ITEM_INVALID } },
+  { { ITEM_STRUCT_WITH_INT32S, ITEM_INT32, ITEM_STRUCT_WITH_INT32S, ITEM_INVALID } },
+  { { ITEM_INT32, ITEM_STRUCT_WITH_INT32S, ITEM_INT32, ITEM_STRUCT_WITH_INT32S, ITEM_INVALID } },
+  { { ITEM_INT32, ITEM_STRUCT_WITH_INT32S, ITEM_INT32, ITEM_INT32, ITEM_INT32, ITEM_STRUCT_WITH_INT32S, ITEM_INVALID } },
+
+  /* STRUCT_OF_STRUCTS */
+  { { ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
+  { { ITEM_STRUCT_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
+  { { ITEM_STRUCT_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
+  { { ITEM_STRUCT_WITH_INT32S, ITEM_STRUCT_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
+  { { ITEM_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
+  { { ITEM_STRUCT_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
+
+  /* STRUCT_OF_STRUCTS_OF_STRUCTS */
+  { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
+  { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
+  { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
+  { { ITEM_STRUCT_WITH_INT32S, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
+  { { ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
+  { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } }
+  
+};
+
+static dbus_bool_t
+perform_one_run (DataBlock *block,
+                 int        byte_order,
+                 TestRun   *run)
+{
+  DBusTypeReader reader;
+  DBusTypeWriter writer;
+  int i;
+  DataBlockState saved;
+  dbus_bool_t retval;
+
+  retval = FALSE;
+
+  data_block_save (block, &saved);
+  
+  data_block_init_reader_writer (block, 
+                                 byte_order,
+                                 &reader, &writer);
+
+  i = 0;
+  while (run->items[i] != ITEM_INVALID)
+    {
+      CheckMarshalItem *item = &items[run->items[i]];
+      if (!(* item->write_item_func) (block, &writer))
+        goto out;
+      ++i;
+    }
+
+  i = 0;
+  while (run->items[i] != ITEM_INVALID)
+    {
+      CheckMarshalItem *item = &items[run->items[i]];
+      
+      if (!(* item->read_item_func) (block, &reader))
+        goto out;
+
+      _dbus_type_reader_next (&reader);
+      
+      ++i;
+    }
+  
+  retval = TRUE;
+  
+ out:
+  data_block_restore (block, &saved);
+  return retval;
+}
+
+static dbus_bool_t
+perform_all_runs (int byte_order,
+                  int initial_offset)
+{
+  int i;
+  DataBlock block;
+  dbus_bool_t retval;
+
+  retval = FALSE;
+  
+  if (!data_block_init (&block))
+    return FALSE;
+
+  if (!_dbus_string_lengthen (&block.signature, initial_offset))
+    goto out;
+  
+  if (!_dbus_string_lengthen (&block.body, initial_offset))
+    goto out;
+  
+  i = 0;
+  while (i < _DBUS_N_ELEMENTS (runs))
+    {
+      if (!perform_one_run (&block, byte_order, &runs[i]))
+        goto out;
+      
+      ++i;
+    }
+
+  retval = TRUE;
+  
+ out:
+  data_block_free (&block);
+  
+  return retval;
+}
+
+static dbus_bool_t
+perform_all_items (int byte_order,
+                   int initial_offset)
+{
+  int i;
+  DataBlock block;
+  dbus_bool_t retval;
+  TestRun run;
+
+  retval = FALSE;
+  
+  if (!data_block_init (&block))
+    return FALSE;
+
+
+  if (!_dbus_string_lengthen (&block.signature, initial_offset))
+    goto out;
+  
+  if (!_dbus_string_lengthen (&block.body, initial_offset))
+    goto out;
+
+  /* Create a run containing all the items */
+  i = 0;
+  while (i < _DBUS_N_ELEMENTS (items))
+    {
+      _dbus_assert (i == items[i].which);
+      
+      run.items[i] = items[i].which;
+      
+      ++i;
+    }
+  
+  run.items[i] = ITEM_INVALID;
+
+  if (!perform_one_run (&block, byte_order, &run))
+    goto out;  
+  
+  retval = TRUE;
+  
+ out:
+  data_block_free (&block);
+  
+  return retval;
+}
+
+static dbus_bool_t
+recursive_marshal_test_iteration (void *data)
+{
+  int i;
+
+  i = 0;
+  while (i < 18)
+    {
+      if (!perform_all_runs (DBUS_LITTLE_ENDIAN, i))
+        return FALSE;
+      if (!perform_all_runs (DBUS_BIG_ENDIAN, i))
+        return FALSE;
+      if (!perform_all_items (DBUS_LITTLE_ENDIAN, i))
+        return FALSE;
+      if (!perform_all_items (DBUS_BIG_ENDIAN, i))
+        return FALSE;
+      
+      ++i;
+    }
+
+  return TRUE;
+}
+
+dbus_bool_t _dbus_marshal_recursive_test (void);
+
+dbus_bool_t
+_dbus_marshal_recursive_test (void)
+{
+  _dbus_test_oom_handling ("recursive marshaling",
+                           recursive_marshal_test_iteration,
+                           NULL);  
+  
+  return TRUE;
+}
+
+#if 1
+int
+main (int argc, char **argv)
+{
+  _dbus_marshal_recursive_test ();
+
+  return 0;
+}
+#endif /* main() */
+
+#endif /* DBUS_BUILD_TESTS */
diff --git a/dbus/dbus-marshal-recursive.h b/dbus/dbus-marshal-recursive.h
new file mode 100644 (file)
index 0000000..19960ec
--- /dev/null
@@ -0,0 +1,112 @@
+/* -*- mode: C; c-file-style: "gnu" -*- */
+/* dbus-marshal-recursive.h  Marshalling routines for recursive types
+ *
+ * Copyright (C) 2004 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
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef DBUS_MARSHAL_RECURSIVE_H
+#define DBUS_MARSHAL_RECURSIVE_H
+
+#include <config.h>
+#include <dbus/dbus-marshal-basic.h>
+
+#ifndef PACKAGE
+#error "config.h not included here"
+#endif
+
+/* Notes on my plan to implement this:
+ * - also have DBusTypeWriter (heh)
+ * - TypeReader has accessors for:
+ *    . basic type
+ *    . array of basic type (efficiency hack)
+ *    . another type reader
+ * - a dict will appear to be a list of string, whatever, string, whatever
+ * - a variant will contain another TypeReader
+ * - a struct will be a list of whatever, whatever, whatever
+ *
+ * So the basic API usage is to go next, next, next; if the
+ * item is a basic type or basic array then read the item;
+ * if it's another type reader then process it; if it's
+ * a container type (struct, array, variant, dict) then
+ * recurse.
+ * 
+ */
+
+struct DBusTypeReader
+{
+  int byte_order;
+  const DBusString *type_str;
+  int type_pos;
+  const DBusString *value_str;
+  int value_pos;
+};
+
+typedef struct DBusTypeReader DBusTypeReader;
+
+struct DBusTypeWriter
+{
+  int byte_order;
+  DBusString *type_str;
+  int type_pos;
+  DBusString *value_str;
+  int value_pos;
+};
+
+typedef struct DBusTypeWriter DBusTypeWriter;
+
+void        _dbus_type_reader_init             (DBusTypeReader    *reader,
+                                                int                byte_order,
+                                                const DBusString  *type_str,
+                                                int                type_pos,
+                                                const DBusString  *value_str,
+                                                int                value_pos);
+int         _dbus_type_reader_get_value_end    (DBusTypeReader    *reader);
+int         _dbus_type_reader_get_type_end     (DBusTypeReader    *reader);
+int         _dbus_type_reader_get_current_type (DBusTypeReader    *reader);
+int         _dbus_type_reader_get_array_type   (DBusTypeReader    *reader);
+void        _dbus_type_reader_read_basic       (DBusTypeReader    *reader,
+                                                void              *value);
+dbus_bool_t _dbus_type_reader_read_array       (DBusTypeReader    *reader,
+                                                int                type,
+                                                void             **array,
+                                                int               *array_len);
+void        _dbus_type_reader_recurse          (DBusTypeReader    *reader);
+void        _dbus_type_reader_unrecurse        (DBusTypeReader    *reader);
+dbus_bool_t _dbus_type_reader_next             (DBusTypeReader    *reader);
+
+
+void        _dbus_type_writer_init        (DBusTypeWriter *writer,
+                                           int             byte_order,
+                                           DBusString     *type_str,
+                                           int             type_pos,
+                                           DBusString     *value_str,
+                                           int             value_pos);
+dbus_bool_t _dbus_type_writer_write_basic (DBusTypeWriter *writer,
+                                           int             type,
+                                           const void     *value);
+dbus_bool_t _dbus_type_writer_write_array (DBusTypeWriter *writer,
+                                           int             type,
+                                           const void     *array,
+                                           int             array_len);
+dbus_bool_t _dbus_type_writer_recurse     (DBusTypeWriter *writer,
+                                           int             container_type);
+dbus_bool_t _dbus_type_writer_unrecurse   (DBusTypeWriter *writer);
+
+#endif /* DBUS_MARSHAL_RECURSIVE_H */
diff --git a/dbus/dbus-protocol-new.h b/dbus/dbus-protocol-new.h
new file mode 100644 (file)
index 0000000..b029f0f
--- /dev/null
@@ -0,0 +1,180 @@
+/* -*- mode: C; c-file-style: "gnu" -*- */
+/* dbus-protocol.h  D-Bus protocol constants
+ *
+ * Copyright (C) 2002, 2003  CodeFactory AB
+ * Copyright (C) 2004 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
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef DBUS_PROTOCOL_H
+#define DBUS_PROTOCOL_H
+
+/* Don't include anything in here from anywhere else. It's
+ * intended for use by any random library.
+ */
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/* Message byte order */
+#define DBUS_LITTLE_ENDIAN ('l')  /* LSB first */
+#define DBUS_BIG_ENDIAN    ('B')  /* MSB first */    
+
+/* Protocol version */
+#define DBUS_MAJOR_PROTOCOL_VERSION 1
+
+/* Never a legitimate type */
+#define DBUS_TYPE_INVALID       ((int) '\0')
+
+/* Primitive types */
+#define DBUS_TYPE_BYTE          ((int) 'y')
+#define DBUS_TYPE_BOOLEAN       ((int) 'b')
+#define DBUS_TYPE_INT32         ((int) 'i')
+
+#define DBUS_TYPE_UINT32        ((int) 'u')
+#define DBUS_TYPE_INT64         ((int) 'x')
+#define DBUS_TYPE_UINT64        ((int) 't')
+
+#define DBUS_TYPE_DOUBLE        ((int) 'd')
+#define DBUS_TYPE_STRING        ((int) 's')
+#define DBUS_TYPE_OBJECT_PATH   ((int) 'o')
+
+/* Compound types */
+#define DBUS_TYPE_ARRAY         ((int) 'a')
+#define DBUS_TYPE_DICT          ((int) 'm')
+#define DBUS_TYPE_VARIANT       ((int) 'v')
+
+/* STRUCT is sort of special since its code can't appear in a type string,
+ * instead DBUS_STRUCT_BEGIN_CHAR has to appear
+ */
+#define DBUS_TYPE_STRUCT        ((int) 'r')
+
+/* Does not count INVALID */
+#define DBUS_NUMBER_OF_TYPES    (13)
+
+/* characters other than typecodes that appear in type signatures */
+#define DBUS_STRUCT_BEGIN_CHAR   ((int) '(')
+#define DBUS_STRUCT_END_CHAR     ((int) ')')
+#define DBUS_NAME_DELIMITER_CHAR ((int) '\'')
+
+/* Max length in bytes of a service or interface or member name */
+#define DBUS_MAXIMUM_NAME_LENGTH 256
+
+/* Max length of a match rule string */
+#define DBUS_MAXIMUM_MATCH_RULE_LENGTH 1024
+
+/* Types of message */
+#define DBUS_MESSAGE_TYPE_INVALID       0
+#define DBUS_MESSAGE_TYPE_METHOD_CALL   1
+#define DBUS_MESSAGE_TYPE_METHOD_RETURN 2
+#define DBUS_MESSAGE_TYPE_ERROR         3
+#define DBUS_MESSAGE_TYPE_SIGNAL        4
+  
+/* Header flags */
+#define DBUS_HEADER_FLAG_NO_REPLY_EXPECTED 0x1
+#define DBUS_HEADER_FLAG_AUTO_ACTIVATION   0x2
+  
+/* Header fields */
+#define DBUS_HEADER_FIELD_INVALID        0
+#define DBUS_HEADER_FIELD_PATH           1
+#define DBUS_HEADER_FIELD_INTERFACE      2
+#define DBUS_HEADER_FIELD_MEMBER         3
+#define DBUS_HEADER_FIELD_ERROR_NAME     4
+#define DBUS_HEADER_FIELD_REPLY_SERIAL   5
+#define DBUS_HEADER_FIELD_DESTINATION    6
+#define DBUS_HEADER_FIELD_SENDER         7
+#define DBUS_HEADER_FIELD_SIGNATURE      8
+
+#define DBUS_HEADER_FIELD_LAST DBUS_HEADER_FIELD_SIGNATURE
+
+/* Services */
+#define DBUS_SERVICE_ORG_FREEDESKTOP_DBUS      "org.freedesktop.DBus"
+
+/* Paths */
+#define DBUS_PATH_ORG_FREEDESKTOP_DBUS  "/org/freedesktop/DBus"
+#define DBUS_PATH_ORG_FREEDESKTOP_LOCAL "/org/freedesktop/Local"
+  
+/* Interfaces, these #define don't do much other than
+ * catch typos at compile time
+ */
+#define DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS  "org.freedesktop.DBus"
+#define DBUS_INTERFACE_ORG_FREEDESKTOP_INTROSPECTABLE "org.freedesktop.Introspectable"
+  
+/* This is a special interface whose methods can only be invoked
+ * by the local implementation (messages from remote apps aren't
+ * allowed to specify this interface).
+ */
+#define DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL "org.freedesktop.Local"
+  
+/* Service owner flags */
+#define DBUS_SERVICE_FLAG_PROHIBIT_REPLACEMENT 0x1
+#define DBUS_SERVICE_FLAG_REPLACE_EXISTING     0x2
+
+/* Service replies */
+#define DBUS_SERVICE_REPLY_PRIMARY_OWNER  0x1
+#define DBUS_SERVICE_REPLY_IN_QUEUE       0x2
+#define DBUS_SERVICE_REPLY_SERVICE_EXISTS 0x4
+#define DBUS_SERVICE_REPLY_ALREADY_OWNER  0x8
+
+/* Activation replies */
+#define DBUS_ACTIVATION_REPLY_ACTIVATED      0x0
+#define DBUS_ACTIVATION_REPLY_ALREADY_ACTIVE 0x1
+
+/* Errors */
+/* WARNING these get autoconverted to an enum in dbus-glib.h. Thus,
+ * if you change the order it breaks the ABI. Keep them in order.
+ * Also, don't change the formatting since that will break the sed
+ * script.
+ */
+#define DBUS_ERROR_FAILED                     "org.freedesktop.DBus.Error.Failed"
+#define DBUS_ERROR_NO_MEMORY                  "org.freedesktop.DBus.Error.NoMemory"
+#define DBUS_ERROR_ACTIVATE_SERVICE_NOT_FOUND "org.freedesktop.DBus.Error.ServiceNotFound"
+#define DBUS_ERROR_SERVICE_DOES_NOT_EXIST     "org.freedesktop.DBus.Error.ServiceDoesNotExist"
+#define DBUS_ERROR_SERVICE_HAS_NO_OWNER       "org.freedesktop.DBus.Error.ServiceHasNoOwner"
+#define DBUS_ERROR_NO_REPLY                   "org.freedesktop.DBus.Error.NoReply"
+#define DBUS_ERROR_IO_ERROR                   "org.freedesktop.DBus.Error.IOError"
+#define DBUS_ERROR_BAD_ADDRESS                "org.freedesktop.DBus.Error.BadAddress"
+#define DBUS_ERROR_NOT_SUPPORTED              "org.freedesktop.DBus.Error.NotSupported"
+#define DBUS_ERROR_LIMITS_EXCEEDED            "org.freedesktop.DBus.Error.LimitsExceeded"
+#define DBUS_ERROR_ACCESS_DENIED              "org.freedesktop.DBus.Error.AccessDenied"
+#define DBUS_ERROR_AUTH_FAILED                "org.freedesktop.DBus.Error.AuthFailed"
+#define DBUS_ERROR_NO_SERVER                  "org.freedesktop.DBus.Error.NoServer"
+#define DBUS_ERROR_TIMEOUT                    "org.freedesktop.DBus.Error.Timeout"
+#define DBUS_ERROR_NO_NETWORK                 "org.freedesktop.DBus.Error.NoNetwork"
+#define DBUS_ERROR_ADDRESS_IN_USE             "org.freedesktop.DBus.Error.AddressInUse"
+#define DBUS_ERROR_DISCONNECTED               "org.freedesktop.DBus.Error.Disconnected"
+#define DBUS_ERROR_INVALID_ARGS               "org.freedesktop.DBus.Error.InvalidArgs"
+#define DBUS_ERROR_FILE_NOT_FOUND             "org.freedesktop.DBus.Error.FileNotFound"
+#define DBUS_ERROR_UNKNOWN_METHOD             "org.freedesktop.DBus.Error.UnknownMethod"
+#define DBUS_ERROR_TIMED_OUT                  "org.freedesktop.DBus.Error.TimedOut"
+#define DBUS_ERROR_MATCH_RULE_NOT_FOUND       "org.freedesktop.DBus.Error.MatchRuleNotFound"
+#define DBUS_ERROR_MATCH_RULE_INVALID         "org.freedesktop.DBus.Error.MatchRuleInvalid"
+#define DBUS_ERROR_SPAWN_EXEC_FAILED          "org.freedesktop.DBus.Error.Spawn.ExecFailed"
+#define DBUS_ERROR_SPAWN_FORK_FAILED          "org.freedesktop.DBus.Error.Spawn.ForkFailed"
+#define DBUS_ERROR_SPAWN_CHILD_EXITED         "org.freedesktop.DBus.Error.Spawn.ChildExited"
+#define DBUS_ERROR_SPAWN_CHILD_SIGNALED       "org.freedesktop.DBus.Error.Spawn.ChildSignaled"
+#define DBUS_ERROR_SPAWN_FAILED               "org.freedesktop.DBus.Error.Spawn.Failed"
+#define DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN    "org.freedesktop.DBus.Error.UnixProcessIdUnknown"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* DBUS_PROTOCOL_H */