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

Generated on Tue Feb 24 16:40:39 2009 for D-Bus by  doxygen 1.5.1