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:
Havoc Pennington 2005-01-28 05:30:53 +00:00
parent 3ed9db546e
commit c7816d45e8
11 changed files with 543 additions and 45 deletions

View file

@ -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

View file

@ -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;
}
}
/** @} */

View file

@ -175,6 +175,7 @@ byteswap_body_helper (DBusTypeReader *reader,
break;
case DBUS_TYPE_STRUCT:
case DBUS_TYPE_DICT_ENTRY:
{
DBusTypeReader sub;

View file

@ -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)
{

View file

@ -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 */

View file

@ -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;

View file

@ -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,

View file

@ -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;

View file

@ -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

View file

@ -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
===

View file

@ -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>