dbus-marshal-basic.c 56.8 KB
Newer Older
1 2 3 4
/* -*- mode: C; c-file-style: "gnu" -*- */
/* dbus-marshal-basic.c  Marshalling routines for basic (primitive) types
 *
 * Copyright (C) 2002 CodeFactory AB
5
 * Copyright (C) 2003, 2004, 2005 Red Hat, Inc.
6 7
 *
 * Licensed under the Academic Free License version 2.1
8
 *
9 10 11 12 13 14 15 16 17
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
18
 *
19 20 21 22 23 24 25
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#include "dbus-internals.h"
26 27
#include "dbus-marshal-basic.h"

28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
#include <string.h>

/**
 * @defgroup DBusMarshal marshaling and unmarshaling
 * @ingroup  DBusInternals
 * @brief functions to marshal/unmarshal data from the wire
 *
 * Types and functions related to converting primitive data types from
 * wire format to native machine format, and vice versa.
 *
 * A signature is just a string with multiple types one after the other.
 * for example a type is "i" or "(ii)", a signature is "i(ii)"
 * where i is int and (ii) is struct { int; int; }
 *
 * @{
 */

45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
static void
pack_4_octets (dbus_uint32_t   value,
               int             byte_order,
               unsigned char  *data)
{
  _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);

  if ((byte_order) == DBUS_LITTLE_ENDIAN)
    *((dbus_uint32_t*)(data)) = DBUS_UINT32_TO_LE (value);
  else
    *((dbus_uint32_t*)(data)) = DBUS_UINT32_TO_BE (value);
}

static void
pack_8_octets (DBusBasicValue     value,
               int                byte_order,
               unsigned char     *data)
{
  _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 8) == data);

#ifdef DBUS_HAVE_INT64
  if ((byte_order) == DBUS_LITTLE_ENDIAN)
    *((dbus_uint64_t*)(data)) = DBUS_UINT64_TO_LE (value.u64);
  else
    *((dbus_uint64_t*)(data)) = DBUS_UINT64_TO_BE (value.u64);
#else
  *(DBus8ByteStruct*)data = value.u64;
  swap_8_octets ((DBusBasicValue*)data, byte_order);
#endif
}

/**
 * Packs a 32 bit unsigned integer into a data pointer.
 *
 * @param value the value
 * @param byte_order the byte order to use
 * @param data the data pointer
 */
void
_dbus_pack_uint32 (dbus_uint32_t   value,
                   int             byte_order,
                   unsigned char  *data)
{
  pack_4_octets (value, byte_order, data);
}

/**
 * Packs a 32 bit signed integer into a data pointer.
 *
 * @param value the value
 * @param byte_order the byte order to use
 * @param data the data pointer
 */
void
_dbus_pack_int32 (dbus_int32_t   value,
                  int            byte_order,
                  unsigned char *data)
{
  pack_4_octets ((dbus_uint32_t) value, byte_order, data);
}

106 107 108 109 110
static dbus_uint32_t
unpack_4_octets (int                  byte_order,
                 const unsigned char *data)
{
  _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
111

112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
  if (byte_order == DBUS_LITTLE_ENDIAN)
    return DBUS_UINT32_FROM_LE (*(dbus_uint32_t*)data);
  else
    return DBUS_UINT32_FROM_BE (*(dbus_uint32_t*)data);
}

#ifndef DBUS_HAVE_INT64
/* from ORBit */
static void
swap_bytes (unsigned char *data,
            unsigned int   len)
{
  unsigned char *p1 = data;
  unsigned char *p2 = data + len - 1;

  while (p1 < p2)
    {
      unsigned char tmp = *p1;
      *p1 = *p2;
      *p2 = tmp;

      --p2;
      ++p1;
    }
}
#endif /* !DBUS_HAVE_INT64 */

139 140 141
static void
swap_8_octets (DBusBasicValue    *value,
               int                byte_order)
142
{
143 144
  if (byte_order != DBUS_COMPILER_BYTE_ORDER)
    {
145
#ifdef DBUS_HAVE_INT64
146 147 148
      value->u64 = DBUS_UINT64_SWAP_LE_BE (value->u64);
#else
      swap_bytes ((unsigned char *)value, 8);
149
#endif
150 151
    }
}
152

153
#if 0
154
static DBusBasicValue
155 156 157
unpack_8_octets (int                  byte_order,
                 const unsigned char *data)
{
158
  DBusBasicValue r;
159

160 161
  _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 8) == data);
  _dbus_assert (sizeof (r) == 8);
162

163 164
#ifdef DBUS_HAVE_INT64
  if (byte_order == DBUS_LITTLE_ENDIAN)
165
    r.u64 = DBUS_UINT64_FROM_LE (*(dbus_uint64_t*)data);
166
  else
167
    r.u64 = DBUS_UINT64_FROM_BE (*(dbus_uint64_t*)data);
168
#else
169 170
  r.u64 = *(DBus8ByteStruct*)data;
  swap_8_octets (&r, byte_order);
171
#endif
172

173 174
  return r;
}
175
#endif
176 177 178 179 180 181 182 183 184 185 186 187 188

/**
 * Unpacks a 32 bit unsigned integer from a data pointer
 *
 * @param byte_order The byte order to use
 * @param data the data pointer
 * @returns the integer
 */
dbus_uint32_t
_dbus_unpack_uint32 (int                  byte_order,
                     const unsigned char *data)
{
  return unpack_4_octets (byte_order, data);
189
}
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207

/**
 * Unpacks a 32 bit signed integer from a data pointer
 *
 * @param byte_order The byte order to use
 * @param data the data pointer
 * @returns the integer
 */
dbus_int32_t
_dbus_unpack_int32 (int                  byte_order,
                    const unsigned char *data)
{
  return (dbus_int32_t) unpack_4_octets (byte_order, data);
}

static void
set_4_octets (DBusString          *str,
              int                  offset,
208 209
              dbus_uint32_t        value,
              int                  byte_order)
