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, 2004 Red Hat, Inc.
00006  *
00007  * Licensed under the Academic Free License version 2.1
00008  * 
00009  * This program is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  * 
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022  *
00023  */
00024 
00025 #include "dbus-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 
00080 typedef union
00081 {
00082 #ifdef DBUS_HAVE_INT64
00083   dbus_int64_t  s; 
00084   dbus_uint64_t u; 
00085 #endif
00086   double d;        
00087 } DBusOctets8;
00088 
00089 static DBusOctets8
00090 unpack_8_octets (int                  byte_order,
00091                  const unsigned char *data)
00092 {
00093   DBusOctets8 r;
00094   
00095   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 8) == data);
00096   _dbus_assert (sizeof (r) == 8);
00097   
00098 #ifdef DBUS_HAVE_INT64
00099   if (byte_order == DBUS_LITTLE_ENDIAN)
00100     r.u = DBUS_UINT64_FROM_LE (*(dbus_uint64_t*)data);
00101   else
00102     r.u = DBUS_UINT64_FROM_BE (*(dbus_uint64_t*)data);
00103 #else
00104   r.d = *(double*)data;
00105   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
00106     swap_bytes ((unsigned char*) &r, sizeof (r));
00107 #endif
00108   
00109   return r;
00110 }
00111 
00119 dbus_uint32_t
00120 _dbus_unpack_uint32 (int                  byte_order,
00121                      const unsigned char *data)
00122 {
00123   return unpack_4_octets (byte_order, data);
00124 }  
00125 
00133 dbus_int32_t
00134 _dbus_unpack_int32 (int                  byte_order,
00135                     const unsigned char *data)
00136 {
00137   return (dbus_int32_t) unpack_4_octets (byte_order, data);
00138 }
00139 
00140 #ifdef DBUS_HAVE_INT64
00141 
00148 dbus_uint64_t
00149 _dbus_unpack_uint64 (int                  byte_order,
00150                      const unsigned char *data)
00151 {
00152   DBusOctets8 r;
00153   
00154   r = unpack_8_octets (byte_order, data);
00155 
00156   return r.u;
00157 }  
00158 
00166 dbus_int64_t
00167 _dbus_unpack_int64 (int                  byte_order,
00168                     const unsigned char *data)
00169 {
00170   DBusOctets8 r;
00171   
00172   r = unpack_8_octets (byte_order, data);
00173 
00174   return r.s;
00175 }
00176 
00177 #endif /* DBUS_HAVE_INT64 */
00178 
00179 static void
00180 pack_4_octets (dbus_uint32_t   value,
00181                int             byte_order,
00182                unsigned char  *data)
00183 {
00184   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
00185   
00186   if ((byte_order) == DBUS_LITTLE_ENDIAN)                  
00187     *((dbus_uint32_t*)(data)) = DBUS_UINT32_TO_LE (value);       
00188   else
00189     *((dbus_uint32_t*)(data)) = DBUS_UINT32_TO_BE (value);
00190 }
00191 
00192 static void
00193 pack_8_octets (DBusOctets8     value,
00194                int             byte_order,
00195                unsigned char  *data)
00196 {
00197   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 8) == data);
00198 
00199 #ifdef DBUS_HAVE_INT64
00200   if ((byte_order) == DBUS_LITTLE_ENDIAN)                  
00201     *((dbus_uint64_t*)(data)) = DBUS_UINT64_TO_LE (value.u); 
00202   else
00203     *((dbus_uint64_t*)(data)) = DBUS_UINT64_TO_BE (value.u);
00204 #else
00205   memcpy (data, &value, 8);
00206   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
00207     swap_bytes ((unsigned char *)data, 8);
00208 #endif
00209 }
00210 
00218 void
00219 _dbus_pack_uint32 (dbus_uint32_t   value,
00220                    int             byte_order,
00221                    unsigned char  *data)
00222 {
00223   pack_4_octets (value, byte_order, data);
00224 }
00225 
00233 void
00234 _dbus_pack_int32 (dbus_int32_t   value,
00235                   int            byte_order,
00236                   unsigned char *data)
00237 {
00238   pack_4_octets ((dbus_uint32_t) value, byte_order, data);
00239 }
00240 
00241 #ifdef DBUS_HAVE_INT64
00242 
00249 void
00250 _dbus_pack_uint64 (dbus_uint64_t   value,
00251                    int             byte_order,
00252                    unsigned char  *data)
00253 {
00254   DBusOctets8 r;
00255   r.u = value;
00256   pack_8_octets (r, byte_order, data);
00257 }
00258 
00266 void
00267 _dbus_pack_int64 (dbus_int64_t   value,
00268                   int            byte_order,
00269                   unsigned char *data)
00270 {
00271   DBusOctets8 r;
00272   r.s = value;
00273   pack_8_octets (r, byte_order, data);
00274 }
00275 #endif /* DBUS_HAVE_INT64 */
00276 
00277 static void
00278 set_4_octets (DBusString          *str,
00279               int                  byte_order,
00280               int                  offset,
00281               dbus_uint32_t        value)
00282 {
00283   char *data;
00284   
00285   _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
00286                 byte_order == DBUS_BIG_ENDIAN);
00287   
00288   data = _dbus_string_get_data_len (str, offset, 4);
00289 
00290   _dbus_pack_uint32 (value, byte_order, data);
00291 }
00292 
00293 static void
00294 set_8_octets (DBusString          *str,
00295               int                  byte_order,
00296               int                  offset,
00297               DBusOctets8          value)
00298 {
00299   char *data;
00300   
00301   _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
00302                 byte_order == DBUS_BIG_ENDIAN);
00303   
00304   data = _dbus_string_get_data_len (str, offset, 8);
00305 
00306   pack_8_octets (value, byte_order, data);
00307 }
00308 
00319 void
00320 _dbus_marshal_set_int32 (DBusString          *str,
00321                          int                  byte_order,
00322                          int                  offset,
00323                          dbus_int32_t         value)
00324 {
00325   set_4_octets (str, byte_order, offset, (dbus_uint32_t) value);
00326 }
00327 
00338 void
00339 _dbus_marshal_set_uint32 (DBusString          *str,
00340                           int                  byte_order,
00341                           int                  offset,
00342                           dbus_uint32_t        value)
00343 {
00344   set_4_octets (str, byte_order, offset, value);
00345 }
00346 
00347 #ifdef DBUS_HAVE_INT64
00348 
00359 void
00360 _dbus_marshal_set_int64 (DBusString          *str,
00361                          int                  byte_order,
00362                          int                  offset,
00363                          dbus_int64_t         value)
00364 {
00365   DBusOctets8 r;
00366   r.s = value;
00367   set_8_octets (str, byte_order, offset, r);
00368 }
00369 
00380 void
00381 _dbus_marshal_set_uint64 (DBusString          *str,
00382                           int                  byte_order,
00383                           int                  offset,
00384                           dbus_uint64_t        value)
00385 {
00386   DBusOctets8 r;
00387   r.u = value;
00388   set_8_octets (str, byte_order, offset, r);
00389 }
00390 #endif /* DBUS_HAVE_INT64 */
00391 
00410 dbus_bool_t
00411 _dbus_marshal_set_string (DBusString          *str,
00412                           int                  byte_order,
00413                           int                  offset,
00414                           const DBusString    *value,
00415                           int                  len)
00416 {
00417   int old_len;
00418   
00419   _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
00420                 byte_order == DBUS_BIG_ENDIAN);
00421   
00422   old_len = _dbus_demarshal_uint32 (str, byte_order,
00423                                     offset, NULL);
00424 
00425   if (!_dbus_string_replace_len (value, 0, len,
00426                                  str, offset + 4, old_len))
00427     return FALSE;
00428 
00429   _dbus_marshal_set_uint32 (str, byte_order,
00430                             offset, len);
00431 
00432   return TRUE;
00433 }
00434 
00448 void
00449 _dbus_marshal_set_object_path (DBusString         *str,
00450                                int                 byte_order,
00451                                int                 offset,
00452                                const char        **path,
00453                                int                 path_len)
00454 {
00455 
00456   /* FIXME */
00457 }
00458 
00459 static dbus_bool_t
00460 marshal_4_octets (DBusString   *str,
00461                   int           byte_order,
00462                   dbus_uint32_t value)
00463 {
00464   _dbus_assert (sizeof (value) == 4);
00465   
00466   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
00467     value = DBUS_UINT32_SWAP_LE_BE (value);
00468 
00469   return _dbus_string_append_4_aligned (str,
00470                                         (const unsigned char *)&value);
00471 }
00472 
00473 static dbus_bool_t
00474 marshal_8_octets (DBusString *str,
00475                   int         byte_order,
00476                   DBusOctets8 value)
00477 {
00478   _dbus_assert (sizeof (value) == 8);
00479   
00480   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
00481     pack_8_octets (value, byte_order, (unsigned char*) &value); /* pack into self, swapping as we go */
00482 
00483   return _dbus_string_append_8_aligned (str,
00484                                         (const unsigned char *)&value);
00485 }
00486 
00495 dbus_bool_t
00496 _dbus_marshal_double (DBusString *str,
00497                       int         byte_order,
00498                       double      value)
00499 {
00500   DBusOctets8 r;
00501   r.d = value;
00502   return marshal_8_octets (str, byte_order, r);
00503 }
00504 
00513 dbus_bool_t
00514 _dbus_marshal_int32  (DBusString   *str,
00515                       int           byte_order,
00516                       dbus_int32_t  value)
00517 {
00518   return marshal_4_octets (str, byte_order, (dbus_uint32_t) value);
00519 }
00520 
00529 dbus_bool_t
00530 _dbus_marshal_uint32 (DBusString    *str,
00531                       int            byte_order,
00532                       dbus_uint32_t  value)
00533 {
00534   return marshal_4_octets (str, byte_order, value);
00535 }
00536 
00537 
00538 #ifdef DBUS_HAVE_INT64
00539 
00547 dbus_bool_t
00548 _dbus_marshal_int64  (DBusString   *str,
00549                       int           byte_order,
00550                       dbus_int64_t  value)
00551 {
00552   DBusOctets8 r;
00553   r.s = value;
00554   return marshal_8_octets (str, byte_order, r);
00555 }
00556 
00565 dbus_bool_t
00566 _dbus_marshal_uint64 (DBusString    *str,
00567                       int            byte_order,
00568                       dbus_uint64_t  value)
00569 {
00570   DBusOctets8 r;
00571   r.u = value;
00572   return marshal_8_octets (str, byte_order, r);
00573 }
00574 
00575 #endif /* DBUS_HAVE_INT64 */
00576 
00588 dbus_bool_t
00589 _dbus_marshal_string (DBusString    *str,
00590                       int            byte_order,
00591                       const char    *value)
00592 {
00593   int len, old_string_len;
00594 
00595   old_string_len = _dbus_string_get_length (str);
00596   
00597   len = strlen (value);
00598 
00599   if (!_dbus_marshal_uint32 (str, byte_order, len))
00600     {
00601       /* Restore the previous length */
00602       _dbus_string_set_length (str, old_string_len);
00603 
00604       return FALSE;
00605     }
00606 
00607   return _dbus_string_append_len (str, value, len + 1);
00608 }
00609 
00622 dbus_bool_t
00623 _dbus_marshal_string_len (DBusString    *str,
00624                           int            byte_order,
00625                           const char    *value,
00626                           int            len)
00627 {
00628   int old_string_len;
00629 
00630   old_string_len = _dbus_string_get_length (str);
00631 
00632   if (!_dbus_marshal_uint32 (str, byte_order, len))
00633     {
00634       /* Restore the previous length */
00635       _dbus_string_set_length (str, old_string_len);
00636 
00637       return FALSE;
00638     }
00639 
00640   if (!_dbus_string_append_len (str, value, len))
00641     return FALSE;
00642 
00643   /* add a nul byte */
00644   if (!_dbus_string_lengthen (str, 1))
00645     return FALSE;
00646 
00647   return TRUE;
00648 }
00649 
00659 dbus_bool_t
00660 _dbus_marshal_byte_array (DBusString          *str,
00661                           int                  byte_order,
00662                           const unsigned char *value,
00663                           int                  len)
00664 {
00665   int old_string_len;
00666 
00667   old_string_len = _dbus_string_get_length (str);
00668   
00669   if (!_dbus_marshal_uint32 (str, byte_order, len))
00670     {
00671       /* Restore the previous length */
00672       _dbus_string_set_length (str, old_string_len);
00673 
00674       return FALSE;
00675     }
00676 
00677   if (len == 0)
00678     return TRUE;
00679   else
00680     return _dbus_string_append_len (str, value, len);
00681 }
00682 
00683 static dbus_bool_t
00684 marshal_4_octets_array (DBusString          *str,
00685                         int                  byte_order,
00686                         const dbus_uint32_t *value,
00687                         int                  len)
00688 {
00689   int old_string_len;
00690   int array_start;
00691 
00692   old_string_len = _dbus_string_get_length (str);
00693 
00694   if (!_dbus_marshal_uint32 (str, byte_order, len * 4))
00695     goto error;
00696 
00697   array_start = _dbus_string_get_length (str);
00698   
00699   if (!_dbus_string_append_len (str, (const unsigned char*) value,
00700                                 len * 4))
00701     goto error;
00702   
00703   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
00704     {
00705       const unsigned char *d;
00706       const unsigned char *end;
00707       
00708       d = _dbus_string_get_data (str) + array_start;
00709       end = d + len * 4;
00710       while (d != end)
00711         {
00712           *((dbus_uint32_t*)d) = DBUS_UINT32_SWAP_LE_BE (*((dbus_uint32_t*)d));
00713           d += 4;
00714         }
00715     }
00716 
00717   return TRUE;
00718   
00719  error:
00720   /* Restore previous length */
00721   _dbus_string_set_length (str, old_string_len);
00722   
00723   return FALSE;  
00724 }
00725 
00726 static dbus_bool_t
00727 marshal_8_octets_array (DBusString          *str,
00728                         int                  byte_order,
00729                         const DBusOctets8   *value,
00730                         int                  len)
00731 {
00732   int old_string_len;
00733   int array_start;
00734 
00735   old_string_len = _dbus_string_get_length (str);
00736 
00737   if (!_dbus_marshal_uint32 (str, byte_order, len * 8))
00738     goto error;
00739 
00740   array_start = _dbus_string_get_length (str);
00741   
00742   if (!_dbus_string_append_len (str, (const unsigned char*) value,
00743                                 len * 8))
00744     goto error;
00745   
00746   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
00747     {
00748       const unsigned char *d;
00749       const unsigned char *end;
00750       
00751       d = _dbus_string_get_data (str) + array_start;
00752       end = d + len * 8;
00753       while (d != end)
00754         {
00755 #ifdef DBUS_HAVE_INT64
00756           *((dbus_uint64_t*)d) = DBUS_UINT64_SWAP_LE_BE (*((dbus_uint64_t*)d));
00757 #else
00758           swap_bytes ((unsigned char*) d, 8);
00759 #endif
00760           d += 8;
00761         }
00762     }
00763 
00764   return TRUE;
00765   
00766  error:
00767   /* Restore previous length */
00768   _dbus_string_set_length (str, old_string_len);
00769   
00770   return FALSE;  
00771 }
00772 
00782 dbus_bool_t
00783 _dbus_marshal_int32_array (DBusString         *str,
00784                            int                 byte_order,
00785                            const dbus_int32_t *value,
00786                            int                 len)
00787 {
00788   return marshal_4_octets_array (str, byte_order,
00789                                  (const dbus_uint32_t*) value,
00790                                  len);
00791 }
00792 
00802 dbus_bool_t
00803 _dbus_marshal_uint32_array (DBusString          *str,
00804                             int                  byte_order,
00805                             const dbus_uint32_t  *value,
00806                             int                  len)
00807 {
00808   return marshal_4_octets_array (str, byte_order,
00809                                  value,
00810                                  len);
00811 }
00812 
00813 #ifdef DBUS_HAVE_INT64
00814 
00824 dbus_bool_t
00825 _dbus_marshal_int64_array (DBusString         *str,
00826                            int                 byte_order,
00827                            const dbus_int64_t *value,
00828                            int                 len)
00829 {
00830   return marshal_8_octets_array (str, byte_order,
00831                                  (const DBusOctets8*) value,
00832                                  len);
00833 }
00834 
00844 dbus_bool_t
00845 _dbus_marshal_uint64_array (DBusString          *str,
00846                             int                  byte_order,
00847                             const dbus_uint64_t  *value,
00848                             int                  len)
00849 {
00850   return marshal_8_octets_array (str, byte_order,
00851                                  (const DBusOctets8*) value,
00852                                  len);
00853 }
00854 
00855 #endif /* DBUS_HAVE_INT64 */
00856 
00866 dbus_bool_t
00867 _dbus_marshal_double_array (DBusString          *str,
00868                             int                  byte_order,
00869                             const double        *value,
00870                             int                  len)
00871 {
00872   return marshal_8_octets_array (str, byte_order,
00873                                  (const DBusOctets8*) value,
00874                                  len);
00875 }
00876 
00886 dbus_bool_t
00887 _dbus_marshal_string_array (DBusString  *str,
00888                             int          byte_order,
00889                             const char **value,
00890                             int          len)
00891 {
00892   int i, old_string_len, array_start;
00893 
00894   old_string_len = _dbus_string_get_length (str);
00895 
00896   /* Set the length to 0 temporarily */
00897   if (!_dbus_marshal_uint32 (str, byte_order, 0))
00898     goto error;
00899 
00900   array_start = _dbus_string_get_length (str);
00901   
00902   for (i = 0; i < len; i++)
00903     if (!_dbus_marshal_string (str, byte_order, value[i]))
00904       goto error;
00905 
00906   /* Write the length now that we know it */
00907   _dbus_marshal_set_uint32 (str, byte_order,
00908                             _DBUS_ALIGN_VALUE (old_string_len, sizeof(dbus_uint32_t)),
00909                             _dbus_string_get_length (str) - array_start);
00910   
00911   return TRUE;
00912   
00913  error:
00914   /* Restore previous length */
00915   _dbus_string_set_length (str, old_string_len);
00916   
00917   return FALSE;      
00918 }
00919 
00929 dbus_bool_t
00930 _dbus_marshal_object_path (DBusString            *str,
00931                            int                    byte_order,
00932                            const char           **path,
00933                            int                    path_len)
00934 {
00935   int array_start, old_string_len;
00936   int i;
00937   
00938   old_string_len = _dbus_string_get_length (str);
00939   
00940   /* Set the length to 0 temporarily */
00941   if (!_dbus_marshal_uint32 (str, byte_order, 0))
00942     goto nomem;
00943 
00944   array_start = _dbus_string_get_length (str);
00945   
00946   i = 0;
00947   while (i < path_len)
00948     {
00949       if (!_dbus_string_append_byte (str, '/'))
00950         goto nomem;
00951       
00952       if (!_dbus_string_append (str, path[0]))
00953         goto nomem;
00954 
00955       ++i;
00956     }
00957 
00958   /* Write the length now that we know it */
00959   _dbus_marshal_set_uint32 (str, byte_order,
00960                             _DBUS_ALIGN_VALUE (old_string_len, sizeof(dbus_uint32_t)),
00961                             _dbus_string_get_length (str) - array_start);  
00962 
00963   return TRUE;
00964 
00965  nomem:
00966   /* Restore the previous length */
00967   _dbus_string_set_length (str, old_string_len);
00968   
00969   return FALSE;
00970 }
00971 
00972 static dbus_uint32_t
00973 demarshal_4_octets (const DBusString *str,
00974                     int               byte_order,
00975                     int               pos,
00976                     int              *new_pos)
00977 {
00978   const DBusRealString *real = (const DBusRealString*) str;
00979   
00980   pos = _DBUS_ALIGN_VALUE (pos, 4);
00981   
00982   if (new_pos)
00983     *new_pos = pos + 4;
00984 
00985   return unpack_4_octets (byte_order, real->str + pos);
00986 }
00987 
00988 static DBusOctets8
00989 demarshal_8_octets (const DBusString *str,
00990                     int               byte_order,
00991                     int               pos,
00992                     int              *new_pos)
00993 {
00994   const DBusRealString *real = (const DBusRealString*) str;
00995   
00996   pos = _DBUS_ALIGN_VALUE (pos, 8);
00997   
00998   if (new_pos)
00999     *new_pos = pos + 8;
01000 
01001   return unpack_8_octets (byte_order, real->str + pos);
01002 }
01003 
01013 double
01014 _dbus_demarshal_double (const DBusString  *str,
01015                         int                byte_order,
01016                         int                pos,
01017                         int               *new_pos)
01018 {
01019   DBusOctets8 r;
01020 
01021   r = demarshal_8_octets (str, byte_order, pos, new_pos);
01022 
01023   return r.d;
01024 }
01025 
01035 dbus_int32_t
01036 _dbus_demarshal_int32  (const DBusString *str,
01037                         int               byte_order,
01038                         int               pos,
01039                         int              *new_pos)
01040 {
01041   return (dbus_int32_t) demarshal_4_octets (str, byte_order, pos, new_pos);
01042 }
01043 
01053 dbus_uint32_t
01054 _dbus_demarshal_uint32  (const DBusString *str,
01055                          int         byte_order,
01056                          int         pos,
01057                          int        *new_pos)
01058 {
01059   return demarshal_4_octets (str, byte_order, pos, new_pos);
01060 }
01061 
01062 #ifdef DBUS_HAVE_INT64
01063 
01073 dbus_int64_t
01074 _dbus_demarshal_int64  (const DBusString *str,
01075                         int               byte_order,
01076                         int               pos,
01077                         int              *new_pos)
01078 {
01079   DBusOctets8 r;
01080 
01081   r = demarshal_8_octets (str, byte_order, pos, new_pos);
01082 
01083   return r.s;
01084 }
01085 
01095 dbus_uint64_t
01096 _dbus_demarshal_uint64  (const DBusString *str,
01097                          int         byte_order,
01098                          int         pos,
01099                          int        *new_pos)
01100 {
01101   DBusOctets8 r;
01102 
01103   r = demarshal_8_octets (str, byte_order, pos, new_pos);
01104 
01105   return r.u;
01106 }
01107 
01108 #endif /* DBUS_HAVE_INT64 */
01109 
01120 void
01121 _dbus_demarshal_basic_type (const DBusString      *str,
01122                             int                    type,
01123                             void                  *value,
01124                             int                    byte_order,
01125                             int                   *pos)
01126 {
01127   const char *str_data = _dbus_string_get_const_data (str);
01128 
01129   switch (type)
01130     {
01131     case DBUS_TYPE_BYTE:
01132     case DBUS_TYPE_BOOLEAN:
01133       *(unsigned char *) value = _dbus_string_get_byte (str, *pos);
01134       (*pos)++;
01135       break;
01136     case DBUS_TYPE_INT32:
01137     case DBUS_TYPE_UINT32:
01138       *pos = _DBUS_ALIGN_VALUE (*pos, 4);
01139       *(dbus_uint32_t *) value = *(dbus_uint32_t *)(str_data + *pos);
01140       if (byte_order != DBUS_COMPILER_BYTE_ORDER)
01141         *(dbus_uint32_t *) value = DBUS_UINT32_SWAP_LE_BE (*(dbus_uint32_t *) value);
01142       *pos += 4;
01143       break;
01144 #ifdef DBUS_HAVE_INT64
01145     case DBUS_TYPE_INT64:
01146     case DBUS_TYPE_UINT64: 
01147 #endif /* DBUS_HAVE_INT64 */
01148     case DBUS_TYPE_DOUBLE:
01149       *pos = _DBUS_ALIGN_VALUE (*pos, 8);
01150       memcpy (value, str_data + *pos, 8);
01151       if (byte_order != DBUS_COMPILER_BYTE_ORDER)
01152 #ifdef DBUS_HAVE_INT64
01153         *(dbus_uint64_t *) value = DBUS_UINT64_SWAP_LE_BE (*(dbus_uint64_t *) value);
01154 #else   
01155         swap_bytes (value, 8);
01156 #endif
01157       *pos += 8;
01158       break;
01159     default:
01160       _dbus_assert_not_reached ("not a basic type");
01161       break;
01162     }
01163 }
01164 
01181 char *
01182 _dbus_demarshal_string (const DBusString *str,
01183                         int               byte_order,
01184                         int               pos,
01185                         int              *new_pos)
01186 {
01187   int len;
01188   char *retval;
01189   const char *data;
01190   
01191   len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
01192 
01193   retval = dbus_malloc (len + 1);
01194 
01195   if (!retval)
01196     return NULL;
01197 
01198   data = _dbus_string_get_const_data_len (str, pos, len + 1);
01199 
01200   if (!data)
01201     return NULL;
01202 
01203   memcpy (retval, data, len + 1);
01204 
01205   if (new_pos)
01206     *new_pos = pos + len + 1;
01207   
01208   return retval;
01209 }
01210 
01226 dbus_bool_t
01227 _dbus_demarshal_byte_array (const DBusString  *str,
01228                             int                byte_order,
01229                             int                pos,
01230                             int               *new_pos,
01231                             unsigned char    **array,
01232                             int               *array_len)
01233 {
01234   int len;
01235   unsigned char *retval;
01236   const char *data;
01237 
01238   len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
01239 
01240   if (len == 0)
01241     {
01242       *array_len = len;
01243       *array = NULL;
01244 
01245       if (new_pos)
01246         *new_pos = pos;
01247       
01248       return TRUE;
01249     }
01250   
01251   retval = dbus_malloc (len);
01252 
01253   if (!retval)
01254     return FALSE;
01255 
01256   data = _dbus_string_get_const_data_len (str, pos, len);
01257 
01258   if (!data)
01259     {
01260       dbus_free (retval);
01261       return FALSE;
01262     }
01263 
01264   memcpy (retval, data, len);
01265 
01266   if (new_pos)
01267     *new_pos = pos + len;
01268 
01269   *array = retval;
01270   *array_len = len;
01271   
01272   return TRUE;
01273 }
01274 
01275 static dbus_bool_t
01276 demarshal_4_octets_array (const DBusString  *str,
01277                           int                byte_order,
01278                           int                pos,
01279                           int               *new_pos,
01280                           dbus_uint32_t    **array,
01281                           int               *array_len)
01282 {
01283   int len, i;
01284   dbus_uint32_t *retval;
01285   int byte_len;
01286   
01287   byte_len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
01288   len = byte_len / 4;
01289 
01290   if (len == 0)
01291     {
01292       *array_len = 0;
01293       *array = NULL;
01294 
01295       if (new_pos)
01296         *new_pos = pos;
01297       
01298       return TRUE;
01299     }
01300 
01301   if (!_dbus_string_copy_data_len (str, (char**) &retval,
01302                                    pos, byte_len))
01303     return FALSE;
01304   
01305   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
01306     {
01307       for (i = 0; i < len; i++)
01308         retval[i] = DBUS_UINT32_SWAP_LE_BE (retval[i]);
01309     }
01310 
01311   if (new_pos)
01312     *new_pos = pos + byte_len;
01313 
01314   *array_len = len;
01315   *array = retval;
01316   
01317   return TRUE;  
01318 }
01319 
01320 static dbus_bool_t
01321 demarshal_8_octets_array (const DBusString  *str,
01322                           int                byte_order,
01323                           int                pos,
01324                           int               *new_pos,
01325                           DBusOctets8      **array,
01326                           int               *array_len)
01327 {
01328   int len, i;
01329   DBusOctets8 *retval;
01330   int byte_len;
01331   
01332   byte_len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
01333   len = byte_len / 8;
01334 
01335   if (len == 0)
01336     {
01337       *array_len = 0;
01338       *array = NULL;
01339 
01340       if (new_pos)
01341         *new_pos = pos;
01342       
01343       return TRUE;
01344     }
01345 
01346   if (!_dbus_string_copy_data_len (str, (char**) &retval,
01347                                    pos, byte_len))
01348     return FALSE;
01349   
01350   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
01351     {
01352       for (i = 0; i < len; i++)
01353         {
01354 #ifdef DBUS_HAVE_INT64
01355           retval[i].u = DBUS_UINT64_SWAP_LE_BE (retval[i].u);
01356 #else
01357           swap_bytes ((unsigned char *) &retval[i], 8);
01358 #endif
01359         }
01360     }
01361 
01362   if (new_pos)
01363     *new_pos = pos + byte_len;
01364 
01365   *array_len = len;
01366   *array = retval;
01367   
01368   return TRUE;  
01369 }
01370 
01382 dbus_bool_t
01383 _dbus_demarshal_int32_array (const DBusString  *str,
01384                              int                byte_order,
01385                              int                pos,
01386                              int               *new_pos,
01387                              dbus_int32_t     **array,
01388                              int               *array_len)
01389 {
01390   return demarshal_4_octets_array (str, byte_order, pos, new_pos,
01391                                    (dbus_uint32_t**) array, array_len);
01392 }
01393 
01405 dbus_bool_t
01406 _dbus_demarshal_uint32_array (const DBusString  *str,
01407                               int                byte_order,
01408                               int                pos,
01409                               int               *new_pos,
01410                               dbus_uint32_t    **array,
01411                               int               *array_len)
01412 {
01413   return demarshal_4_octets_array (str, byte_order, pos, new_pos,
01414                                    array, array_len);
01415 }
01416 
01417 #ifdef DBUS_HAVE_INT64
01418 
01430 dbus_bool_t
01431 _dbus_demarshal_int64_array (const DBusString  *str,
01432                              int                byte_order,
01433                              int                pos,
01434                              int               *new_pos,
01435                              dbus_int64_t     **array,
01436                              int               *array_len)
01437 {
01438   return demarshal_8_octets_array (str, byte_order, pos, new_pos,
01439                                    (DBusOctets8**) array, array_len);
01440 }
01441 
01453 dbus_bool_t
01454 _dbus_demarshal_uint64_array (const DBusString  *str,
01455                               int                byte_order,
01456                               int                pos,
01457                               int               *new_pos,
01458                               dbus_uint64_t    **array,
01459                               int               *array_len)
01460 {
01461   return demarshal_8_octets_array (str, byte_order, pos, new_pos,
01462                                    (DBusOctets8**) array, array_len);
01463 }
01464 
01465 #endif /* DBUS_HAVE_INT64 */
01466 
01478 dbus_bool_t
01479 _dbus_demarshal_double_array (const DBusString  *str,
01480                               int                byte_order,
01481                               int                pos,
01482                               int               *new_pos,
01483                               double           **array,
01484                               int               *array_len)
01485 {
01486   return demarshal_8_octets_array (str, byte_order, pos, new_pos,
01487                                    (DBusOctets8**) array, array_len);
01488 }
01489 
01490 
01502 dbus_bool_t
01503 _dbus_demarshal_basic_type_array (const DBusString      *str,
01504                                   int                    element_type,
01505                                   void                 **array,
01506                                   int                   *array_len,
01507                                   int                    byte_order,
01508                                   int                   *pos)
01509 {
01510   switch (element_type)
01511     {
01512     case DBUS_TYPE_BOOLEAN:
01513       /* FIXME: do we want to post-normalize these ? */
01514     case DBUS_TYPE_BYTE:
01515       return _dbus_demarshal_byte_array (str, byte_order, *pos, pos,
01516                                          (unsigned char **)array, array_len);
01517       break;
01518     case DBUS_TYPE_INT32:
01519     case DBUS_TYPE_UINT32:
01520       return demarshal_4_octets_array (str, byte_order, *pos, pos,
01521                                        (dbus_uint32_t **)array, array_len);
01522       break;
01523 #ifdef DBUS_HAVE_INT64
01524     case DBUS_TYPE_INT64:
01525     case DBUS_TYPE_UINT64: 
01526 #endif /* DBUS_HAVE_INT64 */
01527     case DBUS_TYPE_DOUBLE:
01528       return demarshal_8_octets_array (str, byte_order, *pos, pos,
01529                                        (DBusOctets8**) array, array_len);
01530     default:
01531       _dbus_assert_not_reached ("not a basic type");
01532       break;
01533     }
01534   return FALSE;
01535 }
01536 
01548 dbus_bool_t
01549 _dbus_demarshal_string_array (const DBusString   *str,
01550                               int                 byte_order,
01551                               int                 pos,
01552                               int                *new_pos,
01553                               char             ***array,
01554                               int                *array_len)
01555 {
01556   int bytes_len, i;
01557   int len, allocated;
01558   int end_pos;
01559   char **retval;
01560   
01561   bytes_len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
01562   
01563   if (bytes_len == 0)
01564     {
01565       *array_len = 0;
01566       *array = NULL;
01567 
01568       if (new_pos)
01569         *new_pos = pos;
01570       
01571       return TRUE;
01572     }
01573 
01574   len = 0;
01575   allocated = 4;
01576   end_pos = pos + bytes_len;
01577   
01578   retval = dbus_new (char *, allocated);
01579 
01580   if (!retval)
01581     return FALSE;
01582 
01583   while (pos < end_pos)
01584     {
01585       retval[len] = _dbus_demarshal_string (str, byte_order, pos, &pos);
01586       
01587       if (retval[len] == NULL)
01588         goto error;
01589       
01590       len += 1;
01591 
01592       if (len >= allocated - 1) /* -1 for NULL termination */
01593         {
01594           char **newp;
01595           newp = dbus_realloc (retval,
01596                                sizeof (char*) * allocated * 2);
01597           if (newp == NULL)
01598             goto error;
01599 
01600           allocated *= 2;
01601           retval = newp;
01602         }
01603     }
01604       
01605   retval[len] = NULL;
01606 
01607   if (new_pos)
01608     *new_pos = pos;
01609   
01610   *array = retval;
01611   *array_len = len;
01612   
01613   return TRUE;
01614 
01615  error:
01616   for (i = 0; i < len; i++)
01617     dbus_free (retval[i]);
01618   dbus_free (retval);
01619 
01620   return FALSE;
01621 }
01622 
01624 #define VERBOSE_DECOMPOSE 0
01625 
01635 dbus_bool_t
01636 _dbus_decompose_path (const char*     data,
01637                       int             len,
01638                       char         ***path,
01639                       int            *path_len)
01640 {
01641   char **retval;
01642   int n_components;
01643   int i, j, comp;
01644 
01645   _dbus_assert (data != NULL);
01646 
01647 #if VERBOSE_DECOMPOSE
01648   _dbus_verbose ("Decomposing path \"%s\"\n",
01649                  data);
01650 #endif
01651   
01652   n_components = 0;
01653   i = 0;
01654   while (i < len)
01655     {
01656       if (data[i] == '/')
01657         n_components += 1;
01658       ++i;
01659     }
01660   
01661   retval = dbus_new0 (char*, n_components + 1);
01662 
01663   if (retval == NULL)
01664     return FALSE;
01665 
01666   comp = 0;
01667   i = 0;
01668   while (i < len)
01669     {
01670       if (data[i] == '/')
01671         ++i;
01672       j = i;
01673 
01674       while (j < len && data[j] != '/')
01675         ++j;
01676 
01677       /* Now [i, j) is the path component */
01678       _dbus_assert (i < j);
01679       _dbus_assert (data[i] != '/');
01680       _dbus_assert (j == len || data[j] == '/');
01681 
01682 #if VERBOSE_DECOMPOSE
01683       _dbus_verbose ("  (component in [%d,%d))\n",
01684                      i, j);
01685 #endif
01686       
01687       retval[comp] = _dbus_memdup (&data[i], j - i + 1);
01688       if (retval[comp] == NULL)
01689         {
01690           dbus_free_string_array (retval);
01691           return FALSE;
01692         }
01693       retval[comp][j-i] = '\0';
01694 #if VERBOSE_DECOMPOSE
01695       _dbus_verbose ("  (component %d = \"%s\")\n",
01696                      comp, retval[comp]);
01697 #endif
01698 
01699       ++comp;
01700       i = j;
01701     }
01702   _dbus_assert (i == len);
01703   
01704   *path = retval;
01705   if (path_len)
01706     *path_len = n_components;
01707   
01708   return TRUE;
01709 }
01710 
01722 dbus_bool_t
01723 _dbus_demarshal_object_path (const DBusString *str,
01724                              int               byte_order,
01725                              int               pos,
01726                              int              *new_pos,
01727                              char           ***path,
01728                              int              *path_len)
01729 {
01730   int len;
01731   const char *data;
01732   
01733   len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
01734   data = _dbus_string_get_const_data_len (str, pos, len + 1);
01735 
01736   if (!_dbus_decompose_path (data, len, path, path_len))
01737     return FALSE;
01738 
01739   if (new_pos)
01740     *new_pos = pos + len + 1;
01741 
01742   return TRUE;
01743 }
01744 
01758 dbus_bool_t
01759 _dbus_marshal_get_arg_end_pos (const DBusString *str,
01760                                int               byte_order,
01761                                int               type,
01762                                int               pos,
01763                                int              *end_pos)
01764 {
01765   if (pos >= _dbus_string_get_length (str))
01766     return FALSE;
01767 
01768   switch (type)
01769     {
01770     case DBUS_TYPE_INVALID:
01771       return FALSE;
01772       break;
01773 
01774     case DBUS_TYPE_NIL:
01775       *end_pos = pos;
01776       break;
01777 
01778     case DBUS_TYPE_BYTE:
01779       *end_pos = pos + 1;
01780       break;
01781       
01782     case DBUS_TYPE_BOOLEAN:
01783       *end_pos = pos + 1;
01784       break;
01785 
01786     case DBUS_TYPE_INT32:
01787     case DBUS_TYPE_UINT32:
01788       *end_pos = _DBUS_ALIGN_VALUE (pos, 4) + 4;
01789       break;
01790 
01791     case DBUS_TYPE_INT64:
01792     case DBUS_TYPE_UINT64:
01793     case DBUS_TYPE_DOUBLE:
01794       
01795       *end_pos = _DBUS_ALIGN_VALUE (pos, 8) + 8;
01796       break;
01797 
01798     case DBUS_TYPE_OBJECT_PATH:
01799     case DBUS_TYPE_STRING:
01800       {
01801         int len;
01802         
01803         /* Demarshal the length */
01804         len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
01805 
01806         *end_pos = pos + len + 1;
01807       }
01808       break;
01809 
01810     case DBUS_TYPE_CUSTOM:
01811       {
01812         int len;
01813         
01814         /* Demarshal the string length */
01815         len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
01816 
01817         pos += len + 1;
01818         
01819         /* Demarshal the data length */
01820         len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
01821 
01822         *end_pos = pos + len;
01823       }
01824       break;
01825       
01826     case DBUS_TYPE_ARRAY:
01827       {
01828         int len;
01829 
01830         /* Demarshal the length  */
01831         len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
01832         
01833         *end_pos = pos + len;
01834       }
01835       break;
01836 
01837     case DBUS_TYPE_DICT:
01838       {
01839         int len;
01840 
01841         /* Demarshal the length */
01842         len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
01843         
01844         *end_pos = pos + len;
01845       }
01846       break;
01847       
01848     default:
01849       _dbus_warn ("Unknown message arg type %d\n", type);
01850       _dbus_assert_not_reached ("Unknown message argument type\n");
01851       return FALSE;
01852     }
01853 
01854   if (*end_pos > _dbus_string_get_length (str))
01855     return FALSE;
01856   
01857   return TRUE;
01858 }
01859 
01873 static int
01874 demarshal_and_validate_len (const DBusString *str,
01875                             int               byte_order,
01876                             int               pos,
01877                             int              *new_pos)
01878 {
01879   int align_4 = _DBUS_ALIGN_VALUE (pos, 4);
01880   unsigned int len;
01881 
01882   _dbus_assert (new_pos != NULL);
01883   
01884   if ((align_4 + 4) > _dbus_string_get_length (str))
01885     {
01886       _dbus_verbose ("not enough room in message for array length\n");
01887       return -1;
01888     }
01889   
01890   if (!_dbus_string_validate_nul (str, pos,
01891                                   align_4 - pos))
01892     {
01893       _dbus_verbose ("array length alignment padding not initialized to nul at %d\n", pos);
01894       return -1;
01895     }
01896 
01897   len = _dbus_demarshal_uint32 (str, byte_order, align_4, new_pos);
01898 
01899   /* note that the len is the number of bytes, so we need it to be
01900    * at least SIZE_T_MAX, but make it smaller just to keep things
01901    * sane.  We end up using ints for most sizes to avoid unsigned mess
01902    * so limit to maximum 32-bit signed int divided by at least 8, more
01903    * for a bit of paranoia margin. INT_MAX/32 is about 65 megabytes.
01904    */  
01905 #define MAX_ARRAY_LENGTH (((unsigned int)_DBUS_INT_MAX) / 32)
01906   if (len > MAX_ARRAY_LENGTH)
01907     {
01908       _dbus_verbose ("array length %u exceeds maximum of %u at pos %d\n",
01909                      len, MAX_ARRAY_LENGTH, pos);
01910       return -1;
01911     }
01912   else
01913     return (int) len;
01914 }
01915 
01916 static dbus_bool_t
01917 validate_string (const DBusString *str,
01918                  int               pos,
01919                  int               len_without_nul,
01920                  int              *end_pos)
01921 {
01922   *end_pos = pos + len_without_nul + 1;
01923   
01924   if (*end_pos > _dbus_string_get_length (str))
01925     {
01926       _dbus_verbose ("string length outside length of the message\n");
01927       return FALSE;
01928     }
01929   
01930   if (_dbus_string_get_byte (str, pos + len_without_nul) != '\0')
01931     {
01932       _dbus_verbose ("string arg not nul-terminated\n");
01933       return FALSE;
01934     }
01935   
01936   if (!_dbus_string_validate_utf8 (str, pos, len_without_nul))
01937     {
01938       _dbus_verbose ("string is not valid UTF-8\n");
01939       return FALSE;
01940     }
01941 
01942   return TRUE;
01943 }   
01944 
01956 dbus_bool_t
01957 _dbus_marshal_validate_type   (const DBusString *str,
01958                                int               pos,
01959                                int              *type,
01960                                int              *end_pos)
01961 {
01962   const char *data;
01963   
01964   if (pos >= _dbus_string_get_length (str))
01965     return FALSE;
01966 
01967   data = _dbus_string_get_const_data_len (str, pos, 1);
01968 
01969   if (_dbus_type_is_valid (*data))
01970     {
01971       *type = *data;
01972       if (end_pos != NULL)
01973         *end_pos = pos + 1;
01974       return TRUE;
01975     }
01976 
01977   _dbus_verbose ("'%c' %d invalid type code\n", (int) *data, (int) *data);
01978   
01979   return FALSE;
01980 }
01981 
01982 /* Faster validator for array data that doesn't call
01983  * validate_arg for each value
01984  */
01985 static dbus_bool_t
01986 validate_array_data (const DBusString *str,
01987                      int               byte_order,
01988                      int               depth,
01989                      int               type,
01990                      int               array_type_pos,
01991                      int               pos,
01992                      int              *new_pos,
01993                      int               end)
01994 {
01995   switch (type)
01996     {
01997     case DBUS_TYPE_INVALID:
01998       return FALSE;
01999       break;
02000 
02001     case DBUS_TYPE_NIL:
02002       break;
02003 
02004     case DBUS_TYPE_OBJECT_PATH:
02005     case DBUS_TYPE_STRING:
02006     case DBUS_TYPE_CUSTOM:
02007     case DBUS_TYPE_ARRAY:
02008     case DBUS_TYPE_DICT:
02009       /* This clean recursion to validate_arg is what we
02010        * are doing logically for all types, but we don't
02011        * really want to call validate_arg for every byte
02012        * in a byte array, so the primitive types are
02013        * special-cased.
02014        */
02015       while (pos < end)
02016         {
02017           if (!_dbus_marshal_validate_arg (str, byte_order, depth,
02018                                            type, array_type_pos, pos, &pos))
02019             return FALSE;
02020         }
02021       break;
02022       
02023     case DBUS_TYPE_BYTE:
02024       pos = end;
02025       break;
02026       
02027     case DBUS_TYPE_BOOLEAN:
02028       while (pos < end)
02029         {
02030           unsigned char c;
02031           
02032           c = _dbus_string_get_byte (str, pos);
02033           
02034           if (!(c == 0 || c == 1))
02035             {
02036               _dbus_verbose ("boolean value must be either 0 or 1, not %d\n", c);
02037               return FALSE;
02038             }
02039           
02040           ++pos;
02041         }
02042       break;
02043       
02044     case DBUS_TYPE_INT32:
02045     case DBUS_TYPE_UINT32:
02046       /* Call validate arg one time to check alignment padding
02047        * at start of array
02048        */
02049       if (!_dbus_marshal_validate_arg (str, byte_order, depth,
02050                                        type, array_type_pos, pos, &pos))
02051         return FALSE;
02052       pos = _DBUS_ALIGN_VALUE (end, 4);
02053       break;
02054 
02055     case DBUS_TYPE_INT64:
02056     case DBUS_TYPE_UINT64:
02057     case DBUS_TYPE_DOUBLE:
02058       /* Call validate arg one time to check alignment padding
02059        * at start of array
02060        */
02061       if (!_dbus_marshal_validate_arg (str, byte_order, depth,
02062                                        type, array_type_pos, pos, &pos))
02063         return FALSE;
02064       pos = _DBUS_ALIGN_VALUE (end, 8);
02065       break;
02066       
02067     default:
02068       _dbus_verbose ("Unknown message arg type %d\n", type);
02069       return FALSE;
02070     }
02071 
02072   *new_pos = pos;
02073 
02074   return TRUE;
02075 }
02076 
02097 dbus_bool_t
02098 _dbus_marshal_validate_arg (const DBusString *str,
02099                             int               byte_order,
02100                             int               depth,
02101                             int               type,
02102                             int               array_type_pos,
02103                             int               pos,
02104                             int              *end_pos)
02105 {
02106   if (pos > _dbus_string_get_length (str))
02107     {
02108       _dbus_verbose ("Validation went off the end of the message\n");
02109       return FALSE;
02110     }
02111 
02112 #define MAX_VALIDATION_DEPTH 32
02113   
02114   if (depth > MAX_VALIDATION_DEPTH)
02115     {
02116       _dbus_verbose ("Maximum recursion depth reached validating message\n");
02117       return FALSE;
02118     }
02119   
02120   switch (type)
02121     {
02122     case DBUS_TYPE_INVALID:
02123       return FALSE;
02124       break;
02125 
02126     case DBUS_TYPE_NIL:
02127       *end_pos = pos;
02128       break;
02129 
02130     case DBUS_TYPE_BYTE:
02131       if (1 > _dbus_string_get_length (str) - pos)
02132         {
02133           _dbus_verbose ("no room for byte value\n");
02134           return FALSE;
02135         }
02136         
02137       *end_pos = pos + 1;
02138       break;
02139       
02140     case DBUS_TYPE_BOOLEAN:
02141       {
02142         unsigned char c;
02143 
02144         if (1 > _dbus_string_get_length (str) - pos)
02145           {
02146             _dbus_verbose ("no room for boolean value\n");
02147             return FALSE;
02148           }
02149         
02150         c = _dbus_string_get_byte (str, pos);
02151 
02152         if (!(c == 0 || c == 1))
02153           {
02154             _dbus_verbose ("boolean value must be either 0 or 1, not %d\n", c);
02155             return FALSE;
02156           }
02157         
02158         *end_pos = pos + 1;
02159       }
02160       break;
02161       
02162     case DBUS_TYPE_INT32:
02163     case DBUS_TYPE_UINT32:
02164       {
02165         int align_4 = _DBUS_ALIGN_VALUE (pos, 4);
02166         
02167         if (!_dbus_string_validate_nul (str, pos,
02168                                         align_4 - pos))
02169           {
02170             _dbus_verbose ("int32/uint32 alignment padding not initialized to nul\n");
02171             return FALSE;
02172           }
02173 
02174         *end_pos = align_4 + 4;
02175       }
02176       break;
02177 
02178     case DBUS_TYPE_INT64:
02179     case DBUS_TYPE_UINT64:      
02180     case DBUS_TYPE_DOUBLE:
02181       {
02182         int align_8 = _DBUS_ALIGN_VALUE (pos, 8);
02183 
02184         _dbus_verbose_bytes_of_string (str, pos, (align_8 + 8 - pos));
02185         
02186         if (!_dbus_string_validate_nul (str, pos,
02187                                         align_8 - pos))
02188           {
02189             _dbus_verbose ("double/int64/uint64/objid alignment padding not initialized to nul at %d\n", pos);
02190             return FALSE;
02191           }
02192 
02193         *end_pos = align_8 + 8;
02194       }
02195       break;
02196 
02197     case DBUS_TYPE_OBJECT_PATH:
02198     case DBUS_TYPE_STRING:
02199       {
02200         int len;
02201 
02202         /* Demarshal the length, which does NOT include
02203          * nul termination
02204          */
02205         len = demarshal_and_validate_len (str, byte_order, pos, &pos);
02206         if (len < 0)
02207           return FALSE;
02208 
02209         if (!validate_string (str, pos, len, end_pos))
02210           return FALSE;
02211 
02212         if (type == DBUS_TYPE_OBJECT_PATH)
02213           {
02214             if (!_dbus_string_validate_path (str, pos, len))
02215               return FALSE;
02216           }
02217       }
02218       break;
02219 
02220     case DBUS_TYPE_CUSTOM:
02221       {
02222         int len;
02223 
02224         /* Demarshal the string length, which does NOT include
02225          * nul termination
02226          */
02227         len = demarshal_and_validate_len (str, byte_order, pos, &pos);
02228         if (len < 0)
02229           return FALSE;
02230 
02231         if (!validate_string (str, pos, len, &pos))
02232           return FALSE;
02233 
02234         /* Validate data */
02235         len = demarshal_and_validate_len (str, byte_order, pos, &pos);
02236         if (len < 0)
02237           return FALSE;
02238 
02239         *end_pos = pos + len;
02240       }
02241       break;
02242       
02243     case DBUS_TYPE_ARRAY:
02244       {
02245         int len;
02246         int end;
02247         int array_type;
02248 
02249         if (array_type_pos == -1)
02250           {
02251             array_type_pos = pos;
02252 
02253             do
02254               {
02255                 if (!_dbus_marshal_validate_type (str, pos, &array_type, &pos))
02256                   {
02257                     _dbus_verbose ("invalid array type\n");
02258                     return FALSE;
02259                   }
02260                 
02261                 /* NIL values take up no space, so you couldn't iterate over an array of them.
02262                  * array of nil seems useless anyway; the useful thing might be array of
02263                  * (nil OR string) but we have no framework for that.
02264                  */
02265                 if (array_type == DBUS_TYPE_NIL)
02266                   {
02267                     _dbus_verbose ("array of NIL is not allowed\n");
02268                     return FALSE;
02269                   }
02270               }
02271             while (array_type == DBUS_TYPE_ARRAY);
02272           }
02273         else
02274           array_type_pos++;
02275 
02276         if (!_dbus_marshal_validate_type (str, array_type_pos, &array_type, NULL))
02277           {
02278             _dbus_verbose ("invalid array type\n");
02279             return FALSE;
02280           }
02281         
02282         len = demarshal_and_validate_len (str, byte_order, pos, &pos);
02283         if (len < 0)
02284           {
02285             _dbus_verbose ("invalid array length (<0)\n");
02286             return FALSE;
02287           }
02288 
02289         if (len > _dbus_string_get_length (str) - pos)
02290           {
02291             _dbus_verbose ("array length outside length of the message\n");
02292             return FALSE;
02293           }
02294         
02295         end = pos + len;
02296 
02297         if (len > 0 && !validate_array_data (str, byte_order, depth + 1,
02298                                              array_type, array_type_pos,
02299                                              pos, &pos, end))
02300           {
02301             _dbus_verbose ("invalid array data\n");
02302             return FALSE;
02303           }
02304 
02305         if (pos < end)
02306           {
02307             /* This should not be able to happen, as long as validate_arg moves forward;
02308              * but the check is here just to be paranoid.
02309              */
02310             _dbus_verbose ("array length %d specified was longer than actual array contents by %d\n",
02311                            len, end - pos);
02312             return FALSE;
02313           }
02314         
02315         if (pos > end)
02316           {
02317             _dbus_verbose ("array contents exceeds array length %d by %d\n", len, pos - end);
02318             return FALSE;
02319           }
02320 
02321         *end_pos = pos;
02322       }
02323       break;
02324 
02325     case DBUS_TYPE_DICT:
02326       {
02327         int dict_type;
02328         int len;
02329         int end;
02330         
02331         len = demarshal_and_validate_len (str, byte_order, pos, &pos);
02332         if (len < 0)
02333           return FALSE;
02334 
02335         if (len > _dbus_string_get_length (str) - pos)
02336           {
02337             _dbus_verbose ("dict length outside length of the message\n");
02338             return FALSE;
02339           }
02340         
02341         end = pos + len;
02342         
02343         while (pos < end)
02344           {
02345             /* Validate name */
02346             if (!_dbus_marshal_validate_arg (str, byte_order, depth + 1,
02347                                              DBUS_TYPE_STRING, -1, pos, &pos))
02348               return FALSE;
02349             
02350             if (!_dbus_marshal_validate_type (str, pos, &dict_type, &pos))
02351               {
02352                 _dbus_verbose ("invalid dict entry type at offset %d\n", pos);
02353                 return FALSE;
02354               }
02355             
02356             /* Validate element */
02357             if (!_dbus_marshal_validate_arg (str, byte_order, depth + 1,
02358                                              dict_type, -1, pos, &pos))
02359               {
02360                 _dbus_verbose ("dict arg invalid at offset %d\n", pos);
02361                 return FALSE;
02362               }
02363           }
02364         
02365         if (pos > end)
02366           {
02367             _dbus_verbose ("dict contents exceed stated dict length\n");
02368             return FALSE;
02369           }
02370         
02371         *end_pos = pos;
02372       }
02373       break;
02374       
02375     default:
02376       _dbus_verbose ("Unknown message arg type %d\n", type);
02377       return FALSE;
02378     }
02379 
02380   if (*end_pos > _dbus_string_get_length (str))
02381     return FALSE;
02382   
02383   return TRUE;
02384 }
02385 
02391 dbus_bool_t
02392 _dbus_type_is_valid (int typecode)
02393 {
02394   switch (typecode)
02395     {
02396     case DBUS_TYPE_NIL:
02397     case DBUS_TYPE_BYTE:
02398     case DBUS_TYPE_BOOLEAN:
02399     case DBUS_TYPE_INT32:
02400     case DBUS_TYPE_UINT32:
02401     case DBUS_TYPE_INT64:
02402     case DBUS_TYPE_UINT64:
02403     case DBUS_TYPE_DOUBLE:
02404     case DBUS_TYPE_STRING:
02405     case DBUS_TYPE_CUSTOM:
02406     case DBUS_TYPE_ARRAY:
02407     case DBUS_TYPE_DICT:
02408     case DBUS_TYPE_OBJECT_PATH:
02409       return TRUE;
02410       
02411     default:
02412       return FALSE;
02413     }
02414 }
02415 
02424 void
02425 _dbus_verbose_bytes (const unsigned char *data,
02426                      int                  len)
02427 {
02428   int i;
02429   const unsigned char *aligned;
02430 
02431   _dbus_assert (len >= 0);
02432   
02433   /* Print blanks on first row if appropriate */
02434   aligned = _DBUS_ALIGN_ADDRESS (data, 4);
02435   if (aligned > data)
02436     aligned -= 4;
02437   _dbus_assert (aligned <= data);
02438 
02439   if (aligned != data)
02440     {
02441       _dbus_verbose ("%4d\t%p: ", - (data - aligned), aligned); 
02442       while (aligned != data)
02443         {
02444           _dbus_verbose ("    ");
02445           ++aligned;
02446         }
02447     }
02448 
02449   /* now print the bytes */
02450   i = 0;
02451   while (i < len)
02452     {
02453       if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
02454         {
02455           _dbus_verbose ("%4d\t%p: ",
02456                    i, &data[i]);
02457         }
02458       
02459       if (data[i] >= 32 &&
02460           data[i] <= 126)
02461         _dbus_verbose (" '%c' ", data[i]);
02462       else
02463         _dbus_verbose ("0x%s%x ",
02464                  data[i] <= 0xf ? "0" : "", data[i]);
02465 
02466       ++i;
02467 
02468       if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
02469         {
02470           if (i > 3)
02471             _dbus_verbose ("BE: %d LE: %d",
02472                            _dbus_unpack_uint32 (DBUS_BIG_ENDIAN, &data[i-4]),
02473                            _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN, &data[i-4]));
02474 
02475           if (i > 7 && 
02476               _DBUS_ALIGN_ADDRESS (&data[i], 8) == &data[i])
02477             {
02478               _dbus_verbose (" dbl: %g",
02479                              *(double*)&data[i-8]);
02480             }
02481           
02482           _dbus_verbose ("\n");
02483         }
02484     }
02485 
02486   _dbus_verbose ("\n");
02487 }
02488 
02496 void
02497 _dbus_verbose_bytes_of_string (const DBusString    *str,
02498                                int                  start,
02499                                int                  len)
02500 {
02501   const char *d;
02502   int real_len;
02503 
02504   real_len = _dbus_string_get_length (str);
02505 
02506   _dbus_assert (start >= 0);
02507   
02508   if (start > real_len)
02509     {
02510       _dbus_verbose ("  [%d,%d) is not inside string of length %d\n",
02511                      start, len, real_len);
02512       return;
02513     }
02514 
02515   if ((start + len) > real_len)
02516     {
02517       _dbus_verbose ("  [%d,%d) extends outside string of length %d\n",
02518                      start, len, real_len);
02519       len = real_len - start;
02520     }
02521   
02522   d = _dbus_string_get_const_data_len (str, start, len);
02523 
02524   _dbus_verbose_bytes (d, len);
02525 }
02526 
02536 dbus_bool_t
02537 _dbus_marshal_basic_type (DBusString *str,
02538                           char        type,
02539                           void       *value,
02540                           int         byte_order)
02541 {
02542   dbus_bool_t retval;
02543 
02544   switch (type)
02545     {
02546     case DBUS_TYPE_BYTE:
02547     case DBUS_TYPE_BOOLEAN:
02548       retval = _dbus_string_append_byte (str, *(unsigned char *)value);
02549       break;
02550     case DBUS_TYPE_INT32:
02551     case DBUS_TYPE_UINT32:
02552       return marshal_4_octets (str, byte_order, *(dbus_uint32_t *)value);
02553       break;
02554 #ifdef DBUS_HAVE_INT64
02555     case DBUS_TYPE_INT64:
02556     case DBUS_TYPE_UINT64: 
02557       retval = _dbus_marshal_uint64 (str, byte_order, *(dbus_uint64_t *)value);
02558       break;
02559 #endif /* DBUS_HAVE_INT64 */
02560     case DBUS_TYPE_DOUBLE:
02561       retval = _dbus_marshal_double (str, byte_order, *(double *)value);
02562       break;
02563     default:
02564       _dbus_assert_not_reached ("not a basic type");
02565       retval = FALSE;
02566       break;
02567     }
02568   return retval;
02569 }
02570 
02581 dbus_bool_t
02582 _dbus_marshal_basic_type_array (DBusString *str,
02583                                 char        element_type,
02584                                 const void *value,
02585                                 int         len,
02586                                 int         byte_order)
02587 {
02588   switch (element_type)
02589     {
02590     case DBUS_TYPE_BOOLEAN:
02591       /* FIXME: we canonicalize to 0 or 1 for the single boolean case 
02592        * should we here too ? */
02593     case DBUS_TYPE_BYTE:
02594       return _dbus_marshal_byte_array (str, byte_order, value, len);
02595       break;
02596     case DBUS_TYPE_INT32:
02597     case DBUS_TYPE_UINT32:
02598       return marshal_4_octets_array (str, byte_order, value, len);
02599       break;
02600 #ifdef DBUS_HAVE_INT64
02601     case DBUS_TYPE_INT64:
02602     case DBUS_TYPE_UINT64: 
02603 #endif /* DBUS_HAVE_INT64 */
02604     case DBUS_TYPE_DOUBLE:
02605       return marshal_8_octets_array (str, byte_order, value, len);
02606       break;
02607     default:
02608       _dbus_assert_not_reached ("non basic type in array");
02609       break;
02610     }
02611   return FALSE;
02612 }
02613 
02616 #ifdef DBUS_BUILD_TESTS
02617 #include "dbus-test.h"
02618 #include <stdio.h>
02619 
02620 dbus_bool_t
02621 _dbus_marshal_test (void)
02622 {
02623   DBusString str;
02624   char *tmp1, *tmp2;
02625   int pos = 0, len;
02626   dbus_int32_t array1[3] = { 0x123, 0x456, 0x789 }, *array2;
02627 #ifdef DBUS_HAVE_INT64
02628   dbus_int64_t array3[3] = { DBUS_INT64_CONSTANT (0x123ffffffff), 
02629                              DBUS_INT64_CONSTANT (0x456ffffffff), 
02630                              DBUS_INT64_CONSTANT (0x789ffffffff) }, *array4;
02631 #endif
02632   char *s;
02633   DBusString t;
02634   
02635   if (!_dbus_string_init (&str))
02636     _dbus_assert_not_reached ("failed to init string");
02637 
02638   /* Marshal doubles */
02639   if (!_dbus_marshal_double (&str, DBUS_BIG_ENDIAN, 3.14))
02640     _dbus_assert_not_reached ("could not marshal double value");
02641   if (!_dbus_demarshal_double (&str, DBUS_BIG_ENDIAN, pos, &pos) == 3.14)
02642     _dbus_assert_not_reached ("demarshal failed");
02643 
02644   if (!_dbus_marshal_double (&str, DBUS_LITTLE_ENDIAN, 3.14))
02645     _dbus_assert_not_reached ("could not marshal double value");
02646   if (!_dbus_demarshal_double (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == 3.14)
02647     _dbus_assert_not_reached ("demarshal failed");
02648   
02649   /* Marshal signed integers */
02650   if (!_dbus_marshal_int32 (&str, DBUS_BIG_ENDIAN, -12345678))
02651     _dbus_assert_not_reached ("could not marshal signed integer value");
02652   if (!_dbus_demarshal_int32 (&str, DBUS_BIG_ENDIAN, pos, &pos) == -12345678)
02653     _dbus_assert_not_reached ("demarshal failed");
02654 
02655   if (!_dbus_marshal_int32 (&str, DBUS_LITTLE_ENDIAN, -12345678))
02656     _dbus_assert_not_reached ("could not marshal signed integer value");
02657   if (!_dbus_demarshal_int32 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == -12345678)
02658     _dbus_assert_not_reached ("demarshal failed");
02659   
02660   /* Marshal unsigned integers */
02661   if (!_dbus_marshal_uint32 (&str, DBUS_BIG_ENDIAN, 0x12345678))
02662     _dbus_assert_not_reached ("could not marshal signed integer value");
02663   if (!_dbus_demarshal_uint32 (&str, DBUS_BIG_ENDIAN, pos, &pos) == 0x12345678)
02664     _dbus_assert_not_reached ("demarshal failed");
02665   
02666   if (!_dbus_marshal_uint32 (&str, DBUS_LITTLE_ENDIAN, 0x12345678))
02667     _dbus_assert_not_reached ("could not marshal signed integer value");
02668   if (!_dbus_demarshal_uint32 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == 0x12345678)
02669     _dbus_assert_not_reached ("demarshal failed");
02670 
02671 #ifdef DBUS_HAVE_INT64
02672   /* Marshal signed integers */
02673   if (!_dbus_marshal_int64 (&str, DBUS_BIG_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7)))
02674     _dbus_assert_not_reached ("could not marshal signed integer value");
02675   if (_dbus_demarshal_int64 (&str, DBUS_BIG_ENDIAN, pos, &pos) != DBUS_INT64_CONSTANT (-0x123456789abc7))
02676     _dbus_assert_not_reached ("demarshal failed");
02677 
02678   if (!_dbus_marshal_int64 (&str, DBUS_LITTLE_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7)))
02679     _dbus_assert_not_reached ("could not marshal signed integer value");
02680   if (_dbus_demarshal_int64 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) != DBUS_INT64_CONSTANT (-0x123456789abc7))
02681     _dbus_assert_not_reached ("demarshal failed");
02682   
02683   /* Marshal unsigned integers */
02684   if (!_dbus_marshal_uint64 (&str, DBUS_BIG_ENDIAN, DBUS_UINT64_CONSTANT (0x123456789abc7)))
02685     _dbus_assert_not_reached ("could not marshal signed integer value");
02686   if (!(_dbus_demarshal_uint64 (&str, DBUS_BIG_ENDIAN, pos, &pos) == DBUS_UINT64_CONSTANT (0x123456789abc7)))
02687     _dbus_assert_not_reached ("demarshal failed");
02688   
02689   if (!_dbus_marshal_uint64 (&str, DBUS_LITTLE_ENDIAN, DBUS_UINT64_CONSTANT (0x123456789abc7)))
02690     _dbus_assert_not_reached ("could not marshal signed integer value");
02691   if (!(_dbus_demarshal_uint64 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == DBUS_UINT64_CONSTANT (0x123456789abc7)))
02692     _dbus_assert_not_reached ("demarshal failed");
02693 #endif /* DBUS_HAVE_INT64 */
02694   
02695   /* Marshal strings */
02696   tmp1 = "This is the dbus test string";
02697   if (!_dbus_marshal_string (&str, DBUS_BIG_ENDIAN, tmp1))
02698     _dbus_assert_not_reached ("could not marshal string");
02699   tmp2 = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, pos, &pos);
02700   if (!strcmp (tmp1, tmp2) == 0)
02701     _dbus_assert_not_reached ("demarshal failed");
02702   dbus_free (tmp2);
02703 
02704   tmp1 = "This is the dbus test string";
02705   if (!_dbus_marshal_string (&str, DBUS_LITTLE_ENDIAN, tmp1))
02706     _dbus_assert_not_reached ("could not marshal string");
02707   tmp2 = _dbus_demarshal_string (&str, DBUS_LITTLE_ENDIAN, pos, &pos);
02708   if (!strcmp (tmp1, tmp2) == 0)
02709     _dbus_assert_not_reached ("demarshal failed");
02710   dbus_free (tmp2);
02711 
02712   /* Marshal signed integer arrays */
02713   if (!_dbus_marshal_int32_array (&str, DBUS_BIG_ENDIAN, array1, 3))
02714     _dbus_assert_not_reached ("could not marshal integer array");
02715   if (!_dbus_demarshal_int32_array (&str, DBUS_BIG_ENDIAN, pos, &pos, &array2, &len))
02716     _dbus_assert_not_reached ("could not demarshal integer array");
02717 
02718   if (len != 3)
02719     _dbus_assert_not_reached ("Signed integer array lengths differ!\n");
02720   dbus_free (array2);
02721 
02722 #ifdef DBUS_HAVE_INT64
02723   /* Marshal 64-bit signed integer arrays */
02724   if (!_dbus_marshal_int64_array (&str, DBUS_BIG_ENDIAN, array3, 3))
02725     _dbus_assert_not_reached ("could not marshal integer array");
02726   if (!_dbus_demarshal_int64_array (&str, DBUS_BIG_ENDIAN, pos, &pos, &array4, &len))
02727     _dbus_assert_not_reached ("could not demarshal integer array");
02728 
02729   if (len != 3)
02730     _dbus_assert_not_reached ("Signed integer array lengths differ!\n");
02731   dbus_free (array4);
02732 
02733   /* set/pack 64-bit integers */
02734   _dbus_string_set_length (&str, 8);
02735 
02736   /* signed little */
02737   _dbus_marshal_set_int64 (&str, DBUS_LITTLE_ENDIAN,
02738                            0, DBUS_INT64_CONSTANT (-0x123456789abc7));
02739   
02740   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
02741                 _dbus_unpack_int64 (DBUS_LITTLE_ENDIAN,
02742                                     _dbus_string_get_const_data (&str)));
02743 
02744   /* signed big */
02745   _dbus_marshal_set_int64 (&str, DBUS_BIG_ENDIAN,
02746                            0, DBUS_INT64_CONSTANT (-0x123456789abc7));
02747 
02748   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
02749                 _dbus_unpack_int64 (DBUS_BIG_ENDIAN,
02750                                     _dbus_string_get_const_data (&str)));
02751 
02752   /* signed little pack */
02753   _dbus_pack_int64 (DBUS_INT64_CONSTANT (-0x123456789abc7),
02754                     DBUS_LITTLE_ENDIAN,
02755                     _dbus_string_get_data (&str));
02756   
02757   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
02758                 _dbus_unpack_int64 (DBUS_LITTLE_ENDIAN,
02759                                     _dbus_string_get_const_data (&str)));
02760 
02761   /* signed big pack */
02762   _dbus_pack_int64 (DBUS_INT64_CONSTANT (-0x123456789abc7),
02763                     DBUS_BIG_ENDIAN,
02764                     _dbus_string_get_data (&str));
02765 
02766   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
02767                 _dbus_unpack_int64 (DBUS_BIG_ENDIAN,
02768                                     _dbus_string_get_const_data (&str)));
02769 
02770   /* unsigned little */
02771   _dbus_marshal_set_uint64 (&str, DBUS_LITTLE_ENDIAN,
02772                             0, DBUS_UINT64_CONSTANT (0x123456789abc7));
02773   
02774   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
02775                 _dbus_unpack_uint64 (DBUS_LITTLE_ENDIAN,
02776                                      _dbus_string_get_const_data (&str)));
02777 
02778   /* unsigned big */
02779   _dbus_marshal_set_uint64 (&str, DBUS_BIG_ENDIAN,
02780                             0, DBUS_UINT64_CONSTANT (0x123456789abc7));
02781 
02782   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
02783                 _dbus_unpack_uint64 (DBUS_BIG_ENDIAN,
02784                                      _dbus_string_get_const_data (&str)));
02785 
02786   /* unsigned little pack */
02787   _dbus_pack_uint64 (DBUS_UINT64_CONSTANT (0x123456789abc7),
02788                      DBUS_LITTLE_ENDIAN,
02789                      _dbus_string_get_data (&str));
02790   
02791   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
02792                 _dbus_unpack_uint64 (DBUS_LITTLE_ENDIAN,
02793                                      _dbus_string_get_const_data (&str)));
02794 
02795   /* unsigned big pack */
02796   _dbus_pack_uint64 (DBUS_UINT64_CONSTANT (0x123456789abc7),
02797                      DBUS_BIG_ENDIAN,
02798                      _dbus_string_get_data (&str));
02799 
02800   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
02801                 _dbus_unpack_uint64 (DBUS_BIG_ENDIAN,
02802                                      _dbus_string_get_const_data (&str)));
02803   
02804 #endif
02805 
02806   /* set/pack 32-bit integers */
02807   _dbus_string_set_length (&str, 4);
02808 
02809   /* signed little */
02810   _dbus_marshal_set_int32 (&str, DBUS_LITTLE_ENDIAN,
02811                            0, -0x123456);
02812   
02813   _dbus_assert (-0x123456 ==
02814                 _dbus_unpack_int32 (DBUS_LITTLE_ENDIAN,
02815                                     _dbus_string_get_const_data (&str)));
02816 
02817   /* signed big */
02818   _dbus_marshal_set_int32 (&str, DBUS_BIG_ENDIAN,
02819                            0, -0x123456);
02820 
02821   _dbus_assert (-0x123456 ==
02822                 _dbus_unpack_int32 (DBUS_BIG_ENDIAN,
02823                                     _dbus_string_get_const_data (&str)));
02824 
02825   /* signed little pack */
02826   _dbus_pack_int32 (-0x123456,
02827                     DBUS_LITTLE_ENDIAN,
02828                     _dbus_string_get_data (&str));
02829   
02830   _dbus_assert (-0x123456 ==
02831                 _dbus_unpack_int32 (DBUS_LITTLE_ENDIAN,
02832                                     _dbus_string_get_const_data (&str)));
02833 
02834   /* signed big pack */
02835   _dbus_pack_int32 (-0x123456,
02836                     DBUS_BIG_ENDIAN,
02837                     _dbus_string_get_data (&str));
02838 
02839   _dbus_assert (-0x123456 ==
02840                 _dbus_unpack_int32 (DBUS_BIG_ENDIAN,
02841                                     _dbus_string_get_const_data (&str)));
02842 
02843   /* unsigned little */
02844   _dbus_marshal_set_uint32 (&str, DBUS_LITTLE_ENDIAN,
02845                             0, 0x123456);
02846   
02847   _dbus_assert (0x123456 ==
02848                 _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN,
02849                                      _dbus_string_get_const_data (&str)));
02850 
02851   /* unsigned big */
02852   _dbus_marshal_set_uint32 (&str, DBUS_BIG_ENDIAN,
02853                             0, 0x123456);
02854 
02855   _dbus_assert (0x123456 ==
02856                 _dbus_unpack_uint32 (DBUS_BIG_ENDIAN,
02857                                      _dbus_string_get_const_data (&str)));
02858 
02859   /* unsigned little pack */
02860   _dbus_pack_uint32 (0x123456,
02861                      DBUS_LITTLE_ENDIAN,
02862                      _dbus_string_get_data (&str));
02863   
02864   _dbus_assert (0x123456 ==
02865                 _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN,
02866                                      _dbus_string_get_const_data (&str)));
02867 
02868   /* unsigned big pack */
02869   _dbus_pack_uint32 (0x123456,
02870                      DBUS_BIG_ENDIAN,
02871                      _dbus_string_get_data (&str));
02872 
02873   _dbus_assert (0x123456 ==
02874                 _dbus_unpack_uint32 (DBUS_BIG_ENDIAN,
02875                                      _dbus_string_get_const_data (&str)));
02876 
02877 
02878   /* Strings */
02879   
02880   _dbus_string_set_length (&str, 0);
02881 
02882   _dbus_marshal_string (&str, DBUS_LITTLE_ENDIAN,
02883                         "Hello world");
02884   
02885   s = _dbus_demarshal_string (&str, DBUS_LITTLE_ENDIAN, 0, NULL);
02886   _dbus_assert (strcmp (s, "Hello world") == 0);
02887   dbus_free (s);
02888 
02889   _dbus_string_init_const (&t, "Hello world foo");
02890   
02891   _dbus_marshal_set_string (&str, DBUS_LITTLE_ENDIAN, 0,
02892                             &t, _dbus_string_get_length (&t));
02893   
02894   s = _dbus_demarshal_string (&str, DBUS_LITTLE_ENDIAN, 0, NULL);
02895   _dbus_assert (strcmp (s, "Hello world foo") == 0);
02896   dbus_free (s);
02897 
02898   _dbus_string_init_const (&t, "Hello");
02899   
02900   _dbus_marshal_set_string (&str, DBUS_LITTLE_ENDIAN, 0,
02901                             &t, _dbus_string_get_length (&t));
02902   
02903   s = _dbus_demarshal_string (&str, DBUS_LITTLE_ENDIAN, 0, NULL);
02904   _dbus_assert (strcmp (s, "Hello") == 0);
02905   dbus_free (s);
02906 
02907   /* Strings (big endian) */
02908   
02909   _dbus_string_set_length (&str, 0);
02910 
02911   _dbus_marshal_string (&str, DBUS_BIG_ENDIAN,
02912                         "Hello world");
02913   
02914   s = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, 0, NULL);
02915   _dbus_assert (strcmp (s, "Hello world") == 0);
02916   dbus_free (s);
02917 
02918   _dbus_string_init_const (&t, "Hello world foo");
02919   
02920   _dbus_marshal_set_string (&str, DBUS_BIG_ENDIAN, 0,
02921                             &t, _dbus_string_get_length (&t));
02922   
02923   s = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, 0, NULL);
02924   _dbus_assert (strcmp (s, "Hello world foo") == 0);
02925   dbus_free (s);
02926 
02927   _dbus_string_init_const (&t, "Hello");
02928   
02929   _dbus_marshal_set_string (&str, DBUS_BIG_ENDIAN, 0,
02930                             &t, _dbus_string_get_length (&t));
02931   
02932   s = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, 0, NULL);
02933   _dbus_assert (strcmp (s, "Hello") == 0);
02934   dbus_free (s);
02935   
02936   _dbus_string_free (&str);
02937       
02938   return TRUE;
02939 }
02940 
02941 #endif /* DBUS_BUILD_TESTS */

Generated on Sat Sep 25 19:17:12 2004 for D-BUS by  doxygen 1.3.8-20040913