-/* -*- mode: C; c-file-style: "gnu" -*- */
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/* dbus-marshal-recursive.c Marshalling routines for recursive types
*
* Copyright (C) 2004, 2005 Red Hat, Inc.
*
* 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
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
+#include <config.h>
#include "dbus-marshal-recursive.h"
#include "dbus-marshal-basic.h"
#include "dbus-signature.h"
* @{
*/
+static dbus_bool_t _dbus_type_reader_greater_than (const DBusTypeReader *lhs,
+ const DBusTypeReader *rhs);
+
+static void _dbus_type_writer_set_enabled (DBusTypeWriter *writer,
+ dbus_bool_t enabled);
+static dbus_bool_t _dbus_type_writer_write_reader_partial (DBusTypeWriter *writer,
+ DBusTypeReader *reader,
+ const DBusTypeReader *start_after,
+ int start_after_new_pos,
+ int start_after_new_len,
+ DBusList **fixups);
+
/** turn this on to get deluged in TypeReader verbose spam */
#define RECURSIVE_MARSHAL_READ_TRACE 0
dbus_bool_t (* check_finished) (const DBusTypeReader *reader); /**< check whether reader is at the end */
void (* next) (DBusTypeReader *reader,
int current_type); /**< go to the next value */
- void (* init_from_mark) (DBusTypeReader *reader,
- const DBusTypeMark *mark); /**< uncompress from a mark */
};
static int
* type position is stored in the same variable.
*
* @param type_str a type signature (must be valid)
- * @param type_pos an integer position in the type signtaure (in and out)
+ * @param type_pos an integer position in the type signature (in and out)
*/
void
_dbus_type_signature_next (const char *type_str,
_dbus_assert (reader->value_pos >= reader->u.array.start_pos);
switch (_dbus_first_type_in_signature (reader->type_str,
- reader->type_pos))
+ reader->type_pos))
{
case DBUS_TYPE_DICT_ENTRY:
case DBUS_TYPE_STRUCT:
}
}
-static void
-array_init_from_mark (DBusTypeReader *reader,
- const DBusTypeMark *mark)
-{
- /* Fill in the array-specific fields from the mark. The general
- * fields are already filled in.
- */
- reader->u.array.start_pos = mark->array_start_pos;
- reader->array_len_offset = mark->array_len_offset;
-}
-
static const DBusTypeReaderClass body_reader_class = {
"body", 0,
FALSE,
NULL, /* body is always toplevel, so doesn't get recursed into */
NULL,
- base_reader_next,
- NULL
+ base_reader_next
};
static const DBusTypeReaderClass body_types_only_reader_class = {
TRUE,
NULL, /* body is always toplevel, so doesn't get recursed into */
NULL,
- base_reader_next,
- NULL
+ base_reader_next
};
static const DBusTypeReaderClass struct_reader_class = {
FALSE,
struct_or_dict_entry_reader_recurse,
NULL,
- struct_reader_next,
- NULL
+ struct_reader_next
};
static const DBusTypeReaderClass struct_types_only_reader_class = {
TRUE,
struct_or_dict_entry_types_only_reader_recurse,
NULL,
- struct_reader_next,
- NULL
+ struct_reader_next
};
static const DBusTypeReaderClass dict_entry_reader_class = {
FALSE,
struct_or_dict_entry_reader_recurse,
NULL,
- dict_entry_reader_next,
- NULL
+ dict_entry_reader_next
};
static const DBusTypeReaderClass dict_entry_types_only_reader_class = {
TRUE,
struct_or_dict_entry_types_only_reader_recurse,
NULL,
- dict_entry_reader_next,
- NULL
+ dict_entry_reader_next
};
static const DBusTypeReaderClass array_reader_class = {
FALSE,
array_reader_recurse,
array_reader_check_finished,
- array_reader_next,
- array_init_from_mark
+ array_reader_next
};
static const DBusTypeReaderClass array_types_only_reader_class = {
TRUE,
array_types_only_reader_recurse,
NULL,
- array_types_only_reader_next,
- NULL
+ array_types_only_reader_next
};
static const DBusTypeReaderClass variant_reader_class = {
FALSE,
variant_reader_recurse,
NULL,
- base_reader_next,
- NULL
+ base_reader_next
};
-static const DBusTypeReaderClass const *
+#ifndef DBUS_DISABLE_ASSERT
+static const DBusTypeReaderClass * const
all_reader_classes[] = {
&body_reader_class,
&body_types_only_reader_class,
&array_types_only_reader_class,
&variant_reader_class
};
+#endif
/**
* Initializes a type reader.
}
/**
- * Initializes a type reader that's been compressed into a
- * DBusTypeMark. The args have to be the same as those passed in to
- * create the original #DBusTypeReader.
- *
- * @param reader the reader
- * @param byte_order the byte order of the value block
- * @param type_str string containing the type signature
- * @param value_str string containing the values block
- * @param mark the mark to decompress from
- */
-void
-_dbus_type_reader_init_from_mark (DBusTypeReader *reader,
- int byte_order,
- const DBusString *type_str,
- const DBusString *value_str,
- const DBusTypeMark *mark)
-{
- reader->klass = all_reader_classes[mark->container_type];
-
- reader_init (reader, byte_order,
- mark->type_pos_in_value_str ? value_str : type_str,
- mark->type_pos,
- value_str, mark->value_pos);
-
- if (reader->klass->init_from_mark)
- (* reader->klass->init_from_mark) (reader, mark);
-
-#if RECURSIVE_MARSHAL_READ_TRACE
- _dbus_verbose (" type reader %p init from mark 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));
-#endif
-}
-
-/**
* Like _dbus_type_reader_init() but the iteration is over the
* signature, not over values.
*
}
/**
- * Like _dbus_type_reader_init_from_mark() but only iterates over
- * the signature, not the values.
- *
- * @param reader the reader
- * @param type_str the signature string
- * @param mark the mark to decompress from
- */
-void
-_dbus_type_reader_init_types_only_from_mark (DBusTypeReader *reader,
- const DBusString *type_str,
- const DBusTypeMark *mark)
-{
- reader->klass = all_reader_classes[mark->container_type];
- _dbus_assert (reader->klass->types_only);
- _dbus_assert (!mark->type_pos_in_value_str);
-
- reader_init (reader, DBUS_COMPILER_BYTE_ORDER, /* irrelevant */
- type_str, mark->type_pos,
- NULL, _DBUS_INT_MAX /* crashes if we screw up */);
-
- if (reader->klass->init_from_mark)
- (* reader->klass->init_from_mark) (reader, mark);
-
-#if RECURSIVE_MARSHAL_READ_TRACE
- _dbus_verbose (" type reader %p init types only from mark type_pos = %d remaining sig '%s'\n",
- reader, reader->type_pos,
- _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0));
-#endif
-}
-
-/**
- * Compresses a type reader into a #DBusTypeMark, useful for example
- * if you want to cache a bunch of positions in a block of values.
- *
- * @param reader the reader
- * @param mark the mark to init
- */
-void
-_dbus_type_reader_save_mark (const DBusTypeReader *reader,
- DBusTypeMark *mark)
-{
- mark->type_pos_in_value_str = (reader->type_str == reader->value_str);
- mark->container_type = reader->klass->id;
- _dbus_assert (all_reader_classes[reader->klass->id] == reader->klass);
-
- mark->type_pos = reader->type_pos;
- mark->value_pos = reader->value_pos;
-
- /* these are just junk if the reader isn't really an array of course */
- mark->array_len_offset = reader->array_len_offset;
- mark->array_start_pos = reader->u.array.start_pos;
-}
-
-/**
* Gets the type of the value the reader is currently pointing to;
* or for a types-only reader gets the type it's currently pointing to.
* If the reader is at the end of a block or end of a container such
}
/**
- * Returns the number of values remaining in the current array reader.
+ * Returns the number of bytes in the array.
*
* @param reader the reader to read from
- * @returns the number of elements remaining in the array
+ * @returns the number of bytes in the array
*/
int
_dbus_type_reader_get_array_length (const DBusTypeReader *reader)
_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");
+ _dbus_warn_check_failed ("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");
typedef struct
{
- DBusString replacement;
- int padding;
+ DBusString replacement; /**< Marshaled value including alignment padding */
+ int padding; /**< How much of the replacement block is padding */
} ReplacementBlock;
static dbus_bool_t
return retval;
}
-/**
+/*
* Compares two readers, which must be iterating over the same value data.
* Returns #TRUE if the first parameter is further along than the second parameter.
*
* @param rhs left-hand-side (first) parameter
* @returns whether lhs is greater than rhs
*/
-dbus_bool_t
+static dbus_bool_t
_dbus_type_reader_greater_than (const DBusTypeReader *lhs,
const DBusTypeReader *rhs)
{
if (expected != sub->container_type)
{
- _dbus_warn ("Writing an element of type %s, but the expected type here is %s\n",
- _dbus_type_to_string (sub->container_type),
- _dbus_type_to_string (expected));
+ if (expected != DBUS_TYPE_INVALID)
+ _dbus_warn_check_failed ("Writing an element of type %s, but the expected type here is %s\n"
+ "The overall signature expected here was '%s' and we are on byte %d of that signature.\n",
+ _dbus_type_to_string (sub->container_type),
+ _dbus_type_to_string (expected),
+ _dbus_string_get_const_data (writer->type_str), writer->type_pos);
+ else
+ _dbus_warn_check_failed ("Writing an element of type %s, but no value is expected here\n"
+ "The overall signature expected here was '%s' and we are on byte %d of that signature.\n",
+ _dbus_type_to_string (sub->container_type),
+ _dbus_string_get_const_data (writer->type_str), writer->type_pos);
+
_dbus_assert_not_reached ("bad array element or variant content written");
}
}
if (expected != typecode)
{
- _dbus_warn ("Array or variant type requires that type %s be written, but %s was written\n",
- _dbus_type_to_string (expected), _dbus_type_to_string (typecode));
+ if (expected != DBUS_TYPE_INVALID)
+ _dbus_warn_check_failed ("Array or variant type requires that type %s be written, but %s was written.\n"
+ "The overall signature expected here was '%s' and we are on byte %d of that signature.\n",
+ _dbus_type_to_string (expected), _dbus_type_to_string (typecode),
+ _dbus_string_get_const_data (writer->type_str), writer->type_pos);
+ else
+ _dbus_warn_check_failed ("Array or variant type wasn't expecting any more values to be written into it, but a value %s was written.\n"
+ "The overall signature expected here was '%s' and we are on byte %d of that signature.\n",
+ _dbus_type_to_string (typecode),
+ _dbus_string_get_const_data (writer->type_str), writer->type_pos);
_dbus_assert_not_reached ("bad type inserted somewhere inside an array or variant");
}
}
writer->type_str,
writer->u.array.element_type_pos + 1))
{
- _dbus_warn ("Writing an array of '%s' but this is incompatible with the expected type of elements in the parent array\n",
- _dbus_string_get_const_data_len (contained_type,
- contained_type_start,
- contained_type_len));
+ _dbus_warn_check_failed ("Writing an array of '%s' but this is incompatible with the expected type of elements in the parent array\n",
+ _dbus_string_get_const_data_len (contained_type,
+ contained_type_start,
+ contained_type_len));
_dbus_assert_not_reached ("incompatible type for child array");
}
}
return FALSE;
}
-/**
+/*
* Iterate through all values in the given reader, writing a copy of
* each value to the writer. The reader will be moved forward to its
* end position.
* @param fixups list to append #DBusArrayLenFixup if the write was partial
* @returns #FALSE if no memory
*/
-dbus_bool_t
+static dbus_bool_t
_dbus_type_writer_write_reader_partial (DBusTypeWriter *writer,
DBusTypeReader *reader,
const DBusTypeReader *start_after,
return _dbus_type_writer_write_reader_partial (writer, reader, NULL, 0, 0, NULL);
}
-/**
+/*
* If disabled, a writer can still be iterated forward and recursed/unrecursed
* but won't write any values. Types will still be written unless the
* writer is a "values only" writer, because the writer needs access to
* @param writer the type writer
* @param enabled #TRUE if values should be written
*/
-void
+static void
_dbus_type_writer_set_enabled (DBusTypeWriter *writer,
dbus_bool_t enabled)
{