210 211
{
  char *data;
212

213 214
  _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
                byte_order == DBUS_BIG_ENDIAN);
215

216 217 218 219 220 221 222 223
  data = _dbus_string_get_data_len (str, offset, 4);

  _dbus_pack_uint32 (value, byte_order, data);
}

static void
set_8_octets (DBusString          *str,
              int                  offset,
224 225
              DBusBasicValue       value,
              int                  byte_order)
226 227
{
  char *data;
228

229 230
  _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
                byte_order == DBUS_BIG_ENDIAN);
231

232 233 234 235 236 237 238 239 240 241
  data = _dbus_string_get_data_len (str, offset, 8);

  pack_8_octets (value, byte_order, data);
}

/**
 * Sets the 4 bytes at the given offset to a marshaled unsigned
 * integer, replacing anything found there previously.
 *
 * @param str the string to write the marshalled int to
242
 * @param pos the byte offset where int should be written
243 244
 * @param value the value
 * @param byte_order the byte order to use
245
 *
246 247
 */
void
248 249 250 251
_dbus_marshal_set_uint32 (DBusString          *str,
                          int                  pos,
                          dbus_uint32_t        value,
                          int                  byte_order)
252
{
253
  set_4_octets (str, pos, value, byte_order);
254 255 256 257 258 259 260 261 262 263 264 265 266
}

/**
 * Sets the existing marshaled string at the given offset with
 * a new marshaled string. The given offset must point to
 * an existing string or the wrong length will be deleted
 * and replaced with the new string.
 *
 * Note: no attempt is made by this function to re-align
 * any data which has been already marshalled after this
 * string. Use with caution.
 *
 * @param str the string to write the marshalled string to
267
 * @param pos the position of the marshaled string length
268
 * @param value the value
269 270 271 272
 * @param byte_order the byte order to use
 * @param old_end_pos place to store byte after the nul byte of the old value
 * @param new_end_pos place to store byte after the nul byte of the new value
 * @returns #TRUE on success, #FALSE if no memory
273
 *
274
 */
275 276 277 278 279 280 281
static dbus_bool_t
set_string (DBusString          *str,
            int                  pos,
            const char          *value,
            int                  byte_order,
            int                 *old_end_pos,
            int                 *new_end_pos)
282
{
283 284
  int old_len, new_len;
  DBusString dstr;
285

286
  _dbus_string_init_const (&dstr, value);
287

288
  old_len = _dbus_marshal_read_uint32 (str, pos, byte_order, NULL);
289

290 291 292 293
  new_len = _dbus_string_get_length (&dstr);

  if (!_dbus_string_replace_len (&dstr, 0, new_len,
                                 str, pos + 4, old_len))
294 295
    return FALSE;

296 297 298 299 300 301
  _dbus_marshal_set_uint32 (str, pos, new_len, byte_order);

  if (old_end_pos)
    *old_end_pos = pos + 4 + old_len + 1;
  if (new_end_pos)
    *new_end_pos = pos + 4 + new_len + 1;
302 303 304 305

  return TRUE;
}

306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325
/**
 * Sets the existing marshaled signature at the given offset to a new
 * marshaled signature. Same basic ideas as set_string().
 *
 * @param str the string to write the marshalled signature to
 * @param pos the position of the marshaled signature length
 * @param value the value
 * @param byte_order the byte order to use
 * @param old_end_pos place to store byte after the nul byte of the old value
 * @param new_end_pos place to store byte after the nul byte of the new value
 * @returns #TRUE on success, #FALSE if no memory
 *
 */
static dbus_bool_t
set_signature (DBusString          *str,
               int                  pos,
               const char          *value,
               int                  byte_order,
               int                 *old_end_pos,
               int                 *new_end_pos)
326
{
327 328
  int old_len, new_len;
  DBusString dstr;
329

330
  _dbus_string_init_const (&dstr, value);
331

332 333 334 335 336 337 338 339 340 341 342 343 344 345 346
  old_len = _dbus_string_get_byte (str, pos);
  new_len = _dbus_string_get_length (&dstr);

  if (!_dbus_string_replace_len (&dstr, 0, new_len,
                                 str, pos + 1, old_len))
    return FALSE;

  _dbus_string_set_byte (str, pos, new_len);

  if (old_end_pos)
    *old_end_pos = pos + 1 + old_len + 1;
  if (new_end_pos)
    *new_end_pos = pos + 1 + new_len + 1;

  return TRUE;
347 348 349
}

/**
350 351 352 353 354 355 356 357 358 359 360 361 362
 * Sets an existing basic type value to a new value.
 * Arguments work the same way as _dbus_marshal_basic_type().
 *
 * @param str the string
 * @param pos location of the current value
 * @param type the type of the current and new values
 * @param value the address of the new value
 * @param byte_order byte order for marshaling
 * @param old_end_pos location to store end position of the old value, or #NULL
 * @param new_end_pos location to store end position of the new value, or #NULL
 * @returns #FALSE if no memory
 */
dbus_bool_t
363 364 365 366 367 368 369
_dbus_marshal_set_basic (DBusString       *str,
                         int               pos,
                         int               type,
                         const void       *value,
                         int               byte_order,
                         int              *old_end_pos,
                         int              *new_end_pos)
370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387
{
  const DBusBasicValue *vp;

  vp = value;

  switch (type)
    {
    case DBUS_TYPE_BYTE:
    case DBUS_TYPE_BOOLEAN:
      _dbus_string_set_byte (str, pos, vp->byt);
      if (old_end_pos)
        *old_end_pos = pos + 1;
      if (new_end_pos)
        *new_end_pos = pos + 1;
      return TRUE;
      break;
    case DBUS_TYPE_INT32:
    case DBUS_TYPE_UINT32:
388
      pos = _DBUS_ALIGN_VALUE (pos, 4);
389 390 391 392 393 394 395 396 397 398
      set_4_octets (str, pos, vp->u32, byte_order);
      if (old_end_pos)
        *old_end_pos = pos + 4;
      if (new_end_pos)
        *new_end_pos = pos + 4;
      return TRUE;
      break;
    case DBUS_TYPE_INT64:
    case DBUS_TYPE_UINT64:
    case DBUS_TYPE_DOUBLE:
399 400 401
      pos = _DBUS_ALIGN_VALUE (pos, 8);
      set_8_octets (str, pos, *vp, byte_order);
      if (old_end_pos)
402
        *old_end_pos = pos + 8;
403 404 405
      if (new_end_pos)
        *new_end_pos = pos + 8;
      return TRUE;
406 407 408
      break;
    case DBUS_TYPE_STRING:
    case DBUS_TYPE_OBJECT_PATH:
409
      _dbus_assert (vp->str != NULL);
410 411 412 413
      return set_string (str, pos, vp->str, byte_order,
                         old_end_pos, new_end_pos);
      break;
    case DBUS_TYPE_SIGNATURE:
414
      _dbus_assert (vp->str != NULL);
415 416 417 418 419 420 421 422 423 424 425
      return set_signature (str, pos, vp->str, byte_order,
                            old_end_pos, new_end_pos);
      break;
    default:
      _dbus_assert_not_reached ("not a basic type");
      return FALSE;
      break;
    }
}

static dbus_uint32_t
426 427 428 429
read_4_octets (const DBusString *str,
               int               pos,
               int               byte_order,
               int              *new_pos)
430 431 432 433 434 435
{
  pos = _DBUS_ALIGN_VALUE (pos, 4);

  if (new_pos)
    *new_pos = pos + 4;

436 437
  _dbus_assert (pos + 4 <= _dbus_string_get_length (str));
  
438 439 440 441 442 443
  return unpack_4_octets (byte_order,
                          _dbus_string_get_const_data (str) + pos);
}

/**
 * Convenience function to demarshal a 32 bit unsigned integer.
444
 *
445 446 447 448 449
 * @param str the string containing the data
 * @param byte_order the byte order
 * @param pos the position in the string
 * @param new_pos the new position of the string
 * @returns the demarshaled integer.
450
 */
451
dbus_uint32_t
452 453 454 455
_dbus_marshal_read_uint32  (const DBusString *str,
                            int               pos,
                            int               byte_order,
                            int              *new_pos)
456
{
457
  return read_4_octets (str, pos, byte_order, new_pos);
458 459 460
}

/**
461
 * Demarshals a basic-typed value. The "value" pointer is always
462 463 464 465
 * the address of a variable of the basic type. So e.g.
 * if the basic type is "double" then the pointer is
 * a double*, and if it's "char*" then the pointer is
 * a "char**".
466
 *
467 468 469 470 471 472
 * A value of type #DBusBasicValue is guaranteed to be large enough to
 * hold any of the types that may be returned, which is handy if you
 * are trying to do things generically. For example you can pass
 * a DBusBasicValue* in to this function, and then pass the same
 * DBusBasicValue* in to _dbus_marshal_basic_type() in order to
 * move a value from one place to another.
473
 *
474
 * @param str the string containing the data
475
 * @param pos position in the string
476 477 478 479 480 481
 * @param type type of value to demarshal
 * @param value pointer to return value data
 * @param byte_order the byte order
 * @param new_pos pointer to update with new position, or #NULL
 **/
void
482 483 484 485 486 487
_dbus_marshal_read_basic (const DBusString      *str,
                          int                    pos,
                          int                    type,
                          void                  *value,
                          int                    byte_order,
                          int                   *new_pos)
488
{
489
  const char *str_data;
490
  DBusBasicValue *vp;
491

492 493
  _dbus_assert (_dbus_type_is_basic (type));

494
  str_data = _dbus_string_get_const_data (str);
495
  vp = value;
496

497 498 499 500
  switch (type)
    {
    case DBUS_TYPE_BYTE:
    case DBUS_TYPE_BOOLEAN:
501
      vp->byt = _dbus_string_get_byte (str, pos);
502 503 504 505 506
      (pos)++;
      break;
    case DBUS_TYPE_INT32:
    case DBUS_TYPE_UINT32:
      pos = _DBUS_ALIGN_VALUE (pos, 4);
507
      vp->u32 = *(dbus_uint32_t *)(str_data + pos);
508
      if (byte_order != DBUS_COMPILER_BYTE_ORDER)
509
	vp->u32 = DBUS_UINT32_SWAP_LE_BE (vp->u32);
510 511 512 513 514 515 516
      pos += 4;
      break;
    case DBUS_TYPE_INT64:
    case DBUS_TYPE_UINT64:
    case DBUS_TYPE_DOUBLE:
      pos = _DBUS_ALIGN_VALUE (pos, 8);
#ifdef DBUS_HAVE_INT64
517 518 519 520
      if (byte_order != DBUS_COMPILER_BYTE_ORDER)
        vp->u64 = DBUS_UINT64_SWAP_LE_BE (*(dbus_uint64_t*)(str_data + pos));
      else
        vp->u64 = *(dbus_uint64_t*)(str_data + pos);
521
#else
522 523
      vp->u64 = *(DBus8ByteStruct*) (str_data + pos);
      swap_8_octets (vp, byte_order);
524 525 526 527 528 529 530
#endif
      pos += 8;
      break;
    case DBUS_TYPE_STRING:
    case DBUS_TYPE_OBJECT_PATH:
      {
        int len;
531

532
        len = _dbus_marshal_read_uint32 (str, pos, byte_order, &pos);
533

534
        vp->str = (char*) str_data + pos;
535

536 537 538 539 540 541
        pos += len + 1; /* length plus nul */
      }
      break;
    case DBUS_TYPE_SIGNATURE:
      {
        int len;
542

543 544
        len = _dbus_string_get_byte (str, pos);
        pos += 1;
545

546
        vp->str = (char*) str_data + pos;
547

548 549 550 551 552 553 554 555
        pos += len + 1; /* length plus nul */
      }
      break;
    default:
      _dbus_warn ("type %s not a basic type\n",
                  _dbus_type_to_string (type));
      _dbus_assert_not_reached ("not a basic type");
      break;
556 557
    }

558 559
  if (new_pos)
    *new_pos = pos;
560 561
}

