Main Page   Modules   Data Structures   File List   Data Fields   Related Pages  

dbus-marshal.c

00001 /* -*- mode: C; c-file-style: "gnu" -*- */
00002 /* dbus-marshal.c  Marshalling routines
00003  *
00004  * Copyright (C) 2002 CodeFactory AB
00005  * Copyright (C) 2003 Red Hat, Inc.
00006  *
00007  * Licensed under the Academic Free License version 1.2
00008  * 
00009  * This program is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  * 
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022  *
00023  */
00024 
00025 #include "dbus-marshal.h"
00026 #include "dbus-internals.h"
00027 #define DBUS_CAN_USE_DBUS_STRING_PRIVATE 1
00028 #include "dbus-string-private.h"
00029 
00030 #include <string.h>
00031 
00043 static dbus_uint32_t
00044 unpack_4_octets (int                  byte_order,
00045                  const unsigned char *data)
00046 {
00047   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
00048   
00049   if (byte_order == DBUS_LITTLE_ENDIAN)
00050     return DBUS_UINT32_FROM_LE (*(dbus_uint32_t*)data);
00051   else
00052     return DBUS_UINT32_FROM_BE (*(dbus_uint32_t*)data);
00053 }
00054 
00055 #ifndef DBUS_HAVE_INT64
00056 /* from ORBit */
00057 static void
00058 swap_bytes (unsigned char *data,
00059             unsigned int   len)
00060 {
00061   unsigned char *p1 = data;
00062   unsigned char *p2 = data + len - 1;
00063 
00064   while (p1 < p2)
00065     {
00066       unsigned char tmp = *p1;
00067       *p1 = *p2;
00068       *p2 = tmp;
00069 
00070       --p2;
00071       ++p1;
00072     }
00073 }
00074 #endif /* !DBUS_HAVE_INT64 */
00075 
00076 typedef union
00077 {
00078 #ifdef DBUS_HAVE_INT64
00079   dbus_int64_t  s;
00080   dbus_uint64_t u;
00081 #endif
00082   double d;
00083 } DBusOctets8;
00084 
00085 static DBusOctets8
00086 unpack_8_octets (int                  byte_order,
00087                  const unsigned char *data)
00088 {
00089   DBusOctets8 r;
00090   
00091   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 8) == data);
00092   _dbus_assert (sizeof (r) == 8);
00093   
00094 #ifdef DBUS_HAVE_INT64
00095   if (byte_order == DBUS_LITTLE_ENDIAN)
00096     r.u = DBUS_UINT64_FROM_LE (*(dbus_uint64_t*)data);
00097   else
00098     r.u = DBUS_UINT64_FROM_BE (*(dbus_uint64_t*)data);
00099 #else
00100   r.d = *(double*)data;
00101   swap_bytes (&r, sizeof (r));
00102 #endif
00103   
00104   return r;
00105 }
00106 
00114 dbus_uint32_t
00115 _dbus_unpack_uint32 (int                  byte_order,
00116                      const unsigned char *data)
00117 {
00118   return unpack_4_octets (byte_order, data);
00119 }  
00120 
00128 dbus_int32_t
00129 _dbus_unpack_int32 (int                  byte_order,
00130                     const unsigned char *data)
00131 {
00132   return (dbus_int32_t) unpack_4_octets (byte_order, data);
00133 }
00134 
00135 #ifdef DBUS_HAVE_INT64
00136 
00143 dbus_uint64_t
00144 _dbus_unpack_uint64 (int                  byte_order,
00145                      const unsigned char *data)
00146 {
00147   DBusOctets8 r;
00148   
00149   r = unpack_8_octets (byte_order, data);
00150 
00151   return r.u;
00152 }  
00153 
00161 dbus_int64_t
00162 _dbus_unpack_int64 (int                  byte_order,
00163                     const unsigned char *data)
00164 {
00165   DBusOctets8 r;
00166   
00167   r = unpack_8_octets (byte_order, data);
00168 
00169   return r.s;
00170 }
00171 
00172 #endif /* DBUS_HAVE_INT64 */
00173 
00174 static void
00175 pack_4_octets (dbus_uint32_t   value,
00176                int             byte_order,
00177                unsigned char  *data)
00178 {
00179   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
00180   
00181   if ((byte_order) == DBUS_LITTLE_ENDIAN)                  
00182     *((dbus_uint32_t*)(data)) = DBUS_UINT32_TO_LE (value);       
00183   else
00184     *((dbus_uint32_t*)(data)) = DBUS_UINT32_TO_BE (value);
00185 }
00186 
00187 static void
00188 pack_8_octets (DBusOctets8     value,
00189                int             byte_order,
00190                unsigned char  *data)
00191 {
00192   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 8) == data);
00193 
00194 #ifdef DBUS_HAVE_INT64
00195   if ((byte_order) == DBUS_LITTLE_ENDIAN)                  
00196     *((dbus_uint64_t*)(data)) = DBUS_UINT64_TO_LE (value.u); 
00197   else
00198     *((dbus_uint64_t*)(data)) = DBUS_UINT64_TO_BE (value.u);
00199 #else
00200   memcpy (data, &value, 8);
00201   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
00202     swap_bytes ((unsigned char *)data, 8);
00203 #endif
00204 }
00205 
00213 void
00214 _dbus_pack_uint32 (dbus_uint32_t   value,
00215                    int             byte_order,
00216                    unsigned char  *data)
00217 {
00218   pack_4_octets (value, byte_order, data);
00219 }
00220 
00228 void
00229 _dbus_pack_int32 (dbus_int32_t   value,
00230                   int            byte_order,
00231                   unsigned char *data)
00232 {
00233   pack_4_octets ((dbus_uint32_t) value, byte_order, data);
00234 }
00235 
00236 #ifdef DBUS_HAVE_INT64
00237 
00244 void
00245 _dbus_pack_uint64 (dbus_uint64_t   value,
00246                    int             byte_order,
00247                    unsigned char  *data)
00248 {
00249   DBusOctets8 r;
00250   r.u = value;
00251   pack_8_octets (r, byte_order, data);
00252 }
00253 
00261 void
00262 _dbus_pack_int64 (dbus_int64_t   value,
00263                   int            byte_order,
00264                   unsigned char *data)
00265 {
00266   DBusOctets8 r;
00267   r.s = value;
00268   pack_8_octets (r, byte_order, data);
00269 }
00270 #endif /* DBUS_HAVE_INT64 */
00271 
00272 static void
00273 set_4_octets (DBusString          *str,
00274               int                  byte_order,
00275               int                  offset,
00276               dbus_uint32_t        value)
00277 {
00278   char *data;
00279   
00280   _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
00281                 byte_order == DBUS_BIG_ENDIAN);
00282   
00283   data = _dbus_string_get_data_len (str, offset, 4);
00284 
00285   _dbus_pack_uint32 (value, byte_order, data);
00286 }
00287 
00288 static void
00289 set_8_octets (DBusString          *str,
00290               int                  byte_order,
00291               int                  offset,
00292               DBusOctets8          value)
00293 {
00294   char *data;
00295   
00296   _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
00297                 byte_order == DBUS_BIG_ENDIAN);
00298   
00299   data = _dbus_string_get_data_len (str, offset, 8);
00300 
00301   pack_8_octets (value, byte_order, data);
00302 }
00303 
00314 void
00315 _dbus_marshal_set_int32 (DBusString          *str,
00316                          int                  byte_order,
00317                          int                  offset,
00318                          dbus_int32_t         value)
00319 {
00320   set_4_octets (str, byte_order, offset, (dbus_uint32_t) value);
00321 }
00322 
00333 void
00334 _dbus_marshal_set_uint32 (DBusString          *str,
00335                           int                  byte_order,
00336                           int                  offset,
00337                           dbus_uint32_t        value)
00338 {
00339   set_4_octets (str, byte_order, offset, value);
00340 }
00341 
00342 #ifdef DBUS_HAVE_INT64
00343 
00354 void
00355 _dbus_marshal_set_int64 (DBusString          *str,
00356                          int                  byte_order,
00357                          int                  offset,
00358                          dbus_int64_t         value)
00359 {
00360   DBusOctets8 r;
00361   r.s = value;
00362   set_8_octets (str, byte_order, offset, r);
00363 }
00364 
00375 void
00376 _dbus_marshal_set_uint64 (DBusString          *str,
00377                           int                  byte_order,
00378                           int                  offset,
00379                           dbus_uint64_t        value)
00380 {
00381   DBusOctets8 r;
00382   r.u = value;
00383   set_8_octets (str, byte_order, offset, r);
00384 }
00385 #endif /* DBUS_HAVE_INT64 */
00386 
00401 dbus_bool_t
00402 _dbus_marshal_set_string (DBusString          *str,
00403                           int                  byte_order,
00404                           int                  offset,
00405                           const DBusString    *value,
00406                           int                  len)
00407 {
00408   int old_len;
00409   
00410   _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
00411                 byte_order == DBUS_BIG_ENDIAN);
00412   
00413   old_len = _dbus_demarshal_uint32 (str, byte_order,
00414                                     offset, NULL);
00415 
00416   if (!_dbus_string_replace_len (value, 0, len,
00417                                  str, offset + 4, old_len))
00418     return FALSE;
00419 
00420   _dbus_marshal_set_uint32 (str, byte_order,
00421                             offset, len);
00422 
00423   return TRUE;
00424 }
00425 
00426 static dbus_bool_t
00427 marshal_4_octets (DBusString   *str,
00428                   int           byte_order,
00429                   dbus_uint32_t value)
00430 {
00431   _dbus_assert (sizeof (value) == 4);
00432   
00433   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
00434     value = DBUS_UINT32_SWAP_LE_BE (value);
00435 
00436   return _dbus_string_append_4_aligned (str,
00437                                         (const unsigned char *)&value);
00438 }
00439 
00440 static dbus_bool_t
00441 marshal_8_octets (DBusString *str,
00442                   int         byte_order,
00443                   DBusOctets8 value)
00444 {
00445   _dbus_assert (sizeof (value) == 8);
00446   
00447   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
00448     pack_8_octets (value, byte_order, (unsigned char*) &value); /* pack into self, swapping as we go */
00449 
00450   return _dbus_string_append_8_aligned (str,
00451                                         (const unsigned char *)&value);
00452 }
00453 
00462 dbus_bool_t
00463 _dbus_marshal_double (DBusString *str,
00464                       int         byte_order,
00465                       double      value)
00466 {
00467   DBusOctets8 r;
00468   r.d = value;
00469   return marshal_8_octets (str, byte_order, r);
00470 }
00471 
00480 dbus_bool_t
00481 _dbus_marshal_int32  (DBusString   *str,
00482                       int           byte_order,
00483                       dbus_int32_t  value)
00484 {
00485   return marshal_4_octets (str, byte_order, (dbus_uint32_t) value);
00486 }
00487 
00496 dbus_bool_t
00497 _dbus_marshal_uint32 (DBusString    *str,
00498                       int            byte_order,
00499                       dbus_uint32_t  value)
00500 {
00501   return marshal_4_octets (str, byte_order, value);
00502 }
00503 
00504 
00505 #ifdef DBUS_HAVE_INT64
00506 
00514 dbus_bool_t
00515 _dbus_marshal_int64  (DBusString   *str,
00516                       int           byte_order,
00517                       dbus_int64_t  value)
00518 {
00519   DBusOctets8 r;
00520   r.s = value;
00521   return marshal_8_octets (str, byte_order, r);
00522 }
00523 
00532 dbus_bool_t
00533 _dbus_marshal_uint64 (DBusString    *str,
00534                       int            byte_order,
00535                       dbus_uint64_t  value)
00536 {
00537   DBusOctets8 r;
00538   r.u = value;
00539   return marshal_8_octets (str, byte_order, r);
00540 }
00541 
00542 #endif /* DBUS_HAVE_INT64 */
00543 
00555 dbus_bool_t
00556 _dbus_marshal_string (DBusString    *str,
00557                       int            byte_order,
00558                       const char    *value)
00559 {
00560   int len, old_string_len;
00561 
00562   old_string_len = _dbus_string_get_length (str);
00563   
00564   len = strlen (value);
00565 
00566   if (!_dbus_marshal_uint32 (str, byte_order, len))
00567     {
00568       /* Restore the previous length */
00569       _dbus_string_set_length (str, old_string_len);
00570 
00571       return FALSE;
00572     }
00573 
00574   return _dbus_string_append_len (str, value, len + 1);
00575 }
00576 
00586 dbus_bool_t
00587 _dbus_marshal_byte_array (DBusString          *str,
00588                           int                  byte_order,
00589                           const unsigned char *value,
00590                           int                  len)
00591 {
00592   int old_string_len;
00593 
00594   old_string_len = _dbus_string_get_length (str);
00595   
00596   if (!_dbus_marshal_uint32 (str, byte_order, len))
00597     {
00598       /* Restore the previous length */
00599       _dbus_string_set_length (str, old_string_len);
00600 
00601       return FALSE;
00602     }
00603 
00604   if (len == 0)
00605     return TRUE;
00606   else
00607     return _dbus_string_append_len (str, value, len);
00608 }
00609 
00610 static dbus_bool_t
00611 marshal_4_octets_array (DBusString          *str,
00612                         int                  byte_order,
00613                         const dbus_uint32_t *value,
00614                         int                  len)
00615 {
00616   int old_string_len;
00617   int array_start;
00618 
00619   old_string_len = _dbus_string_get_length (str);
00620 
00621   if (!_dbus_marshal_uint32 (str, byte_order, len * 4))
00622     goto error;
00623 
00624   array_start = _dbus_string_get_length (str);
00625   
00626   if (!_dbus_string_append_len (str, (const unsigned char*) value,
00627                                 len * 4))
00628     goto error;
00629   
00630   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
00631     {
00632       const unsigned char *d;
00633       const unsigned char *end;
00634       
00635       d = _dbus_string_get_data (str) + array_start;
00636       end = d + len * 4;
00637       while (d != end)
00638         {
00639           *((dbus_uint32_t*)d) = DBUS_UINT32_SWAP_LE_BE (*((dbus_uint32_t*)d));
00640           d += 4;
00641         }
00642     }
00643 
00644   return TRUE;
00645   
00646  error:
00647   /* Restore previous length */
00648   _dbus_string_set_length (str, old_string_len);
00649   
00650   return FALSE;  
00651 }
00652 
00653 static dbus_bool_t
00654 marshal_8_octets_array (DBusString          *str,
00655                         int                  byte_order,
00656                         const DBusOctets8   *value,
00657                         int                  len)
00658 {
00659   int old_string_len;
00660   int array_start;
00661 
00662   old_string_len = _dbus_string_get_length (str);
00663 
00664   if (!_dbus_marshal_uint32 (str, byte_order, len * 8))
00665     goto error;
00666 
00667   array_start = _dbus_string_get_length (str);
00668   
00669   if (!_dbus_string_append_len (str, (const unsigned char*) value,
00670                                 len * 8))
00671     goto error;
00672   
00673   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
00674     {
00675       const unsigned char *d;
00676       const unsigned char *end;
00677       
00678       d = _dbus_string_get_data (str) + array_start;
00679       end = d + len * 8;
00680       while (d != end)
00681         {
00682 #ifdef DBUS_HAVE_INT64
00683           *((dbus_uint64_t*)d) = DBUS_UINT64_SWAP_LE_BE (*((dbus_uint64_t*)d));
00684 #else
00685           swap_bytes (d, 8);
00686 #endif
00687           d += 8;
00688         }
00689     }
00690 
00691   return TRUE;
00692   
00693  error:
00694   /* Restore previous length */
00695   _dbus_string_set_length (str, old_string_len);
00696   
00697   return FALSE;  
00698 }
00699 
00709 dbus_bool_t
00710 _dbus_marshal_int32_array (DBusString         *str,
00711                            int                 byte_order,
00712                            const dbus_int32_t *value,
00713                            int                 len)
00714 {
00715   return marshal_4_octets_array (str, byte_order,
00716                                  (const dbus_uint32_t*) value,
00717                                  len);
00718 }
00719 
00729 dbus_bool_t
00730 _dbus_marshal_uint32_array (DBusString          *str,
00731                             int                  byte_order,
00732                             const dbus_uint32_t  *value,
00733                             int                  len)
00734 {
00735   return marshal_4_octets_array (str, byte_order,
00736                                  value,
00737                                  len);
00738 }
00739 
00740 #ifdef DBUS_HAVE_INT64
00741 
00751 dbus_bool_t
00752 _dbus_marshal_int64_array (DBusString         *str,
00753                            int                 byte_order,
00754                            const dbus_int64_t *value,
00755                            int                 len)
00756 {
00757   return marshal_8_octets_array (str, byte_order,
00758                                  (const DBusOctets8*) value,
00759                                  len);
00760 }
00761 
00771 dbus_bool_t
00772 _dbus_marshal_uint64_array (DBusString          *str,
00773                             int                  byte_order,
00774                             const dbus_uint64_t  *value,
00775                             int                  len)
00776 {
00777   return marshal_8_octets_array (str, byte_order,
00778                                  (const DBusOctets8*) value,
00779                                  len);
00780 }
00781 
00782 #endif /* DBUS_HAVE_INT64 */
00783 
00793 dbus_bool_t
00794 _dbus_marshal_double_array (DBusString          *str,
00795                             int                  byte_order,
00796                             const double        *value,
00797                             int                  len)
00798 {
00799   return marshal_8_octets_array (str, byte_order,
00800                                  (const DBusOctets8*) value,
00801                                  len);
00802 }
00803 
00813 dbus_bool_t
00814 _dbus_marshal_string_array (DBusString  *str,
00815                             int          byte_order,
00816                             const char **value,
00817                             int          len)
00818 {
00819   int i, old_string_len, array_start;
00820 
00821   old_string_len = _dbus_string_get_length (str);
00822 
00823   /* Set the length to 0 temporarily */
00824   if (!_dbus_marshal_uint32 (str, byte_order, 0))
00825     goto error;
00826 
00827   array_start = _dbus_string_get_length (str);
00828   
00829   for (i = 0; i < len; i++)
00830     if (!_dbus_marshal_string (str, byte_order, value[i]))
00831       goto error;
00832 
00833   /* Write the length now that we know it */
00834   _dbus_marshal_set_uint32 (str, byte_order,
00835                             _DBUS_ALIGN_VALUE (old_string_len, sizeof(dbus_uint32_t)),
00836                             _dbus_string_get_length (str) - array_start);
00837   
00838   return TRUE;
00839   
00840  error:
00841   /* Restore previous length */
00842   _dbus_string_set_length (str, old_string_len);
00843   
00844   return FALSE;      
00845 }
00846 
00847 static dbus_uint32_t
00848 demarshal_4_octets (const DBusString *str,
00849                     int               byte_order,
00850                     int               pos,
00851                     int              *new_pos)
00852 {
00853   const DBusRealString *real = (const DBusRealString*) str;
00854   
00855   pos = _DBUS_ALIGN_VALUE (pos, 4);
00856   
00857   if (new_pos)
00858     *new_pos = pos + 4;
00859 
00860   return unpack_4_octets (byte_order, real->str + pos);
00861 }
00862 
00863 static DBusOctets8
00864 demarshal_8_octets (const DBusString *str,
00865                     int               byte_order,
00866                     int               pos,
00867                     int              *new_pos)
00868 {
00869   const DBusRealString *real = (const DBusRealString*) str;
00870   
00871   pos = _DBUS_ALIGN_VALUE (pos, 8);
00872   
00873   if (new_pos)
00874     *new_pos = pos + 8;
00875 
00876   return unpack_8_octets (byte_order, real->str + pos);
00877 }
00878 
00888 double
00889 _dbus_demarshal_double (const DBusString  *str,
00890                         int                byte_order,
00891                         int                pos,
00892                         int               *new_pos)
00893 {
00894   DBusOctets8 r;
00895 
00896   r = demarshal_8_octets (str, byte_order, pos, new_pos);
00897 
00898   return r.d;
00899 }
00900 
00910 dbus_int32_t
00911 _dbus_demarshal_int32  (const DBusString *str,
00912                         int               byte_order,
00913                         int               pos,
00914                         int              *new_pos)
00915 {
00916   return (dbus_int32_t) demarshal_4_octets (str, byte_order, pos, new_pos);
00917 }
00918 
00928 dbus_uint32_t
00929 _dbus_demarshal_uint32  (const DBusString *str,
00930                          int         byte_order,
00931                          int         pos,
00932                          int        *new_pos)
00933 {
00934   return demarshal_4_octets (str, byte_order, pos, new_pos);
00935 }
00936 
00937 #ifdef DBUS_HAVE_INT64
00938 
00948 dbus_int64_t
00949 _dbus_demarshal_int64  (const DBusString *str,
00950                         int               byte_order,
00951                         int               pos,
00952                         int              *new_pos)
00953 {
00954   DBusOctets8 r;
00955 
00956   r = demarshal_8_octets (str, byte_order, pos, new_pos);
00957 
00958   return r.s;
00959 }
00960 
00970 dbus_uint64_t
00971 _dbus_demarshal_uint64  (const DBusString *str,
00972                          int         byte_order,
00973                          int         pos,
00974                          int        *new_pos)
00975 {
00976   DBusOctets8 r;
00977 
00978   r = demarshal_8_octets (str, byte_order, pos, new_pos);
00979 
00980   return r.u;
00981 }
00982 
00983 #endif /* DBUS_HAVE_INT64 */
00984 
01001 char *
01002 _dbus_demarshal_string (const DBusString *str,
01003                         int               byte_order,
01004                         int               pos,
01005                         int              *new_pos)
01006 {
01007   int len;
01008   char *retval;
01009   const char *data;
01010   
01011   len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
01012 
01013   retval = dbus_malloc (len + 1);
01014 
01015   if (!retval)
01016     return NULL;
01017 
01018   data = _dbus_string_get_const_data_len (str, pos, len + 1);
01019 
01020   if (!data)
01021     return NULL;
01022 
01023   memcpy (retval, data, len + 1);
01024 
01025   if (new_pos)
01026     *new_pos = pos + len + 1;
01027   
01028   return retval;
01029 }
01030 
01046 dbus_bool_t
01047 _dbus_demarshal_byte_array (const DBusString  *str,
01048                             int                byte_order,
01049                             int                pos,
01050                             int               *new_pos,
01051                             unsigned char    **array,
01052                             int               *array_len)
01053 {
01054   int len;
01055   unsigned char *retval;
01056   const char *data;
01057 
01058   len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
01059 
01060   if (len == 0)
01061     {
01062       *array_len = len;
01063       *array = NULL;
01064 
01065       if (new_pos)
01066         *new_pos = pos;
01067       
01068       return TRUE;
01069     }
01070   
01071   retval = dbus_malloc (len);
01072 
01073   if (!retval)
01074     return FALSE;
01075 
01076   data = _dbus_string_get_const_data_len (str, pos, len);
01077 
01078   if (!data)
01079     {
01080       dbus_free (retval);
01081       return FALSE;
01082     }
01083 
01084   memcpy (retval, data, len);
01085 
01086   if (new_pos)
01087     *new_pos = pos + len;
01088 
01089   *array = retval;
01090   *array_len = len;
01091   
01092   return TRUE;
01093 }
01094 
01095 static dbus_bool_t
01096 demarshal_4_octets_array (const DBusString  *str,
01097                           int                byte_order,
01098                           int                pos,
01099                           int               *new_pos,
01100                           dbus_uint32_t    **array,
01101                           int               *array_len)
01102 {
01103   int len, i;
01104   dbus_uint32_t *retval;
01105   int byte_len;
01106   
01107   byte_len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
01108   len = byte_len / 4;
01109 
01110   if (len == 0)
01111     {
01112       *array_len = 0;
01113       *array = NULL;
01114 
01115       if (new_pos)
01116         *new_pos = pos;
01117       
01118       return TRUE;
01119     }
01120 
01121   if (!_dbus_string_copy_data_len (str, (char**) &retval,
01122                                    pos, byte_len))
01123     return FALSE;
01124   
01125   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
01126     {
01127       for (i = 0; i < len; i++)
01128         retval[i] = DBUS_UINT32_SWAP_LE_BE (retval[i]);
01129     }
01130 
01131   if (new_pos)
01132     *new_pos = pos + byte_len;
01133 
01134   *array_len = len;
01135   *array = retval;
01136   
01137   return TRUE;  
01138 }
01139 
01140 static dbus_bool_t
01141 demarshal_8_octets_array (const DBusString  *str,
01142                           int                byte_order,
01143                           int                pos,
01144                           int               *new_pos,
01145                           DBusOctets8      **array,
01146                           int               *array_len)
01147 {
01148   int len, i;
01149   DBusOctets8 *retval;
01150   int byte_len;
01151   
01152   byte_len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
01153   len = byte_len / 8;
01154 
01155   if (len == 0)
01156     {
01157       *array_len = 0;
01158       *array = NULL;
01159 
01160       if (new_pos)
01161         *new_pos = pos;
01162       
01163       return TRUE;
01164     }
01165 
01166   if (!_dbus_string_copy_data_len (str, (char**) &retval,
01167                                    pos, byte_len))
01168     return FALSE;
01169   
01170   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
01171     {
01172       for (i = 0; i < len; i++)
01173         {
01174 #ifdef DBUS_HAVE_INT64
01175           retval[i].u = DBUS_UINT64_SWAP_LE_BE (retval[i].u);
01176 #else
01177           swap_bytes (&retval[i], 8);
01178 #endif
01179         }
01180     }
01181 
01182   if (new_pos)
01183     *new_pos = pos + byte_len;
01184 
01185   *array_len = len;
01186   *array = retval;
01187   
01188   return TRUE;  
01189 }
01190 
01202 dbus_bool_t
01203 _dbus_demarshal_int32_array (const DBusString  *str,
01204                              int                byte_order,
01205                              int                pos,
01206                              int               *new_pos,
01207                              dbus_int32_t     **array,
01208                              int               *array_len)
01209 {
01210   return demarshal_4_octets_array (str, byte_order, pos, new_pos,
01211                                    (dbus_uint32_t**) array, array_len);
01212 }
01213 
01225 dbus_bool_t
01226 _dbus_demarshal_uint32_array (const DBusString  *str,
01227                               int                byte_order,
01228                               int                pos,
01229                               int               *new_pos,
01230                               dbus_uint32_t    **array,
01231                               int               *array_len)
01232 {
01233   return demarshal_4_octets_array (str, byte_order, pos, new_pos,
01234                                    array, array_len);
01235 }
01236 
01237 #ifdef DBUS_HAVE_INT64
01238 
01250 dbus_bool_t
01251 _dbus_demarshal_int64_array (const DBusString  *str,
01252                              int                byte_order,
01253                              int                pos,
01254                              int               *new_pos,
01255                              dbus_int64_t     **array,
01256                              int               *array_len)
01257 {
01258   return demarshal_8_octets_array (str, byte_order, pos, new_pos,
01259                                    (DBusOctets8**) array, array_len);
01260 }
01261 
01273 dbus_bool_t
01274 _dbus_demarshal_uint64_array (const DBusString  *str,
01275                               int                byte_order,
01276                               int                pos,
01277                               int               *new_pos,
01278                               dbus_uint64_t    **array,
01279                               int               *array_len)
01280 {
01281   return demarshal_8_octets_array (str, byte_order, pos, new_pos,
01282                                    (DBusOctets8**) array, array_len);
01283 }
01284 
01285 #endif /* DBUS_HAVE_INT64 */
01286 
01298 dbus_bool_t
01299 _dbus_demarshal_double_array (const DBusString  *str,
01300                               int                byte_order,
01301                               int                pos,
01302                               int               *new_pos,
01303                               double           **array,
01304                               int               *array_len)
01305 {
01306   return demarshal_8_octets_array (str, byte_order, pos, new_pos,
01307                                    (DBusOctets8**) array, array_len);
01308 }
01309 
01321 dbus_bool_t
01322 _dbus_demarshal_string_array (const DBusString   *str,
01323                               int                 byte_order,
01324                               int                 pos,
01325                               int                *new_pos,
01326                               char             ***array,
01327                               int                *array_len)
01328 {
01329   int bytes_len, i;
01330   int len, allocated;
01331   int end_pos;
01332   char **retval;
01333   
01334   bytes_len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
01335   
01336   if (bytes_len == 0)
01337     {
01338       *array_len = 0;
01339       *array = NULL;
01340 
01341       if (new_pos)
01342         *new_pos = pos;
01343       
01344       return TRUE;
01345     }
01346 
01347   len = 0;
01348   allocated = 4;
01349   end_pos = pos + bytes_len;
01350   
01351   retval = dbus_new (char *, allocated);
01352 
01353   if (!retval)
01354     return FALSE;
01355 
01356   while (pos < end_pos)
01357     {
01358       retval[len] = _dbus_demarshal_string (str, byte_order, pos, &pos);
01359       
01360       if (retval[len] == NULL)
01361         goto error;
01362       
01363       len += 1;
01364 
01365       if (len >= allocated - 1) /* -1 for NULL termination */
01366         {
01367           char **newp;
01368           newp = dbus_realloc (retval,
01369                                sizeof (char*) * allocated * 2);
01370           if (newp == NULL)
01371             goto error;
01372 
01373           allocated *= 2;
01374           retval = newp;
01375         }
01376     }
01377       
01378   retval[len] = NULL;
01379 
01380   if (new_pos)
01381     *new_pos = pos;
01382   
01383   *array = retval;
01384   *array_len = len;
01385   
01386   return TRUE;
01387 
01388  error:
01389   for (i = 0; i < len; i++)
01390     dbus_free (retval[i]);
01391   dbus_free (retval);
01392 
01393   return FALSE;
01394 }
01395 
01409 dbus_bool_t
01410 _dbus_marshal_get_arg_end_pos (const DBusString *str,
01411                                int               byte_order,
01412                                int               type,
01413                                int               pos,
01414                                int              *end_pos)
01415 {
01416   if (pos >= _dbus_string_get_length (str))
01417     return FALSE;
01418 
01419   switch (type)
01420     {
01421     case DBUS_TYPE_INVALID:
01422       return FALSE;
01423       break;
01424 
01425     case DBUS_TYPE_NIL:
01426       *end_pos = pos;
01427       break;
01428 
01429     case DBUS_TYPE_BYTE:
01430       *end_pos = pos + 1;
01431       break;
01432       
01433     case DBUS_TYPE_BOOLEAN:
01434       *end_pos = pos + 1;
01435       break;
01436 
01437     case DBUS_TYPE_INT32:
01438       *end_pos = _DBUS_ALIGN_VALUE (pos, sizeof (dbus_int32_t)) + sizeof (dbus_int32_t);
01439 
01440       break;
01441 
01442     case DBUS_TYPE_UINT32:
01443       *end_pos = _DBUS_ALIGN_VALUE (pos, sizeof (dbus_uint32_t)) + sizeof (dbus_uint32_t);
01444 
01445       break;
01446 
01447 #ifdef DBUS_HAVE_INT64
01448     case DBUS_TYPE_INT64:
01449       *end_pos = _DBUS_ALIGN_VALUE (pos, sizeof (dbus_int64_t)) + sizeof (dbus_int64_t);
01450 
01451       break;
01452 
01453     case DBUS_TYPE_UINT64:
01454       *end_pos = _DBUS_ALIGN_VALUE (pos, sizeof (dbus_uint64_t)) + sizeof (dbus_uint64_t);
01455 
01456       break;
01457 #endif /* DBUS_HAVE_INT64 */
01458       
01459     case DBUS_TYPE_DOUBLE:
01460       *end_pos = _DBUS_ALIGN_VALUE (pos, sizeof (double)) + sizeof (double);
01461 
01462       break;
01463 
01464     case DBUS_TYPE_STRING:
01465       {
01466         int len;
01467         
01468         /* Demarshal the length */
01469         len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
01470 
01471         *end_pos = pos + len + 1;
01472       }
01473       break;
01474 
01475     case DBUS_TYPE_NAMED:
01476       {
01477         int len;
01478         
01479         /* Demarshal the string length */
01480         len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
01481 
01482         *end_pos = pos + len + 1;
01483         
01484         /* Demarshal the data length */
01485         len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
01486 
01487         *end_pos = pos + len;
01488       }
01489       break;
01490       
01491     case DBUS_TYPE_ARRAY:
01492       {
01493         int len;
01494 
01495         /* Demarshal the length  */
01496         len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
01497         
01498         *end_pos = pos + len;
01499       }
01500       break;
01501 
01502     case DBUS_TYPE_DICT:
01503       {
01504         int len;
01505 
01506         /* Demarshal the length */
01507         len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
01508         
01509         *end_pos = pos + len;
01510       }
01511       break;
01512       
01513     default:
01514       _dbus_warn ("Unknown message arg type %d\n", type);
01515       _dbus_assert_not_reached ("Unknown message argument type\n");
01516       return FALSE;
01517     }
01518 
01519   if (*end_pos > _dbus_string_get_length (str))
01520     return FALSE;
01521   
01522   return TRUE;
01523 }
01524 
01538 static int
01539 demarshal_and_validate_len (const DBusString *str,
01540                             int               byte_order,
01541                             int               pos,
01542                             int              *new_pos)
01543 {
01544   int align_4 = _DBUS_ALIGN_VALUE (pos, 4);
01545   unsigned int len;
01546 
01547   _dbus_assert (new_pos != NULL);
01548   
01549   if ((align_4 + 4) > _dbus_string_get_length (str))
01550     {
01551       _dbus_verbose ("not enough room in message for array length\n");
01552       return -1;
01553     }
01554   
01555   if (!_dbus_string_validate_nul (str, pos,
01556                                   align_4 - pos))
01557     {
01558       _dbus_verbose ("array length alignment padding not initialized to nul\n");
01559       return -1;
01560     }
01561 
01562   len = _dbus_demarshal_uint32 (str, byte_order, align_4, new_pos);
01563 
01564   /* note that the len is the number of bytes, so we need it to be
01565    * at least SIZE_T_MAX, but make it smaller just to keep things
01566    * sane.  We end up using ints for most sizes to avoid unsigned mess
01567    * so limit to maximum 32-bit signed int divided by at least 8, more
01568    * for a bit of paranoia margin. INT_MAX/32 is about 65 megabytes.
01569    */  
01570 #define MAX_ARRAY_LENGTH (((unsigned int)_DBUS_INT_MAX) / 32)
01571   if (len > MAX_ARRAY_LENGTH)
01572     {
01573       _dbus_verbose ("array length %u exceeds maximum of %u\n",
01574                      len, MAX_ARRAY_LENGTH);
01575       return -1;
01576     }
01577   else
01578     return (int) len;
01579 }
01580 
01581 static dbus_bool_t
01582 validate_string (const DBusString *str,
01583                  int               pos,
01584                  int               len_without_nul,
01585                  int              *end_pos)
01586 {
01587   *end_pos = pos + len_without_nul + 1;
01588   
01589   if (*end_pos > _dbus_string_get_length (str))
01590     {
01591       _dbus_verbose ("string length outside length of the message\n");
01592       return FALSE;
01593     }
01594   
01595   if (_dbus_string_get_byte (str, pos + len_without_nul) != '\0')
01596     {
01597       _dbus_verbose ("string arg not nul-terminated\n");
01598       return FALSE;
01599     }
01600   
01601   if (!_dbus_string_validate_utf8 (str, pos, len_without_nul))
01602     {
01603       _dbus_verbose ("string is not valid UTF-8\n");
01604       return FALSE;
01605     }
01606 
01607   return TRUE;
01608 }   
01609 
01621 dbus_bool_t
01622 _dbus_marshal_validate_type   (const DBusString *str,
01623                                int               pos,
01624                                int              *type,
01625                                int              *end_pos)
01626 {
01627   const char *data;
01628   
01629   if (pos >= _dbus_string_get_length (str))
01630     return FALSE;
01631 
01632   data = _dbus_string_get_const_data_len (str, pos, 1);
01633 
01634   if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_LAST)
01635     {
01636       *type = *data;
01637       if (end_pos != NULL)
01638         *end_pos = pos + 1;
01639       return TRUE;
01640     }
01641   
01642   return FALSE;
01643 }
01644 
01645 /* Faster validator for array data that doesn't call
01646  * validate_arg for each value
01647  */
01648 static dbus_bool_t
01649 validate_array_data (const DBusString *str,
01650                      int               byte_order,
01651                      int               depth,
01652                      int               type,
01653                      int               array_type_pos,
01654                      int               pos,
01655                      int              *new_pos,
01656                      int               end)
01657 {
01658   switch (type)
01659     {
01660     case DBUS_TYPE_INVALID:
01661       return FALSE;
01662       break;
01663 
01664     case DBUS_TYPE_NIL:
01665       break;
01666 
01667     case DBUS_TYPE_STRING:
01668     case DBUS_TYPE_NAMED:      
01669     case DBUS_TYPE_ARRAY:
01670     case DBUS_TYPE_DICT:
01671       /* This clean recursion to validate_arg is what we
01672        * are doing logically for all types, but we don't
01673        * really want to call validate_arg for every byte
01674        * in a byte array, so the primitive types are
01675        * special-cased.
01676        */
01677       while (pos < end)
01678         {
01679           if (!_dbus_marshal_validate_arg (str, byte_order, depth,
01680                                            type, array_type_pos, pos, &pos))
01681             return FALSE;
01682         }
01683       break;
01684       
01685     case DBUS_TYPE_BYTE:
01686       pos = end;
01687       break;
01688       
01689     case DBUS_TYPE_BOOLEAN:
01690       while (pos < end)
01691         {
01692           unsigned char c;
01693           
01694           c = _dbus_string_get_byte (str, pos);
01695           
01696           if (!(c == 0 || c == 1))
01697             {
01698               _dbus_verbose ("boolean value must be either 0 or 1, not %d\n", c);
01699               return FALSE;
01700             }
01701           
01702           ++pos;
01703         }
01704       break;
01705       
01706     case DBUS_TYPE_INT32:
01707     case DBUS_TYPE_UINT32:
01708       /* Call validate arg one time to check alignment padding
01709        * at start of array
01710        */
01711       if (!_dbus_marshal_validate_arg (str, byte_order, depth,
01712                                        type, array_type_pos, pos, &pos))
01713         return FALSE;
01714       pos = _DBUS_ALIGN_VALUE (end, 4);
01715       break;
01716 
01717     case DBUS_TYPE_INT64:
01718     case DBUS_TYPE_UINT64:
01719     case DBUS_TYPE_DOUBLE:
01720       /* Call validate arg one time to check alignment padding
01721        * at start of array
01722        */
01723       if (!_dbus_marshal_validate_arg (str, byte_order, depth,
01724                                        type, array_type_pos, pos, &pos))
01725         return FALSE;
01726       pos = _DBUS_ALIGN_VALUE (end, 8);
01727       break;
01728       
01729     default:
01730       _dbus_verbose ("Unknown message arg type %d\n", type);
01731       return FALSE;
01732     }
01733 
01734   *new_pos = pos;
01735 
01736   return TRUE;
01737 }
01738 
01763 dbus_bool_t
01764 _dbus_marshal_validate_arg (const DBusString *str,
01765                             int               byte_order,
01766                             int               depth,
01767                             int               type,
01768                             int               array_type_pos,
01769                             int               pos,
01770                             int              *end_pos)
01771 {
01772   if (pos > _dbus_string_get_length (str))
01773     {
01774       _dbus_verbose ("Validation went off the end of the message\n");
01775       return FALSE;
01776     }
01777 
01778 #define MAX_VALIDATION_DEPTH 32
01779   
01780   if (depth > MAX_VALIDATION_DEPTH)
01781     {
01782       _dbus_verbose ("Maximum recursion depth reached validating message\n");
01783       return FALSE;
01784     }
01785   
01786   switch (type)
01787     {
01788     case DBUS_TYPE_INVALID:
01789       return FALSE;
01790       break;
01791 
01792     case DBUS_TYPE_NIL:
01793       *end_pos = pos;
01794       break;
01795 
01796     case DBUS_TYPE_BYTE:
01797       if (1 > _dbus_string_get_length (str) - pos)
01798         {
01799           _dbus_verbose ("no room for byte value\n");
01800           return FALSE;
01801         }
01802         
01803       *end_pos = pos + 1;
01804       break;
01805       
01806     case DBUS_TYPE_BOOLEAN:
01807       {
01808         unsigned char c;
01809 
01810         if (1 > _dbus_string_get_length (str) - pos)
01811           {
01812             _dbus_verbose ("no room for boolean value\n");
01813             return FALSE;
01814           }
01815         
01816         c = _dbus_string_get_byte (str, pos);
01817 
01818         if (!(c == 0 || c == 1))
01819           {
01820             _dbus_verbose ("boolean value must be either 0 or 1, not %d\n", c);
01821             return FALSE;
01822           }
01823         
01824         *end_pos = pos + 1;
01825       }
01826       break;
01827       
01828     case DBUS_TYPE_INT32:
01829     case DBUS_TYPE_UINT32:
01830       {
01831         int align_4 = _DBUS_ALIGN_VALUE (pos, 4);
01832         
01833         if (!_dbus_string_validate_nul (str, pos,
01834                                         align_4 - pos))
01835           {
01836             _dbus_verbose ("int32/uint32 alignment padding not initialized to nul\n");
01837             return FALSE;
01838           }
01839 
01840         *end_pos = align_4 + 4;
01841       }
01842       break;
01843 
01844     case DBUS_TYPE_INT64:
01845     case DBUS_TYPE_UINT64:
01846       {
01847         int align_8 = _DBUS_ALIGN_VALUE (pos, 8);
01848         
01849         if (!_dbus_string_validate_nul (str, pos,
01850                                         align_8 - pos))
01851           {
01852             _dbus_verbose ("int64/uint64 alignment padding not initialized to nul\n");
01853             return FALSE;
01854           }
01855 
01856         *end_pos = align_8 + 8;
01857       }
01858       break;
01859       
01860     case DBUS_TYPE_DOUBLE:
01861       {
01862         int align_8 = _DBUS_ALIGN_VALUE (pos, 8);
01863 
01864         _dbus_verbose_bytes_of_string (str, pos, (align_8 + 8 - pos));
01865         
01866         if (!_dbus_string_validate_nul (str, pos,
01867                                         align_8 - pos))
01868           {
01869             _dbus_verbose ("double alignment padding not initialized to nul\n");
01870             return FALSE;
01871           }
01872 
01873         *end_pos = align_8 + 8;
01874       }
01875       break;
01876 
01877     case DBUS_TYPE_STRING:
01878       {
01879         int len;
01880 
01881         /* Demarshal the length, which does NOT include
01882          * nul termination
01883          */
01884         len = demarshal_and_validate_len (str, byte_order, pos, &pos);
01885         if (len < 0)
01886           return FALSE;
01887 
01888         if (!validate_string (str, pos, len, end_pos))
01889           return FALSE;
01890       }
01891       break;
01892 
01893     case DBUS_TYPE_NAMED:
01894       {
01895         int len;
01896 
01897         /* Demarshal the string length, which does NOT include
01898          * nul termination
01899          */
01900         len = demarshal_and_validate_len (str, byte_order, pos, &pos);
01901         if (len < 0)
01902           return FALSE;
01903 
01904         if (!validate_string (str, pos, len, &pos))
01905           return FALSE;
01906 
01907         /* Validate data */
01908         len = demarshal_and_validate_len (str, byte_order, pos, &pos);
01909         if (len < 0)
01910           return FALSE;
01911 
01912         *end_pos = pos + len;
01913       }
01914       break;
01915       
01916     case DBUS_TYPE_ARRAY:
01917       {
01918         int len;
01919         int end;
01920         int array_type;
01921 
01922         if (array_type_pos == -1)
01923           {
01924             array_type_pos = pos;
01925 
01926             do
01927               {
01928                 if (!_dbus_marshal_validate_type (str, pos, &array_type, &pos))
01929                   {
01930                     _dbus_verbose ("invalid array type\n");
01931                     return FALSE;
01932                   }
01933                 
01934                 /* NIL values take up no space, so you couldn't iterate over an array of them.
01935                  * array of nil seems useless anyway; the useful thing might be array of
01936                  * (nil OR string) but we have no framework for that.
01937                  */
01938                 if (array_type == DBUS_TYPE_NIL)
01939                   {
01940                     _dbus_verbose ("array of NIL is not allowed\n");
01941                     return FALSE;
01942                   }
01943               }
01944             while (array_type == DBUS_TYPE_ARRAY);
01945           }
01946         else
01947           array_type_pos++;
01948 
01949         if (!_dbus_marshal_validate_type (str, array_type_pos, &array_type, NULL))
01950           {
01951             _dbus_verbose ("invalid array type\n");
01952             return FALSE;
01953           }
01954         
01955         len = demarshal_and_validate_len (str, byte_order, pos, &pos);
01956         if (len < 0)
01957           return FALSE;
01958 
01959         if (len > _dbus_string_get_length (str) - pos)
01960           {
01961             _dbus_verbose ("array length outside length of the message\n");
01962             return FALSE;
01963           }
01964         
01965         end = pos + len;
01966 
01967         if (!validate_array_data (str, byte_order, depth + 1,
01968                                   array_type, array_type_pos,
01969                                   pos, &pos, end))
01970           return FALSE;
01971 
01972         if (pos < end)
01973           {
01974             /* This should not be able to happen, as long as validate_arg moves forward;
01975              * but the check is here just to be paranoid.
01976              */
01977             _dbus_verbose ("array length %d specified was longer than actual array contents by %d\n",
01978                            len, end - pos);
01979             return FALSE;
01980           }
01981         
01982         if (pos > end)
01983           {
01984             _dbus_verbose ("array contents exceeds array length %d by %d\n", len, pos - end);
01985             return FALSE;
01986           }
01987 
01988         *end_pos = pos;
01989       }
01990       break;
01991 
01992     case DBUS_TYPE_DICT:
01993       {
01994         int dict_type;
01995         int len;
01996         int end;
01997         
01998         len = demarshal_and_validate_len (str, byte_order, pos, &pos);
01999         if (len < 0)
02000           return FALSE;
02001 
02002         if (len > _dbus_string_get_length (str) - pos)
02003           {
02004             _dbus_verbose ("dict length outside length of the message\n");
02005             return FALSE;
02006           }
02007         
02008         end = pos + len;
02009         
02010         while (pos < end)
02011           {
02012             /* Validate name */
02013             if (!_dbus_marshal_validate_arg (str, byte_order, depth + 1,
02014                                              DBUS_TYPE_STRING, -1, pos, &pos))
02015               return FALSE;
02016             
02017             if (!_dbus_marshal_validate_type (str, pos, &dict_type, &pos))
02018               {
02019                 _dbus_verbose ("invalid dict entry type at offset %d\n", pos);
02020                 return FALSE;
02021               }
02022             
02023             /* Validate element */
02024             if (!_dbus_marshal_validate_arg (str, byte_order, depth + 1,
02025                                              dict_type, -1, pos, &pos))
02026               return FALSE;
02027           }
02028         
02029         if (pos > end)
02030           {
02031             _dbus_verbose ("dict contents exceed stated dict length\n");
02032             return FALSE;
02033           }
02034         
02035         *end_pos = pos;
02036       }
02037       break;
02038       
02039     default:
02040       _dbus_verbose ("Unknown message arg type %d\n", type);
02041       return FALSE;
02042     }
02043 
02044   if (*end_pos > _dbus_string_get_length (str))
02045     return FALSE;
02046   
02047   return TRUE;
02048 }
02049 
02050 
02059 void
02060 _dbus_verbose_bytes (const unsigned char *data,
02061                      int                  len)
02062 {
02063   int i;
02064   const unsigned char *aligned;
02065 
02066   _dbus_assert (len >= 0);
02067   
02068   /* Print blanks on first row if appropriate */
02069   aligned = _DBUS_ALIGN_ADDRESS (data, 4);
02070   if (aligned > data)
02071     aligned -= 4;
02072   _dbus_assert (aligned <= data);
02073 
02074   if (aligned != data)
02075     {
02076       _dbus_verbose ("%4d\t%p: ", - (data - aligned), aligned); 
02077       while (aligned != data)
02078         {
02079           _dbus_verbose ("    ");
02080           ++aligned;
02081         }
02082     }
02083 
02084   /* now print the bytes */
02085   i = 0;
02086   while (i < len)
02087     {
02088       if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
02089         {
02090           _dbus_verbose ("%4d\t%p: ",
02091                    i, &data[i]);
02092         }
02093       
02094       if (data[i] >= 32 &&
02095           data[i] <= 126)
02096         _dbus_verbose (" '%c' ", data[i]);
02097       else
02098         _dbus_verbose ("0x%s%x ",
02099                  data[i] <= 0xf ? "0" : "", data[i]);
02100 
02101       ++i;
02102 
02103       if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
02104         {
02105           if (i > 3)
02106             _dbus_verbose ("BE: %d LE: %d",
02107                            _dbus_unpack_uint32 (DBUS_BIG_ENDIAN, &data[i-4]),
02108                            _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN, &data[i-4]));
02109 
02110           if (i > 7 && 
02111               _DBUS_ALIGN_ADDRESS (&data[i], 8) == &data[i])
02112             {
02113               _dbus_verbose (" dbl: %g",
02114                              *(double*)&data[i-8]);
02115             }
02116           
02117           _dbus_verbose ("\n");
02118         }
02119     }
02120 
02121   _dbus_verbose ("\n");
02122 }
02123 
02131 void
02132 _dbus_verbose_bytes_of_string (const DBusString    *str,
02133                                int                  start,
02134                                int                  len)
02135 {
02136   const char *d;
02137   int real_len;
02138 
02139   real_len = _dbus_string_get_length (str);
02140 
02141   _dbus_assert (start >= 0);
02142   
02143   if (start > real_len)
02144     {
02145       _dbus_verbose ("  [%d,%d) is not inside string of length %d\n",
02146                      start, len, real_len);
02147       return;
02148     }
02149 
02150   if ((start + len) > real_len)
02151     {
02152       _dbus_verbose ("  [%d,%d) extends outside string of length %d\n",
02153                      start, len, real_len);
02154       len = real_len - start;
02155     }
02156   
02157   d = _dbus_string_get_const_data_len (str, start, len);
02158 
02159   _dbus_verbose_bytes (d, len);
02160 }
02161 
02164 #ifdef DBUS_BUILD_TESTS
02165 #include "dbus-test.h"
02166 #include <stdio.h>
02167 
02168 dbus_bool_t
02169 _dbus_marshal_test (void)
02170 {
02171   DBusString str;
02172   char *tmp1, *tmp2;
02173   int pos = 0, len;
02174   dbus_int32_t array1[3] = { 0x123, 0x456, 0x789 }, *array2;
02175 #ifdef DBUS_HAVE_INT64
02176   dbus_int64_t array3[3] = { 0x123ffffffff, 0x456ffffffff, 0x789ffffffff }, *array4;
02177 #endif
02178   char *s;
02179   DBusString t;
02180   
02181   if (!_dbus_string_init (&str))
02182     _dbus_assert_not_reached ("failed to init string");
02183 
02184   /* Marshal doubles */
02185   if (!_dbus_marshal_double (&str, DBUS_BIG_ENDIAN, 3.14))
02186     _dbus_assert_not_reached ("could not marshal double value");
02187   if (!_dbus_demarshal_double (&str, DBUS_BIG_ENDIAN, pos, &pos) == 3.14)
02188     _dbus_assert_not_reached ("demarshal failed");
02189 
02190   if (!_dbus_marshal_double (&str, DBUS_LITTLE_ENDIAN, 3.14))
02191     _dbus_assert_not_reached ("could not marshal double value");
02192   if (!_dbus_demarshal_double (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == 3.14)
02193     _dbus_assert_not_reached ("demarshal failed");
02194   
02195   /* Marshal signed integers */
02196   if (!_dbus_marshal_int32 (&str, DBUS_BIG_ENDIAN, -12345678))
02197     _dbus_assert_not_reached ("could not marshal signed integer value");
02198   if (!_dbus_demarshal_int32 (&str, DBUS_BIG_ENDIAN, pos, &pos) == -12345678)
02199     _dbus_assert_not_reached ("demarshal failed");
02200 
02201   if (!_dbus_marshal_int32 (&str, DBUS_LITTLE_ENDIAN, -12345678))
02202     _dbus_assert_not_reached ("could not marshal signed integer value");
02203   if (!_dbus_demarshal_int32 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == -12345678)
02204     _dbus_assert_not_reached ("demarshal failed");
02205   
02206   /* Marshal unsigned integers */
02207   if (!_dbus_marshal_uint32 (&str, DBUS_BIG_ENDIAN, 0x12345678))
02208     _dbus_assert_not_reached ("could not marshal signed integer value");
02209   if (!_dbus_demarshal_uint32 (&str, DBUS_BIG_ENDIAN, pos, &pos) == 0x12345678)
02210     _dbus_assert_not_reached ("demarshal failed");
02211   
02212   if (!_dbus_marshal_uint32 (&str, DBUS_LITTLE_ENDIAN, 0x12345678))
02213     _dbus_assert_not_reached ("could not marshal signed integer value");
02214   if (!_dbus_demarshal_uint32 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == 0x12345678)
02215     _dbus_assert_not_reached ("demarshal failed");
02216 
02217 #ifdef DBUS_HAVE_INT64
02218   /* Marshal signed integers */
02219   if (!_dbus_marshal_int64 (&str, DBUS_BIG_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7)))
02220     _dbus_assert_not_reached ("could not marshal signed integer value");
02221   if (!_dbus_demarshal_int64 (&str, DBUS_BIG_ENDIAN, pos, &pos) == DBUS_INT64_CONSTANT (-0x123456789abc7))
02222     _dbus_assert_not_reached ("demarshal failed");
02223 
02224   if (!_dbus_marshal_int64 (&str, DBUS_LITTLE_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7)))
02225     _dbus_assert_not_reached ("could not marshal signed integer value");
02226   if (!_dbus_demarshal_int64 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == DBUS_INT64_CONSTANT (-0x123456789abc7))
02227     _dbus_assert_not_reached ("demarshal failed");
02228   
02229   /* Marshal unsigned integers */
02230   if (!_dbus_marshal_uint64 (&str, DBUS_BIG_ENDIAN, DBUS_UINT64_CONSTANT (0x123456789abc7)))
02231     _dbus_assert_not_reached ("could not marshal signed integer value");
02232   if (!(_dbus_demarshal_uint64 (&str, DBUS_BIG_ENDIAN, pos, &pos) == DBUS_UINT64_CONSTANT (0x123456789abc7)))
02233     _dbus_assert_not_reached ("demarshal failed");
02234   
02235   if (!_dbus_marshal_uint64 (&str, DBUS_LITTLE_ENDIAN, DBUS_UINT64_CONSTANT (0x123456789abc7)))
02236     _dbus_assert_not_reached ("could not marshal signed integer value");
02237   if (!(_dbus_demarshal_uint64 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == DBUS_UINT64_CONSTANT (0x123456789abc7)))
02238     _dbus_assert_not_reached ("demarshal failed");
02239 #endif /* DBUS_HAVE_INT64 */
02240   
02241   /* Marshal strings */
02242   tmp1 = "This is the dbus test string";
02243   if (!_dbus_marshal_string (&str, DBUS_BIG_ENDIAN, tmp1))
02244     _dbus_assert_not_reached ("could not marshal string");
02245   tmp2 = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, pos, &pos);
02246   if (!strcmp (tmp1, tmp2) == 0)
02247     _dbus_assert_not_reached ("demarshal failed");
02248   dbus_free (tmp2);
02249 
02250   tmp1 = "This is the dbus test string";
02251   if (!_dbus_marshal_string (&str, DBUS_LITTLE_ENDIAN, tmp1))
02252     _dbus_assert_not_reached ("could not marshal string");
02253   tmp2 = _dbus_demarshal_string (&str, DBUS_LITTLE_ENDIAN, pos, &pos);
02254   if (!strcmp (tmp1, tmp2) == 0)
02255     _dbus_assert_not_reached ("demarshal failed");
02256   dbus_free (tmp2);
02257 
02258   /* Marshal signed integer arrays */
02259   if (!_dbus_marshal_int32_array (&str, DBUS_BIG_ENDIAN, array1, 3))
02260     _dbus_assert_not_reached ("could not marshal integer array");
02261   if (!_dbus_demarshal_int32_array (&str, DBUS_BIG_ENDIAN, pos, &pos, &array2, &len))
02262     _dbus_assert_not_reached ("could not demarshal integer array");
02263 
02264   if (len != 3)
02265     _dbus_assert_not_reached ("Signed integer array lengths differ!\n");
02266   dbus_free (array2);
02267 
02268 #ifdef DBUS_HAVE_INT64
02269   /* Marshal 64-bit signed integer arrays */
02270   if (!_dbus_marshal_int64_array (&str, DBUS_BIG_ENDIAN, array3, 3))
02271     _dbus_assert_not_reached ("could not marshal integer array");
02272   if (!_dbus_demarshal_int64_array (&str, DBUS_BIG_ENDIAN, pos, &pos, &array4, &len))
02273     _dbus_assert_not_reached ("could not demarshal integer array");
02274 
02275   if (len != 3)
02276     _dbus_assert_not_reached ("Signed integer array lengths differ!\n");
02277   dbus_free (array4);
02278 
02279   /* set/pack 64-bit integers */
02280   _dbus_string_set_length (&str, 8);
02281 
02282   /* signed little */
02283   _dbus_marshal_set_int64 (&str, DBUS_LITTLE_ENDIAN,
02284                            0, DBUS_INT64_CONSTANT (-0x123456789abc7));
02285   
02286   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
02287                 _dbus_unpack_int64 (DBUS_LITTLE_ENDIAN,
02288                                     _dbus_string_get_const_data (&str)));
02289 
02290   /* signed big */
02291   _dbus_marshal_set_int64 (&str, DBUS_BIG_ENDIAN,
02292                            0, DBUS_INT64_CONSTANT (-0x123456789abc7));
02293 
02294   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
02295                 _dbus_unpack_int64 (DBUS_BIG_ENDIAN,
02296                                     _dbus_string_get_const_data (&str)));
02297 
02298   /* signed little pack */
02299   _dbus_pack_int64 (DBUS_INT64_CONSTANT (-0x123456789abc7),
02300                     DBUS_LITTLE_ENDIAN,
02301                     _dbus_string_get_data (&str));
02302   
02303   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
02304                 _dbus_unpack_int64 (DBUS_LITTLE_ENDIAN,
02305                                     _dbus_string_get_const_data (&str)));
02306 
02307   /* signed big pack */
02308   _dbus_pack_int64 (DBUS_INT64_CONSTANT (-0x123456789abc7),
02309                     DBUS_BIG_ENDIAN,
02310                     _dbus_string_get_data (&str));
02311 
02312   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
02313                 _dbus_unpack_int64 (DBUS_BIG_ENDIAN,
02314                                     _dbus_string_get_const_data (&str)));
02315 
02316   /* unsigned little */
02317   _dbus_marshal_set_uint64 (&str, DBUS_LITTLE_ENDIAN,
02318                             0, DBUS_UINT64_CONSTANT (0x123456789abc7));
02319   
02320   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
02321                 _dbus_unpack_uint64 (DBUS_LITTLE_ENDIAN,
02322                                      _dbus_string_get_const_data (&str)));
02323 
02324   /* unsigned big */
02325   _dbus_marshal_set_uint64 (&str, DBUS_BIG_ENDIAN,
02326                             0, DBUS_UINT64_CONSTANT (0x123456789abc7));
02327 
02328   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
02329                 _dbus_unpack_uint64 (DBUS_BIG_ENDIAN,
02330                                      _dbus_string_get_const_data (&str)));
02331 
02332   /* unsigned little pack */
02333   _dbus_pack_uint64 (DBUS_UINT64_CONSTANT (0x123456789abc7),
02334                      DBUS_LITTLE_ENDIAN,
02335                      _dbus_string_get_data (&str));
02336   
02337   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
02338                 _dbus_unpack_uint64 (DBUS_LITTLE_ENDIAN,
02339                                      _dbus_string_get_const_data (&str)));
02340 
02341   /* unsigned big pack */
02342   _dbus_pack_uint64 (DBUS_UINT64_CONSTANT (0x123456789abc7),
02343                      DBUS_BIG_ENDIAN,
02344                      _dbus_string_get_data (&str));
02345 
02346   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
02347                 _dbus_unpack_uint64 (DBUS_BIG_ENDIAN,
02348                                      _dbus_string_get_const_data (&str)));
02349   
02350 #endif
02351 
02352   /* set/pack 32-bit integers */
02353   _dbus_string_set_length (&str, 4);
02354 
02355   /* signed little */
02356   _dbus_marshal_set_int32 (&str, DBUS_LITTLE_ENDIAN,
02357                            0, -0x123456);
02358   
02359   _dbus_assert (-0x123456 ==
02360                 _dbus_unpack_int32 (DBUS_LITTLE_ENDIAN,
02361                                     _dbus_string_get_const_data (&str)));
02362 
02363   /* signed big */
02364   _dbus_marshal_set_int32 (&str, DBUS_BIG_ENDIAN,
02365                            0, -0x123456);
02366 
02367   _dbus_assert (-0x123456 ==
02368                 _dbus_unpack_int32 (DBUS_BIG_ENDIAN,
02369                                     _dbus_string_get_const_data (&str)));
02370 
02371   /* signed little pack */
02372   _dbus_pack_int32 (-0x123456,
02373                     DBUS_LITTLE_ENDIAN,
02374                     _dbus_string_get_data (&str));
02375   
02376   _dbus_assert (-0x123456 ==
02377                 _dbus_unpack_int32 (DBUS_LITTLE_ENDIAN,
02378                                     _dbus_string_get_const_data (&str)));
02379 
02380   /* signed big pack */
02381   _dbus_pack_int32 (-0x123456,
02382                     DBUS_BIG_ENDIAN,
02383                     _dbus_string_get_data (&str));
02384 
02385   _dbus_assert (-0x123456 ==
02386                 _dbus_unpack_int32 (DBUS_BIG_ENDIAN,
02387                                     _dbus_string_get_const_data (&str)));
02388 
02389   /* unsigned little */
02390   _dbus_marshal_set_uint32 (&str, DBUS_LITTLE_ENDIAN,
02391                             0, 0x123456);
02392   
02393   _dbus_assert (0x123456 ==
02394                 _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN,
02395                                      _dbus_string_get_const_data (&str)));
02396 
02397   /* unsigned big */
02398   _dbus_marshal_set_uint32 (&str, DBUS_BIG_ENDIAN,
02399                             0, 0x123456);
02400 
02401   _dbus_assert (0x123456 ==
02402                 _dbus_unpack_uint32 (DBUS_BIG_ENDIAN,
02403                                      _dbus_string_get_const_data (&str)));
02404 
02405   /* unsigned little pack */
02406   _dbus_pack_uint32 (0x123456,
02407                      DBUS_LITTLE_ENDIAN,
02408                      _dbus_string_get_data (&str));
02409   
02410   _dbus_assert (0x123456 ==
02411                 _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN,
02412                                      _dbus_string_get_const_data (&str)));
02413 
02414   /* unsigned big pack */
02415   _dbus_pack_uint32 (0x123456,
02416                      DBUS_BIG_ENDIAN,
02417                      _dbus_string_get_data (&str));
02418 
02419   _dbus_assert (0x123456 ==
02420                 _dbus_unpack_uint32 (DBUS_BIG_ENDIAN,
02421                                      _dbus_string_get_const_data (&str)));
02422 
02423 
02424   /* Strings */
02425   
02426   _dbus_string_set_length (&str, 0);
02427 
02428   _dbus_marshal_string (&str, DBUS_LITTLE_ENDIAN,
02429                         "Hello world");
02430   
02431   s = _dbus_demarshal_string (&str, DBUS_LITTLE_ENDIAN, 0, NULL);
02432   _dbus_assert (strcmp (s, "Hello world") == 0);
02433   dbus_free (s);
02434 
02435   _dbus_string_init_const (&t, "Hello world foo");
02436   
02437   _dbus_marshal_set_string (&str, DBUS_LITTLE_ENDIAN, 0,
02438                             &t, _dbus_string_get_length (&t));
02439   
02440   s = _dbus_demarshal_string (&str, DBUS_LITTLE_ENDIAN, 0, NULL);
02441   _dbus_assert (strcmp (s, "Hello world foo") == 0);
02442   dbus_free (s);
02443 
02444   _dbus_string_init_const (&t, "Hello");
02445   
02446   _dbus_marshal_set_string (&str, DBUS_LITTLE_ENDIAN, 0,
02447                             &t, _dbus_string_get_length (&t));
02448   
02449   s = _dbus_demarshal_string (&str, DBUS_LITTLE_ENDIAN, 0, NULL);
02450   _dbus_assert (strcmp (s, "Hello") == 0);
02451   dbus_free (s);
02452 
02453   /* Strings (big endian) */
02454   
02455   _dbus_string_set_length (&str, 0);
02456 
02457   _dbus_marshal_string (&str, DBUS_BIG_ENDIAN,
02458                         "Hello world");
02459   
02460   s = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, 0, NULL);
02461   _dbus_assert (strcmp (s, "Hello world") == 0);
02462   dbus_free (s);
02463 
02464   _dbus_string_init_const (&t, "Hello world foo");
02465   
02466   _dbus_marshal_set_string (&str, DBUS_BIG_ENDIAN, 0,
02467                             &t, _dbus_string_get_length (&t));
02468   
02469   s = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, 0, NULL);
02470   _dbus_assert (strcmp (s, "Hello world foo") == 0);
02471   dbus_free (s);
02472 
02473   _dbus_string_init_const (&t, "Hello");
02474   
02475   _dbus_marshal_set_string (&str, DBUS_BIG_ENDIAN, 0,
02476                             &t, _dbus_string_get_length (&t));
02477   
02478   s = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, 0, NULL);
02479   _dbus_assert (strcmp (s, "Hello") == 0);
02480   dbus_free (s);
02481 
02482   
02483   _dbus_string_free (&str);
02484       
02485   return TRUE;
02486 }
02487 
02488 #endif /* DBUS_BUILD_TESTS */

Generated on Wed Oct 22 14:05:02 2003 for D-BUS by doxygen1.3-rc3