mirror of
https://gitlab.freedesktop.org/dbus/dbus.git
synced 2026-05-09 04:58:02 +02:00
switch to a vtable approach for the reader
This commit is contained in:
parent
8645ee5251
commit
9b0fc4e482
2 changed files with 397 additions and 338 deletions
|
|
@ -29,6 +29,16 @@
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
struct DBusTypeReaderClass
|
||||||
|
{
|
||||||
|
const char *name;
|
||||||
|
void (* recurse) (DBusTypeReader *sub,
|
||||||
|
DBusTypeReader *parent);
|
||||||
|
int (* get_current_type) (DBusTypeReader *reader);
|
||||||
|
void (* next) (DBusTypeReader *reader,
|
||||||
|
int current_type);
|
||||||
|
};
|
||||||
|
|
||||||
static int
|
static int
|
||||||
first_type_in_signature (const DBusString *str,
|
first_type_in_signature (const DBusString *str,
|
||||||
int pos)
|
int pos)
|
||||||
|
|
@ -50,233 +60,137 @@ element_type_get_alignment (const DBusString *str,
|
||||||
return _dbus_type_get_alignment (first_type_in_signature (str, pos));
|
return _dbus_type_get_alignment (first_type_in_signature (str, pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
_dbus_type_reader_init (DBusTypeReader *reader,
|
reader_init (DBusTypeReader *reader,
|
||||||
int byte_order,
|
int byte_order,
|
||||||
const DBusString *type_str,
|
const DBusString *type_str,
|
||||||
int type_pos,
|
int type_pos,
|
||||||
const DBusString *value_str,
|
const DBusString *value_str,
|
||||||
int value_pos)
|
int value_pos)
|
||||||
{
|
{
|
||||||
reader->byte_order = byte_order;
|
reader->byte_order = byte_order;
|
||||||
reader->type_str = type_str;
|
reader->type_str = type_str;
|
||||||
reader->type_pos = type_pos;
|
reader->type_pos = type_pos;
|
||||||
reader->value_str = value_str;
|
reader->value_str = value_str;
|
||||||
reader->value_pos = value_pos;
|
reader->value_pos = value_pos;
|
||||||
reader->container_type = DBUS_TYPE_INVALID;
|
|
||||||
|
|
||||||
_dbus_verbose (" type reader %p init type_pos = %d value_pos = %d remaining sig '%s'\n",
|
|
||||||
reader, reader->type_pos, reader->value_pos,
|
|
||||||
_dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
static void
|
||||||
_dbus_type_reader_get_current_type (DBusTypeReader *reader)
|
base_reader_recurse (DBusTypeReader *sub,
|
||||||
|
DBusTypeReader *parent)
|
||||||
|
{
|
||||||
|
/* point subreader at the same place as parent */
|
||||||
|
reader_init (sub,
|
||||||
|
parent->byte_order,
|
||||||
|
parent->type_str,
|
||||||
|
parent->type_pos,
|
||||||
|
parent->value_str,
|
||||||
|
parent->value_pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
struct_reader_recurse (DBusTypeReader *sub,
|
||||||
|
DBusTypeReader *parent)
|
||||||
|
{
|
||||||
|
base_reader_recurse (sub, parent);
|
||||||
|
|
||||||
|
_dbus_assert (_dbus_string_get_byte (sub->type_str,
|
||||||
|
sub->type_pos) == DBUS_STRUCT_BEGIN_CHAR);
|
||||||
|
|
||||||
|
sub->type_pos += 1;
|
||||||
|
|
||||||
|
/* struct has 8 byte alignment */
|
||||||
|
sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 8);
|
||||||
|
|
||||||
|
sub->u.strct.finished = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
array_reader_recurse (DBusTypeReader *sub,
|
||||||
|
DBusTypeReader *parent)
|
||||||
|
{
|
||||||
|
dbus_uint32_t array_len;
|
||||||
|
int alignment;
|
||||||
|
|
||||||
|
_dbus_assert (!_dbus_type_reader_array_is_empty (parent));
|
||||||
|
|
||||||
|
base_reader_recurse (sub, parent);
|
||||||
|
|
||||||
|
/* point type_pos at the array element type */
|
||||||
|
sub->type_pos += 1;
|
||||||
|
|
||||||
|
sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 4);
|
||||||
|
|
||||||
|
_dbus_demarshal_basic_type (sub->value_str,
|
||||||
|
DBUS_TYPE_UINT32,
|
||||||
|
&array_len,
|
||||||
|
sub->byte_order,
|
||||||
|
&sub->value_pos);
|
||||||
|
|
||||||
|
sub->u.array.len = array_len;
|
||||||
|
|
||||||
|
alignment = element_type_get_alignment (sub->type_str,
|
||||||
|
sub->type_pos);
|
||||||
|
|
||||||
|
sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, alignment);
|
||||||
|
|
||||||
|
sub->u.array.element_type = first_type_in_signature (sub->type_str,
|
||||||
|
sub->type_pos);
|
||||||
|
sub->u.array.start_pos = sub->value_pos;
|
||||||
|
|
||||||
|
_dbus_verbose (" type reader %p array start = %d array len = %d array element type = %s\n",
|
||||||
|
sub,
|
||||||
|
sub->u.array.start_pos,
|
||||||
|
sub->u.array.len,
|
||||||
|
_dbus_type_to_string (sub->u.array.element_type));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
body_reader_get_current_type (DBusTypeReader *reader)
|
||||||
{
|
{
|
||||||
int t;
|
int t;
|
||||||
|
|
||||||
/* for INVALID t will == DBUS_TYPE_INVALID when we
|
t = first_type_in_signature (reader->type_str,
|
||||||
* reach the end of type_str, for STRUCT we have to
|
reader->type_pos);
|
||||||
* check the finished flag
|
|
||||||
*/
|
|
||||||
if (reader->container_type == DBUS_TYPE_INVALID)
|
|
||||||
{
|
|
||||||
t = first_type_in_signature (reader->type_str,
|
|
||||||
reader->type_pos);
|
|
||||||
}
|
|
||||||
else if (reader->container_type == DBUS_TYPE_STRUCT)
|
|
||||||
{
|
|
||||||
if (reader->u.strct.finished)
|
|
||||||
t = DBUS_TYPE_INVALID;
|
|
||||||
else
|
|
||||||
t = first_type_in_signature (reader->type_str,
|
|
||||||
reader->type_pos);
|
|
||||||
}
|
|
||||||
else if (reader->container_type == DBUS_TYPE_ARRAY)
|
|
||||||
{
|
|
||||||
/* return the array element type if elements remain, and
|
|
||||||
* TYPE_INVALID otherwise
|
|
||||||
*/
|
|
||||||
int end_pos;
|
|
||||||
|
|
||||||
end_pos = reader->u.array.start_pos + reader->u.array.len;
|
|
||||||
|
|
||||||
_dbus_assert (reader->value_pos <= end_pos);
|
|
||||||
_dbus_assert (reader->value_pos >= reader->u.array.start_pos);
|
|
||||||
|
|
||||||
if (reader->value_pos < end_pos)
|
|
||||||
t = reader->u.array.element_type;
|
|
||||||
else
|
|
||||||
t = DBUS_TYPE_INVALID;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_dbus_assert_not_reached ("reader->container_type should not be set to this");
|
|
||||||
t = DBUS_TYPE_INVALID; /* quiet gcc */
|
|
||||||
}
|
|
||||||
|
|
||||||
_dbus_assert (t != DBUS_STRUCT_END_CHAR);
|
|
||||||
_dbus_assert (t != DBUS_STRUCT_BEGIN_CHAR);
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
_dbus_verbose (" type reader %p current type_pos = %d type = %s\n",
|
|
||||||
reader, reader->type_pos,
|
|
||||||
_dbus_type_to_string (t));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
dbus_bool_t
|
static int
|
||||||
_dbus_type_reader_array_is_empty (DBusTypeReader *reader)
|
struct_reader_get_current_type (DBusTypeReader *reader)
|
||||||
{
|
|
||||||
dbus_uint32_t array_len;
|
|
||||||
int len_pos;
|
|
||||||
|
|
||||||
_dbus_return_val_if_fail (_dbus_type_reader_get_current_type (reader) == DBUS_TYPE_ARRAY,
|
|
||||||
TRUE);
|
|
||||||
|
|
||||||
len_pos = _DBUS_ALIGN_VALUE (reader->value_pos, 4);
|
|
||||||
|
|
||||||
_dbus_demarshal_basic_type (reader->value_str,
|
|
||||||
DBUS_TYPE_UINT32,
|
|
||||||
&array_len,
|
|
||||||
reader->byte_order,
|
|
||||||
&len_pos);
|
|
||||||
|
|
||||||
return array_len == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
_dbus_type_reader_read_basic (DBusTypeReader *reader,
|
|
||||||
void *value)
|
|
||||||
{
|
|
||||||
if (reader->container_type == DBUS_TYPE_INVALID ||
|
|
||||||
reader->container_type == DBUS_TYPE_STRUCT ||
|
|
||||||
reader->container_type == DBUS_TYPE_ARRAY)
|
|
||||||
{
|
|
||||||
int t;
|
|
||||||
int next;
|
|
||||||
|
|
||||||
t = _dbus_type_reader_get_current_type (reader);
|
|
||||||
|
|
||||||
next = reader->value_pos;
|
|
||||||
_dbus_demarshal_basic_type (reader->value_str,
|
|
||||||
t, value,
|
|
||||||
reader->byte_order,
|
|
||||||
&next);
|
|
||||||
|
|
||||||
|
|
||||||
_dbus_verbose (" type reader %p read basic type_pos = %d value_pos = %d next = %d remaining sig '%s'\n",
|
|
||||||
reader, reader->type_pos, reader->value_pos, next,
|
|
||||||
_dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_dbus_assert_not_reached ("reader->container_type should not be set to this");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dbus_bool_t
|
|
||||||
_dbus_type_reader_read_array_of_basic (DBusTypeReader *reader,
|
|
||||||
int type,
|
|
||||||
void **array,
|
|
||||||
int *array_len)
|
|
||||||
{
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize a new reader pointing to the first type and
|
|
||||||
* corresponding value that's a child of the current container. It's
|
|
||||||
* an error to call this if the current type is a non-container.
|
|
||||||
*
|
|
||||||
* Note that DBusTypeReader traverses values, not types. So if you
|
|
||||||
* have an empty array of array of int, you can't recurse into it. You
|
|
||||||
* can only recurse into each element.
|
|
||||||
*
|
|
||||||
* @param reader the reader
|
|
||||||
* @param sub a reader to init pointing to the first child
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
_dbus_type_reader_recurse (DBusTypeReader *reader,
|
|
||||||
DBusTypeReader *sub)
|
|
||||||
{
|
{
|
||||||
int t;
|
int t;
|
||||||
|
|
||||||
t = first_type_in_signature (reader->type_str, reader->type_pos);
|
if (reader->u.strct.finished)
|
||||||
|
t = DBUS_TYPE_INVALID;
|
||||||
/* point subreader at the same place as reader */
|
|
||||||
_dbus_type_reader_init (sub,
|
|
||||||
reader->byte_order,
|
|
||||||
reader->type_str,
|
|
||||||
reader->type_pos,
|
|
||||||
reader->value_str,
|
|
||||||
reader->value_pos);
|
|
||||||
|
|
||||||
if (t == DBUS_TYPE_STRUCT)
|
|
||||||
{
|
|
||||||
sub->container_type = DBUS_TYPE_STRUCT;
|
|
||||||
|
|
||||||
sub->type_pos += 1;
|
|
||||||
|
|
||||||
/* struct has 8 byte alignment */
|
|
||||||
sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 8);
|
|
||||||
|
|
||||||
sub->u.strct.finished = FALSE;
|
|
||||||
}
|
|
||||||
else if (t == DBUS_TYPE_ARRAY)
|
|
||||||
{
|
|
||||||
dbus_uint32_t array_len;
|
|
||||||
int alignment;
|
|
||||||
|
|
||||||
_dbus_return_if_fail (!_dbus_type_reader_array_is_empty (reader));
|
|
||||||
|
|
||||||
sub->container_type = DBUS_TYPE_ARRAY;
|
|
||||||
|
|
||||||
/* point type_pos at the array element type */
|
|
||||||
sub->type_pos += 1;
|
|
||||||
|
|
||||||
sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 4);
|
|
||||||
|
|
||||||
_dbus_demarshal_basic_type (sub->value_str,
|
|
||||||
DBUS_TYPE_UINT32,
|
|
||||||
&array_len,
|
|
||||||
sub->byte_order,
|
|
||||||
&sub->value_pos);
|
|
||||||
|
|
||||||
sub->u.array.len = array_len;
|
|
||||||
|
|
||||||
alignment = element_type_get_alignment (sub->type_str,
|
|
||||||
sub->type_pos);
|
|
||||||
|
|
||||||
sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, alignment);
|
|
||||||
|
|
||||||
sub->u.array.element_type = first_type_in_signature (sub->type_str,
|
|
||||||
sub->type_pos);
|
|
||||||
sub->u.array.start_pos = sub->value_pos;
|
|
||||||
|
|
||||||
_dbus_verbose (" type reader %p array start = %d array len = %d array element type = %s\n",
|
|
||||||
reader,
|
|
||||||
sub->u.array.start_pos,
|
|
||||||
sub->u.array.len,
|
|
||||||
_dbus_type_to_string (sub->u.array.element_type));
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
t = first_type_in_signature (reader->type_str,
|
||||||
_dbus_verbose ("recursing into type %s\n", _dbus_type_to_string (t));
|
reader->type_pos);
|
||||||
#ifndef DBUS_DISABLE_CHECKS
|
|
||||||
if (t == DBUS_TYPE_INVALID)
|
|
||||||
_dbus_warn ("You can't recurse into an empty array or off the end of a message body\n");
|
|
||||||
#endif /* DBUS_DISABLE_CHECKS */
|
|
||||||
|
|
||||||
_dbus_assert_not_reached ("don't yet handle recursing into this type");
|
|
||||||
}
|
|
||||||
|
|
||||||
_dbus_verbose (" type reader %p RECURSED type_pos = %d value_pos = %d remaining sig '%s'\n",
|
return t;
|
||||||
sub, sub->type_pos, sub->value_pos,
|
}
|
||||||
_dbus_string_get_const_data_len (sub->type_str, sub->type_pos, 0));
|
|
||||||
|
static int
|
||||||
|
array_reader_get_current_type (DBusTypeReader *reader)
|
||||||
|
{
|
||||||
|
int t;
|
||||||
|
int end_pos;
|
||||||
|
|
||||||
|
/* return the array element type if elements remain, and
|
||||||
|
* TYPE_INVALID otherwise
|
||||||
|
*/
|
||||||
|
|
||||||
|
end_pos = reader->u.array.start_pos + reader->u.array.len;
|
||||||
|
|
||||||
|
_dbus_assert (reader->value_pos <= end_pos);
|
||||||
|
_dbus_assert (reader->value_pos >= reader->u.array.start_pos);
|
||||||
|
|
||||||
|
if (reader->value_pos < end_pos)
|
||||||
|
t = reader->u.array.element_type;
|
||||||
|
else
|
||||||
|
t = DBUS_TYPE_INVALID;
|
||||||
|
|
||||||
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -337,6 +251,275 @@ skip_array_values (int element_type,
|
||||||
*value_pos = pos + array_len;
|
*value_pos = pos + array_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
base_reader_next (DBusTypeReader *reader,
|
||||||
|
int current_type)
|
||||||
|
{
|
||||||
|
switch (current_type)
|
||||||
|
{
|
||||||
|
case DBUS_TYPE_STRUCT:
|
||||||
|
/* Scan forward over the entire container contents */
|
||||||
|
{
|
||||||
|
DBusTypeReader sub;
|
||||||
|
|
||||||
|
/* Recurse into the struct */
|
||||||
|
_dbus_type_reader_recurse (reader, &sub);
|
||||||
|
|
||||||
|
/* Skip everything in this subreader */
|
||||||
|
while (_dbus_type_reader_next (&sub))
|
||||||
|
{
|
||||||
|
/* nothing */;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now we are at the end of this container */
|
||||||
|
reader->type_pos = sub.type_pos;
|
||||||
|
reader->value_pos = sub.value_pos;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DBUS_TYPE_ARRAY:
|
||||||
|
{
|
||||||
|
skip_array_values (first_type_in_signature (reader->type_str,
|
||||||
|
reader->type_pos + 1),
|
||||||
|
reader->value_str, &reader->value_pos, reader->byte_order);
|
||||||
|
skip_one_complete_type (reader->type_str, &reader->type_pos);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
_dbus_marshal_skip_basic_type (reader->value_str,
|
||||||
|
current_type, reader->byte_order,
|
||||||
|
&reader->value_pos);
|
||||||
|
reader->type_pos += 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
struct_reader_next (DBusTypeReader *reader,
|
||||||
|
int current_type)
|
||||||
|
{
|
||||||
|
int t;
|
||||||
|
|
||||||
|
base_reader_next (reader, current_type);
|
||||||
|
|
||||||
|
/* for STRUCT containers we return FALSE at the end of the struct,
|
||||||
|
* for INVALID we return FALSE at the end of the signature.
|
||||||
|
* In both cases we arrange for get_current_type() to return INVALID
|
||||||
|
* which is defined to happen iff we're at the end (no more next())
|
||||||
|
*/
|
||||||
|
t = _dbus_string_get_byte (reader->type_str, reader->type_pos);
|
||||||
|
if (t == DBUS_STRUCT_END_CHAR)
|
||||||
|
{
|
||||||
|
reader->type_pos += 1;
|
||||||
|
reader->u.strct.finished = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
array_reader_next (DBusTypeReader *reader,
|
||||||
|
int current_type)
|
||||||
|
{
|
||||||
|
/* Skip one array element */
|
||||||
|
int end_pos;
|
||||||
|
|
||||||
|
end_pos = reader->u.array.start_pos + reader->u.array.len;
|
||||||
|
|
||||||
|
_dbus_assert (reader->value_pos < end_pos);
|
||||||
|
_dbus_assert (reader->value_pos >= reader->u.array.start_pos);
|
||||||
|
|
||||||
|
if (reader->u.array.element_type == DBUS_TYPE_STRUCT)
|
||||||
|
{
|
||||||
|
DBusTypeReader sub;
|
||||||
|
|
||||||
|
/* Recurse into the struct */
|
||||||
|
_dbus_type_reader_recurse (reader, &sub);
|
||||||
|
|
||||||
|
/* Skip everything in this element */
|
||||||
|
while (_dbus_type_reader_next (&sub))
|
||||||
|
{
|
||||||
|
/* nothing */;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now we are at the end of this element */
|
||||||
|
reader->value_pos = sub.value_pos;
|
||||||
|
}
|
||||||
|
else if (reader->u.array.element_type == DBUS_TYPE_ARRAY)
|
||||||
|
{
|
||||||
|
skip_array_values (first_type_in_signature (reader->type_str,
|
||||||
|
reader->type_pos + 1),
|
||||||
|
reader->value_str, &reader->value_pos, reader->byte_order);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_dbus_marshal_skip_basic_type (reader->value_str,
|
||||||
|
current_type, reader->byte_order,
|
||||||
|
&reader->value_pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
_dbus_assert (reader->value_pos <= end_pos);
|
||||||
|
|
||||||
|
if (reader->value_pos == end_pos)
|
||||||
|
{
|
||||||
|
skip_one_complete_type (reader->type_str,
|
||||||
|
&reader->type_pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const DBusTypeReaderClass body_reader_class = {
|
||||||
|
"body",
|
||||||
|
NULL, /* body is always toplevel, so doesn't get recursed into */
|
||||||
|
body_reader_get_current_type,
|
||||||
|
base_reader_next
|
||||||
|
};
|
||||||
|
|
||||||
|
static const DBusTypeReaderClass struct_reader_class = {
|
||||||
|
"struct",
|
||||||
|
struct_reader_recurse,
|
||||||
|
struct_reader_get_current_type,
|
||||||
|
struct_reader_next
|
||||||
|
};
|
||||||
|
|
||||||
|
static const DBusTypeReaderClass array_reader_class = {
|
||||||
|
"array",
|
||||||
|
array_reader_recurse,
|
||||||
|
array_reader_get_current_type,
|
||||||
|
array_reader_next
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
_dbus_type_reader_init (DBusTypeReader *reader,
|
||||||
|
int byte_order,
|
||||||
|
const DBusString *type_str,
|
||||||
|
int type_pos,
|
||||||
|
const DBusString *value_str,
|
||||||
|
int value_pos)
|
||||||
|
{
|
||||||
|
reader->klass = &body_reader_class;
|
||||||
|
|
||||||
|
reader_init (reader, byte_order, type_str, type_pos,
|
||||||
|
value_str, value_pos);
|
||||||
|
|
||||||
|
_dbus_verbose (" type reader %p init type_pos = %d value_pos = %d remaining sig '%s'\n",
|
||||||
|
reader, reader->type_pos, reader->value_pos,
|
||||||
|
_dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
_dbus_type_reader_get_current_type (DBusTypeReader *reader)
|
||||||
|
{
|
||||||
|
int t;
|
||||||
|
|
||||||
|
t = (* reader->klass->get_current_type) (reader);
|
||||||
|
|
||||||
|
_dbus_assert (t != DBUS_STRUCT_END_CHAR);
|
||||||
|
_dbus_assert (t != DBUS_STRUCT_BEGIN_CHAR);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
_dbus_verbose (" type reader %p current type_pos = %d type = %s\n",
|
||||||
|
reader, reader->type_pos,
|
||||||
|
_dbus_type_to_string (t));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
dbus_bool_t
|
||||||
|
_dbus_type_reader_array_is_empty (DBusTypeReader *reader)
|
||||||
|
{
|
||||||
|
dbus_uint32_t array_len;
|
||||||
|
int len_pos;
|
||||||
|
|
||||||
|
_dbus_return_val_if_fail (_dbus_type_reader_get_current_type (reader) == DBUS_TYPE_ARRAY,
|
||||||
|
TRUE);
|
||||||
|
|
||||||
|
len_pos = _DBUS_ALIGN_VALUE (reader->value_pos, 4);
|
||||||
|
|
||||||
|
_dbus_demarshal_basic_type (reader->value_str,
|
||||||
|
DBUS_TYPE_UINT32,
|
||||||
|
&array_len,
|
||||||
|
reader->byte_order,
|
||||||
|
&len_pos);
|
||||||
|
|
||||||
|
return array_len == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_dbus_type_reader_read_basic (DBusTypeReader *reader,
|
||||||
|
void *value)
|
||||||
|
{
|
||||||
|
int t;
|
||||||
|
int next;
|
||||||
|
|
||||||
|
t = _dbus_type_reader_get_current_type (reader);
|
||||||
|
|
||||||
|
next = reader->value_pos;
|
||||||
|
_dbus_demarshal_basic_type (reader->value_str,
|
||||||
|
t, value,
|
||||||
|
reader->byte_order,
|
||||||
|
&next);
|
||||||
|
|
||||||
|
|
||||||
|
_dbus_verbose (" type reader %p read basic type_pos = %d value_pos = %d next = %d remaining sig '%s'\n",
|
||||||
|
reader, reader->type_pos, reader->value_pos, next,
|
||||||
|
_dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
dbus_bool_t
|
||||||
|
_dbus_type_reader_read_array_of_basic (DBusTypeReader *reader,
|
||||||
|
int type,
|
||||||
|
void **array,
|
||||||
|
int *array_len)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize a new reader pointing to the first type and
|
||||||
|
* corresponding value that's a child of the current container. It's
|
||||||
|
* an error to call this if the current type is a non-container.
|
||||||
|
*
|
||||||
|
* Note that DBusTypeReader traverses values, not types. So if you
|
||||||
|
* have an empty array of array of int, you can't recurse into it. You
|
||||||
|
* can only recurse into each element.
|
||||||
|
*
|
||||||
|
* @param reader the reader
|
||||||
|
* @param sub a reader to init pointing to the first child
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
_dbus_type_reader_recurse (DBusTypeReader *reader,
|
||||||
|
DBusTypeReader *sub)
|
||||||
|
{
|
||||||
|
int t;
|
||||||
|
|
||||||
|
t = first_type_in_signature (reader->type_str, reader->type_pos);
|
||||||
|
|
||||||
|
switch (t)
|
||||||
|
{
|
||||||
|
case DBUS_TYPE_STRUCT:
|
||||||
|
sub->klass = &struct_reader_class;
|
||||||
|
break;
|
||||||
|
case DBUS_TYPE_ARRAY:
|
||||||
|
sub->klass = &array_reader_class;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
_dbus_verbose ("recursing into type %s\n", _dbus_type_to_string (t));
|
||||||
|
#ifndef DBUS_DISABLE_CHECKS
|
||||||
|
if (t == DBUS_TYPE_INVALID)
|
||||||
|
_dbus_warn ("You can't recurse into an empty array or off the end of a message body\n");
|
||||||
|
#endif /* DBUS_DISABLE_CHECKS */
|
||||||
|
|
||||||
|
_dbus_assert_not_reached ("don't yet handle recursing into this type");
|
||||||
|
}
|
||||||
|
|
||||||
|
(* sub->klass->recurse) (sub, reader);
|
||||||
|
|
||||||
|
_dbus_verbose (" type reader %p RECURSED type_pos = %d value_pos = %d remaining sig '%s'\n",
|
||||||
|
sub, sub->type_pos, sub->value_pos,
|
||||||
|
_dbus_string_get_const_data_len (sub->type_str, sub->type_pos, 0));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Skip to the next value on this "level". e.g. the next field in a
|
* Skip to the next value on this "level". e.g. the next field in a
|
||||||
* struct, the next value in an array, the next key or value in a
|
* struct, the next value in an array, the next key or value in a
|
||||||
|
|
@ -359,115 +542,8 @@ _dbus_type_reader_next (DBusTypeReader *reader)
|
||||||
|
|
||||||
if (t == DBUS_TYPE_INVALID)
|
if (t == DBUS_TYPE_INVALID)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
if (reader->container_type == DBUS_TYPE_INVALID ||
|
|
||||||
reader->container_type == DBUS_TYPE_STRUCT)
|
|
||||||
{
|
|
||||||
switch (t)
|
|
||||||
{
|
|
||||||
case DBUS_TYPE_STRUCT:
|
|
||||||
/* Scan forward over the entire container contents */
|
|
||||||
{
|
|
||||||
DBusTypeReader sub;
|
|
||||||
|
|
||||||
/* Recurse into the struct */
|
(* reader->klass->next) (reader, t);
|
||||||
_dbus_type_reader_recurse (reader, &sub);
|
|
||||||
|
|
||||||
/* Skip everything in this subreader */
|
|
||||||
while (_dbus_type_reader_next (&sub))
|
|
||||||
{
|
|
||||||
/* nothing */;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now we are at the end of this container */
|
|
||||||
reader->type_pos = sub.type_pos;
|
|
||||||
reader->value_pos = sub.value_pos;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DBUS_TYPE_ARRAY:
|
|
||||||
{
|
|
||||||
skip_array_values (first_type_in_signature (reader->type_str,
|
|
||||||
reader->type_pos + 1),
|
|
||||||
reader->value_str, &reader->value_pos, reader->byte_order);
|
|
||||||
skip_one_complete_type (reader->type_str, &reader->type_pos);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
_dbus_marshal_skip_basic_type (reader->value_str,
|
|
||||||
t, reader->byte_order,
|
|
||||||
&reader->value_pos);
|
|
||||||
reader->type_pos += 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* for STRUCT containers we return FALSE at the end of the struct,
|
|
||||||
* for INVALID we return FALSE at the end of the signature.
|
|
||||||
* In both cases we arrange for get_current_type() to return INVALID
|
|
||||||
* which is defined to happen iff we're at the end (no more next())
|
|
||||||
*/
|
|
||||||
if (reader->container_type == DBUS_TYPE_STRUCT)
|
|
||||||
{
|
|
||||||
t = _dbus_string_get_byte (reader->type_str, reader->type_pos);
|
|
||||||
if (t == DBUS_STRUCT_END_CHAR)
|
|
||||||
{
|
|
||||||
reader->type_pos += 1;
|
|
||||||
reader->u.strct.finished = TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (reader->container_type == DBUS_TYPE_ARRAY)
|
|
||||||
{
|
|
||||||
/* Skip one array element */
|
|
||||||
int end_pos;
|
|
||||||
|
|
||||||
end_pos = reader->u.array.start_pos + reader->u.array.len;
|
|
||||||
|
|
||||||
_dbus_assert (reader->value_pos < end_pos);
|
|
||||||
_dbus_assert (reader->value_pos >= reader->u.array.start_pos);
|
|
||||||
|
|
||||||
if (reader->u.array.element_type == DBUS_TYPE_STRUCT)
|
|
||||||
{
|
|
||||||
DBusTypeReader sub;
|
|
||||||
|
|
||||||
/* Recurse into the struct */
|
|
||||||
_dbus_type_reader_recurse (reader, &sub);
|
|
||||||
|
|
||||||
/* Skip everything in this element */
|
|
||||||
while (_dbus_type_reader_next (&sub))
|
|
||||||
{
|
|
||||||
/* nothing */;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now we are at the end of this element */
|
|
||||||
reader->value_pos = sub.value_pos;
|
|
||||||
}
|
|
||||||
else if (reader->u.array.element_type == DBUS_TYPE_ARRAY)
|
|
||||||
{
|
|
||||||
skip_array_values (first_type_in_signature (reader->type_str,
|
|
||||||
reader->type_pos + 1),
|
|
||||||
reader->value_str, &reader->value_pos, reader->byte_order);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_dbus_marshal_skip_basic_type (reader->value_str,
|
|
||||||
t, reader->byte_order,
|
|
||||||
&reader->value_pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
_dbus_assert (reader->value_pos <= end_pos);
|
|
||||||
|
|
||||||
if (reader->value_pos == end_pos)
|
|
||||||
{
|
|
||||||
skip_one_complete_type (reader->type_str,
|
|
||||||
&reader->type_pos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_dbus_assert_not_reached ("reader->container_type should not be set to this");
|
|
||||||
}
|
|
||||||
|
|
||||||
_dbus_verbose (" type reader %p END next() type_pos = %d value_pos = %d remaining sig '%s' current_type = %s\n",
|
_dbus_verbose (" type reader %p END next() type_pos = %d value_pos = %d remaining sig '%s' current_type = %s\n",
|
||||||
reader, reader->type_pos, reader->value_pos,
|
reader, reader->type_pos, reader->value_pos,
|
||||||
|
|
|
||||||
|
|
@ -31,23 +31,10 @@
|
||||||
#error "config.h not included here"
|
#error "config.h not included here"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Notes on my plan to implement this:
|
typedef struct DBusTypeReader DBusTypeReader;
|
||||||
* - also have DBusTypeWriter (heh)
|
typedef struct DBusTypeWriter DBusTypeWriter;
|
||||||
* - TypeReader has accessors for:
|
typedef struct DBusTypeReaderClass DBusTypeReaderClass;
|
||||||
* . basic type
|
typedef struct DBusTypeWriterClass DBusTypeWriterClass;
|
||||||
* . 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
|
struct DBusTypeReader
|
||||||
{
|
{
|
||||||
|
|
@ -57,8 +44,7 @@ struct DBusTypeReader
|
||||||
const DBusString *value_str;
|
const DBusString *value_str;
|
||||||
int value_pos;
|
int value_pos;
|
||||||
|
|
||||||
/* Hmm - it might be cleaner to do TypeReaderClass *vtable for container type */
|
const DBusTypeReaderClass *klass;
|
||||||
int container_type;
|
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
struct {
|
struct {
|
||||||
|
|
@ -78,8 +64,6 @@ struct DBusTypeReader
|
||||||
} u;
|
} u;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct DBusTypeReader DBusTypeReader;
|
|
||||||
|
|
||||||
struct DBusTypeWriter
|
struct DBusTypeWriter
|
||||||
{
|
{
|
||||||
int byte_order;
|
int byte_order;
|
||||||
|
|
@ -90,6 +74,7 @@ struct DBusTypeWriter
|
||||||
|
|
||||||
dbus_uint32_t inside_array : 1;
|
dbus_uint32_t inside_array : 1;
|
||||||
|
|
||||||
|
/* const DBusTypeWriterClass *klass; */
|
||||||
int container_type;
|
int container_type;
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
|
|
@ -107,8 +92,6 @@ struct DBusTypeWriter
|
||||||
} u;
|
} u;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct DBusTypeWriter DBusTypeWriter;
|
|
||||||
|
|
||||||
void _dbus_type_reader_init (DBusTypeReader *reader,
|
void _dbus_type_reader_init (DBusTypeReader *reader,
|
||||||
int byte_order,
|
int byte_order,
|
||||||
const DBusString *type_str,
|
const DBusString *type_str,
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue