Main Page | Modules | Data Structures | Directories | File List | Data Fields | Related Pages

dbus-marshal-basic.c

00001 /* -*- mode: C; c-file-style: "gnu" -*- */
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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   DBusBasicValue *vp;
00512 
00513   _dbus_assert (dbus_type_is_basic (type));
00514 
00515   str_data = _dbus_string_get_const_data (str);
00516   vp = value;
00517 
00518   switch (type)
00519     {
00520     case DBUS_TYPE_BYTE:
00521       vp->byt = _dbus_string_get_byte (str, pos);
00522       (pos)++;
00523       break;
00524     case DBUS_TYPE_INT16:
00525     case DBUS_TYPE_UINT16:
00526       pos = _DBUS_ALIGN_VALUE (pos, 2);
00527       vp->u16 = *(dbus_uint16_t *)(str_data + pos);
00528       if (byte_order != DBUS_COMPILER_BYTE_ORDER)
00529         vp->u16 = DBUS_UINT16_SWAP_LE_BE (vp->u16);
00530       pos += 2;
00531       break;
00532     case DBUS_TYPE_INT32:
00533     case DBUS_TYPE_UINT32:
00534     case DBUS_TYPE_BOOLEAN:
00535       pos = _DBUS_ALIGN_VALUE (pos, 4);
00536       vp->u32 = *(dbus_uint32_t *)(str_data + pos);
00537       if (byte_order != DBUS_COMPILER_BYTE_ORDER)
00538         vp->u32 = DBUS_UINT32_SWAP_LE_BE (vp->u32);
00539       pos += 4;
00540       break;
00541     case DBUS_TYPE_INT64:
00542     case DBUS_TYPE_UINT64:
00543     case DBUS_TYPE_DOUBLE:
00544       pos = _DBUS_ALIGN_VALUE (pos, 8);
00545 #ifdef DBUS_HAVE_INT64
00546       if (byte_order != DBUS_COMPILER_BYTE_ORDER)
00547         vp->u64 = DBUS_UINT64_SWAP_LE_BE (*(dbus_uint64_t*)(str_data + pos));
00548       else
00549         vp->u64 = *(dbus_uint64_t*)(str_data + pos);
00550 #else
00551       vp->u64 = *(DBus8ByteStruct*) (str_data + pos);
00552       swap_8_octets (vp, byte_order);
00553 #endif
00554       pos += 8;
00555       break;
00556     case DBUS_TYPE_STRING:
00557     case DBUS_TYPE_OBJECT_PATH:
00558       {
00559         int len;
00560 
00561         len = _dbus_marshal_read_uint32 (str, pos, byte_order, &pos);
00562 
00563         vp->str = (char*) str_data + pos;
00564 
00565         pos += len + 1; /* length plus nul */
00566       }
00567       break;
00568     case DBUS_TYPE_SIGNATURE:
00569       {
00570         int len;
00571 
00572         len = _dbus_string_get_byte (str, pos);
00573         pos += 1;
00574 
00575         vp->str = (char*) str_data + pos;
00576 
00577         pos += len + 1; /* length plus nul */
00578       }
00579       break;
00580     default:
00581       _dbus_warn ("type %s %d not a basic type\n",
00582                   _dbus_type_to_string (type), type);
00583       _dbus_assert_not_reached ("not a basic type");
00584       break;
00585     }
00586 
00587   if (new_pos)
00588     *new_pos = pos;
00589 }
00590 
00611 void
00612 _dbus_marshal_read_fixed_multi  (const DBusString *str,
00613                                  int               pos,
00614                                  int               element_type,
00615                                  void             *value,
00616                                  int               n_elements,
00617                                  int               byte_order,
00618                                  int              *new_pos)
00619 {
00620   int array_len;
00621   int alignment;
00622 
00623   _dbus_assert (dbus_type_is_fixed (element_type));
00624   _dbus_assert (dbus_type_is_basic (element_type));
00625 
00626 #if 0
00627   _dbus_verbose ("reading %d elements of %s\n",
00628                  n_elements, _dbus_type_to_string (element_type));
00629 #endif
00630   
00631   alignment = _dbus_type_get_alignment (element_type);
00632 
00633   pos = _DBUS_ALIGN_VALUE (pos, alignment);
00634   
00635   array_len = n_elements * alignment;
00636 
00637   *(const DBusBasicValue**) value = (void*) _dbus_string_get_const_data_len (str, pos, array_len);
00638   if (new_pos)
00639     *new_pos = pos + array_len;
00640 }
00641 
00642 static dbus_bool_t
00643 marshal_2_octets (DBusString   *str,
00644                   int           insert_at,
00645                   dbus_uint16_t value,
00646                   int           byte_order,
00647                   int          *pos_after)
00648 {
00649   dbus_bool_t retval;
00650   int orig_len;
00651 
00652   _dbus_assert (sizeof (value) == 2);
00653 
00654   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
00655     value = DBUS_UINT16_SWAP_LE_BE (value);
00656 
00657   orig_len = _dbus_string_get_length (str);
00658 
00659   retval = _dbus_string_insert_2_aligned (str, insert_at,
00660                                           (const unsigned char *)&value);
00661 
00662   if (pos_after)
00663     {
00664       *pos_after = insert_at + (_dbus_string_get_length (str) - orig_len);
00665       _dbus_assert (*pos_after <= _dbus_string_get_length (str));
00666     }
00667 
00668   return retval;
00669 }
00670 
00671 static dbus_bool_t
00672 marshal_4_octets (DBusString   *str,
00673                   int           insert_at,
00674                   dbus_uint32_t value,
00675                   int           byte_order,
00676                   int          *pos_after)
00677 {
00678   dbus_bool_t retval;
00679   int orig_len;
00680 
00681   _dbus_assert (sizeof (value) == 4);
00682 
00683   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
00684     value = DBUS_UINT32_SWAP_LE_BE (value);
00685 
00686   orig_len = _dbus_string_get_length (str);
00687 
00688   retval = _dbus_string_insert_4_aligned (str, insert_at,
00689                                           (const unsigned char *)&value);
00690 
00691   if (pos_after)
00692     {
00693       *pos_after = insert_at + (_dbus_string_get_length (str) - orig_len);
00694       _dbus_assert (*pos_after <= _dbus_string_get_length (str));
00695     }
00696 
00697   return retval;
00698 }
00699 
00700 static dbus_bool_t
00701 marshal_8_octets (DBusString    *str,
00702                   int            insert_at,
00703                   DBusBasicValue value,
00704                   int            byte_order,
00705                   int           *pos_after)
00706 {
00707   dbus_bool_t retval;
00708   int orig_len;
00709 
00710   _dbus_assert (sizeof (value) == 8);
00711 
00712   swap_8_octets (&value, byte_order);
00713 
00714   orig_len = _dbus_string_get_length (str);
00715 
00716   retval = _dbus_string_insert_8_aligned (str, insert_at,
00717                                           (const unsigned char *)&value);
00718 
00719   if (pos_after)
00720     *pos_after = insert_at + _dbus_string_get_length (str) - orig_len;
00721 
00722   return retval;
00723 }
00724 
00725 enum
00726   {
00727     MARSHAL_AS_STRING,
00728     MARSHAL_AS_SIGNATURE,
00729     MARSHAL_AS_BYTE_ARRAY
00730   };
00731 
00732 static dbus_bool_t
00733 marshal_len_followed_by_bytes (int                  marshal_as,
00734                                DBusString          *str,
00735                                int                  insert_at,
00736                                const unsigned char *value,
00737                                int                  data_len, /* doesn't include nul if any */
00738                                int                  byte_order,
00739                                int                 *pos_after)
00740 {
00741   int pos;
00742   DBusString value_str;
00743   int value_len;
00744 
00745   _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN || byte_order == DBUS_BIG_ENDIAN);
00746   if (insert_at > _dbus_string_get_length (str))
00747     _dbus_warn ("insert_at = %d string len = %d data_len = %d\n",
00748                 insert_at, _dbus_string_get_length (str), data_len);
00749   
00750   if (marshal_as == MARSHAL_AS_BYTE_ARRAY)
00751     value_len = data_len;
00752   else
00753     value_len = data_len + 1; /* value has a nul */
00754 
00755   _dbus_string_init_const_len (&value_str, value, value_len);
00756 
00757   pos = insert_at;
00758 
00759   if (marshal_as == MARSHAL_AS_SIGNATURE)
00760     {
00761       _dbus_assert (data_len <= DBUS_MAXIMUM_SIGNATURE_LENGTH);
00762       _dbus_assert (data_len <= 255); /* same as max sig len right now */
00763       
00764       if (!_dbus_string_insert_byte (str, pos, data_len))
00765         goto oom;
00766 
00767       pos += 1;
00768     }
00769   else
00770     {
00771       if (!marshal_4_octets (str, pos, data_len,
00772                              byte_order, &pos))
00773         goto oom;
00774     }
00775 
00776   if (!_dbus_string_copy_len (&value_str, 0, value_len,
00777                               str, pos))
00778     goto oom;
00779 
00780 #if 0
00781   /* too expensive */
00782   _dbus_assert (_dbus_string_equal_substring (&value_str, 0, value_len,
00783                                               str, pos));
00784   _dbus_verbose_bytes_of_string (str, pos, value_len);
00785 #endif
00786 
00787   pos += value_len;
00788 
00789   if (pos_after)
00790     *pos_after = pos;
00791 
00792   return TRUE;
00793 
00794  oom:
00795   /* Delete what we've inserted */
00796   _dbus_string_delete (str, insert_at, pos - insert_at);
00797 
00798   return FALSE;
00799 }
00800 
00801 static dbus_bool_t
00802 marshal_string (DBusString    *str,
00803                 int            insert_at,
00804                 const char    *value,
00805                 int            byte_order,
00806                 int           *pos_after)
00807 {
00808   return marshal_len_followed_by_bytes (MARSHAL_AS_STRING,
00809                                         str, insert_at, value,
00810                                         strlen (value),
00811                                         byte_order, pos_after);
00812 }
00813 
00814 static dbus_bool_t
00815 marshal_signature (DBusString    *str,
00816                    int            insert_at,
00817                    const char    *value,
00818                    int           *pos_after)
00819 {
00820   return marshal_len_followed_by_bytes (MARSHAL_AS_SIGNATURE,
00821                                         str, insert_at, value,
00822                                         strlen (value),
00823                                         DBUS_COMPILER_BYTE_ORDER, /* irrelevant */
00824                                         pos_after);
00825 }
00826 
00843 dbus_bool_t
00844 _dbus_marshal_write_basic (DBusString *str,
00845                            int         insert_at,
00846                            int         type,
00847                            const void *value,
00848                            int         byte_order,
00849                            int        *pos_after)
00850 {
00851   const DBusBasicValue *vp;
00852 
00853   _dbus_assert (dbus_type_is_basic (type));
00854 
00855   vp = value;
00856 
00857   switch (type)
00858     {
00859     case DBUS_TYPE_BYTE:
00860       if (!_dbus_string_insert_byte (str, insert_at, vp->byt))
00861         return FALSE;
00862       if (pos_after)
00863         *pos_after = insert_at + 1;
00864       return TRUE;
00865       break;
00866     case DBUS_TYPE_INT16:
00867     case DBUS_TYPE_UINT16:
00868       return marshal_2_octets (str, insert_at, vp->u16,
00869                                byte_order, pos_after);
00870       break;
00871     case DBUS_TYPE_BOOLEAN:
00872       return marshal_4_octets (str, insert_at, vp->u32 != FALSE,
00873                                byte_order, pos_after);
00874       break;
00875     case DBUS_TYPE_INT32:
00876     case DBUS_TYPE_UINT32:
00877       return marshal_4_octets (str, insert_at, vp->u32,
00878                                byte_order, pos_after);
00879       break;
00880     case DBUS_TYPE_INT64:
00881     case DBUS_TYPE_UINT64:
00882     case DBUS_TYPE_DOUBLE:
00883       return marshal_8_octets (str, insert_at, *vp, byte_order, pos_after);
00884       break;
00885 
00886     case DBUS_TYPE_STRING:
00887     case DBUS_TYPE_OBJECT_PATH:
00888       _dbus_assert (vp->str != NULL);
00889       return marshal_string (str, insert_at, vp->str, byte_order, pos_after);
00890       break;
00891     case DBUS_TYPE_SIGNATURE:
00892       _dbus_assert (vp->str != NULL);
00893       return marshal_signature (str, insert_at, vp->str, pos_after);
00894       break;
00895     default:
00896       _dbus_assert_not_reached ("not a basic type");
00897       return FALSE;
00898       break;
00899     }
00900 }
00901 
00902 static dbus_bool_t
00903 marshal_1_octets_array (DBusString          *str,
00904                         int                  insert_at,
00905                         const unsigned char *value,
00906                         int                  n_elements,
00907                         int                  byte_order,
00908                         int                 *pos_after)
00909 {
00910   int pos;
00911   DBusString value_str;
00912 
00913   _dbus_string_init_const_len (&value_str, value, n_elements);
00914 
00915   pos = insert_at;
00916 
00917   if (!_dbus_string_copy_len (&value_str, 0, n_elements,
00918                               str, pos))
00919     return FALSE;
00920 
00921   pos += n_elements;
00922 
00923   if (pos_after)
00924     *pos_after = pos;
00925 
00926   return TRUE;
00927 }
00928 
00936 void
00937 _dbus_swap_array (unsigned char *data,
00938                   int            n_elements,
00939                   int            alignment)
00940 {
00941   unsigned char *d;
00942   unsigned char *end;
00943 
00944   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, alignment) == data);
00945 
00946   /* we use const_data and cast it off so DBusString can be a const string
00947    * for the unit tests. don't ask.
00948    */
00949   d = data;
00950   end = d + (n_elements * alignment);
00951   
00952   if (alignment == 8)
00953     {
00954       while (d != end)
00955         {
00956 #ifdef DBUS_HAVE_INT64
00957           *((dbus_uint64_t*)d) = DBUS_UINT64_SWAP_LE_BE (*((dbus_uint64_t*)d));
00958 #else
00959           swap_8_bytes ((DBusBasicValue*) d);
00960 #endif
00961           d += 8;
00962         }
00963     }
00964   else if (alignment == 4)
00965     {
00966       while (d != end)
00967         {
00968           *((dbus_uint32_t*)d) = DBUS_UINT32_SWAP_LE_BE (*((dbus_uint32_t*)d));
00969           d += 4;
00970         }
00971     }
00972   else
00973     {
00974       _dbus_assert (alignment == 2);
00975       
00976       while (d != end)
00977         {
00978           *((dbus_uint16_t*)d) = DBUS_UINT16_SWAP_LE_BE (*((dbus_uint16_t*)d));
00979           d += 2;
00980         }
00981     }
00982 }
00983 
00984 static void
00985 swap_array (DBusString *str,
00986             int         array_start,
00987             int         n_elements,
00988             int         byte_order,
00989             int         alignment)
00990 {
00991   _dbus_assert (_DBUS_ALIGN_VALUE (array_start, alignment) == (unsigned) array_start);
00992 
00993   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
00994     {
00995       /* we use const_data and cast it off so DBusString can be a const string
00996        * for the unit tests. don't ask.
00997        */
00998       _dbus_swap_array ((unsigned char*) (_dbus_string_get_const_data (str) + array_start),
00999                         n_elements, alignment);
01000     }
01001 }
01002 
01003 static dbus_bool_t
01004 marshal_fixed_multi (DBusString           *str,
01005                      int                   insert_at,
01006                      const DBusBasicValue *value,
01007                      int                   n_elements,
01008                      int                   byte_order,
01009                      int                   alignment,
01010                      int                  *pos_after)
01011 {
01012   int old_string_len;
01013   int array_start;
01014   DBusString t;
01015   int len_in_bytes;
01016 
01017   _dbus_assert (n_elements <= DBUS_MAXIMUM_ARRAY_LENGTH / alignment);
01018   
01019   old_string_len = _dbus_string_get_length (str);
01020 
01021   len_in_bytes = n_elements * alignment;
01022   array_start = insert_at;
01023   
01024   /* Note that we do alignment padding unconditionally
01025    * even if the array is empty; this means that
01026    * padding + len is always equal to the number of bytes
01027    * in the array.
01028    */
01029 
01030   if (!_dbus_string_insert_alignment (str, &array_start, alignment))
01031     goto error;
01032 
01033   _dbus_string_init_const_len (&t,
01034                                (const unsigned char*) value,
01035                                len_in_bytes);
01036 
01037   if (!_dbus_string_copy (&t, 0,
01038                           str, array_start))
01039     goto error;
01040 
01041   swap_array (str, array_start, n_elements, byte_order, alignment);
01042 
01043   if (pos_after)
01044     *pos_after = array_start + len_in_bytes;
01045   
01046   return TRUE;
01047 
01048  error:
01049   _dbus_string_delete (str, insert_at,
01050                        _dbus_string_get_length (str) - old_string_len);
01051 
01052   return FALSE;
01053 }
01054 
01072 dbus_bool_t
01073 _dbus_marshal_write_fixed_multi (DBusString *str,
01074                                  int         insert_at,
01075                                  int         element_type,
01076                                  const void *value,
01077                                  int         n_elements,
01078                                  int         byte_order,
01079                                  int        *pos_after)
01080 {
01081   const void* vp = *(const DBusBasicValue**)value;
01082   
01083   _dbus_assert (dbus_type_is_fixed (element_type));
01084   _dbus_assert (n_elements >= 0);
01085 
01086 #if 0
01087   _dbus_verbose ("writing %d elements of %s\n",
01088                  n_elements, _dbus_type_to_string (element_type));
01089 #endif
01090   
01091   switch (element_type)
01092     {
01093     case DBUS_TYPE_BYTE:
01094       return marshal_1_octets_array (str, insert_at, vp, n_elements, byte_order, pos_after);
01095       break;
01096     case DBUS_TYPE_INT16:
01097     case DBUS_TYPE_UINT16:
01098       return marshal_fixed_multi (str, insert_at, vp, n_elements, byte_order, 2, pos_after);
01099       /* FIXME: we canonicalize to 0 or 1 for the single boolean case
01100        * should we here too ? */
01101     case DBUS_TYPE_BOOLEAN:
01102     case DBUS_TYPE_INT32:
01103     case DBUS_TYPE_UINT32:
01104       return marshal_fixed_multi (str, insert_at, vp, n_elements, byte_order, 4, pos_after);
01105       break;
01106     case DBUS_TYPE_INT64:
01107     case DBUS_TYPE_UINT64:
01108     case DBUS_TYPE_DOUBLE:
01109       return marshal_fixed_multi (str, insert_at, vp, n_elements, byte_order, 8, pos_after);
01110       break;
01111 
01112     default:
01113       _dbus_assert_not_reached ("non fixed type in array write");
01114       break;
01115     }
01116 
01117   return FALSE;
01118 }
01119 
01120 
01130 void
01131 _dbus_marshal_skip_basic (const DBusString      *str,
01132                           int                    type,
01133                           int                    byte_order,
01134                           int                   *pos)
01135 {
01136   _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
01137                 byte_order == DBUS_BIG_ENDIAN);
01138   
01139   switch (type)
01140     {
01141     case DBUS_TYPE_BYTE:
01142       (*pos)++;
01143       break;
01144     case DBUS_TYPE_INT16:
01145     case DBUS_TYPE_UINT16:
01146       *pos = _DBUS_ALIGN_VALUE (*pos, 2);
01147       *pos += 2;
01148       break;
01149     case DBUS_TYPE_BOOLEAN:
01150     case DBUS_TYPE_INT32:
01151     case DBUS_TYPE_UINT32:
01152       *pos = _DBUS_ALIGN_VALUE (*pos, 4);
01153       *pos += 4;
01154       break;
01155     case DBUS_TYPE_INT64:
01156     case DBUS_TYPE_UINT64:
01157     case DBUS_TYPE_DOUBLE:
01158       *pos = _DBUS_ALIGN_VALUE (*pos, 8);
01159       *pos += 8;
01160       break;
01161     case DBUS_TYPE_STRING:
01162     case DBUS_TYPE_OBJECT_PATH:
01163       {
01164         int len;
01165 
01166         len = _dbus_marshal_read_uint32 (str, *pos, byte_order, pos);
01167         
01168         *pos += len + 1; /* length plus nul */
01169       }
01170       break;
01171     case DBUS_TYPE_SIGNATURE:
01172       {
01173         int len;
01174 
01175         len = _dbus_string_get_byte (str, *pos);
01176 
01177         *pos += len + 2; /* length byte plus length plus nul */
01178       }
01179       break;
01180     default:
01181       _dbus_warn ("type %s not a basic type\n",
01182                   _dbus_type_to_string (type));
01183       _dbus_assert_not_reached ("not a basic type");
01184       break;
01185     }
01186 }
01187 
01197 void
01198 _dbus_marshal_skip_array (const DBusString  *str,
01199                           int                element_type,
01200                           int                byte_order,
01201                           int               *pos)
01202 {
01203   dbus_uint32_t array_len;
01204   int i;
01205   int alignment;
01206 
01207   i = _DBUS_ALIGN_VALUE (*pos, 4);
01208 
01209   array_len = _dbus_marshal_read_uint32 (str, i, byte_order, &i);
01210 
01211   alignment = _dbus_type_get_alignment (element_type);
01212 
01213   i = _DBUS_ALIGN_VALUE (i, alignment);
01214 
01215   *pos = i + array_len;
01216 }
01217 
01225 int
01226 _dbus_type_get_alignment (int typecode)
01227 {
01228   switch (typecode)
01229     {
01230     case DBUS_TYPE_BYTE:
01231     case DBUS_TYPE_VARIANT:
01232     case DBUS_TYPE_SIGNATURE:
01233       return 1;
01234     case DBUS_TYPE_INT16:
01235     case DBUS_TYPE_UINT16:
01236       return 2;
01237     case DBUS_TYPE_BOOLEAN:
01238     case DBUS_TYPE_INT32:
01239     case DBUS_TYPE_UINT32:
01240       /* this stuff is 4 since it starts with a length */
01241     case DBUS_TYPE_STRING:
01242     case DBUS_TYPE_OBJECT_PATH:
01243     case DBUS_TYPE_ARRAY:
01244       return 4;
01245     case DBUS_TYPE_INT64:
01246     case DBUS_TYPE_UINT64:
01247     case DBUS_TYPE_DOUBLE:
01248       /* struct is 8 since it could contain an 8-aligned item
01249        * and it's simpler to just always align structs to 8;
01250        * we want the amount of padding in a struct of a given
01251        * type to be predictable, not location-dependent.
01252        * DICT_ENTRY is always the same as struct.
01253        */
01254     case DBUS_TYPE_STRUCT:
01255     case DBUS_TYPE_DICT_ENTRY:
01256       return 8;
01257 
01258     default:
01259       _dbus_assert_not_reached ("unknown typecode in _dbus_type_get_alignment()");
01260       return 0;
01261     }
01262 }
01263 
01264 
01273 dbus_bool_t
01274 _dbus_type_is_valid (int typecode)
01275 {
01276   switch (typecode)
01277     {
01278     case DBUS_TYPE_BYTE:
01279     case DBUS_TYPE_BOOLEAN:
01280     case DBUS_TYPE_INT16:
01281     case DBUS_TYPE_UINT16:
01282     case DBUS_TYPE_INT32:
01283     case DBUS_TYPE_UINT32:
01284     case DBUS_TYPE_INT64:
01285     case DBUS_TYPE_UINT64:
01286     case DBUS_TYPE_DOUBLE:
01287     case DBUS_TYPE_STRING:
01288     case DBUS_TYPE_OBJECT_PATH:
01289     case DBUS_TYPE_SIGNATURE:
01290     case DBUS_TYPE_ARRAY:
01291     case DBUS_TYPE_STRUCT:
01292     case DBUS_TYPE_DICT_ENTRY:
01293     case DBUS_TYPE_VARIANT:
01294       return TRUE;
01295 
01296     default:
01297       return FALSE;
01298     }
01299 }
01300 
01307 const char *
01308 _dbus_type_to_string (int typecode)
01309 {
01310   switch (typecode)
01311     {
01312     case DBUS_TYPE_INVALID:
01313       return "invalid";
01314     case DBUS_TYPE_BOOLEAN:
01315       return "boolean";
01316     case DBUS_TYPE_BYTE:
01317       return "byte";
01318     case DBUS_TYPE_INT16:
01319       return "int16";
01320     case DBUS_TYPE_UINT16:
01321       return "uint16";
01322     case DBUS_TYPE_INT32:
01323       return "int32";
01324     case DBUS_TYPE_UINT32:
01325       return "uint32";
01326     case DBUS_TYPE_DOUBLE:
01327       return "double";
01328     case DBUS_TYPE_STRING:
01329       return "string";
01330     case DBUS_TYPE_OBJECT_PATH:
01331       return "object_path";
01332     case DBUS_TYPE_SIGNATURE:
01333       return "signature";
01334     case DBUS_TYPE_STRUCT:
01335       return "struct";
01336     case DBUS_TYPE_DICT_ENTRY:
01337       return "dict_entry";
01338     case DBUS_TYPE_ARRAY:
01339       return "array";
01340     case DBUS_TYPE_VARIANT:
01341       return "variant";
01342     case DBUS_STRUCT_BEGIN_CHAR:
01343       return "begin_struct";
01344     case DBUS_STRUCT_END_CHAR:
01345       return "end_struct";
01346     case DBUS_DICT_ENTRY_BEGIN_CHAR:
01347       return "begin_dict_entry";
01348     case DBUS_DICT_ENTRY_END_CHAR:
01349       return "end_dict_entry";
01350     default:
01351       return "unknown";
01352     }
01353 }
01354 
01364 void
01365 _dbus_verbose_bytes (const unsigned char *data,
01366                      int                  len,
01367                      int                  offset)
01368 {
01369   int i;
01370   const unsigned char *aligned;
01371 
01372   _dbus_assert (len >= 0);
01373 
01374   /* Print blanks on first row if appropriate */
01375   aligned = _DBUS_ALIGN_ADDRESS (data, 4);
01376   if (aligned > data)
01377     aligned -= 4;
01378   _dbus_assert (aligned <= data);
01379 
01380   if (aligned != data)
01381     {
01382       _dbus_verbose ("%4d\t%p: ", - (data - aligned), aligned);
01383       while (aligned != data)
01384         {
01385           _dbus_verbose ("    ");
01386           ++aligned;
01387         }
01388     }
01389 
01390   /* now print the bytes */
01391   i = 0;
01392   while (i < len)
01393     {
01394       if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
01395         {
01396           _dbus_verbose ("%4d\t%p: ",
01397                          offset + i, &data[i]);
01398         }
01399 
01400       if (data[i] >= 32 &&
01401           data[i] <= 126)
01402         _dbus_verbose (" '%c' ", data[i]);
01403       else
01404         _dbus_verbose ("0x%s%x ",
01405                        data[i] <= 0xf ? "0" : "", data[i]);
01406 
01407       ++i;
01408 
01409       if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
01410         {
01411           if (i > 3)
01412             _dbus_verbose ("BE: %d LE: %d",
01413                            _dbus_unpack_uint32 (DBUS_BIG_ENDIAN, &data[i-4]),
01414                            _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN, &data[i-4]));
01415 
01416           if (i > 7 &&
01417               _DBUS_ALIGN_ADDRESS (&data[i], 8) == &data[i])
01418             {
01419 #ifdef DBUS_HAVE_INT64
01420               /* I think I probably mean "GNU libc printf" and not "GNUC"
01421                * but we'll wait until someone complains. If you hit this,
01422                * just turn off verbose mode as a workaround.
01423                */
01424 #if __GNUC__
01425               _dbus_verbose (" u64: 0x%llx",
01426                              *(dbus_uint64_t*)&data[i-8]);
01427 #endif
01428 #endif
01429               _dbus_verbose (" dbl: %g",
01430                              *(double*)&data[i-8]);
01431             }
01432 
01433           _dbus_verbose ("\n");
01434         }
01435     }
01436 
01437   _dbus_verbose ("\n");
01438 }
01439 
01447 void
01448 _dbus_verbose_bytes_of_string (const DBusString    *str,
01449                                int                  start,
01450                                int                  len)
01451 {
01452   const char *d;
01453   int real_len;
01454 
01455   real_len = _dbus_string_get_length (str);
01456 
01457   _dbus_assert (start >= 0);
01458 
01459   if (start > real_len)
01460     {
01461       _dbus_verbose ("  [%d,%d) is not inside string of length %d\n",
01462                      start, len, real_len);
01463       return;
01464     }
01465 
01466   if ((start + len) > real_len)
01467     {
01468       _dbus_verbose ("  [%d,%d) extends outside string of length %d\n",
01469                      start, len, real_len);
01470       len = real_len - start;
01471     }
01472 
01473   d = _dbus_string_get_const_data_len (str, start, len);
01474 
01475   _dbus_verbose_bytes (d, len, start);
01476 }
01477 
01478 static int
01479 map_type_char_to_type (int t)
01480 {
01481   if (t == DBUS_STRUCT_BEGIN_CHAR)
01482     return DBUS_TYPE_STRUCT;
01483   else if (t == DBUS_DICT_ENTRY_BEGIN_CHAR)
01484     return DBUS_TYPE_DICT_ENTRY;
01485   else
01486     {
01487       _dbus_assert (t != DBUS_STRUCT_END_CHAR);
01488       _dbus_assert (t != DBUS_DICT_ENTRY_END_CHAR);
01489       return t;
01490     }
01491 }
01492 
01503 int
01504 _dbus_first_type_in_signature (const DBusString *str,
01505                                int               pos)
01506 {
01507   return map_type_char_to_type (_dbus_string_get_byte (str, pos));
01508 }
01509 
01518 int
01519 _dbus_first_type_in_signature_c_str (const char       *str,
01520                                      int               pos)
01521 {
01522   return map_type_char_to_type (str[pos]);
01523 }
01524 
01527 #ifdef DBUS_BUILD_TESTS
01528 #include "dbus-test.h"
01529 #include <stdio.h>
01530 
01531 static void
01532 swap_test_array (void *array,
01533                  int   len_bytes,
01534                  int   byte_order,
01535                  int   alignment)
01536 {
01537   DBusString t;
01538 
01539   if (alignment == 1)
01540     return;
01541   
01542   _dbus_string_init_const_len (&t, array, len_bytes);
01543   swap_array (&t, 0, len_bytes / alignment, byte_order, alignment);
01544 }
01545 
01546 #define MARSHAL_BASIC(typename, byte_order, literal)                    \
01547   do {                                                                  \
01548      v_##typename = literal;                                            \
01549      if (!_dbus_marshal_write_basic (&str, pos, DBUS_TYPE_##typename,   \
01550                                     &v_##typename,                      \
01551                                     byte_order, NULL))                  \
01552        _dbus_assert_not_reached ("no memory");                          \
01553    } while (0)
01554 
01555 #define DEMARSHAL_BASIC(typename, byte_order)                                   \
01556   do {                                                                          \
01557     _dbus_marshal_read_basic (&str, pos, DBUS_TYPE_##typename, &v_##typename,   \
01558                               byte_order, &pos);                                \
01559   } while (0)
01560 
01561 #define DEMARSHAL_BASIC_AND_CHECK(typename, byte_order, literal)                        \
01562   do {                                                                                  \
01563     DEMARSHAL_BASIC (typename, byte_order);                                             \
01564     if (literal != v_##typename)                                                        \
01565       {                                                                                 \
01566         _dbus_verbose_bytes_of_string (&str, dump_pos,                                  \
01567                                      _dbus_string_get_length (&str) - dump_pos);        \
01568         _dbus_assert_not_reached ("demarshaled wrong value");                           \
01569       }                                                                                 \
01570   } while (0)
01571 
01572 #define MARSHAL_TEST(typename, byte_order, literal)             \
01573   do {                                                          \
01574     MARSHAL_BASIC (typename, byte_order, literal);              \
01575     dump_pos = pos;                                             \
01576     DEMARSHAL_BASIC_AND_CHECK (typename, byte_order, literal);  \
01577   } while (0)
01578 
01579 #define MARSHAL_TEST_STRCMP(typename, byte_order, literal)                              \
01580   do {                                                                                  \
01581     MARSHAL_BASIC (typename, byte_order, literal);                                      \
01582     dump_pos = pos;                                                                     \
01583     DEMARSHAL_BASIC (typename, byte_order);                                             \
01584     if (strcmp (literal, v_##typename) != 0)                                            \
01585       {                                                                                 \
01586         _dbus_verbose_bytes_of_string (&str, dump_pos,                                  \
01587                                        _dbus_string_get_length (&str) - dump_pos);      \
01588         _dbus_warn ("literal '%s'\nvalue  '%s'\n", literal, v_##typename);              \
01589         _dbus_assert_not_reached ("demarshaled wrong value");                           \
01590       }                                                                                 \
01591   } while (0)
01592 
01593 #define MARSHAL_FIXED_ARRAY(typename, byte_order, literal)                                      \
01594   do {                                                                                          \
01595      int next;                                                                                  \
01596      v_UINT32 = sizeof(literal);                                                                \
01597      if (!_dbus_marshal_write_basic (&str, pos, DBUS_TYPE_UINT32, &v_UINT32,                    \
01598                                      byte_order, &next))                                        \
01599        _dbus_assert_not_reached ("no memory");                                                  \
01600      v_ARRAY_##typename = literal;                                                              \
01601      if (!_dbus_marshal_write_fixed_multi (&str, next, DBUS_TYPE_##typename,                    \
01602                                            &v_ARRAY_##typename, _DBUS_N_ELEMENTS(literal),      \
01603                                            byte_order, NULL))                                   \
01604        _dbus_assert_not_reached ("no memory");                                                  \
01605    } while (0)
01606 
01607 #define DEMARSHAL_FIXED_ARRAY(typename, byte_order)                                             \
01608   do {                                                                                          \
01609     int next;                                                                                   \
01610     alignment = _dbus_type_get_alignment (DBUS_TYPE_##typename);                                \
01611     v_UINT32 = _dbus_marshal_read_uint32 (&str, dump_pos, byte_order, &next);                   \
01612     _dbus_marshal_read_fixed_multi (&str, next, DBUS_TYPE_##typename, &v_ARRAY_##typename,      \
01613                                     v_UINT32/alignment,                                         \
01614                                     byte_order, NULL);                                          \
01615     swap_test_array (v_ARRAY_##typename, v_UINT32,                                              \
01616                      byte_order, alignment);                                                    \
01617   } while (0)
01618 
01619 #define DEMARSHAL_FIXED_ARRAY_AND_CHECK(typename, byte_order, literal)                  \
01620   do {                                                                                  \
01621     DEMARSHAL_FIXED_ARRAY (typename, byte_order);                                       \
01622     if (memcmp (literal, v_ARRAY_##typename, sizeof (literal) != 0))                    \
01623       {                                                                                 \
01624         _dbus_verbose ("MARSHALED DATA\n");                                             \
01625         _dbus_verbose_bytes_of_string (&str, dump_pos,                                  \
01626                                       _dbus_string_get_length (&str) - dump_pos);       \
01627         _dbus_verbose ("LITERAL DATA\n");                                               \
01628         _dbus_verbose_bytes ((char*)literal, sizeof (literal), 0);                      \
01629         _dbus_verbose ("READ DATA\n");                                                  \
01630         _dbus_verbose_bytes ((char*)v_ARRAY_##typename, sizeof (literal), 0);           \
01631         _dbus_assert_not_reached ("demarshaled wrong fixed array value");               \
01632       }                                                                                 \
01633   } while (0)
01634 
01635 #define MARSHAL_TEST_FIXED_ARRAY(typename, byte_order, literal)         \
01636   do {                                                                  \
01637     MARSHAL_FIXED_ARRAY (typename, byte_order, literal);                \
01638     dump_pos = pos;                                                     \
01639     DEMARSHAL_FIXED_ARRAY_AND_CHECK (typename, byte_order, literal);    \
01640   } while (0)
01641 
01642 dbus_bool_t
01643 _dbus_marshal_test (void)
01644 {
01645   int alignment;
01646   DBusString str;
01647   int pos, dump_pos;
01648   unsigned char array1[5] = { 3, 4, 0, 1, 9 };
01649   dbus_int16_t array2[3] = { 124, 457, 780 };
01650   dbus_int32_t array4[3] = { 123, 456, 789 };
01651 #ifdef DBUS_HAVE_INT64
01652   dbus_int64_t array8[3] = { DBUS_INT64_CONSTANT (0x123ffffffff),
01653                              DBUS_INT64_CONSTANT (0x456ffffffff),
01654                              DBUS_INT64_CONSTANT (0x789ffffffff) };
01655   dbus_int64_t *v_ARRAY_INT64;
01656 #endif
01657   unsigned char *v_ARRAY_BYTE;
01658   dbus_int16_t *v_ARRAY_INT16;
01659   dbus_uint16_t *v_ARRAY_UINT16;
01660   dbus_int32_t *v_ARRAY_INT32;
01661   dbus_uint32_t *v_ARRAY_UINT32;
01662   double *v_ARRAY_DOUBLE;
01663   DBusString t;
01664   double v_DOUBLE;
01665   double t_DOUBLE;
01666   dbus_int16_t v_INT16;
01667   dbus_uint16_t v_UINT16;
01668   dbus_int32_t v_INT32;
01669   dbus_uint32_t v_UINT32;
01670   dbus_int64_t v_INT64;
01671   dbus_uint64_t v_UINT64;
01672   unsigned char v_BYTE;
01673   dbus_bool_t v_BOOLEAN;
01674   const char *v_STRING;
01675   const char *v_SIGNATURE;
01676   const char *v_OBJECT_PATH;
01677   int byte_order;
01678 
01679   if (!_dbus_string_init (&str))
01680     _dbus_assert_not_reached ("failed to init string");
01681 
01682   pos = 0;
01683 
01684   /* Marshal doubles */
01685   MARSHAL_BASIC (DOUBLE, DBUS_BIG_ENDIAN, 3.14);
01686   DEMARSHAL_BASIC (DOUBLE, DBUS_BIG_ENDIAN);
01687   t_DOUBLE = 3.14;
01688   if (!_DBUS_DOUBLES_BITWISE_EQUAL (t_DOUBLE, v_DOUBLE))
01689     _dbus_assert_not_reached ("got wrong double value");
01690 
01691   MARSHAL_BASIC (DOUBLE, DBUS_LITTLE_ENDIAN, 3.14);
01692   DEMARSHAL_BASIC (DOUBLE, DBUS_LITTLE_ENDIAN);
01693   t_DOUBLE = 3.14;
01694   if (!_DBUS_DOUBLES_BITWISE_EQUAL (t_DOUBLE, v_DOUBLE))
01695     _dbus_assert_not_reached ("got wrong double value");
01696 
01697   /* Marshal signed 16 integers */
01698   MARSHAL_TEST (INT16, DBUS_BIG_ENDIAN, -12345);
01699   MARSHAL_TEST (INT16, DBUS_LITTLE_ENDIAN, -12345);
01700 
01701   /* Marshal unsigned 16 integers */
01702   MARSHAL_TEST (UINT16, DBUS_BIG_ENDIAN, 0x1234);
01703   MARSHAL_TEST (UINT16, DBUS_LITTLE_ENDIAN, 0x1234);
01704   
01705   /* Marshal signed integers */
01706   MARSHAL_TEST (INT32, DBUS_BIG_ENDIAN, -12345678);
01707   MARSHAL_TEST (INT32, DBUS_LITTLE_ENDIAN, -12345678);
01708 
01709   /* Marshal unsigned integers */
01710   MARSHAL_TEST (UINT32, DBUS_BIG_ENDIAN, 0x12345678);
01711   MARSHAL_TEST (UINT32, DBUS_LITTLE_ENDIAN, 0x12345678);
01712 
01713 #ifdef DBUS_HAVE_INT64
01714   /* Marshal signed integers */
01715   MARSHAL_TEST (INT64, DBUS_BIG_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7));
01716   MARSHAL_TEST (INT64, DBUS_LITTLE_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7));
01717 
01718   /* Marshal unsigned integers */
01719   MARSHAL_TEST (UINT64, DBUS_BIG_ENDIAN, DBUS_UINT64_CONSTANT (0x123456789abc7));
01720   MARSHAL_TEST (UINT64, DBUS_LITTLE_ENDIAN, DBUS_UINT64_CONSTANT (0x123456789abc7));
01721 #endif /* DBUS_HAVE_INT64 */
01722 
01723   /* Marshal byte */
01724   MARSHAL_TEST (BYTE, DBUS_BIG_ENDIAN, 5);
01725   MARSHAL_TEST (BYTE, DBUS_LITTLE_ENDIAN, 5);
01726 
01727   /* Marshal all possible bools! */
01728   MARSHAL_TEST (BOOLEAN, DBUS_BIG_ENDIAN, FALSE);
01729   MARSHAL_TEST (BOOLEAN, DBUS_LITTLE_ENDIAN, FALSE);
01730   MARSHAL_TEST (BOOLEAN, DBUS_BIG_ENDIAN, TRUE);
01731   MARSHAL_TEST (BOOLEAN, DBUS_LITTLE_ENDIAN, TRUE);
01732 
01733   /* Marshal strings */
01734   MARSHAL_TEST_STRCMP (STRING, DBUS_BIG_ENDIAN, "");
01735   MARSHAL_TEST_STRCMP (STRING, DBUS_LITTLE_ENDIAN, "");
01736   MARSHAL_TEST_STRCMP (STRING, DBUS_BIG_ENDIAN, "This is the dbus test string");
01737   MARSHAL_TEST_STRCMP (STRING, DBUS_LITTLE_ENDIAN, "This is the dbus test string");
01738 
01739   /* object paths */
01740   MARSHAL_TEST_STRCMP (OBJECT_PATH, DBUS_BIG_ENDIAN, "/a/b/c");
01741   MARSHAL_TEST_STRCMP (OBJECT_PATH, DBUS_LITTLE_ENDIAN, "/a/b/c");
01742 
01743   /* signatures */
01744   MARSHAL_TEST_STRCMP (SIGNATURE, DBUS_BIG_ENDIAN, "");
01745   MARSHAL_TEST_STRCMP (SIGNATURE, DBUS_LITTLE_ENDIAN, "");
01746   MARSHAL_TEST_STRCMP (SIGNATURE, DBUS_BIG_ENDIAN, "a(ii)");
01747   MARSHAL_TEST_STRCMP (SIGNATURE, DBUS_LITTLE_ENDIAN, "a(ii)");
01748 
01749   /* Arrays */
01750   MARSHAL_TEST_FIXED_ARRAY (INT16, DBUS_BIG_ENDIAN, array2);
01751   MARSHAL_TEST_FIXED_ARRAY (INT16, DBUS_LITTLE_ENDIAN, array2);
01752   MARSHAL_TEST_FIXED_ARRAY (UINT16, DBUS_BIG_ENDIAN, array2);
01753   MARSHAL_TEST_FIXED_ARRAY (UINT16, DBUS_LITTLE_ENDIAN, array2);
01754   
01755   MARSHAL_TEST_FIXED_ARRAY (INT32, DBUS_BIG_ENDIAN, array4);
01756   MARSHAL_TEST_FIXED_ARRAY (INT32, DBUS_LITTLE_ENDIAN, array4);
01757   MARSHAL_TEST_FIXED_ARRAY (UINT32, DBUS_BIG_ENDIAN, array4);
01758   MARSHAL_TEST_FIXED_ARRAY (UINT32, DBUS_LITTLE_ENDIAN, array4);
01759 
01760   MARSHAL_TEST_FIXED_ARRAY (BYTE, DBUS_BIG_ENDIAN, array1);
01761   MARSHAL_TEST_FIXED_ARRAY (BYTE, DBUS_LITTLE_ENDIAN, array1);
01762   
01763 #ifdef DBUS_HAVE_INT64
01764   MARSHAL_TEST_FIXED_ARRAY (INT64, DBUS_BIG_ENDIAN, array8);
01765   MARSHAL_TEST_FIXED_ARRAY (INT64, DBUS_LITTLE_ENDIAN, array8);
01766 #endif
01767 
01768 #if 0
01769 
01770   /*
01771    * FIXME restore the set/pack tests
01772    */
01773 
01774 #ifdef DBUS_HAVE_INT64
01775   /* set/pack 64-bit integers */
01776   _dbus_string_set_length (&str, 8);
01777 
01778   /* signed little */
01779   _dbus_marshal_set_int64 (&str, DBUS_LITTLE_ENDIAN,
01780                            0, DBUS_INT64_CONSTANT (-0x123456789abc7));
01781 
01782   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
01783                 _dbus_unpack_int64 (DBUS_LITTLE_ENDIAN,
01784                                     _dbus_string_get_const_data (&str)));
01785 
01786   /* signed big */
01787   _dbus_marshal_set_int64 (&str, DBUS_BIG_ENDIAN,
01788                            0, DBUS_INT64_CONSTANT (-0x123456789abc7));
01789 
01790   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
01791                 _dbus_unpack_int64 (DBUS_BIG_ENDIAN,
01792                                     _dbus_string_get_const_data (&str)));
01793 
01794   /* signed little pack */
01795   _dbus_pack_int64 (DBUS_INT64_CONSTANT (-0x123456789abc7),
01796                     DBUS_LITTLE_ENDIAN,
01797                     _dbus_string_get_data (&str));
01798 
01799   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
01800                 _dbus_unpack_int64 (DBUS_LITTLE_ENDIAN,
01801                                     _dbus_string_get_const_data (&str)));
01802 
01803   /* signed big pack */
01804   _dbus_pack_int64 (DBUS_INT64_CONSTANT (-0x123456789abc7),
01805                     DBUS_BIG_ENDIAN,
01806                     _dbus_string_get_data (&str));
01807 
01808   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
01809                 _dbus_unpack_int64 (DBUS_BIG_ENDIAN,
01810                                     _dbus_string_get_const_data (&str)));
01811 
01812   /* unsigned little */
01813   _dbus_marshal_set_uint64 (&str, DBUS_LITTLE_ENDIAN,
01814                             0, DBUS_UINT64_CONSTANT (0x123456789abc7));
01815 
01816   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
01817                 _dbus_unpack_uint64 (DBUS_LITTLE_ENDIAN,
01818                                      _dbus_string_get_const_data (&str)));
01819 
01820   /* unsigned big */
01821   _dbus_marshal_set_uint64 (&str, DBUS_BIG_ENDIAN,
01822                             0, DBUS_UINT64_CONSTANT (0x123456789abc7));
01823 
01824   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
01825                 _dbus_unpack_uint64 (DBUS_BIG_ENDIAN,
01826                                      _dbus_string_get_const_data (&str)));
01827 
01828   /* unsigned little pack */
01829   _dbus_pack_uint64 (DBUS_UINT64_CONSTANT (0x123456789abc7),
01830                      DBUS_LITTLE_ENDIAN,
01831                      _dbus_string_get_data (&str));
01832 
01833   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
01834                 _dbus_unpack_uint64 (DBUS_LITTLE_ENDIAN,
01835                                      _dbus_string_get_const_data (&str)));
01836 
01837   /* unsigned big pack */
01838   _dbus_pack_uint64 (DBUS_UINT64_CONSTANT (0x123456789abc7),
01839                      DBUS_BIG_ENDIAN,
01840                      _dbus_string_get_data (&str));
01841 
01842   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
01843                 _dbus_unpack_uint64 (DBUS_BIG_ENDIAN,
01844                                      _dbus_string_get_const_data (&str)));
01845 #endif /* DBUS_HAVE_INT64 */
01846 
01847   /* set/pack 32-bit integers */
01848   _dbus_string_set_length (&str, 4);
01849 
01850   /* signed little */
01851   _dbus_marshal_set_int32 (&str, DBUS_LITTLE_ENDIAN,
01852                            0, -0x123456);
01853 
01854   _dbus_assert (-0x123456 ==
01855                 _dbus_unpack_int32 (DBUS_LITTLE_ENDIAN,
01856                                     _dbus_string_get_const_data (&str)));
01857 
01858   /* signed big */
01859   _dbus_marshal_set_int32 (&str, DBUS_BIG_ENDIAN,
01860                            0, -0x123456);
01861 
01862   _dbus_assert (-0x123456 ==
01863                 _dbus_unpack_int32 (DBUS_BIG_ENDIAN,
01864                                     _dbus_string_get_const_data (&str)));
01865 
01866   /* signed little pack */
01867   _dbus_pack_int32 (-0x123456,
01868                     DBUS_LITTLE_ENDIAN,
01869                     _dbus_string_get_data (&str));
01870 
01871   _dbus_assert (-0x123456 ==
01872                 _dbus_unpack_int32 (DBUS_LITTLE_ENDIAN,
01873                                     _dbus_string_get_const_data (&str)));
01874 
01875   /* signed big pack */
01876   _dbus_pack_int32 (-0x123456,
01877                     DBUS_BIG_ENDIAN,
01878                     _dbus_string_get_data (&str));
01879 
01880   _dbus_assert (-0x123456 ==
01881                 _dbus_unpack_int32 (DBUS_BIG_ENDIAN,
01882                                     _dbus_string_get_const_data (&str)));
01883 
01884   /* unsigned little */
01885   _dbus_marshal_set_uint32 (&str,
01886                             0, 0x123456,
01887                             DBUS_LITTLE_ENDIAN);
01888 
01889   _dbus_assert (0x123456 ==
01890                 _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN,
01891                                      _dbus_string_get_const_data (&str)));
01892 
01893   /* unsigned big */
01894   _dbus_marshal_set_uint32 (&str,
01895                             0, 0x123456,
01896                             DBUS_BIG_ENDIAN);
01897 
01898   _dbus_assert (0x123456 ==
01899                 _dbus_unpack_uint32 (DBUS_BIG_ENDIAN,
01900                                      _dbus_string_get_const_data (&str)));
01901 
01902   /* unsigned little pack */
01903   _dbus_pack_uint32 (0x123456,
01904                      DBUS_LITTLE_ENDIAN,
01905                      _dbus_string_get_data (&str));
01906 
01907   _dbus_assert (0x123456 ==
01908                 _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN,
01909                                      _dbus_string_get_const_data (&str)));
01910 
01911   /* unsigned big pack */
01912   _dbus_pack_uint32 (0x123456,
01913                      DBUS_BIG_ENDIAN,
01914                      _dbus_string_get_data (&str));
01915 
01916   _dbus_assert (0x123456 ==
01917                 _dbus_unpack_uint32 (DBUS_BIG_ENDIAN,
01918                                      _dbus_string_get_const_data (&str)));
01919 
01920 #endif /* set/pack tests for integers */
01921 
01922   /* Strings in-place set */
01923   byte_order = DBUS_LITTLE_ENDIAN;
01924   while (TRUE)
01925     {
01926       /* Init a string */
01927       _dbus_string_set_length (&str, 0);
01928 
01929       /* reset pos for the macros */
01930       pos = 0;
01931 
01932       MARSHAL_TEST_STRCMP (STRING, byte_order, "Hello world");
01933 
01934       /* Set it to something longer */
01935       _dbus_string_init_const (&t, "Hello world foo");
01936 
01937       v_STRING = _dbus_string_get_const_data (&t);
01938       _dbus_marshal_set_basic (&str, 0, DBUS_TYPE_STRING,
01939                                &v_STRING, byte_order, NULL, NULL);
01940 
01941       _dbus_marshal_read_basic (&str, 0, DBUS_TYPE_STRING,
01942                                 &v_STRING, byte_order,
01943                                 NULL);
01944       _dbus_assert (strcmp (v_STRING, "Hello world foo") == 0);
01945 
01946       /* Set it to something shorter */
01947       _dbus_string_init_const (&t, "Hello");
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       _dbus_marshal_read_basic (&str, 0, DBUS_TYPE_STRING,
01953                                 &v_STRING, byte_order,
01954                                 NULL);
01955       _dbus_assert (strcmp (v_STRING, "Hello") == 0);
01956 
01957       /* Do the other byte order */
01958       if (byte_order == DBUS_LITTLE_ENDIAN)
01959         byte_order = DBUS_BIG_ENDIAN;
01960       else
01961         break;
01962     }
01963 
01964   /* Clean up */
01965   _dbus_string_free (&str);
01966 
01967   return TRUE;
01968 }
01969 
01970 #endif /* DBUS_BUILD_TESTS */

Generated on Tue Aug 30 16:35:50 2005 for D-BUS by  doxygen 1.4.3