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 if (expected != DBUS_TYPE_INVALID)
01649 _dbus_warn_check_failed ("Writing an element of type %s, but the expected type here is %s\n"
01650 "The overall signature expected here was '%s' and we are on byte %d of that signature.\n",
01651 _dbus_type_to_string (sub->container_type),
01652 _dbus_type_to_string (expected),
01653 _dbus_string_get_const_data (writer->type_str), writer->type_pos);
01654 else
01655 _dbus_warn_check_failed ("Writing an element of type %s, but no value is expected here\n",
01656 "The overall signature expected here was '%s' and we are on byte %d of that signature.\n",
01657 _dbus_type_to_string (sub->container_type),
01658 _dbus_string_get_const_data (writer->type_str), writer->type_pos);
01659
01660 _dbus_assert_not_reached ("bad array element or variant content written");
01661 }
01662 }
01663 #endif
01664
01665 #if RECURSIVE_MARSHAL_WRITE_TRACE
01666 _dbus_verbose (" type writer %p recurse parent %s type_pos = %d value_pos = %d is_expectation = %d remaining sig '%s' enabled = %d\n",
01667 writer,
01668 _dbus_type_to_string (writer->container_type),
01669 writer->type_pos, writer->value_pos, writer->type_pos_is_expectation,
01670 writer->type_str ?
01671 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0) :
01672 "unknown",
01673 writer->enabled);
01674 _dbus_verbose (" type writer %p recurse sub %s type_pos = %d value_pos = %d is_expectation = %d enabled = %d\n",
01675 sub,
01676 _dbus_type_to_string (sub->container_type),
01677 sub->type_pos, sub->value_pos,
01678 sub->type_pos_is_expectation,
01679 sub->enabled);
01680 #endif
01681 }
01682
01683 static dbus_bool_t
01684 write_or_verify_typecode (DBusTypeWriter *writer,
01685 int typecode)
01686 {
01687
01688
01689
01690
01691
01692 #if RECURSIVE_MARSHAL_WRITE_TRACE
01693 _dbus_verbose (" type writer %p write_or_verify start type_pos = %d remaining sig '%s' enabled = %d\n",
01694 writer, writer->type_pos,
01695 writer->type_str ?
01696 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0) :
01697 "unknown",
01698 writer->enabled);
01699 #endif
01700
01701 if (writer->type_str == NULL)
01702 return TRUE;
01703
01704 if (writer->type_pos_is_expectation)
01705 {
01706 #ifndef DBUS_DISABLE_CHECKS
01707 {
01708 int expected;
01709
01710 expected = _dbus_string_get_byte (writer->type_str, writer->type_pos);
01711
01712 if (expected != typecode)
01713 {
01714 if (expected != DBUS_TYPE_INVALID)
01715 _dbus_warn_check_failed ("Array or variant type requires that type %s be written, but %s was written.\n"
01716 "The overall signature expected here was '%s' and we are on byte %d of that signature.\n",
01717 _dbus_type_to_string (expected), _dbus_type_to_string (typecode),
01718 _dbus_string_get_const_data (writer->type_str), writer->type_pos);
01719 else
01720 _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"
01721 "The overall signature expected here was '%s' and we are on byte %d of that signature.\n",
01722 _dbus_type_to_string (typecode),
01723 _dbus_string_get_const_data (writer->type_str), writer->type_pos);
01724 _dbus_assert_not_reached ("bad type inserted somewhere inside an array or variant");
01725 }
01726 }
01727 #endif
01728
01729
01730
01731
01732
01733 if (writer->container_type != DBUS_TYPE_ARRAY)
01734 writer->type_pos += 1;
01735 }
01736 else
01737 {
01738 if (!_dbus_string_insert_byte (writer->type_str,
01739 writer->type_pos,
01740 typecode))
01741 return FALSE;
01742
01743 writer->type_pos += 1;
01744 }
01745
01746 #if RECURSIVE_MARSHAL_WRITE_TRACE
01747 _dbus_verbose (" type writer %p write_or_verify end type_pos = %d remaining sig '%s'\n",
01748 writer, writer->type_pos,
01749 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0));
01750 #endif
01751
01752 return TRUE;
01753 }
01754
01755 static dbus_bool_t
01756 writer_recurse_struct_or_dict_entry (DBusTypeWriter *writer,
01757 int begin_char,
01758 const DBusString *contained_type,
01759 int contained_type_start,
01760 int contained_type_len,
01761 DBusTypeWriter *sub)
01762 {
01763
01764
01765
01766
01767
01768
01769 if (writer->enabled)
01770 {
01771 if (!_dbus_string_alloc_space (sub->value_str, 8))
01772 return FALSE;
01773 }
01774
01775 if (!write_or_verify_typecode (sub, begin_char))
01776 _dbus_assert_not_reached ("failed to insert struct typecode after prealloc");
01777
01778 if (writer->enabled)
01779 {
01780 if (!_dbus_string_insert_bytes (sub->value_str,
01781 sub->value_pos,
01782 _DBUS_ALIGN_VALUE (sub->value_pos, 8) - sub->value_pos,
01783 '\0'))
01784 _dbus_assert_not_reached ("should not have failed to insert alignment padding for struct");
01785 sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 8);
01786 }
01787
01788 return TRUE;
01789 }
01790
01791
01792 static dbus_bool_t
01793 writer_recurse_array (DBusTypeWriter *writer,
01794 const DBusString *contained_type,
01795 int contained_type_start,
01796 int contained_type_len,
01797 DBusTypeWriter *sub,
01798 dbus_bool_t is_array_append)
01799 {
01800 dbus_uint32_t value = 0;
01801 int alignment;
01802 int aligned;
01803
01804 #ifndef DBUS_DISABLE_CHECKS
01805 if (writer->container_type == DBUS_TYPE_ARRAY &&
01806 writer->type_str)
01807 {
01808 if (!_dbus_string_equal_substring (contained_type,
01809 contained_type_start,
01810 contained_type_len,
01811 writer->type_str,
01812 writer->u.array.element_type_pos + 1))
01813 {
01814 _dbus_warn_check_failed ("Writing an array of '%s' but this is incompatible with the expected type of elements in the parent array\n",
01815 _dbus_string_get_const_data_len (contained_type,
01816 contained_type_start,
01817 contained_type_len));
01818 _dbus_assert_not_reached ("incompatible type for child array");
01819 }
01820 }
01821 #endif
01822
01823 if (writer->enabled && !is_array_append)
01824 {
01825
01826
01827
01828 if (!_dbus_string_alloc_space (sub->value_str, 3 + 4 + 4))
01829 return FALSE;
01830 }
01831
01832 if (writer->type_str != NULL)
01833 {
01834 sub->type_pos += 1;
01835
01836
01837 sub->u.array.element_type_pos = sub->type_pos;
01838 }
01839
01840 if (!writer->type_pos_is_expectation)
01841 {
01842
01843
01844
01845 if (!_dbus_string_alloc_space (writer->type_str, 1 + contained_type_len))
01846 return FALSE;
01847
01848 if (!_dbus_string_insert_byte (writer->type_str,
01849 writer->type_pos,
01850 DBUS_TYPE_ARRAY))
01851 _dbus_assert_not_reached ("failed to insert array typecode after prealloc");
01852
01853 if (!_dbus_string_copy_len (contained_type,
01854 contained_type_start, contained_type_len,
01855 sub->type_str,
01856 sub->u.array.element_type_pos))
01857 _dbus_assert_not_reached ("should not have failed to insert array element typecodes");
01858 }
01859
01860 if (writer->type_str != NULL)
01861 {
01862
01863
01864
01865 if (writer->container_type != DBUS_TYPE_ARRAY)
01866 writer->type_pos += 1 + contained_type_len;
01867 else
01868 _dbus_assert (writer->type_pos_is_expectation);
01869 }
01870
01871 if (writer->enabled)
01872 {
01873
01874 sub->u.array.len_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 4);
01875
01876 if (is_array_append)
01877 {
01878 sub->value_pos += 4;
01879 }
01880 else
01881 {
01882 if (!_dbus_type_writer_write_basic_no_typecode (sub, DBUS_TYPE_UINT32,
01883 &value))
01884 _dbus_assert_not_reached ("should not have failed to insert array len");
01885 }
01886
01887 _dbus_assert (sub->u.array.len_pos == sub->value_pos - 4);
01888
01889
01890
01891
01892
01893 alignment = element_type_get_alignment (contained_type, contained_type_start);
01894
01895 aligned = _DBUS_ALIGN_VALUE (sub->value_pos, alignment);
01896 if (aligned != sub->value_pos)
01897 {
01898 if (!is_array_append)
01899 {
01900 if (!_dbus_string_insert_bytes (sub->value_str,
01901 sub->value_pos,
01902 aligned - sub->value_pos,
01903 '\0'))
01904 _dbus_assert_not_reached ("should not have failed to insert alignment padding");
01905 }
01906
01907 sub->value_pos = aligned;
01908 }
01909
01910 sub->u.array.start_pos = sub->value_pos;
01911
01912 if (is_array_append)
01913 {
01914 dbus_uint32_t len;
01915
01916 _dbus_assert (_DBUS_ALIGN_VALUE (sub->u.array.len_pos, 4) ==
01917 (unsigned) sub->u.array.len_pos);
01918 len = _dbus_unpack_uint32 (sub->byte_order,
01919 _dbus_string_get_const_data_len (sub->value_str,
01920 sub->u.array.len_pos,
01921 4));
01922
01923 sub->value_pos += len;
01924 }
01925 }
01926 else
01927 {
01928
01929 sub->u.array.len_pos = -1;
01930 sub->u.array.start_pos = sub->value_pos;
01931 }
01932
01933 _dbus_assert (sub->u.array.len_pos < sub->u.array.start_pos);
01934 _dbus_assert (is_array_append || sub->u.array.start_pos == sub->value_pos);
01935
01936 #if RECURSIVE_MARSHAL_WRITE_TRACE
01937 _dbus_verbose (" type writer %p recurse array done remaining sig '%s' array start_pos = %d len_pos = %d value_pos = %d\n", sub,
01938 sub->type_str ?
01939 _dbus_string_get_const_data_len (sub->type_str, sub->type_pos, 0) :
01940 "unknown",
01941 sub->u.array.start_pos, sub->u.array.len_pos, sub->value_pos);
01942 #endif
01943
01944 return TRUE;
01945 }
01946
01947
01948
01949
01950
01951
01952
01953
01954
01955
01956
01957
01958
01959
01960
01961
01962
01963
01964
01965 static dbus_bool_t
01966 writer_recurse_variant (DBusTypeWriter *writer,
01967 const DBusString *contained_type,
01968 int contained_type_start,
01969 int contained_type_len,
01970 DBusTypeWriter *sub)
01971 {
01972 int contained_alignment;
01973
01974 if (writer->enabled)
01975 {
01976
01977
01978
01979
01980 if (!_dbus_string_alloc_space (sub->value_str, contained_type_len + 9))
01981 return FALSE;
01982 }
01983
01984
01985 if (!write_or_verify_typecode (writer, DBUS_TYPE_VARIANT))
01986 return FALSE;
01987
01988
01989
01990 if (!writer->enabled)
01991 {
01992 sub->type_str = NULL;
01993 sub->type_pos = -1;
01994
01995 return TRUE;
01996 }
01997
01998
01999
02000 if (!_dbus_string_insert_byte (sub->value_str,
02001 sub->value_pos,
02002 contained_type_len))
02003 _dbus_assert_not_reached ("should not have failed to insert variant type sig len");
02004
02005 sub->value_pos += 1;
02006
02007
02008 sub->type_str = sub->value_str;
02009 sub->type_pos = sub->value_pos;
02010
02011 if (!_dbus_string_copy_len (contained_type, contained_type_start, contained_type_len,
02012 sub->value_str, sub->value_pos))
02013 _dbus_assert_not_reached ("should not have failed to insert variant type sig");
02014
02015 sub->value_pos += contained_type_len;
02016
02017 if (!_dbus_string_insert_byte (sub->value_str,
02018 sub->value_pos,
02019 DBUS_TYPE_INVALID))
02020 _dbus_assert_not_reached ("should not have failed to insert variant type nul termination");
02021
02022 sub->value_pos += 1;
02023
02024 contained_alignment = _dbus_type_get_alignment (_dbus_first_type_in_signature (contained_type, contained_type_start));
02025
02026 if (!_dbus_string_insert_bytes (sub->value_str,
02027 sub->value_pos,
02028 _DBUS_ALIGN_VALUE (sub->value_pos, contained_alignment) - sub->value_pos,
02029 '\0'))
02030 _dbus_assert_not_reached ("should not have failed to insert alignment padding for variant body");
02031 sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, contained_alignment);
02032
02033 return TRUE;
02034 }
02035
02036 static dbus_bool_t
02037 _dbus_type_writer_recurse_contained_len (DBusTypeWriter *writer,
02038 int container_type,
02039 const DBusString *contained_type,
02040 int contained_type_start,
02041 int contained_type_len,
02042 DBusTypeWriter *sub,
02043 dbus_bool_t is_array_append)
02044 {
02045 writer_recurse_init_and_check (writer, container_type, sub);
02046
02047 switch (container_type)
02048 {
02049 case DBUS_TYPE_STRUCT:
02050 return writer_recurse_struct_or_dict_entry (writer,
02051 DBUS_STRUCT_BEGIN_CHAR,
02052 contained_type,
02053 contained_type_start, contained_type_len,
02054 sub);
02055 break;
02056 case DBUS_TYPE_DICT_ENTRY:
02057 return writer_recurse_struct_or_dict_entry (writer,
02058 DBUS_DICT_ENTRY_BEGIN_CHAR,
02059 contained_type,
02060 contained_type_start, contained_type_len,
02061 sub);
02062 break;
02063 case DBUS_TYPE_ARRAY:
02064 return writer_recurse_array (writer,
02065 contained_type, contained_type_start, contained_type_len,
02066 sub, is_array_append);
02067 break;
02068 case DBUS_TYPE_VARIANT:
02069 return writer_recurse_variant (writer,
02070 contained_type, contained_type_start, contained_type_len,
02071 sub);
02072 break;
02073 default:
02074 _dbus_assert_not_reached ("tried to recurse into type that doesn't support that");
02075 return FALSE;
02076 break;
02077 }
02078 }
02079
02090 dbus_bool_t
02091 _dbus_type_writer_recurse (DBusTypeWriter *writer,
02092 int container_type,
02093 const DBusString *contained_type,
02094 int contained_type_start,
02095 DBusTypeWriter *sub)
02096 {
02097 int contained_type_len;
02098
02099 if (contained_type)
02100 contained_type_len = find_len_of_complete_type (contained_type, contained_type_start);
02101 else
02102 contained_type_len = 0;
02103
02104 return _dbus_type_writer_recurse_contained_len (writer, container_type,
02105 contained_type,
02106 contained_type_start,
02107 contained_type_len,
02108 sub,
02109 FALSE);
02110 }
02111
02124 dbus_bool_t
02125 _dbus_type_writer_append_array (DBusTypeWriter *writer,
02126 const DBusString *contained_type,
02127 int contained_type_start,
02128 DBusTypeWriter *sub)
02129 {
02130 int contained_type_len;
02131
02132 if (contained_type)
02133 contained_type_len = find_len_of_complete_type (contained_type, contained_type_start);
02134 else
02135 contained_type_len = 0;
02136
02137 return _dbus_type_writer_recurse_contained_len (writer, DBUS_TYPE_ARRAY,
02138 contained_type,
02139 contained_type_start,
02140 contained_type_len,
02141 sub,
02142 TRUE);
02143 }
02144
02145 static int
02146 writer_get_array_len (DBusTypeWriter *writer)
02147 {
02148 _dbus_assert (writer->container_type == DBUS_TYPE_ARRAY);
02149 return writer->value_pos - writer->u.array.start_pos;
02150 }
02151
02160 dbus_bool_t
02161 _dbus_type_writer_unrecurse (DBusTypeWriter *writer,
02162 DBusTypeWriter *sub)
02163 {
02164
02165 _dbus_assert (!writer->type_pos_is_expectation ||
02166 (writer->type_pos_is_expectation && sub->type_pos_is_expectation));
02167
02168 #if RECURSIVE_MARSHAL_WRITE_TRACE
02169 _dbus_verbose (" type writer %p unrecurse type_pos = %d value_pos = %d is_expectation = %d container_type = %s\n",
02170 writer, writer->type_pos, writer->value_pos, writer->type_pos_is_expectation,
02171 _dbus_type_to_string (writer->container_type));
02172 _dbus_verbose (" type writer %p unrecurse sub type_pos = %d value_pos = %d is_expectation = %d container_type = %s\n",
02173 sub, sub->type_pos, sub->value_pos,
02174 sub->type_pos_is_expectation,
02175 _dbus_type_to_string (sub->container_type));
02176 #endif
02177
02178 if (sub->container_type == DBUS_TYPE_STRUCT)
02179 {
02180 if (!write_or_verify_typecode (sub, DBUS_STRUCT_END_CHAR))
02181 return FALSE;
02182 }
02183 else if (sub->container_type == DBUS_TYPE_DICT_ENTRY)
02184 {
02185 if (!write_or_verify_typecode (sub, DBUS_DICT_ENTRY_END_CHAR))
02186 return FALSE;
02187 }
02188 else if (sub->container_type == DBUS_TYPE_ARRAY)
02189 {
02190 if (sub->u.array.len_pos >= 0)
02191 {
02192 dbus_uint32_t len;
02193
02194
02195 len = writer_get_array_len (sub);
02196 _dbus_marshal_set_uint32 (sub->value_str,
02197 sub->u.array.len_pos,
02198 len,
02199 sub->byte_order);
02200 #if RECURSIVE_MARSHAL_WRITE_TRACE
02201 _dbus_verbose (" filled in sub array len to %u at len_pos %d\n",
02202 len, sub->u.array.len_pos);
02203 #endif
02204 }
02205 #if RECURSIVE_MARSHAL_WRITE_TRACE
02206 else
02207 {
02208 _dbus_verbose (" not filling in sub array len because we were disabled when we passed the len\n");
02209 }
02210 #endif
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
02242
02243
02244
02245
02246
02247
02248
02249
02250
02251
02252
02253
02254
02255
02256
02257
02258 if (writer->type_str != NULL)
02259 {
02260 if ((sub->container_type == DBUS_TYPE_STRUCT ||
02261 sub->container_type == DBUS_TYPE_DICT_ENTRY) &&
02262 (writer->container_type == DBUS_TYPE_STRUCT ||
02263 writer->container_type == DBUS_TYPE_DICT_ENTRY ||
02264 writer->container_type == DBUS_TYPE_INVALID))
02265 {
02266
02267 writer->type_pos = sub->type_pos;
02268 }
02269 }
02270
02271 writer->value_pos = sub->value_pos;
02272
02273 #if RECURSIVE_MARSHAL_WRITE_TRACE
02274 _dbus_verbose (" type writer %p unrecursed type_pos = %d value_pos = %d remaining sig '%s'\n",
02275 writer, writer->type_pos, writer->value_pos,
02276 writer->type_str ?
02277 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0) :
02278 "unknown");
02279 #endif
02280
02281 return TRUE;
02282 }
02283
02292 dbus_bool_t
02293 _dbus_type_writer_write_basic (DBusTypeWriter *writer,
02294 int type,
02295 const void *value)
02296 {
02297 dbus_bool_t retval;
02298
02299
02300 if (!writer->type_pos_is_expectation && writer->type_str != NULL)
02301 {
02302 if (!_dbus_string_alloc_space (writer->type_str, 1))
02303 return FALSE;
02304 }
02305
02306 retval = FALSE;
02307
02308 if (!_dbus_type_writer_write_basic_no_typecode (writer, type, value))
02309 goto out;
02310
02311 if (!write_or_verify_typecode (writer, type))
02312 _dbus_assert_not_reached ("failed to write typecode after prealloc");
02313
02314 retval = TRUE;
02315
02316 out:
02317 #if RECURSIVE_MARSHAL_WRITE_TRACE
02318 _dbus_verbose (" type writer %p basic type_pos = %d value_pos = %d is_expectation = %d enabled = %d\n",
02319 writer, writer->type_pos, writer->value_pos, writer->type_pos_is_expectation,
02320 writer->enabled);
02321 #endif
02322
02323 return retval;
02324 }
02325
02340 dbus_bool_t
02341 _dbus_type_writer_write_fixed_multi (DBusTypeWriter *writer,
02342 int element_type,
02343 const void *value,
02344 int n_elements)
02345 {
02346 _dbus_assert (writer->container_type == DBUS_TYPE_ARRAY);
02347 _dbus_assert (dbus_type_is_fixed (element_type));
02348 _dbus_assert (writer->type_pos_is_expectation);
02349 _dbus_assert (n_elements >= 0);
02350
02351 #if RECURSIVE_MARSHAL_WRITE_TRACE
02352 _dbus_verbose (" type writer %p entering fixed multi type_pos = %d value_pos = %d n_elements %d\n",
02353 writer, writer->type_pos, writer->value_pos, n_elements);
02354 #endif
02355
02356 if (!write_or_verify_typecode (writer, element_type))
02357 _dbus_assert_not_reached ("OOM should not happen if only verifying typecode");
02358
02359 if (writer->enabled)
02360 {
02361 if (!_dbus_marshal_write_fixed_multi (writer->value_str,
02362 writer->value_pos,
02363 element_type,
02364 value,
02365 n_elements,
02366 writer->byte_order,
02367 &writer->value_pos))
02368 return FALSE;
02369 }
02370
02371 #if RECURSIVE_MARSHAL_WRITE_TRACE
02372 _dbus_verbose (" type writer %p fixed multi written new type_pos = %d new value_pos = %d n_elements %d\n",
02373 writer, writer->type_pos, writer->value_pos, n_elements);
02374 #endif
02375
02376 return TRUE;
02377 }
02378
02379 static void
02380 enable_if_after (DBusTypeWriter *writer,
02381 DBusTypeReader *reader,
02382 const DBusTypeReader *start_after)
02383 {
02384 if (start_after)
02385 {
02386 if (!writer->enabled && _dbus_type_reader_greater_than (reader, start_after))
02387 {
02388 _dbus_type_writer_set_enabled (writer, TRUE);
02389 #if RECURSIVE_MARSHAL_WRITE_TRACE
02390 _dbus_verbose ("ENABLING writer %p at %d because reader at value_pos %d is after reader at value_pos %d\n",
02391 writer, writer->value_pos, reader->value_pos, start_after->value_pos);
02392 #endif
02393 }
02394
02395 _dbus_assert ((!writer->enabled && !_dbus_type_reader_greater_than (reader, start_after)) ||
02396 (writer->enabled && _dbus_type_reader_greater_than (reader, start_after)));
02397 }
02398 }
02399
02400 static dbus_bool_t
02401 append_fixup (DBusList **fixups,
02402 const DBusArrayLenFixup *fixup)
02403 {
02404 DBusArrayLenFixup *f;
02405
02406 f = dbus_new (DBusArrayLenFixup, 1);
02407 if (f == NULL)
02408 return FALSE;
02409
02410 *f = *fixup;
02411
02412 if (!_dbus_list_append (fixups, f))
02413 {
02414 dbus_free (f);
02415 return FALSE;
02416 }
02417
02418 _dbus_assert (f->len_pos_in_reader == fixup->len_pos_in_reader);
02419 _dbus_assert (f->new_len == fixup->new_len);
02420
02421 return TRUE;
02422 }
02423
02424
02425
02426
02427 static dbus_bool_t
02428 writer_write_reader_helper (DBusTypeWriter *writer,
02429 DBusTypeReader *reader,
02430 const DBusTypeReader *start_after,
02431 int start_after_new_pos,
02432 int start_after_new_len,
02433 DBusList **fixups,
02434 dbus_bool_t inside_start_after)
02435 {
02436 int current_type;
02437
02438 while ((current_type = _dbus_type_reader_get_current_type (reader)) != DBUS_TYPE_INVALID)
02439 {
02440 if (dbus_type_is_container (current_type))
02441 {
02442 DBusTypeReader subreader;
02443 DBusTypeWriter subwriter;
02444 const DBusString *sig_str;
02445 int sig_start;
02446 int sig_len;
02447 dbus_bool_t enabled_at_recurse;
02448 dbus_bool_t past_start_after;
02449 int reader_array_len_pos;
02450 int reader_array_start_pos;
02451 dbus_bool_t this_is_start_after;
02452
02453
02454
02455
02456
02457
02458 if (!inside_start_after && start_after &&
02459 reader->value_pos == start_after->value_pos &&
02460 reader->type_str == start_after->type_str &&
02461 reader->type_pos == start_after->type_pos)
02462 this_is_start_after = TRUE;
02463 else
02464 this_is_start_after = FALSE;
02465
02466 _dbus_type_reader_recurse (reader, &subreader);
02467
02468 if (current_type == DBUS_TYPE_ARRAY)
02469 {
02470 reader_array_len_pos = ARRAY_READER_LEN_POS (&subreader);
02471 reader_array_start_pos = subreader.u.array.start_pos;
02472 }
02473 else
02474 {
02475
02476 reader_array_len_pos = -1;
02477 reader_array_start_pos = -1;
02478 }
02479
02480 _dbus_type_reader_get_signature (&subreader, &sig_str,
02481 &sig_start, &sig_len);
02482
02483 #if RECURSIVE_MARSHAL_WRITE_TRACE
02484 _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",
02485 _dbus_type_to_string (current_type),
02486 reader->value_pos,
02487 subreader.value_pos,
02488 writer->value_pos,
02489 start_after ? start_after->value_pos : -1,
02490 _dbus_string_get_length (writer->value_str),
02491 inside_start_after, this_is_start_after);
02492 #endif
02493
02494 if (!inside_start_after && !this_is_start_after)
02495 enable_if_after (writer, &subreader, start_after);
02496 enabled_at_recurse = writer->enabled;
02497 if (!_dbus_type_writer_recurse_contained_len (writer, current_type,
02498 sig_str, sig_start, sig_len,
02499 &subwriter, FALSE))
02500 goto oom;
02501
02502 #if RECURSIVE_MARSHAL_WRITE_TRACE
02503 _dbus_verbose ("recursed into subwriter at %d write target len %d\n",
02504 subwriter.value_pos,
02505 _dbus_string_get_length (subwriter.value_str));
02506 #endif
02507
02508 if (!writer_write_reader_helper (&subwriter, &subreader, start_after,
02509 start_after_new_pos, start_after_new_len,
02510 fixups,
02511 inside_start_after ||
02512 this_is_start_after))
02513 goto oom;
02514
02515 #if RECURSIVE_MARSHAL_WRITE_TRACE
02516 _dbus_verbose ("about to unrecurse from %s subreader at %d writer at %d subwriter at %d write target len %d\n",
02517 _dbus_type_to_string (current_type),
02518 subreader.value_pos,
02519 writer->value_pos,
02520 subwriter.value_pos,
02521 _dbus_string_get_length (writer->value_str));
02522 #endif
02523
02524 if (!inside_start_after && !this_is_start_after)
02525 enable_if_after (writer, &subreader, start_after);
02526 past_start_after = writer->enabled;
02527 if (!_dbus_type_writer_unrecurse (writer, &subwriter))
02528 goto oom;
02529
02530
02531
02532
02533
02534
02535 if (start_after != NULL &&
02536 !enabled_at_recurse && past_start_after &&
02537 current_type == DBUS_TYPE_ARRAY &&
02538 fixups != NULL)
02539 {
02540 DBusArrayLenFixup fixup;
02541 int bytes_written_after_start_after;
02542 int bytes_before_start_after;
02543 int old_len;
02544
02545
02546
02547
02548
02549 bytes_written_after_start_after = writer_get_array_len (&subwriter);
02550
02551 bytes_before_start_after =
02552 start_after->value_pos - reader_array_start_pos;
02553
02554 fixup.len_pos_in_reader = reader_array_len_pos;
02555 fixup.new_len =
02556 bytes_before_start_after +
02557 start_after_new_len +
02558 bytes_written_after_start_after;
02559
02560 _dbus_assert (_DBUS_ALIGN_VALUE (fixup.len_pos_in_reader, 4) ==
02561 (unsigned) fixup.len_pos_in_reader);
02562
02563 old_len = _dbus_unpack_uint32 (reader->byte_order,
02564 _dbus_string_get_const_data_len (reader->value_str,
02565 fixup.len_pos_in_reader, 4));
02566
02567 if (old_len != fixup.new_len && !append_fixup (fixups, &fixup))
02568 goto oom;
02569
02570 #if RECURSIVE_MARSHAL_WRITE_TRACE
02571 _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",
02572 fixup.len_pos_in_reader,
02573 fixup.new_len,
02574 reader_array_start_pos,
02575 start_after->value_pos,
02576 bytes_before_start_after,
02577 start_after_new_len,
02578 bytes_written_after_start_after);
02579 #endif
02580 }
02581 }
02582 else
02583 {
02584 DBusBasicValue val;
02585
02586 _dbus_assert (dbus_type_is_basic (current_type));
02587
02588 #if RECURSIVE_MARSHAL_WRITE_TRACE
02589 _dbus_verbose ("Reading basic value %s at %d\n",
02590 _dbus_type_to_string (current_type),
02591 reader->value_pos);
02592 #endif
02593
02594 _dbus_type_reader_read_basic (reader, &val);
02595
02596 #if RECURSIVE_MARSHAL_WRITE_TRACE
02597 _dbus_verbose ("Writing basic value %s at %d write target len %d inside_start_after = %d\n",
02598 _dbus_type_to_string (current_type),
02599 writer->value_pos,
02600 _dbus_string_get_length (writer->value_str),
02601 inside_start_after);
02602 #endif
02603 if (!inside_start_after)
02604 enable_if_after (writer, reader, start_after);
02605 if (!_dbus_type_writer_write_basic (writer, current_type, &val))
02606 goto oom;
02607 #if RECURSIVE_MARSHAL_WRITE_TRACE
02608 _dbus_verbose ("Wrote basic value %s, new value_pos %d write target len %d\n",
02609 _dbus_type_to_string (current_type),
02610 writer->value_pos,
02611 _dbus_string_get_length (writer->value_str));
02612 #endif
02613 }
02614
02615 _dbus_type_reader_next (reader);
02616 }
02617
02618 return TRUE;
02619
02620 oom:
02621 if (fixups)
02622 apply_and_free_fixups (fixups, NULL);
02623
02624 return FALSE;
02625 }
02626
02658 dbus_bool_t
02659 _dbus_type_writer_write_reader_partial (DBusTypeWriter *writer,
02660 DBusTypeReader *reader,
02661 const DBusTypeReader *start_after,
02662 int start_after_new_pos,
02663 int start_after_new_len,
02664 DBusList **fixups)
02665 {
02666 DBusTypeWriter orig;
02667 int orig_type_len;
02668 int orig_value_len;
02669 int new_bytes;
02670 int orig_enabled;
02671
02672 orig = *writer;
02673 orig_type_len = _dbus_string_get_length (writer->type_str);
02674 orig_value_len = _dbus_string_get_length (writer->value_str);
02675 orig_enabled = writer->enabled;
02676
02677 if (start_after)
02678 _dbus_type_writer_set_enabled (writer, FALSE);
02679
02680 if (!writer_write_reader_helper (writer, reader, start_after,
02681 start_after_new_pos,
02682 start_after_new_len,
02683 fixups, FALSE))
02684 goto oom;
02685
02686 _dbus_type_writer_set_enabled (writer, orig_enabled);
02687 return TRUE;
02688
02689 oom:
02690 if (!writer->type_pos_is_expectation)
02691 {
02692 new_bytes = _dbus_string_get_length (writer->type_str) - orig_type_len;
02693 _dbus_string_delete (writer->type_str, orig.type_pos, new_bytes);
02694 }
02695 new_bytes = _dbus_string_get_length (writer->value_str) - orig_value_len;
02696 _dbus_string_delete (writer->value_str, orig.value_pos, new_bytes);
02697
02698 *writer = orig;
02699
02700 return FALSE;
02701 }
02702
02712 dbus_bool_t
02713 _dbus_type_writer_write_reader (DBusTypeWriter *writer,
02714 DBusTypeReader *reader)
02715 {
02716 return _dbus_type_writer_write_reader_partial (writer, reader, NULL, 0, 0, NULL);
02717 }
02718
02728 void
02729 _dbus_type_writer_set_enabled (DBusTypeWriter *writer,
02730 dbus_bool_t enabled)
02731 {
02732 writer->enabled = enabled != FALSE;
02733 }
02734
02736
02737