D-Bus  1.10.12
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 _DBUS_STATIC_ASSERT (sizeof (dbus_int64_t) == 8);
00062 _DBUS_ASSERT_ALIGNMENT (dbus_int64_t, <=, 8);
00063 _DBUS_STATIC_ASSERT (sizeof (dbus_uint64_t) == 8);
00064 _DBUS_ASSERT_ALIGNMENT (dbus_uint64_t, <=, 8);
00065 
00066 _DBUS_STATIC_ASSERT (sizeof (DBusBasicValue) >= 8);
00067 /* The alignment of a DBusBasicValue might conceivably be > 8 because of the
00068  * pointer, so we don't assert about it */
00069 
00070 _DBUS_STATIC_ASSERT (sizeof (DBus8ByteStruct) == 8);
00071 _DBUS_ASSERT_ALIGNMENT (DBus8ByteStruct, <=, 8);
00072 
00088 static void
00089 pack_2_octets (dbus_uint16_t   value,
00090                int             byte_order,
00091                unsigned char  *data)
00092 {
00093   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 2) == data);
00094 
00095   if ((byte_order) == DBUS_LITTLE_ENDIAN)
00096     *((dbus_uint16_t*)(data)) = DBUS_UINT16_TO_LE (value);
00097   else
00098     *((dbus_uint16_t*)(data)) = DBUS_UINT16_TO_BE (value);
00099 }
00100 
00101 static void
00102 pack_4_octets (dbus_uint32_t   value,
00103                int             byte_order,
00104                unsigned char  *data)
00105 {
00106   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
00107 
00108   if ((byte_order) == DBUS_LITTLE_ENDIAN)
00109     *((dbus_uint32_t*)(data)) = DBUS_UINT32_TO_LE (value);
00110   else
00111     *((dbus_uint32_t*)(data)) = DBUS_UINT32_TO_BE (value);
00112 }
00113 
00114 static void
00115 pack_8_octets (DBusBasicValue     value,
00116                int                byte_order,
00117                unsigned char     *data)
00118 {
00119   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 8) == data);
00120 
00121   if ((byte_order) == DBUS_LITTLE_ENDIAN)
00122     *((dbus_uint64_t*)(data)) = DBUS_UINT64_TO_LE (value.u64);
00123   else
00124     *((dbus_uint64_t*)(data)) = DBUS_UINT64_TO_BE (value.u64);
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 static void
00143 swap_8_octets (DBusBasicValue    *value,
00144                int                byte_order)
00145 {
00146   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
00147     {
00148       value->u64 = DBUS_UINT64_SWAP_LE_BE (value->u64);
00149     }
00150 }
00151 
00152 #ifndef _dbus_unpack_uint16
00153 
00160 dbus_uint16_t
00161 _dbus_unpack_uint16 (int                  byte_order,
00162                      const unsigned char *data)
00163 {
00164   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 2) == data);
00165 
00166   if (byte_order == DBUS_LITTLE_ENDIAN)
00167     return DBUS_UINT16_FROM_LE (*(dbus_uint16_t*)data);
00168   else
00169     return DBUS_UINT16_FROM_BE (*(dbus_uint16_t*)data);
00170 }
00171 #endif /* _dbus_unpack_uint16 */
00172 
00173 #ifndef _dbus_unpack_uint32
00174 
00181 dbus_uint32_t
00182 _dbus_unpack_uint32 (int                  byte_order,
00183                      const unsigned char *data)
00184 {
00185   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
00186 
00187   if (byte_order == DBUS_LITTLE_ENDIAN)
00188     return DBUS_UINT32_FROM_LE (*(dbus_uint32_t*)data);
00189   else
00190     return DBUS_UINT32_FROM_BE (*(dbus_uint32_t*)data);
00191 }
00192 #endif /* _dbus_unpack_uint32 */
00193 
00194 static void
00195 set_2_octets (DBusString          *str,
00196               int                  offset,
00197               dbus_uint16_t        value,
00198               int                  byte_order)
00199 {
00200   char *data;
00201 
00202   _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
00203                 byte_order == DBUS_BIG_ENDIAN);
00204 
00205   data = _dbus_string_get_data_len (str, offset, 2);
00206 
00207   pack_2_octets (value, byte_order, data);
00208 }
00209 
00210 static void
00211 set_4_octets (DBusString          *str,
00212               int                  offset,
00213               dbus_uint32_t        value,
00214               int                  byte_order)
00215 {
00216   char *data;
00217 
00218   _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
00219                 byte_order == DBUS_BIG_ENDIAN);
00220 
00221   data = _dbus_string_get_data_len (str, offset, 4);
00222 
00223   pack_4_octets (value, byte_order, data);
00224 }
00225 
00226 static void
00227 set_8_octets (DBusString          *str,
00228               int                  offset,
00229               DBusBasicValue       value,
00230               int                  byte_order)
00231 {
00232   char *data;
00233 
00234   _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
00235                 byte_order == DBUS_BIG_ENDIAN);
00236 
00237   data = _dbus_string_get_data_len (str, offset, 8);
00238 
00239   pack_8_octets (value, byte_order, data);
00240 }
00241 
00252 void
00253 _dbus_marshal_set_uint32 (DBusString          *str,
00254                           int                  pos,
00255                           dbus_uint32_t        value,
00256                           int                  byte_order)
00257 {
00258   set_4_octets (str, pos, value, byte_order);
00259 }
00260 
00280 static dbus_bool_t
00281 set_string (DBusString          *str,
00282             int                  pos,
00283             const char          *value,
00284             int                  byte_order,
00285             int                 *old_end_pos,
00286             int                 *new_end_pos)
00287 {
00288   int old_len, new_len;
00289   DBusString dstr;
00290 
00291   _dbus_string_init_const (&dstr, value);
00292 
00293   _dbus_assert (_DBUS_ALIGN_VALUE (pos, 4) == (unsigned) pos);
00294   old_len = _dbus_unpack_uint32 (byte_order,
00295                                  _dbus_string_get_const_data_len (str, pos, 4));
00296 
00297   new_len = _dbus_string_get_length (&dstr);
00298 
00299   if (!_dbus_string_replace_len (&dstr, 0, new_len,
00300                                  str, pos + 4, old_len))
00301     return FALSE;
00302 
00303   _dbus_marshal_set_uint32 (str, pos, new_len, byte_order);
00304 
00305   if (old_end_pos)
00306     *old_end_pos = pos + 4 + old_len + 1;
00307   if (new_end_pos)
00308     *new_end_pos = pos + 4 + new_len + 1;
00309 
00310   return TRUE;
00311 }
00312 
00326 static dbus_bool_t
00327 set_signature (DBusString          *str,
00328                int                  pos,
00329                const char          *value,
00330                int                  byte_order,
00331                int                 *old_end_pos,
00332                int                 *new_end_pos)
00333 {
00334   int old_len, new_len;
00335   DBusString dstr;
00336 
00337   _dbus_string_init_const (&dstr, value);
00338 
00339   old_len = _dbus_string_get_byte (str, pos);
00340   new_len = _dbus_string_get_length (&dstr);
00341 
00342   if (!_dbus_string_replace_len (&dstr, 0, new_len,
00343                                  str, pos + 1, old_len))
00344     return FALSE;
00345 
00346   _dbus_string_set_byte (str, pos, new_len);
00347 
00348   if (old_end_pos)
00349     *old_end_pos = pos + 1 + old_len + 1;
00350   if (new_end_pos)
00351     *new_end_pos = pos + 1 + new_len + 1;
00352 
00353   return TRUE;
00354 }
00355 
00369 dbus_bool_t
00370 _dbus_marshal_set_basic (DBusString       *str,
00371                          int               pos,
00372                          int               type,
00373                          const void       *value,
00374                          int               byte_order,
00375                          int              *old_end_pos,
00376                          int              *new_end_pos)
00377 {
00378   const DBusBasicValue *vp;
00379 
00380   vp = value;
00381 
00382   switch (type)
00383     {
00384     case DBUS_TYPE_BYTE:
00385       _dbus_string_set_byte (str, pos, vp->byt);
00386       if (old_end_pos)
00387         *old_end_pos = pos + 1;
00388       if (new_end_pos)
00389         *new_end_pos = pos + 1;
00390       return TRUE;
00391       break;
00392     case DBUS_TYPE_INT16:
00393     case DBUS_TYPE_UINT16:
00394       pos = _DBUS_ALIGN_VALUE (pos, 2);
00395       set_2_octets (str, pos, vp->u16, byte_order);
00396       if (old_end_pos)
00397         *old_end_pos = pos + 2;
00398       if (new_end_pos)
00399         *new_end_pos = pos + 2;
00400       return TRUE;
00401       break;
00402     case DBUS_TYPE_BOOLEAN:
00403     case DBUS_TYPE_INT32:
00404     case DBUS_TYPE_UINT32:
00405     case DBUS_TYPE_UNIX_FD:
00406       pos = _DBUS_ALIGN_VALUE (pos, 4);
00407       set_4_octets (str, pos, vp->u32, byte_order);
00408       if (old_end_pos)
00409         *old_end_pos = pos + 4;
00410       if (new_end_pos)
00411         *new_end_pos = pos + 4;
00412       return TRUE;
00413       break;
00414     case DBUS_TYPE_INT64:
00415     case DBUS_TYPE_UINT64:
00416     case DBUS_TYPE_DOUBLE:
00417       pos = _DBUS_ALIGN_VALUE (pos, 8);
00418       set_8_octets (str, pos, *vp, byte_order);
00419       if (old_end_pos)
00420         *old_end_pos = pos + 8;
00421       if (new_end_pos)
00422         *new_end_pos = pos + 8;
00423       return TRUE;
00424       break;
00425     case DBUS_TYPE_STRING:
00426     case DBUS_TYPE_OBJECT_PATH:
00427       pos = _DBUS_ALIGN_VALUE (pos, 4);
00428       _dbus_assert (vp->str != NULL);
00429       return set_string (str, pos, vp->str, byte_order,
00430                          old_end_pos, new_end_pos);
00431       break;
00432     case DBUS_TYPE_SIGNATURE:
00433       _dbus_assert (vp->str != NULL);
00434       return set_signature (str, pos, vp->str, byte_order,
00435                             old_end_pos, new_end_pos);
00436       break;
00437     default:
00438       _dbus_assert_not_reached ("not a basic type");
00439       return FALSE;
00440       break;
00441     }
00442 }
00443 
00453 dbus_uint32_t
00454 _dbus_marshal_read_uint32  (const DBusString *str,
00455                             int               pos,
00456                             int               byte_order,
00457                             int              *new_pos)
00458 {
00459   pos = _DBUS_ALIGN_VALUE (pos, 4);
00460 
00461   if (new_pos)
00462     *new_pos = pos + 4;
00463 
00464   _dbus_assert (pos + 4 <= _dbus_string_get_length (str));
00465   
00466   return _dbus_unpack_uint32 (byte_order,
00467                               _dbus_string_get_const_data (str) + pos);
00468 }
00469 
00491 void
00492 _dbus_marshal_read_basic (const DBusString      *str,
00493                           int                    pos,
00494                           int                    type,
00495                           void                  *value,
00496                           int                    byte_order,
00497                           int                   *new_pos)
00498 {
00499   const char *str_data;
00500 
00501   _dbus_assert (dbus_type_is_basic (type));
00502 
00503   str_data = _dbus_string_get_const_data (str);
00504 
00505   /* Below we volatile types to avoid aliasing issues;
00506    * see http://bugs.freedesktop.org/show_bug.cgi?id=20137
00507    */
00508   
00509   switch (type)
00510     {
00511     case DBUS_TYPE_BYTE:
00512       {
00513       volatile unsigned char *vp = value;
00514       *vp = (unsigned char) _dbus_string_get_byte (str, pos);
00515       (pos)++;
00516       }
00517       break;
00518     case DBUS_TYPE_INT16:
00519     case DBUS_TYPE_UINT16:
00520       {
00521       volatile dbus_uint16_t *vp = value;
00522       pos = _DBUS_ALIGN_VALUE (pos, 2);
00523       *vp = *(dbus_uint16_t *)(str_data + pos);
00524       if (byte_order != DBUS_COMPILER_BYTE_ORDER)
00525         *vp = DBUS_UINT16_SWAP_LE_BE (*vp);
00526       pos += 2;
00527       }
00528       break;
00529     case DBUS_TYPE_INT32:
00530     case DBUS_TYPE_UINT32:
00531     case DBUS_TYPE_BOOLEAN:
00532     case DBUS_TYPE_UNIX_FD:
00533       {
00534       volatile dbus_uint32_t *vp = value;
00535       pos = _DBUS_ALIGN_VALUE (pos, 4);
00536       *vp = *(dbus_uint32_t *)(str_data + pos);
00537       if (byte_order != DBUS_COMPILER_BYTE_ORDER)
00538         *vp = DBUS_UINT32_SWAP_LE_BE (*vp);
00539       pos += 4;
00540       }
00541       break;
00542     case DBUS_TYPE_INT64:
00543     case DBUS_TYPE_UINT64:
00544     case DBUS_TYPE_DOUBLE:
00545       {
00546       volatile dbus_uint64_t *vp = value;
00547       pos = _DBUS_ALIGN_VALUE (pos, 8);
00548       if (byte_order != DBUS_COMPILER_BYTE_ORDER)
00549         *vp = DBUS_UINT64_SWAP_LE_BE (*(dbus_uint64_t*)(str_data + pos));
00550       else
00551         *vp = *(dbus_uint64_t*)(str_data + pos);
00552       pos += 8;
00553       }
00554       break;
00555     case DBUS_TYPE_STRING:
00556     case DBUS_TYPE_OBJECT_PATH:
00557       {
00558         int len;
00559         volatile char **vp = value;
00560 
00561         len = _dbus_marshal_read_uint32 (str, pos, byte_order, &pos);
00562 
00563         *vp = (char*) str_data + pos;
00564 
00565         pos += len + 1; /* length plus nul */
00566       }
00567       break;
00568     case DBUS_TYPE_SIGNATURE:
00569       {
00570         int len;
00571         volatile char **vp = value;
00572 
00573         len = _dbus_string_get_byte (str, pos);
00574         pos += 1;
00575 
00576         *vp = (char*) str_data + pos;
00577 
00578         pos += len + 1; /* length plus nul */
00579       }
00580       break;
00581     default:
00582       _dbus_warn_check_failed ("type %s %d not a basic type\n",
00583                                _dbus_type_to_string (type), type);
00584       _dbus_assert_not_reached ("not a basic type");
00585       break;
00586     }
00587 
00588   if (new_pos)
00589     *new_pos = pos;
00590 }
00591 
00592 static dbus_bool_t
00593 marshal_2_octets (DBusString   *str,
00594                   int           insert_at,
00595                   dbus_uint16_t value,
00596                   int           byte_order,
00597                   int          *pos_after)
00598 {
00599   dbus_bool_t retval;
00600   int orig_len;
00601 
00602   _DBUS_STATIC_ASSERT (sizeof (value) == 2);
00603 
00604   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
00605     value = DBUS_UINT16_SWAP_LE_BE (value);
00606 
00607   orig_len = _dbus_string_get_length (str);
00608 
00609   retval = _dbus_string_insert_2_aligned (str, insert_at,
00610                                           (const unsigned char *)&value);
00611 
00612   if (pos_after)
00613     {
00614       *pos_after = insert_at + (_dbus_string_get_length (str) - orig_len);
00615       _dbus_assert (*pos_after <= _dbus_string_get_length (str));
00616     }
00617 
00618   return retval;
00619 }
00620 
00621 static dbus_bool_t
00622 marshal_4_octets (DBusString   *str,
00623                   int           insert_at,
00624                   dbus_uint32_t value,
00625                   int           byte_order,
00626                   int          *pos_after)
00627 {
00628   dbus_bool_t retval;
00629   int orig_len;
00630 
00631   _DBUS_STATIC_ASSERT (sizeof (value) == 4);
00632 
00633   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
00634     value = DBUS_UINT32_SWAP_LE_BE (value);
00635 
00636   orig_len = _dbus_string_get_length (str);
00637 
00638   retval = _dbus_string_insert_4_aligned (str, insert_at,
00639                                           (const unsigned char *)&value);
00640 
00641   if (pos_after)
00642     {
00643       *pos_after = insert_at + (_dbus_string_get_length (str) - orig_len);
00644       _dbus_assert (*pos_after <= _dbus_string_get_length (str));
00645     }
00646 
00647   return retval;
00648 }
00649 
00650 static dbus_bool_t
00651 marshal_8_octets (DBusString    *str,
00652                   int            insert_at,
00653                   DBusBasicValue value,
00654                   int            byte_order,
00655                   int           *pos_after)
00656 {
00657   dbus_bool_t retval;
00658   int orig_len;
00659 
00660   _DBUS_STATIC_ASSERT (sizeof (value) == 8);
00661 
00662   swap_8_octets (&value, byte_order);
00663 
00664   orig_len = _dbus_string_get_length (str);
00665 
00666   retval = _dbus_string_insert_8_aligned (str, insert_at,
00667                                           (const unsigned char *)&value);
00668 
00669   if (pos_after)
00670     *pos_after = insert_at + _dbus_string_get_length (str) - orig_len;
00671 
00672   return retval;
00673 }
00674 
00675 enum
00676   {
00677     MARSHAL_AS_STRING,
00678     MARSHAL_AS_SIGNATURE,
00679     MARSHAL_AS_BYTE_ARRAY
00680   };
00681 
00682 static dbus_bool_t
00683 marshal_len_followed_by_bytes (int                  marshal_as,
00684                                DBusString          *str,
00685                                int                  insert_at,
00686                                const unsigned char *value,
00687                                int                  data_len, /* doesn't include nul if any */
00688                                int                  byte_order,
00689                                int                 *pos_after)
00690 {
00691   int pos;
00692   DBusString value_str;
00693   int value_len;
00694 
00695   _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN || byte_order == DBUS_BIG_ENDIAN);
00696   if (insert_at > _dbus_string_get_length (str))
00697     _dbus_warn ("insert_at = %d string len = %d data_len = %d\n",
00698                 insert_at, _dbus_string_get_length (str), data_len);
00699   
00700   if (marshal_as == MARSHAL_AS_BYTE_ARRAY)
00701     value_len = data_len;
00702   else
00703     value_len = data_len + 1; /* value has a nul */
00704 
00705   _dbus_string_init_const_len (&value_str, value, value_len);
00706 
00707   pos = insert_at;
00708 
00709   if (marshal_as == MARSHAL_AS_SIGNATURE)
00710     {
00711       _dbus_assert (data_len <= DBUS_MAXIMUM_SIGNATURE_LENGTH);
00712       _dbus_assert (data_len <= 255); /* same as max sig len right now */
00713       
00714       if (!_dbus_string_insert_byte (str, pos, data_len))
00715         goto oom;
00716 
00717       pos += 1;
00718     }
00719   else
00720     {
00721       if (!marshal_4_octets (str, pos, data_len,
00722                              byte_order, &pos))
00723         goto oom;
00724     }
00725 
00726   if (!_dbus_string_copy_len (&value_str, 0, value_len,
00727                               str, pos))
00728     goto oom;
00729 
00730 #if 0
00731   /* too expensive */
00732   _dbus_assert (_dbus_string_equal_substring (&value_str, 0, value_len,
00733                                               str, pos));
00734   _dbus_verbose_bytes_of_string (str, pos, value_len);
00735 #endif
00736 
00737   pos += value_len;
00738 
00739   if (pos_after)
00740     *pos_after = pos;
00741 
00742   return TRUE;
00743 
00744  oom:
00745   /* Delete what we've inserted */
00746   _dbus_string_delete (str, insert_at, pos - insert_at);
00747 
00748   return FALSE;
00749 }
00750 
00751 static dbus_bool_t
00752 marshal_string (DBusString    *str,
00753                 int            insert_at,
00754                 const char    *value,
00755                 int            byte_order,
00756                 int           *pos_after)
00757 {
00758   return marshal_len_followed_by_bytes (MARSHAL_AS_STRING,
00759                                         str, insert_at, value,
00760                                         strlen (value),
00761                                         byte_order, pos_after);
00762 }
00763 
00764 static dbus_bool_t
00765 marshal_signature (DBusString    *str,
00766                    int            insert_at,
00767                    const char    *value,
00768                    int           *pos_after)
00769 {
00770   return marshal_len_followed_by_bytes (MARSHAL_AS_SIGNATURE,
00771                                         str, insert_at, value,
00772                                         strlen (value),
00773                                         DBUS_COMPILER_BYTE_ORDER, /* irrelevant */
00774                                         pos_after);
00775 }
00776 
00793 dbus_bool_t
00794 _dbus_marshal_write_basic (DBusString *str,
00795                            int         insert_at,
00796                            int         type,
00797                            const void *value,
00798                            int         byte_order,
00799                            int        *pos_after)
00800 {
00801   const DBusBasicValue *vp;
00802 
00803   _dbus_assert (dbus_type_is_basic (type));
00804 
00805   vp = value;
00806 
00807   switch (type)
00808     {
00809     case DBUS_TYPE_BYTE:
00810       if (!_dbus_string_insert_byte (str, insert_at, vp->byt))
00811         return FALSE;
00812       if (pos_after)
00813         *pos_after = insert_at + 1;
00814       return TRUE;
00815       break;
00816     case DBUS_TYPE_INT16:
00817     case DBUS_TYPE_UINT16:
00818       return marshal_2_octets (str, insert_at, vp->u16,
00819                                byte_order, pos_after);
00820       break;
00821     case DBUS_TYPE_BOOLEAN:
00822       return marshal_4_octets (str, insert_at, vp->u32 != FALSE,
00823                                byte_order, pos_after);
00824       break;
00825     case DBUS_TYPE_INT32:
00826     case DBUS_TYPE_UINT32:
00827     case DBUS_TYPE_UNIX_FD:
00828       return marshal_4_octets (str, insert_at, vp->u32,
00829                                byte_order, pos_after);
00830       break;
00831     case DBUS_TYPE_INT64:
00832     case DBUS_TYPE_UINT64:
00833     case DBUS_TYPE_DOUBLE:
00834       return marshal_8_octets (str, insert_at, *vp, byte_order, pos_after);
00835       break;
00836 
00837     case DBUS_TYPE_STRING:
00838     case DBUS_TYPE_OBJECT_PATH:
00839       _dbus_assert (vp->str != NULL);
00840       return marshal_string (str, insert_at, vp->str, byte_order, pos_after);
00841       break;
00842     case DBUS_TYPE_SIGNATURE:
00843       _dbus_assert (vp->str != NULL);
00844       return marshal_signature (str, insert_at, vp->str, pos_after);
00845       break;
00846     default:
00847       _dbus_assert_not_reached ("not a basic type");
00848       return FALSE;
00849       break;
00850     }
00851 }
00852 
00853 static dbus_bool_t
00854 marshal_1_octets_array (DBusString          *str,
00855                         int                  insert_at,
00856                         const unsigned char *value,
00857                         int                  n_elements,
00858                         int                  byte_order,
00859                         int                 *pos_after)
00860 {
00861   int pos;
00862   DBusString value_str;
00863 
00864   _dbus_string_init_const_len (&value_str, value, n_elements);
00865 
00866   pos = insert_at;
00867 
00868   if (!_dbus_string_copy_len (&value_str, 0, n_elements,
00869                               str, pos))
00870     return FALSE;
00871 
00872   pos += n_elements;
00873 
00874   if (pos_after)
00875     *pos_after = pos;
00876 
00877   return TRUE;
00878 }
00879 
00887 void
00888 _dbus_swap_array (unsigned char *data,
00889                   int            n_elements,
00890                   int            alignment)
00891 {
00892   unsigned char *d;
00893   unsigned char *end;
00894 
00895   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, alignment) == data);
00896 
00897   /* we use const_data and cast it off so DBusString can be a const string
00898    * for the unit tests. don't ask.
00899    */
00900   d = data;
00901   end = d + (n_elements * alignment);
00902   
00903   if (alignment == 8)
00904     {
00905       while (d != end)
00906         {
00907           *((dbus_uint64_t*)d) = DBUS_UINT64_SWAP_LE_BE (*((dbus_uint64_t*)d));
00908           d += 8;
00909         }
00910     }
00911   else if (alignment == 4)
00912     {
00913       while (d != end)
00914         {
00915           *((dbus_uint32_t*)d) = DBUS_UINT32_SWAP_LE_BE (*((dbus_uint32_t*)d));
00916           d += 4;
00917         }
00918     }
00919   else
00920     {
00921       _dbus_assert (alignment == 2);
00922       
00923       while (d != end)
00924         {
00925           *((dbus_uint16_t*)d) = DBUS_UINT16_SWAP_LE_BE (*((dbus_uint16_t*)d));
00926           d += 2;
00927         }
00928     }
00929 }
00930 
00931 static void
00932 swap_array (DBusString *str,
00933             int         array_start,
00934             int         n_elements,
00935             int         byte_order,
00936             int         alignment)
00937 {
00938   _dbus_assert (_DBUS_ALIGN_VALUE (array_start, alignment) == (unsigned) array_start);
00939 
00940   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
00941     {
00942       /* we use const_data and cast it off so DBusString can be a const string
00943        * for the unit tests. don't ask.
00944        */
00945       _dbus_swap_array ((unsigned char*) (_dbus_string_get_const_data (str) + array_start),
00946                         n_elements, alignment);
00947     }
00948 }
00949 
00950 static dbus_bool_t
00951 marshal_fixed_multi (DBusString           *str,
00952                      int                   insert_at,
00953                      const DBusBasicValue *value,
00954                      int                   n_elements,
00955                      int                   byte_order,
00956                      int                   alignment,
00957                      int                  *pos_after)
00958 {
00959   int old_string_len;
00960   int array_start;
00961   DBusString t;
00962   int len_in_bytes;
00963 
00964   _dbus_assert (n_elements <= DBUS_MAXIMUM_ARRAY_LENGTH / alignment);
00965   
00966   old_string_len = _dbus_string_get_length (str);
00967 
00968   len_in_bytes = n_elements * alignment;
00969   array_start = insert_at;
00970   
00971   /* Note that we do alignment padding unconditionally
00972    * even if the array is empty; this means that
00973    * padding + len is always equal to the number of bytes
00974    * in the array.
00975    */
00976 
00977   if (!_dbus_string_insert_alignment (str, &array_start, alignment))
00978     goto error;
00979 
00980   _dbus_string_init_const_len (&t,
00981                                (const unsigned char*) value,
00982                                len_in_bytes);
00983 
00984   if (!_dbus_string_copy (&t, 0,
00985                           str, array_start))
00986     goto error;
00987 
00988   swap_array (str, array_start, n_elements, byte_order, alignment);
00989 
00990   if (pos_after)
00991     *pos_after = array_start + len_in_bytes;
00992   
00993   return TRUE;
00994 
00995  error:
00996   _dbus_string_delete (str, insert_at,
00997                        _dbus_string_get_length (str) - old_string_len);
00998 
00999   return FALSE;
01000 }
01001 
01019 dbus_bool_t
01020 _dbus_marshal_write_fixed_multi (DBusString *str,
01021                                  int         insert_at,
01022                                  int         element_type,
01023                                  const void *value,
01024                                  int         n_elements,
01025                                  int         byte_order,
01026                                  int        *pos_after)
01027 {
01028   const void* vp = *(const DBusBasicValue**)value;
01029   
01030   _dbus_assert (dbus_type_is_fixed (element_type));
01031   _dbus_assert (n_elements >= 0);
01032 
01033 #if 0
01034   _dbus_verbose ("writing %d elements of %s\n",
01035                  n_elements, _dbus_type_to_string (element_type));
01036 #endif
01037   
01038   switch (element_type)
01039     {
01040     case DBUS_TYPE_BYTE:
01041       return marshal_1_octets_array (str, insert_at, vp, n_elements, byte_order, pos_after);
01042       break;
01043     case DBUS_TYPE_INT16:
01044     case DBUS_TYPE_UINT16:
01045       return marshal_fixed_multi (str, insert_at, vp, n_elements, byte_order, 2, pos_after);
01046     case DBUS_TYPE_BOOLEAN:
01047     case DBUS_TYPE_INT32:
01048     case DBUS_TYPE_UINT32:
01049     case DBUS_TYPE_UNIX_FD:
01050       return marshal_fixed_multi (str, insert_at, vp, n_elements, byte_order, 4, pos_after);
01051       break;
01052     case DBUS_TYPE_INT64:
01053     case DBUS_TYPE_UINT64:
01054     case DBUS_TYPE_DOUBLE:
01055       return marshal_fixed_multi (str, insert_at, vp, n_elements, byte_order, 8, pos_after);
01056       break;
01057 
01058     default:
01059       _dbus_assert_not_reached ("non fixed type in array write");
01060       break;
01061     }
01062 
01063   return FALSE;
01064 }
01065 
01066 
01076 void
01077 _dbus_marshal_skip_basic (const DBusString      *str,
01078                           int                    type,
01079                           int                    byte_order,
01080                           int                   *pos)
01081 {
01082   _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
01083                 byte_order == DBUS_BIG_ENDIAN);
01084   
01085   switch (type)
01086     {
01087     case DBUS_TYPE_BYTE:
01088       (*pos)++;
01089       break;
01090     case DBUS_TYPE_INT16:
01091     case DBUS_TYPE_UINT16:
01092       *pos = _DBUS_ALIGN_VALUE (*pos, 2);
01093       *pos += 2;
01094       break;
01095     case DBUS_TYPE_BOOLEAN:
01096     case DBUS_TYPE_INT32:
01097     case DBUS_TYPE_UINT32:
01098     case DBUS_TYPE_UNIX_FD:
01099       *pos = _DBUS_ALIGN_VALUE (*pos, 4);
01100       *pos += 4;
01101       break;
01102     case DBUS_TYPE_INT64:
01103     case DBUS_TYPE_UINT64:
01104     case DBUS_TYPE_DOUBLE:
01105       *pos = _DBUS_ALIGN_VALUE (*pos, 8);
01106       *pos += 8;
01107       break;
01108     case DBUS_TYPE_STRING:
01109     case DBUS_TYPE_OBJECT_PATH:
01110       {
01111         int len;
01112 
01113         len = _dbus_marshal_read_uint32 (str, *pos, byte_order, pos);
01114         
01115         *pos += len + 1; /* length plus nul */
01116       }
01117       break;
01118     case DBUS_TYPE_SIGNATURE:
01119       {
01120         int len;
01121 
01122         len = _dbus_string_get_byte (str, *pos);
01123 
01124         *pos += len + 2; /* length byte plus length plus nul */
01125       }
01126       break;
01127     default:
01128       _dbus_warn ("type %s not a basic type\n",
01129                   _dbus_type_to_string (type));
01130       _dbus_assert_not_reached ("not a basic type");
01131       break;
01132     }
01133 }
01134 
01144 void
01145 _dbus_marshal_skip_array (const DBusString  *str,
01146                           int                element_type,
01147                           int                byte_order,
01148                           int               *pos)
01149 {
01150   dbus_uint32_t array_len;
01151   int i;
01152   int alignment;
01153 
01154   i = _DBUS_ALIGN_VALUE (*pos, 4);
01155 
01156   array_len = _dbus_marshal_read_uint32 (str, i, byte_order, &i);
01157 
01158   alignment = _dbus_type_get_alignment (element_type);
01159 
01160   i = _DBUS_ALIGN_VALUE (i, alignment);
01161 
01162   *pos = i + array_len;
01163 }
01164 
01172 int
01173 _dbus_type_get_alignment (int typecode)
01174 {
01175   switch (typecode)
01176     {
01177     case DBUS_TYPE_BYTE:
01178     case DBUS_TYPE_VARIANT:
01179     case DBUS_TYPE_SIGNATURE:
01180       return 1;
01181     case DBUS_TYPE_INT16:
01182     case DBUS_TYPE_UINT16:
01183       return 2;
01184     case DBUS_TYPE_BOOLEAN:
01185     case DBUS_TYPE_INT32:
01186     case DBUS_TYPE_UINT32:
01187     case DBUS_TYPE_UNIX_FD:
01188       /* this stuff is 4 since it starts with a length */
01189     case DBUS_TYPE_STRING:
01190     case DBUS_TYPE_OBJECT_PATH:
01191     case DBUS_TYPE_ARRAY:
01192       return 4;
01193     case DBUS_TYPE_INT64:
01194     case DBUS_TYPE_UINT64:
01195     case DBUS_TYPE_DOUBLE:
01196       /* struct is 8 since it could contain an 8-aligned item
01197        * and it's simpler to just always align structs to 8;
01198        * we want the amount of padding in a struct of a given
01199        * type to be predictable, not location-dependent.
01200        * DICT_ENTRY is always the same as struct.
01201        */
01202     case DBUS_TYPE_STRUCT:
01203     case DBUS_TYPE_DICT_ENTRY:
01204       return 8;
01205 
01206     default:
01207       _dbus_assert_not_reached ("unknown typecode in _dbus_type_get_alignment()");
01208       return 0;
01209     }
01210 }
01211 
01218 const char *
01219 _dbus_type_to_string (int typecode)
01220 {
01221   switch (typecode)
01222     {
01223     case DBUS_TYPE_INVALID:
01224       return "invalid";
01225     case DBUS_TYPE_BOOLEAN:
01226       return "boolean";
01227     case DBUS_TYPE_BYTE:
01228       return "byte";
01229     case DBUS_TYPE_INT16:
01230       return "int16";
01231     case DBUS_TYPE_UINT16:
01232       return "uint16";
01233     case DBUS_TYPE_INT32:
01234       return "int32";
01235     case DBUS_TYPE_UINT32:
01236       return "uint32";
01237     case DBUS_TYPE_INT64:
01238       return "int64";
01239     case DBUS_TYPE_UINT64:
01240       return "uint64";      
01241     case DBUS_TYPE_DOUBLE:
01242       return "double";
01243     case DBUS_TYPE_STRING:
01244       return "string";
01245     case DBUS_TYPE_OBJECT_PATH:
01246       return "object_path";
01247     case DBUS_TYPE_SIGNATURE:
01248       return "signature";
01249     case DBUS_TYPE_STRUCT:
01250       return "struct";
01251     case DBUS_TYPE_DICT_ENTRY:
01252       return "dict_entry";
01253     case DBUS_TYPE_ARRAY:
01254       return "array";
01255     case DBUS_TYPE_VARIANT:
01256       return "variant";
01257     case DBUS_STRUCT_BEGIN_CHAR:
01258       return "begin_struct";
01259     case DBUS_STRUCT_END_CHAR:
01260       return "end_struct";
01261     case DBUS_DICT_ENTRY_BEGIN_CHAR:
01262       return "begin_dict_entry";
01263     case DBUS_DICT_ENTRY_END_CHAR:
01264       return "end_dict_entry";
01265     case DBUS_TYPE_UNIX_FD:
01266       return "unix_fd";
01267     default:
01268       return "unknown";
01269     }
01270 }
01271 
01279 void
01280 _dbus_verbose_bytes (const unsigned char *data,
01281                      int                  len,
01282                      int                  offset)
01283 {
01284   int i;
01285   const unsigned char *aligned;
01286 
01287   _dbus_assert (len >= 0);
01288 
01289   if (!_dbus_is_verbose())
01290     return;
01291 
01292   /* Print blanks on first row if appropriate */
01293   aligned = _DBUS_ALIGN_ADDRESS (data, 4);
01294   if (aligned > data)
01295     aligned -= 4;
01296   _dbus_assert (aligned <= data);
01297 
01298   if (aligned != data)
01299     {
01300       _dbus_verbose ("%4ld\t%p: ", - (long)(data - aligned), aligned);
01301       while (aligned != data)
01302         {
01303           _dbus_verbose ("    ");
01304           ++aligned;
01305         }
01306     }
01307 
01308   /* now print the bytes */
01309   i = 0;
01310   while (i < len)
01311     {
01312       if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
01313         {
01314           _dbus_verbose ("%4d\t%p: ",
01315                          offset + i, &data[i]);
01316         }
01317 
01318       if (data[i] >= 32 &&
01319           data[i] <= 126)
01320         _dbus_verbose (" '%c' ", data[i]);
01321       else
01322         _dbus_verbose ("0x%s%x ",
01323                        data[i] <= 0xf ? "0" : "", data[i]);
01324 
01325       ++i;
01326 
01327       if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
01328         {
01329           if (i > 3)
01330             _dbus_verbose ("BE: %d LE: %d",
01331                            _dbus_unpack_uint32 (DBUS_BIG_ENDIAN, &data[i-4]),
01332                            _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN, &data[i-4]));
01333 
01334           if (i > 7 &&
01335               _DBUS_ALIGN_ADDRESS (&data[i], 8) == &data[i])
01336             {
01337 #ifdef DBUS_INT64_PRINTF_MODIFIER
01338               _dbus_verbose (" u64: 0x%" DBUS_INT64_PRINTF_MODIFIER "x",
01339                              *(dbus_uint64_t*)&data[i-8]);
01340 #endif
01341               _dbus_verbose (" dbl: %g",
01342                              *(double*)&data[i-8]);
01343             }
01344 
01345           _dbus_verbose ("\n");
01346         }
01347     }
01348 
01349   _dbus_verbose ("\n");
01350 }
01351 
01359 void
01360 _dbus_verbose_bytes_of_string (const DBusString    *str,
01361                                int                  start,
01362                                int                  len)
01363 {
01364   const char *d;
01365   int real_len;
01366 
01367   real_len = _dbus_string_get_length (str);
01368 
01369   _dbus_assert (start >= 0);
01370 
01371   if (start > real_len)
01372     {
01373       _dbus_verbose ("  [%d,%d) is not inside string of length %d\n",
01374                      start, len, real_len);
01375       return;
01376     }
01377 
01378   if ((start + len) > real_len)
01379     {
01380       _dbus_verbose ("  [%d,%d) extends outside string of length %d\n",
01381                      start, len, real_len);
01382       len = real_len - start;
01383     }
01384 
01385   d = _dbus_string_get_const_data_len (str, start, len);
01386 
01387   _dbus_verbose_bytes (d, len, start);
01388 }
01389 
01390 static int
01391 map_type_char_to_type (int t)
01392 {
01393   if (t == DBUS_STRUCT_BEGIN_CHAR)
01394     return DBUS_TYPE_STRUCT;
01395   else if (t == DBUS_DICT_ENTRY_BEGIN_CHAR)
01396     return DBUS_TYPE_DICT_ENTRY;
01397   else
01398     {
01399       _dbus_assert (t != DBUS_STRUCT_END_CHAR);
01400       _dbus_assert (t != DBUS_DICT_ENTRY_END_CHAR);
01401       return t;
01402     }
01403 }
01404 
01415 int
01416 _dbus_first_type_in_signature (const DBusString *str,
01417                                int               pos)
01418 {
01419   return map_type_char_to_type (_dbus_string_get_byte (str, pos));
01420 }
01421 
01430 int
01431 _dbus_first_type_in_signature_c_str (const char       *str,
01432                                      int               pos)
01433 {
01434   return map_type_char_to_type (str[pos]);
01435 }
01436 
01439 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
01440 #include "dbus-test.h"
01441 #include <stdio.h>
01442 
01461 void
01462 _dbus_marshal_read_fixed_multi  (const DBusString *str,
01463                                  int               pos,
01464                                  int               element_type,
01465                                  void             *value,
01466                                  int               n_elements,
01467                                  int               byte_order,
01468                                  int              *new_pos)
01469 {
01470   int array_len;
01471   int alignment;
01472 
01473   _dbus_assert (dbus_type_is_fixed (element_type));
01474   _dbus_assert (dbus_type_is_basic (element_type));
01475 
01476 #if 0
01477   _dbus_verbose ("reading %d elements of %s\n",
01478                  n_elements, _dbus_type_to_string (element_type));
01479 #endif
01480   
01481   alignment = _dbus_type_get_alignment (element_type);
01482 
01483   pos = _DBUS_ALIGN_VALUE (pos, alignment);
01484   
01485   array_len = n_elements * alignment;
01486 
01487   *(const DBusBasicValue**) value = (void*) _dbus_string_get_const_data_len (str, pos, array_len);
01488   if (new_pos)
01489     *new_pos = pos + array_len;
01490 }
01491 
01492 static void
01493 swap_test_array (void *array,
01494                  int   len_bytes,
01495                  int   byte_order,
01496                  int   alignment)
01497 {
01498   DBusString t;
01499 
01500   if (alignment == 1)
01501     return;
01502   
01503   _dbus_string_init_const_len (&t, array, len_bytes);
01504   swap_array (&t, 0, len_bytes / alignment, byte_order, alignment);
01505 }
01506 
01507 #define MARSHAL_BASIC(typename, byte_order, literal)                    \
01508   do {                                                                  \
01509      v_##typename = literal;                                            \
01510      if (!_dbus_marshal_write_basic (&str, pos, DBUS_TYPE_##typename,   \
01511                                     &v_##typename,                      \
01512                                     byte_order, NULL))                  \
01513        _dbus_assert_not_reached ("no memory");                          \
01514    } while (0)
01515 
01516 #define DEMARSHAL_BASIC(typename, byte_order)                                   \
01517   do {                                                                          \
01518     _dbus_marshal_read_basic (&str, pos, DBUS_TYPE_##typename, &v_##typename,   \
01519                               byte_order, &pos);                                \
01520   } while (0)
01521 
01522 #define DEMARSHAL_BASIC_AND_CHECK(typename, byte_order, literal)                        \
01523   do {                                                                                  \
01524     DEMARSHAL_BASIC (typename, byte_order);                                             \
01525     if (literal != v_##typename)                                                        \
01526       {                                                                                 \
01527         _dbus_verbose_bytes_of_string (&str, dump_pos,                                  \
01528                                      _dbus_string_get_length (&str) - dump_pos);        \
01529         _dbus_assert_not_reached ("demarshaled wrong value");                           \
01530       }                                                                                 \
01531   } while (0)
01532 
01533 #define MARSHAL_TEST(typename, byte_order, literal)             \
01534   do {                                                          \
01535     MARSHAL_BASIC (typename, byte_order, literal);              \
01536     dump_pos = pos;                                             \
01537     DEMARSHAL_BASIC_AND_CHECK (typename, byte_order, literal);  \
01538   } while (0)
01539 
01540 #define MARSHAL_TEST_STRCMP(typename, byte_order, literal)                              \
01541   do {                                                                                  \
01542     MARSHAL_BASIC (typename, byte_order, literal);                                      \
01543     dump_pos = pos;                                                                     \
01544     DEMARSHAL_BASIC (typename, byte_order);                                             \
01545     if (strcmp (literal, v_##typename) != 0)                                            \
01546       {                                                                                 \
01547         _dbus_verbose_bytes_of_string (&str, dump_pos,                                  \
01548                                        _dbus_string_get_length (&str) - dump_pos);      \
01549         _dbus_warn ("literal '%s'\nvalue  '%s'\n", literal, v_##typename);              \
01550         _dbus_assert_not_reached ("demarshaled wrong value");                           \
01551       }                                                                                 \
01552   } while (0)
01553 
01554 #define MARSHAL_FIXED_ARRAY(typename, byte_order, literal)                                      \
01555   do {                                                                                          \
01556      int next;                                                                                  \
01557      v_UINT32 = sizeof(literal);                                                                \
01558      if (!_dbus_marshal_write_basic (&str, pos, DBUS_TYPE_UINT32, &v_UINT32,                    \
01559                                      byte_order, &next))                                        \
01560        _dbus_assert_not_reached ("no memory");                                                  \
01561      v_ARRAY_##typename = literal;                                                              \
01562      if (!_dbus_marshal_write_fixed_multi (&str, next, DBUS_TYPE_##typename,                    \
01563                                            &v_ARRAY_##typename, _DBUS_N_ELEMENTS(literal),      \
01564                                            byte_order, NULL))                                   \
01565        _dbus_assert_not_reached ("no memory");                                                  \
01566    } while (0)
01567 
01568 #define DEMARSHAL_FIXED_ARRAY(typename, byte_order)                                             \
01569   do {                                                                                          \
01570     int next;                                                                                   \
01571     alignment = _dbus_type_get_alignment (DBUS_TYPE_##typename);                                \
01572     v_UINT32 = _dbus_marshal_read_uint32 (&str, dump_pos, byte_order, &next);                   \
01573     _dbus_marshal_read_fixed_multi (&str, next, DBUS_TYPE_##typename, &v_ARRAY_##typename,      \
01574                                     v_UINT32/alignment,                                         \
01575                                     byte_order, NULL);                                          \
01576     swap_test_array (v_ARRAY_##typename, v_UINT32,                                              \
01577                      byte_order, alignment);                                                    \
01578   } while (0)
01579 
01580 #define DEMARSHAL_FIXED_ARRAY_AND_CHECK(typename, byte_order, literal)                  \
01581   do {                                                                                  \
01582     DEMARSHAL_FIXED_ARRAY (typename, byte_order);                                       \
01583     if (memcmp (literal, v_ARRAY_##typename, sizeof (literal)) != 0)                    \
01584       {                                                                                 \
01585         _dbus_verbose ("MARSHALED DATA\n");                                             \
01586         _dbus_verbose_bytes_of_string (&str, dump_pos,                                  \
01587                                       _dbus_string_get_length (&str) - dump_pos);       \
01588         _dbus_verbose ("LITERAL DATA\n");                                               \
01589         _dbus_verbose_bytes ((char*)literal, sizeof (literal), 0);                      \
01590         _dbus_verbose ("READ DATA\n");                                                  \
01591         _dbus_verbose_bytes ((char*)v_ARRAY_##typename, sizeof (literal), 0);           \
01592         _dbus_assert_not_reached ("demarshaled wrong fixed array value");               \
01593       }                                                                                 \
01594   } while (0)
01595 
01596 #define MARSHAL_TEST_FIXED_ARRAY(typename, byte_order, literal)         \
01597   do {                                                                  \
01598     MARSHAL_FIXED_ARRAY (typename, byte_order, literal);                \
01599     dump_pos = pos;                                                     \
01600     DEMARSHAL_FIXED_ARRAY_AND_CHECK (typename, byte_order, literal);    \
01601   } while (0)
01602 
01603 dbus_bool_t
01604 _dbus_marshal_test (void)
01605 {
01606   int alignment;
01607   DBusString str;
01608   int pos, dump_pos;
01609   unsigned char array1[5] = { 3, 4, 0, 1, 9 };
01610   dbus_int16_t array2[3] = { 124, 457, 780 };
01611   dbus_int32_t array4[3] = { 123, 456, 789 };
01612   dbus_int64_t array8[3] = { DBUS_INT64_CONSTANT (0x123ffffffff),
01613                              DBUS_INT64_CONSTANT (0x456ffffffff),
01614                              DBUS_INT64_CONSTANT (0x789ffffffff) };
01615   dbus_int64_t *v_ARRAY_INT64;
01616   unsigned char *v_ARRAY_BYTE;
01617   dbus_int16_t *v_ARRAY_INT16;
01618   dbus_uint16_t *v_ARRAY_UINT16;
01619   dbus_int32_t *v_ARRAY_INT32;
01620   dbus_uint32_t *v_ARRAY_UINT32;
01621   DBusString t;
01622   double v_DOUBLE;
01623   double t_DOUBLE;
01624   dbus_int16_t v_INT16;
01625   dbus_uint16_t v_UINT16;
01626   dbus_int32_t v_INT32;
01627   dbus_uint32_t v_UINT32;
01628   dbus_int64_t v_INT64;
01629   dbus_uint64_t v_UINT64;
01630   unsigned char v_BYTE;
01631   dbus_bool_t v_BOOLEAN;
01632   const char *v_STRING;
01633   const char *v_SIGNATURE;
01634   const char *v_OBJECT_PATH;
01635   int byte_order;
01636 
01637   if (!_dbus_string_init (&str))
01638     _dbus_assert_not_reached ("failed to init string");
01639 
01640   pos = 0;
01641 
01642   /* Marshal doubles */
01643   MARSHAL_BASIC (DOUBLE, DBUS_BIG_ENDIAN, 3.14);
01644   DEMARSHAL_BASIC (DOUBLE, DBUS_BIG_ENDIAN);
01645   t_DOUBLE = 3.14;
01646   if (!_DBUS_DOUBLES_BITWISE_EQUAL (t_DOUBLE, v_DOUBLE))
01647     _dbus_assert_not_reached ("got wrong double value");
01648 
01649   MARSHAL_BASIC (DOUBLE, DBUS_LITTLE_ENDIAN, 3.14);
01650   DEMARSHAL_BASIC (DOUBLE, DBUS_LITTLE_ENDIAN);
01651   t_DOUBLE = 3.14;
01652   if (!_DBUS_DOUBLES_BITWISE_EQUAL (t_DOUBLE, v_DOUBLE))
01653     _dbus_assert_not_reached ("got wrong double value");
01654 
01655   /* Marshal signed 16 integers */
01656   MARSHAL_TEST (INT16, DBUS_BIG_ENDIAN, -12345);
01657   MARSHAL_TEST (INT16, DBUS_LITTLE_ENDIAN, -12345);
01658 
01659   /* Marshal unsigned 16 integers */
01660   MARSHAL_TEST (UINT16, DBUS_BIG_ENDIAN, 0x1234);
01661   MARSHAL_TEST (UINT16, DBUS_LITTLE_ENDIAN, 0x1234);
01662   
01663   /* Marshal signed integers */
01664   MARSHAL_TEST (INT32, DBUS_BIG_ENDIAN, -12345678);
01665   MARSHAL_TEST (INT32, DBUS_LITTLE_ENDIAN, -12345678);
01666 
01667   /* Marshal unsigned integers */
01668   MARSHAL_TEST (UINT32, DBUS_BIG_ENDIAN, 0x12345678);
01669   MARSHAL_TEST (UINT32, DBUS_LITTLE_ENDIAN, 0x12345678);
01670 
01671   /* Marshal signed integers */
01672   MARSHAL_TEST (INT64, DBUS_BIG_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7));
01673   MARSHAL_TEST (INT64, DBUS_LITTLE_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7));
01674 
01675   /* Marshal unsigned integers */
01676   MARSHAL_TEST (UINT64, DBUS_BIG_ENDIAN, DBUS_UINT64_CONSTANT (0x123456789abc7));
01677   MARSHAL_TEST (UINT64, DBUS_LITTLE_ENDIAN, DBUS_UINT64_CONSTANT (0x123456789abc7));
01678 
01679   /* Marshal byte */
01680   MARSHAL_TEST (BYTE, DBUS_BIG_ENDIAN, 5);
01681   MARSHAL_TEST (BYTE, DBUS_LITTLE_ENDIAN, 5);
01682 
01683   /* Marshal all possible bools! */
01684   MARSHAL_TEST (BOOLEAN, DBUS_BIG_ENDIAN, FALSE);
01685   MARSHAL_TEST (BOOLEAN, DBUS_LITTLE_ENDIAN, FALSE);
01686   MARSHAL_TEST (BOOLEAN, DBUS_BIG_ENDIAN, TRUE);
01687   MARSHAL_TEST (BOOLEAN, DBUS_LITTLE_ENDIAN, TRUE);
01688 
01689   /* Marshal strings */
01690   MARSHAL_TEST_STRCMP (STRING, DBUS_BIG_ENDIAN, "");
01691   MARSHAL_TEST_STRCMP (STRING, DBUS_LITTLE_ENDIAN, "");
01692   MARSHAL_TEST_STRCMP (STRING, DBUS_BIG_ENDIAN, "This is the dbus test string");
01693   MARSHAL_TEST_STRCMP (STRING, DBUS_LITTLE_ENDIAN, "This is the dbus test string");
01694 
01695   /* object paths */
01696   MARSHAL_TEST_STRCMP (OBJECT_PATH, DBUS_BIG_ENDIAN, "/a/b/c");
01697   MARSHAL_TEST_STRCMP (OBJECT_PATH, DBUS_LITTLE_ENDIAN, "/a/b/c");
01698 
01699   /* signatures */
01700   MARSHAL_TEST_STRCMP (SIGNATURE, DBUS_BIG_ENDIAN, "");
01701   MARSHAL_TEST_STRCMP (SIGNATURE, DBUS_LITTLE_ENDIAN, "");
01702   MARSHAL_TEST_STRCMP (SIGNATURE, DBUS_BIG_ENDIAN, "a(ii)");
01703   MARSHAL_TEST_STRCMP (SIGNATURE, DBUS_LITTLE_ENDIAN, "a(ii)");
01704 
01705   /* Arrays */
01706   MARSHAL_TEST_FIXED_ARRAY (INT16, DBUS_BIG_ENDIAN, array2);
01707   MARSHAL_TEST_FIXED_ARRAY (INT16, DBUS_LITTLE_ENDIAN, array2);
01708   MARSHAL_TEST_FIXED_ARRAY (UINT16, DBUS_BIG_ENDIAN, array2);
01709   MARSHAL_TEST_FIXED_ARRAY (UINT16, DBUS_LITTLE_ENDIAN, array2);
01710   
01711   MARSHAL_TEST_FIXED_ARRAY (INT32, DBUS_BIG_ENDIAN, array4);
01712   MARSHAL_TEST_FIXED_ARRAY (INT32, DBUS_LITTLE_ENDIAN, array4);
01713   MARSHAL_TEST_FIXED_ARRAY (UINT32, DBUS_BIG_ENDIAN, array4);
01714   MARSHAL_TEST_FIXED_ARRAY (UINT32, DBUS_LITTLE_ENDIAN, array4);
01715 
01716   MARSHAL_TEST_FIXED_ARRAY (BYTE, DBUS_BIG_ENDIAN, array1);
01717   MARSHAL_TEST_FIXED_ARRAY (BYTE, DBUS_LITTLE_ENDIAN, array1);
01718   
01719   MARSHAL_TEST_FIXED_ARRAY (INT64, DBUS_BIG_ENDIAN, array8);
01720   MARSHAL_TEST_FIXED_ARRAY (INT64, DBUS_LITTLE_ENDIAN, array8);
01721 
01722 #if 0
01723 
01724   /*
01725    * FIXME restore the set/pack tests
01726    */
01727 
01728   /* set/pack 64-bit integers */
01729   _dbus_string_set_length (&str, 8);
01730 
01731   /* signed little */
01732   _dbus_marshal_set_int64 (&str, DBUS_LITTLE_ENDIAN,
01733                            0, DBUS_INT64_CONSTANT (-0x123456789abc7));
01734 
01735   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
01736                 _dbus_unpack_int64 (DBUS_LITTLE_ENDIAN,
01737                                     _dbus_string_get_const_data (&str)));
01738 
01739   /* signed big */
01740   _dbus_marshal_set_int64 (&str, DBUS_BIG_ENDIAN,
01741                            0, DBUS_INT64_CONSTANT (-0x123456789abc7));
01742 
01743   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
01744                 _dbus_unpack_int64 (DBUS_BIG_ENDIAN,
01745                                     _dbus_string_get_const_data (&str)));
01746 
01747   /* signed little pack */
01748   _dbus_pack_int64 (DBUS_INT64_CONSTANT (-0x123456789abc7),
01749                     DBUS_LITTLE_ENDIAN,
01750                     _dbus_string_get_data (&str));
01751 
01752   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
01753                 _dbus_unpack_int64 (DBUS_LITTLE_ENDIAN,
01754                                     _dbus_string_get_const_data (&str)));
01755 
01756   /* signed big pack */
01757   _dbus_pack_int64 (DBUS_INT64_CONSTANT (-0x123456789abc7),
01758                     DBUS_BIG_ENDIAN,
01759                     _dbus_string_get_data (&str));
01760 
01761   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
01762                 _dbus_unpack_int64 (DBUS_BIG_ENDIAN,
01763                                     _dbus_string_get_const_data (&str)));
01764 
01765   /* unsigned little */
01766   _dbus_marshal_set_uint64 (&str, DBUS_LITTLE_ENDIAN,
01767                             0, DBUS_UINT64_CONSTANT (0x123456789abc7));
01768 
01769   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
01770                 _dbus_unpack_uint64 (DBUS_LITTLE_ENDIAN,
01771                                      _dbus_string_get_const_data (&str)));
01772 
01773   /* unsigned big */
01774   _dbus_marshal_set_uint64 (&str, DBUS_BIG_ENDIAN,
01775                             0, DBUS_UINT64_CONSTANT (0x123456789abc7));
01776 
01777   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
01778                 _dbus_unpack_uint64 (DBUS_BIG_ENDIAN,
01779                                      _dbus_string_get_const_data (&str)));
01780 
01781   /* unsigned little pack */
01782   _dbus_pack_uint64 (DBUS_UINT64_CONSTANT (0x123456789abc7),
01783                      DBUS_LITTLE_ENDIAN,
01784                      _dbus_string_get_data (&str));
01785 
01786   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
01787                 _dbus_unpack_uint64 (DBUS_LITTLE_ENDIAN,
01788                                      _dbus_string_get_const_data (&str)));
01789 
01790   /* unsigned big pack */
01791   _dbus_pack_uint64 (DBUS_UINT64_CONSTANT (0x123456789abc7),
01792                      DBUS_BIG_ENDIAN,
01793                      _dbus_string_get_data (&str));
01794 
01795   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
01796                 _dbus_unpack_uint64 (DBUS_BIG_ENDIAN,
01797                                      _dbus_string_get_const_data (&str)));
01798 
01799   /* set/pack 32-bit integers */
01800   _dbus_string_set_length (&str, 4);
01801 
01802   /* signed little */
01803   _dbus_marshal_set_int32 (&str, DBUS_LITTLE_ENDIAN,
01804                            0, -0x123456);
01805 
01806   _dbus_assert (-0x123456 ==
01807                 _dbus_unpack_int32 (DBUS_LITTLE_ENDIAN,
01808                                     _dbus_string_get_const_data (&str)));
01809 
01810   /* signed big */
01811   _dbus_marshal_set_int32 (&str, DBUS_BIG_ENDIAN,
01812                            0, -0x123456);
01813 
01814   _dbus_assert (-0x123456 ==
01815                 _dbus_unpack_int32 (DBUS_BIG_ENDIAN,
01816                                     _dbus_string_get_const_data (&str)));
01817 
01818   /* signed little pack */
01819   _dbus_pack_int32 (-0x123456,
01820                     DBUS_LITTLE_ENDIAN,
01821                     _dbus_string_get_data (&str));
01822 
01823   _dbus_assert (-0x123456 ==
01824                 _dbus_unpack_int32 (DBUS_LITTLE_ENDIAN,
01825                                     _dbus_string_get_const_data (&str)));
01826 
01827   /* signed big pack */
01828   _dbus_pack_int32 (-0x123456,
01829                     DBUS_BIG_ENDIAN,
01830                     _dbus_string_get_data (&str));
01831 
01832   _dbus_assert (-0x123456 ==
01833                 _dbus_unpack_int32 (DBUS_BIG_ENDIAN,
01834                                     _dbus_string_get_const_data (&str)));
01835 
01836   /* unsigned little */
01837   _dbus_marshal_set_uint32 (&str,
01838                             0, 0x123456,
01839                             DBUS_LITTLE_ENDIAN);
01840 
01841   _dbus_assert (0x123456 ==
01842                 _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN,
01843                                      _dbus_string_get_const_data (&str)));
01844 
01845   /* unsigned big */
01846   _dbus_marshal_set_uint32 (&str,
01847                             0, 0x123456,
01848                             DBUS_BIG_ENDIAN);
01849 
01850   _dbus_assert (0x123456 ==
01851                 _dbus_unpack_uint32 (DBUS_BIG_ENDIAN,
01852                                      _dbus_string_get_const_data (&str)));
01853 
01854   /* unsigned little pack */
01855   _dbus_pack_uint32 (0x123456,
01856                      DBUS_LITTLE_ENDIAN,
01857                      _dbus_string_get_data (&str));
01858 
01859   _dbus_assert (0x123456 ==
01860                 _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN,
01861                                      _dbus_string_get_const_data (&str)));
01862 
01863   /* unsigned big pack */
01864   _dbus_pack_uint32 (0x123456,
01865                      DBUS_BIG_ENDIAN,
01866                      _dbus_string_get_data (&str));
01867 
01868   _dbus_assert (0x123456 ==
01869                 _dbus_unpack_uint32 (DBUS_BIG_ENDIAN,
01870                                      _dbus_string_get_const_data (&str)));
01871 
01872 #endif /* set/pack tests for integers */
01873 
01874   /* Strings in-place set */
01875   byte_order = DBUS_LITTLE_ENDIAN;
01876   while (TRUE)
01877     {
01878       /* Init a string */
01879       _dbus_string_set_length (&str, 0);
01880 
01881       /* reset pos for the macros */
01882       pos = 0;
01883 
01884       MARSHAL_TEST_STRCMP (STRING, byte_order, "Hello world");
01885 
01886       /* Set it to something longer */
01887       _dbus_string_init_const (&t, "Hello world foo");
01888 
01889       v_STRING = _dbus_string_get_const_data (&t);
01890       _dbus_marshal_set_basic (&str, 0, DBUS_TYPE_STRING,
01891                                &v_STRING, byte_order, NULL, NULL);
01892 
01893       _dbus_marshal_read_basic (&str, 0, DBUS_TYPE_STRING,
01894                                 &v_STRING, byte_order,
01895                                 NULL);
01896       _dbus_assert (strcmp (v_STRING, "Hello world foo") == 0);
01897 
01898       /* Set it to something shorter */
01899       _dbus_string_init_const (&t, "Hello");
01900 
01901       v_STRING = _dbus_string_get_const_data (&t);
01902       _dbus_marshal_set_basic (&str, 0, DBUS_TYPE_STRING,
01903                                &v_STRING, byte_order, NULL, NULL);
01904       _dbus_marshal_read_basic (&str, 0, DBUS_TYPE_STRING,
01905                                 &v_STRING, byte_order,
01906                                 NULL);
01907       _dbus_assert (strcmp (v_STRING, "Hello") == 0);
01908 
01909       /* Do the other byte order */
01910       if (byte_order == DBUS_LITTLE_ENDIAN)
01911         byte_order = DBUS_BIG_ENDIAN;
01912       else
01913         break;
01914     }
01915 
01916   /* Clean up */
01917   _dbus_string_free (&str);
01918 
01919   return TRUE;
01920 }
01921 
01922 #endif /* DBUS_ENABLE_EMBEDDED_TESTS */