D-Bus 1.4.14
dbus-marshal-basic.c
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
00002 /* dbus-marshal-basic.c  Marshalling routines for basic (primitive) types
00003  *
00004  * Copyright (C) 2002 CodeFactory AB
00005  * Copyright (C) 2003, 2004, 2005 Red Hat, Inc.
00006  *
00007  * Licensed under the Academic Free License version 2.1
00008  *
00009  * This program is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00022  *
00023  */
00024 
00025 #include <config.h>
00026 #include "dbus-internals.h"
00027 #include "dbus-marshal-basic.h"
00028 #include "dbus-signature.h"
00029 
00030 #include <string.h>
00031 
00047 static void
00048 pack_2_octets (dbus_uint16_t   value,
00049                int             byte_order,
00050                unsigned char  *data)
00051 {
00052   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 2) == data);
00053 
00054   if ((byte_order) == DBUS_LITTLE_ENDIAN)
00055     *((dbus_uint16_t*)(data)) = DBUS_UINT16_TO_LE (value);
00056   else
00057     *((dbus_uint16_t*)(data)) = DBUS_UINT16_TO_BE (value);
00058 }
00059 
00060 static void
00061 pack_4_octets (dbus_uint32_t   value,
00062                int             byte_order,
00063                unsigned char  *data)
00064 {
00065   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
00066 
00067   if ((byte_order) == DBUS_LITTLE_ENDIAN)
00068     *((dbus_uint32_t*)(data)) = DBUS_UINT32_TO_LE (value);
00069   else
00070     *((dbus_uint32_t*)(data)) = DBUS_UINT32_TO_BE (value);
00071 }
00072 
00073 static void
00074 pack_8_octets (DBusBasicValue     value,
00075                int                byte_order,
00076                unsigned char     *data)
00077 {
00078   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 8) == data);
00079 
00080 #ifdef DBUS_HAVE_INT64
00081   if ((byte_order) == DBUS_LITTLE_ENDIAN)
00082     *((dbus_uint64_t*)(data)) = DBUS_UINT64_TO_LE (value.u64);
00083   else
00084     *((dbus_uint64_t*)(data)) = DBUS_UINT64_TO_BE (value.u64);
00085 #else
00086   *(DBus8ByteStruct*)data = value.u64;
00087   swap_8_octets ((DBusBasicValue*)data, byte_order);
00088 #endif
00089 }
00090 
00098 void
00099 _dbus_pack_uint32 (dbus_uint32_t   value,
00100                    int             byte_order,
00101                    unsigned char  *data)
00102 {
00103   pack_4_octets (value, byte_order, data);
00104 }
00105 
00106 #ifndef DBUS_HAVE_INT64
00107 /* from ORBit */
00108 static void
00109 swap_bytes (unsigned char *data,
00110             unsigned int   len)
00111 {
00112   unsigned char *p1 = data;
00113   unsigned char *p2 = data + len - 1;
00114 
00115   while (p1 < p2)
00116     {
00117       unsigned char tmp = *p1;
00118       *p1 = *p2;
00119       *p2 = tmp;
00120 
00121       --p2;
00122       ++p1;
00123     }
00124 }
00125 #endif /* !DBUS_HAVE_INT64 */
00126 
00127 static void
00128 swap_8_octets (DBusBasicValue    *value,
00129                int                byte_order)
00130 {
00131   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
00132     {
00133 #ifdef DBUS_HAVE_INT64
00134       value->u64 = DBUS_UINT64_SWAP_LE_BE (value->u64);
00135 #else
00136       swap_bytes ((unsigned char *)value, 8);
00137 #endif
00138     }
00139 }
00140 
00141 #if 0
00142 static DBusBasicValue
00143 unpack_8_octets (int                  byte_order,
00144                  const unsigned char *data)
00145 {
00146   DBusBasicValue r;
00147 
00148   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 8) == data);
00149   _dbus_assert (sizeof (r) == 8);
00150 
00151 #ifdef DBUS_HAVE_INT64
00152   if (byte_order == DBUS_LITTLE_ENDIAN)
00153     r.u64 = DBUS_UINT64_FROM_LE (*(dbus_uint64_t*)data);
00154   else
00155     r.u64 = DBUS_UINT64_FROM_BE (*(dbus_uint64_t*)data);
00156 #else
00157   r.u64 = *(DBus8ByteStruct*)data;
00158   swap_8_octets (&r, byte_order);
00159 #endif
00160 
00161   return r;
00162 }
00163 #endif
00164 
00165 #ifndef _dbus_unpack_uint16
00166 
00173 dbus_uint16_t
00174 _dbus_unpack_uint16 (int                  byte_order,
00175                      const unsigned char *data)
00176 {
00177   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 2) == data);
00178 
00179   if (byte_order == DBUS_LITTLE_ENDIAN)
00180     return DBUS_UINT16_FROM_LE (*(dbus_uint16_t*)data);
00181   else
00182     return DBUS_UINT16_FROM_BE (*(dbus_uint16_t*)data);
00183 }
00184 #endif /* _dbus_unpack_uint16 */
00185 
00186 #ifndef _dbus_unpack_uint32
00187 
00194 dbus_uint32_t
00195 _dbus_unpack_uint32 (int                  byte_order,
00196                      const unsigned char *data)
00197 {
00198   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
00199 
00200   if (byte_order == DBUS_LITTLE_ENDIAN)
00201     return DBUS_UINT32_FROM_LE (*(dbus_uint32_t*)data);
00202   else
00203     return DBUS_UINT32_FROM_BE (*(dbus_uint32_t*)data);
00204 }
00205 #endif /* _dbus_unpack_uint32 */
00206 
00207 static void
00208 set_2_octets (DBusString          *str,
00209               int                  offset,
00210               dbus_uint16_t        value,
00211               int                  byte_order)
00212 {
00213   char *data;
00214 
00215   _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
00216                 byte_order == DBUS_BIG_ENDIAN);
00217 
00218   data = _dbus_string_get_data_len (str, offset, 2);
00219 
00220   pack_2_octets (value, byte_order, data);
00221 }
00222 
00223 static void
00224 set_4_octets (DBusString          *str,
00225               int                  offset,
00226               dbus_uint32_t        value,
00227               int                  byte_order)
00228 {
00229   char *data;
00230 
00231   _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
00232                 byte_order == DBUS_BIG_ENDIAN);
00233 
00234   data = _dbus_string_get_data_len (str, offset, 4);
00235 
00236   pack_4_octets (value, byte_order, data);
00237 }
00238 
00239 static void
00240 set_8_octets (DBusString          *str,
00241               int                  offset,
00242               DBusBasicValue       value,
00243               int                  byte_order)
00244 {
00245   char *data;
00246 
00247   _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
00248                 byte_order == DBUS_BIG_ENDIAN);
00249 
00250   data = _dbus_string_get_data_len (str, offset, 8);
00251 
00252   pack_8_octets (value, byte_order, data);
00253 }
00254 
00265 void
00266 _dbus_marshal_set_uint32 (DBusString          *str,
00267                           int                  pos,
00268                           dbus_uint32_t        value,
00269                           int                  byte_order)
00270 {
00271   set_4_octets (str, pos, value, byte_order);
00272 }
00273 
00293 static dbus_bool_t
00294 set_string (DBusString          *str,
00295             int                  pos,
00296             const char          *value,
00297             int                  byte_order,
00298             int                 *old_end_pos,
00299             int                 *new_end_pos)
00300 {
00301   int old_len, new_len;
00302   DBusString dstr;
00303 
00304   _dbus_string_init_const (&dstr, value);
00305 
00306   _dbus_assert (_DBUS_ALIGN_VALUE (pos, 4) == (unsigned) pos);
00307   old_len = _dbus_unpack_uint32 (byte_order,
00308                                  _dbus_string_get_const_data_len (str, pos, 4));
00309 
00310   new_len = _dbus_string_get_length (&dstr);
00311 
00312   if (!_dbus_string_replace_len (&dstr, 0, new_len,
00313                                  str, pos + 4, old_len))
00314     return FALSE;
00315 
00316   _dbus_marshal_set_uint32 (str, pos, new_len, byte_order);
00317 
00318   if (old_end_pos)
00319     *old_end_pos = pos + 4 + old_len + 1;
00320   if (new_end_pos)
00321     *new_end_pos = pos + 4 + new_len + 1;
00322 
00323   return TRUE;
00324 }
00325 
00339 static dbus_bool_t
00340 set_signature (DBusString          *str,
00341                int                  pos,
00342                const char          *value,
00343                int                  byte_order,
00344                int                 *old_end_pos,
00345                int                 *new_end_pos)
00346 {
00347   int old_len, new_len;
00348   DBusString dstr;
00349 
00350   _dbus_string_init_const (&dstr, value);
00351 
00352   old_len = _dbus_string_get_byte (str, pos);
00353   new_len = _dbus_string_get_length (&dstr);
00354 
00355   if (!_dbus_string_replace_len (&dstr, 0, new_len,
00356                                  str, pos + 1, old_len))
00357     return FALSE;
00358 
00359   _dbus_string_set_byte (str, pos, new_len);
00360 
00361   if (old_end_pos)
00362     *old_end_pos = pos + 1 + old_len + 1;
00363   if (new_end_pos)
00364     *new_end_pos = pos + 1 + new_len + 1;
00365 
00366   return TRUE;
00367 }
00368 
00382 dbus_bool_t
00383 _dbus_marshal_set_basic (DBusString       *str,
00384                          int               pos,
00385                          int               type,
00386                          const void       *value,
00387                          int               byte_order,
00388                          int              *old_end_pos,
00389                          int              *new_end_pos)
00390 {
00391   const DBusBasicValue *vp;
00392 
00393   vp = value;
00394 
00395   switch (type)
00396     {
00397     case DBUS_TYPE_BYTE:
00398       _dbus_string_set_byte (str, pos, vp->byt);
00399       if (old_end_pos)
00400         *old_end_pos = pos + 1;
00401       if (new_end_pos)
00402         *new_end_pos = pos + 1;
00403       return TRUE;
00404       break;
00405     case DBUS_TYPE_INT16:
00406     case DBUS_TYPE_UINT16:
00407       pos = _DBUS_ALIGN_VALUE (pos, 2);
00408       set_2_octets (str, pos, vp->u16, byte_order);
00409       if (old_end_pos)
00410         *old_end_pos = pos + 2;
00411       if (new_end_pos)
00412         *new_end_pos = pos + 2;
00413       return TRUE;
00414       break;
00415     case DBUS_TYPE_BOOLEAN:
00416     case DBUS_TYPE_INT32:
00417     case DBUS_TYPE_UINT32:
00418     case DBUS_TYPE_UNIX_FD:
00419       pos = _DBUS_ALIGN_VALUE (pos, 4);
00420       set_4_octets (str, pos, vp->u32, byte_order);
00421       if (old_end_pos)
00422         *old_end_pos = pos + 4;
00423       if (new_end_pos)
00424         *new_end_pos = pos + 4;
00425       return TRUE;
00426       break;
00427     case DBUS_TYPE_INT64:
00428     case DBUS_TYPE_UINT64:
00429     case DBUS_TYPE_DOUBLE:
00430       pos = _DBUS_ALIGN_VALUE (pos, 8);
00431       set_8_octets (str, pos, *vp, byte_order);
00432       if (old_end_pos)
00433         *old_end_pos = pos + 8;
00434       if (new_end_pos)
00435         *new_end_pos = pos + 8;
00436       return TRUE;
00437       break;
00438     case DBUS_TYPE_STRING:
00439     case DBUS_TYPE_OBJECT_PATH:
00440       pos = _DBUS_ALIGN_VALUE (pos, 4);
00441       _dbus_assert (vp->str != NULL);
00442       return set_string (str, pos, vp->str, byte_order,
00443                          old_end_pos, new_end_pos);
00444       break;
00445     case DBUS_TYPE_SIGNATURE:
00446       _dbus_assert (vp->str != NULL);
00447       return set_signature (str, pos, vp->str, byte_order,
00448                             old_end_pos, new_end_pos);
00449       break;
00450     default:
00451       _dbus_assert_not_reached ("not a basic type");
00452       return FALSE;
00453       break;
00454     }
00455 }
00456 
00466 dbus_uint32_t
00467 _dbus_marshal_read_uint32  (const DBusString *str,
00468                             int               pos,
00469                             int               byte_order,
00470                             int              *new_pos)
00471 {
00472   pos = _DBUS_ALIGN_VALUE (pos, 4);
00473 
00474   if (new_pos)
00475     *new_pos = pos + 4;
00476 
00477   _dbus_assert (pos + 4 <= _dbus_string_get_length (str));
00478   
00479   return _dbus_unpack_uint32 (byte_order,
00480                               _dbus_string_get_const_data (str) + pos);
00481 }
00482 
00504 void
00505 _dbus_marshal_read_basic (const DBusString      *str,
00506                           int                    pos,
00507                           int                    type,
00508                           void                  *value,
00509                           int                    byte_order,
00510                           int                   *new_pos)
00511 {
00512   const char *str_data;
00513 
00514   _dbus_assert (dbus_type_is_basic (type));
00515 
00516   str_data = _dbus_string_get_const_data (str);
00517 
00518   /* Below we volatile types to avoid aliasing issues;
00519    * see http://bugs.freedesktop.org/show_bug.cgi?id=20137
00520    */
00521   
00522   switch (type)
00523     {
00524     case DBUS_TYPE_BYTE:
00525       {
00526       volatile unsigned char *vp = value;
00527       *vp = (unsigned char) _dbus_string_get_byte (str, pos);
00528       (pos)++;
00529       }
00530       break;
00531     case DBUS_TYPE_INT16:
00532     case DBUS_TYPE_UINT16:
00533       {
00534       volatile dbus_uint16_t *vp = value;
00535       pos = _DBUS_ALIGN_VALUE (pos, 2);
00536       *vp = *(dbus_uint16_t *)(str_data + pos);
00537       if (byte_order != DBUS_COMPILER_BYTE_ORDER)
00538         *vp = DBUS_UINT16_SWAP_LE_BE (*vp);
00539       pos += 2;
00540       }
00541       break;
00542     case DBUS_TYPE_INT32:
00543     case DBUS_TYPE_UINT32:
00544     case DBUS_TYPE_BOOLEAN:
00545     case DBUS_TYPE_UNIX_FD:
00546       {
00547       volatile dbus_uint32_t *vp = value;
00548       pos = _DBUS_ALIGN_VALUE (pos, 4);
00549       *vp = *(dbus_uint32_t *)(str_data + pos);
00550       if (byte_order != DBUS_COMPILER_BYTE_ORDER)
00551         *vp = DBUS_UINT32_SWAP_LE_BE (*vp);
00552       pos += 4;
00553       }
00554       break;
00555     case DBUS_TYPE_INT64:
00556     case DBUS_TYPE_UINT64:
00557     case DBUS_TYPE_DOUBLE:
00558       {
00559       volatile dbus_uint64_t *vp = value;
00560       pos = _DBUS_ALIGN_VALUE (pos, 8);
00561 #ifdef DBUS_HAVE_INT64
00562       if (byte_order != DBUS_COMPILER_BYTE_ORDER)
00563         *vp = DBUS_UINT64_SWAP_LE_BE (*(dbus_uint64_t*)(str_data + pos));
00564       else
00565         *vp = *(dbus_uint64_t*)(str_data + pos);
00566 #else
00567       *vp = *(DBus8ByteStruct*) (str_data + pos);
00568       swap_8_octets (vp, byte_order);
00569 #endif
00570       pos += 8;
00571       }
00572       break;
00573     case DBUS_TYPE_STRING:
00574     case DBUS_TYPE_OBJECT_PATH:
00575       {
00576         int len;
00577         volatile char **vp = value;
00578 
00579         len = _dbus_marshal_read_uint32 (str, pos, byte_order, &pos);
00580 
00581         *vp = (char*) str_data + pos;
00582 
00583         pos += len + 1; /* length plus nul */
00584       }
00585       break;
00586     case DBUS_TYPE_SIGNATURE:
00587       {
00588         int len;
00589         volatile char **vp = value;
00590 
00591         len = _dbus_string_get_byte (str, pos);
00592         pos += 1;
00593 
00594         *vp = (char*) str_data + pos;
00595 
00596         pos += len + 1; /* length plus nul */
00597       }
00598       break;
00599     default:
00600       _dbus_warn_check_failed ("type %s %d not a basic type\n",
00601                                _dbus_type_to_string (type), type);
00602       _dbus_assert_not_reached ("not a basic type");
00603       break;
00604     }
00605 
00606   if (new_pos)
00607     *new_pos = pos;
00608 }
00609 
00610 static dbus_bool_t
00611 marshal_2_octets (DBusString   *str,
00612                   int           insert_at,
00613                   dbus_uint16_t value,
00614                   int           byte_order,
00615                   int          *pos_after)
00616 {
00617   dbus_bool_t retval;
00618   int orig_len;
00619 
00620   _dbus_assert (sizeof (value) == 2);
00621 
00622   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
00623     value = DBUS_UINT16_SWAP_LE_BE (value);
00624 
00625   orig_len = _dbus_string_get_length (str);
00626 
00627   retval = _dbus_string_insert_2_aligned (str, insert_at,
00628                                           (const unsigned char *)&value);
00629 
00630   if (pos_after)
00631     {
00632       *pos_after = insert_at + (_dbus_string_get_length (str) - orig_len);
00633       _dbus_assert (*pos_after <= _dbus_string_get_length (str));
00634     }
00635 
00636   return retval;
00637 }
00638 
00639 static dbus_bool_t
00640 marshal_4_octets (DBusString   *str,
00641                   int           insert_at,
00642                   dbus_uint32_t value,
00643                   int           byte_order,
00644                   int          *pos_after)
00645 {
00646   dbus_bool_t retval;
00647   int orig_len;
00648 
00649   _dbus_assert (sizeof (value) == 4);
00650 
00651   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
00652     value = DBUS_UINT32_SWAP_LE_BE (value);
00653 
00654   orig_len = _dbus_string_get_length (str);
00655 
00656   retval = _dbus_string_insert_4_aligned (str, insert_at,
00657                                           (const unsigned char *)&value);
00658 
00659   if (pos_after)
00660     {
00661       *pos_after = insert_at + (_dbus_string_get_length (str) - orig_len);
00662       _dbus_assert (*pos_after <= _dbus_string_get_length (str));
00663     }
00664 
00665   return retval;
00666 }
00667 
00668 static dbus_bool_t
00669 marshal_8_octets (DBusString    *str,
00670                   int            insert_at,
00671                   DBusBasicValue value,
00672                   int            byte_order,
00673                   int           *pos_after)
00674 {
00675   dbus_bool_t retval;
00676   int orig_len;
00677 
00678   _dbus_assert (sizeof (value) == 8);
00679 
00680   swap_8_octets (&value, byte_order);
00681 
00682   orig_len = _dbus_string_get_length (str);
00683 
00684   retval = _dbus_string_insert_8_aligned (str, insert_at,
00685                                           (const unsigned char *)&value);
00686 
00687   if (pos_after)
00688     *pos_after = insert_at + _dbus_string_get_length (str) - orig_len;
00689 
00690   return retval;
00691 }
00692 
00693 enum
00694   {
00695     MARSHAL_AS_STRING,
00696     MARSHAL_AS_SIGNATURE,
00697     MARSHAL_AS_BYTE_ARRAY
00698   };
00699 
00700 static dbus_bool_t
00701 marshal_len_followed_by_bytes (int                  marshal_as,
00702                                DBusString          *str,
00703                                int                  insert_at,
00704                                const unsigned char *value,
00705                                int                  data_len, /* doesn't include nul if any */
00706                                int                  byte_order,
00707                                int                 *pos_after)
00708 {
00709   int pos;
00710   DBusString value_str;
00711   int value_len;
00712 
00713   _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN || byte_order == DBUS_BIG_ENDIAN);
00714   if (insert_at > _dbus_string_get_length (str))
00715     _dbus_warn ("insert_at = %d string len = %d data_len = %d\n",
00716                 insert_at, _dbus_string_get_length (str), data_len);
00717   
00718   if (marshal_as == MARSHAL_AS_BYTE_ARRAY)
00719     value_len = data_len;
00720   else
00721     value_len = data_len + 1; /* value has a nul */
00722 
00723   _dbus_string_init_const_len (&value_str, value, value_len);
00724 
00725   pos = insert_at;
00726 
00727   if (marshal_as == MARSHAL_AS_SIGNATURE)
00728     {
00729       _dbus_assert (data_len <= DBUS_MAXIMUM_SIGNATURE_LENGTH);
00730       _dbus_assert (data_len <= 255); /* same as max sig len right now */
00731       
00732       if (!_dbus_string_insert_byte (str, pos, data_len))
00733         goto oom;
00734 
00735       pos += 1;
00736     }
00737   else
00738     {
00739       if (!marshal_4_octets (str, pos, data_len,
00740                              byte_order, &pos))
00741         goto oom;
00742     }
00743 
00744   if (!_dbus_string_copy_len (&value_str, 0, value_len,
00745                               str, pos))
00746     goto oom;
00747 
00748 #if 0
00749   /* too expensive */
00750   _dbus_assert (_dbus_string_equal_substring (&value_str, 0, value_len,
00751                                               str, pos));
00752   _dbus_verbose_bytes_of_string (str, pos, value_len);
00753 #endif
00754 
00755   pos += value_len;
00756 
00757   if (pos_after)
00758     *pos_after = pos;
00759 
00760   return TRUE;
00761 
00762  oom:
00763   /* Delete what we've inserted */
00764   _dbus_string_delete (str, insert_at, pos - insert_at);
00765 
00766   return FALSE;
00767 }
00768 
00769 static dbus_bool_t
00770 marshal_string (DBusString    *str,
00771                 int            insert_at,
00772                 const char    *value,
00773                 int            byte_order,
00774                 int           *pos_after)
00775 {
00776   return marshal_len_followed_by_bytes (MARSHAL_AS_STRING,
00777                                         str, insert_at, value,
00778                                         strlen (value),
00779                                         byte_order, pos_after);
00780 }
00781 
00782 static dbus_bool_t
00783 marshal_signature (DBusString    *str,
00784                    int            insert_at,
00785                    const char    *value,
00786                    int           *pos_after)
00787 {
00788   return marshal_len_followed_by_bytes (MARSHAL_AS_SIGNATURE,
00789                                         str, insert_at, value,
00790                                         strlen (value),
00791                                         DBUS_COMPILER_BYTE_ORDER, /* irrelevant */
00792                                         pos_after);
00793 }
00794 
00811 dbus_bool_t
00812 _dbus_marshal_write_basic (DBusString *str,
00813                            int         insert_at,
00814                            int         type,
00815                            const void *value,
00816                            int         byte_order,
00817                            int        *pos_after)
00818 {
00819   const DBusBasicValue *vp;
00820 
00821   _dbus_assert (dbus_type_is_basic (type));
00822 
00823   vp = value;
00824 
00825   switch (type)
00826     {
00827     case DBUS_TYPE_BYTE:
00828       if (!_dbus_string_insert_byte (str, insert_at, vp->byt))
00829         return FALSE;
00830       if (pos_after)
00831         *pos_after = insert_at + 1;
00832       return TRUE;
00833       break;
00834     case DBUS_TYPE_INT16:
00835     case DBUS_TYPE_UINT16:
00836       return marshal_2_octets (str, insert_at, vp->u16,
00837                                byte_order, pos_after);
00838       break;
00839     case DBUS_TYPE_BOOLEAN:
00840       return marshal_4_octets (str, insert_at, vp->u32 != FALSE,
00841                                byte_order, pos_after);
00842       break;
00843     case DBUS_TYPE_INT32:
00844     case DBUS_TYPE_UINT32:
00845     case DBUS_TYPE_UNIX_FD:
00846       return marshal_4_octets (str, insert_at, vp->u32,
00847                                byte_order, pos_after);
00848       break;
00849     case DBUS_TYPE_INT64:
00850     case DBUS_TYPE_UINT64:
00851     case DBUS_TYPE_DOUBLE:
00852       return marshal_8_octets (str, insert_at, *vp, byte_order, pos_after);
00853       break;
00854 
00855     case DBUS_TYPE_STRING:
00856     case DBUS_TYPE_OBJECT_PATH:
00857       _dbus_assert (vp->str != NULL);
00858       return marshal_string (str, insert_at, vp->str, byte_order, pos_after);
00859       break;
00860     case DBUS_TYPE_SIGNATURE:
00861       _dbus_assert (vp->str != NULL);
00862       return marshal_signature (str, insert_at, vp->str, pos_after);
00863       break;
00864     default:
00865       _dbus_assert_not_reached ("not a basic type");
00866       return FALSE;
00867       break;
00868     }
00869 }
00870 
00871 static dbus_bool_t
00872 marshal_1_octets_array (DBusString          *str,
00873                         int                  insert_at,
00874                         const unsigned char *value,
00875                         int                  n_elements,
00876                         int                  byte_order,
00877                         int                 *pos_after)
00878 {
00879   int pos;
00880   DBusString value_str;
00881 
00882   _dbus_string_init_const_len (&value_str, value, n_elements);
00883 
00884   pos = insert_at;
00885 
00886   if (!_dbus_string_copy_len (&value_str, 0, n_elements,
00887                               str, pos))
00888     return FALSE;
00889 
00890   pos += n_elements;
00891 
00892   if (pos_after)
00893     *pos_after = pos;
00894 
00895   return TRUE;
00896 }
00897 
00905 void
00906 _dbus_swap_array (unsigned char *data,
00907                   int            n_elements,
00908                   int            alignment)
00909 {
00910   unsigned char *d;
00911   unsigned char *end;
00912 
00913   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, alignment) == data);
00914 
00915   /* we use const_data and cast it off so DBusString can be a const string
00916    * for the unit tests. don't ask.
00917    */
00918   d = data;
00919   end = d + (n_elements * alignment);
00920   
00921   if (alignment == 8)
00922     {
00923       while (d != end)
00924         {
00925 #ifdef DBUS_HAVE_INT64
00926           *((dbus_uint64_t*)d) = DBUS_UINT64_SWAP_LE_BE (*((dbus_uint64_t*)d));
00927 #else
00928           swap_8_bytes ((DBusBasicValue*) d);
00929 #endif
00930           d += 8;
00931         }
00932     }
00933   else if (alignment == 4)
00934     {
00935       while (d != end)
00936         {
00937           *((dbus_uint32_t*)d) = DBUS_UINT32_SWAP_LE_BE (*((dbus_uint32_t*)d));
00938           d += 4;
00939         }
00940     }
00941   else
00942     {
00943       _dbus_assert (alignment == 2);
00944       
00945       while (d != end)
00946         {
00947           *((dbus_uint16_t*)d) = DBUS_UINT16_SWAP_LE_BE (*((dbus_uint16_t*)d));
00948           d += 2;
00949         }
00950     }
00951 }
00952 
00953 static void
00954 swap_array (DBusString *str,
00955             int         array_start,
00956             int         n_elements,
00957             int         byte_order,
00958             int         alignment)
00959 {
00960   _dbus_assert (_DBUS_ALIGN_VALUE (array_start, alignment) == (unsigned) array_start);
00961 
00962   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
00963     {
00964       /* we use const_data and cast it off so DBusString can be a const string
00965        * for the unit tests. don't ask.
00966        */
00967       _dbus_swap_array ((unsigned char*) (_dbus_string_get_const_data (str) + array_start),
00968                         n_elements, alignment);
00969     }
00970 }
00971 
00972 static dbus_bool_t
00973 marshal_fixed_multi (DBusString           *str,
00974                      int                   insert_at,
00975                      const DBusBasicValue *value,
00976                      int                   n_elements,
00977                      int                   byte_order,
00978                      int                   alignment,
00979                      int                  *pos_after)
00980 {
00981   int old_string_len;
00982   int array_start;
00983   DBusString t;
00984   int len_in_bytes;
00985 
00986   _dbus_assert (n_elements <= DBUS_MAXIMUM_ARRAY_LENGTH / alignment);
00987   
00988   old_string_len = _dbus_string_get_length (str);
00989 
00990   len_in_bytes = n_elements * alignment;
00991   array_start = insert_at;
00992   
00993   /* Note that we do alignment padding unconditionally
00994    * even if the array is empty; this means that
00995    * padding + len is always equal to the number of bytes
00996    * in the array.
00997    */
00998 
00999   if (!_dbus_string_insert_alignment (str, &array_start, alignment))
01000     goto error;
01001 
01002   _dbus_string_init_const_len (&t,
01003                                (const unsigned char*) value,
01004                                len_in_bytes);
01005 
01006   if (!_dbus_string_copy (&t, 0,
01007                           str, array_start))
01008     goto error;
01009 
01010   swap_array (str, array_start, n_elements, byte_order, alignment);
01011 
01012   if (pos_after)
01013     *pos_after = array_start + len_in_bytes;
01014   
01015   return TRUE;
01016 
01017  error:
01018   _dbus_string_delete (str, insert_at,
01019                        _dbus_string_get_length (str) - old_string_len);
01020 
01021   return FALSE;
01022 }
01023 
01041 dbus_bool_t
01042 _dbus_marshal_write_fixed_multi (DBusString *str,
01043                                  int         insert_at,
01044                                  int         element_type,
01045                                  const void *value,
01046                                  int         n_elements,
01047                                  int         byte_order,
01048                                  int        *pos_after)
01049 {
01050   const void* vp = *(const DBusBasicValue**)value;
01051   
01052   _dbus_assert (dbus_type_is_fixed (element_type));
01053   _dbus_assert (n_elements >= 0);
01054 
01055 #if 0
01056   _dbus_verbose ("writing %d elements of %s\n",
01057                  n_elements, _dbus_type_to_string (element_type));
01058 #endif
01059   
01060   switch (element_type)
01061     {
01062     case DBUS_TYPE_BYTE:
01063       return marshal_1_octets_array (str, insert_at, vp, n_elements, byte_order, pos_after);
01064       break;
01065     case DBUS_TYPE_INT16:
01066     case DBUS_TYPE_UINT16:
01067       return marshal_fixed_multi (str, insert_at, vp, n_elements, byte_order, 2, pos_after);
01068     case DBUS_TYPE_BOOLEAN:
01069     case DBUS_TYPE_INT32:
01070     case DBUS_TYPE_UINT32:
01071     case DBUS_TYPE_UNIX_FD:
01072       return marshal_fixed_multi (str, insert_at, vp, n_elements, byte_order, 4, pos_after);
01073       break;
01074     case DBUS_TYPE_INT64:
01075     case DBUS_TYPE_UINT64:
01076     case DBUS_TYPE_DOUBLE:
01077       return marshal_fixed_multi (str, insert_at, vp, n_elements, byte_order, 8, pos_after);
01078       break;
01079 
01080     default:
01081       _dbus_assert_not_reached ("non fixed type in array write");
01082       break;
01083     }
01084 
01085   return FALSE;
01086 }
01087 
01088 
01098 void
01099 _dbus_marshal_skip_basic (const DBusString      *str,
01100                           int                    type,
01101                           int                    byte_order,
01102                           int                   *pos)
01103 {
01104   _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
01105                 byte_order == DBUS_BIG_ENDIAN);
01106   
01107   switch (type)
01108     {
01109     case DBUS_TYPE_BYTE:
01110       (*pos)++;
01111       break;
01112     case DBUS_TYPE_INT16:
01113     case DBUS_TYPE_UINT16:
01114       *pos = _DBUS_ALIGN_VALUE (*pos, 2);
01115       *pos += 2;
01116       break;
01117     case DBUS_TYPE_BOOLEAN:
01118     case DBUS_TYPE_INT32:
01119     case DBUS_TYPE_UINT32:
01120     case DBUS_TYPE_UNIX_FD:
01121       *pos = _DBUS_ALIGN_VALUE (*pos, 4);
01122       *pos += 4;
01123       break;
01124     case DBUS_TYPE_INT64:
01125     case DBUS_TYPE_UINT64:
01126     case DBUS_TYPE_DOUBLE:
01127       *pos = _DBUS_ALIGN_VALUE (*pos, 8);
01128       *pos += 8;
01129       break;
01130     case DBUS_TYPE_STRING:
01131     case DBUS_TYPE_OBJECT_PATH:
01132       {
01133         int len;
01134 
01135         len = _dbus_marshal_read_uint32 (str, *pos, byte_order, pos);
01136         
01137         *pos += len + 1; /* length plus nul */
01138       }
01139       break;
01140     case DBUS_TYPE_SIGNATURE:
01141       {
01142         int len;
01143 
01144         len = _dbus_string_get_byte (str, *pos);
01145 
01146         *pos += len + 2; /* length byte plus length plus nul */
01147       }
01148       break;
01149     default:
01150       _dbus_warn ("type %s not a basic type\n",
01151                   _dbus_type_to_string (type));
01152       _dbus_assert_not_reached ("not a basic type");
01153       break;
01154     }
01155 }
01156 
01166 void
01167 _dbus_marshal_skip_array (const DBusString  *str,
01168                           int                element_type,
01169                           int                byte_order,
01170                           int               *pos)
01171 {
01172   dbus_uint32_t array_len;
01173   int i;
01174   int alignment;
01175 
01176   i = _DBUS_ALIGN_VALUE (*pos, 4);
01177 
01178   array_len = _dbus_marshal_read_uint32 (str, i, byte_order, &i);
01179 
01180   alignment = _dbus_type_get_alignment (element_type);
01181 
01182   i = _DBUS_ALIGN_VALUE (i, alignment);
01183 
01184   *pos = i + array_len;
01185 }
01186 
01194 int
01195 _dbus_type_get_alignment (int typecode)
01196 {
01197   switch (typecode)
01198     {
01199     case DBUS_TYPE_BYTE:
01200     case DBUS_TYPE_VARIANT:
01201     case DBUS_TYPE_SIGNATURE:
01202       return 1;
01203     case DBUS_TYPE_INT16:
01204     case DBUS_TYPE_UINT16:
01205       return 2;
01206     case DBUS_TYPE_BOOLEAN:
01207     case DBUS_TYPE_INT32:
01208     case DBUS_TYPE_UINT32:
01209     case DBUS_TYPE_UNIX_FD:
01210       /* this stuff is 4 since it starts with a length */
01211     case DBUS_TYPE_STRING:
01212     case DBUS_TYPE_OBJECT_PATH:
01213     case DBUS_TYPE_ARRAY:
01214       return 4;
01215     case DBUS_TYPE_INT64:
01216     case DBUS_TYPE_UINT64:
01217     case DBUS_TYPE_DOUBLE:
01218       /* struct is 8 since it could contain an 8-aligned item
01219        * and it's simpler to just always align structs to 8;
01220        * we want the amount of padding in a struct of a given
01221        * type to be predictable, not location-dependent.
01222        * DICT_ENTRY is always the same as struct.
01223        */
01224     case DBUS_TYPE_STRUCT:
01225     case DBUS_TYPE_DICT_ENTRY:
01226       return 8;
01227 
01228     default:
01229       _dbus_assert_not_reached ("unknown typecode in _dbus_type_get_alignment()");
01230       return 0;
01231     }
01232 }
01233 
01234 
01243 dbus_bool_t
01244 _dbus_type_is_valid (int typecode)
01245 {
01246   switch (typecode)
01247     {
01248     case DBUS_TYPE_BYTE:
01249     case DBUS_TYPE_BOOLEAN:
01250     case DBUS_TYPE_INT16:
01251     case DBUS_TYPE_UINT16:
01252     case DBUS_TYPE_INT32:
01253     case DBUS_TYPE_UINT32:
01254     case DBUS_TYPE_INT64:
01255     case DBUS_TYPE_UINT64:
01256     case DBUS_TYPE_DOUBLE:
01257     case DBUS_TYPE_STRING:
01258     case DBUS_TYPE_OBJECT_PATH:
01259     case DBUS_TYPE_SIGNATURE:
01260     case DBUS_TYPE_ARRAY:
01261     case DBUS_TYPE_STRUCT:
01262     case DBUS_TYPE_DICT_ENTRY:
01263     case DBUS_TYPE_VARIANT:
01264     case DBUS_TYPE_UNIX_FD:
01265       return TRUE;
01266 
01267     default:
01268       return FALSE;
01269     }
01270 }
01271 
01278 const char *
01279 _dbus_type_to_string (int typecode)
01280 {
01281   switch (typecode)
01282     {
01283     case DBUS_TYPE_INVALID:
01284       return "invalid";
01285     case DBUS_TYPE_BOOLEAN:
01286       return "boolean";
01287     case DBUS_TYPE_BYTE:
01288       return "byte";
01289     case DBUS_TYPE_INT16:
01290       return "int16";
01291     case DBUS_TYPE_UINT16:
01292       return "uint16";
01293     case DBUS_TYPE_INT32:
01294       return "int32";
01295     case DBUS_TYPE_UINT32:
01296       return "uint32";
01297     case DBUS_TYPE_INT64:
01298       return "int64";
01299     case DBUS_TYPE_UINT64:
01300       return "uint64";      
01301     case DBUS_TYPE_DOUBLE:
01302       return "double";
01303     case DBUS_TYPE_STRING:
01304       return "string";
01305     case DBUS_TYPE_OBJECT_PATH:
01306       return "object_path";
01307     case DBUS_TYPE_SIGNATURE:
01308       return "signature";
01309     case DBUS_TYPE_STRUCT:
01310       return "struct";
01311     case DBUS_TYPE_DICT_ENTRY:
01312       return "dict_entry";
01313     case DBUS_TYPE_ARRAY:
01314       return "array";
01315     case DBUS_TYPE_VARIANT:
01316       return "variant";
01317     case DBUS_STRUCT_BEGIN_CHAR:
01318       return "begin_struct";
01319     case DBUS_STRUCT_END_CHAR:
01320       return "end_struct";
01321     case DBUS_DICT_ENTRY_BEGIN_CHAR:
01322       return "begin_dict_entry";
01323     case DBUS_DICT_ENTRY_END_CHAR:
01324       return "end_dict_entry";
01325     case DBUS_TYPE_UNIX_FD:
01326       return "unix_fd";
01327     default:
01328       return "unknown";
01329     }
01330 }
01331 
01339 void
01340 _dbus_verbose_bytes (const unsigned char *data,
01341                      int                  len,
01342                      int                  offset)
01343 {
01344   int i;
01345   const unsigned char *aligned;
01346 
01347   _dbus_assert (len >= 0);
01348 
01349   if (!_dbus_is_verbose())
01350     return;
01351 
01352   /* Print blanks on first row if appropriate */
01353   aligned = _DBUS_ALIGN_ADDRESS (data, 4);
01354   if (aligned > data)
01355     aligned -= 4;
01356   _dbus_assert (aligned <= data);
01357 
01358   if (aligned != data)
01359     {
01360       _dbus_verbose ("%4ld\t%p: ", - (long)(data - aligned), aligned);
01361       while (aligned != data)
01362         {
01363           _dbus_verbose ("    ");
01364           ++aligned;
01365         }
01366     }
01367 
01368   /* now print the bytes */
01369   i = 0;
01370   while (i < len)
01371     {
01372       if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
01373         {
01374           _dbus_verbose ("%4d\t%p: ",
01375                          offset + i, &data[i]);
01376         }
01377 
01378       if (data[i] >= 32 &&
01379           data[i] <= 126)
01380         _dbus_verbose (" '%c' ", data[i]);
01381       else
01382         _dbus_verbose ("0x%s%x ",
01383                        data[i] <= 0xf ? "0" : "", data[i]);
01384 
01385       ++i;
01386 
01387       if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
01388         {
01389           if (i > 3)
01390             _dbus_verbose ("BE: %d LE: %d",
01391                            _dbus_unpack_uint32 (DBUS_BIG_ENDIAN, &data[i-4]),
01392                            _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN, &data[i-4]));
01393 
01394           if (i > 7 &&
01395               _DBUS_ALIGN_ADDRESS (&data[i], 8) == &data[i])
01396             {
01397 #ifdef DBUS_INT64_PRINTF_MODIFIER
01398               _dbus_verbose (" u64: 0x%" DBUS_INT64_PRINTF_MODIFIER "x",
01399                              *(dbus_uint64_t*)&data[i-8]);
01400 #endif
01401               _dbus_verbose (" dbl: %g",
01402                              *(double*)&data[i-8]);
01403             }
01404 
01405           _dbus_verbose ("\n");
01406         }
01407     }
01408 
01409   _dbus_verbose ("\n");
01410 }
01411 
01419 void
01420 _dbus_verbose_bytes_of_string (const DBusString    *str,
01421                                int                  start,
01422                                int                  len)
01423 {
01424   const char *d;
01425   int real_len;
01426 
01427   real_len = _dbus_string_get_length (str);
01428 
01429   _dbus_assert (start >= 0);
01430 
01431   if (start > real_len)
01432     {
01433       _dbus_verbose ("  [%d,%d) is not inside string of length %d\n",
01434                      start, len, real_len);
01435       return;
01436     }
01437 
01438   if ((start + len) > real_len)
01439     {
01440       _dbus_verbose ("  [%d,%d) extends outside string of length %d\n",
01441                      start, len, real_len);
01442       len = real_len - start;
01443     }
01444 
01445   d = _dbus_string_get_const_data_len (str, start, len);
01446 
01447   _dbus_verbose_bytes (d, len, start);
01448 }
01449 
01450 static int
01451 map_type_char_to_type (int t)
01452 {
01453   if (t == DBUS_STRUCT_BEGIN_CHAR)
01454     return DBUS_TYPE_STRUCT;
01455   else if (t == DBUS_DICT_ENTRY_BEGIN_CHAR)
01456     return DBUS_TYPE_DICT_ENTRY;
01457   else
01458     {
01459       _dbus_assert (t != DBUS_STRUCT_END_CHAR);
01460       _dbus_assert (t != DBUS_DICT_ENTRY_END_CHAR);
01461       return t;
01462     }
01463 }
01464 
01475 int
01476 _dbus_first_type_in_signature (const DBusString *str,
01477                                int               pos)
01478 {
01479   return map_type_char_to_type (_dbus_string_get_byte (str, pos));
01480 }
01481 
01490 int
01491 _dbus_first_type_in_signature_c_str (const char       *str,
01492                                      int               pos)
01493 {
01494   return map_type_char_to_type (str[pos]);
01495 }
01496 
01499 #ifdef DBUS_BUILD_TESTS
01500 #include "dbus-test.h"
01501 #include <stdio.h>
01502 
01521 void
01522 _dbus_marshal_read_fixed_multi  (const DBusString *str,
01523                                  int               pos,
01524                                  int               element_type,
01525                                  void             *value,
01526                                  int               n_elements,
01527                                  int               byte_order,
01528                                  int              *new_pos)
01529 {
01530   int array_len;
01531   int alignment;
01532 
01533   _dbus_assert (dbus_type_is_fixed (element_type));
01534   _dbus_assert (dbus_type_is_basic (element_type));
01535 
01536 #if 0
01537   _dbus_verbose ("reading %d elements of %s\n",
01538                  n_elements, _dbus_type_to_string (element_type));
01539 #endif
01540   
01541   alignment = _dbus_type_get_alignment (element_type);
01542 
01543   pos = _DBUS_ALIGN_VALUE (pos, alignment);
01544   
01545   array_len = n_elements * alignment;
01546 
01547   *(const DBusBasicValue**) value = (void*) _dbus_string_get_const_data_len (str, pos, array_len);
01548   if (new_pos)
01549     *new_pos = pos + array_len;
01550 }
01551 
01552 static void
01553 swap_test_array (void *array,
01554                  int   len_bytes,
01555                  int   byte_order,
01556                  int   alignment)
01557 {
01558   DBusString t;
01559 
01560   if (alignment == 1)
01561     return;
01562   
01563   _dbus_string_init_const_len (&t, array, len_bytes);
01564   swap_array (&t, 0, len_bytes / alignment, byte_order, alignment);
01565 }
01566 
01567 #define MARSHAL_BASIC(typename, byte_order, literal)                    \
01568   do {                                                                  \
01569      v_##typename = literal;                                            \
01570      if (!_dbus_marshal_write_basic (&str, pos, DBUS_TYPE_##typename,   \
01571                                     &v_##typename,                      \
01572                                     byte_order, NULL))                  \
01573        _dbus_assert_not_reached ("no memory");                          \
01574    } while (0)
01575 
01576 #define DEMARSHAL_BASIC(typename, byte_order)                                   \
01577   do {                                                                          \
01578     _dbus_marshal_read_basic (&str, pos, DBUS_TYPE_##typename, &v_##typename,   \
01579                               byte_order, &pos);                                \
01580   } while (0)
01581 
01582 #define DEMARSHAL_BASIC_AND_CHECK(typename, byte_order, literal)                        \
01583   do {                                                                                  \
01584     DEMARSHAL_BASIC (typename, byte_order);                                             \
01585     if (literal != v_##typename)                                                        \
01586       {                                                                                 \
01587         _dbus_verbose_bytes_of_string (&str, dump_pos,                                  \
01588                                      _dbus_string_get_length (&str) - dump_pos);        \
01589         _dbus_assert_not_reached ("demarshaled wrong value");                           \
01590       }                                                                                 \
01591   } while (0)
01592 
01593 #define MARSHAL_TEST(typename, byte_order, literal)             \
01594   do {                                                          \
01595     MARSHAL_BASIC (typename, byte_order, literal);              \
01596     dump_pos = pos;                                             \
01597     DEMARSHAL_BASIC_AND_CHECK (typename, byte_order, literal);  \
01598   } while (0)
01599 
01600 #define MARSHAL_TEST_STRCMP(typename, byte_order, literal)                              \
01601   do {                                                                                  \
01602     MARSHAL_BASIC (typename, byte_order, literal);                                      \
01603     dump_pos = pos;                                                                     \
01604     DEMARSHAL_BASIC (typename, byte_order);                                             \
01605     if (strcmp (literal, v_##typename) != 0)                                            \
01606       {                                                                                 \
01607         _dbus_verbose_bytes_of_string (&str, dump_pos,                                  \
01608                                        _dbus_string_get_length (&str) - dump_pos);      \
01609         _dbus_warn ("literal '%s'\nvalue  '%s'\n", literal, v_##typename);              \
01610         _dbus_assert_not_reached ("demarshaled wrong value");                           \
01611       }                                                                                 \
01612   } while (0)
01613 
01614 #define MARSHAL_FIXED_ARRAY(typename, byte_order, literal)                                      \
01615   do {                                                                                          \
01616      int next;                                                                                  \
01617      v_UINT32 = sizeof(literal);                                                                \
01618      if (!_dbus_marshal_write_basic (&str, pos, DBUS_TYPE_UINT32, &v_UINT32,                    \
01619                                      byte_order, &next))                                        \
01620        _dbus_assert_not_reached ("no memory");                                                  \
01621      v_ARRAY_##typename = literal;                                                              \
01622      if (!_dbus_marshal_write_fixed_multi (&str, next, DBUS_TYPE_##typename,                    \
01623                                            &v_ARRAY_##typename, _DBUS_N_ELEMENTS(literal),      \
01624                                            byte_order, NULL))                                   \
01625        _dbus_assert_not_reached ("no memory");                                                  \
01626    } while (0)
01627 
01628 #define DEMARSHAL_FIXED_ARRAY(typename, byte_order)                                             \
01629   do {                                                                                          \
01630     int next;                                                                                   \
01631     alignment = _dbus_type_get_alignment (DBUS_TYPE_##typename);                                \
01632     v_UINT32 = _dbus_marshal_read_uint32 (&str, dump_pos, byte_order, &next);                   \
01633     _dbus_marshal_read_fixed_multi (&str, next, DBUS_TYPE_##typename, &v_ARRAY_##typename,      \
01634                                     v_UINT32/alignment,                                         \
01635                                     byte_order, NULL);                                          \
01636     swap_test_array (v_ARRAY_##typename, v_UINT32,                                              \
01637                      byte_order, alignment);                                                    \
01638   } while (0)
01639 
01640 #define DEMARSHAL_FIXED_ARRAY_AND_CHECK(typename, byte_order, literal)                  \
01641   do {                                                                                  \
01642     DEMARSHAL_FIXED_ARRAY (typename, byte_order);                                       \
01643     if (memcmp (literal, v_ARRAY_##typename, sizeof (literal) != 0))                    \
01644       {                                                                                 \
01645         _dbus_verbose ("MARSHALED DATA\n");                                             \
01646         _dbus_verbose_bytes_of_string (&str, dump_pos,                                  \
01647                                       _dbus_string_get_length (&str) - dump_pos);       \
01648         _dbus_verbose ("LITERAL DATA\n");                                               \
01649         _dbus_verbose_bytes ((char*)literal, sizeof (literal), 0);                      \
01650         _dbus_verbose ("READ DATA\n");                                                  \
01651         _dbus_verbose_bytes ((char*)v_ARRAY_##typename, sizeof (literal), 0);           \
01652         _dbus_assert_not_reached ("demarshaled wrong fixed array value");               \
01653       }                                                                                 \
01654   } while (0)
01655 
01656 #define MARSHAL_TEST_FIXED_ARRAY(typename, byte_order, literal)         \
01657   do {                                                                  \
01658     MARSHAL_FIXED_ARRAY (typename, byte_order, literal);                \
01659     dump_pos = pos;                                                     \
01660     DEMARSHAL_FIXED_ARRAY_AND_CHECK (typename, byte_order, literal);    \
01661   } while (0)
01662 
01663 dbus_bool_t
01664 _dbus_marshal_test (void)
01665 {
01666   int alignment;
01667   DBusString str;
01668   int pos, dump_pos;
01669   unsigned char array1[5] = { 3, 4, 0, 1, 9 };
01670   dbus_int16_t array2[3] = { 124, 457, 780 };
01671   dbus_int32_t array4[3] = { 123, 456, 789 };
01672 #ifdef DBUS_HAVE_INT64
01673   dbus_int64_t array8[3] = { DBUS_INT64_CONSTANT (0x123ffffffff),
01674                              DBUS_INT64_CONSTANT (0x456ffffffff),
01675                              DBUS_INT64_CONSTANT (0x789ffffffff) };
01676   dbus_int64_t *v_ARRAY_INT64;
01677 #endif
01678   unsigned char *v_ARRAY_BYTE;
01679   dbus_int16_t *v_ARRAY_INT16;
01680   dbus_uint16_t *v_ARRAY_UINT16;
01681   dbus_int32_t *v_ARRAY_INT32;
01682   dbus_uint32_t *v_ARRAY_UINT32;
01683   DBusString t;
01684   double v_DOUBLE;
01685   double t_DOUBLE;
01686   dbus_int16_t v_INT16;
01687   dbus_uint16_t v_UINT16;
01688   dbus_int32_t v_INT32;
01689   dbus_uint32_t v_UINT32;
01690   dbus_int64_t v_INT64;
01691   dbus_uint64_t v_UINT64;
01692   unsigned char v_BYTE;
01693   dbus_bool_t v_BOOLEAN;
01694   const char *v_STRING;
01695   const char *v_SIGNATURE;
01696   const char *v_OBJECT_PATH;
01697   int byte_order;
01698 
01699   if (!_dbus_string_init (&str))
01700     _dbus_assert_not_reached ("failed to init string");
01701 
01702   pos = 0;
01703 
01704   /* Marshal doubles */
01705   MARSHAL_BASIC (DOUBLE, DBUS_BIG_ENDIAN, 3.14);
01706   DEMARSHAL_BASIC (DOUBLE, DBUS_BIG_ENDIAN);
01707   t_DOUBLE = 3.14;
01708   if (!_DBUS_DOUBLES_BITWISE_EQUAL (t_DOUBLE, v_DOUBLE))
01709     _dbus_assert_not_reached ("got wrong double value");
01710 
01711   MARSHAL_BASIC (DOUBLE, DBUS_LITTLE_ENDIAN, 3.14);
01712   DEMARSHAL_BASIC (DOUBLE, DBUS_LITTLE_ENDIAN);
01713   t_DOUBLE = 3.14;
01714   if (!_DBUS_DOUBLES_BITWISE_EQUAL (t_DOUBLE, v_DOUBLE))
01715     _dbus_assert_not_reached ("got wrong double value");
01716 
01717   /* Marshal signed 16 integers */
01718   MARSHAL_TEST (INT16, DBUS_BIG_ENDIAN, -12345);
01719   MARSHAL_TEST (INT16, DBUS_LITTLE_ENDIAN, -12345);
01720 
01721   /* Marshal unsigned 16 integers */
01722   MARSHAL_TEST (UINT16, DBUS_BIG_ENDIAN, 0x1234);
01723   MARSHAL_TEST (UINT16, DBUS_LITTLE_ENDIAN, 0x1234);
01724   
01725   /* Marshal signed integers */
01726   MARSHAL_TEST (INT32, DBUS_BIG_ENDIAN, -12345678);
01727   MARSHAL_TEST (INT32, DBUS_LITTLE_ENDIAN, -12345678);
01728 
01729   /* Marshal unsigned integers */
01730   MARSHAL_TEST (UINT32, DBUS_BIG_ENDIAN, 0x12345678);
01731   MARSHAL_TEST (UINT32, DBUS_LITTLE_ENDIAN, 0x12345678);
01732 
01733 #ifdef DBUS_HAVE_INT64
01734   /* Marshal signed integers */
01735   MARSHAL_TEST (INT64, DBUS_BIG_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7));
01736   MARSHAL_TEST (INT64, DBUS_LITTLE_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7));
01737 
01738   /* Marshal unsigned integers */
01739   MARSHAL_TEST (UINT64, DBUS_BIG_ENDIAN, DBUS_UINT64_CONSTANT (0x123456789abc7));
01740   MARSHAL_TEST (UINT64, DBUS_LITTLE_ENDIAN, DBUS_UINT64_CONSTANT (0x123456789abc7));
01741 #endif /* DBUS_HAVE_INT64 */
01742 
01743   /* Marshal byte */
01744   MARSHAL_TEST (BYTE, DBUS_BIG_ENDIAN, 5);
01745   MARSHAL_TEST (BYTE, DBUS_LITTLE_ENDIAN, 5);
01746 
01747   /* Marshal all possible bools! */
01748   MARSHAL_TEST (BOOLEAN, DBUS_BIG_ENDIAN, FALSE);
01749   MARSHAL_TEST (BOOLEAN, DBUS_LITTLE_ENDIAN, FALSE);
01750   MARSHAL_TEST (BOOLEAN, DBUS_BIG_ENDIAN, TRUE);
01751   MARSHAL_TEST (BOOLEAN, DBUS_LITTLE_ENDIAN, TRUE);
01752 
01753   /* Marshal strings */
01754   MARSHAL_TEST_STRCMP (STRING, DBUS_BIG_ENDIAN, "");
01755   MARSHAL_TEST_STRCMP (STRING, DBUS_LITTLE_ENDIAN, "");
01756   MARSHAL_TEST_STRCMP (STRING, DBUS_BIG_ENDIAN, "This is the dbus test string");
01757   MARSHAL_TEST_STRCMP (STRING, DBUS_LITTLE_ENDIAN, "This is the dbus test string");
01758 
01759   /* object paths */
01760   MARSHAL_TEST_STRCMP (OBJECT_PATH, DBUS_BIG_ENDIAN, "/a/b/c");
01761   MARSHAL_TEST_STRCMP (OBJECT_PATH, DBUS_LITTLE_ENDIAN, "/a/b/c");
01762 
01763   /* signatures */
01764   MARSHAL_TEST_STRCMP (SIGNATURE, DBUS_BIG_ENDIAN, "");
01765   MARSHAL_TEST_STRCMP (SIGNATURE, DBUS_LITTLE_ENDIAN, "");
01766   MARSHAL_TEST_STRCMP (SIGNATURE, DBUS_BIG_ENDIAN, "a(ii)");
01767   MARSHAL_TEST_STRCMP (SIGNATURE, DBUS_LITTLE_ENDIAN, "a(ii)");
01768 
01769   /* Arrays */
01770   MARSHAL_TEST_FIXED_ARRAY (INT16, DBUS_BIG_ENDIAN, array2);
01771   MARSHAL_TEST_FIXED_ARRAY (INT16, DBUS_LITTLE_ENDIAN, array2);
01772   MARSHAL_TEST_FIXED_ARRAY (UINT16, DBUS_BIG_ENDIAN, array2);
01773   MARSHAL_TEST_FIXED_ARRAY (UINT16, DBUS_LITTLE_ENDIAN, array2);
01774   
01775   MARSHAL_TEST_FIXED_ARRAY (INT32, DBUS_BIG_ENDIAN, array4);
01776   MARSHAL_TEST_FIXED_ARRAY (INT32, DBUS_LITTLE_ENDIAN, array4);
01777   MARSHAL_TEST_FIXED_ARRAY (UINT32, DBUS_BIG_ENDIAN, array4);
01778   MARSHAL_TEST_FIXED_ARRAY (UINT32, DBUS_LITTLE_ENDIAN, array4);
01779 
01780   MARSHAL_TEST_FIXED_ARRAY (BYTE, DBUS_BIG_ENDIAN, array1);
01781   MARSHAL_TEST_FIXED_ARRAY (BYTE, DBUS_LITTLE_ENDIAN, array1);
01782   
01783 #ifdef DBUS_HAVE_INT64
01784   MARSHAL_TEST_FIXED_ARRAY (INT64, DBUS_BIG_ENDIAN, array8);
01785   MARSHAL_TEST_FIXED_ARRAY (INT64, DBUS_LITTLE_ENDIAN, array8);
01786 #endif
01787 
01788 #if 0
01789 
01790   /*
01791    * FIXME restore the set/pack tests
01792    */
01793 
01794 #ifdef DBUS_HAVE_INT64
01795   /* set/pack 64-bit integers */
01796   _dbus_string_set_length (&str, 8);
01797 
01798   /* signed little */
01799   _dbus_marshal_set_int64 (&str, DBUS_LITTLE_ENDIAN,
01800                            0, DBUS_INT64_CONSTANT (-0x123456789abc7));
01801 
01802   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
01803                 _dbus_unpack_int64 (DBUS_LITTLE_ENDIAN,
01804                                     _dbus_string_get_const_data (&str)));
01805 
01806   /* signed big */
01807   _dbus_marshal_set_int64 (&str, DBUS_BIG_ENDIAN,
01808                            0, DBUS_INT64_CONSTANT (-0x123456789abc7));
01809 
01810   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
01811                 _dbus_unpack_int64 (DBUS_BIG_ENDIAN,
01812                                     _dbus_string_get_const_data (&str)));
01813 
01814   /* signed little pack */
01815   _dbus_pack_int64 (DBUS_INT64_CONSTANT (-0x123456789abc7),
01816                     DBUS_LITTLE_ENDIAN,
01817                     _dbus_string_get_data (&str));
01818 
01819   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
01820                 _dbus_unpack_int64 (DBUS_LITTLE_ENDIAN,
01821                                     _dbus_string_get_const_data (&str)));
01822 
01823   /* signed big pack */
01824   _dbus_pack_int64 (DBUS_INT64_CONSTANT (-0x123456789abc7),
01825                     DBUS_BIG_ENDIAN,
01826                     _dbus_string_get_data (&str));
01827 
01828   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
01829                 _dbus_unpack_int64 (DBUS_BIG_ENDIAN,
01830                                     _dbus_string_get_const_data (&str)));
01831 
01832   /* unsigned little */
01833   _dbus_marshal_set_uint64 (&str, DBUS_LITTLE_ENDIAN,
01834                             0, DBUS_UINT64_CONSTANT (0x123456789abc7));
01835 
01836   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
01837                 _dbus_unpack_uint64 (DBUS_LITTLE_ENDIAN,
01838                                      _dbus_string_get_const_data (&str)));
01839 
01840   /* unsigned big */
01841   _dbus_marshal_set_uint64 (&str, DBUS_BIG_ENDIAN,
01842                             0, DBUS_UINT64_CONSTANT (0x123456789abc7));
01843 
01844   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
01845                 _dbus_unpack_uint64 (DBUS_BIG_ENDIAN,
01846                                      _dbus_string_get_const_data (&str)));
01847 
01848   /* unsigned little pack */
01849   _dbus_pack_uint64 (DBUS_UINT64_CONSTANT (0x123456789abc7),
01850                      DBUS_LITTLE_ENDIAN,
01851                      _dbus_string_get_data (&str));
01852 
01853   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
01854                 _dbus_unpack_uint64 (DBUS_LITTLE_ENDIAN,
01855                                      _dbus_string_get_const_data (&str)));
01856 
01857   /* unsigned big pack */
01858   _dbus_pack_uint64 (DBUS_UINT64_CONSTANT (0x123456789abc7),
01859                      DBUS_BIG_ENDIAN,
01860                      _dbus_string_get_data (&str));
01861 
01862   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
01863                 _dbus_unpack_uint64 (DBUS_BIG_ENDIAN,
01864                                      _dbus_string_get_const_data (&str)));
01865 #endif /* DBUS_HAVE_INT64 */
01866 
01867   /* set/pack 32-bit integers */
01868   _dbus_string_set_length (&str, 4);
01869 
01870   /* signed little */
01871   _dbus_marshal_set_int32 (&str, DBUS_LITTLE_ENDIAN,
01872                            0, -0x123456);
01873 
01874   _dbus_assert (-0x123456 ==
01875                 _dbus_unpack_int32 (DBUS_LITTLE_ENDIAN,
01876                                     _dbus_string_get_const_data (&str)));
01877 
01878   /* signed big */
01879   _dbus_marshal_set_int32 (&str, DBUS_BIG_ENDIAN,
01880                            0, -0x123456);
01881 
01882   _dbus_assert (-0x123456 ==
01883                 _dbus_unpack_int32 (DBUS_BIG_ENDIAN,
01884                                     _dbus_string_get_const_data (&str)));
01885 
01886   /* signed little pack */
01887   _dbus_pack_int32 (-0x123456,
01888                     DBUS_LITTLE_ENDIAN,
01889                     _dbus_string_get_data (&str));
01890 
01891   _dbus_assert (-0x123456 ==
01892                 _dbus_unpack_int32 (DBUS_LITTLE_ENDIAN,
01893                                     _dbus_string_get_const_data (&str)));
01894 
01895   /* signed big pack */
01896   _dbus_pack_int32 (-0x123456,
01897                     DBUS_BIG_ENDIAN,
01898                     _dbus_string_get_data (&str));
01899 
01900   _dbus_assert (-0x123456 ==
01901                 _dbus_unpack_int32 (DBUS_BIG_ENDIAN,
01902                                     _dbus_string_get_const_data (&str)));
01903 
01904   /* unsigned little */
01905   _dbus_marshal_set_uint32 (&str,
01906                             0, 0x123456,
01907                             DBUS_LITTLE_ENDIAN);
01908 
01909   _dbus_assert (0x123456 ==
01910                 _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN,
01911                                      _dbus_string_get_const_data (&str)));
01912 
01913   /* unsigned big */
01914   _dbus_marshal_set_uint32 (&str,
01915                             0, 0x123456,
01916                             DBUS_BIG_ENDIAN);
01917 
01918   _dbus_assert (0x123456 ==
01919                 _dbus_unpack_uint32 (DBUS_BIG_ENDIAN,
01920                                      _dbus_string_get_const_data (&str)));
01921 
01922   /* unsigned little pack */
01923   _dbus_pack_uint32 (0x123456,
01924                      DBUS_LITTLE_ENDIAN,
01925                      _dbus_string_get_data (&str));
01926 
01927   _dbus_assert (0x123456 ==
01928                 _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN,
01929                                      _dbus_string_get_const_data (&str)));
01930 
01931   /* unsigned big pack */
01932   _dbus_pack_uint32 (0x123456,
01933                      DBUS_BIG_ENDIAN,
01934                      _dbus_string_get_data (&str));
01935 
01936   _dbus_assert (0x123456 ==
01937                 _dbus_unpack_uint32 (DBUS_BIG_ENDIAN,
01938                                      _dbus_string_get_const_data (&str)));
01939 
01940 #endif /* set/pack tests for integers */
01941 
01942   /* Strings in-place set */
01943   byte_order = DBUS_LITTLE_ENDIAN;
01944   while (TRUE)
01945     {
01946       /* Init a string */
01947       _dbus_string_set_length (&str, 0);
01948 
01949       /* reset pos for the macros */
01950       pos = 0;
01951 
01952       MARSHAL_TEST_STRCMP (STRING, byte_order, "Hello world");
01953 
01954       /* Set it to something longer */
01955       _dbus_string_init_const (&t, "Hello world foo");
01956 
01957       v_STRING = _dbus_string_get_const_data (&t);
01958       _dbus_marshal_set_basic (&str, 0, DBUS_TYPE_STRING,
01959                                &v_STRING, byte_order, NULL, NULL);
01960 
01961       _dbus_marshal_read_basic (&str, 0, DBUS_TYPE_STRING,
01962                                 &v_STRING, byte_order,
01963                                 NULL);
01964       _dbus_assert (strcmp (v_STRING, "Hello world foo") == 0);
01965 
01966       /* Set it to something shorter */
01967       _dbus_string_init_const (&t, "Hello");
01968 
01969       v_STRING = _dbus_string_get_const_data (&t);
01970       _dbus_marshal_set_basic (&str, 0, DBUS_TYPE_STRING,
01971                                &v_STRING, byte_order, NULL, NULL);
01972       _dbus_marshal_read_basic (&str, 0, DBUS_TYPE_STRING,
01973                                 &v_STRING, byte_order,
01974                                 NULL);
01975       _dbus_assert (strcmp (v_STRING, "Hello") == 0);
01976 
01977       /* Do the other byte order */
01978       if (byte_order == DBUS_LITTLE_ENDIAN)
01979         byte_order = DBUS_BIG_ENDIAN;
01980       else
01981         break;
01982     }
01983 
01984   /* Clean up */
01985   _dbus_string_free (&str);
01986 
01987   return TRUE;
01988 }
01989 
01990 #endif /* DBUS_BUILD_TESTS */