1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-marshal-recursive.c Marshalling routines for recursive types
4 * Copyright (C) 2004 Red Hat, Inc.
6 * Licensed under the Academic Free License version 2.1
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include "dbus-marshal-recursive.h"
25 #include "dbus-internals.h"
28 * @addtogroup DBusMarshal
33 _dbus_type_reader_init (DBusTypeReader *reader,
35 const DBusString *type_str,
37 const DBusString *value_str,
45 _dbus_type_reader_get_value_end (DBusTypeReader *reader)
52 _dbus_type_reader_get_type_end (DBusTypeReader *reader)
59 _dbus_type_reader_get_current_type (DBusTypeReader *reader)
66 _dbus_type_reader_get_array_type (DBusTypeReader *reader)
73 _dbus_type_reader_read_basic (DBusTypeReader *reader,
81 _dbus_type_reader_read_array (DBusTypeReader *reader,
91 _dbus_type_reader_recurse (DBusTypeReader *reader)
98 _dbus_type_reader_unrecurse (DBusTypeReader *reader)
105 _dbus_type_reader_next (DBusTypeReader *reader)
113 _dbus_type_writer_init (DBusTypeWriter *writer,
115 DBusString *type_str,
117 DBusString *value_str,
125 _dbus_type_writer_write_basic (DBusTypeWriter *writer,
134 _dbus_type_writer_write_array (DBusTypeWriter *writer,
144 _dbus_type_writer_recurse (DBusTypeWriter *writer,
152 _dbus_type_writer_unrecurse (DBusTypeWriter *writer)
158 /** @} */ /* end of DBusMarshal group */
160 #ifdef DBUS_BUILD_TESTS
161 #include "dbus-test.h"
167 DBusString signature;
178 data_block_init (DataBlock *block)
180 if (!_dbus_string_init (&block->signature))
183 if (!_dbus_string_init (&block->body))
185 _dbus_string_free (&block->signature);
193 data_block_free (DataBlock *block)
195 _dbus_string_free (&block->signature);
196 _dbus_string_free (&block->body);
200 data_block_save (DataBlock *block,
201 DataBlockState *state)
203 state->saved_sig_len = _dbus_string_get_length (&block->signature);
204 state->saved_body_len = _dbus_string_get_length (&block->body);
208 data_block_restore (DataBlock *block,
209 DataBlockState *state)
211 /* These set_length should be shortening things so should always work */
213 if (!_dbus_string_set_length (&block->signature,
214 state->saved_sig_len))
215 _dbus_assert_not_reached ("could not restore signature length");
217 if (!_dbus_string_set_length (&block->body,
218 state->saved_body_len))
219 _dbus_assert_not_reached ("could not restore body length");
223 data_block_init_reader_writer (DataBlock *block,
225 DBusTypeReader *reader,
226 DBusTypeWriter *writer)
228 _dbus_type_reader_init (reader,
231 _dbus_string_get_length (&block->signature),
233 _dbus_string_get_length (&block->body));
235 _dbus_type_writer_init (writer,
238 _dbus_string_get_length (&block->signature),
240 _dbus_string_get_length (&block->body));
243 #define SAMPLE_INT32 12345678
244 #define SAMPLE_INT32_ALTERNATE 53781429
246 write_int32 (DataBlock *block,
247 DBusTypeWriter *writer)
249 dbus_int32_t v = SAMPLE_INT32;
251 return _dbus_type_writer_write_basic (writer,
257 check_expected_type (DBusTypeReader *reader,
262 t = _dbus_type_reader_get_current_type (reader);
266 _dbus_warn ("Read type %s while expecting %s\n",
267 _dbus_type_to_string (t),
268 _dbus_type_to_string (expected));
274 read_int32 (DataBlock *block,
275 DBusTypeReader *reader)
279 check_expected_type (reader, DBUS_TYPE_INT32);
281 _dbus_type_reader_read_basic (reader,
284 _dbus_assert (v == SAMPLE_INT32);
290 write_struct_with_int32s (DataBlock *block,
291 DBusTypeWriter *writer)
294 DataBlockState saved;
296 data_block_save (block, &saved);
298 if (!_dbus_type_writer_recurse (writer,
303 if (!_dbus_type_writer_write_basic (writer,
307 data_block_restore (block, &saved);
311 v = SAMPLE_INT32_ALTERNATE;
312 if (!_dbus_type_writer_write_basic (writer,
316 data_block_restore (block, &saved);
320 if (!_dbus_type_writer_unrecurse (writer))
322 data_block_restore (block, &saved);
330 read_struct_with_int32s (DataBlock *block,
331 DBusTypeReader *reader)
335 check_expected_type (reader, DBUS_TYPE_STRUCT);
337 _dbus_type_reader_recurse (reader);
339 check_expected_type (reader, DBUS_TYPE_INT32);
341 _dbus_type_reader_read_basic (reader,
344 _dbus_assert (v == SAMPLE_INT32);
346 _dbus_type_reader_next (reader);
347 check_expected_type (reader, DBUS_TYPE_INT32);
349 _dbus_type_reader_read_basic (reader,
352 _dbus_assert (v == SAMPLE_INT32_ALTERNATE);
354 _dbus_type_reader_unrecurse (reader);
360 write_struct_of_structs (DataBlock *block,
361 DBusTypeWriter *writer)
363 DataBlockState saved;
365 data_block_save (block, &saved);
367 if (!_dbus_type_writer_recurse (writer,
371 if (!write_struct_with_int32s (block, writer))
373 data_block_restore (block, &saved);
376 if (!write_struct_with_int32s (block, writer))
378 data_block_restore (block, &saved);
381 if (!write_struct_with_int32s (block, writer))
383 data_block_restore (block, &saved);
387 if (!_dbus_type_writer_unrecurse (writer))
389 data_block_restore (block, &saved);
397 read_struct_of_structs (DataBlock *block,
398 DBusTypeReader *reader)
400 check_expected_type (reader, DBUS_TYPE_STRUCT);
402 _dbus_type_reader_recurse (reader);
404 if (!read_struct_with_int32s (block, reader))
406 _dbus_type_reader_next (reader);
407 if (!read_struct_with_int32s (block, reader))
409 _dbus_type_reader_next (reader);
410 if (!read_struct_with_int32s (block, reader))
413 _dbus_type_reader_unrecurse (reader);
419 write_struct_of_structs_of_structs (DataBlock *block,
420 DBusTypeWriter *writer)
422 DataBlockState saved;
424 data_block_save (block, &saved);
426 if (!_dbus_type_writer_recurse (writer,
430 if (!write_struct_of_structs (block, writer))
432 data_block_restore (block, &saved);
435 if (!write_struct_of_structs (block, writer))
437 data_block_restore (block, &saved);
441 if (!_dbus_type_writer_unrecurse (writer))
443 data_block_restore (block, &saved);
451 read_struct_of_structs_of_structs (DataBlock *block,
452 DBusTypeReader *reader)
454 check_expected_type (reader, DBUS_TYPE_STRUCT);
456 _dbus_type_reader_recurse (reader);
458 if (!read_struct_of_structs (block, reader))
460 _dbus_type_reader_next (reader);
461 if (!read_struct_of_structs (block, reader))
464 _dbus_type_reader_unrecurse (reader);
472 ITEM_STRUCT_WITH_INT32S,
473 ITEM_STRUCT_OF_STRUCTS,
474 ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS,
479 typedef dbus_bool_t (* WriteItemFunc) (DataBlock *block,
480 DBusTypeWriter *writer);
481 typedef dbus_bool_t (* ReadItemFunc) (DataBlock *block,
482 DBusTypeReader *reader);
487 WriteItemFunc write_item_func;
488 ReadItemFunc read_item_func;
491 static CheckMarshalItem items[] = {
492 { ITEM_INT32, write_int32, read_int32 },
493 { ITEM_STRUCT_WITH_INT32S, write_struct_with_int32s, read_struct_with_int32s },
494 { ITEM_STRUCT_OF_STRUCTS, write_struct_of_structs, read_struct_of_structs },
495 { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS,
496 write_struct_of_structs_of_structs,
497 read_struct_of_structs_of_structs }
502 /* Array of items in the above items[]; -1 terminated */
506 static TestRun runs[] = {
507 { { ITEM_INVALID } },
510 { { ITEM_INT32, ITEM_INVALID } },
511 { { ITEM_INT32, ITEM_INT32, ITEM_INVALID } },
512 { { ITEM_INT32, ITEM_INT32, ITEM_INT32, ITEM_INT32, ITEM_INT32, ITEM_INVALID } },
514 /* STRUCT_WITH_INT32S */
515 { { ITEM_STRUCT_WITH_INT32S, ITEM_INVALID } },
516 { { ITEM_STRUCT_WITH_INT32S, ITEM_STRUCT_WITH_INT32S, ITEM_INVALID } },
517 { { ITEM_STRUCT_WITH_INT32S, ITEM_INT32, ITEM_STRUCT_WITH_INT32S, ITEM_INVALID } },
518 { { ITEM_INT32, ITEM_STRUCT_WITH_INT32S, ITEM_INT32, ITEM_STRUCT_WITH_INT32S, ITEM_INVALID } },
519 { { ITEM_INT32, ITEM_STRUCT_WITH_INT32S, ITEM_INT32, ITEM_INT32, ITEM_INT32, ITEM_STRUCT_WITH_INT32S, ITEM_INVALID } },
521 /* STRUCT_OF_STRUCTS */
522 { { ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
523 { { ITEM_STRUCT_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
524 { { ITEM_STRUCT_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
525 { { ITEM_STRUCT_WITH_INT32S, ITEM_STRUCT_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
526 { { ITEM_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
527 { { ITEM_STRUCT_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
529 /* STRUCT_OF_STRUCTS_OF_STRUCTS */
530 { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
531 { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
532 { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
533 { { ITEM_STRUCT_WITH_INT32S, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
534 { { ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
535 { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } }
540 perform_one_run (DataBlock *block,
544 DBusTypeReader reader;
545 DBusTypeWriter writer;
547 DataBlockState saved;
552 data_block_save (block, &saved);
554 data_block_init_reader_writer (block,
559 while (run->items[i] != ITEM_INVALID)
561 CheckMarshalItem *item = &items[run->items[i]];
562 if (!(* item->write_item_func) (block, &writer))
568 while (run->items[i] != ITEM_INVALID)
570 CheckMarshalItem *item = &items[run->items[i]];
572 if (!(* item->read_item_func) (block, &reader))
575 _dbus_type_reader_next (&reader);
583 data_block_restore (block, &saved);
588 perform_all_runs (int byte_order,
597 if (!data_block_init (&block))
600 if (!_dbus_string_lengthen (&block.signature, initial_offset))
603 if (!_dbus_string_lengthen (&block.body, initial_offset))
607 while (i < _DBUS_N_ELEMENTS (runs))
609 if (!perform_one_run (&block, byte_order, &runs[i]))
618 data_block_free (&block);
624 perform_all_items (int byte_order,
634 if (!data_block_init (&block))
638 if (!_dbus_string_lengthen (&block.signature, initial_offset))
641 if (!_dbus_string_lengthen (&block.body, initial_offset))
644 /* Create a run containing all the items */
646 while (i < _DBUS_N_ELEMENTS (items))
648 _dbus_assert (i == items[i].which);
650 run.items[i] = items[i].which;
655 run.items[i] = ITEM_INVALID;
657 if (!perform_one_run (&block, byte_order, &run))
663 data_block_free (&block);
669 recursive_marshal_test_iteration (void *data)
676 if (!perform_all_runs (DBUS_LITTLE_ENDIAN, i))
678 if (!perform_all_runs (DBUS_BIG_ENDIAN, i))
680 if (!perform_all_items (DBUS_LITTLE_ENDIAN, i))
682 if (!perform_all_items (DBUS_BIG_ENDIAN, i))
691 dbus_bool_t _dbus_marshal_recursive_test (void);
694 _dbus_marshal_recursive_test (void)
696 _dbus_test_oom_handling ("recursive marshaling",
697 recursive_marshal_test_iteration,
705 main (int argc, char **argv)
707 _dbus_marshal_recursive_test ();
713 #endif /* DBUS_BUILD_TESTS */