00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "dbus-marshal-recursive.h"
00025 #include "dbus-marshal-basic.h"
00026 #include "dbus-signature.h"
00027 #include "dbus-internals.h"
00028
00035 #define RECURSIVE_MARSHAL_READ_TRACE 0
00036
00038 #define RECURSIVE_MARSHAL_WRITE_TRACE 0
00039
00040 static void
00041 free_fixups (DBusList **fixups)
00042 {
00043 DBusList *link;
00044
00045 link = _dbus_list_get_first_link (fixups);
00046 while (link != NULL)
00047 {
00048 DBusList *next;
00049
00050 next = _dbus_list_get_next_link (fixups, link);
00051
00052 dbus_free (link->data);
00053 _dbus_list_free_link (link);
00054
00055 link = next;
00056 }
00057
00058 *fixups = NULL;
00059 }
00060
00061 static void
00062 apply_and_free_fixups (DBusList **fixups,
00063 DBusTypeReader *reader)
00064 {
00065 DBusList *link;
00066
00067 #if RECURSIVE_MARSHAL_WRITE_TRACE
00068 if (*fixups)
00069 _dbus_verbose (" %d FIXUPS to apply\n",
00070 _dbus_list_get_length (fixups));
00071 #endif
00072
00073 link = _dbus_list_get_first_link (fixups);
00074 while (link != NULL)
00075 {
00076 DBusList *next;
00077
00078 next = _dbus_list_get_next_link (fixups, link);
00079
00080 if (reader)
00081 {
00082 DBusArrayLenFixup *f;
00083
00084 f = link->data;
00085
00086 #if RECURSIVE_MARSHAL_WRITE_TRACE
00087 _dbus_verbose (" applying FIXUP to reader %p at pos %d new_len = %d old len %d\n",
00088 reader, f->len_pos_in_reader, f->new_len,
00089 _dbus_marshal_read_uint32 (reader->value_str,
00090 f->len_pos_in_reader,
00091 reader->byte_order, NULL));
00092 #endif
00093
00094 _dbus_marshal_set_uint32 ((DBusString*) reader->value_str,
00095 f->len_pos_in_reader,
00096 f->new_len,
00097 reader->byte_order);
00098 }
00099
00100 dbus_free (link->data);
00101 _dbus_list_free_link (link);
00102
00103 link = next;
00104 }
00105
00106 *fixups = NULL;
00107 }
00108
00112 struct DBusTypeReaderClass
00113 {
00114 const char *name;
00115 int id;
00116 dbus_bool_t types_only;
00117 void (* recurse) (DBusTypeReader *sub,
00118 DBusTypeReader *parent);
00119 dbus_bool_t (* check_finished) (const DBusTypeReader *reader);
00120 void (* next) (DBusTypeReader *reader,
00121 int current_type);
00122 };
00123
00124 static int
00125 element_type_get_alignment (const DBusString *str,
00126 int pos)
00127 {
00128 return _dbus_type_get_alignment (_dbus_first_type_in_signature (str, pos));
00129 }
00130
00131 static void
00132 reader_init (DBusTypeReader *reader,
00133 int byte_order,
00134 const DBusString *type_str,
00135 int type_pos,
00136 const DBusString *value_str,
00137 int value_pos)
00138 {
00139 reader->byte_order = byte_order;
00140 reader->finished = FALSE;
00141 reader->type_str = type_str;
00142 reader->type_pos = type_pos;
00143 reader->value_str = value_str;
00144 reader->value_pos = value_pos;
00145 }
00146
00147 static void
00148 base_reader_recurse (DBusTypeReader *sub,
00149 DBusTypeReader *parent)
00150 {
00151
00152 reader_init (sub,
00153 parent->byte_order,
00154 parent->type_str,
00155 parent->type_pos,
00156 parent->value_str,
00157 parent->value_pos);
00158 }
00159
00160 static void
00161 struct_or_dict_entry_types_only_reader_recurse (DBusTypeReader *sub,
00162 DBusTypeReader *parent)
00163 {
00164 base_reader_recurse (sub, parent);
00165
00166 _dbus_assert (_dbus_string_get_byte (sub->type_str,
00167 sub->type_pos) == DBUS_STRUCT_BEGIN_CHAR ||
00168 _dbus_string_get_byte (sub->type_str,
00169 sub->type_pos) == DBUS_DICT_ENTRY_BEGIN_CHAR);
00170
00171 sub->type_pos += 1;
00172 }
00173
00174 static void
00175 struct_or_dict_entry_reader_recurse (DBusTypeReader *sub,
00176 DBusTypeReader *parent)
00177 {
00178 struct_or_dict_entry_types_only_reader_recurse (sub, parent);
00179
00180
00181 sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 8);
00182 }
00183
00184 static void
00185 array_types_only_reader_recurse (DBusTypeReader *sub,
00186 DBusTypeReader *parent)
00187 {
00188 base_reader_recurse (sub, parent);
00189
00190
00191 sub->type_pos += 1;
00192
00193
00194 sub->u.array.start_pos = _DBUS_INT_MAX;
00195 sub->array_len_offset = 7;
00196 }
00197
00200 #define ARRAY_READER_LEN_POS(reader) \
00201 ((reader)->u.array.start_pos - ((int)(reader)->array_len_offset) - 4)
00202
00203 static int
00204 array_reader_get_array_len (const DBusTypeReader *reader)
00205 {
00206 dbus_uint32_t array_len;
00207 int len_pos;
00208
00209 len_pos = ARRAY_READER_LEN_POS (reader);
00210
00211 _dbus_assert (_DBUS_ALIGN_VALUE (len_pos, 4) == (unsigned) len_pos);
00212 array_len = _dbus_unpack_uint32 (reader->byte_order,
00213 _dbus_string_get_const_data_len (reader->value_str, len_pos, 4));
00214
00215 #if RECURSIVE_MARSHAL_READ_TRACE
00216 _dbus_verbose (" reader %p len_pos %d array len %u len_offset %d\n",
00217 reader, len_pos, array_len, reader->array_len_offset);
00218 #endif
00219
00220 _dbus_assert (reader->u.array.start_pos - len_pos - 4 < 8);
00221
00222 return array_len;
00223 }
00224
00225 static void
00226 array_reader_recurse (DBusTypeReader *sub,
00227 DBusTypeReader *parent)
00228 {
00229 int alignment;
00230 int len_pos;
00231
00232 array_types_only_reader_recurse (sub, parent);
00233
00234 sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 4);
00235
00236 len_pos = sub->value_pos;
00237
00238 sub->value_pos += 4;
00239
00240 alignment = element_type_get_alignment (sub->type_str,
00241 sub->type_pos);
00242
00243 sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, alignment);
00244
00245 sub->u.array.start_pos = sub->value_pos;
00246 _dbus_assert ((sub->u.array.start_pos - (len_pos + 4)) < 8);
00247 sub->array_len_offset = sub->u.array.start_pos - (len_pos + 4);
00248
00249 #if RECURSIVE_MARSHAL_READ_TRACE
00250 _dbus_verbose (" type reader %p array start = %d len_offset = %d array len = %d array element type = %s\n",
00251 sub,
00252 sub->u.array.start_pos,
00253 sub->array_len_offset,
00254 array_reader_get_array_len (sub),
00255 _dbus_type_to_string (_dbus_first_type_in_signature (sub->type_str,
00256 sub->type_pos)));
00257 #endif
00258 }
00259
00260 static void
00261 variant_reader_recurse (DBusTypeReader *sub,
00262 DBusTypeReader *parent)
00263 {
00264 int sig_len;
00265 int contained_alignment;
00266
00267 base_reader_recurse (sub, parent);
00268
00269
00270
00271
00272
00273 sig_len = _dbus_string_get_byte (sub->value_str, sub->value_pos);
00274
00275 sub->type_str = sub->value_str;
00276 sub->type_pos = sub->value_pos + 1;
00277
00278 sub->value_pos = sub->type_pos + sig_len + 1;
00279
00280 contained_alignment = _dbus_type_get_alignment (_dbus_first_type_in_signature (sub->type_str,
00281 sub->type_pos));
00282
00283 sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, contained_alignment);
00284
00285 #if RECURSIVE_MARSHAL_READ_TRACE
00286 _dbus_verbose (" type reader %p variant containing '%s'\n",
00287 sub,
00288 _dbus_string_get_const_data_len (sub->type_str,
00289 sub->type_pos, 0));
00290 #endif
00291 }
00292
00293 static dbus_bool_t
00294 array_reader_check_finished (const DBusTypeReader *reader)
00295 {
00296 int end_pos;
00297
00298
00299
00300
00301
00302 end_pos = reader->u.array.start_pos + array_reader_get_array_len (reader);
00303
00304 _dbus_assert (reader->value_pos <= end_pos);
00305 _dbus_assert (reader->value_pos >= reader->u.array.start_pos);
00306
00307 return reader->value_pos == end_pos;
00308 }
00309
00310 static void
00311 skip_one_complete_type (const DBusString *type_str,
00312 int *type_pos)
00313 {
00314 _dbus_type_signature_next (_dbus_string_get_const_data (type_str),
00315 type_pos);
00316 }
00317
00326 void
00327 _dbus_type_signature_next (const char *type_str,
00328 int *type_pos)
00329 {
00330 const unsigned char *p;
00331 const unsigned char *start;
00332
00333 _dbus_assert (type_str != NULL);
00334 _dbus_assert (type_pos != NULL);
00335
00336 start = type_str;
00337 p = start + *type_pos;
00338
00339 _dbus_assert (*p != DBUS_STRUCT_END_CHAR);
00340 _dbus_assert (*p != DBUS_DICT_ENTRY_END_CHAR);
00341
00342 while (*p == DBUS_TYPE_ARRAY)
00343 ++p;
00344
00345 _dbus_assert (*p != DBUS_STRUCT_END_CHAR);
00346 _dbus_assert (*p != DBUS_DICT_ENTRY_END_CHAR);
00347
00348 if (*p == DBUS_STRUCT_BEGIN_CHAR)
00349 {
00350 int depth;
00351
00352 depth = 1;
00353
00354 while (TRUE)
00355 {
00356 _dbus_assert (*p != DBUS_TYPE_INVALID);
00357
00358 ++p;
00359
00360 _dbus_assert (*p != DBUS_TYPE_INVALID);
00361
00362 if (*p == DBUS_STRUCT_BEGIN_CHAR)
00363 depth += 1;
00364 else if (*p == DBUS_STRUCT_END_CHAR)
00365 {
00366 depth -= 1;
00367 if (depth == 0)
00368 {
00369 ++p;
00370 break;
00371 }
00372 }
00373 }
00374 }
00375 else if (*p == DBUS_DICT_ENTRY_BEGIN_CHAR)
00376 {
00377 int depth;
00378
00379 depth = 1;
00380
00381 while (TRUE)
00382 {
00383 _dbus_assert (*p != DBUS_TYPE_INVALID);
00384
00385 ++p;
00386
00387 _dbus_assert (*p != DBUS_TYPE_INVALID);
00388
00389 if (*p == DBUS_DICT_ENTRY_BEGIN_CHAR)
00390 depth += 1;
00391 else if (*p == DBUS_DICT_ENTRY_END_CHAR)
00392 {
00393 depth -= 1;
00394 if (depth == 0)
00395 {
00396 ++p;
00397 break;
00398 }
00399 }
00400 }
00401 }
00402 else
00403 {
00404 ++p;
00405 }
00406
00407 *type_pos = (int) (p - start);
00408 }
00409
00410 static int
00411 find_len_of_complete_type (const DBusString *type_str,
00412 int type_pos)
00413 {
00414 int end;
00415
00416 end = type_pos;
00417
00418 skip_one_complete_type (type_str, &end);
00419
00420 return end - type_pos;
00421 }
00422
00423 static void
00424 base_reader_next (DBusTypeReader *reader,
00425 int current_type)
00426 {
00427 switch (current_type)
00428 {
00429 case DBUS_TYPE_DICT_ENTRY:
00430 case DBUS_TYPE_STRUCT:
00431 case DBUS_TYPE_VARIANT:
00432
00433 {
00434 DBusTypeReader sub;
00435
00436 if (reader->klass->types_only && current_type == DBUS_TYPE_VARIANT)
00437 ;
00438 else
00439 {
00440
00441 _dbus_type_reader_recurse (reader, &sub);
00442
00443
00444 while (_dbus_type_reader_next (&sub))
00445 {
00446 ;
00447 }
00448 }
00449 if (!reader->klass->types_only)
00450 reader->value_pos = sub.value_pos;
00451
00452
00453
00454
00455
00456
00457 if (current_type == DBUS_TYPE_VARIANT)
00458 reader->type_pos += 1;
00459 else
00460 reader->type_pos = sub.type_pos;
00461 }
00462 break;
00463
00464 case DBUS_TYPE_ARRAY:
00465 {
00466 if (!reader->klass->types_only)
00467 _dbus_marshal_skip_array (reader->value_str,
00468 _dbus_first_type_in_signature (reader->type_str,
00469 reader->type_pos + 1),
00470 reader->byte_order,
00471 &reader->value_pos);
00472
00473 skip_one_complete_type (reader->type_str, &reader->type_pos);
00474 }
00475 break;
00476
00477 default:
00478 if (!reader->klass->types_only)
00479 _dbus_marshal_skip_basic (reader->value_str,
00480 current_type, reader->byte_order,
00481 &reader->value_pos);
00482
00483 reader->type_pos += 1;
00484 break;
00485 }
00486 }
00487
00488 static void
00489 struct_reader_next (DBusTypeReader *reader,
00490 int current_type)
00491 {
00492 int t;
00493
00494 base_reader_next (reader, current_type);
00495
00496
00497
00498
00499
00500
00501 t = _dbus_string_get_byte (reader->type_str, reader->type_pos);
00502 if (t == DBUS_STRUCT_END_CHAR)
00503 {
00504 reader->type_pos += 1;
00505 reader->finished = TRUE;
00506 }
00507 }
00508
00509 static void
00510 dict_entry_reader_next (DBusTypeReader *reader,
00511 int current_type)
00512 {
00513 int t;
00514
00515 base_reader_next (reader, current_type);
00516
00517
00518
00519
00520
00521
00522 t = _dbus_string_get_byte (reader->type_str, reader->type_pos);
00523 if (t == DBUS_DICT_ENTRY_END_CHAR)
00524 {
00525 reader->type_pos += 1;
00526 reader->finished = TRUE;
00527 }
00528 }
00529
00530 static void
00531 array_types_only_reader_next (DBusTypeReader *reader,
00532 int current_type)
00533 {
00534
00535
00536
00537
00538
00539 reader->finished = TRUE;
00540 }
00541
00542 static void
00543 array_reader_next (DBusTypeReader *reader,
00544 int current_type)
00545 {
00546
00547 int end_pos;
00548
00549 end_pos = reader->u.array.start_pos + array_reader_get_array_len (reader);
00550
00551 #if RECURSIVE_MARSHAL_READ_TRACE
00552 _dbus_verbose (" reader %p array next START start_pos = %d end_pos = %d value_pos = %d current_type = %s\n",
00553 reader,
00554 reader->u.array.start_pos,
00555 end_pos, reader->value_pos,
00556 _dbus_type_to_string (current_type));
00557 #endif
00558
00559 _dbus_assert (reader->value_pos < end_pos);
00560 _dbus_assert (reader->value_pos >= reader->u.array.start_pos);
00561
00562 switch (_dbus_first_type_in_signature (reader->type_str,
00563 reader->type_pos))
00564 {
00565 case DBUS_TYPE_DICT_ENTRY:
00566 case DBUS_TYPE_STRUCT:
00567 case DBUS_TYPE_VARIANT:
00568 {
00569 DBusTypeReader sub;
00570
00571
00572 _dbus_type_reader_recurse (reader, &sub);
00573
00574
00575 while (_dbus_type_reader_next (&sub))
00576 {
00577 ;
00578 }
00579
00580
00581 reader->value_pos = sub.value_pos;
00582 }
00583 break;
00584
00585 case DBUS_TYPE_ARRAY:
00586 {
00587 _dbus_marshal_skip_array (reader->value_str,
00588 _dbus_first_type_in_signature (reader->type_str,
00589 reader->type_pos + 1),
00590 reader->byte_order,
00591 &reader->value_pos);
00592 }
00593 break;
00594
00595 default:
00596 {
00597 _dbus_marshal_skip_basic (reader->value_str,
00598 current_type, reader->byte_order,
00599 &reader->value_pos);
00600 }
00601 break;
00602 }
00603
00604 #if RECURSIVE_MARSHAL_READ_TRACE
00605 _dbus_verbose (" reader %p array next END start_pos = %d end_pos = %d value_pos = %d current_type = %s\n",
00606 reader,
00607 reader->u.array.start_pos,
00608 end_pos, reader->value_pos,
00609 _dbus_type_to_string (current_type));
00610 #endif
00611
00612 _dbus_assert (reader->value_pos <= end_pos);
00613
00614 if (reader->value_pos == end_pos)
00615 {
00616 skip_one_complete_type (reader->type_str,
00617 &reader->type_pos);
00618 }
00619 }
00620
00621 static const DBusTypeReaderClass body_reader_class = {
00622 "body", 0,
00623 FALSE,
00624 NULL,
00625 NULL,
00626 base_reader_next
00627 };
00628
00629 static const DBusTypeReaderClass body_types_only_reader_class = {
00630 "body types", 1,
00631 TRUE,
00632 NULL,
00633 NULL,
00634 base_reader_next
00635 };
00636
00637 static const DBusTypeReaderClass struct_reader_class = {
00638 "struct", 2,
00639 FALSE,
00640 struct_or_dict_entry_reader_recurse,
00641 NULL,
00642 struct_reader_next
00643 };
00644
00645 static const DBusTypeReaderClass struct_types_only_reader_class = {
00646 "struct types", 3,
00647 TRUE,
00648 struct_or_dict_entry_types_only_reader_recurse,
00649 NULL,
00650 struct_reader_next
00651 };
00652
00653 static const DBusTypeReaderClass dict_entry_reader_class = {
00654 "dict_entry", 4,
00655 FALSE,
00656 struct_or_dict_entry_reader_recurse,
00657 NULL,
00658 dict_entry_reader_next
00659 };
00660
00661 static const DBusTypeReaderClass dict_entry_types_only_reader_class = {
00662 "dict_entry types", 5,
00663 TRUE,
00664 struct_or_dict_entry_types_only_reader_recurse,
00665 NULL,
00666 dict_entry_reader_next
00667 };
00668
00669 static const DBusTypeReaderClass array_reader_class = {
00670 "array", 6,
00671 FALSE,
00672 array_reader_recurse,
00673 array_reader_check_finished,
00674 array_reader_next
00675 };
00676
00677 static const DBusTypeReaderClass array_types_only_reader_class = {
00678 "array types", 7,
00679 TRUE,
00680 array_types_only_reader_recurse,
00681 NULL,
00682 array_types_only_reader_next
00683 };
00684
00685 static const DBusTypeReaderClass variant_reader_class = {
00686 "variant", 8,
00687 FALSE,
00688 variant_reader_recurse,
00689 NULL,
00690 base_reader_next
00691 };
00692
00693 #ifndef DBUS_DISABLE_ASSERT
00694 static const DBusTypeReaderClass * const
00695 all_reader_classes[] = {
00696 &body_reader_class,
00697 &body_types_only_reader_class,
00698 &struct_reader_class,
00699 &struct_types_only_reader_class,
00700 &dict_entry_reader_class,
00701 &dict_entry_types_only_reader_class,
00702 &array_reader_class,
00703 &array_types_only_reader_class,
00704 &variant_reader_class
00705 };
00706 #endif
00707
00718 void
00719 _dbus_type_reader_init (DBusTypeReader *reader,
00720 int byte_order,
00721 const DBusString *type_str,
00722 int type_pos,
00723 const DBusString *value_str,
00724 int value_pos)
00725 {
00726 reader->klass = &body_reader_class;
00727
00728 reader_init (reader, byte_order, type_str, type_pos,
00729 value_str, value_pos);
00730
00731 #if RECURSIVE_MARSHAL_READ_TRACE
00732 _dbus_verbose (" type reader %p init type_pos = %d value_pos = %d remaining sig '%s'\n",
00733 reader, reader->type_pos, reader->value_pos,
00734 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0));
00735 #endif
00736 }
00737
00746 void
00747 _dbus_type_reader_init_types_only (DBusTypeReader *reader,
00748 const DBusString *type_str,
00749 int type_pos)
00750 {
00751 reader->klass = &body_types_only_reader_class;
00752
00753 reader_init (reader, DBUS_COMPILER_BYTE_ORDER ,
00754 type_str, type_pos, NULL, _DBUS_INT_MAX );
00755
00756 #if RECURSIVE_MARSHAL_READ_TRACE
00757 _dbus_verbose (" type reader %p init types only type_pos = %d remaining sig '%s'\n",
00758 reader, reader->type_pos,
00759 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0));
00760 #endif
00761 }
00762
00771 int
00772 _dbus_type_reader_get_current_type (const DBusTypeReader *reader)
00773 {
00774 int t;
00775
00776 if (reader->finished ||
00777 (reader->klass->check_finished &&
00778 (* reader->klass->check_finished) (reader)))
00779 t = DBUS_TYPE_INVALID;
00780 else
00781 t = _dbus_first_type_in_signature (reader->type_str,
00782 reader->type_pos);
00783
00784 _dbus_assert (t != DBUS_STRUCT_END_CHAR);
00785 _dbus_assert (t != DBUS_STRUCT_BEGIN_CHAR);
00786 _dbus_assert (t != DBUS_DICT_ENTRY_END_CHAR);
00787 _dbus_assert (t != DBUS_DICT_ENTRY_BEGIN_CHAR);
00788
00789 #if 0
00790 _dbus_verbose (" type reader %p current type_pos = %d type = %s\n",
00791 reader, reader->type_pos,
00792 _dbus_type_to_string (t));
00793 #endif
00794
00795 return t;
00796 }
00797
00806 int
00807 _dbus_type_reader_get_element_type (const DBusTypeReader *reader)
00808 {
00809 int element_type;
00810
00811 _dbus_assert (_dbus_type_reader_get_current_type (reader) == DBUS_TYPE_ARRAY);
00812
00813 element_type = _dbus_first_type_in_signature (reader->type_str,
00814 reader->type_pos + 1);
00815
00816 return element_type;
00817 }
00818
00823 int
00824 _dbus_type_reader_get_value_pos (const DBusTypeReader *reader)
00825 {
00826 return reader->value_pos;
00827 }
00828
00838 void
00839 _dbus_type_reader_read_raw (const DBusTypeReader *reader,
00840 const unsigned char **value_location)
00841 {
00842 _dbus_assert (!reader->klass->types_only);
00843
00844 *value_location = _dbus_string_get_const_data_len (reader->value_str,
00845 reader->value_pos,
00846 0);
00847 }
00848
00855 void
00856 _dbus_type_reader_read_basic (const DBusTypeReader *reader,
00857 void *value)
00858 {
00859 int t;
00860
00861 _dbus_assert (!reader->klass->types_only);
00862
00863 t = _dbus_type_reader_get_current_type (reader);
00864
00865 _dbus_marshal_read_basic (reader->value_str,
00866 reader->value_pos,
00867 t, value,
00868 reader->byte_order,
00869 NULL);
00870
00871
00872 #if RECURSIVE_MARSHAL_READ_TRACE
00873 _dbus_verbose (" type reader %p read basic type_pos = %d value_pos = %d remaining sig '%s'\n",
00874 reader, reader->type_pos, reader->value_pos,
00875 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0));
00876 #endif
00877 }
00878
00885 int
00886 _dbus_type_reader_get_array_length (const DBusTypeReader *reader)
00887 {
00888 _dbus_assert (!reader->klass->types_only);
00889 _dbus_assert (reader->klass == &array_reader_class);
00890
00891 return array_reader_get_array_len (reader);
00892 }
00893
00909 void
00910 _dbus_type_reader_read_fixed_multi (const DBusTypeReader *reader,
00911 void *value,
00912 int *n_elements)
00913 {
00914 int element_type;
00915 int end_pos;
00916 int remaining_len;
00917 int alignment;
00918 int total_len;
00919
00920 _dbus_assert (!reader->klass->types_only);
00921 _dbus_assert (reader->klass == &array_reader_class);
00922
00923 element_type = _dbus_first_type_in_signature (reader->type_str,
00924 reader->type_pos);
00925
00926 _dbus_assert (element_type != DBUS_TYPE_INVALID);
00927 _dbus_assert (dbus_type_is_fixed (element_type));
00928
00929 alignment = _dbus_type_get_alignment (element_type);
00930
00931 _dbus_assert (reader->value_pos >= reader->u.array.start_pos);
00932
00933 total_len = array_reader_get_array_len (reader);
00934 end_pos = reader->u.array.start_pos + total_len;
00935 remaining_len = end_pos - reader->value_pos;
00936
00937 #if RECURSIVE_MARSHAL_READ_TRACE
00938 _dbus_verbose ("end_pos %d total_len %d remaining_len %d value_pos %d\n",
00939 end_pos, total_len, remaining_len, reader->value_pos);
00940 #endif
00941
00942 _dbus_assert (remaining_len <= total_len);
00943
00944 if (remaining_len == 0)
00945 *(const DBusBasicValue**) value = NULL;
00946 else
00947 *(const DBusBasicValue**) value =
00948 (void*) _dbus_string_get_const_data_len (reader->value_str,
00949 reader->value_pos,
00950 remaining_len);
00951
00952 *n_elements = remaining_len / alignment;
00953 _dbus_assert ((remaining_len % alignment) == 0);
00954
00955 #if RECURSIVE_MARSHAL_READ_TRACE
00956 _dbus_verbose (" type reader %p read fixed array type_pos = %d value_pos = %d remaining sig '%s'\n",
00957 reader, reader->type_pos, reader->value_pos,
00958 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0));
00959 #endif
00960 }
00961
00974 void
00975 _dbus_type_reader_recurse (DBusTypeReader *reader,
00976 DBusTypeReader *sub)
00977 {
00978 int t;
00979
00980 t = _dbus_first_type_in_signature (reader->type_str, reader->type_pos);
00981
00982 switch (t)
00983 {
00984 case DBUS_TYPE_STRUCT:
00985 if (reader->klass->types_only)
00986 sub->klass = &struct_types_only_reader_class;
00987 else
00988 sub->klass = &struct_reader_class;
00989 break;
00990 case DBUS_TYPE_DICT_ENTRY:
00991 if (reader->klass->types_only)
00992 sub->klass = &dict_entry_types_only_reader_class;
00993 else
00994 sub->klass = &dict_entry_reader_class;
00995 break;
00996 case DBUS_TYPE_ARRAY:
00997 if (reader->klass->types_only)
00998 sub->klass = &array_types_only_reader_class;
00999 else
01000 sub->klass = &array_reader_class;
01001 break;
01002 case DBUS_TYPE_VARIANT:
01003 if (reader->klass->types_only)
01004 _dbus_assert_not_reached ("can't recurse into variant typecode");
01005 else
01006 sub->klass = &variant_reader_class;
01007 break;
01008 default:
01009 _dbus_verbose ("recursing into type %s\n", _dbus_type_to_string (t));
01010 #ifndef DBUS_DISABLE_CHECKS
01011 if (t == DBUS_TYPE_INVALID)
01012 _dbus_warn_check_failed ("You can't recurse into an empty array or off the end of a message body\n");
01013 #endif
01014
01015 _dbus_assert_not_reached ("don't yet handle recursing into this type");
01016 }
01017
01018 _dbus_assert (sub->klass == all_reader_classes[sub->klass->id]);
01019
01020 (* sub->klass->recurse) (sub, reader);
01021
01022 #if RECURSIVE_MARSHAL_READ_TRACE
01023 _dbus_verbose (" type reader %p RECURSED type_pos = %d value_pos = %d remaining sig '%s'\n",
01024 sub, sub->type_pos, sub->value_pos,
01025 _dbus_string_get_const_data_len (sub->type_str, sub->type_pos, 0));
01026 #endif
01027 }
01028
01037 dbus_bool_t
01038 _dbus_type_reader_next (DBusTypeReader *reader)
01039 {
01040 int t;
01041
01042 t = _dbus_type_reader_get_current_type (reader);
01043
01044 #if RECURSIVE_MARSHAL_READ_TRACE
01045 _dbus_verbose (" type reader %p START next() { type_pos = %d value_pos = %d remaining sig '%s' current_type = %s\n",
01046 reader, reader->type_pos, reader->value_pos,
01047 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0),
01048 _dbus_type_to_string (t));
01049 #endif
01050
01051 if (t == DBUS_TYPE_INVALID)
01052 return FALSE;
01053
01054 (* reader->klass->next) (reader, t);
01055
01056 #if RECURSIVE_MARSHAL_READ_TRACE
01057 _dbus_verbose (" type reader %p END next() type_pos = %d value_pos = %d remaining sig '%s' current_type = %s\n",
01058 reader, reader->type_pos, reader->value_pos,
01059 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0),
01060 _dbus_type_to_string (_dbus_type_reader_get_current_type (reader)));
01061 #endif
01062
01063 return _dbus_type_reader_get_current_type (reader) != DBUS_TYPE_INVALID;
01064 }
01065
01077 dbus_bool_t
01078 _dbus_type_reader_has_next (const DBusTypeReader *reader)
01079 {
01080
01081 DBusTypeReader copy;
01082
01083 copy = *reader;
01084 return _dbus_type_reader_next (©);
01085 }
01086
01108 void
01109 _dbus_type_reader_get_signature (const DBusTypeReader *reader,
01110 const DBusString **str_p,
01111 int *start_p,
01112 int *len_p)
01113 {
01114 *str_p = reader->type_str;
01115 *start_p = reader->type_pos;
01116 *len_p = find_len_of_complete_type (reader->type_str, reader->type_pos);
01117 }
01118
01119 typedef struct
01120 {
01121 DBusString replacement;
01122 int padding;
01123 } ReplacementBlock;
01124
01125 static dbus_bool_t
01126 replacement_block_init (ReplacementBlock *block,
01127 DBusTypeReader *reader)
01128 {
01129 if (!_dbus_string_init (&block->replacement))
01130 return FALSE;
01131
01132
01133
01134
01135 block->padding = reader->value_pos % 8;
01136
01137 if (!_dbus_string_lengthen (&block->replacement, block->padding))
01138 goto oom;
01139
01140 return TRUE;
01141
01142 oom:
01143 _dbus_string_free (&block->replacement);
01144 return FALSE;
01145 }
01146
01147 static dbus_bool_t
01148 replacement_block_replace (ReplacementBlock *block,
01149 DBusTypeReader *reader,
01150 const DBusTypeReader *realign_root)
01151 {
01152 DBusTypeWriter writer;
01153 DBusTypeReader realign_reader;
01154 DBusList *fixups;
01155 int orig_len;
01156
01157 _dbus_assert (realign_root != NULL);
01158
01159 orig_len = _dbus_string_get_length (&block->replacement);
01160
01161 realign_reader = *realign_root;
01162
01163 #if RECURSIVE_MARSHAL_WRITE_TRACE
01164 _dbus_verbose ("INITIALIZING replacement block writer %p at value_pos %d\n",
01165 &writer, _dbus_string_get_length (&block->replacement));
01166 #endif
01167 _dbus_type_writer_init_values_only (&writer,
01168 realign_reader.byte_order,
01169 realign_reader.type_str,
01170 realign_reader.type_pos,
01171 &block->replacement,
01172 _dbus_string_get_length (&block->replacement));
01173
01174 _dbus_assert (realign_reader.value_pos <= reader->value_pos);
01175
01176 #if RECURSIVE_MARSHAL_WRITE_TRACE
01177 _dbus_verbose ("COPYING from reader at value_pos %d to writer %p starting after value_pos %d\n",
01178 realign_reader.value_pos, &writer, reader->value_pos);
01179 #endif
01180 fixups = NULL;
01181 if (!_dbus_type_writer_write_reader_partial (&writer,
01182 &realign_reader,
01183 reader,
01184 block->padding,
01185 _dbus_string_get_length (&block->replacement) - block->padding,
01186 &fixups))
01187 goto oom;
01188
01189 #if RECURSIVE_MARSHAL_WRITE_TRACE
01190 _dbus_verbose ("REPLACEMENT at padding %d len %d\n", block->padding,
01191 _dbus_string_get_length (&block->replacement) - block->padding);
01192 _dbus_verbose_bytes_of_string (&block->replacement, block->padding,
01193 _dbus_string_get_length (&block->replacement) - block->padding);
01194 _dbus_verbose ("TO BE REPLACED at value_pos = %d (align pad %d) len %d realign_reader.value_pos %d\n",
01195 reader->value_pos, reader->value_pos % 8,
01196 realign_reader.value_pos - reader->value_pos,
01197 realign_reader.value_pos);
01198 _dbus_verbose_bytes_of_string (reader->value_str,
01199 reader->value_pos,
01200 realign_reader.value_pos - reader->value_pos);
01201 #endif
01202
01203
01204
01205
01206 if (!_dbus_string_replace_len (&block->replacement, block->padding,
01207 _dbus_string_get_length (&block->replacement) - block->padding,
01208 (DBusString*) reader->value_str,
01209 reader->value_pos,
01210 realign_reader.value_pos - reader->value_pos))
01211 goto oom;
01212
01213
01214 apply_and_free_fixups (&fixups, reader);
01215
01216 return TRUE;
01217
01218 oom:
01219 _dbus_string_set_length (&block->replacement, orig_len);
01220 free_fixups (&fixups);
01221 return FALSE;
01222 }
01223
01224 static void
01225 replacement_block_free (ReplacementBlock *block)
01226 {
01227 _dbus_string_free (&block->replacement);
01228 }
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253 static dbus_bool_t
01254 reader_set_basic_variable_length (DBusTypeReader *reader,
01255 int current_type,
01256 const void *value,
01257 const DBusTypeReader *realign_root)
01258 {
01259 dbus_bool_t retval;
01260 ReplacementBlock block;
01261 DBusTypeWriter writer;
01262
01263 _dbus_assert (realign_root != NULL);
01264
01265 retval = FALSE;
01266
01267 if (!replacement_block_init (&block, reader))
01268 return FALSE;
01269
01270
01271 #if RECURSIVE_MARSHAL_WRITE_TRACE
01272 _dbus_verbose ("INITIALIZING writer %p to write basic value at value_pos %d of replacement string\n",
01273 &writer, _dbus_string_get_length (&block.replacement));
01274 #endif
01275 _dbus_type_writer_init_values_only (&writer,
01276 reader->byte_order,
01277 reader->type_str,
01278 reader->type_pos,
01279 &block.replacement,
01280 _dbus_string_get_length (&block.replacement));
01281 #if RECURSIVE_MARSHAL_WRITE_TRACE
01282 _dbus_verbose ("WRITING basic value to writer %p (replacement string)\n", &writer);
01283 #endif
01284 if (!_dbus_type_writer_write_basic (&writer, current_type, value))
01285 goto out;
01286
01287 if (!replacement_block_replace (&block,
01288 reader,
01289 realign_root))
01290 goto out;
01291
01292 retval = TRUE;
01293
01294 out:
01295 replacement_block_free (&block);
01296 return retval;
01297 }
01298
01299 static void
01300 reader_set_basic_fixed_length (DBusTypeReader *reader,
01301 int current_type,
01302 const void *value)
01303 {
01304 _dbus_marshal_set_basic ((DBusString*) reader->value_str,
01305 reader->value_pos,
01306 current_type,
01307 value,
01308 reader->byte_order,
01309 NULL, NULL);
01310 }
01311
01346 dbus_bool_t
01347 _dbus_type_reader_set_basic (DBusTypeReader *reader,
01348 const void *value,
01349 const DBusTypeReader *realign_root)
01350 {
01351 int current_type;
01352
01353 _dbus_assert (!reader->klass->types_only);
01354 _dbus_assert (reader->value_str == realign_root->value_str);
01355 _dbus_assert (reader->value_pos >= realign_root->value_pos);
01356
01357 current_type = _dbus_type_reader_get_current_type (reader);
01358
01359 #if RECURSIVE_MARSHAL_WRITE_TRACE
01360 _dbus_verbose (" SET BASIC type reader %p type_pos = %d value_pos = %d remaining sig '%s' realign_root = %p with value_pos %d current_type = %s\n",
01361 reader, reader->type_pos, reader->value_pos,
01362 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0),
01363 realign_root,
01364 realign_root ? realign_root->value_pos : -1,
01365 _dbus_type_to_string (current_type));
01366 _dbus_verbose_bytes_of_string (realign_root->value_str, realign_root->value_pos,
01367 _dbus_string_get_length (realign_root->value_str) -
01368 realign_root->value_pos);
01369 #endif
01370
01371 _dbus_assert (dbus_type_is_basic (current_type));
01372
01373 if (dbus_type_is_fixed (current_type))
01374 {
01375 reader_set_basic_fixed_length (reader, current_type, value);
01376 return TRUE;
01377 }
01378 else
01379 {
01380 _dbus_assert (realign_root != NULL);
01381 return reader_set_basic_variable_length (reader, current_type,
01382 value, realign_root);
01383 }
01384 }
01385
01403 dbus_bool_t
01404 _dbus_type_reader_delete (DBusTypeReader *reader,
01405 const DBusTypeReader *realign_root)
01406 {
01407 dbus_bool_t retval;
01408 ReplacementBlock block;
01409
01410 _dbus_assert (realign_root != NULL);
01411 _dbus_assert (reader->klass == &array_reader_class);
01412
01413 retval = FALSE;
01414
01415 if (!replacement_block_init (&block, reader))
01416 return FALSE;
01417
01418 if (!replacement_block_replace (&block,
01419 reader,
01420 realign_root))
01421 goto out;
01422
01423 retval = TRUE;
01424
01425 out:
01426 replacement_block_free (&block);
01427 return retval;
01428 }
01429
01438 dbus_bool_t
01439 _dbus_type_reader_greater_than (const DBusTypeReader *lhs,
01440 const DBusTypeReader *rhs)
01441 {
01442 _dbus_assert (lhs->value_str == rhs->value_str);
01443
01444 return lhs->value_pos > rhs->value_pos;
01445 }
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455
01476 void
01477 _dbus_type_writer_init (DBusTypeWriter *writer,
01478 int byte_order,
01479 DBusString *type_str,
01480 int type_pos,
01481 DBusString *value_str,
01482 int value_pos)
01483 {
01484 writer->byte_order = byte_order;
01485 writer->type_str = type_str;
01486 writer->type_pos = type_pos;
01487 writer->value_str = value_str;
01488 writer->value_pos = value_pos;
01489 writer->container_type = DBUS_TYPE_INVALID;
01490 writer->type_pos_is_expectation = FALSE;
01491 writer->enabled = TRUE;
01492
01493 #if RECURSIVE_MARSHAL_WRITE_TRACE
01494 _dbus_verbose ("writer %p init remaining sig '%s'\n", writer,
01495 writer->type_str ?
01496 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0) :
01497 "unknown");
01498 #endif
01499 }
01500
01511 void
01512 _dbus_type_writer_init_types_delayed (DBusTypeWriter *writer,
01513 int byte_order,
01514 DBusString *value_str,
01515 int value_pos)
01516 {
01517 _dbus_type_writer_init (writer, byte_order,
01518 NULL, 0, value_str, value_pos);
01519 }
01520
01529 void
01530 _dbus_type_writer_add_types (DBusTypeWriter *writer,
01531 DBusString *type_str,
01532 int type_pos)
01533 {
01534 if (writer->type_str == NULL)
01535 {
01536 writer->type_str = type_str;
01537 writer->type_pos = type_pos;
01538 }
01539 }
01540
01546 void
01547 _dbus_type_writer_remove_types (DBusTypeWriter *writer)
01548 {
01549 writer->type_str = NULL;
01550 writer->type_pos = -1;
01551 }
01552
01567 void
01568 _dbus_type_writer_init_values_only (DBusTypeWriter *writer,
01569 int byte_order,
01570 const DBusString *type_str,
01571 int type_pos,
01572 DBusString *value_str,
01573 int value_pos)
01574 {
01575 _dbus_type_writer_init (writer, byte_order,
01576 (DBusString*)type_str, type_pos,
01577 value_str, value_pos);
01578
01579 writer->type_pos_is_expectation = TRUE;
01580 }
01581
01582 static dbus_bool_t
01583 _dbus_type_writer_write_basic_no_typecode (DBusTypeWriter *writer,
01584 int type,
01585 const void *value)
01586 {
01587 if (writer->enabled)
01588 return _dbus_marshal_write_basic (writer->value_str,
01589 writer->value_pos,
01590 type,
01591 value,
01592 writer->byte_order,
01593 &writer->value_pos);
01594 else
01595 return TRUE;
01596 }
01597
01598
01599
01600
01601
01602
01603
01604
01605
01606
01607
01608
01609
01610
01611
01612
01613
01614
01615
01616
01617
01618
01619 static void
01620 writer_recurse_init_and_check (DBusTypeWriter *writer,
01621 int container_type,
01622 DBusTypeWriter *sub)
01623 {
01624 _dbus_type_writer_init (sub,
01625 writer->byte_order,
01626 writer->type_str,
01627 writer->type_pos,
01628 writer->value_str,
01629 writer->value_pos);
01630
01631 sub->container_type = container_type;
01632
01633 if (writer->type_pos_is_expectation ||
01634 (sub->container_type == DBUS_TYPE_ARRAY || sub->container_type == DBUS_TYPE_VARIANT))
01635 sub->type_pos_is_expectation = TRUE;
01636 else
01637 sub->type_pos_is_expectation = FALSE;
01638
01639 sub->enabled = writer->enabled;
01640
01641 #ifndef DBUS_DISABLE_CHECKS
01642 if (writer->type_pos_is_expectation && writer->type_str)
01643 {
01644 int expected;
01645
01646 expected = _dbus_first_type_in_signature (writer->type_str, writer->type_pos);
01647
01648 if (expected != sub->container_type)
01649 {
01650 if (expected != DBUS_TYPE_INVALID)
01651 _dbus_warn_check_failed ("Writing an element of type %s, but the expected type here is %s\n"
01652 "The overall signature expected here was '%s' and we are on byte %d of that signature.\n",
01653 _dbus_type_to_string (sub->container_type),
01654 _dbus_type_to_string (expected),
01655 _dbus_string_get_const_data (writer->type_str), writer->type_pos);
01656 else
01657 _dbus_warn_check_failed ("Writing an element of type %s, but no value is expected here\n"
01658 "The overall signature expected here was '%s' and we are on byte %d of that signature.\n",
01659 _dbus_type_to_string (sub->container_type),
01660 _dbus_string_get_const_data (writer->type_str), writer->type_pos);
01661
01662 _dbus_assert_not_reached ("bad array element or variant content written");
01663 }
01664 }
01665 #endif
01666
01667 #if RECURSIVE_MARSHAL_WRITE_TRACE
01668 _dbus_verbose (" type writer %p recurse parent %s type_pos = %d value_pos = %d is_expectation = %d remaining sig '%s' enabled = %d\n",
01669 writer,
01670 _dbus_type_to_string (writer->container_type),
01671 writer->type_pos, writer->value_pos, writer->type_pos_is_expectation,
01672 writer->type_str ?
01673 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0) :
01674 "unknown",
01675 writer->enabled);
01676 _dbus_verbose (" type writer %p recurse sub %s type_pos = %d value_pos = %d is_expectation = %d enabled = %d\n",
01677 sub,
01678 _dbus_type_to_string (sub->container_type),
01679 sub->type_pos, sub->value_pos,
01680 sub->type_pos_is_expectation,
01681 sub->enabled);
01682 #endif
01683 }
01684
01685 static dbus_bool_t
01686 write_or_verify_typecode (DBusTypeWriter *writer,
01687 int typecode)
01688 {
01689
01690
01691
01692
01693
01694 #if RECURSIVE_MARSHAL_WRITE_TRACE
01695 _dbus_verbose (" type writer %p write_or_verify start type_pos = %d remaining sig '%s' enabled = %d\n",
01696 writer, writer->type_pos,
01697 writer->type_str ?
01698 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0) :
01699 "unknown",
01700 writer->enabled);
01701 #endif
01702
01703 if (writer->type_str == NULL)
01704 return TRUE;
01705
01706 if (writer->type_pos_is_expectation)
01707 {
01708 #ifndef DBUS_DISABLE_CHECKS
01709 {
01710 int expected;
01711
01712 expected = _dbus_string_get_byte (writer->type_str, writer->type_pos);
01713
01714 if (expected != typecode)
01715 {
01716 if (expected != DBUS_TYPE_INVALID)
01717 _dbus_warn_check_failed ("Array or variant type requires that type %s be written, but %s was written.\n"
01718 "The overall signature expected here was '%s' and we are on byte %d of that signature.\n",
01719 _dbus_type_to_string (expected), _dbus_type_to_string (typecode),
01720 _dbus_string_get_const_data (writer->type_str), writer->type_pos);
01721 else
01722 _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"
01723 "The overall signature expected here was '%s' and we are on byte %d of that signature.\n",
01724 _dbus_type_to_string (typecode),
01725 _dbus_string_get_const_data (writer->type_str), writer->type_pos);
01726 _dbus_assert_not_reached ("bad type inserted somewhere inside an array or variant");
01727 }
01728 }
01729 #endif
01730
01731
01732
01733
01734
01735 if (writer->container_type != DBUS_TYPE_ARRAY)
01736 writer->type_pos += 1;
01737 }
01738 else
01739 {
01740 if (!_dbus_string_insert_byte (writer->type_str,
01741 writer->type_pos,
01742 typecode))
01743 return FALSE;
01744
01745 writer->type_pos += 1;
01746 }
01747
01748 #if RECURSIVE_MARSHAL_WRITE_TRACE
01749 _dbus_verbose (" type writer %p write_or_verify end type_pos = %d remaining sig '%s'\n",
01750 writer, writer->type_pos,
01751 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0));
01752 #endif
01753
01754 return TRUE;
01755 }
01756
01757 static dbus_bool_t
01758 writer_recurse_struct_or_dict_entry (DBusTypeWriter *writer,
01759 int begin_char,
01760 const DBusString *contained_type,
01761 int contained_type_start,
01762 int contained_type_len,
01763 DBusTypeWriter *sub)
01764 {
01765
01766
01767
01768
01769
01770
01771 if (writer->enabled)
01772 {
01773 if (!_dbus_string_alloc_space (sub->value_str, 8))
01774 return FALSE;
01775 }
01776
01777 if (!write_or_verify_typecode (sub, begin_char))
01778 _dbus_assert_not_reached ("failed to insert struct typecode after prealloc");
01779
01780 if (writer->enabled)
01781 {
01782 if (!_dbus_string_insert_bytes (sub->value_str,
01783 sub->value_pos,
01784 _DBUS_ALIGN_VALUE (sub->value_pos, 8) - sub->value_pos,
01785 '\0'))
01786 _dbus_assert_not_reached ("should not have failed to insert alignment padding for struct");
01787 sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 8);
01788 }
01789
01790 return TRUE;
01791 }
01792
01793
01794 static dbus_bool_t
01795 writer_recurse_array (DBusTypeWriter *writer,
01796 const DBusString *contained_type,
01797 int contained_type_start,
01798 int contained_type_len,
01799 DBusTypeWriter *sub,
01800 dbus_bool_t is_array_append)
01801 {
01802 dbus_uint32_t value = 0;
01803 int alignment;
01804 int aligned;
01805
01806 #ifndef DBUS_DISABLE_CHECKS
01807 if (writer->container_type == DBUS_TYPE_ARRAY &&
01808 writer->type_str)
01809 {
01810 if (!_dbus_string_equal_substring (contained_type,
01811 contained_type_start,
01812 contained_type_len,
01813 writer->type_str,
01814 writer->u.array.element_type_pos + 1))
01815 {
01816 _dbus_warn_check_failed ("Writing an array of '%s' but this is incompatible with the expected type of elements in the parent array\n",
01817 _dbus_string_get_const_data_len (contained_type,
01818 contained_type_start,
01819 contained_type_len));
01820 _dbus_assert_not_reached ("incompatible type for child array");
01821 }
01822 }
01823 #endif
01824
01825 if (writer->enabled && !is_array_append)
01826 {
01827
01828
01829
01830 if (!_dbus_string_alloc_space (sub->value_str, 3 + 4 + 4))
01831 return FALSE;
01832 }
01833
01834 if (writer->type_str != NULL)
01835 {
01836 sub->type_pos += 1;
01837
01838
01839 sub->u.array.element_type_pos = sub->type_pos;
01840 }
01841
01842 if (!writer->type_pos_is_expectation)
01843 {
01844
01845
01846
01847 if (!_dbus_string_alloc_space (writer->type_str, 1 + contained_type_len))
01848 return FALSE;
01849
01850 if (!_dbus_string_insert_byte (writer->type_str,
01851 writer->type_pos,
01852 DBUS_TYPE_ARRAY))
01853 _dbus_assert_not_reached ("failed to insert array typecode after prealloc");
01854
01855 if (!_dbus_string_copy_len (contained_type,
01856 contained_type_start, contained_type_len,
01857 sub->type_str,
01858 sub->u.array.element_type_pos))
01859 _dbus_assert_not_reached ("should not have failed to insert array element typecodes");
01860 }
01861
01862 if (writer->type_str != NULL)
01863 {
01864
01865
01866
01867 if (writer->container_type != DBUS_TYPE_ARRAY)
01868 writer->type_pos += 1 + contained_type_len;
01869 else
01870 _dbus_assert (writer->type_pos_is_expectation);
01871 }
01872
01873 if (writer->enabled)
01874 {
01875
01876 sub->u.array.len_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 4);
01877
01878 if (is_array_append)
01879 {
01880 sub->value_pos += 4;
01881 }
01882 else
01883 {
01884 if (!_dbus_type_writer_write_basic_no_typecode (sub, DBUS_TYPE_UINT32,
01885 &value))
01886 _dbus_assert_not_reached ("should not have failed to insert array len");
01887 }
01888
01889 _dbus_assert (sub->u.array.len_pos == sub->value_pos - 4);
01890
01891
01892
01893
01894
01895 alignment = element_type_get_alignment (contained_type, contained_type_start);
01896
01897 aligned = _DBUS_ALIGN_VALUE (sub->value_pos, alignment);
01898 if (aligned != sub->value_pos)
01899 {
01900 if (!is_array_append)
01901 {
01902 if (!_dbus_string_insert_bytes (sub->value_str,
01903 sub->value_pos,
01904 aligned - sub->value_pos,
01905 '\0'))
01906 _dbus_assert_not_reached ("should not have failed to insert alignment padding");
01907 }
01908
01909 sub->value_pos = aligned;
01910 }
01911
01912 sub->u.array.start_pos = sub->value_pos;
01913
01914 if (is_array_append)
01915 {
01916 dbus_uint32_t len;
01917
01918 _dbus_assert (_DBUS_ALIGN_VALUE (sub->u.array.len_pos, 4) ==
01919 (unsigned) sub->u.array.len_pos);
01920 len = _dbus_unpack_uint32 (sub->byte_order,
01921 _dbus_string_get_const_data_len (sub->value_str,
01922 sub->u.array.len_pos,
01923 4));
01924
01925 sub->value_pos += len;
01926 }
01927 }
01928 else
01929 {
01930
01931 sub->u.array.len_pos = -1;
01932 sub->u.array.start_pos = sub->value_pos;
01933 }
01934
01935 _dbus_assert (sub->u.array.len_pos < sub->u.array.start_pos);
01936 _dbus_assert (is_array_append || sub->u.array.start_pos == sub->value_pos);
01937
01938 #if RECURSIVE_MARSHAL_WRITE_TRACE
01939 _dbus_verbose (" type writer %p recurse array done remaining sig '%s' array start_pos = %d len_pos = %d value_pos = %d\n", sub,
01940 sub->type_str ?
01941 _dbus_string_get_const_data_len (sub->type_str, sub->type_pos, 0) :
01942 "unknown",
01943 sub->u.array.start_pos, sub->u.array.len_pos, sub->value_pos);
01944 #endif
01945
01946 return TRUE;
01947 }
01948
01949
01950
01951
01952
01953
01954
01955
01956
01957
01958
01959
01960
01961
01962
01963
01964
01965
01966
01967 static dbus_bool_t
01968 writer_recurse_variant (DBusTypeWriter *writer,
01969 const DBusString *contained_type,
01970 int contained_type_start,
01971 int contained_type_len,
01972 DBusTypeWriter *sub)
01973 {
01974 int contained_alignment;
01975
01976 if (writer->enabled)
01977 {
01978
01979
01980
01981
01982 if (!_dbus_string_alloc_space (sub->value_str, contained_type_len + 9))
01983 return FALSE;
01984 }
01985
01986
01987 if (!write_or_verify_typecode (writer, DBUS_TYPE_VARIANT))
01988 return FALSE;
01989
01990
01991
01992 if (!writer->enabled)
01993 {
01994 sub->type_str = NULL;
01995 sub->type_pos = -1;
01996
01997 return TRUE;
01998 }
01999
02000
02001
02002 if (!_dbus_string_insert_byte (sub->value_str,
02003 sub->value_pos,
02004 contained_type_len))
02005 _dbus_assert_not_reached ("should not have failed to insert variant type sig len");
02006
02007 sub->value_pos += 1;
02008
02009
02010 sub->type_str = sub->value_str;
02011 sub->type_pos = sub->value_pos;
02012
02013 if (!_dbus_string_copy_len (contained_type, contained_type_start, contained_type_len,
02014 sub->value_str, sub->value_pos))
02015 _dbus_assert_not_reached ("should not have failed to insert variant type sig");
02016
02017 sub->value_pos += contained_type_len;
02018
02019 if (!_dbus_string_insert_byte (sub->value_str,
02020 sub->value_pos,
02021 DBUS_TYPE_INVALID))
02022 _dbus_assert_not_reached ("should not have failed to insert variant type nul termination");
02023
02024 sub->value_pos += 1;
02025
02026 contained_alignment = _dbus_type_get_alignment (_dbus_first_type_in_signature (contained_type, contained_type_start));
02027
02028 if (!_dbus_string_insert_bytes (sub->value_str,
02029 sub->value_pos,
02030 _DBUS_ALIGN_VALUE (sub->value_pos, contained_alignment) - sub->value_pos,
02031 '\0'))
02032 _dbus_assert_not_reached ("should not have failed to insert alignment padding for variant body");
02033 sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, contained_alignment);
02034
02035 return TRUE;
02036 }
02037
02038 static dbus_bool_t
02039 _dbus_type_writer_recurse_contained_len (DBusTypeWriter *writer,
02040 int container_type,
02041 const DBusString *contained_type,
02042 int contained_type_start,
02043 int contained_type_len,
02044 DBusTypeWriter *sub,
02045 dbus_bool_t is_array_append)
02046 {
02047 writer_recurse_init_and_check (writer, container_type, sub);
02048
02049 switch (container_type)
02050 {
02051 case DBUS_TYPE_STRUCT:
02052 return writer_recurse_struct_or_dict_entry (writer,
02053 DBUS_STRUCT_BEGIN_CHAR,
02054 contained_type,
02055 contained_type_start, contained_type_len,
02056 sub);
02057 break;
02058 case DBUS_TYPE_DICT_ENTRY:
02059 return writer_recurse_struct_or_dict_entry (writer,
02060 DBUS_DICT_ENTRY_BEGIN_CHAR,
02061 contained_type,
02062 contained_type_start, contained_type_len,
02063 sub);
02064 break;
02065 case DBUS_TYPE_ARRAY:
02066 return writer_recurse_array (writer,
02067 contained_type, contained_type_start, contained_type_len,
02068 sub, is_array_append);
02069 break;
02070 case DBUS_TYPE_VARIANT:
02071 return writer_recurse_variant (writer,
02072 contained_type, contained_type_start, contained_type_len,
02073 sub);
02074 break;
02075 default:
02076 _dbus_assert_not_reached ("tried to recurse into type that doesn't support that");
02077 return FALSE;
02078 break;
02079 }
02080 }
02081
02092 dbus_bool_t
02093 _dbus_type_writer_recurse (DBusTypeWriter *writer,
02094 int container_type,
02095 const DBusString *contained_type,
02096 int contained_type_start,
02097 DBusTypeWriter *sub)
02098 {
02099 int contained_type_len;
02100
02101 if (contained_type)
02102 contained_type_len = find_len_of_complete_type (contained_type, contained_type_start);
02103 else
02104 contained_type_len = 0;
02105
02106 return _dbus_type_writer_recurse_contained_len (writer, container_type,
02107 contained_type,
02108 contained_type_start,
02109 contained_type_len,
02110 sub,
02111 FALSE);
02112 }
02113
02126 dbus_bool_t
02127 _dbus_type_writer_append_array (DBusTypeWriter *writer,
02128 const DBusString *contained_type,
02129 int contained_type_start,
02130 DBusTypeWriter *sub)
02131 {
02132 int contained_type_len;
02133
02134 if (contained_type)
02135 contained_type_len = find_len_of_complete_type (contained_type, contained_type_start);
02136 else
02137 contained_type_len = 0;
02138
02139 return _dbus_type_writer_recurse_contained_len (writer, DBUS_TYPE_ARRAY,
02140 contained_type,
02141 contained_type_start,
02142 contained_type_len,
02143 sub,
02144 TRUE);
02145 }
02146
02147 static int
02148 writer_get_array_len (DBusTypeWriter *writer)
02149 {
02150 _dbus_assert (writer->container_type == DBUS_TYPE_ARRAY);
02151 return writer->value_pos - writer->u.array.start_pos;
02152 }
02153
02162 dbus_bool_t
02163 _dbus_type_writer_unrecurse (DBusTypeWriter *writer,
02164 DBusTypeWriter *sub)
02165 {
02166
02167 _dbus_assert (!writer->type_pos_is_expectation ||
02168 (writer->type_pos_is_expectation && sub->type_pos_is_expectation));
02169
02170 #if RECURSIVE_MARSHAL_WRITE_TRACE
02171 _dbus_verbose (" type writer %p unrecurse type_pos = %d value_pos = %d is_expectation = %d container_type = %s\n",
02172 writer, writer->type_pos, writer->value_pos, writer->type_pos_is_expectation,
02173 _dbus_type_to_string (writer->container_type));
02174 _dbus_verbose (" type writer %p unrecurse sub type_pos = %d value_pos = %d is_expectation = %d container_type = %s\n",
02175 sub, sub->type_pos, sub->value_pos,
02176 sub->type_pos_is_expectation,
02177 _dbus_type_to_string (sub->container_type));
02178 #endif
02179
02180 if (sub->container_type == DBUS_TYPE_STRUCT)
02181 {
02182 if (!write_or_verify_typecode (sub, DBUS_STRUCT_END_CHAR))
02183 return FALSE;
02184 }
02185 else if (sub->container_type == DBUS_TYPE_DICT_ENTRY)
02186 {
02187 if (!write_or_verify_typecode (sub, DBUS_DICT_ENTRY_END_CHAR))
02188 return FALSE;
02189 }
02190 else if (sub->container_type == DBUS_TYPE_ARRAY)
02191 {
02192 if (sub->u.array.len_pos >= 0)
02193 {
02194 dbus_uint32_t len;
02195
02196
02197 len = writer_get_array_len (sub);
02198 _dbus_marshal_set_uint32 (sub->value_str,
02199 sub->u.array.len_pos,
02200 len,
02201 sub->byte_order);
02202 #if RECURSIVE_MARSHAL_WRITE_TRACE
02203 _dbus_verbose (" filled in sub array len to %u at len_pos %d\n",
02204 len, sub->u.array.len_pos);
02205 #endif
02206 }
02207 #if RECURSIVE_MARSHAL_WRITE_TRACE
02208 else
02209 {
02210 _dbus_verbose (" not filling in sub array len because we were disabled when we passed the len\n");
02211 }
02212 #endif
02213 }
02214
02215
02216
02217
02218
02219
02220
02221
02222
02223
02224
02225
02226
02227
02228
02229
02230
02231
02232
02233
02234
02235
02236
02237
02238
02239
02240
02241
02242
02243
02244
02245
02246
02247
02248
02249
02250
02251
02252
02253
02254
02255
02256
02257
02258
02259
02260 if (writer->type_str != NULL)
02261 {
02262 if ((sub->container_type == DBUS_TYPE_STRUCT ||
02263 sub->container_type == DBUS_TYPE_DICT_ENTRY) &&
02264 (writer->container_type == DBUS_TYPE_STRUCT ||
02265 writer->container_type == DBUS_TYPE_DICT_ENTRY ||
02266 writer->container_type == DBUS_TYPE_INVALID))
02267 {
02268
02269 writer->type_pos = sub->type_pos;
02270 }
02271 }
02272
02273 writer->value_pos = sub->value_pos;
02274
02275 #if RECURSIVE_MARSHAL_WRITE_TRACE
02276 _dbus_verbose (" type writer %p unrecursed type_pos = %d value_pos = %d remaining sig '%s'\n",
02277 writer, writer->type_pos, writer->value_pos,
02278 writer->type_str ?
02279 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0) :
02280 "unknown");
02281 #endif
02282
02283 return TRUE;
02284 }
02285
02294 dbus_bool_t
02295 _dbus_type_writer_write_basic (DBusTypeWriter *writer,
02296 int type,
02297 const void *value)
02298 {
02299 dbus_bool_t retval;
02300
02301
02302 if (!writer->type_pos_is_expectation && writer->type_str != NULL)
02303 {
02304 if (!_dbus_string_alloc_space (writer->type_str, 1))
02305 return FALSE;
02306 }
02307
02308 retval = FALSE;
02309
02310 if (!_dbus_type_writer_write_basic_no_typecode (writer, type, value))
02311 goto out;
02312
02313 if (!write_or_verify_typecode (writer, type))
02314 _dbus_assert_not_reached ("failed to write typecode after prealloc");
02315
02316 retval = TRUE;
02317
02318 out:
02319 #if RECURSIVE_MARSHAL_WRITE_TRACE
02320 _dbus_verbose (" type writer %p basic type_pos = %d value_pos = %d is_expectation = %d enabled = %d\n",
02321 writer, writer->type_pos, writer->value_pos, writer->type_pos_is_expectation,
02322 writer->enabled);
02323 #endif
02324
02325 return retval;
02326 }
02327
02342 dbus_bool_t
02343 _dbus_type_writer_write_fixed_multi (DBusTypeWriter *writer,
02344 int element_type,
02345 const void *value,
02346 int n_elements)
02347 {
02348 _dbus_assert (writer->container_type == DBUS_TYPE_ARRAY);
02349 _dbus_assert (dbus_type_is_fixed (element_type));
02350 _dbus_assert (writer->type_pos_is_expectation);
02351 _dbus_assert (n_elements >= 0);
02352
02353 #if RECURSIVE_MARSHAL_WRITE_TRACE
02354 _dbus_verbose (" type writer %p entering fixed multi type_pos = %d value_pos = %d n_elements %d\n",
02355 writer, writer->type_pos, writer->value_pos, n_elements);
02356 #endif
02357
02358 if (!write_or_verify_typecode (writer, element_type))
02359 _dbus_assert_not_reached ("OOM should not happen if only verifying typecode");
02360
02361 if (writer->enabled)
02362 {
02363 if (!_dbus_marshal_write_fixed_multi (writer->value_str,
02364 writer->value_pos,
02365 element_type,
02366 value,
02367 n_elements,
02368 writer->byte_order,
02369 &writer->value_pos))
02370 return FALSE;
02371 }
02372
02373 #if RECURSIVE_MARSHAL_WRITE_TRACE
02374 _dbus_verbose (" type writer %p fixed multi written new type_pos = %d new value_pos = %d n_elements %d\n",
02375 writer, writer->type_pos, writer->value_pos, n_elements);
02376 #endif
02377
02378 return TRUE;
02379 }
02380
02381 static void
02382 enable_if_after (DBusTypeWriter *writer,
02383 DBusTypeReader *reader,
02384 const DBusTypeReader *start_after)
02385 {
02386 if (start_after)
02387 {
02388 if (!writer->enabled && _dbus_type_reader_greater_than (reader, start_after))
02389 {
02390 _dbus_type_writer_set_enabled (writer, TRUE);
02391 #if RECURSIVE_MARSHAL_WRITE_TRACE
02392 _dbus_verbose ("ENABLING writer %p at %d because reader at value_pos %d is after reader at value_pos %d\n",
02393 writer, writer->value_pos, reader->value_pos, start_after->value_pos);
02394 #endif
02395 }
02396
02397 _dbus_assert ((!writer->enabled && !_dbus_type_reader_greater_than (reader, start_after)) ||
02398 (writer->enabled && _dbus_type_reader_greater_than (reader, start_after)));
02399 }
02400 }
02401
02402 static dbus_bool_t
02403 append_fixup (DBusList **fixups,
02404 const DBusArrayLenFixup *fixup)
02405 {
02406 DBusArrayLenFixup *f;
02407
02408 f = dbus_new (DBusArrayLenFixup, 1);
02409 if (f == NULL)
02410 return FALSE;
02411
02412 *f = *fixup;
02413
02414 if (!_dbus_list_append (fixups, f))
02415 {
02416 dbus_free (f);
02417 return FALSE;
02418 }
02419
02420 _dbus_assert (f->len_pos_in_reader == fixup->len_pos_in_reader);
02421 _dbus_assert (f->new_len == fixup->new_len);
02422
02423 return TRUE;
02424 }
02425
02426
02427
02428
02429 static dbus_bool_t
02430 writer_write_reader_helper (DBusTypeWriter *writer,
02431 DBusTypeReader *reader,
02432 const DBusTypeReader *start_after,
02433 int start_after_new_pos,
02434 int start_after_new_len,
02435 DBusList **fixups,
02436 dbus_bool_t inside_start_after)
02437 {
02438 int current_type;
02439
02440 while ((current_type = _dbus_type_reader_get_current_type (reader)) != DBUS_TYPE_INVALID)
02441 {
02442 if (dbus_type_is_container (current_type))
02443 {
02444 DBusTypeReader subreader;
02445 DBusTypeWriter subwriter;
02446 const DBusString *sig_str;
02447 int sig_start;
02448 int sig_len;
02449 dbus_bool_t enabled_at_recurse;
02450 dbus_bool_t past_start_after;
02451 int reader_array_len_pos;
02452 int reader_array_start_pos;
02453 dbus_bool_t this_is_start_after;
02454
02455
02456
02457
02458
02459
02460 if (!inside_start_after && start_after &&
02461 reader->value_pos == start_after->value_pos &&
02462 reader->type_str == start_after->type_str &&
02463 reader->type_pos == start_after->type_pos)
02464 this_is_start_after = TRUE;
02465 else
02466 this_is_start_after = FALSE;
02467
02468 _dbus_type_reader_recurse (reader, &subreader);
02469
02470 if (current_type == DBUS_TYPE_ARRAY)
02471 {
02472 reader_array_len_pos = ARRAY_READER_LEN_POS (&subreader);
02473 reader_array_start_pos = subreader.u.array.start_pos;
02474 }
02475 else
02476 {
02477
02478 reader_array_len_pos = -1;
02479 reader_array_start_pos = -1;
02480 }
02481
02482 _dbus_type_reader_get_signature (&subreader, &sig_str,
02483 &sig_start, &sig_len);
02484
02485 #if RECURSIVE_MARSHAL_WRITE_TRACE
02486 _dbus_verbose ("about to recurse into %s reader at %d subreader at %d writer at %d start_after reader at %d write target len %d inside_start_after = %d this_is_start_after = %d\n",
02487 _dbus_type_to_string (current_type),
02488 reader->value_pos,
02489 subreader.value_pos,
02490 writer->value_pos,
02491 start_after ? start_after->value_pos : -1,
02492 _dbus_string_get_length (writer->value_str),
02493 inside_start_after, this_is_start_after);
02494 #endif
02495
02496 if (!inside_start_after && !this_is_start_after)
02497 enable_if_after (writer, &subreader, start_after);
02498 enabled_at_recurse = writer->enabled;
02499 if (!_dbus_type_writer_recurse_contained_len (writer, current_type,
02500 sig_str, sig_start, sig_len,
02501 &subwriter, FALSE))
02502 goto oom;
02503
02504 #if RECURSIVE_MARSHAL_WRITE_TRACE
02505 _dbus_verbose ("recursed into subwriter at %d write target len %d\n",
02506 subwriter.value_pos,
02507 _dbus_string_get_length (subwriter.value_str));
02508 #endif
02509
02510 if (!writer_write_reader_helper (&subwriter, &subreader, start_after,
02511 start_after_new_pos, start_after_new_len,
02512 fixups,
02513 inside_start_after ||
02514 this_is_start_after))
02515 goto oom;
02516
02517 #if RECURSIVE_MARSHAL_WRITE_TRACE
02518 _dbus_verbose ("about to unrecurse from %s subreader at %d writer at %d subwriter at %d write target len %d\n",
02519 _dbus_type_to_string (current_type),
02520 subreader.value_pos,
02521 writer->value_pos,
02522 subwriter.value_pos,
02523 _dbus_string_get_length (writer->value_str));
02524 #endif
02525
02526 if (!inside_start_after && !this_is_start_after)
02527 enable_if_after (writer, &subreader, start_after);
02528 past_start_after = writer->enabled;
02529 if (!_dbus_type_writer_unrecurse (writer, &subwriter))
02530 goto oom;
02531
02532
02533
02534
02535
02536
02537 if (start_after != NULL &&
02538 !enabled_at_recurse && past_start_after &&
02539 current_type == DBUS_TYPE_ARRAY &&
02540 fixups != NULL)
02541 {
02542 DBusArrayLenFixup fixup;
02543 int bytes_written_after_start_after;
02544 int bytes_before_start_after;
02545 int old_len;
02546
02547
02548
02549
02550
02551 bytes_written_after_start_after = writer_get_array_len (&subwriter);
02552
02553 bytes_before_start_after =
02554 start_after->value_pos - reader_array_start_pos;
02555
02556 fixup.len_pos_in_reader = reader_array_len_pos;
02557 fixup.new_len =
02558 bytes_before_start_after +
02559 start_after_new_len +
02560 bytes_written_after_start_after;
02561
02562 _dbus_assert (_DBUS_ALIGN_VALUE (fixup.len_pos_in_reader, 4) ==
02563 (unsigned) fixup.len_pos_in_reader);
02564
02565 old_len = _dbus_unpack_uint32 (reader->byte_order,
02566 _dbus_string_get_const_data_len (reader->value_str,
02567 fixup.len_pos_in_reader, 4));
02568
02569 if (old_len != fixup.new_len && !append_fixup (fixups, &fixup))
02570 goto oom;
02571
02572 #if RECURSIVE_MARSHAL_WRITE_TRACE
02573 _dbus_verbose ("Generated fixup len_pos_in_reader = %d new_len = %d reader_array_start_pos = %d start_after->value_pos = %d bytes_before_start_after = %d start_after_new_len = %d bytes_written_after_start_after = %d\n",
02574 fixup.len_pos_in_reader,
02575 fixup.new_len,
02576 reader_array_start_pos,
02577 start_after->value_pos,
02578 bytes_before_start_after,
02579 start_after_new_len,
02580 bytes_written_after_start_after);
02581 #endif
02582 }
02583 }
02584 else
02585 {
02586 DBusBasicValue val;
02587
02588 _dbus_assert (dbus_type_is_basic (current_type));
02589
02590 #if RECURSIVE_MARSHAL_WRITE_TRACE
02591 _dbus_verbose ("Reading basic value %s at %d\n",
02592 _dbus_type_to_string (current_type),
02593 reader->value_pos);
02594 #endif
02595
02596 _dbus_type_reader_read_basic (reader, &val);
02597
02598 #if RECURSIVE_MARSHAL_WRITE_TRACE
02599 _dbus_verbose ("Writing basic value %s at %d write target len %d inside_start_after = %d\n",
02600 _dbus_type_to_string (current_type),
02601 writer->value_pos,
02602 _dbus_string_get_length (writer->value_str),
02603 inside_start_after);
02604 #endif
02605 if (!inside_start_after)
02606 enable_if_after (writer, reader, start_after);
02607 if (!_dbus_type_writer_write_basic (writer, current_type, &val))
02608 goto oom;
02609 #if RECURSIVE_MARSHAL_WRITE_TRACE
02610 _dbus_verbose ("Wrote basic value %s, new value_pos %d write target len %d\n",
02611 _dbus_type_to_string (current_type),
02612 writer->value_pos,
02613 _dbus_string_get_length (writer->value_str));
02614 #endif
02615 }
02616
02617 _dbus_type_reader_next (reader);
02618 }
02619
02620 return TRUE;
02621
02622 oom:
02623 if (fixups)
02624 apply_and_free_fixups (fixups, NULL);
02625
02626 return FALSE;
02627 }
02628
02660 dbus_bool_t
02661 _dbus_type_writer_write_reader_partial (DBusTypeWriter *writer,
02662 DBusTypeReader *reader,
02663 const DBusTypeReader *start_after,
02664 int start_after_new_pos,
02665 int start_after_new_len,
02666 DBusList **fixups)
02667 {
02668 DBusTypeWriter orig;
02669 int orig_type_len;
02670 int orig_value_len;
02671 int new_bytes;
02672 int orig_enabled;
02673
02674 orig = *writer;
02675 orig_type_len = _dbus_string_get_length (writer->type_str);
02676 orig_value_len = _dbus_string_get_length (writer->value_str);
02677 orig_enabled = writer->enabled;
02678
02679 if (start_after)
02680 _dbus_type_writer_set_enabled (writer, FALSE);
02681
02682 if (!writer_write_reader_helper (writer, reader, start_after,
02683 start_after_new_pos,
02684 start_after_new_len,
02685 fixups, FALSE))
02686 goto oom;
02687
02688 _dbus_type_writer_set_enabled (writer, orig_enabled);
02689 return TRUE;
02690
02691 oom:
02692 if (!writer->type_pos_is_expectation)
02693 {
02694 new_bytes = _dbus_string_get_length (writer->type_str) - orig_type_len;
02695 _dbus_string_delete (writer->type_str, orig.type_pos, new_bytes);
02696 }
02697 new_bytes = _dbus_string_get_length (writer->value_str) - orig_value_len;
02698 _dbus_string_delete (writer->value_str, orig.value_pos, new_bytes);
02699
02700 *writer = orig;
02701
02702 return FALSE;
02703 }
02704
02714 dbus_bool_t
02715 _dbus_type_writer_write_reader (DBusTypeWriter *writer,
02716 DBusTypeReader *reader)
02717 {
02718 return _dbus_type_writer_write_reader_partial (writer, reader, NULL, 0, 0, NULL);
02719 }
02720
02730 void
02731 _dbus_type_writer_set_enabled (DBusTypeWriter *writer,
02732 dbus_bool_t enabled)
02733 {
02734 writer->enabled = enabled != FALSE;
02735 }
02736
02738
02739