dbus/dbus dbus-marshal-basic.c, NONE, 1.1 dbus-marshal-basic.h, NONE,
1.1 dbus-marshal-recursive.c, NONE,
1.1 dbus-marshal-recursive.h, NONE, 1.1 dbus-protocol-new.h,
NONE, 1.1
Havoc Pennington
hp at freedesktop.org
Sat Dec 18 16:11:51 PST 2004
Update of /cvs/dbus/dbus/dbus
In directory gabe:/tmp/cvs-serv31365
Added Files:
dbus-marshal-basic.c dbus-marshal-basic.h
dbus-marshal-recursive.c dbus-marshal-recursive.h
dbus-protocol-new.h
Log Message:
back up some files I'm working on that don't do anything yet
--- NEW FILE: dbus-marshal-basic.c ---
/* -*- 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 */
--- NEW FILE: dbus-marshal-basic.h ---
/* -*- 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 */
--- NEW FILE: dbus-marshal-recursive.c ---
/* -*- 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 */
--- NEW FILE: dbus-marshal-recursive.h ---
/* -*- 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 */
--- NEW FILE: dbus-protocol-new.h ---
/* -*- 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 */
More information about the dbus-commit
mailing list