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