562
/**
563 564
 * Reads a block of fixed-length basic values, as an optimization
 * vs. reading each one individually into a new buffer.
565
 *
566
 * This function returns the data in-place; it does not make a copy,
567 568 569 570 571
 * and it does not swap the bytes.
 *
 * If you ask for #DBUS_TYPE_DOUBLE you will get a "const double*" back
 * and the "value" argument should be a "const double**" and so on.
 *
572 573
 * @todo we aren't using this function (except in the test suite)
 * 
574 575 576 577
 * @param str the string to read from
 * @param pos position to read from
 * @param element_type type of array elements
 * @param value place to return the array
578
 * @param n_elements number of array elements to read
579 580 581 582
 * @param byte_order the byte order, used to read the array length
 * @param new_pos #NULL or location to store a position after the elements
 */
void
583
_dbus_marshal_read_fixed_multi  (const DBusString *str,
584 585 586
                                 int               pos,
                                 int               element_type,
                                 void             *value,
587
                                 int               n_elements,
588 589 590
                                 int               byte_order,
                                 int              *new_pos)
{
591
  int array_len;
592 593 594 595 596
  int alignment;

  _dbus_assert (_dbus_type_is_fixed (element_type));
  _dbus_assert (_dbus_type_is_basic (element_type));

597 598 599 600 601
#if 0
  _dbus_verbose ("reading %d elements of %s\n",
                 n_elements, _dbus_type_to_string (element_type));
#endif
  
602 603 604
  alignment = _dbus_type_get_alignment (element_type);

  pos = _DBUS_ALIGN_VALUE (pos, alignment);
605 606
  
  array_len = n_elements * alignment;
607 608 609 610 611 612

  *(const DBusBasicValue**) value = (void*) _dbus_string_get_const_data_len (str, pos, array_len);
  if (new_pos)
    *new_pos = pos + array_len;
}

613 614 615 616 617 618
static dbus_bool_t
marshal_4_octets (DBusString   *str,
                  int           insert_at,
                  dbus_uint32_t value,
                  int           byte_order,
                  int          *pos_after)
619
{
620 621
  dbus_bool_t retval;
  int orig_len;
622

623
  _dbus_assert (sizeof (value) == 4);
624

625 626
  if (byte_order != DBUS_COMPILER_BYTE_ORDER)
    value = DBUS_UINT32_SWAP_LE_BE (value);
627

628
  orig_len = _dbus_string_get_length (str);
629

630 631 632 633 634 635 636
  retval = _dbus_string_insert_4_aligned (str, insert_at,
                                          (const unsigned char *)&value);

  if (pos_after)
    {
      *pos_after = insert_at + (_dbus_string_get_length (str) - orig_len);
      _dbus_assert (*pos_after <= _dbus_string_get_length (str));
637
    }
638 639

  return retval;
640 641
}

642 643 644 645 646 647
static dbus_bool_t
marshal_8_octets (DBusString    *str,
                  int            insert_at,
                  DBusBasicValue value,
                  int            byte_order,
                  int           *pos_after)
648
{
649 650
  dbus_bool_t retval;
  int orig_len;
651

652
  _dbus_assert (sizeof (value) == 8);
653

654
  swap_8_octets (&value, byte_order);
655

656
  orig_len = _dbus_string_get_length (str);
657

658 659
  retval = _dbus_string_insert_8_aligned (str, insert_at,
                                          (const unsigned char *)&value);
660

661 662 663 664
  if (pos_after)
    *pos_after = insert_at + _dbus_string_get_length (str) - orig_len;

  return retval;
665 666
}

667 668 669 670 671 672 673 674 675 676 677 678 679 680 681
enum
  {
    MARSHAL_AS_STRING,
    MARSHAL_AS_SIGNATURE,
    MARSHAL_AS_BYTE_ARRAY
  };

static dbus_bool_t
marshal_len_followed_by_bytes (int                  marshal_as,
                               DBusString          *str,
                               int                  insert_at,
                               const unsigned char *value,
                               int                  data_len, /* doesn't include nul if any */
                               int                  byte_order,
                               int                 *pos_after)
682
{
683 684 685 686 687 688 689 690
  int pos;
  DBusString value_str;
  int value_len;

  _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN || byte_order == DBUS_BIG_ENDIAN);
  if (insert_at > _dbus_string_get_length (str))
    _dbus_warn ("insert_at = %d string len = %d data_len = %d\n",
                insert_at, _dbus_string_get_length (str), data_len);
691
  
692 693 694 695 696 697 698 699 700 701
  if (marshal_as == MARSHAL_AS_BYTE_ARRAY)
    value_len = data_len;
  else
    value_len = data_len + 1; /* value has a nul */

  _dbus_string_init_const_len (&value_str, value, value_len);

  pos = insert_at;

  if (marshal_as == MARSHAL_AS_SIGNATURE)
702
    {
703 704
      if (!_dbus_string_insert_byte (str, pos, data_len))
        goto oom;
705

706
      pos += 1;
707
    }
708
  else
709 710 711 712 713 714 715 716 717 718
    {
      if (!marshal_4_octets (str, pos, data_len,
                             byte_order, &pos))
        goto oom;
    }

  if (!_dbus_string_copy_len (&value_str, 0, value_len,
                              str, pos))
    goto oom;

719
#if 0
720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765
  /* too expensive */
  _dbus_assert (_dbus_string_equal_substring (&value_str, 0, value_len,
                                              str, pos));
  _dbus_verbose_bytes_of_string (str, pos, value_len);
#endif

  pos += value_len;

  if (pos_after)
    *pos_after = pos;

  return TRUE;

 oom:
  /* Delete what we've inserted */
  _dbus_string_delete (str, insert_at, pos - insert_at);

  return FALSE;
}

