diff options
| author | Havoc Pennington <hp@redhat.com> | 2004-12-19 00:11:49 +0000 | 
|---|---|---|
| committer | Havoc Pennington <hp@redhat.com> | 2004-12-19 00:11:49 +0000 | 
| commit | 305a8d4d988a1011982e284e358165d3368067cc (patch) | |
| tree | 6b2a915f7d277768387c137a3c49e3b6192b0fa7 | |
| parent | f3228b477df95ba247c90cc54189ce6d62059251 (diff) | |
back up some files I'm working on that don't do anything yet
| -rw-r--r-- | dbus/dbus-marshal-basic.c | 2945 | ||||
| -rw-r--r-- | dbus/dbus-marshal-basic.h | 400 | ||||
| -rw-r--r-- | dbus/dbus-marshal-recursive.c | 713 | ||||
| -rw-r--r-- | dbus/dbus-marshal-recursive.h | 112 | ||||
| -rw-r--r-- | dbus/dbus-protocol-new.h | 180 | 
5 files changed, 4350 insertions, 0 deletions
diff --git a/dbus/dbus-marshal-basic.c b/dbus/dbus-marshal-basic.c new file mode 100644 index 00000000..76477279 --- /dev/null +++ b/dbus/dbus-marshal-basic.c @@ -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 index 00000000..25db7cc5 --- /dev/null +++ b/dbus/dbus-marshal-basic.h @@ -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 index 00000000..eb85a2c4 --- /dev/null +++ b/dbus/dbus-marshal-recursive.c @@ -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 index 00000000..19960ec8 --- /dev/null +++ b/dbus/dbus-marshal-recursive.h @@ -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 index 00000000..b029f0fb --- /dev/null +++ b/dbus/dbus-protocol-new.h @@ -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 */  | 
