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