static dbus_bool_t
marshal_string (DBusString    *str,
                int            insert_at,
                const char    *value,
                int            byte_order,
                int           *pos_after)
{
  return marshal_len_followed_by_bytes (MARSHAL_AS_STRING,
                                        str, insert_at, value,
                                        strlen (value),
                                        byte_order, pos_after);
}

static dbus_bool_t
marshal_signature (DBusString    *str,
                   int            insert_at,
                   const char    *value,
                   int           *pos_after)
{
  return marshal_len_followed_by_bytes (MARSHAL_AS_SIGNATURE,
                                        str, insert_at, value,
                                        strlen (value),
                                        DBUS_COMPILER_BYTE_ORDER, /* irrelevant */
                                        pos_after);
}

766
/**
767
 * Marshals a basic-typed value. The "value" pointer is always the
768 769 770
 * address of a variable containing the basic type value.
 * So for example for int32 it will be dbus_int32_t*, and
 * for string it will be const char**. This is for symmetry
771
 * with _dbus_marshal_read_basic() and to have a simple
772
 * consistent rule.
773 774
 *
 * @param str string to marshal to
775
 * @param insert_at where to insert the value
776
 * @param type type of value
777
 * @param value pointer to a variable containing the value
778
 * @param byte_order byte order
779
 * @param pos_after #NULL or the position after the type
780 781 782
 * @returns #TRUE on success
 **/
dbus_bool_t
783 784 785 786 787 788
_dbus_marshal_write_basic (DBusString *str,
                           int         insert_at,
                           int         type,
                           const void *value,
                           int         byte_order,
                           int        *pos_after)
789
{
790 791
  const DBusBasicValue *vp;

792 793
  _dbus_assert (_dbus_type_is_basic (type));

794
  vp = value;
795

796 797 798 799
  switch (type)
    {
    case DBUS_TYPE_BYTE:
    case DBUS_TYPE_BOOLEAN:
800
      if (!_dbus_string_insert_byte (str, insert_at, vp->byt))
801 802 803 804
        return FALSE;
      if (pos_after)
        *pos_after = insert_at + 1;
      return TRUE;
805 806 807
      break;
    case DBUS_TYPE_INT32:
    case DBUS_TYPE_UINT32:
808
      return marshal_4_octets (str, insert_at, vp->u32,
809
                               byte_order, pos_after);
810 811
      break;
    case DBUS_TYPE_INT64:
812
    case DBUS_TYPE_UINT64:
813
    case DBUS_TYPE_DOUBLE:
814 815 816 817 818
      return marshal_8_octets (str, insert_at, *vp, byte_order, pos_after);
      break;

    case DBUS_TYPE_STRING:
    case DBUS_TYPE_OBJECT_PATH:
819
      _dbus_assert (vp->str != NULL);
820 821 822
      return marshal_string (str, insert_at, vp->str, byte_order, pos_after);
      break;
    case DBUS_TYPE_SIGNATURE:
823
      _dbus_assert (vp->str != NULL);
824 825 826 827 828 829 830 831 832 833 834 835 836
      return marshal_signature (str, insert_at, vp->str, pos_after);
      break;
    default:
      _dbus_assert_not_reached ("not a basic type");
      return FALSE;
      break;
    }
}

static dbus_bool_t
marshal_1_octets_array (DBusString          *str,
                        int                  insert_at,
                        const unsigned char *value,
837
                        int                  n_elements,
838 839 840
                        int                  byte_order,
                        int                 *pos_after)
{
841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857
  int pos;
  DBusString value_str;

  _dbus_string_init_const_len (&value_str, value, n_elements);

  pos = insert_at;

  if (!_dbus_string_copy_len (&value_str, 0, n_elements,
                              str, pos))
    return FALSE;

  pos += n_elements;

  if (pos_after)
    *pos_after = pos;

  return TRUE;
858 859
}

860 861 862 863 864 865
static void
swap_array (DBusString *str,
            int         array_start,
            int         n_elements,
            int         byte_order,
            int         alignment)
866
{
867
  _dbus_assert (_DBUS_ALIGN_VALUE (array_start, alignment) == (unsigned) array_start);
868 869 870

  if (byte_order != DBUS_COMPILER_BYTE_ORDER)
    {
871 872
      unsigned char *d;
      unsigned char *end;
873

874 875 876 877 878 879 880
      /* we use const_data and cast it off so DBusString can be a const string
       * for the unit tests. don't ask.
       */
      d = (unsigned char*) _dbus_string_get_const_data (str) + array_start;
      end = d + n_elements * alignment;

      if (alignment == 8)
881
        {
882 883 884 885 886 887 888 889 890
          while (d != end)
            {
#ifdef DBUS_HAVE_INT64
              *((dbus_uint64_t*)d) = DBUS_UINT64_SWAP_LE_BE (*((dbus_uint64_t*)d));
#else
              swap_8_bytes ((DBusBasicValue*) d);
#endif
              d += 8;
            }
891
        }
892 893 894
      else
        {
          _dbus_assert (alignment == 4);
895

896 897 898 899 900 901 902
          while (d != end)
            {
              *((dbus_uint32_t*)d) = DBUS_UINT32_SWAP_LE_BE (*((dbus_uint32_t*)d));
              d += 4;
            }
        }
    }
903 904 905
}

static dbus_bool_t
906
marshal_fixed_multi (DBusString           *str,
907 908 909 910 911 912
                     int                   insert_at,
                     const DBusBasicValue *value,
                     int                   n_elements,
                     int                   byte_order,
                     int                   alignment,
                     int                  *pos_after)
