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