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 void (* init_from_mark) (DBusTypeReader *reader,
00123 const DBusTypeMark *mark);
00124 };
00125
00126 static int
00127 element_type_get_alignment (const DBusString *str,
00128 int pos)
00129 {
00130 return _dbus_type_get_alignment (_dbus_first_type_in_signature (str, pos));
00131 }
00132
00133 static void
00134 reader_init (DBusTypeReader *reader,
00135 int byte_order,
00136 const DBusString *type_str,
00137 int type_pos,
00138 const DBusString *value_str,
00139 int value_pos)
00140 {
00141 reader->byte_order = byte_order;
00142 reader->finished = FALSE;
00143 reader->type_str = type_str;
00144 reader->type_pos = type_pos;
00145 reader->value_str = value_str;
00146 reader->value_pos = value_pos;
00147 }
00148
00149 static void
00150 base_reader_recurse (DBusTypeReader *sub,
00151 DBusTypeReader *parent)
00152 {
00153
00154 reader_init (sub,
00155 parent->byte_order,
00156 parent->type_str,
00157 parent->type_pos,
00158 parent->value_str,
00159 parent->value_pos);
00160 }
00161
00162 static void
00163 struct_or_dict_entry_types_only_reader_recurse (DBusTypeReader *sub,
00164 DBusTypeReader *parent)
00165 {
00166 base_reader_recurse (sub, parent);
00167
00168 _dbus_assert (_dbus_string_get_byte (sub->type_str,
00169 sub->type_pos) == DBUS_STRUCT_BEGIN_CHAR ||
00170 _dbus_string_get_byte (sub->type_str,
00171 sub->type_pos) == DBUS_DICT_ENTRY_BEGIN_CHAR);
00172
00173 sub->type_pos += 1;
00174 }
00175
00176 static void
00177 struct_or_dict_entry_reader_recurse (DBusTypeReader *sub,
00178 DBusTypeReader *parent)
00179 {
00180 struct_or_dict_entry_types_only_reader_recurse (sub, parent);
00181
00182
00183 sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 8);
00184 }
00185
00186 static void
00187 array_types_only_reader_recurse (DBusTypeReader *sub,
00188 DBusTypeReader *parent)
00189 {
00190 base_reader_recurse (sub, parent);
00191
00192
00193 sub->type_pos += 1;
00194
00195
00196 sub->u.array.start_pos = _DBUS_INT_MAX;
00197 sub->array_len_offset = 7;
00198 }
00199
00202 #define ARRAY_READER_LEN_POS(reader) \
00203 ((reader)->u.array.start_pos - ((int)(reader)->array_len_offset) - 4)
00204
00205 static int
00206 array_reader_get_array_len (const DBusTypeReader *reader)
00207 {
00208 dbus_uint32_t array_len;
00209 int len_pos;
00210
00211 len_pos = ARRAY_READER_LEN_POS (reader);
00212
00213 _dbus_assert (_DBUS_ALIGN_VALUE (len_pos, 4) == (unsigned) len_pos);
00214 array_len = _dbus_unpack_uint32 (reader->byte_order,
00215 _dbus_string_get_const_data_len (reader->value_str, len_pos, 4));
00216
00217 #if RECURSIVE_MARSHAL_READ_TRACE
00218 _dbus_verbose (" reader %p len_pos %d array len %u len_offset %d\n",
00219 reader, len_pos, array_len, reader->array_len_offset);
00220 #endif
00221
00222 _dbus_assert (reader->u.array.start_pos - len_pos - 4 < 8);
00223
00224 return array_len;
00225 }
00226
00227 static void
00228 array_reader_recurse (DBusTypeReader *sub,
00229 DBusTypeReader *parent)
00230 {
00231 int alignment;
00232 int len_pos;
00233
00234 array_types_only_reader_recurse (sub, parent);
00235
00236 sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 4);
00237
00238 len_pos = sub->value_pos;
00239
00240 sub->value_pos += 4;
00241
00242 alignment = element_type_get_alignment (sub->type_str,
00243 sub->type_pos);
00244
00245 sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, alignment);
00246
00247 sub->u.array.start_pos = sub->value_pos;
00248 _dbus_assert ((sub->u.array.start_pos - (len_pos + 4)) < 8);
00249 sub->array_len_offset = sub->u.array.start_pos - (len_pos + 4);
00250
00251 #if RECURSIVE_MARSHAL_READ_TRACE
00252 _dbus_verbose (" type reader %p array start = %d len_offset = %d array len = %d array element type = %s\n",
00253 sub,
00254 sub->u.array.start_pos,
00255 sub->array_len_offset,
00256 array_reader_get_array_len (sub),
00257 _dbus_type_to_string (_dbus_first_type_in_signature (sub->type_str,
00258 sub->type_pos)));
00259 #endif
00260 }
00261
00262 static void
00263 variant_reader_recurse (DBusTypeReader *sub,
00264 DBusTypeReader *parent)
00265 {
00266 int sig_len;
00267 int contained_alignment;
00268
00269 base_reader_recurse (sub, parent);
00270
00271
00272
00273
00274
00275 sig_len = _dbus_string_get_byte (sub->value_str, sub->value_pos);
00276
00277 sub->type_str = sub->value_str;
00278 sub->type_pos = sub->value_pos + 1;
00279
00280 sub->value_pos = sub->type_pos + sig_len + 1;
00281
00282 contained_alignment = _dbus_type_get_alignment (_dbus_first_type_in_signature (sub->type_str,
00283 sub->type_pos));
00284
00285 sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, contained_alignment);
00286
00287 #if RECURSIVE_MARSHAL_READ_TRACE
00288 _dbus_verbose (" type reader %p variant containing '%s'\n",
00289 sub,
00290 _dbus_string_get_const_data_len (sub->type_str,
00291 sub->type_pos, 0));
00292 #endif
00293 }
00294
00295 static dbus_bool_t
00296 array_reader_check_finished (const DBusTypeReader *reader)
00297 {
00298 int end_pos;
00299
00300
00301
00302
00303
00304 end_pos = reader->u.array.start_pos + array_reader_get_array_len (reader);
00305
00306 _dbus_assert (reader->value_pos <= end_pos);
00307 _dbus_assert (reader->value_pos >= reader->u.array.start_pos);
00308
00309 return reader->value_pos == end_pos;
00310 }
00311
00312 static void
00313 skip_one_complete_type (const DBusString *type_str,
00314 int *type_pos)
00315 {
00316 _dbus_type_signature_next (_dbus_string_get_const_data (type_str),
00317 type_pos);
00318 }
00319
00328 void
00329 _dbus_type_signature_next (const char *type_str,
00330 int *type_pos)
00331 {
00332 const unsigned char *p;
00333 const unsigned char *start;
00334
00335 _dbus_assert (type_str != NULL);
00336 _dbus_assert (type_pos != NULL);
00337
00338 start = type_str;
00339 p = start + *type_pos;
00340
00341 _dbus_assert (*p != DBUS_STRUCT_END_CHAR);
00342 _dbus_assert (*p != DBUS_DICT_ENTRY_END_CHAR);
00343
00344 while (*p == DBUS_TYPE_ARRAY)
00345 ++p;
00346
00347 _dbus_assert (*p != DBUS_STRUCT_END_CHAR);
00348 _dbus_assert (*p != DBUS_DICT_ENTRY_END_CHAR);
00349
00350 if (*p == DBUS_STRUCT_BEGIN_CHAR)
00351 {
00352 int depth;
00353
00354 depth = 1;
00355
00356 while (TRUE)
00357 {
00358 _dbus_assert (*p != DBUS_TYPE_INVALID);
00359
00360 ++p;
00361
00362 _dbus_assert (*p != DBUS_TYPE_INVALID);
00363
00364 if (*p == DBUS_STRUCT_BEGIN_CHAR)
00365 depth += 1;
00366 else if (*p == DBUS_STRUCT_END_CHAR)
00367 {
00368 depth -= 1;
00369 if (depth == 0)
00370 {
00371 ++p;
00372 break;
00373 }
00374 }
00375 }
00376 }
00377 else if (*p == DBUS_DICT_ENTRY_BEGIN_CHAR)
00378 {
00379 int depth;
00380
00381 depth = 1;
00382
00383 while (TRUE)
00384 {
00385 _dbus_assert (*p != DBUS_TYPE_INVALID);
00386
00387 ++p;
00388
00389 _dbus_assert (*p != DBUS_TYPE_INVALID);
00390
00391 if (*p == DBUS_DICT_ENTRY_BEGIN_CHAR)
00392 depth += 1;
00393 else if (*p == DBUS_DICT_ENTRY_END_CHAR)
00394 {
00395 depth -= 1;
00396 if (depth == 0)
00397 {
00398 ++p;
00399 break;
00400 }
00401 }
00402 }
00403 }
00404 else
00405 {
00406 ++p;
00407 }
00408
00409 *type_pos = (int) (p - start);
00410 }
00411
00412 static int
00413 find_len_of_complete_type (const DBusString *type_str,
00414 int type_pos)
00415 {
00416 int end;
00417
00418 end = type_pos;
00419
00420 skip_one_complete_type (type_str, &end);
00421
00422 return end - type_pos;
00423 }
00424
00425 static void
00426 base_reader_next (DBusTypeReader *reader,
00427 int current_type)
00428 {
00429 switch (current_type)
00430 {
00431 case DBUS_TYPE_DICT_ENTRY:
00432 case DBUS_TYPE_STRUCT:
00433 case DBUS_TYPE_VARIANT:
00434
00435 {
00436 DBusTypeReader sub;
00437
00438 if (reader->klass->types_only && current_type == DBUS_TYPE_VARIANT)
00439 ;
00440 else
00441 {
00442
00443 _dbus_type_reader_recurse (reader, &sub);
00444
00445
00446 while (_dbus_type_reader_next (&sub))
00447 {
00448 ;
00449 }
00450 }
00451 if (!reader->klass->types_only)
00452 reader->value_pos = sub.value_pos;
00453
00454
00455
00456
00457
00458
00459 if (current_type == DBUS_TYPE_VARIANT)
00460 reader->type_pos += 1;
00461 else
00462 reader->type_pos = sub.type_pos;
00463 }
00464 break;
00465
00466 case DBUS_TYPE_ARRAY:
00467 {
00468 if (!reader->klass->types_only)
00469 _dbus_marshal_skip_array (reader->value_str,
00470 _dbus_first_type_in_signature (reader->type_str,
00471 reader->type_pos + 1),
00472 reader->byte_order,
00473 &reader->value_pos);
00474
00475 skip_one_complete_type (reader->type_str, &reader->type_pos);
00476 }
00477 break;
00478
00479 default:
00480 if (!reader->klass->types_only)
00481 _dbus_marshal_skip_basic (reader->value_str,
00482 current_type, reader->byte_order,
00483 &reader->value_pos);
00484
00485 reader->type_pos += 1;
00486 break;
00487 }
00488 }
00489
00490 static void
00491 struct_reader_next (DBusTypeReader *reader,
00492 int current_type)
00493 {
00494 int t;
00495
00496 base_reader_next (reader, current_type);
00497
00498
00499
00500
00501
00502
00503 t = _dbus_string_get_byte (reader->type_str, reader->type_pos);
00504 if (t == DBUS_STRUCT_END_CHAR)
00505 {
00506 reader->type_pos += 1;
00507 reader->finished = TRUE;
00508 }
00509 }
00510
00511 static void
00512 dict_entry_reader_next (DBusTypeReader *reader,
00513 int current_type)
00514 {
00515 int t;
00516
00517 base_reader_next (reader, current_type);
00518
00519
00520
00521
00522
00523
00524 t = _dbus_string_get_byte (reader->type_str, reader->type_pos);
00525 if (t == DBUS_DICT_ENTRY_END_CHAR)
00526 {
00527 reader->type_pos += 1;
00528 reader->finished = TRUE;
00529 }
00530 }
00531
00532 static void
00533 array_types_only_reader_next (DBusTypeReader *reader,
00534 int current_type)
00535 {
00536
00537
00538
00539
00540
00541 reader->finished = TRUE;
00542 }
00543
00544 static void
00545 array_reader_next (DBusTypeReader *reader,
00546 int current_type)
00547 {
00548
00549 int end_pos;
00550
00551 end_pos = reader->u.array.start_pos + array_reader_get_array_len (reader);
00552
00553 #if RECURSIVE_MARSHAL_READ_TRACE
00554 _dbus_verbose (" reader %p array next START start_pos = %d end_pos = %d value_pos = %d current_type = %s\n",
00555 reader,
00556 reader->u.array.start_pos,
00557 end_pos, reader->value_pos,
00558 _dbus_type_to_string (current_type));
00559 #endif
00560
00561 _dbus_assert (reader->value_pos < end_pos);
00562 _dbus_assert (reader->value_pos >= reader->u.array.start_pos);
00563
00564 switch (_dbus_first_type_in_signature (reader->type_str,
00565 reader->type_pos))
00566 {
00567 case DBUS_TYPE_DICT_ENTRY:
00568 case DBUS_TYPE_STRUCT:
00569 case DBUS_TYPE_VARIANT:
00570 {
00571 DBusTypeReader sub;
00572
00573
00574 _dbus_type_reader_recurse (reader, &sub);
00575
00576
00577 while (_dbus_type_reader_next (&sub))
00578 {
00579 ;
00580 }
00581
00582
00583 reader->value_pos = sub.value_pos;
00584 }
00585 break;
00586
00587 case DBUS_TYPE_ARRAY:
00588 {
00589 _dbus_marshal_skip_array (reader->value_str,
00590 _dbus_first_type_in_signature (reader->type_str,
00591 reader->type_pos + 1),
00592 reader->byte_order,
00593 &reader->value_pos);
00594 }
00595 break;
00596
00597 default:
00598 {
00599 _dbus_marshal_skip_basic (reader->value_str,
00600 current_type, reader->byte_order,
00601 &reader->value_pos);
00602 }
00603 break;
00604 }
00605
00606 #if RECURSIVE_MARSHAL_READ_TRACE
00607 _dbus_verbose (" reader %p array next END start_pos = %d end_pos = %d value_pos = %d current_type = %s\n",
00608 reader,
00609 reader->u.array.start_pos,
00610 end_pos, reader->value_pos,
00611 _dbus_type_to_string (current_type));
00612 #endif
00613
00614 _dbus_assert (reader->value_pos <= end_pos);
00615
00616 if (reader->value_pos == end_pos)
00617 {
00618 skip_one_complete_type (reader->type_str,
00619 &reader->type_pos);
00620 }
00621 }
00622
00623 static void
00624 array_init_from_mark (DBusTypeReader *reader,
00625 const DBusTypeMark *mark)
00626 {
00627
00628
00629
00630 reader->u.array.start_pos = mark->array_start_pos;
00631 reader->array_len_offset = mark->array_len_offset;
00632 }
00633
00634 static const DBusTypeReaderClass body_reader_class = {
00635 "body", 0,
00636 FALSE,
00637 NULL,
00638 NULL,
00639 base_reader_next,
00640 NULL
00641 };
00642
00643 static const DBusTypeReaderClass body_types_only_reader_class = {
00644 "body types", 1,
00645 TRUE,
00646 NULL,
00647 NULL,
00648 base_reader_next,
00649 NULL
00650 };
00651
00652 static const DBusTypeReaderClass struct_reader_class = {
00653 "struct", 2,
00654 FALSE,
00655 struct_or_dict_entry_reader_recurse,
00656 NULL,
00657 struct_reader_next,
00658 NULL
00659 };
00660
00661 static const DBusTypeReaderClass struct_types_only_reader_class = {
00662 "struct types", 3,
00663 TRUE,
00664 struct_or_dict_entry_types_only_reader_recurse,
00665 NULL,
00666 struct_reader_next,
00667 NULL
00668 };
00669
00670 static const DBusTypeReaderClass dict_entry_reader_class = {
00671 "dict_entry", 4,
00672 FALSE,
00673 struct_or_dict_entry_reader_recurse,
00674 NULL,
00675 dict_entry_reader_next,
00676 NULL
00677 };
00678
00679 static const DBusTypeReaderClass dict_entry_types_only_reader_class = {
00680 "dict_entry types", 5,
00681 TRUE,
00682 struct_or_dict_entry_types_only_reader_recurse,
00683 NULL,
00684 dict_entry_reader_next,
00685 NULL
00686 };
00687
00688 static const DBusTypeReaderClass array_reader_class = {
00689 "array", 6,
00690 FALSE,
00691 array_reader_recurse,
00692 array_reader_check_finished,
00693 array_reader_next,
00694 array_init_from_mark
00695 };
00696
00697 static const DBusTypeReaderClass array_types_only_reader_class = {
00698 "array types", 7,
00699 TRUE,
00700 array_types_only_reader_recurse,
00701 NULL,
00702 array_types_only_reader_next,
00703 NULL
00704 };
00705
00706 static const DBusTypeReaderClass variant_reader_class = {
00707 "variant", 8,
00708 FALSE,
00709 variant_reader_recurse,
00710 NULL,
00711 base_reader_next,
00712 NULL
00713 };
00714
00715 static const DBusTypeReaderClass const *
00716 all_reader_classes[] = {
00717 &body_reader_class,
00718 &body_types_only_reader_class,
00719 &struct_reader_class,
00720 &struct_types_only_reader_class,
00721 &dict_entry_reader_class,
00722 &dict_entry_types_only_reader_class,
00723 &array_reader_class,
00724 &array_types_only_reader_class,
00725 &variant_reader_class
00726 };
00727
00738 void
00739 _dbus_type_reader_init (DBusTypeReader *reader,
00740 int byte_order,
00741 const DBusString *type_str,
00742 int type_pos,
00743 const DBusString *value_str,
00744 int value_pos)
00745 {
00746 reader->klass = &body_reader_class;
00747
00748 reader_init (reader, byte_order, type_str, type_pos,
00749 value_str, value_pos);
00750
00751 #if RECURSIVE_MARSHAL_READ_TRACE
00752 _dbus_verbose (" type reader %p init type_pos = %d value_pos = %d remaining sig '%s'\n",
00753 reader, reader->type_pos, reader->value_pos,
00754 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0));
00755 #endif
00756 }
00757
00769 void
00770 _dbus_type_reader_init_from_mark (DBusTypeReader *reader,
00771 int byte_order,
00772 const DBusString *type_str,
00773 const DBusString *value_str,
00774 const DBusTypeMark *mark)
00775 {
00776 reader->klass = all_reader_classes[mark->container_type];
00777
00778 reader_init (reader, byte_order,
00779 mark->type_pos_in_value_str ? value_str : type_str,
00780 mark->type_pos,
00781 value_str, mark->value_pos);
00782
00783 if (reader->klass->init_from_mark)
00784 (* reader->klass->init_from_mark) (reader, mark);
00785
00786 #if RECURSIVE_MARSHAL_READ_TRACE
00787 _dbus_verbose (" type reader %p init from mark type_pos = %d value_pos = %d remaining sig '%s'\n",
00788 reader, reader->type_pos, reader->value_pos,
00789 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0));
00790 #endif
00791 }
00792
00801 void
00802 _dbus_type_reader_init_types_only (DBusTypeReader *reader,
00803 const DBusString *type_str,
00804 int type_pos)
00805 {
00806 reader->klass = &body_types_only_reader_class;
00807
00808 reader_init (reader, DBUS_COMPILER_BYTE_ORDER ,
00809 type_str, type_pos, NULL, _DBUS_INT_MAX );
00810
00811 #if RECURSIVE_MARSHAL_READ_TRACE
00812 _dbus_verbose (" type reader %p init types only type_pos = %d remaining sig '%s'\n",
00813 reader, reader->type_pos,
00814 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0));
00815 #endif
00816 }
00817
00826 void
00827 _dbus_type_reader_init_types_only_from_mark (DBusTypeReader *reader,
00828 const DBusString *type_str,
00829 const DBusTypeMark *mark)
00830 {
00831 reader->klass = all_reader_classes[mark->container_type];
00832 _dbus_assert (reader->klass->types_only);
00833 _dbus_assert (!mark->type_pos_in_value_str);
00834
00835 reader_init (reader, DBUS_COMPILER_BYTE_ORDER,
00836 type_str, mark->type_pos,
00837 NULL, _DBUS_INT_MAX );
00838
00839 if (reader->klass->init_from_mark)
00840 (* reader->klass->init_from_mark) (reader, mark);
00841
00842 #if RECURSIVE_MARSHAL_READ_TRACE
00843 _dbus_verbose (" type reader %p init types only from mark type_pos = %d remaining sig '%s'\n",
00844 reader, reader->type_pos,
00845 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0));
00846 #endif
00847 }
00848
00856 void
00857 _dbus_type_reader_save_mark (const DBusTypeReader *reader,
00858 DBusTypeMark *mark)
00859 {
00860 mark->type_pos_in_value_str = (reader->type_str == reader->value_str);
00861 mark->container_type = reader->klass->id;
00862 _dbus_assert (all_reader_classes[reader->klass->id] == reader->klass);
00863
00864 mark->type_pos = reader->type_pos;
00865 mark->value_pos = reader->value_pos;
00866
00867
00868 mark->array_len_offset = reader->array_len_offset;
00869 mark->array_start_pos = reader->u.array.start_pos;
00870 }
00871
00880 int
00881 _dbus_type_reader_get_current_type (const DBusTypeReader *reader)
00882 {
00883 int t;
00884
00885 if (reader->finished ||
00886 (reader->klass->check_finished &&
00887 (* reader->klass->check_finished) (reader)))
00888 t = DBUS_TYPE_INVALID;
00889 else
00890 t = _dbus_first_type_in_signature (reader->type_str,
00891 reader->type_pos);
00892
00893 _dbus_assert (t != DBUS_STRUCT_END_CHAR);
00894 _dbus_assert (t != DBUS_STRUCT_BEGIN_CHAR);
00895 _dbus_assert (t != DBUS_DICT_ENTRY_END_CHAR);
00896 _dbus_assert (t != DBUS_DICT_ENTRY_BEGIN_CHAR);
00897
00898 #if 0
00899 _dbus_verbose (" type reader %p current type_pos = %d type = %s\n",
00900 reader, reader->type_pos,
00901 _dbus_type_to_string (t));
00902 #endif
00903
00904 return t;
00905 }
00906
00915 int
00916 _dbus_type_reader_get_element_type (const DBusTypeReader *reader)
00917 {
00918 int element_type;
00919
00920 _dbus_assert (_dbus_type_reader_get_current_type (reader) == DBUS_TYPE_ARRAY);
00921
00922 element_type = _dbus_first_type_in_signature (reader->type_str,
00923 reader->type_pos + 1);
00924
00925 return element_type;
00926 }
00927
00932 int
00933 _dbus_type_reader_get_value_pos (const DBusTypeReader *reader)
00934 {
00935 return reader->value_pos;
00936 }
00937
00947 void
00948 _dbus_type_reader_read_raw (const DBusTypeReader *reader,
00949 const unsigned char **value_location)
00950 {
00951 _dbus_assert (!reader->klass->types_only);
00952
00953 *value_location = _dbus_string_get_const_data_len (reader->value_str,
00954 reader->value_pos,
00955 0);
00956 }
00957
00964 void
00965 _dbus_type_reader_read_basic (const DBusTypeReader *reader,
00966 void *value)
00967 {
00968 int t;
00969
00970 _dbus_assert (!reader->klass->types_only);
00971
00972 t = _dbus_type_reader_get_current_type (reader);
00973
00974 _dbus_marshal_read_basic (reader->value_str,
00975 reader->value_pos,
00976 t, value,
00977 reader->byte_order,
00978 NULL);
00979
00980
00981 #if RECURSIVE_MARSHAL_READ_TRACE
00982 _dbus_verbose (" type reader %p read basic type_pos = %d value_pos = %d remaining sig '%s'\n",
00983 reader, reader->type_pos, reader->value_pos,
00984 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0));
00985 #endif
00986 }
00987
00994 int
00995 _dbus_type_reader_get_array_length (const DBusTypeReader *reader)
00996 {
00997 _dbus_assert (!reader->klass->types_only);
00998 _dbus_assert (reader->klass == &array_reader_class);
00999
01000 return array_reader_get_array_len (reader);
01001 }
01002
01018 void
01019 _dbus_type_reader_read_fixed_multi (const DBusTypeReader *reader,
01020 void *value,
01021 int *n_elements)
01022 {
01023 int element_type;
01024 int end_pos;
01025 int remaining_len;
01026 int alignment;
01027 int total_len;
01028
01029 _dbus_assert (!reader->klass->types_only);
01030 _dbus_assert (reader->klass == &array_reader_class);
01031
01032 element_type = _dbus_first_type_in_signature (reader->type_str,
01033 reader->type_pos);
01034
01035 _dbus_assert (element_type != DBUS_TYPE_INVALID);
01036 _dbus_assert (dbus_type_is_fixed (element_type));
01037
01038 alignment = _dbus_type_get_alignment (element_type);
01039
01040 _dbus_assert (reader->value_pos >= reader->u.array.start_pos);
01041
01042 total_len = array_reader_get_array_len (reader);
01043 end_pos = reader->u.array.start_pos + total_len;
01044 remaining_len = end_pos - reader->value_pos;
01045
01046 #if RECURSIVE_MARSHAL_READ_TRACE
01047 _dbus_verbose ("end_pos %d total_len %d remaining_len %d value_pos %d\n",
01048 end_pos, total_len, remaining_len, reader->value_pos);
01049 #endif
01050
01051 _dbus_assert (remaining_len <= total_len);
01052
01053 if (remaining_len == 0)
01054 *(const DBusBasicValue**) value = NULL;
01055 else
01056 *(const DBusBasicValue**) value =
01057 (void*) _dbus_string_get_const_data_len (reader->value_str,
01058 reader->value_pos,
01059 remaining_len);
01060
01061 *n_elements = remaining_len / alignment;
01062 _dbus_assert ((remaining_len % alignment) == 0);
01063
01064 #if RECURSIVE_MARSHAL_READ_TRACE
01065 _dbus_verbose (" type reader %p read fixed array type_pos = %d value_pos = %d remaining sig '%s'\n",
01066 reader, reader->type_pos, reader->value_pos,
01067 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0));
01068 #endif
01069 }
01070
01083 void
01084 _dbus_type_reader_recurse (DBusTypeReader *reader,
01085 DBusTypeReader *sub)
01086 {
01087 int t;
01088
01089 t = _dbus_first_type_in_signature (reader->type_str, reader->type_pos);
01090
01091 switch (t)
01092 {
01093 case DBUS_TYPE_STRUCT:
01094 if (reader->klass->types_only)
01095 sub->klass = &struct_types_only_reader_class;
01096 else
01097 sub->klass = &struct_reader_class;
01098 break;
01099 case DBUS_TYPE_DICT_ENTRY:
01100 if (reader->klass->types_only)
01101 sub->klass = &dict_entry_types_only_reader_class;
01102 else
01103 sub->klass = &dict_entry_reader_class;
01104 break;
01105 case DBUS_TYPE_ARRAY:
01106 if (reader->klass->types_only)
01107 sub->klass = &array_types_only_reader_class;
01108 else
01109 sub->klass = &array_reader_class;
01110 break;
01111 case DBUS_TYPE_VARIANT:
01112 if (reader->klass->types_only)
01113 _dbus_assert_not_reached ("can't recurse into variant typecode");
01114 else
01115 sub->klass = &variant_reader_class;
01116 break;
01117 default:
01118 _dbus_verbose ("recursing into type %s\n", _dbus_type_to_string (t));
01119 #ifndef DBUS_DISABLE_CHECKS
01120 if (t == DBUS_TYPE_INVALID)
01121 _dbus_warn ("You can't recurse into an empty array or off the end of a message body\n");
01122 #endif
01123
01124 _dbus_assert_not_reached ("don't yet handle recursing into this type");
01125 }
01126
01127 _dbus_assert (sub->klass == all_reader_classes[sub->klass->id]);
01128
01129 (* sub->klass->recurse) (sub, reader);
01130
01131 #if RECURSIVE_MARSHAL_READ_TRACE
01132 _dbus_verbose (" type reader %p RECURSED type_pos = %d value_pos = %d remaining sig '%s'\n",
01133 sub, sub->type_pos, sub->value_pos,
01134 _dbus_string_get_const_data_len (sub->type_str, sub->type_pos, 0));
01135 #endif
01136 }
01137
01146 dbus_bool_t
01147 _dbus_type_reader_next (DBusTypeReader *reader)
01148 {
01149 int t;
01150
01151 t = _dbus_type_reader_get_current_type (reader);
01152
01153 #if RECURSIVE_MARSHAL_READ_TRACE
01154 _dbus_verbose (" type reader %p START next() { type_pos = %d value_pos = %d remaining sig '%s' current_type = %s\n",
01155 reader, reader->type_pos, reader->value_pos,
01156 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0),
01157 _dbus_type_to_string (t));
01158 #endif
01159
01160 if (t == DBUS_TYPE_INVALID)
01161 return FALSE;
01162
01163 (* reader->klass->next) (reader, t);
01164
01165 #if RECURSIVE_MARSHAL_READ_TRACE
01166 _dbus_verbose (" type reader %p END next() type_pos = %d value_pos = %d remaining sig '%s' current_type = %s\n",
01167 reader, reader->type_pos, reader->value_pos,
01168 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0),
01169 _dbus_type_to_string (_dbus_type_reader_get_current_type (reader)));
01170 #endif
01171
01172 return _dbus_type_reader_get_current_type (reader) != DBUS_TYPE_INVALID;
01173 }
01174
01186 dbus_bool_t
01187 _dbus_type_reader_has_next (const DBusTypeReader *reader)
01188 {
01189
01190 DBusTypeReader copy;
01191
01192 copy = *reader;
01193 return _dbus_type_reader_next (©);
01194 }
01195
01217 void
01218 _dbus_type_reader_get_signature (const DBusTypeReader *reader,
01219 const DBusString **str_p,
01220 int *start_p,
01221 int *len_p)
01222 {
01223 *str_p = reader->type_str;
01224 *start_p = reader->type_pos;
01225 *len_p = find_len_of_complete_type (reader->type_str, reader->type_pos);
01226 }
01227
01228 typedef struct
01229 {
01230 DBusString replacement;
01231 int padding;
01232 } ReplacementBlock;
01233
01234 static dbus_bool_t
01235 replacement_block_init (ReplacementBlock *block,
01236 DBusTypeReader *reader)
01237 {
01238 if (!_dbus_string_init (&block->replacement))
01239 return FALSE;
01240
01241
01242
01243
01244 block->padding = reader->value_pos % 8;
01245
01246 if (!_dbus_string_lengthen (&block->replacement, block->padding))
01247 goto oom;
01248
01249 return TRUE;
01250
01251 oom:
01252 _dbus_string_free (&block->replacement);
01253 return FALSE;
01254 }
01255
01256 static dbus_bool_t
01257 replacement_block_replace (ReplacementBlock *block,
01258 DBusTypeReader *reader,
01259 const DBusTypeReader *realign_root)
01260 {
01261 DBusTypeWriter writer;
01262 DBusTypeReader realign_reader;
01263 DBusList *fixups;
01264 int orig_len;
01265
01266 _dbus_assert (realign_root != NULL);
01267
01268 orig_len = _dbus_string_get_length (&block->replacement);
01269
01270 realign_reader = *realign_root;
01271
01272 #if RECURSIVE_MARSHAL_WRITE_TRACE
01273 _dbus_verbose ("INITIALIZING replacement block writer %p at value_pos %d\n",
01274 &writer, _dbus_string_get_length (&block->replacement));
01275 #endif
01276 _dbus_type_writer_init_values_only (&writer,
01277 realign_reader.byte_order,
01278 realign_reader.type_str,
01279 realign_reader.type_pos,
01280 &block->replacement,
01281 _dbus_string_get_length (&block->replacement));
01282
01283 _dbus_assert (realign_reader.value_pos <= reader->value_pos);
01284
01285 #if RECURSIVE_MARSHAL_WRITE_TRACE
01286 _dbus_verbose ("COPYING from reader at value_pos %d to writer %p starting after value_pos %d\n",
01287 realign_reader.value_pos, &writer, reader->value_pos);
01288 #endif
01289 fixups = NULL;
01290 if (!_dbus_type_writer_write_reader_partial (&writer,
01291 &realign_reader,
01292 reader,
01293 block->padding,
01294 _dbus_string_get_length (&block->replacement) - block->padding,
01295 &fixups))
01296 goto oom;
01297
01298 #if RECURSIVE_MARSHAL_WRITE_TRACE
01299 _dbus_verbose ("REPLACEMENT at padding %d len %d\n", block->padding,
01300 _dbus_string_get_length (&block->replacement) - block->padding);
01301 _dbus_verbose_bytes_of_string (&block->replacement, block->padding,
01302 _dbus_string_get_length (&block->replacement) - block->padding);
01303 _dbus_verbose ("TO BE REPLACED at value_pos = %d (align pad %d) len %d realign_reader.value_pos %d\n",
01304 reader->value_pos, reader->value_pos % 8,
01305 realign_reader.value_pos - reader->value_pos,
01306 realign_reader.value_pos);
01307 _dbus_verbose_bytes_of_string (reader->value_str,
01308 reader->value_pos,
01309 realign_reader.value_pos - reader->value_pos);
01310 #endif
01311
01312
01313
01314
01315 if (!_dbus_string_replace_len (&block->replacement, block->padding,
01316 _dbus_string_get_length (&block->replacement) - block->padding,
01317 (DBusString*) reader->value_str,
01318 reader->value_pos,
01319 realign_reader.value_pos - reader->value_pos))
01320 goto oom;
01321
01322
01323 apply_and_free_fixups (&fixups, reader);
01324
01325 return TRUE;
01326
01327 oom:
01328 _dbus_string_set_length (&block->replacement, orig_len);
01329 free_fixups (&fixups);
01330 return FALSE;
01331 }
01332
01333 static void
01334 replacement_block_free (ReplacementBlock *block)
01335 {
01336 _dbus_string_free (&block->replacement);
01337 }
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362 static dbus_bool_t
01363 reader_set_basic_variable_length (DBusTypeReader *reader,
01364 int current_type,
01365 const void *value,
01366 const DBusTypeReader *realign_root)
01367 {
01368 dbus_bool_t retval;
01369 ReplacementBlock block;
01370 DBusTypeWriter writer;
01371
01372 _dbus_assert (realign_root != NULL);
01373
01374 retval = FALSE;
01375
01376 if (!replacement_block_init (&block, reader))
01377 return FALSE;
01378
01379
01380 #if RECURSIVE_MARSHAL_WRITE_TRACE
01381 _dbus_verbose ("INITIALIZING writer %p to write basic value at value_pos %d of replacement string\n",
01382 &writer, _dbus_string_get_length (&block.replacement));
01383 #endif
01384 _dbus_type_writer_init_values_only (&writer,
01385 reader->byte_order,
01386 reader->type_str,
01387 reader->type_pos,
01388 &block.replacement,
01389 _dbus_string_get_length (&block.replacement));
01390 #if RECURSIVE_MARSHAL_WRITE_TRACE
01391 _dbus_verbose ("WRITING basic value to writer %p (replacement string)\n", &writer);
01392 #endif
01393 if (!_dbus_type_writer_write_basic (&writer, current_type, value))
01394 goto out;
01395
01396 if (!replacement_block_replace (&block,
01397 reader,
01398 realign_root))
01399 goto out;
01400
01401 retval = TRUE;
01402
01403 out:
01404 replacement_block_free (&block);
01405 return retval;
01406 }
01407
01408 static void
01409 reader_set_basic_fixed_length (DBusTypeReader *reader,
01410 int current_type,
01411 const void *value)
01412 {
01413 _dbus_marshal_set_basic ((DBusString*) reader->value_str,
01414 reader->value_pos,
01415 current_type,
01416 value,
01417 reader->byte_order,
01418 NULL, NULL);
01419 }
01420
01455 dbus_bool_t
01456 _dbus_type_reader_set_basic (DBusTypeReader *reader,
01457 const void *value,
01458 const DBusTypeReader *realign_root)
01459 {
01460 int current_type;
01461
01462 _dbus_assert (!reader->klass->types_only);
01463 _dbus_assert (reader->value_str == realign_root->value_str);
01464 _dbus_assert (reader->value_pos >= realign_root->value_pos);
01465
01466 current_type = _dbus_type_reader_get_current_type (reader);
01467
01468 #if RECURSIVE_MARSHAL_WRITE_TRACE
01469 _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",
01470 reader, reader->type_pos, reader->value_pos,
01471 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0),
01472 realign_root,
01473 realign_root ? realign_root->value_pos : -1,
01474 _dbus_type_to_string (current_type));
01475 _dbus_verbose_bytes_of_string (realign_root->value_str, realign_root->value_pos,
01476 _dbus_string_get_length (realign_root->value_str) -
01477 realign_root->value_pos);
01478 #endif
01479
01480 _dbus_assert (dbus_type_is_basic (current_type));
01481
01482 if (dbus_type_is_fixed (current_type))
01483 {
01484 reader_set_basic_fixed_length (reader, current_type, value);
01485 return TRUE;
01486 }
01487 else
01488 {
01489 _dbus_assert (realign_root != NULL);
01490 return reader_set_basic_variable_length (reader, current_type,
01491 value, realign_root);
01492 }
01493 }
01494
01512 dbus_bool_t
01513 _dbus_type_reader_delete (DBusTypeReader *reader,
01514 const DBusTypeReader *realign_root)
01515 {
01516 dbus_bool_t retval;
01517 ReplacementBlock block;
01518
01519 _dbus_assert (realign_root != NULL);
01520 _dbus_assert (reader->klass == &array_reader_class);
01521
01522 retval = FALSE;
01523
01524 if (!replacement_block_init (&block, reader))
01525 return FALSE;
01526
01527 if (!replacement_block_replace (&block,
01528 reader,
01529 realign_root))
01530 goto out;
01531
01532 retval = TRUE;
01533
01534 out:
01535 replacement_block_free (&block);
01536 return retval;
01537 }
01538
01547 dbus_bool_t
01548 _dbus_type_reader_greater_than (const DBusTypeReader *lhs,
01549 const DBusTypeReader *rhs)
01550 {
01551 _dbus_assert (lhs->value_str == rhs->value_str);
01552
01553 return lhs->value_pos > rhs->value_pos;
01554 }
01555
01556
01557
01558
01559
01560
01561
01562
01563
01564
01585 void
01586 _dbus_type_writer_init (DBusTypeWriter *writer,
01587 int byte_order,
01588 DBusString *type_str,
01589 int type_pos,
01590 DBusString *value_str,
01591 int value_pos)
01592 {
01593 writer->byte_order = byte_order;
01594 writer->type_str = type_str;
01595 writer->type_pos = type_pos;
01596 writer->value_str = value_str;
01597 writer->value_pos = value_pos;
01598 writer->container_type = DBUS_TYPE_INVALID;
01599 writer->type_pos_is_expectation = FALSE;
01600 writer->enabled = TRUE;
01601
01602 #if RECURSIVE_MARSHAL_WRITE_TRACE
01603 _dbus_verbose ("writer %p init remaining sig '%s'\n", writer,
01604 writer->type_str ?
01605 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0) :
01606 "unknown");
01607 #endif
01608 }
01609
01620 void
01621 _dbus_type_writer_init_types_delayed (DBusTypeWriter *writer,
01622 int byte_order,
01623 DBusString *value_str,
01624 int value_pos)
01625 {
01626 _dbus_type_writer_init (writer, byte_order,
01627 NULL, 0, value_str, value_pos);
01628 }
01629
01638 void
01639 _dbus_type_writer_add_types (DBusTypeWriter *writer,
01640 DBusString *type_str,
01641 int type_pos)
01642 {
01643 if (writer->type_str == NULL)
01644 {
01645 writer->type_str = type_str;
01646 writer->type_pos = type_pos;
01647 }
01648 }
01649
01655 void
01656 _dbus_type_writer_remove_types (DBusTypeWriter *writer)
01657 {
01658 writer->type_str = NULL;
01659 writer->type_pos = -1;
01660 }
01661
01676 void
01677 _dbus_type_writer_init_values_only (DBusTypeWriter *writer,
01678 int byte_order,
01679 const DBusString *type_str,
01680 int type_pos,
01681 DBusString *value_str,
01682 int value_pos)
01683 {
01684 _dbus_type_writer_init (writer, byte_order,
01685 (DBusString*)type_str, type_pos,
01686 value_str, value_pos);
01687
01688 writer->type_pos_is_expectation = TRUE;
01689 }
01690
01691 static dbus_bool_t
01692 _dbus_type_writer_write_basic_no_typecode (DBusTypeWriter *writer,
01693 int type,
01694 const void *value)
01695 {
01696 if (writer->enabled)
01697 return _dbus_marshal_write_basic (writer->value_str,
01698 writer->value_pos,
01699 type,
01700 value,
01701 writer->byte_order,
01702 &writer->value_pos);
01703 else
01704 return TRUE;
01705 }
01706
01707
01708
01709
01710
01711
01712
01713
01714
01715
01716
01717
01718
01719
01720
01721
01722
01723
01724
01725
01726
01727
01728 static void
01729 writer_recurse_init_and_check (DBusTypeWriter *writer,
01730 int container_type,
01731 DBusTypeWriter *sub)
01732 {
01733 _dbus_type_writer_init (sub,
01734 writer->byte_order,
01735 writer->type_str,
01736 writer->type_pos,
01737 writer->value_str,
01738 writer->value_pos);
01739
01740 sub->container_type = container_type;
01741
01742 if (writer->type_pos_is_expectation ||
01743 (sub->container_type == DBUS_TYPE_ARRAY || sub->container_type == DBUS_TYPE_VARIANT))
01744 sub->type_pos_is_expectation = TRUE;
01745 else
01746 sub->type_pos_is_expectation = FALSE;
01747
01748 sub->enabled = writer->enabled;
01749
01750 #ifndef DBUS_DISABLE_CHECKS
01751 if (writer->type_pos_is_expectation && writer->type_str)
01752 {
01753 int expected;
01754
01755 expected = _dbus_first_type_in_signature (writer->type_str, writer->type_pos);
01756
01757 if (expected != sub->container_type)
01758 {
01759 _dbus_warn ("Writing an element of type %s, but the expected type here is %s\n",
01760 _dbus_type_to_string (sub->container_type),
01761 _dbus_type_to_string (expected));
01762 _dbus_assert_not_reached ("bad array element or variant content written");
01763 }
01764 }
01765 #endif
01766
01767 #if RECURSIVE_MARSHAL_WRITE_TRACE
01768 _dbus_verbose (" type writer %p recurse parent %s type_pos = %d value_pos = %d is_expectation = %d remaining sig '%s' enabled = %d\n",
01769 writer,
01770 _dbus_type_to_string (writer->container_type),
01771 writer->type_pos, writer->value_pos, writer->type_pos_is_expectation,
01772 writer->type_str ?
01773 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0) :
01774 "unknown",
01775 writer->enabled);
01776 _dbus_verbose (" type writer %p recurse sub %s type_pos = %d value_pos = %d is_expectation = %d enabled = %d\n",
01777 sub,
01778 _dbus_type_to_string (sub->container_type),
01779 sub->type_pos, sub->value_pos,
01780 sub->type_pos_is_expectation,
01781 sub->enabled);
01782 #endif
01783 }
01784
01785 static dbus_bool_t
01786 write_or_verify_typecode (DBusTypeWriter *writer,
01787 int typecode)
01788 {
01789
01790
01791
01792
01793
01794 #if RECURSIVE_MARSHAL_WRITE_TRACE
01795 _dbus_verbose (" type writer %p write_or_verify start type_pos = %d remaining sig '%s' enabled = %d\n",
01796 writer, writer->type_pos,
01797 writer->type_str ?
01798 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0) :
01799 "unknown",
01800 writer->enabled);
01801 #endif
01802
01803 if (writer->type_str == NULL)
01804 return TRUE;
01805
01806 if (writer->type_pos_is_expectation)
01807 {
01808 #ifndef DBUS_DISABLE_CHECKS
01809 {
01810 int expected;
01811
01812 expected = _dbus_string_get_byte (writer->type_str, writer->type_pos);
01813
01814 if (expected != typecode)
01815 {
01816 _dbus_warn ("Array or variant type requires that type %s be written, but %s was written\n",
01817 _dbus_type_to_string (expected), _dbus_type_to_string (typecode));
01818 _dbus_assert_not_reached ("bad type inserted somewhere inside an array or variant");
01819 }
01820 }
01821 #endif
01822
01823
01824
01825
01826
01827 if (writer->container_type != DBUS_TYPE_ARRAY)
01828 writer->type_pos += 1;
01829 }
01830 else
01831 {
01832 if (!_dbus_string_insert_byte (writer->type_str,
01833 writer->type_pos,
01834 typecode))
01835 return FALSE;
01836
01837 writer->type_pos += 1;
01838 }
01839
01840 #if RECURSIVE_MARSHAL_WRITE_TRACE
01841 _dbus_verbose (" type writer %p write_or_verify end type_pos = %d remaining sig '%s'\n",
01842 writer, writer->type_pos,
01843 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0));
01844 #endif
01845
01846 return TRUE;
01847 }
01848
01849 static dbus_bool_t
01850 writer_recurse_struct_or_dict_entry (DBusTypeWriter *writer,
01851 int begin_char,
01852 const DBusString *contained_type,
01853 int contained_type_start,
01854 int contained_type_len,
01855 DBusTypeWriter *sub)
01856 {
01857
01858
01859
01860
01861
01862
01863 if (writer->enabled)
01864 {
01865 if (!_dbus_string_alloc_space (sub->value_str, 8))
01866 return FALSE;
01867 }
01868
01869 if (!write_or_verify_typecode (sub, begin_char))
01870 _dbus_assert_not_reached ("failed to insert struct typecode after prealloc");
01871
01872 if (writer->enabled)
01873 {
01874 if (!_dbus_string_insert_bytes (sub->value_str,
01875 sub->value_pos,
01876 _DBUS_ALIGN_VALUE (sub->value_pos, 8) - sub->value_pos,
01877 '\0'))
01878 _dbus_assert_not_reached ("should not have failed to insert alignment padding for struct");
01879 sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 8);
01880 }
01881
01882 return TRUE;
01883 }
01884
01885
01886 static dbus_bool_t
01887 writer_recurse_array (DBusTypeWriter *writer,
01888 const DBusString *contained_type,
01889 int contained_type_start,
01890 int contained_type_len,
01891 DBusTypeWriter *sub,
01892 dbus_bool_t is_array_append)
01893 {
01894 dbus_uint32_t value = 0;
01895 int alignment;
01896 int aligned;
01897
01898 #ifndef DBUS_DISABLE_CHECKS
01899 if (writer->container_type == DBUS_TYPE_ARRAY &&
01900 writer->type_str)
01901 {
01902 if (!_dbus_string_equal_substring (contained_type,
01903 contained_type_start,
01904 contained_type_len,
01905 writer->type_str,
01906 writer->u.array.element_type_pos + 1))
01907 {
01908 _dbus_warn ("Writing an array of '%s' but this is incompatible with the expected type of elements in the parent array\n",
01909 _dbus_string_get_const_data_len (contained_type,
01910 contained_type_start,
01911 contained_type_len));
01912 _dbus_assert_not_reached ("incompatible type for child array");
01913 }
01914 }
01915 #endif
01916
01917 if (writer->enabled && !is_array_append)
01918 {
01919
01920
01921
01922 if (!_dbus_string_alloc_space (sub->value_str, 3 + 4 + 4))
01923 return FALSE;
01924 }
01925
01926 if (writer->type_str != NULL)
01927 {
01928 sub->type_pos += 1;
01929
01930
01931 sub->u.array.element_type_pos = sub->type_pos;
01932 }
01933
01934 if (!writer->type_pos_is_expectation)
01935 {
01936
01937
01938
01939 if (!_dbus_string_alloc_space (writer->type_str, 1 + contained_type_len))
01940 return FALSE;
01941
01942 if (!_dbus_string_insert_byte (writer->type_str,
01943 writer->type_pos,
01944 DBUS_TYPE_ARRAY))
01945 _dbus_assert_not_reached ("failed to insert array typecode after prealloc");
01946
01947 if (!_dbus_string_copy_len (contained_type,
01948 contained_type_start, contained_type_len,
01949 sub->type_str,
01950 sub->u.array.element_type_pos))
01951 _dbus_assert_not_reached ("should not have failed to insert array element typecodes");
01952 }
01953
01954 if (writer->type_str != NULL)
01955 {
01956
01957
01958
01959 if (writer->container_type != DBUS_TYPE_ARRAY)
01960 writer->type_pos += 1 + contained_type_len;
01961 else
01962 _dbus_assert (writer->type_pos_is_expectation);
01963 }
01964
01965 if (writer->enabled)
01966 {
01967
01968 sub->u.array.len_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 4);
01969
01970 if (is_array_append)
01971 {
01972 sub->value_pos += 4;
01973 }
01974 else
01975 {
01976 if (!_dbus_type_writer_write_basic_no_typecode (sub, DBUS_TYPE_UINT32,
01977 &value))
01978 _dbus_assert_not_reached ("should not have failed to insert array len");
01979 }
01980
01981 _dbus_assert (sub->u.array.len_pos == sub->value_pos - 4);
01982
01983
01984
01985
01986
01987 alignment = element_type_get_alignment (contained_type, contained_type_start);
01988
01989 aligned = _DBUS_ALIGN_VALUE (sub->value_pos, alignment);
01990 if (aligned != sub->value_pos)
01991 {
01992 if (!is_array_append)
01993 {
01994 if (!_dbus_string_insert_bytes (sub->value_str,
01995 sub->value_pos,
01996 aligned - sub->value_pos,
01997 '\0'))
01998 _dbus_assert_not_reached ("should not have failed to insert alignment padding");
01999 }
02000
02001 sub->value_pos = aligned;
02002 }
02003
02004 sub->u.array.start_pos = sub->value_pos;
02005
02006 if (is_array_append)
02007 {
02008 dbus_uint32_t len;
02009
02010 _dbus_assert (_DBUS_ALIGN_VALUE (sub->u.array.len_pos, 4) ==
02011 (unsigned) sub->u.array.len_pos);
02012 len = _dbus_unpack_uint32 (sub->byte_order,
02013 _dbus_string_get_const_data_len (sub->value_str,
02014 sub->u.array.len_pos,
02015 4));
02016
02017 sub->value_pos += len;
02018 }
02019 }
02020 else
02021 {
02022
02023 sub->u.array.len_pos = -1;
02024 sub->u.array.start_pos = sub->value_pos;
02025 }
02026
02027 _dbus_assert (sub->u.array.len_pos < sub->u.array.start_pos);
02028 _dbus_assert (is_array_append || sub->u.array.start_pos == sub->value_pos);
02029
02030 #if RECURSIVE_MARSHAL_WRITE_TRACE
02031 _dbus_verbose (" type writer %p recurse array done remaining sig '%s' array start_pos = %d len_pos = %d value_pos = %d\n", sub,
02032 sub->type_str ?
02033 _dbus_string_get_const_data_len (sub->type_str, sub->type_pos, 0) :
02034 "unknown",
02035 sub->u.array.start_pos, sub->u.array.len_pos, sub->value_pos);
02036 #endif
02037
02038 return TRUE;
02039 }
02040
02041
02042
02043
02044
02045
02046
02047
02048
02049
02050
02051
02052
02053
02054
02055
02056
02057
02058
02059 static dbus_bool_t
02060 writer_recurse_variant (DBusTypeWriter *writer,
02061 const DBusString *contained_type,
02062 int contained_type_start,
02063 int contained_type_len,
02064 DBusTypeWriter *sub)
02065 {
02066 int contained_alignment;
02067
02068 if (writer->enabled)
02069 {
02070
02071
02072
02073
02074 if (!_dbus_string_alloc_space (sub->value_str, contained_type_len + 9))
02075 return FALSE;
02076 }
02077
02078
02079 if (!write_or_verify_typecode (writer, DBUS_TYPE_VARIANT))
02080 return FALSE;
02081
02082
02083
02084 if (!writer->enabled)
02085 {
02086 sub->type_str = NULL;
02087 sub->type_pos = -1;
02088
02089 return TRUE;
02090 }
02091
02092
02093
02094 if (!_dbus_string_insert_byte (sub->value_str,
02095 sub->value_pos,
02096 contained_type_len))
02097 _dbus_assert_not_reached ("should not have failed to insert variant type sig len");
02098
02099 sub->value_pos += 1;
02100
02101
02102 sub->type_str = sub->value_str;
02103 sub->type_pos = sub->value_pos;
02104
02105 if (!_dbus_string_copy_len (contained_type, contained_type_start, contained_type_len,
02106 sub->value_str, sub->value_pos))
02107 _dbus_assert_not_reached ("should not have failed to insert variant type sig");
02108
02109 sub->value_pos += contained_type_len;
02110
02111 if (!_dbus_string_insert_byte (sub->value_str,
02112 sub->value_pos,
02113 DBUS_TYPE_INVALID))
02114 _dbus_assert_not_reached ("should not have failed to insert variant type nul termination");
02115
02116 sub->value_pos += 1;
02117
02118 contained_alignment = _dbus_type_get_alignment (_dbus_first_type_in_signature (contained_type, contained_type_start));
02119
02120 if (!_dbus_string_insert_bytes (sub->value_str,
02121 sub->value_pos,
02122 _DBUS_ALIGN_VALUE (sub->value_pos, contained_alignment) - sub->value_pos,
02123 '\0'))
02124 _dbus_assert_not_reached ("should not have failed to insert alignment padding for variant body");
02125 sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, contained_alignment);
02126
02127 return TRUE;
02128 }
02129
02130 static dbus_bool_t
02131 _dbus_type_writer_recurse_contained_len (DBusTypeWriter *writer,
02132 int container_type,
02133 const DBusString *contained_type,
02134 int contained_type_start,
02135 int contained_type_len,
02136 DBusTypeWriter *sub,
02137 dbus_bool_t is_array_append)
02138 {
02139 writer_recurse_init_and_check (writer, container_type, sub);
02140
02141 switch (container_type)
02142 {
02143 case DBUS_TYPE_STRUCT:
02144 return writer_recurse_struct_or_dict_entry (writer,
02145 DBUS_STRUCT_BEGIN_CHAR,
02146 contained_type,
02147 contained_type_start, contained_type_len,
02148 sub);
02149 break;
02150 case DBUS_TYPE_DICT_ENTRY:
02151 return writer_recurse_struct_or_dict_entry (writer,
02152 DBUS_DICT_ENTRY_BEGIN_CHAR,
02153 contained_type,
02154 contained_type_start, contained_type_len,
02155 sub);
02156 break;
02157 case DBUS_TYPE_ARRAY:
02158 return writer_recurse_array (writer,
02159 contained_type, contained_type_start, contained_type_len,
02160 sub, is_array_append);
02161 break;
02162 case DBUS_TYPE_VARIANT:
02163 return writer_recurse_variant (writer,
02164 contained_type, contained_type_start, contained_type_len,
02165 sub);
02166 break;
02167 default:
02168 _dbus_assert_not_reached ("tried to recurse into type that doesn't support that");
02169 return FALSE;
02170 break;
02171 }
02172 }
02173
02184 dbus_bool_t
02185 _dbus_type_writer_recurse (DBusTypeWriter *writer,
02186 int container_type,
02187 const DBusString *contained_type,
02188 int contained_type_start,
02189 DBusTypeWriter *sub)
02190 {
02191 int contained_type_len;
02192
02193 if (contained_type)
02194 contained_type_len = find_len_of_complete_type (contained_type, contained_type_start);
02195 else
02196 contained_type_len = 0;
02197
02198 return _dbus_type_writer_recurse_contained_len (writer, container_type,
02199 contained_type,
02200 contained_type_start,
02201 contained_type_len,
02202 sub,
02203 FALSE);
02204 }
02205
02218 dbus_bool_t
02219 _dbus_type_writer_append_array (DBusTypeWriter *writer,
02220 const DBusString *contained_type,
02221 int contained_type_start,
02222 DBusTypeWriter *sub)
02223 {
02224 int contained_type_len;
02225
02226 if (contained_type)
02227 contained_type_len = find_len_of_complete_type (contained_type, contained_type_start);
02228 else
02229 contained_type_len = 0;
02230
02231 return _dbus_type_writer_recurse_contained_len (writer, DBUS_TYPE_ARRAY,
02232 contained_type,
02233 contained_type_start,
02234 contained_type_len,
02235 sub,
02236 TRUE);
02237 }
02238
02239 static int
02240 writer_get_array_len (DBusTypeWriter *writer)
02241 {
02242 _dbus_assert (writer->container_type == DBUS_TYPE_ARRAY);
02243 return writer->value_pos - writer->u.array.start_pos;
02244 }
02245
02254 dbus_bool_t
02255 _dbus_type_writer_unrecurse (DBusTypeWriter *writer,
02256 DBusTypeWriter *sub)
02257 {
02258
02259 _dbus_assert (!writer->type_pos_is_expectation ||
02260 (writer->type_pos_is_expectation && sub->type_pos_is_expectation));
02261
02262 #if RECURSIVE_MARSHAL_WRITE_TRACE
02263 _dbus_verbose (" type writer %p unrecurse type_pos = %d value_pos = %d is_expectation = %d container_type = %s\n",
02264 writer, writer->type_pos, writer->value_pos, writer->type_pos_is_expectation,
02265 _dbus_type_to_string (writer->container_type));
02266 _dbus_verbose (" type writer %p unrecurse sub type_pos = %d value_pos = %d is_expectation = %d container_type = %s\n",
02267 sub, sub->type_pos, sub->value_pos,
02268 sub->type_pos_is_expectation,
02269 _dbus_type_to_string (sub->container_type));
02270 #endif
02271
02272 if (sub->container_type == DBUS_TYPE_STRUCT)
02273 {
02274 if (!write_or_verify_typecode (sub, DBUS_STRUCT_END_CHAR))
02275 return FALSE;
02276 }
02277 else if (sub->container_type == DBUS_TYPE_DICT_ENTRY)
02278 {
02279 if (!write_or_verify_typecode (sub, DBUS_DICT_ENTRY_END_CHAR))
02280 return FALSE;
02281 }
02282 else if (sub->container_type == DBUS_TYPE_ARRAY)
02283 {
02284 if (sub->u.array.len_pos >= 0)
02285 {
02286 dbus_uint32_t len;
02287
02288
02289 len = writer_get_array_len (sub);
02290 _dbus_marshal_set_uint32 (sub->value_str,
02291 sub->u.array.len_pos,
02292 len,
02293 sub->byte_order);
02294 #if RECURSIVE_MARSHAL_WRITE_TRACE
02295 _dbus_verbose (" filled in sub array len to %u at len_pos %d\n",
02296 len, sub->u.array.len_pos);
02297 #endif
02298 }
02299 #if RECURSIVE_MARSHAL_WRITE_TRACE
02300 else
02301 {
02302 _dbus_verbose (" not filling in sub array len because we were disabled when we passed the len\n");
02303 }
02304 #endif
02305 }
02306
02307
02308
02309
02310
02311
02312
02313
02314
02315
02316
02317
02318
02319
02320
02321
02322
02323
02324
02325
02326
02327
02328
02329
02330
02331
02332
02333
02334
02335
02336
02337
02338
02339
02340
02341
02342
02343
02344
02345
02346
02347
02348
02349
02350
02351
02352 if (writer->type_str != NULL)
02353 {
02354 if ((sub->container_type == DBUS_TYPE_STRUCT ||
02355 sub->container_type == DBUS_TYPE_DICT_ENTRY) &&
02356 (writer->container_type == DBUS_TYPE_STRUCT ||
02357 writer->container_type == DBUS_TYPE_DICT_ENTRY ||
02358 writer->container_type == DBUS_TYPE_INVALID))
02359 {
02360
02361 writer->type_pos = sub->type_pos;
02362 }
02363 }
02364
02365 writer->value_pos = sub->value_pos;
02366
02367 #if RECURSIVE_MARSHAL_WRITE_TRACE
02368 _dbus_verbose (" type writer %p unrecursed type_pos = %d value_pos = %d remaining sig '%s'\n",
02369 writer, writer->type_pos, writer->value_pos,
02370 writer->type_str ?
02371 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0) :
02372 "unknown");
02373 #endif
02374
02375 return TRUE;
02376 }
02377
02386 dbus_bool_t
02387 _dbus_type_writer_write_basic (DBusTypeWriter *writer,
02388 int type,
02389 const void *value)
02390 {
02391 dbus_bool_t retval;
02392
02393
02394 if (!writer->type_pos_is_expectation && writer->type_str != NULL)
02395 {
02396 if (!_dbus_string_alloc_space (writer->type_str, 1))
02397 return FALSE;
02398 }
02399
02400 retval = FALSE;
02401
02402 if (!_dbus_type_writer_write_basic_no_typecode (writer, type, value))
02403 goto out;
02404
02405 if (!write_or_verify_typecode (writer, type))
02406 _dbus_assert_not_reached ("failed to write typecode after prealloc");
02407
02408 retval = TRUE;
02409
02410 out:
02411 #if RECURSIVE_MARSHAL_WRITE_TRACE
02412 _dbus_verbose (" type writer %p basic type_pos = %d value_pos = %d is_expectation = %d enabled = %d\n",
02413 writer, writer->type_pos, writer->value_pos, writer->type_pos_is_expectation,
02414 writer->enabled);
02415 #endif
02416
02417 return retval;
02418 }
02419
02434 dbus_bool_t
02435 _dbus_type_writer_write_fixed_multi (DBusTypeWriter *writer,
02436 int element_type,
02437 const void *value,
02438 int n_elements)
02439 {
02440 _dbus_assert (writer->container_type == DBUS_TYPE_ARRAY);
02441 _dbus_assert (dbus_type_is_fixed (element_type));
02442 _dbus_assert (writer->type_pos_is_expectation);
02443 _dbus_assert (n_elements >= 0);
02444
02445 #if RECURSIVE_MARSHAL_WRITE_TRACE
02446 _dbus_verbose (" type writer %p entering fixed multi type_pos = %d value_pos = %d n_elements %d\n",
02447 writer, writer->type_pos, writer->value_pos, n_elements);
02448 #endif
02449
02450 if (!write_or_verify_typecode (writer, element_type))
02451 _dbus_assert_not_reached ("OOM should not happen if only verifying typecode");
02452
02453 if (writer->enabled)
02454 {
02455 if (!_dbus_marshal_write_fixed_multi (writer->value_str,
02456 writer->value_pos,
02457 element_type,
02458 value,
02459 n_elements,
02460 writer->byte_order,
02461 &writer->value_pos))
02462 return FALSE;
02463 }
02464
02465 #if RECURSIVE_MARSHAL_WRITE_TRACE
02466 _dbus_verbose (" type writer %p fixed multi written new type_pos = %d new value_pos = %d n_elements %d\n",
02467 writer, writer->type_pos, writer->value_pos, n_elements);
02468 #endif
02469
02470 return TRUE;
02471 }
02472
02473 static void
02474 enable_if_after (DBusTypeWriter *writer,
02475 DBusTypeReader *reader,
02476 const DBusTypeReader *start_after)
02477 {
02478 if (start_after)
02479 {
02480 if (!writer->enabled && _dbus_type_reader_greater_than (reader, start_after))
02481 {
02482 _dbus_type_writer_set_enabled (writer, TRUE);
02483 #if RECURSIVE_MARSHAL_WRITE_TRACE
02484 _dbus_verbose ("ENABLING writer %p at %d because reader at value_pos %d is after reader at value_pos %d\n",
02485 writer, writer->value_pos, reader->value_pos, start_after->value_pos);
02486 #endif
02487 }
02488
02489 _dbus_assert ((!writer->enabled && !_dbus_type_reader_greater_than (reader, start_after)) ||
02490 (writer->enabled && _dbus_type_reader_greater_than (reader, start_after)));
02491 }
02492 }
02493
02494 static dbus_bool_t
02495 append_fixup (DBusList **fixups,
02496 const DBusArrayLenFixup *fixup)
02497 {
02498 DBusArrayLenFixup *f;
02499
02500 f = dbus_new (DBusArrayLenFixup, 1);
02501 if (f == NULL)
02502 return FALSE;
02503
02504 *f = *fixup;
02505
02506 if (!_dbus_list_append (fixups, f))
02507 {
02508 dbus_free (f);
02509 return FALSE;
02510 }
02511
02512 _dbus_assert (f->len_pos_in_reader == fixup->len_pos_in_reader);
02513 _dbus_assert (f->new_len == fixup->new_len);
02514
02515 return TRUE;
02516 }
02517
02518
02519
02520
02521 static dbus_bool_t
02522 writer_write_reader_helper (DBusTypeWriter *writer,
02523 DBusTypeReader *reader,
02524 const DBusTypeReader *start_after,
02525 int start_after_new_pos,
02526 int start_after_new_len,
02527 DBusList **fixups,
02528 dbus_bool_t inside_start_after)
02529 {
02530 int current_type;
02531
02532 while ((current_type = _dbus_type_reader_get_current_type (reader)) != DBUS_TYPE_INVALID)
02533 {
02534 if (dbus_type_is_container (current_type))
02535 {
02536 DBusTypeReader subreader;
02537 DBusTypeWriter subwriter;
02538 const DBusString *sig_str;
02539 int sig_start;
02540 int sig_len;
02541 dbus_bool_t enabled_at_recurse;
02542 dbus_bool_t past_start_after;
02543 int reader_array_len_pos;
02544 int reader_array_start_pos;
02545 dbus_bool_t this_is_start_after;
02546
02547
02548
02549
02550
02551
02552 if (!inside_start_after && start_after &&
02553 reader->value_pos == start_after->value_pos &&
02554 reader->type_str == start_after->type_str &&
02555 reader->type_pos == start_after->type_pos)
02556 this_is_start_after = TRUE;
02557 else
02558 this_is_start_after = FALSE;
02559
02560 _dbus_type_reader_recurse (reader, &subreader);
02561
02562 if (current_type == DBUS_TYPE_ARRAY)
02563 {
02564 reader_array_len_pos = ARRAY_READER_LEN_POS (&subreader);
02565 reader_array_start_pos = subreader.u.array.start_pos;
02566 }
02567 else
02568 {
02569
02570 reader_array_len_pos = -1;
02571 reader_array_start_pos = -1;
02572 }
02573
02574 _dbus_type_reader_get_signature (&subreader, &sig_str,
02575 &sig_start, &sig_len);
02576
02577 #if RECURSIVE_MARSHAL_WRITE_TRACE
02578 _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",
02579 _dbus_type_to_string (current_type),
02580 reader->value_pos,
02581 subreader.value_pos,
02582 writer->value_pos,
02583 start_after ? start_after->value_pos : -1,
02584 _dbus_string_get_length (writer->value_str),
02585 inside_start_after, this_is_start_after);
02586 #endif
02587
02588 if (!inside_start_after && !this_is_start_after)
02589 enable_if_after (writer, &subreader, start_after);
02590 enabled_at_recurse = writer->enabled;
02591 if (!_dbus_type_writer_recurse_contained_len (writer, current_type,
02592 sig_str, sig_start, sig_len,
02593 &subwriter, FALSE))
02594 goto oom;
02595
02596 #if RECURSIVE_MARSHAL_WRITE_TRACE
02597 _dbus_verbose ("recursed into subwriter at %d write target len %d\n",
02598 subwriter.value_pos,
02599 _dbus_string_get_length (subwriter.value_str));
02600 #endif
02601
02602 if (!writer_write_reader_helper (&subwriter, &subreader, start_after,
02603 start_after_new_pos, start_after_new_len,
02604 fixups,
02605 inside_start_after ||
02606 this_is_start_after))
02607 goto oom;
02608
02609 #if RECURSIVE_MARSHAL_WRITE_TRACE
02610 _dbus_verbose ("about to unrecurse from %s subreader at %d writer at %d subwriter at %d write target len %d\n",
02611 _dbus_type_to_string (current_type),
02612 subreader.value_pos,
02613 writer->value_pos,
02614 subwriter.value_pos,
02615 _dbus_string_get_length (writer->value_str));
02616 #endif
02617
02618 if (!inside_start_after && !this_is_start_after)
02619 enable_if_after (writer, &subreader, start_after);
02620 past_start_after = writer->enabled;
02621 if (!_dbus_type_writer_unrecurse (writer, &subwriter))
02622 goto oom;
02623
02624
02625
02626
02627
02628
02629 if (start_after != NULL &&
02630 !enabled_at_recurse && past_start_after &&
02631 current_type == DBUS_TYPE_ARRAY &&
02632 fixups != NULL)
02633 {
02634 DBusArrayLenFixup fixup;
02635 int bytes_written_after_start_after;
02636 int bytes_before_start_after;
02637 int old_len;
02638
02639
02640
02641
02642
02643 bytes_written_after_start_after = writer_get_array_len (&subwriter);
02644
02645 bytes_before_start_after =
02646 start_after->value_pos - reader_array_start_pos;
02647
02648 fixup.len_pos_in_reader = reader_array_len_pos;
02649 fixup.new_len =
02650 bytes_before_start_after +
02651 start_after_new_len +
02652 bytes_written_after_start_after;
02653
02654 _dbus_assert (_DBUS_ALIGN_VALUE (fixup.len_pos_in_reader, 4) ==
02655 (unsigned) fixup.len_pos_in_reader);
02656
02657 old_len = _dbus_unpack_uint32 (reader->byte_order,
02658 _dbus_string_get_const_data_len (reader->value_str,
02659 fixup.len_pos_in_reader, 4));
02660
02661 if (old_len != fixup.new_len && !append_fixup (fixups, &fixup))
02662 goto oom;
02663
02664 #if RECURSIVE_MARSHAL_WRITE_TRACE
02665 _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",
02666 fixup.len_pos_in_reader,
02667 fixup.new_len,
02668 reader_array_start_pos,
02669 start_after->value_pos,
02670 bytes_before_start_after,
02671 start_after_new_len,
02672 bytes_written_after_start_after);
02673 #endif
02674 }
02675 }
02676 else
02677 {
02678 DBusBasicValue val;
02679
02680 _dbus_assert (dbus_type_is_basic (current_type));
02681
02682 #if RECURSIVE_MARSHAL_WRITE_TRACE
02683 _dbus_verbose ("Reading basic value %s at %d\n",
02684 _dbus_type_to_string (current_type),
02685 reader->value_pos);
02686 #endif
02687
02688 _dbus_type_reader_read_basic (reader, &val);
02689
02690 #if RECURSIVE_MARSHAL_WRITE_TRACE
02691 _dbus_verbose ("Writing basic value %s at %d write target len %d inside_start_after = %d\n",
02692 _dbus_type_to_string (current_type),
02693 writer->value_pos,
02694 _dbus_string_get_length (writer->value_str),
02695 inside_start_after);
02696 #endif
02697 if (!inside_start_after)
02698 enable_if_after (writer, reader, start_after);
02699 if (!_dbus_type_writer_write_basic (writer, current_type, &val))
02700 goto oom;
02701 #if RECURSIVE_MARSHAL_WRITE_TRACE
02702 _dbus_verbose ("Wrote basic value %s, new value_pos %d write target len %d\n",
02703 _dbus_type_to_string (current_type),
02704 writer->value_pos,
02705 _dbus_string_get_length (writer->value_str));
02706 #endif
02707 }
02708
02709 _dbus_type_reader_next (reader);
02710 }
02711
02712 return TRUE;
02713
02714 oom:
02715 if (fixups)
02716 apply_and_free_fixups (fixups, NULL);
02717
02718 return FALSE;
02719 }
02720
02752 dbus_bool_t
02753 _dbus_type_writer_write_reader_partial (DBusTypeWriter *writer,
02754 DBusTypeReader *reader,
02755 const DBusTypeReader *start_after,
02756 int start_after_new_pos,
02757 int start_after_new_len,
02758 DBusList **fixups)
02759 {
02760 DBusTypeWriter orig;
02761 int orig_type_len;
02762 int orig_value_len;
02763 int new_bytes;
02764 int orig_enabled;
02765
02766 orig = *writer;
02767 orig_type_len = _dbus_string_get_length (writer->type_str);
02768 orig_value_len = _dbus_string_get_length (writer->value_str);
02769 orig_enabled = writer->enabled;
02770
02771 if (start_after)
02772 _dbus_type_writer_set_enabled (writer, FALSE);
02773
02774 if (!writer_write_reader_helper (writer, reader, start_after,
02775 start_after_new_pos,
02776 start_after_new_len,
02777 fixups, FALSE))
02778 goto oom;
02779
02780 _dbus_type_writer_set_enabled (writer, orig_enabled);
02781 return TRUE;
02782
02783 oom:
02784 if (!writer->type_pos_is_expectation)
02785 {
02786 new_bytes = _dbus_string_get_length (writer->type_str) - orig_type_len;
02787 _dbus_string_delete (writer->type_str, orig.type_pos, new_bytes);
02788 }
02789 new_bytes = _dbus_string_get_length (writer->value_str) - orig_value_len;
02790 _dbus_string_delete (writer->value_str, orig.value_pos, new_bytes);
02791
02792 *writer = orig;
02793
02794 return FALSE;
02795 }
02796
02806 dbus_bool_t
02807 _dbus_type_writer_write_reader (DBusTypeWriter *writer,
02808 DBusTypeReader *reader)
02809 {
02810 return _dbus_type_writer_write_reader_partial (writer, reader, NULL, 0, 0, NULL);
02811 }
02812
02822 void
02823 _dbus_type_writer_set_enabled (DBusTypeWriter *writer,
02824 dbus_bool_t enabled)
02825 {
02826 writer->enabled = enabled != FALSE;
02827 }
02828
02830
02831