913 914 915
{
  int old_string_len;
  int array_start;
916
  DBusString t;
917
  int len_in_bytes;
918

919 920
  _dbus_assert (n_elements <= DBUS_MAXIMUM_ARRAY_LENGTH / alignment);
  
921 922
  old_string_len = _dbus_string_get_length (str);

923 924 925
  len_in_bytes = n_elements * alignment;
  array_start = insert_at;
  
926 927 928 929 930 931
  /* Note that we do alignment padding unconditionally
   * even if the array is empty; this means that
   * padding + len is always equal to the number of bytes
   * in the array.
   */

932
  if (!_dbus_string_insert_alignment (str, &array_start, alignment))
933 934
    goto error;

935 936
  _dbus_string_init_const_len (&t,
                               (const unsigned char*) value,
937
                               len_in_bytes);
938

939 940 941
  if (!_dbus_string_copy (&t, 0,
                          str, array_start))
    goto error;
942

943
  swap_array (str, array_start, n_elements, byte_order, alignment);
944

945 946 947
  if (pos_after)
    *pos_after = array_start + len_in_bytes;
  
948 949 950
  return TRUE;

 error:
951 952
  _dbus_string_delete (str, insert_at,
                       _dbus_string_get_length (str) - old_string_len);
953 954 955 956 957

  return FALSE;
}

/**
958 959 960
 * Marshals a block of values of fixed-length type all at once, as an
 * optimization.  _dbus_type_is_fixed() returns #TRUE for fixed-length
 * types, which are the basic types minus the string-like types.
961 962 963
 *
 * The value argument should be the adddress of an
 * array, so e.g. "const dbus_uint32_t**"
964 965 966 967
 *
 * @param str string to marshal to
 * @param insert_at where to insert the value
 * @param element_type type of array elements
968
 * @param value address of an array to marshal
969
 * @param n_elements number of elements in the array
970 971 972 973 974
 * @param byte_order byte order
 * @param pos_after #NULL or the position after the type
 * @returns #TRUE on success
 **/
dbus_bool_t
975
_dbus_marshal_write_fixed_multi (DBusString *str,
976 977 978
                                 int         insert_at,
                                 int         element_type,
                                 const void *value,
979
                                 int         n_elements,
980 981
                                 int         byte_order,
                                 int        *pos_after)
982
{
983
  const void* vp = *(const DBusBasicValue**)value;
984
  
985
  _dbus_assert (_dbus_type_is_fixed (element_type));
986
  _dbus_assert (n_elements >= 0);
987

988 989 990 991 992
#if 0
  _dbus_verbose ("writing %d elements of %s\n",
                 n_elements, _dbus_type_to_string (element_type));
#endif
  
993 994 995 996 997 998
  switch (element_type)
    {
    case DBUS_TYPE_BOOLEAN:
      /* FIXME: we canonicalize to 0 or 1 for the single boolean case
       * should we here too ? */
    case DBUS_TYPE_BYTE:
999
      return marshal_1_octets_array (str, insert_at, vp, n_elements, byte_order, pos_after);
1000 1001 1002
      break;
    case DBUS_TYPE_INT32:
    case DBUS_TYPE_UINT32:
1003
      return marshal_fixed_multi (str, insert_at, vp, n_elements, byte_order, 4, pos_after);
1004 1005 1006 1007
      break;
    case DBUS_TYPE_INT64:
    case DBUS_TYPE_UINT64:
    case DBUS_TYPE_DOUBLE:
1008
      return marshal_fixed_multi (str, insert_at, vp, n_elements, byte_order, 8, pos_after);
1009 1010 1011
      break;

    default:
1012
      _dbus_assert_not_reached ("non fixed type in array write");
1013 1014 1015 1016 1017 1018 1019 1020
      break;
    }

  return FALSE;
}


/**
1021
 * Skips over a basic-typed value, reporting the following position.
1022 1023
 *
 * @param str the string containing the data
1024
 * @param type type of value to read
1025 1026 1027 1028 1029
 * @param byte_order the byte order
 * @param pos pointer to position in the string,
 *            updated on return to new position
 **/
void
1030 1031 1032 1033
_dbus_marshal_skip_basic (const DBusString      *str,
                          int                    type,
                          int                    byte_order,
                          int                   *pos)
1034
{
1035 1036 1037
  _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
                byte_order == DBUS_BIG_ENDIAN);
  
1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059
  switch (type)
    {
    case DBUS_TYPE_BYTE:
    case DBUS_TYPE_BOOLEAN:
      (*pos)++;
      break;
    case DBUS_TYPE_INT32:
    case DBUS_TYPE_UINT32:
      *pos = _DBUS_ALIGN_VALUE (*pos, 4);
      *pos += 4;
      break;
    case DBUS_TYPE_INT64:
    case DBUS_TYPE_UINT64:
    case DBUS_TYPE_DOUBLE:
      *pos = _DBUS_ALIGN_VALUE (*pos, 8);
      *pos += 8;
      break;
    case DBUS_TYPE_STRING:
    case DBUS_TYPE_OBJECT_PATH:
      {
        int len;

1060
        len = _dbus_marshal_read_uint32 (str, *pos, byte_order, pos);
1061
        
1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102
        *pos += len + 1; /* length plus nul */
      }
      break;
    case DBUS_TYPE_SIGNATURE:
      {
        int len;

        len = _dbus_string_get_byte (str, *pos);

        *pos += len + 2; /* length byte plus length plus nul */
      }
      break;
    default:
      _dbus_warn ("type %s not a basic type\n",
                  _dbus_type_to_string (type));
      _dbus_assert_not_reached ("not a basic type");
      break;
    }
}

/**
 * Skips an array, returning the next position.
 *
 * @param str the string containing the data
 * @param element_type the type of array elements
 * @param byte_order the byte order
 * @param pos pointer to position in the string,
 *            updated on return to new position
 */
void
_dbus_marshal_skip_array (const DBusString  *str,
                          int                element_type,
                          int                byte_order,
                          int               *pos)
{
  dbus_uint32_t array_len;
  int i;
  int alignment;

  i = _DBUS_ALIGN_VALUE (*pos, 4);

1103
  array_len = _dbus_marshal_read_uint32 (str, i, byte_order, &i);
1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217

  alignment = _dbus_type_get_alignment (element_type);

  i = _DBUS_ALIGN_VALUE (i, alignment);

  *pos = i + array_len;
}

/**
 * Gets the alignment requirement for the given type;
 * will be 1, 4, or 8.
 *
 * @param typecode the type
 * @returns alignment of 1, 4, or 8
 */
