D-Bus  1.13.16
dbus-marshal-recursive.c
1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* dbus-marshal-recursive.c Marshalling routines for recursive types
3  *
4  * Copyright (C) 2004, 2005 Red Hat, Inc.
5  *
6  * Licensed under the Academic Free License version 2.1
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  *
22  */
23 
24 #include <config.h>
25 #include "dbus-marshal-recursive.h"
26 #include "dbus-marshal-basic.h"
27 #include "dbus-signature.h"
28 #include "dbus-internals.h"
29 
35 static dbus_bool_t _dbus_type_reader_greater_than (const DBusTypeReader *lhs,
36  const DBusTypeReader *rhs);
37 
38 static void _dbus_type_writer_set_enabled (DBusTypeWriter *writer,
39  dbus_bool_t enabled);
40 static dbus_bool_t _dbus_type_writer_write_reader_partial (DBusTypeWriter *writer,
41  DBusTypeReader *reader,
42  const DBusTypeReader *start_after,
43  int start_after_new_pos,
44  int start_after_new_len,
45  DBusList **fixups);
46 
48 #define RECURSIVE_MARSHAL_READ_TRACE 0
49 
51 #define RECURSIVE_MARSHAL_WRITE_TRACE 0
52 
53 static void
54 free_fixups (DBusList **fixups)
55 {
56  DBusList *link;
57 
58  link = _dbus_list_get_first_link (fixups);
59  while (link != NULL)
60  {
61  DBusList *next;
62 
63  next = _dbus_list_get_next_link (fixups, link);
64 
65  dbus_free (link->data);
66  _dbus_list_free_link (link);
67 
68  link = next;
69  }
70 
71  *fixups = NULL;
72 }
73 
74 static void
75 apply_and_free_fixups (DBusList **fixups,
76  DBusTypeReader *reader)
77 {
78  DBusList *link;
79 
80 #if RECURSIVE_MARSHAL_WRITE_TRACE
81  if (*fixups)
82  _dbus_verbose (" %d FIXUPS to apply\n",
83  _dbus_list_get_length (fixups));
84 #endif
85 
86  link = _dbus_list_get_first_link (fixups);
87  while (link != NULL)
88  {
89  DBusList *next;
90 
91  next = _dbus_list_get_next_link (fixups, link);
92 
93  if (reader)
94  {
96 
97  f = link->data;
98 
99 #if RECURSIVE_MARSHAL_WRITE_TRACE
100  _dbus_verbose (" applying FIXUP to reader %p at pos %d new_len = %d old len %d\n",
101  reader, f->len_pos_in_reader, f->new_len,
104  reader->byte_order, NULL));
105 #endif
106 
109  f->new_len,
110  reader->byte_order);
111  }
112 
113  dbus_free (link->data);
114  _dbus_list_free_link (link);
115 
116  link = next;
117  }
118 
119  *fixups = NULL;
120 }
121 
126 {
127  const char *name;
128  int id;
130  void (* recurse) (DBusTypeReader *sub,
131  DBusTypeReader *parent);
133  void (* next) (DBusTypeReader *reader,
134  int current_type);
135 };
136 
137 static int
138 element_type_get_alignment (const DBusString *str,
139  int pos)
140 {
142 }
143 
144 static void
145 reader_init (DBusTypeReader *reader,
146  int byte_order,
147  const DBusString *type_str,
148  int type_pos,
149  const DBusString *value_str,
150  int value_pos)
151 {
152  _DBUS_ZERO (*reader);
153  reader->byte_order = byte_order;
154  reader->finished = FALSE;
155  reader->type_str = type_str;
156  reader->type_pos = type_pos;
157  reader->value_str = value_str;
158  reader->value_pos = value_pos;
159 }
160 
161 static void
162 base_reader_recurse (DBusTypeReader *sub,
163  DBusTypeReader *parent)
164 {
165  /* point subreader at the same place as parent */
166  reader_init (sub,
167  parent->byte_order,
168  parent->type_str,
169  parent->type_pos,
170  parent->value_str,
171  parent->value_pos);
172 }
173 
174 static void
175 struct_or_dict_entry_types_only_reader_recurse (DBusTypeReader *sub,
176  DBusTypeReader *parent)
177 {
178  base_reader_recurse (sub, parent);
179 
180  _dbus_assert (_dbus_string_get_byte (sub->type_str,
181  sub->type_pos) == DBUS_STRUCT_BEGIN_CHAR ||
182  _dbus_string_get_byte (sub->type_str,
184 
185  sub->type_pos += 1;
186 }
187 
188 static void
189 struct_or_dict_entry_reader_recurse (DBusTypeReader *sub,
190  DBusTypeReader *parent)
191 {
192  struct_or_dict_entry_types_only_reader_recurse (sub, parent);
193 
194  /* struct and dict entry have 8 byte alignment */
195  sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 8);
196 }
197 
198 static void
199 array_types_only_reader_recurse (DBusTypeReader *sub,
200  DBusTypeReader *parent)
201 {
202  base_reader_recurse (sub, parent);
203 
204  /* point type_pos at the array element type */
205  sub->type_pos += 1;
206 
207  /* Init with values likely to crash things if misused */
208  sub->u.array.start_pos = _DBUS_INT_MAX;
209  sub->array_len_offset = 7;
210 }
211 
214 #define ARRAY_READER_LEN_POS(reader) \
215  ((reader)->u.array.start_pos - ((int)(reader)->array_len_offset) - 4)
216 
217 static int
218 array_reader_get_array_len (const DBusTypeReader *reader)
219 {
220  dbus_uint32_t array_len;
221  int len_pos;
222 
223  len_pos = ARRAY_READER_LEN_POS (reader);
224 
225  _dbus_assert (_DBUS_ALIGN_VALUE (len_pos, 4) == (unsigned) len_pos);
226  array_len = _dbus_unpack_uint32 (reader->byte_order,
227  _dbus_string_get_const_udata_len (reader->value_str, len_pos, 4));
228 
229 #if RECURSIVE_MARSHAL_READ_TRACE
230  _dbus_verbose (" reader %p len_pos %d array len %u len_offset %d\n",
231  reader, len_pos, array_len, reader->array_len_offset);
232 #endif
233 
234  _dbus_assert (reader->u.array.start_pos - len_pos - 4 < 8);
235 
236  return array_len;
237 }
238 
239 static void
240 array_reader_recurse (DBusTypeReader *sub,
241  DBusTypeReader *parent)
242 {
243  int alignment;
244  int len_pos;
245 
246  array_types_only_reader_recurse (sub, parent);
247 
248  sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 4);
249 
250  len_pos = sub->value_pos;
251 
252  sub->value_pos += 4; /* for the length */
253 
254  alignment = element_type_get_alignment (sub->type_str,
255  sub->type_pos);
256 
257  sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, alignment);
258 
259  sub->u.array.start_pos = sub->value_pos;
260  _dbus_assert ((sub->u.array.start_pos - (len_pos + 4)) < 8); /* only 3 bits in array_len_offset */
261  sub->array_len_offset = sub->u.array.start_pos - (len_pos + 4);
262 
263 #if RECURSIVE_MARSHAL_READ_TRACE
264  _dbus_verbose (" type reader %p array start = %d len_offset = %d array len = %d array element type = %s\n",
265  sub,
266  sub->u.array.start_pos,
267  sub->array_len_offset,
268  array_reader_get_array_len (sub),
270  sub->type_pos)));
271 #endif
272 }
273 
274 static void
275 variant_reader_recurse (DBusTypeReader *sub,
276  DBusTypeReader *parent)
277 {
278  int sig_len;
279  int contained_alignment;
280 
281  base_reader_recurse (sub, parent);
282 
283  /* Variant is 1 byte sig length (without nul), signature with nul,
284  * padding to 8-boundary, then values
285  */
286 
287  sig_len = _dbus_string_get_byte (sub->value_str, sub->value_pos);
288 
289  sub->type_str = sub->value_str;
290  sub->type_pos = sub->value_pos + 1;
291 
292  sub->value_pos = sub->type_pos + sig_len + 1;
293 
295  sub->type_pos));
296 
297  sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, contained_alignment);
298 
299 #if RECURSIVE_MARSHAL_READ_TRACE
300  _dbus_verbose (" type reader %p variant containing '%s'\n",
301  sub,
302  _dbus_string_get_const_data_len (sub->type_str,
303  sub->type_pos, 0));
304 #endif
305 }
306 
307 static dbus_bool_t
308 array_reader_check_finished (const DBusTypeReader *reader)
309 {
310  int end_pos;
311 
312  /* return the array element type if elements remain, and
313  * TYPE_INVALID otherwise
314  */
315 
316  end_pos = reader->u.array.start_pos + array_reader_get_array_len (reader);
317 
318  _dbus_assert (reader->value_pos <= end_pos);
319  _dbus_assert (reader->value_pos >= reader->u.array.start_pos);
320 
321  return reader->value_pos == end_pos;
322 }
323 
324 static void
325 skip_one_complete_type (const DBusString *type_str,
326  int *type_pos)
327 {
328  _dbus_type_signature_next (_dbus_string_get_const_data (type_str),
329  type_pos);
330 }
331 
340 void
341 _dbus_type_signature_next (const char *type_str,
342  int *type_pos)
343 {
344  const unsigned char *p;
345  const unsigned char *start;
346 
347  _dbus_assert (type_str != NULL);
348  _dbus_assert (type_pos != NULL);
349 
350  start = (const unsigned char *)type_str;
351  p = start + *type_pos;
352 
355 
356  while (*p == DBUS_TYPE_ARRAY)
357  ++p;
358 
361 
362  if (*p == DBUS_STRUCT_BEGIN_CHAR)
363  {
364  int depth;
365 
366  depth = 1;
367 
368  while (TRUE)
369  {
371 
372  ++p;
373 
375 
376  if (*p == DBUS_STRUCT_BEGIN_CHAR)
377  depth += 1;
378  else if (*p == DBUS_STRUCT_END_CHAR)
379  {
380  depth -= 1;
381  if (depth == 0)
382  {
383  ++p;
384  break;
385  }
386  }
387  }
388  }
389  else if (*p == DBUS_DICT_ENTRY_BEGIN_CHAR)
390  {
391  int depth;
392 
393  depth = 1;
394 
395  while (TRUE)
396  {
398 
399  ++p;
400 
402 
403  if (*p == DBUS_DICT_ENTRY_BEGIN_CHAR)
404  depth += 1;
405  else if (*p == DBUS_DICT_ENTRY_END_CHAR)
406  {
407  depth -= 1;
408  if (depth == 0)
409  {
410  ++p;
411  break;
412  }
413  }
414  }
415  }
416  else
417  {
418  ++p;
419  }
420 
421  *type_pos = (int) (p - start);
422 }
423 
424 static int
425 find_len_of_complete_type (const DBusString *type_str,
426  int type_pos)
427 {
428  int end;
429 
430  end = type_pos;
431 
432  skip_one_complete_type (type_str, &end);
433 
434  return end - type_pos;
435 }
436 
437 static void
438 base_reader_next (DBusTypeReader *reader,
439  int current_type)
440 {
441  switch (current_type)
442  {
444  case DBUS_TYPE_STRUCT:
445  case DBUS_TYPE_VARIANT:
446  /* Scan forward over the entire container contents */
447  {
448  DBusTypeReader sub;
449 
450  if (reader->klass->types_only && current_type == DBUS_TYPE_VARIANT)
451  ;
452  else
453  {
454  /* Recurse into the struct or variant */
455  _dbus_type_reader_recurse (reader, &sub);
456 
457  /* Skip everything in this subreader */
458  while (_dbus_type_reader_next (&sub))
459  {
460  /* nothing */;
461  }
462  }
463  if (!reader->klass->types_only)
464  reader->value_pos = sub.value_pos;
465 
466  /* Now we are at the end of this container; for variants, the
467  * subreader's type_pos is totally inapplicable (it's in the
468  * value string) but we know that we increment by one past the
469  * DBUS_TYPE_VARIANT
470  */
471  if (current_type == DBUS_TYPE_VARIANT)
472  reader->type_pos += 1;
473  else
474  reader->type_pos = sub.type_pos;
475  }
476  break;
477 
478  case DBUS_TYPE_ARRAY:
479  {
480  if (!reader->klass->types_only)
483  reader->type_pos + 1),
484  reader->byte_order,
485  &reader->value_pos);
486 
487  skip_one_complete_type (reader->type_str, &reader->type_pos);
488  }
489  break;
490 
491  default:
492  if (!reader->klass->types_only)
494  current_type, reader->byte_order,
495  &reader->value_pos);
496 
497  reader->type_pos += 1;
498  break;
499  }
500 }
501 
502 static void
503 struct_reader_next (DBusTypeReader *reader,
504  int current_type)
505 {
506  int t;
507 
508  base_reader_next (reader, current_type);
509 
510  /* for STRUCT containers we return FALSE at the end of the struct,
511  * for INVALID we return FALSE at the end of the signature.
512  * In both cases we arrange for get_current_type() to return INVALID
513  * which is defined to happen iff we're at the end (no more next())
514  */
515  t = _dbus_string_get_byte (reader->type_str, reader->type_pos);
516  if (t == DBUS_STRUCT_END_CHAR)
517  {
518  reader->type_pos += 1;
519  reader->finished = TRUE;
520  }
521 }
522 
523 static void
524 dict_entry_reader_next (DBusTypeReader *reader,
525  int current_type)
526 {
527  int t;
528 
529  base_reader_next (reader, current_type);
530 
531  /* for STRUCT containers we return FALSE at the end of the struct,
532  * for INVALID we return FALSE at the end of the signature.
533  * In both cases we arrange for get_current_type() to return INVALID
534  * which is defined to happen iff we're at the end (no more next())
535  */
536  t = _dbus_string_get_byte (reader->type_str, reader->type_pos);
537  if (t == DBUS_DICT_ENTRY_END_CHAR)
538  {
539  reader->type_pos += 1;
540  reader->finished = TRUE;
541  }
542 }
543 
544 static void
545 array_types_only_reader_next (DBusTypeReader *reader,
546  int current_type)
547 {
548  /* We have one "element" to be iterated over
549  * in each array, which is its element type.
550  * So the finished flag indicates whether we've
551  * iterated over it yet or not.
552  */
553  reader->finished = TRUE;
554 }
555 
556 static void
557 array_reader_next (DBusTypeReader *reader,
558  int current_type)
559 {
560  /* Skip one array element */
561  int end_pos;
562 
563  end_pos = reader->u.array.start_pos + array_reader_get_array_len (reader);
564 
565 #if RECURSIVE_MARSHAL_READ_TRACE
566  _dbus_verbose (" reader %p array next START start_pos = %d end_pos = %d value_pos = %d current_type = %s\n",
567  reader,
568  reader->u.array.start_pos,
569  end_pos, reader->value_pos,
570  _dbus_type_to_string (current_type));
571 #endif
572 
573  _dbus_assert (reader->value_pos < end_pos);
574  _dbus_assert (reader->value_pos >= reader->u.array.start_pos);
575 
576  switch (_dbus_first_type_in_signature (reader->type_str,
577  reader->type_pos))
578  {
580  case DBUS_TYPE_STRUCT:
581  case DBUS_TYPE_VARIANT:
582  {
583  DBusTypeReader sub;
584 
585  /* Recurse into the struct or variant */
586  _dbus_type_reader_recurse (reader, &sub);
587 
588  /* Skip everything in this element */
589  while (_dbus_type_reader_next (&sub))
590  {
591  /* nothing */;
592  }
593 
594  /* Now we are at the end of this element */
595  reader->value_pos = sub.value_pos;
596  }
597  break;
598 
599  case DBUS_TYPE_ARRAY:
600  {
603  reader->type_pos + 1),
604  reader->byte_order,
605  &reader->value_pos);
606  }
607  break;
608 
609  default:
610  {
612  current_type, reader->byte_order,
613  &reader->value_pos);
614  }
615  break;
616  }
617 
618 #if RECURSIVE_MARSHAL_READ_TRACE
619  _dbus_verbose (" reader %p array next END start_pos = %d end_pos = %d value_pos = %d current_type = %s\n",
620  reader,
621  reader->u.array.start_pos,
622  end_pos, reader->value_pos,
623  _dbus_type_to_string (current_type));
624 #endif
625 
626  _dbus_assert (reader->value_pos <= end_pos);
627 
628  if (reader->value_pos == end_pos)
629  {
630  skip_one_complete_type (reader->type_str,
631  &reader->type_pos);
632  }
633 }
634 
635 static const DBusTypeReaderClass body_reader_class = {
636  "body", 0,
637  FALSE,
638  NULL, /* body is always toplevel, so doesn't get recursed into */
639  NULL,
640  base_reader_next
641 };
642 
643 static const DBusTypeReaderClass body_types_only_reader_class = {
644  "body types", 1,
645  TRUE,
646  NULL, /* body is always toplevel, so doesn't get recursed into */
647  NULL,
648  base_reader_next
649 };
650 
651 static const DBusTypeReaderClass struct_reader_class = {
652  "struct", 2,
653  FALSE,
654  struct_or_dict_entry_reader_recurse,
655  NULL,
656  struct_reader_next
657 };
658 
659 static const DBusTypeReaderClass struct_types_only_reader_class = {
660  "struct types", 3,
661  TRUE,
662  struct_or_dict_entry_types_only_reader_recurse,
663  NULL,
664  struct_reader_next
665 };
666 
667 static const DBusTypeReaderClass dict_entry_reader_class = {
668  "dict_entry", 4,
669  FALSE,
670  struct_or_dict_entry_reader_recurse,
671  NULL,
672  dict_entry_reader_next
673 };
674 
675 static const DBusTypeReaderClass dict_entry_types_only_reader_class = {
676  "dict_entry types", 5,
677  TRUE,
678  struct_or_dict_entry_types_only_reader_recurse,
679  NULL,
680  dict_entry_reader_next
681 };
682 
683 static const DBusTypeReaderClass array_reader_class = {
684  "array", 6,
685  FALSE,
686  array_reader_recurse,
687  array_reader_check_finished,
688  array_reader_next
689 };
690 
691 static const DBusTypeReaderClass array_types_only_reader_class = {
692  "array types", 7,
693  TRUE,
694  array_types_only_reader_recurse,
695  NULL,
696  array_types_only_reader_next
697 };
698 
699 static const DBusTypeReaderClass variant_reader_class = {
700  "variant", 8,
701  FALSE,
702  variant_reader_recurse,
703  NULL,
704  base_reader_next
705 };
706 
707 #ifndef DBUS_DISABLE_ASSERT
708 static const DBusTypeReaderClass * const
709 all_reader_classes[] = {
710  &body_reader_class,
711  &body_types_only_reader_class,
712  &struct_reader_class,
713  &struct_types_only_reader_class,
714  &dict_entry_reader_class,
715  &dict_entry_types_only_reader_class,
716  &array_reader_class,
717  &array_types_only_reader_class,
718  &variant_reader_class
719 };
720 #endif
721 
732 void
734  int byte_order,
735  const DBusString *type_str,
736  int type_pos,
737  const DBusString *value_str,
738  int value_pos)
739 {
740  reader_init (reader, byte_order, type_str, type_pos,
741  value_str, value_pos);
742 
743  reader->klass = &body_reader_class;
744 
745 #if RECURSIVE_MARSHAL_READ_TRACE
746  _dbus_verbose (" type reader %p init type_pos = %d value_pos = %d remaining sig '%s'\n",
747  reader, reader->type_pos, reader->value_pos,
748  _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0));
749 #endif
750 }
751 
760 void
762  const DBusString *type_str,
763  int type_pos)
764 {
765  reader_init (reader, DBUS_COMPILER_BYTE_ORDER /* irrelevant */,
766  type_str, type_pos, NULL, _DBUS_INT_MAX /* crashes if we screw up */);
767 
768  reader->klass = &body_types_only_reader_class;
769 
770 #if RECURSIVE_MARSHAL_READ_TRACE
771  _dbus_verbose (" type reader %p init types only type_pos = %d remaining sig '%s'\n",
772  reader, reader->type_pos,
773  _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0));
774 #endif
775 }
776 
785 int
787 {
788  int t;
789 
790  if (reader->finished ||
791  (reader->klass->check_finished &&
792  (* reader->klass->check_finished) (reader)))
793  t = DBUS_TYPE_INVALID;
794  else
796  reader->type_pos);
797 
802 
803 #if 0
804  _dbus_verbose (" type reader %p current type_pos = %d type = %s\n",
805  reader, reader->type_pos,
807 #endif
808 
809  return t;
810 }
811 
820 int
822 {
823  int element_type;
824 
826 
827  element_type = _dbus_first_type_in_signature (reader->type_str,
828  reader->type_pos + 1);
829 
830  return element_type;
831 }
832 
837 int
839 {
840  return reader->value_pos;
841 }
842 
852 void
854  const unsigned char **value_location)
855 {
856  _dbus_assert (!reader->klass->types_only);
857 
858  *value_location = _dbus_string_get_const_udata_len (reader->value_str,
859  reader->value_pos,
860  0);
861 }
862 
869 void
871  void *value)
872 {
873  int t;
874 
875  _dbus_assert (!reader->klass->types_only);
876 
878 
880  reader->value_pos,
881  t, value,
882  reader->byte_order,
883  NULL);
884 
885 
886 #if RECURSIVE_MARSHAL_READ_TRACE
887  _dbus_verbose (" type reader %p read basic type_pos = %d value_pos = %d remaining sig '%s'\n",
888  reader, reader->type_pos, reader->value_pos,
889  _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0));
890 #endif
891 }
892 
899 int
901 {
902  _dbus_assert (!reader->klass->types_only);
903  _dbus_assert (reader->klass == &array_reader_class);
904 
905  return array_reader_get_array_len (reader);
906 }
907 
923 void
925  const void **value,
926  int *n_elements)
927 {
928  int element_type;
929  int end_pos;
930  int remaining_len;
931  int alignment;
932  int total_len;
933 
934  _dbus_assert (!reader->klass->types_only);
935  _dbus_assert (reader->klass == &array_reader_class);
936 
937  element_type = _dbus_first_type_in_signature (reader->type_str,
938  reader->type_pos);
939 
940  _dbus_assert (element_type != DBUS_TYPE_INVALID); /* why we don't use get_current_type() */
941  _dbus_assert (dbus_type_is_fixed (element_type));
942 
943  alignment = _dbus_type_get_alignment (element_type);
944 
945  _dbus_assert (reader->value_pos >= reader->u.array.start_pos);
946 
947  total_len = array_reader_get_array_len (reader);
948  end_pos = reader->u.array.start_pos + total_len;
949  remaining_len = end_pos - reader->value_pos;
950 
951 #if RECURSIVE_MARSHAL_READ_TRACE
952  _dbus_verbose ("end_pos %d total_len %d remaining_len %d value_pos %d\n",
953  end_pos, total_len, remaining_len, reader->value_pos);
954 #endif
955 
956  _dbus_assert (remaining_len <= total_len);
957 
958  if (remaining_len == 0)
959  *value = NULL;
960  else
961  *value = _dbus_string_get_const_data_len (reader->value_str,
962  reader->value_pos,
963  remaining_len);
964 
965  *n_elements = remaining_len / alignment;
966  _dbus_assert ((remaining_len % alignment) == 0);
967 
968 #if RECURSIVE_MARSHAL_READ_TRACE
969  _dbus_verbose (" type reader %p read fixed array type_pos = %d value_pos = %d remaining sig '%s'\n",
970  reader, reader->type_pos, reader->value_pos,
971  _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0));
972 #endif
973 }
974 
987 void
989  DBusTypeReader *sub)
990 {
991  int t;
992  const DBusTypeReaderClass *klass = NULL;
993 
994  t = _dbus_first_type_in_signature (reader->type_str, reader->type_pos);
995 
996  switch (t)
997  {
998  case DBUS_TYPE_STRUCT:
999  if (reader->klass->types_only)
1000  klass = &struct_types_only_reader_class;
1001  else
1002  klass = &struct_reader_class;
1003  break;
1004  case DBUS_TYPE_DICT_ENTRY:
1005  if (reader->klass->types_only)
1006  klass = &dict_entry_types_only_reader_class;
1007  else
1008  klass = &dict_entry_reader_class;
1009  break;
1010  case DBUS_TYPE_ARRAY:
1011  if (reader->klass->types_only)
1012  klass = &array_types_only_reader_class;
1013  else
1014  klass = &array_reader_class;
1015  break;
1016  case DBUS_TYPE_VARIANT:
1017  if (reader->klass->types_only)
1018  _dbus_assert_not_reached ("can't recurse into variant typecode");
1019  else
1020  klass = &variant_reader_class;
1021  break;
1022  default:
1023  _dbus_verbose ("recursing into type %s\n", _dbus_type_to_string (t));
1024 #ifndef DBUS_DISABLE_CHECKS
1025  if (t == DBUS_TYPE_INVALID)
1026  _dbus_warn_check_failed ("You can't recurse into an empty array or off the end of a message body");
1027 #endif /* DBUS_DISABLE_CHECKS */
1028 
1029  _dbus_assert_not_reached ("don't yet handle recursing into this type");
1030  }
1031 
1032  _dbus_assert (klass != NULL);
1033  _dbus_assert (klass == all_reader_classes[klass->id]);
1034 
1035  (* klass->recurse) (sub, reader);
1036  sub->klass = klass;
1037 
1038 #if RECURSIVE_MARSHAL_READ_TRACE
1039  _dbus_verbose (" type reader %p RECURSED type_pos = %d value_pos = %d remaining sig '%s'\n",
1040  sub, sub->type_pos, sub->value_pos,
1041  _dbus_string_get_const_data_len (sub->type_str, sub->type_pos, 0));
1042 #endif
1043 }
1044 
1055 {
1056  int t;
1057 
1059 
1060 #if RECURSIVE_MARSHAL_READ_TRACE
1061  _dbus_verbose (" type reader %p START next() { type_pos = %d value_pos = %d remaining sig '%s' current_type = %s\n",
1062  reader, reader->type_pos, reader->value_pos,
1063  _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0),
1064  _dbus_type_to_string (t));
1065 #endif
1066 
1067  if (t == DBUS_TYPE_INVALID)
1068  return FALSE;
1069 
1070  (* reader->klass->next) (reader, t);
1071 
1072 #if RECURSIVE_MARSHAL_READ_TRACE
1073  _dbus_verbose (" type reader %p END next() type_pos = %d value_pos = %d remaining sig '%s' current_type = %s\n",
1074  reader, reader->type_pos, reader->value_pos,
1075  _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0),
1077 #endif
1078 
1080 }
1081 
1095 {
1096  /* Not efficient but works for now. */
1097  DBusTypeReader copy;
1098 
1099  copy = *reader;
1100  return _dbus_type_reader_next (&copy);
1101 }
1102 
1124 void
1126  const DBusString **str_p,
1127  int *start_p,
1128  int *len_p)
1129 {
1130  *str_p = reader->type_str;
1131  *start_p = reader->type_pos;
1132  *len_p = find_len_of_complete_type (reader->type_str, reader->type_pos);
1133 }
1134 
1135 typedef struct
1136 {
1138  int padding;
1140 
1141 static dbus_bool_t
1142 replacement_block_init (ReplacementBlock *block,
1143  DBusTypeReader *reader)
1144 {
1145  if (!_dbus_string_init (&block->replacement))
1146  return FALSE;
1147 
1148  /* % 8 is the padding to have the same align properties in
1149  * our replacement string as we do at the position being replaced
1150  */
1151  block->padding = reader->value_pos % 8;
1152 
1153  if (!_dbus_string_lengthen (&block->replacement, block->padding))
1154  goto oom;
1155 
1156  return TRUE;
1157 
1158  oom:
1159  _dbus_string_free (&block->replacement);
1160  return FALSE;
1161 }
1162 
1163 static dbus_bool_t
1164 replacement_block_replace (ReplacementBlock *block,
1165  DBusTypeReader *reader,
1166  const DBusTypeReader *realign_root)
1167 {
1168  DBusTypeWriter writer;
1169  DBusTypeReader realign_reader;
1170  DBusList *fixups;
1171  int orig_len;
1172 
1173  _dbus_assert (realign_root != NULL);
1174 
1175  orig_len = _dbus_string_get_length (&block->replacement);
1176 
1177  realign_reader = *realign_root;
1178 
1179 #if RECURSIVE_MARSHAL_WRITE_TRACE
1180  _dbus_verbose ("INITIALIZING replacement block writer %p at value_pos %d\n",
1181  &writer, _dbus_string_get_length (&block->replacement));
1182 #endif
1184  realign_reader.byte_order,
1185  realign_reader.type_str,
1186  realign_reader.type_pos,
1187  &block->replacement,
1188  _dbus_string_get_length (&block->replacement));
1189 
1190  _dbus_assert (realign_reader.value_pos <= reader->value_pos);
1191 
1192 #if RECURSIVE_MARSHAL_WRITE_TRACE
1193  _dbus_verbose ("COPYING from reader at value_pos %d to writer %p starting after value_pos %d\n",
1194  realign_reader.value_pos, &writer, reader->value_pos);
1195 #endif
1196  fixups = NULL;
1197  if (!_dbus_type_writer_write_reader_partial (&writer,
1198  &realign_reader,
1199  reader,
1200  block->padding,
1201  _dbus_string_get_length (&block->replacement) - block->padding,
1202  &fixups))
1203  goto oom;
1204 
1205 #if RECURSIVE_MARSHAL_WRITE_TRACE
1206  _dbus_verbose ("REPLACEMENT at padding %d len %d\n", block->padding,
1207  _dbus_string_get_length (&block->replacement) - block->padding);
1209  _dbus_string_get_length (&block->replacement) - block->padding);
1210  _dbus_verbose ("TO BE REPLACED at value_pos = %d (align pad %d) len %d realign_reader.value_pos %d\n",
1211  reader->value_pos, reader->value_pos % 8,
1212  realign_reader.value_pos - reader->value_pos,
1213  realign_reader.value_pos);
1215  reader->value_pos,
1216  realign_reader.value_pos - reader->value_pos);
1217 #endif
1218 
1219  /* Move the replacement into position
1220  * (realign_reader should now be at the end of the block to be replaced)
1221  */
1222  if (!_dbus_string_replace_len (&block->replacement, block->padding,
1223  _dbus_string_get_length (&block->replacement) - block->padding,
1224  (DBusString*) reader->value_str,
1225  reader->value_pos,
1226  realign_reader.value_pos - reader->value_pos))
1227  goto oom;
1228 
1229  /* Process our fixups now that we can't have an OOM error */
1230  apply_and_free_fixups (&fixups, reader);
1231 
1232  return TRUE;
1233 
1234  oom:
1235  _dbus_string_set_length (&block->replacement, orig_len);
1236  free_fixups (&fixups);
1237  return FALSE;
1238 }
1239 
1240 static void
1241 replacement_block_free (ReplacementBlock *block)
1242 {
1243  _dbus_string_free (&block->replacement);
1244 }
1245 
1246 /* In the variable-length case, we have to fix alignment after we insert.
1247  * The strategy is as follows:
1248  *
1249  * - pad a new string to have the same alignment as the
1250  * start of the current basic value
1251  * - write the new basic value
1252  * - copy from the original reader to the new string,
1253  * which will fix the alignment of types following
1254  * the new value
1255  * - this copy has to start at realign_root,
1256  * but not really write anything until it
1257  * passes the value being set
1258  * - as an optimization, we can stop copying
1259  * when the source and dest values are both
1260  * on an 8-boundary, since we know all following
1261  * padding and alignment will be identical
1262  * - copy the new string back to the original
1263  * string, replacing the relevant part of the
1264  * original string
1265  * - now any arrays in the original string that
1266  * contained the replaced string may have the
1267  * wrong length; so we have to fix that
1268  */
1269 static dbus_bool_t
1270 reader_set_basic_variable_length (DBusTypeReader *reader,
1271  int current_type,
1272  const void *value,
1273  const DBusTypeReader *realign_root)
1274 {
1275  dbus_bool_t retval;
1276  ReplacementBlock block;
1277  DBusTypeWriter writer;
1278 
1279  _dbus_assert (realign_root != NULL);
1280 
1281  retval = FALSE;
1282 
1283  if (!replacement_block_init (&block, reader))
1284  return FALSE;
1285 
1286  /* Write the new basic value */
1287 #if RECURSIVE_MARSHAL_WRITE_TRACE
1288  _dbus_verbose ("INITIALIZING writer %p to write basic value at value_pos %d of replacement string\n",
1289  &writer, _dbus_string_get_length (&block.replacement));
1290 #endif
1292  reader->byte_order,
1293  reader->type_str,
1294  reader->type_pos,
1295  &block.replacement,
1296  _dbus_string_get_length (&block.replacement));
1297 #if RECURSIVE_MARSHAL_WRITE_TRACE
1298  _dbus_verbose ("WRITING basic value to writer %p (replacement string)\n", &writer);
1299 #endif
1300  if (!_dbus_type_writer_write_basic (&writer, current_type, value))
1301  goto out;
1302 
1303  if (!replacement_block_replace (&block,
1304  reader,
1305  realign_root))
1306  goto out;
1307 
1308  retval = TRUE;
1309 
1310  out:
1311  replacement_block_free (&block);
1312  return retval;
1313 }
1314 
1315 static void
1316 reader_set_basic_fixed_length (DBusTypeReader *reader,
1317  int current_type,
1318  const void *value)
1319 {
1321  reader->value_pos,
1322  current_type,
1323  value,
1324  reader->byte_order,
1325  NULL, NULL);
1326 }
1327 
1364  const void *value,
1365  const DBusTypeReader *realign_root)
1366 {
1367  int current_type;
1368 
1369  _dbus_assert (!reader->klass->types_only);
1370  _dbus_assert (reader->value_str == realign_root->value_str);
1371  _dbus_assert (reader->value_pos >= realign_root->value_pos);
1372 
1373  current_type = _dbus_type_reader_get_current_type (reader);
1374 
1375 #if RECURSIVE_MARSHAL_WRITE_TRACE
1376  _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",
1377  reader, reader->type_pos, reader->value_pos,
1378  _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0),
1379  realign_root,
1380  realign_root ? realign_root->value_pos : -1,
1381  _dbus_type_to_string (current_type));
1382  _dbus_verbose_bytes_of_string (realign_root->value_str, realign_root->value_pos,
1383  _dbus_string_get_length (realign_root->value_str) -
1384  realign_root->value_pos);
1385 #endif
1386 
1387  _dbus_assert (dbus_type_is_basic (current_type));
1388 
1389  if (dbus_type_is_fixed (current_type))
1390  {
1391  reader_set_basic_fixed_length (reader, current_type, value);
1392  return TRUE;
1393  }
1394  else
1395  {
1396  _dbus_assert (realign_root != NULL);
1397  return reader_set_basic_variable_length (reader, current_type,
1398  value, realign_root);
1399  }
1400 }
1401 
1421  const DBusTypeReader *realign_root)
1422 {
1423  dbus_bool_t retval;
1424  ReplacementBlock block;
1425 
1426  _dbus_assert (realign_root != NULL);
1427  _dbus_assert (reader->klass == &array_reader_class);
1428 
1429  retval = FALSE;
1430 
1431  if (!replacement_block_init (&block, reader))
1432  return FALSE;
1433 
1434  if (!replacement_block_replace (&block,
1435  reader,
1436  realign_root))
1437  goto out;
1438 
1439  retval = TRUE;
1440 
1441  out:
1442  replacement_block_free (&block);
1443  return retval;
1444 }
1445 
1446 /*
1447  * Compares two readers, which must be iterating over the same value data.
1448  * Returns #TRUE if the first parameter is further along than the second parameter.
1449  *
1450  * @param lhs left-hand-side (first) parameter
1451  * @param rhs left-hand-side (first) parameter
1452  * @returns whether lhs is greater than rhs
1453  */
1454 static dbus_bool_t
1455 _dbus_type_reader_greater_than (const DBusTypeReader *lhs,
1456  const DBusTypeReader *rhs)
1457 {
1458  _dbus_assert (lhs->value_str == rhs->value_str);
1459 
1460  return lhs->value_pos > rhs->value_pos;
1461 }
1462 
1463 /*
1464  *
1465  *
1466  * DBusTypeWriter
1467  *
1468  *
1469  *
1470  */
1471 
1492 void
1494  int byte_order,
1495  DBusString *type_str,
1496  int type_pos,
1497  DBusString *value_str,
1498  int value_pos)
1499 {
1500  writer->byte_order = byte_order;
1501  writer->type_str = type_str;
1502  writer->type_pos = type_pos;
1503  writer->value_str = value_str;
1504  writer->value_pos = value_pos;
1506  writer->type_pos_is_expectation = FALSE;
1507  writer->enabled = TRUE;
1508 
1509 #if RECURSIVE_MARSHAL_WRITE_TRACE
1510  _dbus_verbose ("writer %p init remaining sig '%s'\n", writer,
1511  writer->type_str ?
1512  _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0) :
1513  "unknown");
1514 #endif
1515 }
1516 
1527 void
1529  int byte_order,
1530  DBusString *value_str,
1531  int value_pos)
1532 {
1533  _dbus_type_writer_init (writer, byte_order,
1534  NULL, 0, value_str, value_pos);
1535 }
1536 
1545 void
1547  DBusString *type_str,
1548  int type_pos)
1549 {
1550  if (writer->type_str == NULL) /* keeps us from using this as setter */
1551  {
1552  writer->type_str = type_str;
1553  writer->type_pos = type_pos;
1554  }
1555 }
1556 
1562 void
1564 {
1565  writer->type_str = NULL;
1566  writer->type_pos = -1;
1567 }
1568 
1583 void
1585  int byte_order,
1586  const DBusString *type_str,
1587  int type_pos,
1588  DBusString *value_str,
1589  int value_pos)
1590 {
1591  _dbus_type_writer_init (writer, byte_order,
1592  (DBusString*)type_str, type_pos,
1593  value_str, value_pos);
1594 
1595  writer->type_pos_is_expectation = TRUE;
1596 }
1597 
1598 static dbus_bool_t
1599 _dbus_type_writer_write_basic_no_typecode (DBusTypeWriter *writer,
1600  int type,
1601  const void *value)
1602 {
1603  if (writer->enabled)
1604  return _dbus_marshal_write_basic (writer->value_str,
1605  writer->value_pos,
1606  type,
1607  value,
1608  writer->byte_order,
1609  &writer->value_pos);
1610  else
1611  return TRUE;
1612 }
1613 
1614 /* If our parent is an array, things are a little bit complicated.
1615  *
1616  * The parent must have a complete element type, such as
1617  * "i" or "aai" or "(ii)" or "a(ii)". There can't be
1618  * unclosed parens, or an "a" with no following type.
1619  *
1620  * To recurse, the only allowed operation is to recurse into the
1621  * first type in the element type. So for "i" you can't recurse, for
1622  * "ai" you can recurse into the array, for "(ii)" you can recurse
1623  * into the struct.
1624  *
1625  * If you recurse into the array for "ai", then you must specify
1626  * "i" for the element type of the array you recurse into.
1627  *
1628  * While inside an array at any level, we need to avoid writing to
1629  * type_str, since the type only appears once for the whole array,
1630  * it does not appear for each array element.
1631  *
1632  * While inside an array type_pos points to the expected next
1633  * typecode, rather than the next place we could write a typecode.
1634  */
1635 static void
1636 writer_recurse_init_and_check (DBusTypeWriter *writer,
1637  int container_type,
1638  DBusTypeWriter *sub)
1639 {
1641  writer->byte_order,
1642  writer->type_str,
1643  writer->type_pos,
1644  writer->value_str,
1645  writer->value_pos);
1646 
1647  sub->container_type = container_type;
1648 
1649  if (writer->type_pos_is_expectation ||
1652  else
1654 
1655  sub->enabled = writer->enabled;
1656 
1657 #ifndef DBUS_DISABLE_CHECKS
1658  if (writer->type_pos_is_expectation && writer->type_str)
1659  {
1660  int expected;
1661 
1662  expected = _dbus_first_type_in_signature (writer->type_str, writer->type_pos);
1663 
1664  if (expected != sub->container_type)
1665  {
1666  if (expected != DBUS_TYPE_INVALID)
1667  _dbus_warn_check_failed ("Writing an element of type %s, but the expected type here is %s\n"
1668  "The overall signature expected here was '%s' and we are on byte %d of that signature.",
1670  _dbus_type_to_string (expected),
1671  _dbus_string_get_const_data (writer->type_str), writer->type_pos);
1672  else
1673  _dbus_warn_check_failed ("Writing an element of type %s, but no value is expected here\n"
1674  "The overall signature expected here was '%s' and we are on byte %d of that signature.",
1676  _dbus_string_get_const_data (writer->type_str), writer->type_pos);
1677 
1678  _dbus_assert_not_reached ("bad array element or variant content written");
1679  }
1680  }
1681 #endif /* DBUS_DISABLE_CHECKS */
1682 
1683 #if RECURSIVE_MARSHAL_WRITE_TRACE
1684  _dbus_verbose (" type writer %p recurse parent %s type_pos = %d value_pos = %d is_expectation = %d remaining sig '%s' enabled = %d\n",
1685  writer,
1687  writer->type_pos, writer->value_pos, writer->type_pos_is_expectation,
1688  writer->type_str ?
1689  _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0) :
1690  "unknown",
1691  writer->enabled);
1692  _dbus_verbose (" type writer %p recurse sub %s type_pos = %d value_pos = %d is_expectation = %d enabled = %d\n",
1693  sub,
1695  sub->type_pos, sub->value_pos,
1697  sub->enabled);
1698 #endif
1699 }
1700 
1701 static dbus_bool_t
1702 write_or_verify_typecode (DBusTypeWriter *writer,
1703  int typecode)
1704 {
1705  /* A subwriter inside an array or variant will have type_pos
1706  * pointing to the expected typecode; a writer not inside an array
1707  * or variant has type_pos pointing to the next place to insert a
1708  * typecode.
1709  */
1710 #if RECURSIVE_MARSHAL_WRITE_TRACE
1711  _dbus_verbose (" type writer %p write_or_verify start type_pos = %d remaining sig '%s' enabled = %d\n",
1712  writer, writer->type_pos,
1713  writer->type_str ?
1714  _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0) :
1715  "unknown",
1716  writer->enabled);
1717 #endif
1718 
1719  if (writer->type_str == NULL)
1720  return TRUE;
1721 
1722  if (writer->type_pos_is_expectation)
1723  {
1724 #ifndef DBUS_DISABLE_CHECKS
1725  {
1726  int expected;
1727 
1728  expected = _dbus_string_get_byte (writer->type_str, writer->type_pos);
1729 
1730  if (expected != typecode)
1731  {
1732  if (expected != DBUS_TYPE_INVALID)
1733  _dbus_warn_check_failed ("Array or variant type requires that type %s be written, but %s was written.\n"
1734  "The overall signature expected here was '%s' and we are on byte %d of that signature.",
1735  _dbus_type_to_string (expected), _dbus_type_to_string (typecode),
1736  _dbus_string_get_const_data (writer->type_str), writer->type_pos);
1737  else
1738  _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"
1739  "The overall signature expected here was '%s' and we are on byte %d of that signature.",
1740  _dbus_type_to_string (typecode),
1741  _dbus_string_get_const_data (writer->type_str), writer->type_pos);
1742  _dbus_assert_not_reached ("bad type inserted somewhere inside an array or variant");
1743  }
1744  }
1745 #endif /* DBUS_DISABLE_CHECKS */
1746 
1747  /* if immediately inside an array we'd always be appending an element,
1748  * so the expected type doesn't change; if inside a struct or something
1749  * below an array, we need to move through said struct or something.
1750  */
1751  if (writer->container_type != DBUS_TYPE_ARRAY)
1752  writer->type_pos += 1;
1753  }
1754  else
1755  {
1756  if (!_dbus_string_insert_byte (writer->type_str,
1757  writer->type_pos,
1758  typecode))
1759  return FALSE;
1760 
1761  writer->type_pos += 1;
1762  }
1763 
1764 #if RECURSIVE_MARSHAL_WRITE_TRACE
1765  _dbus_verbose (" type writer %p write_or_verify end type_pos = %d remaining sig '%s'\n",
1766  writer, writer->type_pos,
1767  _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0));
1768 #endif
1769 
1770  return TRUE;
1771 }
1772 
1773 static dbus_bool_t
1774 writer_recurse_struct_or_dict_entry (DBusTypeWriter *writer,
1775  int begin_char,
1776  const DBusString *contained_type,
1777  int contained_type_start,
1778  int contained_type_len,
1779  DBusTypeWriter *sub)
1780 {
1781  /* FIXME right now contained_type is ignored; we could probably
1782  * almost trivially fix the code so if it's present we
1783  * write it out and then set type_pos_is_expectation
1784  */
1785 
1786  /* Ensure that we'll be able to add alignment padding and the typecode */
1787  if (writer->enabled)
1788  {
1789  if (!_dbus_string_alloc_space (sub->value_str, 8))
1790  return FALSE;
1791  }
1792 
1793  if (!write_or_verify_typecode (sub, begin_char))
1794  _dbus_assert_not_reached ("failed to insert struct typecode after prealloc");
1795 
1796  if (writer->enabled)
1797  {
1799  sub->value_pos,
1800  _DBUS_ALIGN_VALUE (sub->value_pos, 8) - sub->value_pos,
1801  '\0'))
1802  _dbus_assert_not_reached ("should not have failed to insert alignment padding for struct");
1803  sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 8);
1804  }
1805 
1806  return TRUE;
1807 }
1808 
1809 
1810 static dbus_bool_t
1811 writer_recurse_array (DBusTypeWriter *writer,
1812  const DBusString *contained_type,
1813  int contained_type_start,
1814  int contained_type_len,
1815  DBusTypeWriter *sub,
1816  dbus_bool_t is_array_append)
1817 {
1818  dbus_uint32_t value = 0;
1819  int alignment;
1820  int aligned;
1821 
1822 #ifndef DBUS_DISABLE_CHECKS
1823  if (writer->container_type == DBUS_TYPE_ARRAY &&
1824  writer->type_str)
1825  {
1826  if (!_dbus_string_equal_substring (contained_type,
1827  contained_type_start,
1828  contained_type_len,
1829  writer->type_str,
1830  writer->u.array.element_type_pos + 1))
1831  {
1832  _dbus_warn_check_failed ("Writing an array of '%s' but this is incompatible with the expected type of elements in the parent array",
1833  _dbus_string_get_const_data_len (contained_type,
1834  contained_type_start,
1835  contained_type_len));
1836  _dbus_assert_not_reached ("incompatible type for child array");
1837  }
1838  }
1839 #endif /* DBUS_DISABLE_CHECKS */
1840 
1841  if (writer->enabled && !is_array_append)
1842  {
1843  /* 3 pad + 4 bytes for the array length, and 4 bytes possible padding
1844  * before array values
1845  */
1846  if (!_dbus_string_alloc_space (sub->value_str, 3 + 4 + 4))
1847  return FALSE;
1848  }
1849 
1850  if (writer->type_str != NULL)
1851  {
1852  sub->type_pos += 1; /* move to point to the element type, since type_pos
1853  * should be the expected type for further writes
1854  */
1855  sub->u.array.element_type_pos = sub->type_pos;
1856  }
1857 
1858  if (!writer->type_pos_is_expectation)
1859  {
1860  /* sub is a toplevel/outermost array so we need to write the type data */
1861 
1862  /* alloc space for array typecode, element signature */
1863  if (!_dbus_string_alloc_space (writer->type_str, 1 + contained_type_len))
1864  return FALSE;
1865 
1866  if (!_dbus_string_insert_byte (writer->type_str,
1867  writer->type_pos,
1868  DBUS_TYPE_ARRAY))
1869  _dbus_assert_not_reached ("failed to insert array typecode after prealloc");
1870 
1871  if (!_dbus_string_copy_len (contained_type,
1872  contained_type_start, contained_type_len,
1873  sub->type_str,
1874  sub->u.array.element_type_pos))
1875  _dbus_assert_not_reached ("should not have failed to insert array element typecodes");
1876  }
1877 
1878  if (writer->type_str != NULL)
1879  {
1880  /* If the parent is an array, we hold type_pos pointing at the array element type;
1881  * otherwise advance it to reflect the array value we just recursed into
1882  */
1883  if (writer->container_type != DBUS_TYPE_ARRAY)
1884  writer->type_pos += 1 + contained_type_len;
1885  else
1886  _dbus_assert (writer->type_pos_is_expectation); /* because it's an array */
1887  }
1888 
1889  if (writer->enabled)
1890  {
1891  /* Write (or jump over, if is_array_append) the length */
1892  sub->u.array.len_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 4);
1893 
1894  if (is_array_append)
1895  {
1896  sub->value_pos += 4;
1897  }
1898  else
1899  {
1900  if (!_dbus_type_writer_write_basic_no_typecode (sub, DBUS_TYPE_UINT32,
1901  &value))
1902  _dbus_assert_not_reached ("should not have failed to insert array len");
1903  }
1904 
1905  _dbus_assert (sub->u.array.len_pos == sub->value_pos - 4);
1906 
1907  /* Write alignment padding for array elements
1908  * Note that we write the padding *even for empty arrays*
1909  * to avoid wonky special cases
1910  */
1911  alignment = element_type_get_alignment (contained_type, contained_type_start);
1912 
1913  aligned = _DBUS_ALIGN_VALUE (sub->value_pos, alignment);
1914  if (aligned != sub->value_pos)
1915  {
1916  if (!is_array_append)
1917  {
1919  sub->value_pos,
1920  aligned - sub->value_pos,
1921  '\0'))
1922  _dbus_assert_not_reached ("should not have failed to insert alignment padding");
1923  }
1924 
1925  sub->value_pos = aligned;
1926  }
1927 
1928  sub->u.array.start_pos = sub->value_pos;
1929 
1930  if (is_array_append)
1931  {
1932  dbus_uint32_t len;
1933 
1934  _dbus_assert (_DBUS_ALIGN_VALUE (sub->u.array.len_pos, 4) ==
1935  (unsigned) sub->u.array.len_pos);
1936  len = _dbus_unpack_uint32 (sub->byte_order,
1937  _dbus_string_get_const_udata_len (sub->value_str,
1938  sub->u.array.len_pos,
1939  4));
1940 
1941  sub->value_pos += len;
1942  }
1943  }
1944  else
1945  {
1946  /* not enabled, so we won't write the len_pos; set it to -1 to so indicate */
1947  sub->u.array.len_pos = -1;
1948  sub->u.array.start_pos = sub->value_pos;
1949  }
1950 
1951  _dbus_assert (sub->u.array.len_pos < sub->u.array.start_pos);
1952  _dbus_assert (is_array_append || sub->u.array.start_pos == sub->value_pos);
1953 
1954 #if RECURSIVE_MARSHAL_WRITE_TRACE
1955  _dbus_verbose (" type writer %p recurse array done remaining sig '%s' array start_pos = %d len_pos = %d value_pos = %d\n", sub,
1956  sub->type_str ?
1957  _dbus_string_get_const_data_len (sub->type_str, sub->type_pos, 0) :
1958  "unknown",
1959  sub->u.array.start_pos, sub->u.array.len_pos, sub->value_pos);
1960 #endif
1961 
1962  return TRUE;
1963 }
1964 
1965 /* Variant value will normally have:
1966  * 1 byte signature length not including nul
1967  * signature typecodes (nul terminated)
1968  * padding to alignment of contained type
1969  * body according to signature
1970  *
1971  * The signature string can only have a single type
1972  * in it but that type may be complex/recursive.
1973  *
1974  * So a typical variant type with the integer 3 will have these
1975  * octets:
1976  * 0x1 'i' '\0' [1 byte padding to alignment boundary] 0x0 0x0 0x0 0x3
1977  *
1978  * The main world of hurt for writing out a variant is that the type
1979  * string is the same string as the value string. Which means
1980  * inserting to the type string will move the value_pos; and it means
1981  * that inserting to the type string could break type alignment.
1982  */
1983 static dbus_bool_t
1984 writer_recurse_variant (DBusTypeWriter *writer,
1985  const DBusString *contained_type,
1986  int contained_type_start,
1987  int contained_type_len,
1988  DBusTypeWriter *sub)
1989 {
1990  int contained_alignment;
1991 
1992  if (writer->enabled)
1993  {
1994  /* Allocate space for the worst case, which is 1 byte sig
1995  * length, nul byte at end of sig, and 7 bytes padding to
1996  * 8-boundary.
1997  */
1998  if (!_dbus_string_alloc_space (sub->value_str, contained_type_len + 9))
1999  return FALSE;
2000  }
2001 
2002  /* write VARIANT typecode to the parent's type string */
2003  if (!write_or_verify_typecode (writer, DBUS_TYPE_VARIANT))
2004  return FALSE;
2005 
2006  /* If not enabled, mark that we have no type_str anymore ... */
2007 
2008  if (!writer->enabled)
2009  {
2010  sub->type_str = NULL;
2011  sub->type_pos = -1;
2012 
2013  return TRUE;
2014  }
2015 
2016  /* If we're enabled then continue ... */
2017 
2019  sub->value_pos,
2020  contained_type_len))
2021  _dbus_assert_not_reached ("should not have failed to insert variant type sig len");
2022 
2023  sub->value_pos += 1;
2024 
2025  /* Here we switch over to the expected type sig we're about to write */
2026  sub->type_str = sub->value_str;
2027  sub->type_pos = sub->value_pos;
2028 
2029  if (!_dbus_string_copy_len (contained_type, contained_type_start, contained_type_len,
2030  sub->value_str, sub->value_pos))
2031  _dbus_assert_not_reached ("should not have failed to insert variant type sig");
2032 
2033  sub->value_pos += contained_type_len;
2034 
2036  sub->value_pos,
2038  _dbus_assert_not_reached ("should not have failed to insert variant type nul termination");
2039 
2040  sub->value_pos += 1;
2041 
2042  contained_alignment = _dbus_type_get_alignment (_dbus_first_type_in_signature (contained_type, contained_type_start));
2043 
2045  sub->value_pos,
2046  _DBUS_ALIGN_VALUE (sub->value_pos, contained_alignment) - sub->value_pos,
2047  '\0'))
2048  _dbus_assert_not_reached ("should not have failed to insert alignment padding for variant body");
2049  sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, contained_alignment);
2050 
2051  return TRUE;
2052 }
2053 
2054 static dbus_bool_t
2055 _dbus_type_writer_recurse_contained_len (DBusTypeWriter *writer,
2056  int container_type,
2057  const DBusString *contained_type,
2058  int contained_type_start,
2059  int contained_type_len,
2060  DBusTypeWriter *sub,
2061  dbus_bool_t is_array_append)
2062 {
2063  writer_recurse_init_and_check (writer, container_type, sub);
2064 
2065  switch (container_type)
2066  {
2067  case DBUS_TYPE_STRUCT:
2068  return writer_recurse_struct_or_dict_entry (writer,
2070  contained_type,
2071  contained_type_start, contained_type_len,
2072  sub);
2073  break;
2074  case DBUS_TYPE_DICT_ENTRY:
2075  return writer_recurse_struct_or_dict_entry (writer,
2077  contained_type,
2078  contained_type_start, contained_type_len,
2079  sub);
2080  break;
2081  case DBUS_TYPE_ARRAY:
2082  return writer_recurse_array (writer,
2083  contained_type, contained_type_start, contained_type_len,
2084  sub, is_array_append);
2085  break;
2086  case DBUS_TYPE_VARIANT:
2087  return writer_recurse_variant (writer,
2088  contained_type, contained_type_start, contained_type_len,
2089  sub);
2090  break;
2091  default:
2092  _dbus_assert_not_reached ("tried to recurse into type that doesn't support that");
2093  return FALSE;
2094  break;
2095  }
2096 }
2097 
2110  int container_type,
2111  const DBusString *contained_type,
2112  int contained_type_start,
2113  DBusTypeWriter *sub)
2114 {
2115  int contained_type_len;
2116 
2117  if (contained_type)
2118  contained_type_len = find_len_of_complete_type (contained_type, contained_type_start);
2119  else
2120  contained_type_len = 0;
2121 
2122  return _dbus_type_writer_recurse_contained_len (writer, container_type,
2123  contained_type,
2124  contained_type_start,
2125  contained_type_len,
2126  sub,
2127  FALSE);
2128 }
2129 
2144  const DBusString *contained_type,
2145  int contained_type_start,
2146  DBusTypeWriter *sub)
2147 {
2148  int contained_type_len;
2149 
2150  if (contained_type)
2151  contained_type_len = find_len_of_complete_type (contained_type, contained_type_start);
2152  else
2153  contained_type_len = 0;
2154 
2155  return _dbus_type_writer_recurse_contained_len (writer, DBUS_TYPE_ARRAY,
2156  contained_type,
2157  contained_type_start,
2158  contained_type_len,
2159  sub,
2160  TRUE);
2161 }
2162 
2163 static int
2164 writer_get_array_len (DBusTypeWriter *writer)
2165 {
2167  return writer->value_pos - writer->u.array.start_pos;
2168 }
2169 
2180  DBusTypeWriter *sub)
2181 {
2182  /* type_pos_is_expectation never gets unset once set, or we'd get all hosed */
2185 
2186 #if RECURSIVE_MARSHAL_WRITE_TRACE
2187  _dbus_verbose (" type writer %p unrecurse type_pos = %d value_pos = %d is_expectation = %d container_type = %s\n",
2188  writer, writer->type_pos, writer->value_pos, writer->type_pos_is_expectation,
2190  _dbus_verbose (" type writer %p unrecurse sub type_pos = %d value_pos = %d is_expectation = %d container_type = %s\n",
2191  sub, sub->type_pos, sub->value_pos,
2194 #endif
2195 
2196  if (sub->container_type == DBUS_TYPE_STRUCT)
2197  {
2198  if (!write_or_verify_typecode (sub, DBUS_STRUCT_END_CHAR))
2199  return FALSE;
2200  }
2201  else if (sub->container_type == DBUS_TYPE_DICT_ENTRY)
2202  {
2203  if (!write_or_verify_typecode (sub, DBUS_DICT_ENTRY_END_CHAR))
2204  return FALSE;
2205  }
2206  else if (sub->container_type == DBUS_TYPE_ARRAY)
2207  {
2208  if (sub->u.array.len_pos >= 0) /* len_pos == -1 if we weren't enabled when we passed it */
2209  {
2210  dbus_uint32_t len;
2211 
2212  /* Set the array length */
2213  len = writer_get_array_len (sub);
2215  sub->u.array.len_pos,
2216  len,
2217  sub->byte_order);
2218 #if RECURSIVE_MARSHAL_WRITE_TRACE
2219  _dbus_verbose (" filled in sub array len to %u at len_pos %d\n",
2220  len, sub->u.array.len_pos);
2221 #endif
2222  }
2223 #if RECURSIVE_MARSHAL_WRITE_TRACE
2224  else
2225  {
2226  _dbus_verbose (" not filling in sub array len because we were disabled when we passed the len\n");
2227  }
2228 #endif
2229  }
2230 
2231  /* Now get type_pos right for the parent writer. Here are the cases:
2232  *
2233  * Cases !writer->type_pos_is_expectation:
2234  * (in these cases we want to update to the new insertion point)
2235  *
2236  * - if we recursed into a STRUCT then we didn't know in advance
2237  * what the types in the struct would be; so we have to fill in
2238  * that information now.
2239  * writer->type_pos = sub->type_pos
2240  *
2241  * - if we recursed into anything else, we knew the full array
2242  * type, or knew the single typecode marking VARIANT, so
2243  * writer->type_pos is already correct.
2244  * writer->type_pos should remain as-is
2245  *
2246  * - note that the parent is never an ARRAY or VARIANT, if it were
2247  * then type_pos_is_expectation would be TRUE. The parent
2248  * is thus known to be a toplevel or STRUCT.
2249  *
2250  * Cases where writer->type_pos_is_expectation:
2251  * (in these cases we want to update to next expected type to write)
2252  *
2253  * - we recursed from STRUCT into STRUCT and we didn't increment
2254  * type_pos in the parent just to stay consistent with the
2255  * !writer->type_pos_is_expectation case (though we could
2256  * special-case this in recurse_struct instead if we wanted)
2257  * writer->type_pos = sub->type_pos
2258  *
2259  * - we recursed from STRUCT into ARRAY or VARIANT and type_pos
2260  * for parent should have been incremented already
2261  * writer->type_pos should remain as-is
2262  *
2263  * - we recursed from ARRAY into a sub-element, so type_pos in the
2264  * parent is the element type and should remain the element type
2265  * for the benefit of the next child element
2266  * writer->type_pos should remain as-is
2267  *
2268  * - we recursed from VARIANT into its value, so type_pos in the
2269  * parent makes no difference since there's only one value
2270  * and we just finished writing it and won't use type_pos again
2271  * writer->type_pos should remain as-is
2272  *
2273  *
2274  * For all these, DICT_ENTRY is the same as STRUCT
2275  */
2276  if (writer->type_str != NULL)
2277  {
2278  if ((sub->container_type == DBUS_TYPE_STRUCT ||
2280  (writer->container_type == DBUS_TYPE_STRUCT ||
2281  writer->container_type == DBUS_TYPE_DICT_ENTRY ||
2282  writer->container_type == DBUS_TYPE_INVALID))
2283  {
2284  /* Advance the parent to the next struct field */
2285  writer->type_pos = sub->type_pos;
2286  }
2287  }
2288 
2289  writer->value_pos = sub->value_pos;
2290 
2291 #if RECURSIVE_MARSHAL_WRITE_TRACE
2292  _dbus_verbose (" type writer %p unrecursed type_pos = %d value_pos = %d remaining sig '%s'\n",
2293  writer, writer->type_pos, writer->value_pos,
2294  writer->type_str ?
2295  _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0) :
2296  "unknown");
2297 #endif
2298 
2299  return TRUE;
2300 }
2301 
2312  int type,
2313  const void *value)
2314 {
2315  dbus_bool_t retval;
2316 
2317  /* First ensure that our type realloc will succeed */
2318  if (!writer->type_pos_is_expectation && writer->type_str != NULL)
2319  {
2320  if (!_dbus_string_alloc_space (writer->type_str, 1))
2321  return FALSE;
2322  }
2323 
2324  retval = FALSE;
2325 
2326  if (!_dbus_type_writer_write_basic_no_typecode (writer, type, value))
2327  goto out;
2328 
2329  if (!write_or_verify_typecode (writer, type))
2330  _dbus_assert_not_reached ("failed to write typecode after prealloc");
2331 
2332  retval = TRUE;
2333 
2334  out:
2335 #if RECURSIVE_MARSHAL_WRITE_TRACE
2336  _dbus_verbose (" type writer %p basic type_pos = %d value_pos = %d is_expectation = %d enabled = %d\n",
2337  writer, writer->type_pos, writer->value_pos, writer->type_pos_is_expectation,
2338  writer->enabled);
2339 #endif
2340 
2341  return retval;
2342 }
2343 
2360  int element_type,
2361  const void *value,
2362  int n_elements)
2363 {
2365  _dbus_assert (dbus_type_is_fixed (element_type));
2367  _dbus_assert (n_elements >= 0);
2368 
2369 #if RECURSIVE_MARSHAL_WRITE_TRACE
2370  _dbus_verbose (" type writer %p entering fixed multi type_pos = %d value_pos = %d n_elements %d\n",
2371  writer, writer->type_pos, writer->value_pos, n_elements);
2372 #endif
2373 
2374  if (!write_or_verify_typecode (writer, element_type))
2375  _dbus_assert_not_reached ("OOM should not happen if only verifying typecode");
2376 
2377  if (writer->enabled)
2378  {
2380  writer->value_pos,
2381  element_type,
2382  value,
2383  n_elements,
2384  writer->byte_order,
2385  &writer->value_pos))
2386  return FALSE;
2387  }
2388 
2389 #if RECURSIVE_MARSHAL_WRITE_TRACE
2390  _dbus_verbose (" type writer %p fixed multi written new type_pos = %d new value_pos = %d n_elements %d\n",
2391  writer, writer->type_pos, writer->value_pos, n_elements);
2392 #endif
2393 
2394  return TRUE;
2395 }
2396 
2397 static void
2398 enable_if_after (DBusTypeWriter *writer,
2399  DBusTypeReader *reader,
2400  const DBusTypeReader *start_after)
2401 {
2402  if (start_after)
2403  {
2404  if (!writer->enabled && _dbus_type_reader_greater_than (reader, start_after))
2405  {
2406  _dbus_type_writer_set_enabled (writer, TRUE);
2407 #if RECURSIVE_MARSHAL_WRITE_TRACE
2408  _dbus_verbose ("ENABLING writer %p at %d because reader at value_pos %d is after reader at value_pos %d\n",
2409  writer, writer->value_pos, reader->value_pos, start_after->value_pos);
2410 #endif
2411  }
2412 
2413  _dbus_assert ((!writer->enabled && !_dbus_type_reader_greater_than (reader, start_after)) ||
2414  (writer->enabled && _dbus_type_reader_greater_than (reader, start_after)));
2415  }
2416 }
2417 
2418 static dbus_bool_t
2419 append_fixup (DBusList **fixups,
2420  const DBusArrayLenFixup *fixup)
2421 {
2422  DBusArrayLenFixup *f;
2423 
2424  f = dbus_new (DBusArrayLenFixup, 1);
2425  if (f == NULL)
2426  return FALSE;
2427 
2428  *f = *fixup;
2429 
2430  if (!_dbus_list_append (fixups, f))
2431  {
2432  dbus_free (f);
2433  return FALSE;
2434  }
2435 
2437  _dbus_assert (f->new_len == fixup->new_len);
2438 
2439  return TRUE;
2440 }
2441 
2442 /* This loop is trivial if you ignore all the start_after nonsense,
2443  * so if you're trying to figure it out, start by ignoring that
2444  */
2445 static dbus_bool_t
2446 writer_write_reader_helper (DBusTypeWriter *writer,
2447  DBusTypeReader *reader,
2448  const DBusTypeReader *start_after,
2449  int start_after_new_pos,
2450  int start_after_new_len,
2451  DBusList **fixups,
2452  dbus_bool_t inside_start_after)
2453 {
2454  int current_type;
2455 
2456  while ((current_type = _dbus_type_reader_get_current_type (reader)) != DBUS_TYPE_INVALID)
2457  {
2458  if (dbus_type_is_container (current_type))
2459  {
2460  DBusTypeReader subreader;
2461  DBusTypeWriter subwriter;
2462  const DBusString *sig_str;
2463  int sig_start;
2464  int sig_len;
2465  dbus_bool_t enabled_at_recurse;
2466  dbus_bool_t past_start_after;
2467  int reader_array_len_pos;
2468  int reader_array_start_pos;
2469  dbus_bool_t this_is_start_after;
2470 
2471  /* type_pos is checked since e.g. in a struct the struct
2472  * and its first field have the same value_pos.
2473  * type_str will differ in reader/start_after for variants
2474  * where type_str is inside the value_str
2475  */
2476  if (!inside_start_after && start_after &&
2477  reader->value_pos == start_after->value_pos &&
2478  reader->type_str == start_after->type_str &&
2479  reader->type_pos == start_after->type_pos)
2480  this_is_start_after = TRUE;
2481  else
2482  this_is_start_after = FALSE;
2483 
2484  _dbus_type_reader_recurse (reader, &subreader);
2485 
2486  if (current_type == DBUS_TYPE_ARRAY)
2487  {
2488  reader_array_len_pos = ARRAY_READER_LEN_POS (&subreader);
2489  reader_array_start_pos = subreader.u.array.start_pos;
2490  }
2491  else
2492  {
2493  /* quiet gcc */
2494  reader_array_len_pos = -1;
2495  reader_array_start_pos = -1;
2496  }
2497 
2498  _dbus_type_reader_get_signature (&subreader, &sig_str,
2499  &sig_start, &sig_len);
2500 
2501 #if RECURSIVE_MARSHAL_WRITE_TRACE
2502  _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",
2503  _dbus_type_to_string (current_type),
2504  reader->value_pos,
2505  subreader.value_pos,
2506  writer->value_pos,
2507  start_after ? start_after->value_pos : -1,
2508  _dbus_string_get_length (writer->value_str),
2509  inside_start_after, this_is_start_after);
2510 #endif
2511 
2512  if (!inside_start_after && !this_is_start_after)
2513  enable_if_after (writer, &subreader, start_after);
2514  enabled_at_recurse = writer->enabled;
2515  if (!_dbus_type_writer_recurse_contained_len (writer, current_type,
2516  sig_str, sig_start, sig_len,
2517  &subwriter, FALSE))
2518  goto oom;
2519 
2520 #if RECURSIVE_MARSHAL_WRITE_TRACE
2521  _dbus_verbose ("recursed into subwriter at %d write target len %d\n",
2522  subwriter.value_pos,
2523  _dbus_string_get_length (subwriter.value_str));
2524 #endif
2525 
2526  if (!writer_write_reader_helper (&subwriter, &subreader, start_after,
2527  start_after_new_pos, start_after_new_len,
2528  fixups,
2529  inside_start_after ||
2530  this_is_start_after))
2531  goto oom;
2532 
2533 #if RECURSIVE_MARSHAL_WRITE_TRACE
2534  _dbus_verbose ("about to unrecurse from %s subreader at %d writer at %d subwriter at %d write target len %d\n",
2535  _dbus_type_to_string (current_type),
2536  subreader.value_pos,
2537  writer->value_pos,
2538  subwriter.value_pos,
2539  _dbus_string_get_length (writer->value_str));
2540 #endif
2541 
2542  if (!inside_start_after && !this_is_start_after)
2543  enable_if_after (writer, &subreader, start_after);
2544  past_start_after = writer->enabled;
2545  if (!_dbus_type_writer_unrecurse (writer, &subwriter))
2546  goto oom;
2547 
2548  /* If we weren't enabled when we recursed, we didn't
2549  * write an array len; if we passed start_after
2550  * somewhere inside the array, then we need to generate
2551  * a fixup.
2552  */
2553  if (start_after != NULL &&
2554  !enabled_at_recurse && past_start_after &&
2555  current_type == DBUS_TYPE_ARRAY &&
2556  fixups != NULL)
2557  {
2558  DBusArrayLenFixup fixup;
2559  int bytes_written_after_start_after;
2560  int bytes_before_start_after;
2561  int old_len;
2562 
2563  /* this subwriter access is moderately unkosher since we
2564  * already unrecursed, but it works as long as unrecurse
2565  * doesn't break us on purpose
2566  */
2567  bytes_written_after_start_after = writer_get_array_len (&subwriter);
2568 
2569  bytes_before_start_after =
2570  start_after->value_pos - reader_array_start_pos;
2571 
2572  fixup.len_pos_in_reader = reader_array_len_pos;
2573  fixup.new_len =
2574  bytes_before_start_after +
2575  start_after_new_len +
2576  bytes_written_after_start_after;
2577 
2578  _dbus_assert (_DBUS_ALIGN_VALUE (fixup.len_pos_in_reader, 4) ==
2579  (unsigned) fixup.len_pos_in_reader);
2580 
2581  old_len = _dbus_unpack_uint32 (reader->byte_order,
2582  _dbus_string_get_const_udata_len (reader->value_str,
2583  fixup.len_pos_in_reader, 4));
2584 
2585  if (old_len != fixup.new_len && !append_fixup (fixups, &fixup))
2586  goto oom;
2587 
2588 #if RECURSIVE_MARSHAL_WRITE_TRACE
2589  _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",
2590  fixup.len_pos_in_reader,
2591  fixup.new_len,
2592  reader_array_start_pos,
2593  start_after->value_pos,
2594  bytes_before_start_after,
2595  start_after_new_len,
2596  bytes_written_after_start_after);
2597 #endif
2598  }
2599  }
2600  else
2601  {
2602  DBusBasicValue val;
2603 
2604  _dbus_assert (dbus_type_is_basic (current_type));
2605 
2606 #if RECURSIVE_MARSHAL_WRITE_TRACE
2607  _dbus_verbose ("Reading basic value %s at %d\n",
2608  _dbus_type_to_string (current_type),
2609  reader->value_pos);
2610 #endif
2611 
2612  _dbus_type_reader_read_basic (reader, &val);
2613 
2614 #if RECURSIVE_MARSHAL_WRITE_TRACE
2615  _dbus_verbose ("Writing basic value %s at %d write target len %d inside_start_after = %d\n",
2616  _dbus_type_to_string (current_type),
2617  writer->value_pos,
2618  _dbus_string_get_length (writer->value_str),
2619  inside_start_after);
2620 #endif
2621  if (!inside_start_after)
2622  enable_if_after (writer, reader, start_after);
2623  if (!_dbus_type_writer_write_basic (writer, current_type, &val))
2624  goto oom;
2625 #if RECURSIVE_MARSHAL_WRITE_TRACE
2626  _dbus_verbose ("Wrote basic value %s, new value_pos %d write target len %d\n",
2627  _dbus_type_to_string (current_type),
2628  writer->value_pos,
2629  _dbus_string_get_length (writer->value_str));
2630 #endif
2631  }
2632 
2633  _dbus_type_reader_next (reader);
2634  }
2635 
2636  return TRUE;
2637 
2638  oom:
2639  if (fixups)
2640  apply_and_free_fixups (fixups, NULL); /* NULL for reader to apply to */
2641 
2642  return FALSE;
2643 }
2644 
2645 /*
2646  * Iterate through all values in the given reader, writing a copy of
2647  * each value to the writer. The reader will be moved forward to its
2648  * end position.
2649  *
2650  * If a reader start_after is provided, it should be a reader for the
2651  * same data as the reader to be written. Only values occurring after
2652  * the value pointed to by start_after will be written to the writer.
2653  *
2654  * If start_after is provided, then the copy of the reader will be
2655  * partial. This means that array lengths will not have been copied.
2656  * The assumption is that you wrote a new version of the value at
2657  * start_after to the writer. You have to pass in the start position
2658  * and length of the new value. (If you are deleting the value
2659  * at start_after, pass in 0 for the length.)
2660  *
2661  * If the fixups parameter is non-#NULL, then any array length that
2662  * was read but not written due to start_after will be provided
2663  * as a #DBusArrayLenFixup. The fixup contains the position of the
2664  * array length in the source data, and the correct array length
2665  * assuming you combine the source data before start_after with
2666  * the written data at start_after and beyond.
2667  *
2668  * @param writer the writer to copy to
2669  * @param reader the reader to copy from
2670  * @param start_after #NULL or a reader showing where to start
2671  * @param start_after_new_pos the position of start_after equivalent in the target data
2672  * @param start_after_new_len the length of start_after equivalent in the target data
2673  * @param fixups list to append #DBusArrayLenFixup if the write was partial
2674  * @returns #FALSE if no memory
2675  */
2676 static dbus_bool_t
2677 _dbus_type_writer_write_reader_partial (DBusTypeWriter *writer,
2678  DBusTypeReader *reader,
2679  const DBusTypeReader *start_after,
2680  int start_after_new_pos,
2681  int start_after_new_len,
2682  DBusList **fixups)
2683 {
2684  DBusTypeWriter orig;
2685  int orig_type_len;
2686  int orig_value_len;
2687  int new_bytes;
2688  int orig_enabled;
2689 
2690  orig = *writer;
2691  orig_type_len = _dbus_string_get_length (writer->type_str);
2692  orig_value_len = _dbus_string_get_length (writer->value_str);
2693  orig_enabled = writer->enabled;
2694 
2695  if (start_after)
2696  _dbus_type_writer_set_enabled (writer, FALSE);
2697 
2698  if (!writer_write_reader_helper (writer, reader, start_after,
2699  start_after_new_pos,
2700  start_after_new_len,
2701  fixups, FALSE))
2702  goto oom;
2703 
2704  _dbus_type_writer_set_enabled (writer, orig_enabled);
2705  return TRUE;
2706 
2707  oom:
2708  if (!writer->type_pos_is_expectation)
2709  {
2710  new_bytes = _dbus_string_get_length (writer->type_str) - orig_type_len;
2711  _dbus_string_delete (writer->type_str, orig.type_pos, new_bytes);
2712  }
2713  new_bytes = _dbus_string_get_length (writer->value_str) - orig_value_len;
2714  _dbus_string_delete (writer->value_str, orig.value_pos, new_bytes);
2715 
2716  *writer = orig;
2717 
2718  return FALSE;
2719 }
2720 
2732  DBusTypeReader *reader)
2733 {
2734  return _dbus_type_writer_write_reader_partial (writer, reader, NULL, 0, 0, NULL);
2735 }
2736 
2737 /*
2738  * If disabled, a writer can still be iterated forward and recursed/unrecursed
2739  * but won't write any values. Types will still be written unless the
2740  * writer is a "values only" writer, because the writer needs access to
2741  * a valid signature to be able to iterate.
2742  *
2743  * @param writer the type writer
2744  * @param enabled #TRUE if values should be written
2745  */
2746 static void
2747 _dbus_type_writer_set_enabled (DBusTypeWriter *writer,
2748  dbus_bool_t enabled)
2749 {
2750  writer->enabled = enabled != FALSE;
2751 }
2752  /* end of DBusMarshal group */
2754 
2755 /* tests in dbus-marshal-recursive-util.c */
DBUS_TYPE_ARRAY
#define DBUS_TYPE_ARRAY
Type code marking a D-Bus array type.
Definition: dbus-protocol.h:120
_dbus_type_signature_next
void _dbus_type_signature_next(const char *type_str, int *type_pos)
Skips to the next "complete" type inside a type signature.
Definition: dbus-marshal-recursive.c:341
_dbus_type_reader_next
dbus_bool_t _dbus_type_reader_next(DBusTypeReader *reader)
Skip to the next value on this "level".
Definition: dbus-marshal-recursive.c:1054
DBUS_TYPE_INVALID
#define DBUS_TYPE_INVALID
Type code that is never equal to a legitimate type code.
Definition: dbus-protocol.h:60
DBusTypeWriter::value_pos
int value_pos
next position to write
Definition: dbus-marshal-recursive.h:77
DBusTypeReader::type_pos
int type_pos
current position in signature
Definition: dbus-marshal-recursive.h:48
_dbus_verbose_bytes_of_string
DBUS_PRIVATE_EXPORT void _dbus_verbose_bytes_of_string(const DBusString *str, int start, int len)
Dump the given part of the string to verbose log.
Definition: dbus-marshal-basic.c:1421
_dbus_type_writer_init_values_only
void _dbus_type_writer_init_values_only(DBusTypeWriter *writer, int byte_order, const DBusString *type_str, int type_pos, DBusString *value_str, int value_pos)
Like _dbus_type_writer_init(), except the type string passed in should correspond to an existing sign...
Definition: dbus-marshal-recursive.c:1584
ReplacementBlock::padding
int padding
How much of the replacement block is padding.
Definition: dbus-marshal-recursive.c:1138
DBusTypeWriter::u
union DBusTypeWriter::@3 u
class-specific data
DBusTypeWriter::type_pos_is_expectation
dbus_uint32_t type_pos_is_expectation
type_pos can be either an insertion point for or an expected next type
Definition: dbus-marshal-recursive.h:70
_dbus_string_free
void _dbus_string_free(DBusString *str)
Frees a string created by _dbus_string_init(), and fills it with the same contents as #_DBUS_STRING_I...
Definition: dbus-string.c:271
DBusTypeReader::type_str
const DBusString * type_str
string containing signature of block
Definition: dbus-marshal-recursive.h:47
_dbus_marshal_skip_array
void _dbus_marshal_skip_array(const DBusString *str, int element_type, int byte_order, int *pos)
Skips an array, returning the next position.
Definition: dbus-marshal-basic.c:1208
_DBUS_INT_MAX
#define _DBUS_INT_MAX
Definition: dbus-internals.h:302
_dbus_type_writer_append_array
dbus_bool_t _dbus_type_writer_append_array(DBusTypeWriter *writer, const DBusString *contained_type, int contained_type_start, DBusTypeWriter *sub)
Append to an existing array.
Definition: dbus-marshal-recursive.c:2143
_dbus_marshal_write_basic
dbus_bool_t _dbus_marshal_write_basic(DBusString *str, int insert_at, int type, const void *value, int byte_order, int *pos_after)
Marshals a basic-typed value.
Definition: dbus-marshal-basic.c:827
_dbus_type_writer_recurse
dbus_bool_t _dbus_type_writer_recurse(DBusTypeWriter *writer, int container_type, const DBusString *contained_type, int contained_type_start, DBusTypeWriter *sub)
Opens a new container and writes out the initial information for that container.
Definition: dbus-marshal-recursive.c:2109
_dbus_type_reader_has_next
dbus_bool_t _dbus_type_reader_has_next(const DBusTypeReader *reader)
Check whether there's another value on this "level".
Definition: dbus-marshal-recursive.c:1094
DBusTypeReaderClass::name
const char * name
name for debugging
Definition: dbus-marshal-recursive.c:127
_dbus_type_reader_get_element_type
int _dbus_type_reader_get_element_type(const DBusTypeReader *reader)
Gets the type of an element of the array the reader is currently pointing to.
Definition: dbus-marshal-recursive.c:821
_dbus_type_reader_set_basic
dbus_bool_t _dbus_type_reader_set_basic(DBusTypeReader *reader, const void *value, const DBusTypeReader *realign_root)
Sets a new value for the basic type value pointed to by the reader, leaving the reader valid to conti...
Definition: dbus-marshal-recursive.c:1363
_dbus_type_writer_init_types_delayed
void _dbus_type_writer_init_types_delayed(DBusTypeWriter *writer, int byte_order, DBusString *value_str, int value_pos)
Initialize a write iterator, with the signature to be provided later.
Definition: dbus-marshal-recursive.c:1528
DBusTypeWriter::type_str
DBusString * type_str
where to write typecodes (or read type expectations)
Definition: dbus-marshal-recursive.h:74
_dbus_string_lengthen
dbus_bool_t _dbus_string_lengthen(DBusString *str, int additional_length)
Makes a string longer by the given number of bytes.
Definition: dbus-string.c:784
DBusTypeReader::byte_order
dbus_uint32_t byte_order
byte order of the block
Definition: dbus-marshal-recursive.h:41
_dbus_type_reader_read_basic
void _dbus_type_reader_read_basic(const DBusTypeReader *reader, void *value)
Reads a basic-typed value, as with _dbus_marshal_read_basic().
Definition: dbus-marshal-recursive.c:870
_dbus_type_reader_read_fixed_multi
void _dbus_type_reader_read_fixed_multi(const DBusTypeReader *reader, const void **value, int *n_elements)
Reads a block of fixed-length basic values, from the current point in an array to the end of the arra...
Definition: dbus-marshal-recursive.c:924
_dbus_type_get_alignment
int _dbus_type_get_alignment(int typecode)
Gets the alignment requirement for the given type; will be 1, 4, or 8.
Definition: dbus-marshal-basic.c:1236
_dbus_string_init
dbus_bool_t _dbus_string_init(DBusString *str)
Initializes a string.
Definition: dbus-string.c:182
_dbus_type_writer_add_types
void _dbus_type_writer_add_types(DBusTypeWriter *writer, DBusString *type_str, int type_pos)
Adds type string to the writer, if it had none.
Definition: dbus-marshal-recursive.c:1546
DBUS_STRUCT_BEGIN_CHAR
#define DBUS_STRUCT_BEGIN_CHAR
Code marking the start of a struct type in a type signature.
Definition: dbus-protocol.h:156
TRUE
#define TRUE
_dbus_list_append
dbus_bool_t _dbus_list_append(DBusList **list, void *data)
Appends a value to the list.
Definition: dbus-list.c:271
DBusArrayLenFixup
When modifying an existing block of values, array lengths may need to be adjusted; those adjustments ...
Definition: dbus-marshal-recursive.h:93
DBusTypeWriter::value_str
DBusString * value_str
where to write values
Definition: dbus-marshal-recursive.h:76
DBusTypeReader
The type reader is an iterator for reading values from a block of values.
Definition: dbus-marshal-recursive.h:39
_dbus_marshal_write_fixed_multi
dbus_bool_t _dbus_marshal_write_fixed_multi(DBusString *str, int insert_at, int element_type, const void *value, int n_elements, int byte_order, int *pos_after)
Marshals a block of values of fixed-length type all at once, as an optimization.
Definition: dbus-marshal-basic.c:1069
DBusTypeReader::array_len_offset
dbus_uint32_t array_len_offset
bytes back from start_pos that len ends
Definition: dbus-marshal-recursive.h:46
dbus_free
void dbus_free(void *memory)
Frees a block of memory previously allocated by dbus_malloc() or dbus_malloc0().
Definition: dbus-memory.c:704
DBusTypeWriter::container_type
dbus_uint32_t container_type
what are we inside? (e.g.
Definition: dbus-marshal-recursive.h:68
DBUS_STRUCT_END_CHAR
#define DBUS_STRUCT_END_CHAR
Code marking the end of a struct type in a type signature.
Definition: dbus-protocol.h:160
_dbus_marshal_read_basic
void _dbus_marshal_read_basic(const DBusString *str, int pos, int type, void *value, int byte_order, int *new_pos)
Demarshals a basic-typed value.
Definition: dbus-marshal-basic.c:525
DBusString
Definition: dbus-string.h:42
_dbus_list_get_next_link
#define _dbus_list_get_next_link(list, link)
Definition: dbus-list.h:119
_dbus_string_insert_byte
dbus_bool_t _dbus_string_insert_byte(DBusString *str, int i, unsigned char byte)
Inserts a single byte at the given position.
Definition: dbus-string.c:638
_dbus_marshal_read_uint32
dbus_uint32_t _dbus_marshal_read_uint32(const DBusString *str, int pos, int byte_order, int *new_pos)
Convenience function to demarshal a 32 bit unsigned integer.
Definition: dbus-marshal-basic.c:487
_dbus_type_reader_init
void _dbus_type_reader_init(DBusTypeReader *reader, int byte_order, const DBusString *type_str, int type_pos, const DBusString *value_str, int value_pos)
Initializes a type reader.
Definition: dbus-marshal-recursive.c:733
DBusTypeWriter::enabled
dbus_uint32_t enabled
whether to write values
Definition: dbus-marshal-recursive.h:72
_dbus_type_writer_write_reader
dbus_bool_t _dbus_type_writer_write_reader(DBusTypeWriter *writer, DBusTypeReader *reader)
Iterate through all values in the given reader, writing a copy of each value to the writer.
Definition: dbus-marshal-recursive.c:2731
_dbus_type_reader_get_value_pos
int _dbus_type_reader_get_value_pos(const DBusTypeReader *reader)
Gets the current position in the value block.
Definition: dbus-marshal-recursive.c:838
_dbus_type_reader_read_raw
void _dbus_type_reader_read_raw(const DBusTypeReader *reader, const unsigned char **value_location)
Get the address of the marshaled value in the data being read.
Definition: dbus-marshal-recursive.c:853
DBusTypeReaderClass::recurse
void(* recurse)(DBusTypeReader *sub, DBusTypeReader *parent)
recurse with this reader as sub
Definition: dbus-marshal-recursive.c:130
DBUS_TYPE_STRUCT
#define DBUS_TYPE_STRUCT
STRUCT and DICT_ENTRY are sort of special since their codes can't appear in a type string,...
Definition: dbus-protocol.h:136
DBUS_TYPE_DICT_ENTRY
#define DBUS_TYPE_DICT_ENTRY
Type code used to represent a dict entry; however, this type code does not appear in type signatures,...
Definition: dbus-protocol.h:143
_dbus_string_insert_bytes
dbus_bool_t _dbus_string_insert_bytes(DBusString *str, int i, int n_bytes, unsigned char byte)
Inserts a number of bytes of a given value at the given position.
Definition: dbus-string.c:608
_dbus_type_reader_get_current_type
int _dbus_type_reader_get_current_type(const DBusTypeReader *reader)
Gets the type of the value the reader is currently pointing to; or for a types-only reader gets the t...
Definition: dbus-marshal-recursive.c:786
ReplacementBlock::replacement
DBusString replacement
Marshaled value including alignment padding.
Definition: dbus-marshal-recursive.c:1137
_dbus_type_reader_delete
dbus_bool_t _dbus_type_reader_delete(DBusTypeReader *reader, const DBusTypeReader *realign_root)
Recursively deletes any value pointed to by the reader, leaving the reader valid to continue reading.
Definition: dbus-marshal-recursive.c:1420
FALSE
#define FALSE
_dbus_marshal_skip_basic
void _dbus_marshal_skip_basic(const DBusString *str, int type, int byte_order, int *pos)
Skips over a basic-typed value, reporting the following position.
Definition: dbus-marshal-basic.c:1140
DBusTypeReaderClass::check_finished
dbus_bool_t(* check_finished)(const DBusTypeReader *reader)
check whether reader is at the end
Definition: dbus-marshal-recursive.c:132
DBusTypeReader::value_pos
int value_pos
current position in values
Definition: dbus-marshal-recursive.h:50
_dbus_string_replace_len
dbus_bool_t _dbus_string_replace_len(const DBusString *source, int start, int len, DBusString *dest, int replace_at, int replace_len)
Replaces a segment of dest string with a segment of source string.
Definition: dbus-string.c:1428
DBusList::data
void * data
Data stored at this element.
Definition: dbus-list.h:38
_dbus_unpack_uint32
dbus_uint32_t _dbus_unpack_uint32(int byte_order, const unsigned char *data)
Unpacks a 32 bit unsigned integer from a data pointer.
Definition: dbus-marshal-basic.c:200
_dbus_string_delete
void _dbus_string_delete(DBusString *str, int start, int len)
Deletes a segment of a DBusString with length len starting at start.
Definition: dbus-string.c:1217
_dbus_list_free_link
void _dbus_list_free_link(DBusList *link)
Frees a linked list node allocated with _dbus_list_alloc_link.
Definition: dbus-list.c:255
DBusTypeReader::value_str
const DBusString * value_str
string containing values of block
Definition: dbus-marshal-recursive.h:49
dbus_type_is_container
dbus_bool_t dbus_type_is_container(int typecode)
A "container type" can contain basic types, or nested container types.
Definition: dbus-signature.c:298
_dbus_assert_not_reached
#define _dbus_assert_not_reached(explanation)
Definition: dbus-internals.h:164
_dbus_string_set_length
dbus_bool_t _dbus_string_set_length(DBusString *str, int length)
Sets the length of a string.
Definition: dbus-string.c:826
DBusTypeWriter::type_pos
int type_pos
current pos in type_str
Definition: dbus-marshal-recursive.h:75
dbus_type_is_fixed
dbus_bool_t dbus_type_is_fixed(int typecode)
Tells you whether values of this type can change length if you set them to some other value.
Definition: dbus-signature.c:353
DBUS_DICT_ENTRY_BEGIN_CHAR
#define DBUS_DICT_ENTRY_BEGIN_CHAR
Code marking the start of a dict entry type in a type signature.
Definition: dbus-protocol.h:164
DBusTypeReaderClass::next
void(* next)(DBusTypeReader *reader, int current_type)
go to the next value
Definition: dbus-marshal-recursive.c:133
ReplacementBlock
Definition: dbus-marshal-recursive.c:1135
_dbus_type_writer_write_basic
dbus_bool_t _dbus_type_writer_write_basic(DBusTypeWriter *writer, int type, const void *value)
Writes out a basic type.
Definition: dbus-marshal-recursive.c:2311
_dbus_type_reader_init_types_only
void _dbus_type_reader_init_types_only(DBusTypeReader *reader, const DBusString *type_str, int type_pos)
Like _dbus_type_reader_init() but the iteration is over the signature, not over values.
Definition: dbus-marshal-recursive.c:761
DBusTypeReader::finished
dbus_uint32_t finished
marks we're at end iterator for cases where we don't have another way to tell
Definition: dbus-marshal-recursive.h:43
DBUS_DICT_ENTRY_END_CHAR
#define DBUS_DICT_ENTRY_END_CHAR
Code marking the end of a dict entry type in a type signature.
Definition: dbus-protocol.h:168
dbus_new
#define dbus_new(type, count)
Definition: dbus-memory.h:57
DBusArrayLenFixup::new_len
int new_len
the new value of the length in the written-out block
Definition: dbus-marshal-recursive.h:96
DBusArrayLenFixup::len_pos_in_reader
int len_pos_in_reader
where the length was in the original block
Definition: dbus-marshal-recursive.h:95
_dbus_type_reader_get_array_length
int _dbus_type_reader_get_array_length(const DBusTypeReader *reader)
Returns the number of bytes in the array.
Definition: dbus-marshal-recursive.c:900
_dbus_assert
#define _dbus_assert(condition)
Definition: dbus-internals.h:153
_dbus_marshal_set_uint32
void _dbus_marshal_set_uint32(DBusString *str, int pos, dbus_uint32_t value, int byte_order)
Sets the 4 bytes at the given offset to a marshaled unsigned integer, replacing anything found there ...
Definition: dbus-marshal-basic.c:271
_dbus_list_get_length
int _dbus_list_get_length(DBusList **list)
Gets the length of a list.
Definition: dbus-list.c:758
DBUS_TYPE_VARIANT
#define DBUS_TYPE_VARIANT
Type code marking a D-Bus variant type.
Definition: dbus-protocol.h:124
DBusBasicValue
A simple value union that lets you access bytes as if they were various types; useful when dealing wi...
Definition: dbus-types.h:137
_dbus_first_type_in_signature
int _dbus_first_type_in_signature(const DBusString *str, int pos)
Get the first type in the signature.
Definition: dbus-marshal-basic.c:1477
_dbus_type_writer_unrecurse
dbus_bool_t _dbus_type_writer_unrecurse(DBusTypeWriter *writer, DBusTypeWriter *sub)
Closes a container created by _dbus_type_writer_recurse() and writes any additional information to th...
Definition: dbus-marshal-recursive.c:2179
DBusList
Definition: dbus-list.h:34
_dbus_string_equal_substring
dbus_bool_t _dbus_string_equal_substring(const DBusString *a, int a_start, int a_len, const DBusString *b, int b_start)
Tests two sub-parts of two DBusString for equality.
Definition: dbus-string.c:2128
dbus_type_is_basic
dbus_bool_t dbus_type_is_basic(int typecode)
A "basic type" is a somewhat arbitrary concept, but the intent is to include those types that are ful...
Definition: dbus-signature.c:322
_dbus_type_to_string
const char * _dbus_type_to_string(int typecode)
Returns a string describing the given type.
Definition: dbus-marshal-basic.c:1282
DBusTypeReaderClass::id
int id
index in all_reader_classes
Definition: dbus-marshal-recursive.c:128
_dbus_string_alloc_space
dbus_bool_t _dbus_string_alloc_space(DBusString *str, int extra_bytes)
Preallocate extra_bytes such that a future lengthening of the string by extra_bytes is guaranteed to ...
Definition: dbus-string.c:923
_dbus_type_writer_init
void _dbus_type_writer_init(DBusTypeWriter *writer, int byte_order, DBusString *type_str, int type_pos, DBusString *value_str, int value_pos)
Initialize a write iterator, which is used to write out values in serialized D-Bus format.
Definition: dbus-marshal-recursive.c:1493
_dbus_marshal_set_basic
dbus_bool_t _dbus_marshal_set_basic(DBusString *str, int pos, int type, const void *value, int byte_order, int *old_end_pos, int *new_end_pos)
Sets an existing basic type value to a new value.
Definition: dbus-marshal-basic.c:388
_dbus_type_writer_remove_types
void _dbus_type_writer_remove_types(DBusTypeWriter *writer)
Removes type string from the writer.
Definition: dbus-marshal-recursive.c:1563
_dbus_type_reader_recurse
void _dbus_type_reader_recurse(DBusTypeReader *reader, DBusTypeReader *sub)
Initialize a new reader pointing to the first type and corresponding value that's a child of the curr...
Definition: dbus-marshal-recursive.c:988
_DBUS_ZERO
#define _DBUS_ZERO(object)
Definition: dbus-internals.h:194
_dbus_string_copy_len
dbus_bool_t _dbus_string_copy_len(const DBusString *source, int start, int len, DBusString *dest, int insert_at)
Like _dbus_string_copy(), but can copy a segment from the middle of the source string.
Definition: dbus-string.c:1399
DBusTypeReaderClass::types_only
dbus_bool_t types_only
only iterates over types, not values
Definition: dbus-marshal-recursive.c:129
_dbus_type_reader_get_signature
void _dbus_type_reader_get_signature(const DBusTypeReader *reader, const DBusString **str_p, int *start_p, int *len_p)
Gets the string and range of said string containing the signature of the current value.
Definition: dbus-marshal-recursive.c:1125
DBusTypeReader::u
union DBusTypeReader::@1 u
class-specific data
DBUS_TYPE_UINT32
#define DBUS_TYPE_UINT32
Type code marking a 32-bit unsigned integer.
Definition: dbus-protocol.h:86
_dbus_type_writer_write_fixed_multi
dbus_bool_t _dbus_type_writer_write_fixed_multi(DBusTypeWriter *writer, int element_type, const void *value, int n_elements)
Writes a block of fixed-length basic values, i.e.
Definition: dbus-marshal-recursive.c:2359
DBusTypeWriter
The type writer is an iterator for writing to a block of values.
Definition: dbus-marshal-recursive.h:64
DBusTypeWriter::byte_order
dbus_uint32_t byte_order
byte order to write values with
Definition: dbus-marshal-recursive.h:66
DBusTypeReader::klass
const DBusTypeReaderClass * klass
the vtable for the reader
Definition: dbus-marshal-recursive.h:52
DBusTypeReaderClass
Virtual table for a type reader.
Definition: dbus-marshal-recursive.c:125
_dbus_list_get_first_link
DBusList * _dbus_list_get_first_link(DBusList **list)
Gets the first link in the list.
Definition: dbus-list.c:595
ARRAY_READER_LEN_POS
#define ARRAY_READER_LEN_POS(reader)
compute position of array length given array_len_offset, which is the offset back from start_pos to e...
Definition: dbus-marshal-recursive.c:214
_dbus_warn_check_failed
void _dbus_warn_check_failed(const char *format,...)
Prints a "critical" warning to stderr when an assertion fails; differs from _dbus_warn primarily in t...
Definition: dbus-internals.c:270
dbus_bool_t
dbus_uint32_t dbus_bool_t
Definition: dbus-types.h:35
NULL
#define NULL