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