int
_dbus_type_get_alignment (int typecode)
{
  switch (typecode)
    {
    case DBUS_TYPE_BYTE:
    case DBUS_TYPE_BOOLEAN:
    case DBUS_TYPE_VARIANT:
    case DBUS_TYPE_SIGNATURE:
      return 1;
    case DBUS_TYPE_INT32:
    case DBUS_TYPE_UINT32:
      /* this stuff is 4 since it starts with a length */
    case DBUS_TYPE_STRING:
    case DBUS_TYPE_OBJECT_PATH:
    case DBUS_TYPE_ARRAY:
      return 4;
    case DBUS_TYPE_INT64:
    case DBUS_TYPE_UINT64:
    case DBUS_TYPE_DOUBLE:
      /* struct is 8 since it could contain an 8-aligned item
       * and it's simpler to just always align structs to 8;
       * we want the amount of padding in a struct of a given
       * type to be predictable, not location-dependent.
       */
    case DBUS_TYPE_STRUCT:
      return 8;

    default:
      _dbus_assert_not_reached ("unknown typecode in _dbus_type_get_alignment()");
      return 0;
    }
}


/**
 * Return #TRUE if the typecode is a valid typecode.
 * #DBUS_TYPE_INVALID surprisingly enough is not considered valid, and
 * random unknown bytes aren't either. This function is safe with
 * untrusted data.
 *
 * @returns #TRUE if valid
 */
dbus_bool_t
_dbus_type_is_valid (int typecode)
{
  switch (typecode)
    {
    case DBUS_TYPE_BYTE:
    case DBUS_TYPE_BOOLEAN:
    case DBUS_TYPE_INT32:
    case DBUS_TYPE_UINT32:
    case DBUS_TYPE_INT64:
    case DBUS_TYPE_UINT64:
    case DBUS_TYPE_DOUBLE:
    case DBUS_TYPE_STRING:
    case DBUS_TYPE_OBJECT_PATH:
    case DBUS_TYPE_SIGNATURE:
    case DBUS_TYPE_ARRAY:
    case DBUS_TYPE_STRUCT:
    case DBUS_TYPE_VARIANT:
      return TRUE;

    default:
      return FALSE;
    }
}

#define TYPE_IS_CONTAINER(typecode)             \
    ((typecode) == DBUS_TYPE_STRUCT ||          \
     (typecode) == DBUS_TYPE_VARIANT ||         \
     (typecode) == DBUS_TYPE_ARRAY)

/**
 * A "container type" can contain basic types, or nested
 * container types. #DBUS_TYPE_INVALID is not a container type.
 * This function will crash if passed a typecode that isn't
 * in dbus-protocol.h
 *
 * @returns #TRUE if type is a container
 */
dbus_bool_t
_dbus_type_is_container (int typecode)
{
  /* only reasonable (non-line-noise) typecodes are allowed */
  _dbus_assert (_dbus_type_is_valid (typecode) || typecode == DBUS_TYPE_INVALID);
  return TYPE_IS_CONTAINER (typecode);
}

/**
 * A "basic type" is a somewhat arbitrary concept, but the intent
 * is to include those types that are fully-specified by a single
 * typecode, with no additional type information or nested
 * values. So all numbers and strings are basic types and
 * structs, arrays, and variants are not basic types.
 * #DBUS_TYPE_INVALID is not a basic type.
 *
 * This function is defined to return #TRUE for exactly those
 * types that can be written with _dbus_marshal_basic_type()
1218
 * and read with _dbus_marshal_read_basic().
1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240
 *
 * This function will crash if passed a typecode that isn't
 * in dbus-protocol.h
 *
 * @returns #TRUE if type is basic
 */
dbus_bool_t
_dbus_type_is_basic (int typecode)
{
  /* only reasonable (non-line-noise) typecodes are allowed */
  _dbus_assert (_dbus_type_is_valid (typecode) || typecode == DBUS_TYPE_INVALID);

  /* everything that isn't invalid or a container */
  return !(typecode == DBUS_TYPE_INVALID || TYPE_IS_CONTAINER (typecode));
}

/**
 * Tells you whether values of this type can change length if you set
 * them to some other value. For this purpose, you assume that the
 * first byte of the old and new value would be in the same location,
 * so alignment padding is not a factor.
 *
1241
 * @returns #FALSE if the type can occupy different lengths
1242 1243
 */
dbus_bool_t
1244
_dbus_type_is_fixed (int typecode)
1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255
{
  switch (typecode)
    {
    case DBUS_TYPE_BYTE:
    case DBUS_TYPE_BOOLEAN:
    case DBUS_TYPE_INT32:
    case DBUS_TYPE_UINT32:
    case DBUS_TYPE_INT64:
    case DBUS_TYPE_UINT64:
    case DBUS_TYPE_DOUBLE:
      return TRUE;
1256 1257
    default:
      return FALSE;
1258
    }
1259 1260
}

1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304
/**
 * Returns a string describing the given type.
 *
 * @param typecode the type to describe
 * @returns a constant string describing the type
 */
const char *
_dbus_type_to_string (int typecode)
{
  switch (typecode)
    {
    case DBUS_TYPE_INVALID:
      return "invalid";
    case DBUS_TYPE_BOOLEAN:
      return "boolean";
    case DBUS_TYPE_BYTE:
      return "byte";
    case DBUS_TYPE_INT32:
      return "int32";
    case DBUS_TYPE_UINT32:
      return "uint32";
    case DBUS_TYPE_DOUBLE:
      return "double";
    case DBUS_TYPE_STRING:
      return "string";
    case DBUS_TYPE_OBJECT_PATH:
      return "object_path";
    case DBUS_TYPE_SIGNATURE:
      return "signature";
    case DBUS_TYPE_STRUCT:
      return "struct";
    case DBUS_TYPE_ARRAY:
      return "array";
    case DBUS_TYPE_VARIANT:
      return "variant";
    case DBUS_STRUCT_BEGIN_CHAR:
      return "begin_struct";
    case DBUS_STRUCT_END_CHAR:
      return "end_struct";
    default:
      return "unknown";
    }
}

