• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List

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       /* FIXME: we canonicalize to 0 or 1 for the single boolean case
01069        * should we here too ? */
01070     case DBUS_TYPE_BOOLEAN:
01071     case DBUS_TYPE_INT32:
01072     case DBUS_TYPE_UINT32:
01073     case DBUS_TYPE_UNIX_FD:
01074       return marshal_fixed_multi (str, insert_at, vp, n_elements, byte_order, 4, pos_after);
01075       break;
01076     case DBUS_TYPE_INT64:
01077     case DBUS_TYPE_UINT64:
01078     case DBUS_TYPE_DOUBLE:
01079       return marshal_fixed_multi (str, insert_at, vp, n_elements, byte_order, 8, pos_after);
01080       break;
01081 
01082     default:
01083       _dbus_assert_not_reached ("non fixed type in array write");
01084       break;
01085     }
01086 
01087   return FALSE;
01088 }
01089 
01090 
01100 void
01101 _dbus_marshal_skip_basic (const DBusString      *str,
01102                           int                    type,
01103                           int                    byte_order,
01104                           int                   *pos)
01105 {
01106   _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
01107                 byte_order == DBUS_BIG_ENDIAN);
01108   
01109   switch (type)
01110     {
01111     case DBUS_TYPE_BYTE:
01112       (*pos)++;
01113       break;
01114     case DBUS_TYPE_INT16:
01115     case DBUS_TYPE_UINT16:
01116       *pos = _DBUS_ALIGN_VALUE (*pos, 2);
01117       *pos += 2;
01118       break;
01119     case DBUS_TYPE_BOOLEAN:
01120     case DBUS_TYPE_INT32:
01121     case DBUS_TYPE_UINT32:
01122     case DBUS_TYPE_UNIX_FD:
01123       *pos = _DBUS_ALIGN_VALUE (*pos, 4);
01124       *pos += 4;
01125       break;
01126     case DBUS_TYPE_INT64:
01127     case DBUS_TYPE_UINT64:
01128     case DBUS_TYPE_DOUBLE:
01129       *pos = _DBUS_ALIGN_VALUE (*pos, 8);
01130       *pos += 8;
01131       break;
01132     case DBUS_TYPE_STRING:
01133     case DBUS_TYPE_OBJECT_PATH:
01134       {
01135         int len;
01136 
01137         len = _dbus_marshal_read_uint32 (str, *pos, byte_order, pos);
01138         
01139         *pos += len + 1; /* length plus nul */
01140       }
01141       break;
01142     case DBUS_TYPE_SIGNATURE:
01143       {
01144         int len;
01145 
01146         len = _dbus_string_get_byte (str, *pos);
01147 
01148         *pos += len + 2; /* length byte plus length plus nul */
01149       }
01150       break;
01151     default:
01152       _dbus_warn ("type %s not a basic type\n",
01153                   _dbus_type_to_string (type));
01154       _dbus_assert_not_reached ("not a basic type");
01155       break;
01156     }
01157 }
01158 
01168 void
01169 _dbus_marshal_skip_array (const DBusString  *str,
01170                           int                element_type,
01171                           int                byte_order,
01172                           int               *pos)
01173 {
01174   dbus_uint32_t array_len;
01175   int i;
01176   int alignment;
01177 
01178   i = _DBUS_ALIGN_VALUE (*pos, 4);
01179 
01180   array_len = _dbus_marshal_read_uint32 (str, i, byte_order, &i);
01181 
01182   alignment = _dbus_type_get_alignment (element_type);
01183 
01184   i = _DBUS_ALIGN_VALUE (i, alignment);
01185 
01186   *pos = i + array_len;
01187 }
01188 
01196 int
01197 _dbus_type_get_alignment (int typecode)
01198 {
01199   switch (typecode)
01200     {
01201     case DBUS_TYPE_BYTE:
01202     case DBUS_TYPE_VARIANT:
01203     case DBUS_TYPE_SIGNATURE:
01204       return 1;
01205     case DBUS_TYPE_INT16:
01206     case DBUS_TYPE_UINT16:
01207       return 2;
01208     case DBUS_TYPE_BOOLEAN:
01209     case DBUS_TYPE_INT32:
01210     case DBUS_TYPE_UINT32:
01211     case DBUS_TYPE_UNIX_FD:
01212       /* this stuff is 4 since it starts with a length */
01213     case DBUS_TYPE_STRING:
01214     case DBUS_TYPE_OBJECT_PATH:
01215     case DBUS_TYPE_ARRAY:
01216       return 4;
01217     case DBUS_TYPE_INT64:
01218     case DBUS_TYPE_UINT64:
01219     case DBUS_TYPE_DOUBLE:
01220       /* struct is 8 since it could contain an 8-aligned item
01221        * and it's simpler to just always align structs to 8;
01222        * we want the amount of padding in a struct of a given
01223        * type to be predictable, not location-dependent.
01224        * DICT_ENTRY is always the same as struct.
01225        */
01226     case DBUS_TYPE_STRUCT:
01227     case DBUS_TYPE_DICT_ENTRY:
01228       return 8;
01229 
01230     default:
01231       _dbus_assert_not_reached ("unknown typecode in _dbus_type_get_alignment()");
01232       return 0;
01233     }
01234 }
01235 
01236 
01245 dbus_bool_t
01246 _dbus_type_is_valid (int typecode)
01247 {
01248   switch (typecode)
01249     {
01250     case DBUS_TYPE_BYTE:
01251     case DBUS_TYPE_BOOLEAN:
01252     case DBUS_TYPE_INT16:
01253     case DBUS_TYPE_UINT16:
01254     case DBUS_TYPE_INT32:
01255     case DBUS_TYPE_UINT32:
01256     case DBUS_TYPE_INT64:
01257     case DBUS_TYPE_UINT64:
01258     case DBUS_TYPE_DOUBLE:
01259     case DBUS_TYPE_STRING:
01260     case DBUS_TYPE_OBJECT_PATH:
01261     case DBUS_TYPE_SIGNATURE:
01262     case DBUS_TYPE_ARRAY:
01263     case DBUS_TYPE_STRUCT:
01264     case DBUS_TYPE_DICT_ENTRY:
01265     case DBUS_TYPE_VARIANT:
01266     case DBUS_TYPE_UNIX_FD:
01267       return TRUE;
01268 
01269     default:
01270       return FALSE;
01271     }
01272 }
01273 
01280 const char *
01281 _dbus_type_to_string (int typecode)
01282 {
01283   switch (typecode)
01284     {
01285     case DBUS_TYPE_INVALID:
01286       return "invalid";
01287     case DBUS_TYPE_BOOLEAN:
01288       return "boolean";
01289     case DBUS_TYPE_BYTE:
01290       return "byte";
01291     case DBUS_TYPE_INT16:
01292       return "int16";
01293     case DBUS_TYPE_UINT16:
01294       return "uint16";
01295     case DBUS_TYPE_INT32:
01296       return "int32";
01297     case DBUS_TYPE_UINT32:
01298       return "uint32";
01299     case DBUS_TYPE_INT64:
01300       return "int64";
01301     case DBUS_TYPE_UINT64:
01302       return "uint64";      
01303     case DBUS_TYPE_DOUBLE:
01304       return "double";
01305     case DBUS_TYPE_STRING:
01306       return "string";
01307     case DBUS_TYPE_OBJECT_PATH:
01308       return "object_path";
01309     case DBUS_TYPE_SIGNATURE:
01310       return "signature";
01311     case DBUS_TYPE_STRUCT:
01312       return "struct";
01313     case DBUS_TYPE_DICT_ENTRY:
01314       return "dict_entry";
01315     case DBUS_TYPE_ARRAY:
01316       return "array";
01317     case DBUS_TYPE_VARIANT:
01318       return "variant";
01319     case DBUS_STRUCT_BEGIN_CHAR:
01320       return "begin_struct";
01321     case DBUS_STRUCT_END_CHAR:
01322       return "end_struct";
01323     case DBUS_DICT_ENTRY_BEGIN_CHAR:
01324       return "begin_dict_entry";
01325     case DBUS_DICT_ENTRY_END_CHAR:
01326       return "end_dict_entry";
01327     case DBUS_TYPE_UNIX_FD:
01328       return "unix_fd";
01329     default:
01330       return "unknown";
01331     }
01332 }
01333 
01341 void
01342 _dbus_verbose_bytes (const unsigned char *data,
01343                      int                  len,
01344                      int                  offset)
01345 {
01346   int i;
01347   const unsigned char *aligned;
01348 
01349   _dbus_assert (len >= 0);
01350 
01351   if (!_dbus_is_verbose())
01352     return;
01353 
01354   /* Print blanks on first row if appropriate */
01355   aligned = _DBUS_ALIGN_ADDRESS (data, 4);
01356   if (aligned > data)
01357     aligned -= 4;
01358   _dbus_assert (aligned <= data);
01359 
01360   if (aligned != data)
01361     {
01362       _dbus_verbose ("%4ld\t%p: ", - (long)(data - aligned), aligned);
01363       while (aligned != data)
01364         {
01365           _dbus_verbose ("    ");
01366           ++aligned;
01367         }
01368     }
01369 
01370   /* now print the bytes */
01371   i = 0;
01372   while (i < len)
01373     {
01374       if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
01375         {
01376           _dbus_verbose ("%4d\t%p: ",
01377                          offset + i, &data[i]);
01378         }
01379 
01380       if (data[i] >= 32 &&
01381           data[i] <= 126)
01382         _dbus_verbose (" '%c' ", data[i]);
01383       else
01384         _dbus_verbose ("0x%s%x ",
01385                        data[i] <= 0xf ? "0" : "", data[i]);
01386 
01387       ++i;
01388 
01389       if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
01390         {
01391           if (i > 3)
01392             _dbus_verbose ("BE: %d LE: %d",
01393                            _dbus_unpack_uint32 (DBUS_BIG_ENDIAN, &data[i-4]),
01394                            _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN, &data[i-4]));
01395 
01396           if (i > 7 &&
01397               _DBUS_ALIGN_ADDRESS (&data[i], 8) == &data[i])
01398             {
01399 #ifdef DBUS_INT64_PRINTF_MODIFIER
01400               _dbus_verbose (" u64: 0x%" DBUS_INT64_PRINTF_MODIFIER "x",
01401                              *(dbus_uint64_t*)&data[i-8]);
01402 #endif
01403               _dbus_verbose (" dbl: %g",
01404                              *(double*)&data[i-8]);
01405             }
01406 
01407           _dbus_verbose ("\n");
01408         }
01409     }
01410 
01411   _dbus_verbose ("\n");
01412 }
01413 
01421 void
01422 _dbus_verbose_bytes_of_string (const DBusString    *str,
01423                                int                  start,
01424                                int                  len)
01425 {
01426   const char *d;
01427   int real_len;
01428 
01429   real_len = _dbus_string_get_length (str);
01430 
01431   _dbus_assert (start >= 0);
01432 
01433   if (start > real_len)
01434     {
01435       _dbus_verbose ("  [%d,%d) is not inside string of length %d\n",
01436                      start, len, real_len);
01437       return;
01438     }
01439 
01440   if ((start + len) > real_len)
01441     {
01442       _dbus_verbose ("  [%d,%d) extends outside string of length %d\n",
01443                      start, len, real_len);
01444       len = real_len - start;
01445     }
01446 
01447   d = _dbus_string_get_const_data_len (str, start, len);
01448 
01449   _dbus_verbose_bytes (d, len, start);
01450 }
01451 
01452 static int
01453 map_type_char_to_type (int t)
01454 {
01455   if (t == DBUS_STRUCT_BEGIN_CHAR)
01456     return DBUS_TYPE_STRUCT;
01457   else if (t == DBUS_DICT_ENTRY_BEGIN_CHAR)
01458     return DBUS_TYPE_DICT_ENTRY;
01459   else
01460     {
01461       _dbus_assert (t != DBUS_STRUCT_END_CHAR);
01462       _dbus_assert (t != DBUS_DICT_ENTRY_END_CHAR);
01463       return t;
01464     }
01465 }
01466 
01477 int
01478 _dbus_first_type_in_signature (const DBusString *str,
01479                                int               pos)
01480 {
01481   return map_type_char_to_type (_dbus_string_get_byte (str, pos));
01482 }
01483 
01492 int
01493 _dbus_first_type_in_signature_c_str (const char       *str,
01494                                      int               pos)
01495 {
01496   return map_type_char_to_type (str[pos]);
01497 }
01498 
01501 #ifdef DBUS_BUILD_TESTS
01502 #include "dbus-test.h"
01503 #include <stdio.h>
01504 
01523 void
01524 _dbus_marshal_read_fixed_multi  (const DBusString *str,
01525                                  int               pos,
01526                                  int               element_type,
01527                                  void             *value,
01528                                  int               n_elements,
01529                                  int               byte_order,
01530                                  int              *new_pos)
01531 {
01532   int array_len;
01533   int alignment;
01534 
01535   _dbus_assert (dbus_type_is_fixed (element_type));
01536   _dbus_assert (dbus_type_is_basic (element_type));
01537 
01538 #if 0
01539   _dbus_verbose ("reading %d elements of %s\n",
01540                  n_elements, _dbus_type_to_string (element_type));
01541 #endif
01542   
01543   alignment = _dbus_type_get_alignment (element_type);
01544 
01545   pos = _DBUS_ALIGN_VALUE (pos, alignment);
01546   
01547   array_len = n_elements * alignment;
01548 
01549   *(const DBusBasicValue**) value = (void*) _dbus_string_get_const_data_len (str, pos, array_len);
01550   if (new_pos)
01551     *new_pos = pos + array_len;
01552 }
01553 
01554 static void
01555 swap_test_array (void *array,
01556                  int   len_bytes,
01557                  int   byte_order,
01558                  int   alignment)
01559 {
01560   DBusString t;
01561 
01562   if (alignment == 1)
01563     return;
01564   
01565   _dbus_string_init_const_len (&t, array, len_bytes);
01566   swap_array (&t, 0, len_bytes / alignment, byte_order, alignment);
01567 }
01568 
01569 #define MARSHAL_BASIC(typename, byte_order, literal)                    \
01570   do {                                                                  \
01571      v_##typename = literal;                                            \
01572      if (!_dbus_marshal_write_basic (&str, pos, DBUS_TYPE_##typename,   \
01573                                     &v_##typename,                      \
01574                                     byte_order, NULL))                  \
01575        _dbus_assert_not_reached ("no memory");                          \
01576    } while (0)
01577 
01578 #define DEMARSHAL_BASIC(typename, byte_order)                                   \
01579   do {                                                                          \
01580     _dbus_marshal_read_basic (&str, pos, DBUS_TYPE_##typename, &v_##typename,   \
01581                               byte_order, &pos);                                \
01582   } while (0)
01583 
01584 #define DEMARSHAL_BASIC_AND_CHECK(typename, byte_order, literal)                        \
01585   do {                                                                                  \
01586     DEMARSHAL_BASIC (typename, byte_order);                                             \
01587     if (literal != v_##typename)                                                        \
01588       {                                                                                 \
01589         _dbus_verbose_bytes_of_string (&str, dump_pos,                                  \
01590                                      _dbus_string_get_length (&str) - dump_pos);        \
01591         _dbus_assert_not_reached ("demarshaled wrong value");                           \
01592       }                                                                                 \
01593   } while (0)
01594 
01595 #define MARSHAL_TEST(typename, byte_order, literal)             \
01596   do {                                                          \
01597     MARSHAL_BASIC (typename, byte_order, literal);              \
01598     dump_pos = pos;                                             \
01599     DEMARSHAL_BASIC_AND_CHECK (typename, byte_order, literal);  \
01600   } while (0)
01601 
01602 #define MARSHAL_TEST_STRCMP(typename, byte_order, literal)                              \
01603   do {                                                                                  \
01604     MARSHAL_BASIC (typename, byte_order, literal);                                      \
01605     dump_pos = pos;                                                                     \
01606     DEMARSHAL_BASIC (typename, byte_order);                                             \
01607     if (strcmp (literal, v_##typename) != 0)                                            \
01608       {                                                                                 \
01609         _dbus_verbose_bytes_of_string (&str, dump_pos,                                  \
01610                                        _dbus_string_get_length (&str) - dump_pos);      \
01611         _dbus_warn ("literal '%s'\nvalue  '%s'\n", literal, v_##typename);              \
01612         _dbus_assert_not_reached ("demarshaled wrong value");                           \
01613       }                                                                                 \
01614   } while (0)
01615 
01616 #define MARSHAL_FIXED_ARRAY(typename, byte_order, literal)                                      \
01617   do {                                                                                          \
01618      int next;                                                                                  \
01619      v_UINT32 = sizeof(literal);                                                                \
01620      if (!_dbus_marshal_write_basic (&str, pos, DBUS_TYPE_UINT32, &v_UINT32,                    \
01621                                      byte_order, &next))                                        \
01622        _dbus_assert_not_reached ("no memory");                                                  \
01623      v_ARRAY_##typename = literal;                                                              \
01624      if (!_dbus_marshal_write_fixed_multi (&str, next, DBUS_TYPE_##typename,                    \
01625                                            &v_ARRAY_##typename, _DBUS_N_ELEMENTS(literal),      \
01626                                            byte_order, NULL))                                   \
01627        _dbus_assert_not_reached ("no memory");                                                  \
01628    } while (0)
01629 
01630 #define DEMARSHAL_FIXED_ARRAY(typename, byte_order)                                             \
01631   do {                                                                                          \
01632     int next;                                                                                   \
01633     alignment = _dbus_type_get_alignment (DBUS_TYPE_##typename);                                \
01634     v_UINT32 = _dbus_marshal_read_uint32 (&str, dump_pos, byte_order, &next);                   \
01635     _dbus_marshal_read_fixed_multi (&str, next, DBUS_TYPE_##typename, &v_ARRAY_##typename,      \
01636                                     v_UINT32/alignment,                                         \
01637                                     byte_order, NULL);                                          \
01638     swap_test_array (v_ARRAY_##typename, v_UINT32,                                              \
01639                      byte_order, alignment);                                                    \
01640   } while (0)
01641 
01642 #define DEMARSHAL_FIXED_ARRAY_AND_CHECK(typename, byte_order, literal)                  \
01643   do {                                                                                  \
01644     DEMARSHAL_FIXED_ARRAY (typename, byte_order);                                       \
01645     if (memcmp (literal, v_ARRAY_##typename, sizeof (literal) != 0))                    \
01646       {                                                                                 \
01647         _dbus_verbose ("MARSHALED DATA\n");                                             \
01648         _dbus_verbose_bytes_of_string (&str, dump_pos,                                  \
01649                                       _dbus_string_get_length (&str) - dump_pos);       \
01650         _dbus_verbose ("LITERAL DATA\n");                                               \
01651         _dbus_verbose_bytes ((char*)literal, sizeof (literal), 0);                      \
01652         _dbus_verbose ("READ DATA\n");                                                  \
01653         _dbus_verbose_bytes ((char*)v_ARRAY_##typename, sizeof (literal), 0);           \
01654         _dbus_assert_not_reached ("demarshaled wrong fixed array value");               \
01655       }                                                                                 \
01656   } while (0)
01657 
01658 #define MARSHAL_TEST_FIXED_ARRAY(typename, byte_order, literal)         \
01659   do {                                                                  \
01660     MARSHAL_FIXED_ARRAY (typename, byte_order, literal);                \
01661     dump_pos = pos;                                                     \
01662     DEMARSHAL_FIXED_ARRAY_AND_CHECK (typename, byte_order, literal);    \
01663   } while (0)
01664 
01665 dbus_bool_t
01666 _dbus_marshal_test (void)
01667 {
01668   int alignment;
01669   DBusString str;
01670   int pos, dump_pos;
01671   unsigned char array1[5] = { 3, 4, 0, 1, 9 };
01672   dbus_int16_t array2[3] = { 124, 457, 780 };
01673   dbus_int32_t array4[3] = { 123, 456, 789 };
01674 #ifdef DBUS_HAVE_INT64
01675   dbus_int64_t array8[3] = { DBUS_INT64_CONSTANT (0x123ffffffff),
01676                              DBUS_INT64_CONSTANT (0x456ffffffff),
01677                              DBUS_INT64_CONSTANT (0x789ffffffff) };
01678   dbus_int64_t *v_ARRAY_INT64;
01679 #endif
01680   unsigned char *v_ARRAY_BYTE;
01681   dbus_int16_t *v_ARRAY_INT16;
01682   dbus_uint16_t *v_ARRAY_UINT16;
01683   dbus_int32_t *v_ARRAY_INT32;
01684   dbus_uint32_t *v_ARRAY_UINT32;
01685   DBusString t;
01686   double v_DOUBLE;
01687   double t_DOUBLE;
01688   dbus_int16_t v_INT16;
01689   dbus_uint16_t v_UINT16;
01690   dbus_int32_t v_INT32;
01691   dbus_uint32_t v_UINT32;
01692   dbus_int64_t v_INT64;
01693   dbus_uint64_t v_UINT64;
01694   unsigned char v_BYTE;
01695   dbus_bool_t v_BOOLEAN;
01696   const char *v_STRING;
01697   const char *v_SIGNATURE;
01698   const char *v_OBJECT_PATH;
01699   int byte_order;
01700 
01701   if (!_dbus_string_init (&str))
01702     _dbus_assert_not_reached ("failed to init string");
01703 
01704   pos = 0;
01705 
01706   /* Marshal doubles */
01707   MARSHAL_BASIC (DOUBLE, DBUS_BIG_ENDIAN, 3.14);
01708   DEMARSHAL_BASIC (DOUBLE, DBUS_BIG_ENDIAN);
01709   t_DOUBLE = 3.14;
01710   if (!_DBUS_DOUBLES_BITWISE_EQUAL (t_DOUBLE, v_DOUBLE))
01711     _dbus_assert_not_reached ("got wrong double value");
01712 
01713   MARSHAL_BASIC (DOUBLE, DBUS_LITTLE_ENDIAN, 3.14);
01714   DEMARSHAL_BASIC (DOUBLE, DBUS_LITTLE_ENDIAN);
01715   t_DOUBLE = 3.14;
01716   if (!_DBUS_DOUBLES_BITWISE_EQUAL (t_DOUBLE, v_DOUBLE))
01717     _dbus_assert_not_reached ("got wrong double value");
01718 
01719   /* Marshal signed 16 integers */
01720   MARSHAL_TEST (INT16, DBUS_BIG_ENDIAN, -12345);
01721   MARSHAL_TEST (INT16, DBUS_LITTLE_ENDIAN, -12345);
01722 
01723   /* Marshal unsigned 16 integers */
01724   MARSHAL_TEST (UINT16, DBUS_BIG_ENDIAN, 0x1234);
01725   MARSHAL_TEST (UINT16, DBUS_LITTLE_ENDIAN, 0x1234);
01726   
01727   /* Marshal signed integers */
01728   MARSHAL_TEST (INT32, DBUS_BIG_ENDIAN, -12345678);
01729   MARSHAL_TEST (INT32, DBUS_LITTLE_ENDIAN, -12345678);
01730 
01731   /* Marshal unsigned integers */
01732   MARSHAL_TEST (UINT32, DBUS_BIG_ENDIAN, 0x12345678);
01733   MARSHAL_TEST (UINT32, DBUS_LITTLE_ENDIAN, 0x12345678);
01734 
01735 #ifdef DBUS_HAVE_INT64
01736   /* Marshal signed integers */
01737   MARSHAL_TEST (INT64, DBUS_BIG_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7));
01738   MARSHAL_TEST (INT64, DBUS_LITTLE_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7));
01739 
01740   /* Marshal unsigned integers */
01741   MARSHAL_TEST (UINT64, DBUS_BIG_ENDIAN, DBUS_UINT64_CONSTANT (0x123456789abc7));
01742   MARSHAL_TEST (UINT64, DBUS_LITTLE_ENDIAN, DBUS_UINT64_CONSTANT (0x123456789abc7));
01743 #endif /* DBUS_HAVE_INT64 */
01744 
01745   /* Marshal byte */
01746   MARSHAL_TEST (BYTE, DBUS_BIG_ENDIAN, 5);
01747   MARSHAL_TEST (BYTE, DBUS_LITTLE_ENDIAN, 5);
01748 
01749   /* Marshal all possible bools! */
01750   MARSHAL_TEST (BOOLEAN, DBUS_BIG_ENDIAN, FALSE);
01751   MARSHAL_TEST (BOOLEAN, DBUS_LITTLE_ENDIAN, FALSE);
01752   MARSHAL_TEST (BOOLEAN, DBUS_BIG_ENDIAN, TRUE);
01753   MARSHAL_TEST (BOOLEAN, DBUS_LITTLE_ENDIAN, TRUE);
01754 
01755   /* Marshal strings */
01756   MARSHAL_TEST_STRCMP (STRING, DBUS_BIG_ENDIAN, "");
01757   MARSHAL_TEST_STRCMP (STRING, DBUS_LITTLE_ENDIAN, "");
01758   MARSHAL_TEST_STRCMP (STRING, DBUS_BIG_ENDIAN, "This is the dbus test string");
01759   MARSHAL_TEST_STRCMP (STRING, DBUS_LITTLE_ENDIAN, "This is the dbus test string");
01760 
01761   /* object paths */
01762   MARSHAL_TEST_STRCMP (OBJECT_PATH, DBUS_BIG_ENDIAN, "/a/b/c");
01763   MARSHAL_TEST_STRCMP (OBJECT_PATH, DBUS_LITTLE_ENDIAN, "/a/b/c");
01764 
01765   /* signatures */
01766   MARSHAL_TEST_STRCMP (SIGNATURE, DBUS_BIG_ENDIAN, "");
01767   MARSHAL_TEST_STRCMP (SIGNATURE, DBUS_LITTLE_ENDIAN, "");
01768   MARSHAL_TEST_STRCMP (SIGNATURE, DBUS_BIG_ENDIAN, "a(ii)");
01769   MARSHAL_TEST_STRCMP (SIGNATURE, DBUS_LITTLE_ENDIAN, "a(ii)");
01770 
01771   /* Arrays */
01772   MARSHAL_TEST_FIXED_ARRAY (INT16, DBUS_BIG_ENDIAN, array2);
01773   MARSHAL_TEST_FIXED_ARRAY (INT16, DBUS_LITTLE_ENDIAN, array2);
01774   MARSHAL_TEST_FIXED_ARRAY (UINT16, DBUS_BIG_ENDIAN, array2);
01775   MARSHAL_TEST_FIXED_ARRAY (UINT16, DBUS_LITTLE_ENDIAN, array2);
01776   
01777   MARSHAL_TEST_FIXED_ARRAY (INT32, DBUS_BIG_ENDIAN, array4);
01778   MARSHAL_TEST_FIXED_ARRAY (INT32, DBUS_LITTLE_ENDIAN, array4);
01779   MARSHAL_TEST_FIXED_ARRAY (UINT32, DBUS_BIG_ENDIAN, array4);
01780   MARSHAL_TEST_FIXED_ARRAY (UINT32, DBUS_LITTLE_ENDIAN, array4);
01781 
01782   MARSHAL_TEST_FIXED_ARRAY (BYTE, DBUS_BIG_ENDIAN, array1);
01783   MARSHAL_TEST_FIXED_ARRAY (BYTE, DBUS_LITTLE_ENDIAN, array1);
01784   
01785 #ifdef DBUS_HAVE_INT64
01786   MARSHAL_TEST_FIXED_ARRAY (INT64, DBUS_BIG_ENDIAN, array8);
01787   MARSHAL_TEST_FIXED_ARRAY (INT64, DBUS_LITTLE_ENDIAN, array8);
01788 #endif
01789 
01790 #if 0
01791 
01792   /*
01793    * FIXME restore the set/pack tests
01794    */
01795 
01796 #ifdef DBUS_HAVE_INT64
01797   /* set/pack 64-bit integers */
01798   _dbus_string_set_length (&str, 8);
01799 
01800   /* signed little */
01801   _dbus_marshal_set_int64 (&str, DBUS_LITTLE_ENDIAN,
01802                            0, DBUS_INT64_CONSTANT (-0x123456789abc7));
01803 
01804   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
01805                 _dbus_unpack_int64 (DBUS_LITTLE_ENDIAN,
01806                                     _dbus_string_get_const_data (&str)));
01807 
01808   /* signed big */
01809   _dbus_marshal_set_int64 (&str, DBUS_BIG_ENDIAN,
01810                            0, DBUS_INT64_CONSTANT (-0x123456789abc7));
01811 
01812   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
01813                 _dbus_unpack_int64 (DBUS_BIG_ENDIAN,
01814                                     _dbus_string_get_const_data (&str)));
01815 
01816   /* signed little pack */
01817   _dbus_pack_int64 (DBUS_INT64_CONSTANT (-0x123456789abc7),
01818                     DBUS_LITTLE_ENDIAN,
01819                     _dbus_string_get_data (&str));
01820 
01821   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
01822                 _dbus_unpack_int64 (DBUS_LITTLE_ENDIAN,
01823                                     _dbus_string_get_const_data (&str)));
01824 
01825   /* signed big pack */
01826   _dbus_pack_int64 (DBUS_INT64_CONSTANT (-0x123456789abc7),
01827                     DBUS_BIG_ENDIAN,
01828                     _dbus_string_get_data (&str));
01829 
01830   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
01831                 _dbus_unpack_int64 (DBUS_BIG_ENDIAN,
01832                                     _dbus_string_get_const_data (&str)));
01833 
01834   /* unsigned little */
01835   _dbus_marshal_set_uint64 (&str, DBUS_LITTLE_ENDIAN,
01836                             0, DBUS_UINT64_CONSTANT (0x123456789abc7));
01837 
01838   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
01839                 _dbus_unpack_uint64 (DBUS_LITTLE_ENDIAN,
01840                                      _dbus_string_get_const_data (&str)));
01841 
01842   /* unsigned big */
01843   _dbus_marshal_set_uint64 (&str, DBUS_BIG_ENDIAN,
01844                             0, DBUS_UINT64_CONSTANT (0x123456789abc7));
01845 
01846   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
01847                 _dbus_unpack_uint64 (DBUS_BIG_ENDIAN,
01848                                      _dbus_string_get_const_data (&str)));
01849 
01850   /* unsigned little pack */
01851   _dbus_pack_uint64 (DBUS_UINT64_CONSTANT (0x123456789abc7),
01852                      DBUS_LITTLE_ENDIAN,
01853                      _dbus_string_get_data (&str));
01854 
01855   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
01856                 _dbus_unpack_uint64 (DBUS_LITTLE_ENDIAN,
01857                                      _dbus_string_get_const_data (&str)));
01858 
01859   /* unsigned big pack */
01860   _dbus_pack_uint64 (DBUS_UINT64_CONSTANT (0x123456789abc7),
01861                      DBUS_BIG_ENDIAN,
01862                      _dbus_string_get_data (&str));
01863 
01864   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
01865                 _dbus_unpack_uint64 (DBUS_BIG_ENDIAN,
01866                                      _dbus_string_get_const_data (&str)));
01867 #endif /* DBUS_HAVE_INT64 */
01868 
01869   /* set/pack 32-bit integers */
01870   _dbus_string_set_length (&str, 4);
01871 
01872   /* signed little */
01873   _dbus_marshal_set_int32 (&str, DBUS_LITTLE_ENDIAN,
01874                            0, -0x123456);
01875 
01876   _dbus_assert (-0x123456 ==
01877                 _dbus_unpack_int32 (DBUS_LITTLE_ENDIAN,
01878                                     _dbus_string_get_const_data (&str)));
01879 
01880   /* signed big */
01881   _dbus_marshal_set_int32 (&str, DBUS_BIG_ENDIAN,
01882                            0, -0x123456);
01883 
01884   _dbus_assert (-0x123456 ==
01885                 _dbus_unpack_int32 (DBUS_BIG_ENDIAN,
01886                                     _dbus_string_get_const_data (&str)));
01887 
01888   /* signed little pack */
01889   _dbus_pack_int32 (-0x123456,
01890                     DBUS_LITTLE_ENDIAN,
01891                     _dbus_string_get_data (&str));
01892 
01893   _dbus_assert (-0x123456 ==
01894                 _dbus_unpack_int32 (DBUS_LITTLE_ENDIAN,
01895                                     _dbus_string_get_const_data (&str)));
01896 
01897   /* signed big pack */
01898   _dbus_pack_int32 (-0x123456,
01899                     DBUS_BIG_ENDIAN,
01900                     _dbus_string_get_data (&str));
01901 
01902   _dbus_assert (-0x123456 ==
01903                 _dbus_unpack_int32 (DBUS_BIG_ENDIAN,
01904                                     _dbus_string_get_const_data (&str)));
01905 
01906   /* unsigned little */
01907   _dbus_marshal_set_uint32 (&str,
01908                             0, 0x123456,
01909                             DBUS_LITTLE_ENDIAN);
01910 
01911   _dbus_assert (0x123456 ==
01912                 _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN,
01913                                      _dbus_string_get_const_data (&str)));
01914 
01915   /* unsigned big */
01916   _dbus_marshal_set_uint32 (&str,
01917                             0, 0x123456,
01918                             DBUS_BIG_ENDIAN);
01919 
01920   _dbus_assert (0x123456 ==
01921                 _dbus_unpack_uint32 (DBUS_BIG_ENDIAN,
01922                                      _dbus_string_get_const_data (&str)));
01923 
01924   /* unsigned little pack */
01925   _dbus_pack_uint32 (0x123456,
01926                      DBUS_LITTLE_ENDIAN,
01927                      _dbus_string_get_data (&str));
01928 
01929   _dbus_assert (0x123456 ==
01930                 _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN,
01931                                      _dbus_string_get_const_data (&str)));
01932 
01933   /* unsigned big pack */
01934   _dbus_pack_uint32 (0x123456,
01935                      DBUS_BIG_ENDIAN,
01936                      _dbus_string_get_data (&str));
01937 
01938   _dbus_assert (0x123456 ==
01939                 _dbus_unpack_uint32 (DBUS_BIG_ENDIAN,
01940                                      _dbus_string_get_const_data (&str)));
01941 
01942 #endif /* set/pack tests for integers */
01943 
01944   /* Strings in-place set */
01945   byte_order = DBUS_LITTLE_ENDIAN;
01946   while (TRUE)
01947     {
01948       /* Init a string */
01949       _dbus_string_set_length (&str, 0);
01950 
01951       /* reset pos for the macros */
01952       pos = 0;
01953 
01954       MARSHAL_TEST_STRCMP (STRING, byte_order, "Hello world");
01955 
01956       /* Set it to something longer */
01957       _dbus_string_init_const (&t, "Hello world foo");
01958 
01959       v_STRING = _dbus_string_get_const_data (&t);
01960       _dbus_marshal_set_basic (&str, 0, DBUS_TYPE_STRING,
01961                                &v_STRING, byte_order, NULL, NULL);
01962 
01963       _dbus_marshal_read_basic (&str, 0, DBUS_TYPE_STRING,
01964                                 &v_STRING, byte_order,
01965                                 NULL);
01966       _dbus_assert (strcmp (v_STRING, "Hello world foo") == 0);
01967 
01968       /* Set it to something shorter */
01969       _dbus_string_init_const (&t, "Hello");
01970 
01971       v_STRING = _dbus_string_get_const_data (&t);
01972       _dbus_marshal_set_basic (&str, 0, DBUS_TYPE_STRING,
01973                                &v_STRING, byte_order, NULL, NULL);
01974       _dbus_marshal_read_basic (&str, 0, DBUS_TYPE_STRING,
01975                                 &v_STRING, byte_order,
01976                                 NULL);
01977       _dbus_assert (strcmp (v_STRING, "Hello") == 0);
01978 
01979       /* Do the other byte order */
01980       if (byte_order == DBUS_LITTLE_ENDIAN)
01981         byte_order = DBUS_BIG_ENDIAN;
01982       else
01983         break;
01984     }
01985 
01986   /* Clean up */
01987   _dbus_string_free (&str);
01988 
01989   return TRUE;
01990 }
01991 
01992 #endif /* DBUS_BUILD_TESTS */

Generated on Mon Sep 27 2010 22:54:23 for D-Bus by  doxygen 1.7.1