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