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