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 static const DBusTypeReaderClass const *
00694 all_reader_classes[] = {
00695 &body_reader_class,
00696 &body_types_only_reader_class,
00697 &struct_reader_class,
00698 &struct_types_only_reader_class,
00699 &dict_entry_reader_class,
00700 &dict_entry_types_only_reader_class,
00701 &array_reader_class,
00702 &array_types_only_reader_class,
00703 &variant_reader_class
00704 };
00705
00716 void
00717 _dbus_type_reader_init (DBusTypeReader *reader,
00718 int byte_order,
00719 const DBusString *type_str,
00720 int type_pos,
00721 const DBusString *value_str,
00722 int value_pos)
00723 {
00724 reader->klass = &body_reader_class;
00725
00726 reader_init (reader, byte_order, type_str, type_pos,
00727 value_str, value_pos);
00728
00729 #if RECURSIVE_MARSHAL_READ_TRACE
00730 _dbus_verbose (" type reader %p init type_pos = %d value_pos = %d remaining sig '%s'\n",
00731 reader, reader->type_pos, reader->value_pos,
00732 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0));
00733 #endif
00734 }
00735
00744 void
00745 _dbus_type_reader_init_types_only (DBusTypeReader *reader,
00746 const DBusString *type_str,
00747 int type_pos)
00748 {
00749 reader->klass = &body_types_only_reader_class;
00750
00751 reader_init (reader, DBUS_COMPILER_BYTE_ORDER ,
00752 type_str, type_pos, NULL, _DBUS_INT_MAX );
00753
00754 #if RECURSIVE_MARSHAL_READ_TRACE
00755 _dbus_verbose (" type reader %p init types only type_pos = %d remaining sig '%s'\n",
00756 reader, reader->type_pos,
00757 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0));
00758 #endif
00759 }
00760
00769 int
00770 _dbus_type_reader_get_current_type (const DBusTypeReader *reader)
00771 {
00772 int t;
00773
00774 if (reader->finished ||
00775 (reader->klass->check_finished &&
00776 (* reader->klass->check_finished) (reader)))
00777 t = DBUS_TYPE_INVALID;
00778 else
00779 t = _dbus_first_type_in_signature (reader->type_str,
00780 reader->type_pos);
00781
00782 _dbus_assert (t != DBUS_STRUCT_END_CHAR);
00783 _dbus_assert (t != DBUS_STRUCT_BEGIN_CHAR);
00784 _dbus_assert (t != DBUS_DICT_ENTRY_END_CHAR);
00785 _dbus_assert (t != DBUS_DICT_ENTRY_BEGIN_CHAR);
00786
00787 #if 0
00788 _dbus_verbose (" type reader %p current type_pos = %d type = %s\n",
00789 reader, reader->type_pos,
00790 _dbus_type_to_string (t));
00791 #endif
00792
00793 return t;
00794 }
00795
00804 int
00805 _dbus_type_reader_get_element_type (const DBusTypeReader *reader)
00806 {
00807 int element_type;
00808
00809 _dbus_assert (_dbus_type_reader_get_current_type (reader) == DBUS_TYPE_ARRAY);
00810
00811 element_type = _dbus_first_type_in_signature (reader->type_str,
00812 reader->type_pos + 1);
00813
00814 return element_type;
00815 }
00816
00821 int
00822 _dbus_type_reader_get_value_pos (const DBusTypeReader *reader)
00823 {
00824 return reader->value_pos;
00825 }
00826
00836 void
00837 _dbus_type_reader_read_raw (const DBusTypeReader *reader,
00838 const unsigned char **value_location)
00839 {
00840 _dbus_assert (!reader->klass->types_only);
00841
00842 *value_location = _dbus_string_get_const_data_len (reader->value_str,
00843 reader->value_pos,
00844 0);
00845 }
00846
00853 void
00854 _dbus_type_reader_read_basic (const DBusTypeReader *reader,
00855 void *value)
00856 {
00857 int t;
00858
00859 _dbus_assert (!reader->klass->types_only);
00860
00861 t = _dbus_type_reader_get_current_type (reader);
00862
00863 _dbus_marshal_read_basic (reader->value_str,
00864 reader->value_pos,
00865 t, value,
00866 reader->byte_order,
00867 NULL);
00868
00869
00870 #if RECURSIVE_MARSHAL_READ_TRACE
00871 _dbus_verbose (" type reader %p read basic type_pos = %d value_pos = %d remaining sig '%s'\n",
00872 reader, reader->type_pos, reader->value_pos,
00873 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0));
00874 #endif
00875 }
00876
00883 int
00884 _dbus_type_reader_get_array_length (const DBusTypeReader *reader)
00885 {
00886 _dbus_assert (!reader->klass->types_only);
00887 _dbus_assert (reader->klass == &array_reader_class);
00888
00889 return array_reader_get_array_len (reader);
00890 }
00891
00907 void
00908 _dbus_type_reader_read_fixed_multi (const DBusTypeReader *reader,
00909 void *value,
00910 int *n_elements)
00911 {
00912 int element_type;
00913 int end_pos;
00914 int remaining_len;
00915 int alignment;
00916 int total_len;
00917
00918 _dbus_assert (!reader->klass->types_only);
00919 _dbus_assert (reader->klass == &array_reader_class);
00920
00921 element_type = _dbus_first_type_in_signature (reader->type_str,
00922 reader->type_pos);
00923
00924 _dbus_assert (element_type != DBUS_TYPE_INVALID);
00925 _dbus_assert (dbus_type_is_fixed (element_type));
00926
00927 alignment = _dbus_type_get_alignment (element_type);
00928
00929 _dbus_assert (reader->value_pos >= reader->u.array.start_pos);
00930
00931 total_len = array_reader_get_array_len (reader);
00932 end_pos = reader->u.array.start_pos + total_len;
00933 remaining_len = end_pos - reader->value_pos;
00934
00935 #if RECURSIVE_MARSHAL_READ_TRACE
00936 _dbus_verbose ("end_pos %d total_len %d remaining_len %d value_pos %d\n",
00937 end_pos, total_len, remaining_len, reader->value_pos);
00938 #endif
00939
00940 _dbus_assert (remaining_len <= total_len);
00941
00942 if (remaining_len == 0)
00943 *(const DBusBasicValue**) value = NULL;
00944 else
00945 *(const DBusBasicValue**) value =
00946 (void*) _dbus_string_get_const_data_len (reader->value_str,
00947 reader->value_pos,
00948 remaining_len);
00949
00950 *n_elements = remaining_len / alignment;
00951 _dbus_assert ((remaining_len % alignment) == 0);
00952
00953 #if RECURSIVE_MARSHAL_READ_TRACE
00954 _dbus_verbose (" type reader %p read fixed array type_pos = %d value_pos = %d remaining sig '%s'\n",
00955 reader, reader->type_pos, reader->value_pos,
00956 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0));
00957 #endif
00958 }
00959
00972 void
00973 _dbus_type_reader_recurse (DBusTypeReader *reader,
00974 DBusTypeReader *sub)
00975 {
00976 int t;
00977
00978 t = _dbus_first_type_in_signature (reader->type_str, reader->type_pos);
00979
00980 switch (t)
00981 {
00982 case DBUS_TYPE_STRUCT:
00983 if (reader->klass->types_only)
00984 sub->klass = &struct_types_only_reader_class;
00985 else
00986 sub->klass = &struct_reader_class;
00987 break;
00988 case DBUS_TYPE_DICT_ENTRY:
00989 if (reader->klass->types_only)
00990 sub->klass = &dict_entry_types_only_reader_class;
00991 else
00992 sub->klass = &dict_entry_reader_class;
00993 break;
00994 case DBUS_TYPE_ARRAY:
00995 if (reader->klass->types_only)
00996 sub->klass = &array_types_only_reader_class;
00997 else
00998 sub->klass = &array_reader_class;
00999 break;
01000 case DBUS_TYPE_VARIANT:
01001 if (reader->klass->types_only)
01002 _dbus_assert_not_reached ("can't recurse into variant typecode");
01003 else
01004 sub->klass = &variant_reader_class;
01005 break;
01006 default:
01007 _dbus_verbose ("recursing into type %s\n", _dbus_type_to_string (t));
01008 #ifndef DBUS_DISABLE_CHECKS
01009 if (t == DBUS_TYPE_INVALID)
01010 _dbus_warn_check_failed ("You can't recurse into an empty array or off the end of a message body\n");
01011 #endif
01012
01013 _dbus_assert_not_reached ("don't yet handle recursing into this type");
01014 }
01015
01016 _dbus_assert (sub->klass == all_reader_classes[sub->klass->id]);
01017
01018 (* sub->klass->recurse) (sub, reader);
01019
01020 #if RECURSIVE_MARSHAL_READ_TRACE
01021 _dbus_verbose (" type reader %p RECURSED type_pos = %d value_pos = %d remaining sig '%s'\n",
01022 sub, sub->type_pos, sub->value_pos,
01023 _dbus_string_get_const_data_len (sub->type_str, sub->type_pos, 0));
01024 #endif
01025 }
01026
01035 dbus_bool_t
01036 _dbus_type_reader_next (DBusTypeReader *reader)
01037 {
01038 int t;
01039
01040 t = _dbus_type_reader_get_current_type (reader);
01041
01042 #if RECURSIVE_MARSHAL_READ_TRACE
01043 _dbus_verbose (" type reader %p START next() { type_pos = %d value_pos = %d remaining sig '%s' current_type = %s\n",
01044 reader, reader->type_pos, reader->value_pos,
01045 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0),
01046 _dbus_type_to_string (t));
01047 #endif
01048
01049 if (t == DBUS_TYPE_INVALID)
01050 return FALSE;
01051
01052 (* reader->klass->next) (reader, t);
01053
01054 #if RECURSIVE_MARSHAL_READ_TRACE
01055 _dbus_verbose (" type reader %p END next() type_pos = %d value_pos = %d remaining sig '%s' current_type = %s\n",
01056 reader, reader->type_pos, reader->value_pos,
01057 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0),
01058 _dbus_type_to_string (_dbus_type_reader_get_current_type (reader)));
01059 #endif
01060
01061 return _dbus_type_reader_get_current_type (reader) != DBUS_TYPE_INVALID;
01062 }
01063
01075 dbus_bool_t
01076 _dbus_type_reader_has_next (const DBusTypeReader *reader)
01077 {
01078
01079 DBusTypeReader copy;
01080
01081 copy = *reader;
01082 return _dbus_type_reader_next (©);
01083 }
01084
01106 void
01107 _dbus_type_reader_get_signature (const DBusTypeReader *reader,
01108 const DBusString **str_p,
01109 int *start_p,
01110 int *len_p)
01111 {
01112 *str_p = reader->type_str;
01113 *start_p = reader->type_pos;
01114 *len_p = find_len_of_complete_type (reader->type_str, reader->type_pos);
01115 }
01116
01117 typedef struct
01118 {
01119 DBusString replacement;
01120 int padding;
01121 } ReplacementBlock;
01122
01123 static dbus_bool_t
01124 replacement_block_init (ReplacementBlock *block,
01125 DBusTypeReader *reader)
01126 {
01127 if (!_dbus_string_init (&block->replacement))
01128 return FALSE;
01129
01130
01131
01132
01133 block->padding = reader->value_pos % 8;
01134
01135 if (!_dbus_string_lengthen (&block->replacement, block->padding))
01136 goto oom;
01137
01138 return TRUE;
01139
01140 oom:
01141 _dbus_string_free (&block->replacement);
01142 return FALSE;
01143 }
01144
01145 static dbus_bool_t
01146 replacement_block_replace (ReplacementBlock *block,
01147 DBusTypeReader *reader,
01148 const DBusTypeReader *realign_root)
01149 {
01150 DBusTypeWriter writer;
01151 DBusTypeReader realign_reader;
01152 DBusList *fixups;
01153 int orig_len;
01154
01155 _dbus_assert (realign_root != NULL);
01156
01157 orig_len = _dbus_string_get_length (&block->replacement);
01158
01159 realign_reader = *realign_root;
01160
01161 #if RECURSIVE_MARSHAL_WRITE_TRACE
01162 _dbus_verbose ("INITIALIZING replacement block writer %p at value_pos %d\n",
01163 &writer, _dbus_string_get_length (&block->replacement));
01164 #endif
01165 _dbus_type_writer_init_values_only (&writer,
01166 realign_reader.byte_order,
01167 realign_reader.type_str,
01168 realign_reader.type_pos,
01169 &block->replacement,
01170 _dbus_string_get_length (&block->replacement));
01171
01172 _dbus_assert (realign_reader.value_pos <= reader->value_pos);
01173
01174 #if RECURSIVE_MARSHAL_WRITE_TRACE
01175 _dbus_verbose ("COPYING from reader at value_pos %d to writer %p starting after value_pos %d\n",
01176 realign_reader.value_pos, &writer, reader->value_pos);
01177 #endif
01178 fixups = NULL;
01179 if (!_dbus_type_writer_write_reader_partial (&writer,
01180 &realign_reader,
01181 reader,
01182 block->padding,
01183 _dbus_string_get_length (&block->replacement) - block->padding,
01184 &fixups))
01185 goto oom;
01186
01187 #if RECURSIVE_MARSHAL_WRITE_TRACE
01188 _dbus_verbose ("REPLACEMENT at padding %d len %d\n", block->padding,
01189 _dbus_string_get_length (&block->replacement) - block->padding);
01190 _dbus_verbose_bytes_of_string (&block->replacement, block->padding,
01191 _dbus_string_get_length (&block->replacement) - block->padding);
01192 _dbus_verbose ("TO BE REPLACED at value_pos = %d (align pad %d) len %d realign_reader.value_pos %d\n",
01193 reader->value_pos, reader->value_pos % 8,
01194 realign_reader.value_pos - reader->value_pos,
01195 realign_reader.value_pos);
01196 _dbus_verbose_bytes_of_string (reader->value_str,
01197 reader->value_pos,
01198 realign_reader.value_pos - reader->value_pos);
01199 #endif
01200
01201
01202
01203
01204 if (!_dbus_string_replace_len (&block->replacement, block->padding,
01205 _dbus_string_get_length (&block->replacement) - block->padding,
01206 (DBusString*) reader->value_str,
01207 reader->value_pos,
01208 realign_reader.value_pos - reader->value_pos))
01209 goto oom;
01210
01211
01212 apply_and_free_fixups (&fixups, reader);
01213
01214 return TRUE;
01215
01216 oom:
01217 _dbus_string_set_length (&block->replacement, orig_len);
01218 free_fixups (&fixups);
01219 return FALSE;
01220 }
01221
01222 static void
01223 replacement_block_free (ReplacementBlock *block)
01224 {
01225 _dbus_string_free (&block->replacement);
01226 }
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251 static dbus_bool_t
01252 reader_set_basic_variable_length (DBusTypeReader *reader,
01253 int current_type,
01254 const void *value,
01255 const DBusTypeReader *realign_root)
01256 {
01257 dbus_bool_t retval;
01258 ReplacementBlock block;
01259 DBusTypeWriter writer;
01260
01261 _dbus_assert (realign_root != NULL);
01262
01263 retval = FALSE;
01264
01265 if (!replacement_block_init (&block, reader))
01266 return FALSE;
01267
01268
01269 #if RECURSIVE_MARSHAL_WRITE_TRACE
01270 _dbus_verbose ("INITIALIZING writer %p to write basic value at value_pos %d of replacement string\n",
01271 &writer, _dbus_string_get_length (&block.replacement));
01272 #endif
01273 _dbus_type_writer_init_values_only (&writer,
01274 reader->byte_order,
01275 reader->type_str,
01276 reader->type_pos,
01277 &block.replacement,
01278 _dbus_string_get_length (&block.replacement));
01279 #if RECURSIVE_MARSHAL_WRITE_TRACE
01280 _dbus_verbose ("WRITING basic value to writer %p (replacement string)\n", &writer);
01281 #endif
01282 if (!_dbus_type_writer_write_basic (&writer, current_type, value))
01283 goto out;
01284
01285 if (!replacement_block_replace (&block,
01286 reader,
01287 realign_root))
01288 goto out;
01289
01290 retval = TRUE;
01291
01292 out:
01293 replacement_block_free (&block);
01294 return retval;
01295 }
01296
01297 static void
01298 reader_set_basic_fixed_length (DBusTypeReader *reader,
01299 int current_type,
01300 const void *value)
01301 {
01302 _dbus_marshal_set_basic ((DBusString*) reader->value_str,
01303 reader->value_pos,
01304 current_type,
01305 value,
01306 reader->byte_order,
01307 NULL, NULL);
01308 }
01309
01344 dbus_bool_t
01345 _dbus_type_reader_set_basic (DBusTypeReader *reader,
01346 const void *value,
01347 const DBusTypeReader *realign_root)
01348 {
01349 int current_type;
01350
01351 _dbus_assert (!reader->klass->types_only);
01352 _dbus_assert (reader->value_str == realign_root->value_str);
01353 _dbus_assert (reader->value_pos >= realign_root->value_pos);
01354
01355 current_type = _dbus_type_reader_get_current_type (reader);
01356
01357 #if RECURSIVE_MARSHAL_WRITE_TRACE
01358 _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",
01359 reader, reader->type_pos, reader->value_pos,
01360 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0),
01361 realign_root,
01362 realign_root ? realign_root->value_pos : -1,
01363 _dbus_type_to_string (current_type));
01364 _dbus_verbose_bytes_of_string (realign_root->value_str, realign_root->value_pos,
01365 _dbus_string_get_length (realign_root->value_str) -
01366 realign_root->value_pos);
01367 #endif
01368
01369 _dbus_assert (dbus_type_is_basic (current_type));
01370
01371 if (dbus_type_is_fixed (current_type))
01372 {
01373 reader_set_basic_fixed_length (reader, current_type, value);
01374 return TRUE;
01375 }
01376 else
01377 {
01378 _dbus_assert (realign_root != NULL);
01379 return reader_set_basic_variable_length (reader, current_type,
01380 value, realign_root);
01381 }
01382 }
01383
01401 dbus_bool_t
01402 _dbus_type_reader_delete (DBusTypeReader *reader,
01403 const DBusTypeReader *realign_root)
01404 {
01405 dbus_bool_t retval;
01406 ReplacementBlock block;
01407
01408 _dbus_assert (realign_root != NULL);
01409 _dbus_assert (reader->klass == &array_reader_class);
01410
01411 retval = FALSE;
01412
01413 if (!replacement_block_init (&block, reader))
01414 return FALSE;
01415
01416 if (!replacement_block_replace (&block,
01417 reader,
01418 realign_root))
01419 goto out;
01420
01421 retval = TRUE;
01422
01423 out:
01424 replacement_block_free (&block);
01425 return retval;
01426 }
01427
01436 dbus_bool_t
01437 _dbus_type_reader_greater_than (const DBusTypeReader *lhs,
01438 const DBusTypeReader *rhs)
01439 {
01440 _dbus_assert (lhs->value_str == rhs->value_str);
01441
01442 return lhs->value_pos > rhs->value_pos;
01443 }
01444
01445
01446
01447
01448
01449
01450
01451
01452
01453
01474 void
01475 _dbus_type_writer_init (DBusTypeWriter *writer,
01476 int byte_order,
01477 DBusString *type_str,
01478 int type_pos,
01479 DBusString *value_str,
01480 int value_pos)
01481 {
01482 writer->byte_order = byte_order;
01483 writer->type_str = type_str;
01484 writer->type_pos = type_pos;
01485 writer->value_str = value_str;
01486 writer->value_pos = value_pos;
01487 writer->container_type = DBUS_TYPE_INVALID;
01488 writer->type_pos_is_expectation = FALSE;
01489 writer->enabled = TRUE;
01490
01491 #if RECURSIVE_MARSHAL_WRITE_TRACE
01492 _dbus_verbose ("writer %p init remaining sig '%s'\n", writer,
01493 writer->type_str ?
01494 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0) :
01495 "unknown");
01496 #endif
01497 }
01498
01509 void
01510 _dbus_type_writer_init_types_delayed (DBusTypeWriter *writer,
01511 int byte_order,
01512 DBusString *value_str,
01513 int value_pos)
01514 {
01515 _dbus_type_writer_init (writer, byte_order,
01516 NULL, 0, value_str, value_pos);
01517 }
01518
01527 void
01528 _dbus_type_writer_add_types (DBusTypeWriter *writer,
01529 DBusString *type_str,
01530 int type_pos)
01531 {
01532 if (writer->type_str == NULL)
01533 {
01534 writer->type_str = type_str;
01535 writer->type_pos = type_pos;
01536 }
01537 }
01538
01544 void
01545 _dbus_type_writer_remove_types (DBusTypeWriter *writer)
01546 {
01547 writer->type_str = NULL;
01548 writer->type_pos = -1;
01549 }
01550
01565 void
01566 _dbus_type_writer_init_values_only (DBusTypeWriter *writer,
01567 int byte_order,
01568 const DBusString *type_str,
01569 int type_pos,
01570 DBusString *value_str,
01571 int value_pos)
01572 {
01573 _dbus_type_writer_init (writer, byte_order,
01574 (DBusString*)type_str, type_pos,
01575 value_str, value_pos);
01576
01577 writer->type_pos_is_expectation = TRUE;
01578 }
01579
01580 static dbus_bool_t
01581 _dbus_type_writer_write_basic_no_typecode (DBusTypeWriter *writer,
01582 int type,
01583 const void *value)
01584 {
01585 if (writer->enabled)
01586 return _dbus_marshal_write_basic (writer->value_str,
01587 writer->value_pos,
01588 type,
01589 value,
01590 writer->byte_order,
01591 &writer->value_pos);
01592 else
01593 return TRUE;
01594 }
01595
01596
01597
01598
01599
01600
01601
01602
01603
01604
01605
01606
01607
01608
01609
01610
01611
01612
01613
01614
01615
01616
01617 static void
01618 writer_recurse_init_and_check (DBusTypeWriter *writer,
01619 int container_type,
01620 DBusTypeWriter *sub)
01621 {
01622 _dbus_type_writer_init (sub,
01623 writer->byte_order,
01624 writer->type_str,
01625 writer->type_pos,
01626 writer->value_str,
01627 writer->value_pos);
01628
01629 sub->container_type = container_type;
01630
01631 if (writer->type_pos_is_expectation ||
01632 (sub->container_type == DBUS_TYPE_ARRAY || sub->container_type == DBUS_TYPE_VARIANT))
01633 sub->type_pos_is_expectation = TRUE;
01634 else
01635 sub->type_pos_is_expectation = FALSE;
01636
01637 sub->enabled = writer->enabled;
01638
01639 #ifndef DBUS_DISABLE_CHECKS
01640 if (writer->type_pos_is_expectation && writer->type_str)
01641 {
01642 int expected;
01643
01644 expected = _dbus_first_type_in_signature (writer->type_str, writer->type_pos);
01645
01646 if (expected != sub->container_type)
01647 {
01648 _dbus_warn_check_failed ("Writing an element of type %s, but the expected type here is %s\n",
01649 _dbus_type_to_string (sub->container_type),
01650 _dbus_type_to_string (expected));
01651 _dbus_assert_not_reached ("bad array element or variant content written");
01652 }
01653 }
01654 #endif
01655
01656 #if RECURSIVE_MARSHAL_WRITE_TRACE
01657 _dbus_verbose (" type writer %p recurse parent %s type_pos = %d value_pos = %d is_expectation = %d remaining sig '%s' enabled = %d\n",
01658 writer,
01659 _dbus_type_to_string (writer->container_type),
01660 writer->type_pos, writer->value_pos, writer->type_pos_is_expectation,
01661 writer->type_str ?
01662 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0) :
01663 "unknown",
01664 writer->enabled);
01665 _dbus_verbose (" type writer %p recurse sub %s type_pos = %d value_pos = %d is_expectation = %d enabled = %d\n",
01666 sub,
01667 _dbus_type_to_string (sub->container_type),
01668 sub->type_pos, sub->value_pos,
01669 sub->type_pos_is_expectation,
01670 sub->enabled);
01671 #endif
01672 }
01673
01674 static dbus_bool_t
01675 write_or_verify_typecode (DBusTypeWriter *writer,
01676 int typecode)
01677 {
01678
01679
01680
01681
01682
01683 #if RECURSIVE_MARSHAL_WRITE_TRACE
01684 _dbus_verbose (" type writer %p write_or_verify start type_pos = %d remaining sig '%s' enabled = %d\n",
01685 writer, writer->type_pos,
01686 writer->type_str ?
01687 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0) :
01688 "unknown",
01689 writer->enabled);
01690 #endif
01691
01692 if (writer->type_str == NULL)
01693 return TRUE;
01694
01695 if (writer->type_pos_is_expectation)
01696 {
01697 #ifndef DBUS_DISABLE_CHECKS
01698 {
01699 int expected;
01700
01701 expected = _dbus_string_get_byte (writer->type_str, writer->type_pos);
01702
01703 if (expected != typecode)
01704 {
01705 _dbus_warn_check_failed ("Array or variant type requires that type %s be written, but %s was written\n",
01706 _dbus_type_to_string (expected), _dbus_type_to_string (typecode));
01707 _dbus_assert_not_reached ("bad type inserted somewhere inside an array or variant");
01708 }
01709 }
01710 #endif
01711
01712
01713
01714
01715
01716 if (writer->container_type != DBUS_TYPE_ARRAY)
01717 writer->type_pos += 1;
01718 }
01719 else
01720 {
01721 if (!_dbus_string_insert_byte (writer->type_str,
01722 writer->type_pos,
01723 typecode))
01724 return FALSE;
01725
01726 writer->type_pos += 1;
01727 }
01728
01729 #if RECURSIVE_MARSHAL_WRITE_TRACE
01730 _dbus_verbose (" type writer %p write_or_verify end type_pos = %d remaining sig '%s'\n",
01731 writer, writer->type_pos,
01732 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0));
01733 #endif
01734
01735 return TRUE;
01736 }
01737
01738 static dbus_bool_t
01739 writer_recurse_struct_or_dict_entry (DBusTypeWriter *writer,
01740 int begin_char,
01741 const DBusString *contained_type,
01742 int contained_type_start,
01743 int contained_type_len,
01744 DBusTypeWriter *sub)
01745 {
01746
01747
01748
01749
01750
01751
01752 if (writer->enabled)
01753 {
01754 if (!_dbus_string_alloc_space (sub->value_str, 8))
01755 return FALSE;
01756 }
01757
01758 if (!write_or_verify_typecode (sub, begin_char))
01759 _dbus_assert_not_reached ("failed to insert struct typecode after prealloc");
01760
01761 if (writer->enabled)
01762 {
01763 if (!_dbus_string_insert_bytes (sub->value_str,
01764 sub->value_pos,
01765 _DBUS_ALIGN_VALUE (sub->value_pos, 8) - sub->value_pos,
01766 '\0'))
01767 _dbus_assert_not_reached ("should not have failed to insert alignment padding for struct");
01768 sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 8);
01769 }
01770
01771 return TRUE;
01772 }
01773
01774
01775 static dbus_bool_t
01776 writer_recurse_array (DBusTypeWriter *writer,
01777 const DBusString *contained_type,
01778 int contained_type_start,
01779 int contained_type_len,
01780 DBusTypeWriter *sub,
01781 dbus_bool_t is_array_append)
01782 {
01783 dbus_uint32_t value = 0;
01784 int alignment;
01785 int aligned;
01786
01787 #ifndef DBUS_DISABLE_CHECKS
01788 if (writer->container_type == DBUS_TYPE_ARRAY &&
01789 writer->type_str)
01790 {
01791 if (!_dbus_string_equal_substring (contained_type,
01792 contained_type_start,
01793 contained_type_len,
01794 writer->type_str,
01795 writer->u.array.element_type_pos + 1))
01796 {
01797 _dbus_warn_check_failed ("Writing an array of '%s' but this is incompatible with the expected type of elements in the parent array\n",
01798 _dbus_string_get_const_data_len (contained_type,
01799 contained_type_start,
01800 contained_type_len));
01801 _dbus_assert_not_reached ("incompatible type for child array");
01802 }
01803 }
01804 #endif
01805
01806 if (writer->enabled && !is_array_append)
01807 {
01808
01809
01810
01811 if (!_dbus_string_alloc_space (sub->value_str, 3 + 4 + 4))
01812 return FALSE;
01813 }
01814
01815 if (writer->type_str != NULL)
01816 {
01817 sub->type_pos += 1;
01818
01819
01820 sub->u.array.element_type_pos = sub->type_pos;
01821 }
01822
01823 if (!writer->type_pos_is_expectation)
01824 {
01825
01826
01827
01828 if (!_dbus_string_alloc_space (writer->type_str, 1 + contained_type_len))
01829 return FALSE;
01830
01831 if (!_dbus_string_insert_byte (writer->type_str,
01832 writer->type_pos,
01833 DBUS_TYPE_ARRAY))
01834 _dbus_assert_not_reached ("failed to insert array typecode after prealloc");
01835
01836 if (!_dbus_string_copy_len (contained_type,
01837 contained_type_start, contained_type_len,
01838 sub->type_str,
01839 sub->u.array.element_type_pos))
01840 _dbus_assert_not_reached ("should not have failed to insert array element typecodes");
01841 }
01842
01843 if (writer->type_str != NULL)
01844 {
01845
01846
01847
01848 if (writer->container_type != DBUS_TYPE_ARRAY)
01849 writer->type_pos += 1 + contained_type_len;
01850 else
01851 _dbus_assert (writer->type_pos_is_expectation);
01852 }
01853
01854 if (writer->enabled)
01855 {
01856
01857 sub->u.array.len_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 4);
01858
01859 if (is_array_append)
01860 {
01861 sub->value_pos += 4;
01862 }
01863 else
01864 {
01865 if (!_dbus_type_writer_write_basic_no_typecode (sub, DBUS_TYPE_UINT32,
01866 &value))
01867 _dbus_assert_not_reached ("should not have failed to insert array len");
01868 }
01869
01870 _dbus_assert (sub->u.array.len_pos == sub->value_pos - 4);
01871
01872
01873
01874
01875
01876 alignment = element_type_get_alignment (contained_type, contained_type_start);
01877
01878 aligned = _DBUS_ALIGN_VALUE (sub->value_pos, alignment);
01879 if (aligned != sub->value_pos)
01880 {
01881 if (!is_array_append)
01882 {
01883 if (!_dbus_string_insert_bytes (sub->value_str,
01884 sub->value_pos,
01885 aligned - sub->value_pos,
01886 '\0'))
01887 _dbus_assert_not_reached ("should not have failed to insert alignment padding");
01888 }
01889
01890 sub->value_pos = aligned;
01891 }
01892
01893 sub->u.array.start_pos = sub->value_pos;
01894
01895 if (is_array_append)
01896 {
01897 dbus_uint32_t len;
01898
01899 _dbus_assert (_DBUS_ALIGN_VALUE (sub->u.array.len_pos, 4) ==
01900 (unsigned) sub->u.array.len_pos);
01901 len = _dbus_unpack_uint32 (sub->byte_order,
01902 _dbus_string_get_const_data_len (sub->value_str,
01903 sub->u.array.len_pos,
01904 4));
01905
01906 sub->value_pos += len;
01907 }
01908 }
01909 else
01910 {
01911
01912 sub->u.array.len_pos = -1;
01913 sub->u.array.start_pos = sub->value_pos;
01914 }
01915
01916 _dbus_assert (sub->u.array.len_pos < sub->u.array.start_pos);
01917 _dbus_assert (is_array_append || sub->u.array.start_pos == sub->value_pos);
01918
01919 #if RECURSIVE_MARSHAL_WRITE_TRACE
01920 _dbus_verbose (" type writer %p recurse array done remaining sig '%s' array start_pos = %d len_pos = %d value_pos = %d\n", sub,
01921 sub->type_str ?
01922 _dbus_string_get_const_data_len (sub->type_str, sub->type_pos, 0) :
01923 "unknown",
01924 sub->u.array.start_pos, sub->u.array.len_pos, sub->value_pos);
01925 #endif
01926
01927 return TRUE;
01928 }
01929
01930
01931
01932
01933
01934
01935
01936
01937
01938
01939
01940
01941
01942
01943
01944
01945
01946
01947
01948 static dbus_bool_t
01949 writer_recurse_variant (DBusTypeWriter *writer,
01950 const DBusString *contained_type,
01951 int contained_type_start,
01952 int contained_type_len,
01953 DBusTypeWriter *sub)
01954 {
01955 int contained_alignment;
01956
01957 if (writer->enabled)
01958 {
01959
01960
01961
01962
01963 if (!_dbus_string_alloc_space (sub->value_str, contained_type_len + 9))
01964 return FALSE;
01965 }
01966
01967
01968 if (!write_or_verify_typecode (writer, DBUS_TYPE_VARIANT))
01969 return FALSE;
01970
01971
01972
01973 if (!writer->enabled)
01974 {
01975 sub->type_str = NULL;
01976 sub->type_pos = -1;
01977
01978 return TRUE;
01979 }
01980
01981
01982
01983 if (!_dbus_string_insert_byte (sub->value_str,
01984 sub->value_pos,
01985 contained_type_len))
01986 _dbus_assert_not_reached ("should not have failed to insert variant type sig len");
01987
01988 sub->value_pos += 1;
01989
01990
01991 sub->type_str = sub->value_str;
01992 sub->type_pos = sub->value_pos;
01993
01994 if (!_dbus_string_copy_len (contained_type, contained_type_start, contained_type_len,
01995 sub->value_str, sub->value_pos))
01996 _dbus_assert_not_reached ("should not have failed to insert variant type sig");
01997
01998 sub->value_pos += contained_type_len;
01999
02000 if (!_dbus_string_insert_byte (sub->value_str,
02001 sub->value_pos,
02002 DBUS_TYPE_INVALID))
02003 _dbus_assert_not_reached ("should not have failed to insert variant type nul termination");
02004
02005 sub->value_pos += 1;
02006
02007 contained_alignment = _dbus_type_get_alignment (_dbus_first_type_in_signature (contained_type, contained_type_start));
02008
02009 if (!_dbus_string_insert_bytes (sub->value_str,
02010 sub->value_pos,
02011 _DBUS_ALIGN_VALUE (sub->value_pos, contained_alignment) - sub->value_pos,
02012 '\0'))
02013 _dbus_assert_not_reached ("should not have failed to insert alignment padding for variant body");
02014 sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, contained_alignment);
02015
02016 return TRUE;
02017 }
02018
02019 static dbus_bool_t
02020 _dbus_type_writer_recurse_contained_len (DBusTypeWriter *writer,
02021 int container_type,
02022 const DBusString *contained_type,
02023 int contained_type_start,
02024 int contained_type_len,
02025 DBusTypeWriter *sub,
02026 dbus_bool_t is_array_append)
02027 {
02028 writer_recurse_init_and_check (writer, container_type, sub);
02029
02030 switch (container_type)
02031 {
02032 case DBUS_TYPE_STRUCT:
02033 return writer_recurse_struct_or_dict_entry (writer,
02034 DBUS_STRUCT_BEGIN_CHAR,
02035 contained_type,
02036 contained_type_start, contained_type_len,
02037 sub);
02038 break;
02039 case DBUS_TYPE_DICT_ENTRY:
02040 return writer_recurse_struct_or_dict_entry (writer,
02041 DBUS_DICT_ENTRY_BEGIN_CHAR,
02042 contained_type,
02043 contained_type_start, contained_type_len,
02044 sub);
02045 break;
02046 case DBUS_TYPE_ARRAY:
02047 return writer_recurse_array (writer,
02048 contained_type, contained_type_start, contained_type_len,
02049 sub, is_array_append);
02050 break;
02051 case DBUS_TYPE_VARIANT:
02052 return writer_recurse_variant (writer,
02053 contained_type, contained_type_start, contained_type_len,
02054 sub);
02055 break;
02056 default:
02057 _dbus_assert_not_reached ("tried to recurse into type that doesn't support that");
02058 return FALSE;
02059 break;
02060 }
02061 }
02062
02073 dbus_bool_t
02074 _dbus_type_writer_recurse (DBusTypeWriter *writer,
02075 int container_type,
02076 const DBusString *contained_type,
02077 int contained_type_start,
02078 DBusTypeWriter *sub)
02079 {
02080 int contained_type_len;
02081
02082 if (contained_type)
02083 contained_type_len = find_len_of_complete_type (contained_type, contained_type_start);
02084 else
02085 contained_type_len = 0;
02086
02087 return _dbus_type_writer_recurse_contained_len (writer, container_type,
02088 contained_type,
02089 contained_type_start,
02090 contained_type_len,
02091 sub,
02092 FALSE);
02093 }
02094
02107 dbus_bool_t
02108 _dbus_type_writer_append_array (DBusTypeWriter *writer,
02109 const DBusString *contained_type,
02110 int contained_type_start,
02111 DBusTypeWriter *sub)
02112 {
02113 int contained_type_len;
02114
02115 if (contained_type)
02116 contained_type_len = find_len_of_complete_type (contained_type, contained_type_start);
02117 else
02118 contained_type_len = 0;
02119
02120 return _dbus_type_writer_recurse_contained_len (writer, DBUS_TYPE_ARRAY,
02121 contained_type,
02122 contained_type_start,
02123 contained_type_len,
02124 sub,
02125 TRUE);
02126 }
02127
02128 static int
02129 writer_get_array_len (DBusTypeWriter *writer)
02130 {
02131 _dbus_assert (writer->container_type == DBUS_TYPE_ARRAY);
02132 return writer->value_pos - writer->u.array.start_pos;
02133 }
02134
02143 dbus_bool_t
02144 _dbus_type_writer_unrecurse (DBusTypeWriter *writer,
02145 DBusTypeWriter *sub)
02146 {
02147
02148 _dbus_assert (!writer->type_pos_is_expectation ||
02149 (writer->type_pos_is_expectation && sub->type_pos_is_expectation));
02150
02151 #if RECURSIVE_MARSHAL_WRITE_TRACE
02152 _dbus_verbose (" type writer %p unrecurse type_pos = %d value_pos = %d is_expectation = %d container_type = %s\n",
02153 writer, writer->type_pos, writer->value_pos, writer->type_pos_is_expectation,
02154 _dbus_type_to_string (writer->container_type));
02155 _dbus_verbose (" type writer %p unrecurse sub type_pos = %d value_pos = %d is_expectation = %d container_type = %s\n",
02156 sub, sub->type_pos, sub->value_pos,
02157 sub->type_pos_is_expectation,
02158 _dbus_type_to_string (sub->container_type));
02159 #endif
02160
02161 if (sub->container_type == DBUS_TYPE_STRUCT)
02162 {
02163 if (!write_or_verify_typecode (sub, DBUS_STRUCT_END_CHAR))
02164 return FALSE;
02165 }
02166 else if (sub->container_type == DBUS_TYPE_DICT_ENTRY)
02167 {
02168 if (!write_or_verify_typecode (sub, DBUS_DICT_ENTRY_END_CHAR))
02169 return FALSE;
02170 }
02171 else if (sub->container_type == DBUS_TYPE_ARRAY)
02172 {
02173 if (sub->u.array.len_pos >= 0)
02174 {
02175 dbus_uint32_t len;
02176
02177
02178 len = writer_get_array_len (sub);
02179 _dbus_marshal_set_uint32 (sub->value_str,
02180 sub->u.array.len_pos,
02181 len,
02182 sub->byte_order);
02183 #if RECURSIVE_MARSHAL_WRITE_TRACE
02184 _dbus_verbose (" filled in sub array len to %u at len_pos %d\n",
02185 len, sub->u.array.len_pos);
02186 #endif
02187 }
02188 #if RECURSIVE_MARSHAL_WRITE_TRACE
02189 else
02190 {
02191 _dbus_verbose (" not filling in sub array len because we were disabled when we passed the len\n");
02192 }
02193 #endif
02194 }
02195
02196
02197
02198
02199
02200
02201
02202
02203
02204
02205
02206
02207
02208
02209
02210
02211
02212
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 if (writer->type_str != NULL)
02242 {
02243 if ((sub->container_type == DBUS_TYPE_STRUCT ||
02244 sub->container_type == DBUS_TYPE_DICT_ENTRY) &&
02245 (writer->container_type == DBUS_TYPE_STRUCT ||
02246 writer->container_type == DBUS_TYPE_DICT_ENTRY ||
02247 writer->container_type == DBUS_TYPE_INVALID))
02248 {
02249
02250 writer->type_pos = sub->type_pos;
02251 }
02252 }
02253
02254 writer->value_pos = sub->value_pos;
02255
02256 #if RECURSIVE_MARSHAL_WRITE_TRACE
02257 _dbus_verbose (" type writer %p unrecursed type_pos = %d value_pos = %d remaining sig '%s'\n",
02258 writer, writer->type_pos, writer->value_pos,
02259 writer->type_str ?
02260 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0) :
02261 "unknown");
02262 #endif
02263
02264 return TRUE;
02265 }
02266
02275 dbus_bool_t
02276 _dbus_type_writer_write_basic (DBusTypeWriter *writer,
02277 int type,
02278 const void *value)
02279 {
02280 dbus_bool_t retval;
02281
02282
02283 if (!writer->type_pos_is_expectation && writer->type_str != NULL)
02284 {
02285 if (!_dbus_string_alloc_space (writer->type_str, 1))
02286 return FALSE;
02287 }
02288
02289 retval = FALSE;
02290
02291 if (!_dbus_type_writer_write_basic_no_typecode (writer, type, value))
02292 goto out;
02293
02294 if (!write_or_verify_typecode (writer, type))
02295 _dbus_assert_not_reached ("failed to write typecode after prealloc");
02296
02297 retval = TRUE;
02298
02299 out:
02300 #if RECURSIVE_MARSHAL_WRITE_TRACE
02301 _dbus_verbose (" type writer %p basic type_pos = %d value_pos = %d is_expectation = %d enabled = %d\n",
02302 writer, writer->type_pos, writer->value_pos, writer->type_pos_is_expectation,
02303 writer->enabled);
02304 #endif
02305
02306 return retval;
02307 }
02308
02323 dbus_bool_t
02324 _dbus_type_writer_write_fixed_multi (DBusTypeWriter *writer,
02325 int element_type,
02326 const void *value,
02327 int n_elements)
02328 {
02329 _dbus_assert (writer->container_type == DBUS_TYPE_ARRAY);
02330 _dbus_assert (dbus_type_is_fixed (element_type));
02331 _dbus_assert (writer->type_pos_is_expectation);
02332 _dbus_assert (n_elements >= 0);
02333
02334 #if RECURSIVE_MARSHAL_WRITE_TRACE
02335 _dbus_verbose (" type writer %p entering fixed multi type_pos = %d value_pos = %d n_elements %d\n",
02336 writer, writer->type_pos, writer->value_pos, n_elements);
02337 #endif
02338
02339 if (!write_or_verify_typecode (writer, element_type))
02340 _dbus_assert_not_reached ("OOM should not happen if only verifying typecode");
02341
02342 if (writer->enabled)
02343 {
02344 if (!_dbus_marshal_write_fixed_multi (writer->value_str,
02345 writer->value_pos,
02346 element_type,
02347 value,
02348 n_elements,
02349 writer->byte_order,
02350 &writer->value_pos))
02351 return FALSE;
02352 }
02353
02354 #if RECURSIVE_MARSHAL_WRITE_TRACE
02355 _dbus_verbose (" type writer %p fixed multi written new type_pos = %d new value_pos = %d n_elements %d\n",
02356 writer, writer->type_pos, writer->value_pos, n_elements);
02357 #endif
02358
02359 return TRUE;
02360 }
02361
02362 static void
02363 enable_if_after (DBusTypeWriter *writer,
02364 DBusTypeReader *reader,
02365 const DBusTypeReader *start_after)
02366 {
02367 if (start_after)
02368 {
02369 if (!writer->enabled && _dbus_type_reader_greater_than (reader, start_after))
02370 {
02371 _dbus_type_writer_set_enabled (writer, TRUE);
02372 #if RECURSIVE_MARSHAL_WRITE_TRACE
02373 _dbus_verbose ("ENABLING writer %p at %d because reader at value_pos %d is after reader at value_pos %d\n",
02374 writer, writer->value_pos, reader->value_pos, start_after->value_pos);
02375 #endif
02376 }
02377
02378 _dbus_assert ((!writer->enabled && !_dbus_type_reader_greater_than (reader, start_after)) ||
02379 (writer->enabled && _dbus_type_reader_greater_than (reader, start_after)));
02380 }
02381 }
02382
02383 static dbus_bool_t
02384 append_fixup (DBusList **fixups,
02385 const DBusArrayLenFixup *fixup)
02386 {
02387 DBusArrayLenFixup *f;
02388
02389 f = dbus_new (DBusArrayLenFixup, 1);
02390 if (f == NULL)
02391 return FALSE;
02392
02393 *f = *fixup;
02394
02395 if (!_dbus_list_append (fixups, f))
02396 {
02397 dbus_free (f);
02398 return FALSE;
02399 }
02400
02401 _dbus_assert (f->len_pos_in_reader == fixup->len_pos_in_reader);
02402 _dbus_assert (f->new_len == fixup->new_len);
02403
02404 return TRUE;
02405 }
02406
02407
02408
02409
02410 static dbus_bool_t
02411 writer_write_reader_helper (DBusTypeWriter *writer,
02412 DBusTypeReader *reader,
02413 const DBusTypeReader *start_after,
02414 int start_after_new_pos,
02415 int start_after_new_len,
02416 DBusList **fixups,
02417 dbus_bool_t inside_start_after)
02418 {
02419 int current_type;
02420
02421 while ((current_type = _dbus_type_reader_get_current_type (reader)) != DBUS_TYPE_INVALID)
02422 {
02423 if (dbus_type_is_container (current_type))
02424 {
02425 DBusTypeReader subreader;
02426 DBusTypeWriter subwriter;
02427 const DBusString *sig_str;
02428 int sig_start;
02429 int sig_len;
02430 dbus_bool_t enabled_at_recurse;
02431 dbus_bool_t past_start_after;
02432 int reader_array_len_pos;
02433 int reader_array_start_pos;
02434 dbus_bool_t this_is_start_after;
02435
02436
02437
02438
02439
02440
02441 if (!inside_start_after && start_after &&
02442 reader->value_pos == start_after->value_pos &&
02443 reader->type_str == start_after->type_str &&
02444 reader->type_pos == start_after->type_pos)
02445 this_is_start_after = TRUE;
02446 else
02447 this_is_start_after = FALSE;
02448
02449 _dbus_type_reader_recurse (reader, &subreader);
02450
02451 if (current_type == DBUS_TYPE_ARRAY)
02452 {
02453 reader_array_len_pos = ARRAY_READER_LEN_POS (&subreader);
02454 reader_array_start_pos = subreader.u.array.start_pos;
02455 }
02456 else
02457 {
02458
02459 reader_array_len_pos = -1;
02460 reader_array_start_pos = -1;
02461 }
02462
02463 _dbus_type_reader_get_signature (&subreader, &sig_str,
02464 &sig_start, &sig_len);
02465
02466 #if RECURSIVE_MARSHAL_WRITE_TRACE
02467 _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",
02468 _dbus_type_to_string (current_type),
02469 reader->value_pos,
02470 subreader.value_pos,
02471 writer->value_pos,
02472 start_after ? start_after->value_pos : -1,
02473 _dbus_string_get_length (writer->value_str),
02474 inside_start_after, this_is_start_after);
02475 #endif
02476
02477 if (!inside_start_after && !this_is_start_after)
02478 enable_if_after (writer, &subreader, start_after);
02479 enabled_at_recurse = writer->enabled;
02480 if (!_dbus_type_writer_recurse_contained_len (writer, current_type,
02481 sig_str, sig_start, sig_len,
02482 &subwriter, FALSE))
02483 goto oom;
02484
02485 #if RECURSIVE_MARSHAL_WRITE_TRACE
02486 _dbus_verbose ("recursed into subwriter at %d write target len %d\n",
02487 subwriter.value_pos,
02488 _dbus_string_get_length (subwriter.value_str));
02489 #endif
02490
02491 if (!writer_write_reader_helper (&subwriter, &subreader, start_after,
02492 start_after_new_pos, start_after_new_len,
02493 fixups,
02494 inside_start_after ||
02495 this_is_start_after))
02496 goto oom;
02497
02498 #if RECURSIVE_MARSHAL_WRITE_TRACE
02499 _dbus_verbose ("about to unrecurse from %s subreader at %d writer at %d subwriter at %d write target len %d\n",
02500 _dbus_type_to_string (current_type),
02501 subreader.value_pos,
02502 writer->value_pos,
02503 subwriter.value_pos,
02504 _dbus_string_get_length (writer->value_str));
02505 #endif
02506
02507 if (!inside_start_after && !this_is_start_after)
02508 enable_if_after (writer, &subreader, start_after);
02509 past_start_after = writer->enabled;
02510 if (!_dbus_type_writer_unrecurse (writer, &subwriter))
02511 goto oom;
02512
02513
02514
02515
02516
02517
02518 if (start_after != NULL &&
02519 !enabled_at_recurse && past_start_after &&
02520 current_type == DBUS_TYPE_ARRAY &&
02521 fixups != NULL)
02522 {
02523 DBusArrayLenFixup fixup;
02524 int bytes_written_after_start_after;
02525 int bytes_before_start_after;
02526 int old_len;
02527
02528
02529
02530
02531
02532 bytes_written_after_start_after = writer_get_array_len (&subwriter);
02533
02534 bytes_before_start_after =
02535 start_after->value_pos - reader_array_start_pos;
02536
02537 fixup.len_pos_in_reader = reader_array_len_pos;
02538 fixup.new_len =
02539 bytes_before_start_after +
02540 start_after_new_len +
02541 bytes_written_after_start_after;
02542
02543 _dbus_assert (_DBUS_ALIGN_VALUE (fixup.len_pos_in_reader, 4) ==
02544 (unsigned) fixup.len_pos_in_reader);
02545
02546 old_len = _dbus_unpack_uint32 (reader->byte_order,
02547 _dbus_string_get_const_data_len (reader->value_str,
02548 fixup.len_pos_in_reader, 4));
02549
02550 if (old_len != fixup.new_len && !append_fixup (fixups, &fixup))
02551 goto oom;
02552
02553 #if RECURSIVE_MARSHAL_WRITE_TRACE
02554 _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",
02555 fixup.len_pos_in_reader,
02556 fixup.new_len,
02557 reader_array_start_pos,
02558 start_after->value_pos,
02559 bytes_before_start_after,
02560 start_after_new_len,
02561 bytes_written_after_start_after);
02562 #endif
02563 }
02564 }
02565 else
02566 {
02567 DBusBasicValue val;
02568
02569 _dbus_assert (dbus_type_is_basic (current_type));
02570
02571 #if RECURSIVE_MARSHAL_WRITE_TRACE
02572 _dbus_verbose ("Reading basic value %s at %d\n",
02573 _dbus_type_to_string (current_type),
02574 reader->value_pos);
02575 #endif
02576
02577 _dbus_type_reader_read_basic (reader, &val);
02578
02579 #if RECURSIVE_MARSHAL_WRITE_TRACE
02580 _dbus_verbose ("Writing basic value %s at %d write target len %d inside_start_after = %d\n",
02581 _dbus_type_to_string (current_type),
02582 writer->value_pos,
02583 _dbus_string_get_length (writer->value_str),
02584 inside_start_after);
02585 #endif
02586 if (!inside_start_after)
02587 enable_if_after (writer, reader, start_after);
02588 if (!_dbus_type_writer_write_basic (writer, current_type, &val))
02589 goto oom;
02590 #if RECURSIVE_MARSHAL_WRITE_TRACE
02591 _dbus_verbose ("Wrote basic value %s, new value_pos %d write target len %d\n",
02592 _dbus_type_to_string (current_type),
02593 writer->value_pos,
02594 _dbus_string_get_length (writer->value_str));
02595 #endif
02596 }
02597
02598 _dbus_type_reader_next (reader);
02599 }
02600
02601 return TRUE;
02602
02603 oom:
02604 if (fixups)
02605 apply_and_free_fixups (fixups, NULL);
02606
02607 return FALSE;
02608 }
02609
02641 dbus_bool_t
02642 _dbus_type_writer_write_reader_partial (DBusTypeWriter *writer,
02643 DBusTypeReader *reader,
02644 const DBusTypeReader *start_after,
02645 int start_after_new_pos,
02646 int start_after_new_len,
02647 DBusList **fixups)
02648 {
02649 DBusTypeWriter orig;
02650 int orig_type_len;
02651 int orig_value_len;
02652 int new_bytes;
02653 int orig_enabled;
02654
02655 orig = *writer;
02656 orig_type_len = _dbus_string_get_length (writer->type_str);
02657 orig_value_len = _dbus_string_get_length (writer->value_str);
02658 orig_enabled = writer->enabled;
02659
02660 if (start_after)
02661 _dbus_type_writer_set_enabled (writer, FALSE);
02662
02663 if (!writer_write_reader_helper (writer, reader, start_after,
02664 start_after_new_pos,
02665 start_after_new_len,
02666 fixups, FALSE))
02667 goto oom;
02668
02669 _dbus_type_writer_set_enabled (writer, orig_enabled);
02670 return TRUE;
02671
02672 oom:
02673 if (!writer->type_pos_is_expectation)
02674 {
02675 new_bytes = _dbus_string_get_length (writer->type_str) - orig_type_len;
02676 _dbus_string_delete (writer->type_str, orig.type_pos, new_bytes);
02677 }
02678 new_bytes = _dbus_string_get_length (writer->value_str) - orig_value_len;
02679 _dbus_string_delete (writer->value_str, orig.value_pos, new_bytes);
02680
02681 *writer = orig;
02682
02683 return FALSE;
02684 }
02685
02695 dbus_bool_t
02696 _dbus_type_writer_write_reader (DBusTypeWriter *writer,
02697 DBusTypeReader *reader)
02698 {
02699 return _dbus_type_writer_write_reader_partial (writer, reader, NULL, 0, 0, NULL);
02700 }
02701
02711 void
02712 _dbus_type_writer_set_enabled (DBusTypeWriter *writer,
02713 dbus_bool_t enabled)
02714 {
02715 writer->enabled = enabled != FALSE;
02716 }
02717
02719
02720