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

Generated on Thu Sep 2 2010 01:01:56 for D-Bus by  doxygen 1.7.1