mirror of
https://gitlab.freedesktop.org/dbus/dbus.git
synced 2026-04-21 14:40:47 +02:00
2005-01-28 Havoc Pennington <hp@redhat.com>
* doc/dbus-specification.xml: update to describe 16-bit types and dict entries * dbus/dbus-marshal-basic.c (_dbus_unpack_uint16): fix broken assertion * dbus/dbus-protocol.h (DBUS_TYPE_DICT_ENTRY): add DICT_ENTRY as a type * dbus/dbus-marshal-recursive.c: implement
This commit is contained in:
parent
3ed9db546e
commit
c7816d45e8
11 changed files with 543 additions and 45 deletions
13
ChangeLog
13
ChangeLog
|
|
@ -1,3 +1,16 @@
|
|||
2005-01-28 Havoc Pennington <hp@redhat.com>
|
||||
|
||||
* doc/dbus-specification.xml: update to describe 16-bit types and
|
||||
dict entries
|
||||
|
||||
* dbus/dbus-marshal-basic.c (_dbus_unpack_uint16): fix broken
|
||||
assertion
|
||||
|
||||
* dbus/dbus-protocol.h (DBUS_TYPE_DICT_ENTRY): add DICT_ENTRY as a
|
||||
type
|
||||
|
||||
* dbus/dbus-marshal-recursive.c: implement
|
||||
|
||||
2005-01-27 Havoc Pennington <hp@redhat.com>
|
||||
|
||||
* dbus/dbus-arch-deps.h.in: add 16/32-bit types
|
||||
|
|
|
|||
|
|
@ -172,7 +172,7 @@ dbus_uint16_t
|
|||
_dbus_unpack_uint16 (int byte_order,
|
||||
const unsigned char *data)
|
||||
{
|
||||
_dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
|
||||
_dbus_assert (_DBUS_ALIGN_ADDRESS (data, 2) == data);
|
||||
|
||||
if (byte_order == DBUS_LITTLE_ENDIAN)
|
||||
return DBUS_UINT16_FROM_LE (*(dbus_uint16_t*)data);
|
||||
|
|
@ -1245,8 +1245,10 @@ _dbus_type_get_alignment (int typecode)
|
|||
* and it's simpler to just always align structs to 8;
|
||||
* we want the amount of padding in a struct of a given
|
||||
* type to be predictable, not location-dependent.
|
||||
* DICT_ENTRY is always the same as struct.
|
||||
*/
|
||||
case DBUS_TYPE_STRUCT:
|
||||
case DBUS_TYPE_DICT_ENTRY:
|
||||
return 8;
|
||||
|
||||
default:
|
||||
|
|
@ -1283,6 +1285,7 @@ _dbus_type_is_valid (int typecode)
|
|||
case DBUS_TYPE_SIGNATURE:
|
||||
case DBUS_TYPE_ARRAY:
|
||||
case DBUS_TYPE_STRUCT:
|
||||
case DBUS_TYPE_DICT_ENTRY:
|
||||
case DBUS_TYPE_VARIANT:
|
||||
return TRUE;
|
||||
|
||||
|
|
@ -1294,6 +1297,7 @@ _dbus_type_is_valid (int typecode)
|
|||
/** macro that checks whether a typecode is a container type */
|
||||
#define TYPE_IS_CONTAINER(typecode) \
|
||||
((typecode) == DBUS_TYPE_STRUCT || \
|
||||
(typecode) == DBUS_TYPE_DICT_ENTRY || \
|
||||
(typecode) == DBUS_TYPE_VARIANT || \
|
||||
(typecode) == DBUS_TYPE_ARRAY)
|
||||
|
||||
|
|
@ -1403,6 +1407,8 @@ _dbus_type_to_string (int typecode)
|
|||
return "signature";
|
||||
case DBUS_TYPE_STRUCT:
|
||||
return "struct";
|
||||
case DBUS_TYPE_DICT_ENTRY:
|
||||
return "dict_entry";
|
||||
case DBUS_TYPE_ARRAY:
|
||||
return "array";
|
||||
case DBUS_TYPE_VARIANT:
|
||||
|
|
@ -1411,6 +1417,10 @@ _dbus_type_to_string (int typecode)
|
|||
return "begin_struct";
|
||||
case DBUS_STRUCT_END_CHAR:
|
||||
return "end_struct";
|
||||
case DBUS_DICT_ENTRY_BEGIN_CHAR:
|
||||
return "begin_dict_entry";
|
||||
case DBUS_DICT_ENTRY_END_CHAR:
|
||||
return "end_dict_entry";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
|
|
@ -1559,8 +1569,14 @@ _dbus_first_type_in_signature (const DBusString *str,
|
|||
|
||||
if (t == DBUS_STRUCT_BEGIN_CHAR)
|
||||
return DBUS_TYPE_STRUCT;
|
||||
else if (t == DBUS_DICT_ENTRY_BEGIN_CHAR)
|
||||
return DBUS_TYPE_DICT_ENTRY;
|
||||
else
|
||||
return t;
|
||||
{
|
||||
_dbus_assert (t != DBUS_STRUCT_END_CHAR);
|
||||
_dbus_assert (t != DBUS_DICT_ENTRY_END_CHAR);
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
|
|
|||
|
|
@ -175,6 +175,7 @@ byteswap_body_helper (DBusTypeReader *reader,
|
|||
break;
|
||||
|
||||
case DBUS_TYPE_STRUCT:
|
||||
case DBUS_TYPE_DICT_ENTRY:
|
||||
{
|
||||
DBusTypeReader sub;
|
||||
|
||||
|
|
|
|||
|
|
@ -526,6 +526,19 @@ static dbus_bool_t struct_set_value (TestTypeNode *node,
|
|||
int seed);
|
||||
static dbus_bool_t struct_build_signature (TestTypeNode *node,
|
||||
DBusString *str);
|
||||
static dbus_bool_t dict_write_value (TestTypeNode *node,
|
||||
DataBlock *block,
|
||||
DBusTypeWriter *writer,
|
||||
int seed);
|
||||
static dbus_bool_t dict_read_value (TestTypeNode *node,
|
||||
DBusTypeReader *reader,
|
||||
int seed);
|
||||
static dbus_bool_t dict_set_value (TestTypeNode *node,
|
||||
DBusTypeReader *reader,
|
||||
DBusTypeReader *realign_root,
|
||||
int seed);
|
||||
static dbus_bool_t dict_build_signature (TestTypeNode *node,
|
||||
DBusString *str);
|
||||
static dbus_bool_t array_write_value (TestTypeNode *node,
|
||||
DataBlock *block,
|
||||
DBusTypeWriter *writer,
|
||||
|
|
@ -553,6 +566,7 @@ static dbus_bool_t variant_set_value (TestTypeNode *node,
|
|||
static void container_destroy (TestTypeNode *node);
|
||||
|
||||
|
||||
|
||||
static const TestTypeNodeClass int16_class = {
|
||||
DBUS_TYPE_INT16,
|
||||
sizeof (TestTypeNode),
|
||||
|
|
@ -793,6 +807,20 @@ static const TestTypeNodeClass struct_2_class = {
|
|||
NULL
|
||||
};
|
||||
|
||||
static const TestTypeNodeClass dict_1_class = {
|
||||
DBUS_TYPE_ARRAY, /* this is correct, a dict is an array of dict entry */
|
||||
sizeof (TestTypeNodeContainer),
|
||||
1, /* number of entries */
|
||||
NULL,
|
||||
container_destroy,
|
||||
dict_write_value,
|
||||
dict_read_value,
|
||||
dict_set_value,
|
||||
dict_build_signature,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
static dbus_bool_t arrays_write_fixed_in_blocks = FALSE;
|
||||
|
||||
static const TestTypeNodeClass array_0_class = {
|
||||
|
|
@ -892,7 +920,8 @@ container_nodes[] = {
|
|||
&struct_2_class,
|
||||
&array_0_class,
|
||||
&array_2_class,
|
||||
&variant_class
|
||||
&variant_class,
|
||||
&dict_1_class /* last since we want struct and array before it */
|
||||
/* array_9_class is omitted on purpose, it's too slow;
|
||||
* we only use it in one hardcoded test below
|
||||
*/
|
||||
|
|
@ -2157,8 +2186,8 @@ int16_read_multi (TestTypeNode *node,
|
|||
_dbus_assert (n_elements == count);
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
_dbus_assert (((int)_dbus_unpack_uint16 (reader->byte_order,
|
||||
(const unsigned char*)values + (i * 2))) ==
|
||||
_dbus_assert (((dbus_int16_t)_dbus_unpack_uint16 (reader->byte_order,
|
||||
(const unsigned char*)values + (i * 2))) ==
|
||||
int16_from_seed (seed + i));
|
||||
|
||||
return TRUE;
|
||||
|
|
@ -3298,6 +3327,233 @@ variant_set_value (TestTypeNode *node,
|
|||
return variant_read_or_set_value (node, reader, realign_root, seed);
|
||||
}
|
||||
|
||||
static dbus_bool_t
|
||||
dict_write_value (TestTypeNode *node,
|
||||
DataBlock *block,
|
||||
DBusTypeWriter *writer,
|
||||
int seed)
|
||||
{
|
||||
TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
|
||||
DataBlockState saved;
|
||||
DBusTypeWriter sub;
|
||||
DBusString entry_value_signature;
|
||||
DBusString dict_entry_signature;
|
||||
int i;
|
||||
int n_entries;
|
||||
int entry_value_type;
|
||||
TestTypeNode *child;
|
||||
|
||||
n_entries = node->klass->subclass_detail;
|
||||
|
||||
_dbus_assert (container->children != NULL);
|
||||
|
||||
data_block_save (block, &saved);
|
||||
|
||||
if (!_dbus_string_init (&entry_value_signature))
|
||||
return FALSE;
|
||||
|
||||
if (!_dbus_string_init (&dict_entry_signature))
|
||||
{
|
||||
_dbus_string_free (&entry_value_signature);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
child = _dbus_list_get_first (&container->children);
|
||||
|
||||
if (!node_build_signature (child,
|
||||
&entry_value_signature))
|
||||
goto oom;
|
||||
|
||||
if (!_dbus_string_append (&dict_entry_signature,
|
||||
DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
|
||||
DBUS_TYPE_INT32_AS_STRING))
|
||||
goto oom;
|
||||
|
||||
if (!_dbus_string_copy (&entry_value_signature, 0,
|
||||
&dict_entry_signature,
|
||||
_dbus_string_get_length (&dict_entry_signature)))
|
||||
goto oom;
|
||||
|
||||
if (!_dbus_string_append_byte (&dict_entry_signature,
|
||||
DBUS_DICT_ENTRY_END_CHAR))
|
||||
goto oom;
|
||||
|
||||
entry_value_type = _dbus_first_type_in_signature (&entry_value_signature, 0);
|
||||
|
||||
if (!_dbus_type_writer_recurse (writer, DBUS_TYPE_ARRAY,
|
||||
&dict_entry_signature, 0,
|
||||
&sub))
|
||||
goto oom;
|
||||
|
||||
i = 0;
|
||||
while (i < n_entries)
|
||||
{
|
||||
DBusTypeWriter entry_sub;
|
||||
dbus_int32_t key;
|
||||
|
||||
if (!_dbus_type_writer_recurse (&sub, DBUS_TYPE_DICT_ENTRY,
|
||||
NULL, 0,
|
||||
&entry_sub))
|
||||
goto oom;
|
||||
|
||||
key = int32_from_seed (seed + i);
|
||||
|
||||
if (!_dbus_type_writer_write_basic (&entry_sub,
|
||||
DBUS_TYPE_INT32,
|
||||
&key))
|
||||
goto oom;
|
||||
|
||||
if (!node_write_value (child, block, &entry_sub, seed + i))
|
||||
goto oom;
|
||||
|
||||
if (!_dbus_type_writer_unrecurse (&sub, &entry_sub))
|
||||
goto oom;
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
if (!_dbus_type_writer_unrecurse (writer, &sub))
|
||||
goto oom;
|
||||
|
||||
_dbus_string_free (&entry_value_signature);
|
||||
_dbus_string_free (&dict_entry_signature);
|
||||
return TRUE;
|
||||
|
||||
oom:
|
||||
data_block_restore (block, &saved);
|
||||
_dbus_string_free (&entry_value_signature);
|
||||
_dbus_string_free (&dict_entry_signature);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static dbus_bool_t
|
||||
dict_read_or_set_value (TestTypeNode *node,
|
||||
DBusTypeReader *reader,
|
||||
DBusTypeReader *realign_root,
|
||||
int seed)
|
||||
{
|
||||
TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
|
||||
DBusTypeReader sub;
|
||||
int i;
|
||||
int n_entries;
|
||||
TestTypeNode *child;
|
||||
|
||||
n_entries = node->klass->subclass_detail;
|
||||
|
||||
check_expected_type (reader, DBUS_TYPE_ARRAY);
|
||||
|
||||
child = _dbus_list_get_first (&container->children);
|
||||
|
||||
if (n_entries > 0)
|
||||
{
|
||||
_dbus_type_reader_recurse (reader, &sub);
|
||||
|
||||
check_expected_type (&sub, DBUS_TYPE_DICT_ENTRY);
|
||||
|
||||
i = 0;
|
||||
while (i < n_entries)
|
||||
{
|
||||
DBusTypeReader entry_sub;
|
||||
|
||||
check_expected_type (&sub, DBUS_TYPE_DICT_ENTRY);
|
||||
|
||||
_dbus_type_reader_recurse (&sub, &entry_sub);
|
||||
|
||||
if (realign_root == NULL)
|
||||
{
|
||||
dbus_int32_t v;
|
||||
|
||||
check_expected_type (&entry_sub, DBUS_TYPE_INT32);
|
||||
|
||||
_dbus_type_reader_read_basic (&entry_sub,
|
||||
(dbus_int32_t*) &v);
|
||||
|
||||
_dbus_assert (v == int32_from_seed (seed + i));
|
||||
|
||||
NEXT_EXPECTING_TRUE (&entry_sub);
|
||||
|
||||
if (!node_read_value (child, &entry_sub, seed + i))
|
||||
return FALSE;
|
||||
|
||||
NEXT_EXPECTING_FALSE (&entry_sub);
|
||||
}
|
||||
else
|
||||
{
|
||||
dbus_int32_t v;
|
||||
|
||||
v = int32_from_seed (seed + i);
|
||||
|
||||
if (!_dbus_type_reader_set_basic (&entry_sub,
|
||||
&v,
|
||||
realign_root))
|
||||
return FALSE;
|
||||
|
||||
NEXT_EXPECTING_TRUE (&entry_sub);
|
||||
|
||||
if (!node_set_value (child, &entry_sub, realign_root, seed + i))
|
||||
return FALSE;
|
||||
|
||||
NEXT_EXPECTING_FALSE (&entry_sub);
|
||||
}
|
||||
|
||||
if (i == (n_entries - 1))
|
||||
NEXT_EXPECTING_FALSE (&sub);
|
||||
else
|
||||
NEXT_EXPECTING_TRUE (&sub);
|
||||
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static dbus_bool_t
|
||||
dict_read_value (TestTypeNode *node,
|
||||
DBusTypeReader *reader,
|
||||
int seed)
|
||||
{
|
||||
return dict_read_or_set_value (node, reader, NULL, seed);
|
||||
}
|
||||
|
||||
static dbus_bool_t
|
||||
dict_set_value (TestTypeNode *node,
|
||||
DBusTypeReader *reader,
|
||||
DBusTypeReader *realign_root,
|
||||
int seed)
|
||||
{
|
||||
return dict_read_or_set_value (node, reader, realign_root, seed);
|
||||
}
|
||||
|
||||
static dbus_bool_t
|
||||
dict_build_signature (TestTypeNode *node,
|
||||
DBusString *str)
|
||||
{
|
||||
TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
|
||||
int orig_len;
|
||||
|
||||
orig_len = _dbus_string_get_length (str);
|
||||
|
||||
if (!_dbus_string_append_byte (str, DBUS_TYPE_ARRAY))
|
||||
goto oom;
|
||||
|
||||
if (!_dbus_string_append (str, DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING DBUS_TYPE_INT32_AS_STRING))
|
||||
goto oom;
|
||||
|
||||
if (!node_build_signature (_dbus_list_get_first (&container->children),
|
||||
str))
|
||||
goto oom;
|
||||
|
||||
if (!_dbus_string_append_byte (str, DBUS_DICT_ENTRY_END_CHAR))
|
||||
goto oom;
|
||||
|
||||
return TRUE;
|
||||
|
||||
oom:
|
||||
_dbus_string_set_length (str, orig_len);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
container_destroy (TestTypeNode *node)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -159,24 +159,26 @@ base_reader_recurse (DBusTypeReader *sub,
|
|||
}
|
||||
|
||||
static void
|
||||
struct_types_only_reader_recurse (DBusTypeReader *sub,
|
||||
DBusTypeReader *parent)
|
||||
struct_or_dict_entry_types_only_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) == DBUS_STRUCT_BEGIN_CHAR ||
|
||||
_dbus_string_get_byte (sub->type_str,
|
||||
sub->type_pos) == DBUS_DICT_ENTRY_BEGIN_CHAR);
|
||||
|
||||
sub->type_pos += 1;
|
||||
}
|
||||
|
||||
static void
|
||||
struct_reader_recurse (DBusTypeReader *sub,
|
||||
DBusTypeReader *parent)
|
||||
struct_or_dict_entry_reader_recurse (DBusTypeReader *sub,
|
||||
DBusTypeReader *parent)
|
||||
{
|
||||
struct_types_only_reader_recurse (sub, parent);
|
||||
struct_or_dict_entry_types_only_reader_recurse (sub, parent);
|
||||
|
||||
/* struct has 8 byte alignment */
|
||||
/* struct and dict entry have 8 byte alignment */
|
||||
sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 8);
|
||||
}
|
||||
|
||||
|
|
@ -321,11 +323,13 @@ skip_one_complete_type (const DBusString *type_str,
|
|||
p = start + *type_pos;
|
||||
|
||||
_dbus_assert (*p != DBUS_STRUCT_END_CHAR);
|
||||
_dbus_assert (*p != DBUS_DICT_ENTRY_END_CHAR);
|
||||
|
||||
while (*p == DBUS_TYPE_ARRAY)
|
||||
++p;
|
||||
|
||||
_dbus_assert (*p != DBUS_STRUCT_END_CHAR);
|
||||
_dbus_assert (*p != DBUS_DICT_ENTRY_END_CHAR);
|
||||
|
||||
if (*p == DBUS_STRUCT_BEGIN_CHAR)
|
||||
{
|
||||
|
|
@ -354,6 +358,33 @@ skip_one_complete_type (const DBusString *type_str,
|
|||
}
|
||||
}
|
||||
}
|
||||
else if (*p == DBUS_DICT_ENTRY_BEGIN_CHAR)
|
||||
{
|
||||
int depth;
|
||||
|
||||
depth = 1;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
_dbus_assert (*p != DBUS_TYPE_INVALID);
|
||||
|
||||
++p;
|
||||
|
||||
_dbus_assert (*p != DBUS_TYPE_INVALID);
|
||||
|
||||
if (*p == DBUS_DICT_ENTRY_BEGIN_CHAR)
|
||||
depth += 1;
|
||||
else if (*p == DBUS_DICT_ENTRY_END_CHAR)
|
||||
{
|
||||
depth -= 1;
|
||||
if (depth == 0)
|
||||
{
|
||||
++p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
++p;
|
||||
|
|
@ -381,6 +412,7 @@ base_reader_next (DBusTypeReader *reader,
|
|||
{
|
||||
switch (current_type)
|
||||
{
|
||||
case DBUS_TYPE_DICT_ENTRY:
|
||||
case DBUS_TYPE_STRUCT:
|
||||
case DBUS_TYPE_VARIANT:
|
||||
/* Scan forward over the entire container contents */
|
||||
|
|
@ -460,6 +492,27 @@ struct_reader_next (DBusTypeReader *reader,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dict_entry_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_DICT_ENTRY_END_CHAR)
|
||||
{
|
||||
reader->type_pos += 1;
|
||||
reader->finished = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
array_types_only_reader_next (DBusTypeReader *reader,
|
||||
int current_type)
|
||||
|
|
@ -495,6 +548,7 @@ array_reader_next (DBusTypeReader *reader,
|
|||
switch (_dbus_first_type_in_signature (reader->type_str,
|
||||
reader->type_pos))
|
||||
{
|
||||
case DBUS_TYPE_DICT_ENTRY:
|
||||
case DBUS_TYPE_STRUCT:
|
||||
case DBUS_TYPE_VARIANT:
|
||||
{
|
||||
|
|
@ -582,7 +636,7 @@ static const DBusTypeReaderClass body_types_only_reader_class = {
|
|||
static const DBusTypeReaderClass struct_reader_class = {
|
||||
"struct", 2,
|
||||
FALSE,
|
||||
struct_reader_recurse,
|
||||
struct_or_dict_entry_reader_recurse,
|
||||
NULL,
|
||||
struct_reader_next,
|
||||
NULL
|
||||
|
|
@ -591,14 +645,32 @@ static const DBusTypeReaderClass struct_reader_class = {
|
|||
static const DBusTypeReaderClass struct_types_only_reader_class = {
|
||||
"struct types", 3,
|
||||
TRUE,
|
||||
struct_types_only_reader_recurse,
|
||||
struct_or_dict_entry_types_only_reader_recurse,
|
||||
NULL,
|
||||
struct_reader_next,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const DBusTypeReaderClass dict_entry_reader_class = {
|
||||
"dict_entry", 4,
|
||||
FALSE,
|
||||
struct_or_dict_entry_reader_recurse,
|
||||
NULL,
|
||||
dict_entry_reader_next,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const DBusTypeReaderClass dict_entry_types_only_reader_class = {
|
||||
"dict_entry types", 5,
|
||||
TRUE,
|
||||
struct_or_dict_entry_types_only_reader_recurse,
|
||||
NULL,
|
||||
dict_entry_reader_next,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const DBusTypeReaderClass array_reader_class = {
|
||||
"array", 4,
|
||||
"array", 6,
|
||||
FALSE,
|
||||
array_reader_recurse,
|
||||
array_reader_check_finished,
|
||||
|
|
@ -607,7 +679,7 @@ static const DBusTypeReaderClass array_reader_class = {
|
|||
};
|
||||
|
||||
static const DBusTypeReaderClass array_types_only_reader_class = {
|
||||
"array types", 5,
|
||||
"array types", 7,
|
||||
TRUE,
|
||||
array_types_only_reader_recurse,
|
||||
NULL,
|
||||
|
|
@ -616,7 +688,7 @@ static const DBusTypeReaderClass array_types_only_reader_class = {
|
|||
};
|
||||
|
||||
static const DBusTypeReaderClass variant_reader_class = {
|
||||
"variant", 6,
|
||||
"variant", 8,
|
||||
FALSE,
|
||||
variant_reader_recurse,
|
||||
NULL,
|
||||
|
|
@ -630,6 +702,8 @@ all_reader_classes[] = {
|
|||
&body_types_only_reader_class,
|
||||
&struct_reader_class,
|
||||
&struct_types_only_reader_class,
|
||||
&dict_entry_reader_class,
|
||||
&dict_entry_types_only_reader_class,
|
||||
&array_reader_class,
|
||||
&array_types_only_reader_class,
|
||||
&variant_reader_class
|
||||
|
|
@ -798,11 +872,13 @@ _dbus_type_reader_get_current_type (const DBusTypeReader *reader)
|
|||
t = DBUS_TYPE_INVALID;
|
||||
else
|
||||
t = _dbus_first_type_in_signature (reader->type_str,
|
||||
reader->type_pos);
|
||||
reader->type_pos);
|
||||
|
||||
_dbus_assert (t != DBUS_STRUCT_END_CHAR);
|
||||
_dbus_assert (t != DBUS_STRUCT_BEGIN_CHAR);
|
||||
|
||||
_dbus_assert (t != DBUS_DICT_ENTRY_END_CHAR);
|
||||
_dbus_assert (t != DBUS_DICT_ENTRY_BEGIN_CHAR);
|
||||
|
||||
#if 0
|
||||
_dbus_verbose (" type reader %p current type_pos = %d type = %s\n",
|
||||
reader, reader->type_pos,
|
||||
|
|
@ -989,6 +1065,12 @@ _dbus_type_reader_recurse (DBusTypeReader *reader,
|
|||
else
|
||||
sub->klass = &struct_reader_class;
|
||||
break;
|
||||
case DBUS_TYPE_DICT_ENTRY:
|
||||
if (reader->klass->types_only)
|
||||
sub->klass = &dict_entry_types_only_reader_class;
|
||||
else
|
||||
sub->klass = &dict_entry_reader_class;
|
||||
break;
|
||||
case DBUS_TYPE_ARRAY:
|
||||
if (reader->klass->types_only)
|
||||
sub->klass = &array_types_only_reader_class;
|
||||
|
|
@ -1734,11 +1816,12 @@ write_or_verify_typecode (DBusTypeWriter *writer,
|
|||
}
|
||||
|
||||
static dbus_bool_t
|
||||
writer_recurse_struct (DBusTypeWriter *writer,
|
||||
const DBusString *contained_type,
|
||||
int contained_type_start,
|
||||
int contained_type_len,
|
||||
DBusTypeWriter *sub)
|
||||
writer_recurse_struct_or_dict_entry (DBusTypeWriter *writer,
|
||||
int begin_char,
|
||||
const DBusString *contained_type,
|
||||
int contained_type_start,
|
||||
int contained_type_len,
|
||||
DBusTypeWriter *sub)
|
||||
{
|
||||
/* FIXME right now contained_type is ignored; we could probably
|
||||
* almost trivially fix the code so if it's present we
|
||||
|
|
@ -1752,7 +1835,7 @@ writer_recurse_struct (DBusTypeWriter *writer,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
if (!write_or_verify_typecode (sub, DBUS_STRUCT_BEGIN_CHAR))
|
||||
if (!write_or_verify_typecode (sub, begin_char))
|
||||
_dbus_assert_not_reached ("failed to insert struct typecode after prealloc");
|
||||
|
||||
if (writer->enabled)
|
||||
|
|
@ -2027,9 +2110,18 @@ _dbus_type_writer_recurse_contained_len (DBusTypeWriter *writer,
|
|||
switch (container_type)
|
||||
{
|
||||
case DBUS_TYPE_STRUCT:
|
||||
return writer_recurse_struct (writer,
|
||||
contained_type, contained_type_start, contained_type_len,
|
||||
sub);
|
||||
return writer_recurse_struct_or_dict_entry (writer,
|
||||
DBUS_STRUCT_BEGIN_CHAR,
|
||||
contained_type,
|
||||
contained_type_start, contained_type_len,
|
||||
sub);
|
||||
break;
|
||||
case DBUS_TYPE_DICT_ENTRY:
|
||||
return writer_recurse_struct_or_dict_entry (writer,
|
||||
DBUS_DICT_ENTRY_BEGIN_CHAR,
|
||||
contained_type,
|
||||
contained_type_start, contained_type_len,
|
||||
sub);
|
||||
break;
|
||||
case DBUS_TYPE_ARRAY:
|
||||
return writer_recurse_array (writer,
|
||||
|
|
@ -2151,6 +2243,11 @@ _dbus_type_writer_unrecurse (DBusTypeWriter *writer,
|
|||
if (!write_or_verify_typecode (sub, DBUS_STRUCT_END_CHAR))
|
||||
return FALSE;
|
||||
}
|
||||
else if (sub->container_type == DBUS_TYPE_DICT_ENTRY)
|
||||
{
|
||||
if (!write_or_verify_typecode (sub, DBUS_DICT_ENTRY_END_CHAR))
|
||||
return FALSE;
|
||||
}
|
||||
else if (sub->container_type == DBUS_TYPE_ARRAY)
|
||||
{
|
||||
if (sub->u.array.len_pos >= 0) /* len_pos == -1 if we weren't enabled when we passed it */
|
||||
|
|
@ -2217,11 +2314,16 @@ _dbus_type_writer_unrecurse (DBusTypeWriter *writer,
|
|||
* parent makes no difference since there's only one value
|
||||
* and we just finished writing it and won't use type_pos again
|
||||
* writer->type_pos should remain as-is
|
||||
*
|
||||
*
|
||||
* For all these, DICT_ENTRY is the same as STRUCT
|
||||
*/
|
||||
if (writer->type_str != NULL)
|
||||
{
|
||||
if (sub->container_type == DBUS_TYPE_STRUCT &&
|
||||
if ((sub->container_type == DBUS_TYPE_STRUCT ||
|
||||
sub->container_type == DBUS_TYPE_DICT_ENTRY) &&
|
||||
(writer->container_type == DBUS_TYPE_STRUCT ||
|
||||
writer->container_type == DBUS_TYPE_DICT_ENTRY ||
|
||||
writer->container_type == DBUS_TYPE_INVALID))
|
||||
{
|
||||
/* Advance the parent to the next struct field */
|
||||
|
|
|
|||
|
|
@ -40,6 +40,10 @@
|
|||
* The range passed in should NOT include the terminating
|
||||
* nul/DBUS_TYPE_INVALID.
|
||||
*
|
||||
* @todo verify that dict entries have exactly two fields
|
||||
*
|
||||
* @todo require that dict entries are in an array
|
||||
*
|
||||
* @param type_str the string
|
||||
* @param type_pos where the typecodes start
|
||||
* @param len length of typecodes
|
||||
|
|
@ -55,6 +59,7 @@ _dbus_validate_signature_with_reason (const DBusString *type_str,
|
|||
int last;
|
||||
int struct_depth;
|
||||
int array_depth;
|
||||
int dict_entry_depth;
|
||||
|
||||
_dbus_assert (type_str != NULL);
|
||||
_dbus_assert (type_pos < _DBUS_INT32_MAX - len);
|
||||
|
|
@ -68,6 +73,7 @@ _dbus_validate_signature_with_reason (const DBusString *type_str,
|
|||
end = _dbus_string_get_const_data_len (type_str, type_pos + len, 0);
|
||||
struct_depth = 0;
|
||||
array_depth = 0;
|
||||
dict_entry_depth = 0;
|
||||
last = DBUS_TYPE_INVALID;
|
||||
|
||||
while (p != end)
|
||||
|
|
@ -112,7 +118,28 @@ _dbus_validate_signature_with_reason (const DBusString *type_str,
|
|||
struct_depth -= 1;
|
||||
break;
|
||||
|
||||
case DBUS_TYPE_STRUCT: /* doesn't appear in signatures */
|
||||
case DBUS_DICT_ENTRY_BEGIN_CHAR:
|
||||
if (last != DBUS_TYPE_ARRAY)
|
||||
return DBUS_INVALID_DICT_ENTRY_NOT_INSIDE_ARRAY;
|
||||
|
||||
dict_entry_depth += 1;
|
||||
|
||||
if (dict_entry_depth > DBUS_MAXIMUM_TYPE_RECURSION_DEPTH)
|
||||
return DBUS_INVALID_EXCEEDED_MAXIMUM_DICT_ENTRY_RECURSION;
|
||||
break;
|
||||
|
||||
case DBUS_DICT_ENTRY_END_CHAR:
|
||||
if (dict_entry_depth == 0)
|
||||
return DBUS_INVALID_DICT_ENTRY_ENDED_BUT_NOT_STARTED;
|
||||
|
||||
if (last == DBUS_DICT_ENTRY_BEGIN_CHAR)
|
||||
return DBUS_INVALID_DICT_ENTRY_HAS_NO_FIELDS;
|
||||
|
||||
dict_entry_depth -= 1;
|
||||
break;
|
||||
|
||||
case DBUS_TYPE_STRUCT: /* doesn't appear in signatures */
|
||||
case DBUS_TYPE_DICT_ENTRY: /* ditto */
|
||||
default:
|
||||
return DBUS_INVALID_UNKNOWN_TYPECODE;
|
||||
}
|
||||
|
|
@ -130,6 +157,9 @@ _dbus_validate_signature_with_reason (const DBusString *type_str,
|
|||
if (struct_depth > 0)
|
||||
return DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED;
|
||||
|
||||
if (dict_entry_depth > 0)
|
||||
return DBUS_INVALID_DICT_ENTRY_STARTED_BUT_NOT_ENDED;
|
||||
|
||||
return DBUS_VALID;
|
||||
}
|
||||
|
||||
|
|
@ -377,6 +407,7 @@ validate_body_helper (DBusTypeReader *reader,
|
|||
}
|
||||
break;
|
||||
|
||||
case DBUS_TYPE_DICT_ENTRY:
|
||||
case DBUS_TYPE_STRUCT:
|
||||
{
|
||||
DBusTypeReader sub;
|
||||
|
|
|
|||
|
|
@ -100,7 +100,14 @@ typedef enum
|
|||
DBUS_INVALID_VARIANT_SIGNATURE_SPECIFIES_MULTIPLE_VALUES = 46,
|
||||
DBUS_INVALID_VARIANT_SIGNATURE_MISSING_NUL = 47,
|
||||
DBUS_INVALID_STRING_MISSING_NUL = 48,
|
||||
DBUS_INVALID_SIGNATURE_MISSING_NUL = 49
|
||||
DBUS_INVALID_SIGNATURE_MISSING_NUL = 49,
|
||||
DBUS_INVALID_EXCEEDED_MAXIMUM_DICT_ENTRY_RECURSION = 50,
|
||||
DBUS_INVALID_DICT_ENTRY_ENDED_BUT_NOT_STARTED = 51,
|
||||
DBUS_INVALID_DICT_ENTRY_STARTED_BUT_NOT_ENDED = 52,
|
||||
DBUS_INVALID_DICT_ENTRY_HAS_NO_FIELDS = 53,
|
||||
DBUS_INVALID_DICT_ENTRY_HAS_ONLY_ONE_FIELD = 54,
|
||||
DBUS_INVALID_DICT_ENTRY_HAS_TOO_MANY_FIELDS = 55,
|
||||
DBUS_INVALID_DICT_ENTRY_NOT_INSIDE_ARRAY = 56
|
||||
} DBusValidity;
|
||||
|
||||
DBusValidity _dbus_validate_signature_with_reason (const DBusString *type_str,
|
||||
|
|
|
|||
|
|
@ -2112,10 +2112,10 @@ dbus_message_iter_append_fixed_array (DBusMessageIter *iter,
|
|||
* dbus_message_iter_close_container(). Container types are for
|
||||
* example struct, variant, and array. For variants, the
|
||||
* contained_signature should be the type of the single value inside
|
||||
* the variant. For structs, contained_signature should be #NULL; it
|
||||
* will be set to whatever types you write into the struct. For
|
||||
* arrays, contained_signature should be the type of the array
|
||||
* elements.
|
||||
* the variant. For structs and dict entries, contained_signature
|
||||
* should be #NULL; it will be set to whatever types you write into
|
||||
* the struct. For arrays, contained_signature should be the type of
|
||||
* the array elements.
|
||||
*
|
||||
* @todo If this fails due to lack of memory, the message is hosed and
|
||||
* you have to start over building the whole message.
|
||||
|
|
@ -2142,7 +2142,21 @@ dbus_message_iter_open_container (DBusMessageIter *iter,
|
|||
_dbus_return_val_if_fail (sub != NULL, FALSE);
|
||||
_dbus_return_val_if_fail ((type == DBUS_TYPE_STRUCT &&
|
||||
contained_signature == NULL) ||
|
||||
(type == DBUS_TYPE_DICT_ENTRY &&
|
||||
contained_signature == NULL) ||
|
||||
contained_signature != NULL, FALSE);
|
||||
_dbus_return_val_if_fail (type != DBUS_TYPE_DICT_ENTRY ||
|
||||
dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_ARRAY,
|
||||
FALSE);
|
||||
|
||||
#if 0
|
||||
/* FIXME this would fail if the contained_signature is a dict entry,
|
||||
* since dict entries are invalid signatures standalone (they must be in
|
||||
* an array)
|
||||
*/
|
||||
_dbus_return_val_if_fail (contained_signature == NULL ||
|
||||
_dbus_check_is_valid_signature (contained_signature));
|
||||
#endif
|
||||
|
||||
if (!_dbus_message_iter_open_signature (real))
|
||||
return FALSE;
|
||||
|
|
|
|||
|
|
@ -77,20 +77,27 @@ extern "C" {
|
|||
#define DBUS_TYPE_VARIANT ((int) 'v')
|
||||
#define DBUS_TYPE_VARIANT_AS_STRING "v"
|
||||
|
||||
/* STRUCT is sort of special since its code can't appear in a type string,
|
||||
* instead DBUS_STRUCT_BEGIN_CHAR has to appear
|
||||
/* STRUCT and DICT_ENTRY are sort of special since their codes can't
|
||||
* appear in a type string, instead
|
||||
* DBUS_STRUCT_BEGIN_CHAR/DBUS_DICT_ENTRY_BEGIN_CHAR have to appear
|
||||
*/
|
||||
#define DBUS_TYPE_STRUCT ((int) 'r')
|
||||
#define DBUS_TYPE_STRUCT_AS_STRING "r"
|
||||
#define DBUS_TYPE_DICT_ENTRY ((int) 'e')
|
||||
#define DBUS_TYPE_DICT_ENTRY_AS_STRING "e"
|
||||
|
||||
/* Does not count INVALID */
|
||||
#define DBUS_NUMBER_OF_TYPES (15)
|
||||
#define DBUS_NUMBER_OF_TYPES (16)
|
||||
|
||||
/* characters other than typecodes that appear in type signatures */
|
||||
#define DBUS_STRUCT_BEGIN_CHAR ((int) '(')
|
||||
#define DBUS_STRUCT_BEGIN_CHAR_AS_STRING "("
|
||||
#define DBUS_STRUCT_END_CHAR ((int) ')')
|
||||
#define DBUS_STRUCT_END_CHAR_AS_STRING ")"
|
||||
#define DBUS_DICT_ENTRY_BEGIN_CHAR ((int) '{')
|
||||
#define DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING "{"
|
||||
#define DBUS_DICT_ENTRY_END_CHAR ((int) '}')
|
||||
#define DBUS_DICT_ENTRY_END_CHAR_AS_STRING "}"
|
||||
|
||||
/* Max length in bytes of a bus name, interface, or member (not object
|
||||
* path, paths are unlimited). This is limited because lots of stuff
|
||||
|
|
|
|||
9
doc/TODO
9
doc/TODO
|
|
@ -36,14 +36,15 @@ Important for 1.0
|
|||
yourself; is it an error, or allowed? If allowed,
|
||||
we need to have a test for it in the test suite.
|
||||
|
||||
- array lengths should probably be returned as size_t rather than int
|
||||
(though they are kind of a pita to pass in as size_t with the
|
||||
varargs, so maybe not - what does glib do with g_object_get()?)
|
||||
|
||||
- add string array support back to append_args()
|
||||
|
||||
- validate dict entry number of fields
|
||||
|
||||
- just before 1.0, try a HAVE_INT64=0 build and be sure it runs
|
||||
|
||||
- the spec and implementation should probably require dict keys
|
||||
to be basic types
|
||||
|
||||
Important for 1.0 GLib Bindings
|
||||
===
|
||||
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@
|
|||
<article id="index">
|
||||
<articleinfo>
|
||||
<title>D-BUS Specification</title>
|
||||
<releaseinfo>Version 0.9</releaseinfo>
|
||||
<date>17 January 2005</date>
|
||||
<releaseinfo>Version 0.10</releaseinfo>
|
||||
<date>28 January 2005</date>
|
||||
<authorgroup>
|
||||
<author>
|
||||
<firstname>Havoc</firstname>
|
||||
|
|
@ -262,6 +262,28 @@
|
|||
marshaled value of that type.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
A <literal>DICT_ENTRY</literal> works exactly like a struct, but rather
|
||||
than parentheses it uses curly braces, and it has more restrictions.
|
||||
The restrictions are: it occurs only as an array element type; and it
|
||||
has exactly two single complete types inside the curly
|
||||
braces. Implementations must not accept dict entries outside of arrays,
|
||||
and must not accept dict entries with zero, one, or more than two
|
||||
fields. A dict entry is always a key-value pair.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The first field in the <literal>DICT_ENTRY</literal> is always the key.
|
||||
A message is considered corrupt if the same key occurs twice in the same
|
||||
array of <literal>DICT_ENTRY</literal>. However, for performance reasons
|
||||
implementations are not required to reject dicts with duplicate keys.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
In most languages, an array of dict entry would be represented as a
|
||||
map, hash table, or dict object.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The following table summarizes the D-BUS types.
|
||||
<informaltable>
|
||||
|
|
@ -286,6 +308,14 @@
|
|||
<entry><literal>BOOLEAN</literal></entry>
|
||||
<entry>98 (ASCII 'b')</entry>
|
||||
<entry>Boolean value, 0 is <literal>FALSE</literal> and 1 is <literal>TRUE</literal>. Everything else is invalid.</entry>
|
||||
</row><row>
|
||||
<entry><literal>INT16</literal></entry>
|
||||
<entry>110 (ASCII 'n')</entry>
|
||||
<entry>16-bit signed integer</entry>
|
||||
</row><row>
|
||||
<entry><literal>UINT16</literal></entry>
|
||||
<entry>113 (ASCII 'q')</entry>
|
||||
<entry>16-bit unsigned integer</entry>
|
||||
</row><row>
|
||||
<entry><literal>INT32</literal></entry>
|
||||
<entry>105 (ASCII 'i')</entry>
|
||||
|
|
@ -330,6 +360,10 @@
|
|||
<entry><literal>VARIANT</literal></entry>
|
||||
<entry>118 (ASCII 'v') </entry>
|
||||
<entry>Variant type (the type of the value is part of the value itself)</entry>
|
||||
</row><row>
|
||||
<entry><literal>DICT_ENTRY</literal></entry>
|
||||
<entry>101 (ASCII 'e'), 123 (ASCII '{'), 125 (ASCII '}') </entry>
|
||||
<entry>Entry in a dict or map (array of key-value pairs)</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
|
|
@ -391,6 +425,14 @@
|
|||
<entry><literal>BOOLEAN</literal></entry>
|
||||
<entry>As for <literal>UINT32</literal>, but only 0 and 1 are valid values.</entry>
|
||||
<entry>4</entry>
|
||||
</row><row>
|
||||
<entry><literal>INT16</literal></entry>
|
||||
<entry>16-bit signed integer in the message's byte order.</entry>
|
||||
<entry>2</entry>
|
||||
</row><row>
|
||||
<entry><literal>UINT16</literal></entry>
|
||||
<entry>16-bit unsigned integer in the message's byte order.</entry>
|
||||
<entry>2</entry>
|
||||
</row><row>
|
||||
<entry><literal>INT32</literal></entry>
|
||||
<entry>32-bit signed integer in the message's byte order.</entry>
|
||||
|
|
@ -478,6 +520,14 @@
|
|||
<entry>
|
||||
1 (alignment of the signature)
|
||||
</entry>
|
||||
</row><row>
|
||||
<entry><literal>DICT_ENTRY</literal></entry>
|
||||
<entry>
|
||||
Identical to STRUCT.
|
||||
</entry>
|
||||
<entry>
|
||||
8
|
||||
</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue