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