1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317
/**
 * If in verbose mode, print a block of binary data.
 *
 * @todo right now it prints even if not in verbose mode
 *
 * @param data the data
 * @param len the length of the data
 * @param offset where to start counting for byte indexes
 */
void
_dbus_verbose_bytes (const unsigned char *data,
                     int                  len,
                     int                  offset)
1318
{
1319 1320
  int i;
  const unsigned char *aligned;
1321

1322
  _dbus_assert (len >= 0);
1323

1324 1325 1326 1327 1328
  /* Print blanks on first row if appropriate */
  aligned = _DBUS_ALIGN_ADDRESS (data, 4);
  if (aligned > data)
    aligned -= 4;
  _dbus_assert (aligned <= data);
1329

1330
  if (aligned != data)
1331
    {
1332 1333
      _dbus_verbose ("%4d\t%p: ", - (data - aligned), aligned);
      while (aligned != data)
1334
        {
1335 1336
          _dbus_verbose ("    ");
          ++aligned;
1337 1338 1339
        }
    }

1340 1341 1342 1343 1344 1345 1346 1347 1348
  /* now print the bytes */
  i = 0;
  while (i < len)
    {
      if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
        {
          _dbus_verbose ("%4d\t%p: ",
                         offset + i, &data[i]);
        }
1349

1350 1351 1352 1353 1354 1355
      if (data[i] >= 32 &&
          data[i] <= 126)
        _dbus_verbose (" '%c' ", data[i]);
      else
        _dbus_verbose ("0x%s%x ",
                       data[i] <= 0xf ? "0" : "", data[i]);
1356

1357
      ++i;
1358

1359 1360 1361 1362 1363 1364
      if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
        {
          if (i > 3)
            _dbus_verbose ("BE: %d LE: %d",
                           _dbus_unpack_uint32 (DBUS_BIG_ENDIAN, &data[i-4]),
                           _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN, &data[i-4]));
1365

1366 1367 1368
          if (i > 7 &&
              _DBUS_ALIGN_ADDRESS (&data[i], 8) == &data[i])
            {
1369 1370 1371 1372 1373 1374 1375 1376 1377 1378
#ifdef DBUS_HAVE_INT64
              /* I think I probably mean "GNU libc printf" and not "GNUC"
               * but we'll wait until someone complains. If you hit this,
               * just turn off verbose mode as a workaround.
               */
#if __GNUC__
              _dbus_verbose (" u64: 0x%llx",
                             *(dbus_uint64_t*)&data[i-8]);
#endif
#endif
1379 1380 1381
              _dbus_verbose (" dbl: %g",
                             *(double*)&data[i-8]);
            }
1382

1383
          _dbus_verbose ("\n");
1384 1385 1386
        }
    }

1387
  _dbus_verbose ("\n");
1388 1389 1390
}

/**
1391
 * Dump the given part of the string to verbose log.
1392
 *
1393 1394 1395 1396 1397 1398 1399 1400
 * @param str the string
 * @param start the start of range to dump
 * @param len length of range
 */
void
_dbus_verbose_bytes_of_string (const DBusString    *str,
                               int                  start,
                               int                  len)
1401
{
1402 1403
  const char *d;
  int real_len;
1404

1405
  real_len = _dbus_string_get_length (str);
1406

1407
  _dbus_assert (start >= 0);
1408

1409 1410 1411 1412 1413 1414
  if (start > real_len)
    {
      _dbus_verbose ("  [%d,%d) is not inside string of length %d\n",
                     start, len, real_len);
      return;
    }
1415

1416 1417 1418 1419 1420
  if ((start + len) > real_len)
    {
      _dbus_verbose ("  [%d,%d) extends outside string of length %d\n",
                     start, len, real_len);
      len = real_len - start;
1421
    }
1422

1423 1424 1425
  d = _dbus_string_get_const_data_len (str, start, len);

  _dbus_verbose_bytes (d, len, start);
1426 1427 1428 1429 1430 1431 1432 1433
}

/** @} */

#ifdef DBUS_BUILD_TESTS
#include "dbus-test.h"
#include <stdio.h>

1434 1435 1436 1437 1438 1439 1440
static void
swap_test_array (void *array,
                 int   len_bytes,
                 int   byte_order,
                 int   alignment)
{
  DBusString t;
1441 1442 1443 1444

  if (alignment == 1)
    return;
  
1445 1446 1447 1448
  _dbus_string_init_const_len (&t, array, len_bytes);
  swap_array (&t, 0, len_bytes / alignment, byte_order, alignment);
}

1449 1450 1451
#define MARSHAL_BASIC(typename, byte_order, literal)                    \
  do {                                                                  \
     v_##typename = literal;                                            \
1452
     if (!_dbus_marshal_write_basic (&str, pos, DBUS_TYPE_##typename,   \
1453 1454 1455 1456 1457 1458 1459
                                    &v_##typename,                      \
                                    byte_order, NULL))                  \
       _dbus_assert_not_reached ("no memory");                          \
   } while (0)

#define DEMARSHAL_BASIC(typename, byte_order)                                   \
  do {                                                                          \
1460
    _dbus_marshal_read_basic (&str, pos, DBUS_TYPE_##typename, &v_##typename,   \
1461
                              byte_order, &pos);                                \
1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483
  } while (0)

#define DEMARSHAL_BASIC_AND_CHECK(typename, byte_order, literal)                        \
  do {                                                                                  \
    DEMARSHAL_BASIC (typename, byte_order);                                             \
    if (literal != v_##typename)                                                        \
      {                                                                                 \
        _dbus_verbose_bytes_of_string (&str, dump_pos,                                  \
                                     _dbus_string_get_length (&str) - dump_pos);        \
        _dbus_assert_not_reached ("demarshaled wrong value");                           \
      }                                                                                 \
  } while (0)

#define MARSHAL_TEST(typename, byte_order, literal)             \
  do {                                                          \
    MARSHAL_BASIC (typename, byte_order, literal);