dbus-string.c revision c5020ac870c5990a36c3576453cc23431213e8bf
1/* -*- mode: C; c-file-style: "gnu" -*- */ 2/* dbus-string.c String utility class (internal to D-BUS implementation) 3 * 4 * Copyright (C) 2002, 2003 Red Hat, Inc. 5 * 6 * Licensed under the Academic Free License version 1.2 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 * 22 */ 23 24#include "dbus-internals.h" 25#include "dbus-string.h" 26/* we allow a system header here, for speed/convenience */ 27#include <string.h> 28#include "dbus-marshal.h" 29#define DBUS_CAN_USE_DBUS_STRING_PRIVATE 1 30#include "dbus-string-private.h" 31 32/** 33 * @defgroup DBusString string class 34 * @ingroup DBusInternals 35 * @brief DBusString data structure 36 * 37 * Types and functions related to DBusString. DBusString is intended 38 * to be a string class that makes it hard to mess up security issues 39 * (and just in general harder to write buggy code). It should be 40 * used (or extended and then used) rather than the libc stuff in 41 * string.h. The string class is a bit inconvenient at spots because 42 * it handles out-of-memory failures and tries to be extra-robust. 43 * 44 * A DBusString has a maximum length set at initialization time; this 45 * can be used to ensure that a buffer doesn't get too big. The 46 * _dbus_string_lengthen() method checks for overflow, and for max 47 * length being exceeded. 48 * 49 * Try to avoid conversion to a plain C string, i.e. add methods on 50 * the string object instead, only convert to C string when passing 51 * things out to the public API. In particular, no sprintf, strcpy, 52 * strcat, any of that should be used. The GString feature of 53 * accepting negative numbers for "length of string" is also absent, 54 * because it could keep us from detecting bogus huge lengths. i.e. if 55 * we passed in some bogus huge length it would be taken to mean 56 * "current length of string" instead of "broken crack" 57 */ 58 59/** 60 * @defgroup DBusStringInternals DBusString implementation details 61 * @ingroup DBusInternals 62 * @brief DBusString implementation details 63 * 64 * The guts of DBusString. 65 * 66 * @{ 67 */ 68 69/** 70 * We allocate 1 byte for nul termination, plus 7 bytes for possible 71 * align_offset, so we always need 8 bytes on top of the string's 72 * length to be in the allocated block. 73 */ 74#define ALLOCATION_PADDING 8 75 76/** 77 * This is the maximum max length (and thus also the maximum length) 78 * of a DBusString 79 */ 80#define MAX_MAX_LENGTH (_DBUS_INT_MAX - ALLOCATION_PADDING) 81 82/** 83 * Checks a bunch of assertions about a string object 84 * 85 * @param real the DBusRealString 86 */ 87#define DBUS_GENERIC_STRING_PREAMBLE(real) _dbus_assert ((real) != NULL); _dbus_assert (!(real)->invalid); _dbus_assert ((real)->len >= 0); _dbus_assert ((real)->allocated >= 0); _dbus_assert ((real)->max_length >= 0); _dbus_assert ((real)->len <= ((real)->allocated - ALLOCATION_PADDING)); _dbus_assert ((real)->len <= (real)->max_length) 88 89/** 90 * Checks assertions about a string object that needs to be 91 * modifiable - may not be locked or const. Also declares 92 * the "real" variable pointing to DBusRealString. 93 * @param str the string 94 */ 95#define DBUS_STRING_PREAMBLE(str) DBusRealString *real = (DBusRealString*) str; \ 96 DBUS_GENERIC_STRING_PREAMBLE (real); \ 97 _dbus_assert (!(real)->constant); \ 98 _dbus_assert (!(real)->locked) 99 100/** 101 * Checks assertions about a string object that may be locked but 102 * can't be const. i.e. a string object that we can free. Also 103 * declares the "real" variable pointing to DBusRealString. 104 * 105 * @param str the string 106 */ 107#define DBUS_LOCKED_STRING_PREAMBLE(str) DBusRealString *real = (DBusRealString*) str; \ 108 DBUS_GENERIC_STRING_PREAMBLE (real); \ 109 _dbus_assert (!(real)->constant) 110 111/** 112 * Checks assertions about a string that may be const or locked. Also 113 * declares the "real" variable pointing to DBusRealString. 114 * @param str the string. 115 */ 116#define DBUS_CONST_STRING_PREAMBLE(str) const DBusRealString *real = (DBusRealString*) str; \ 117 DBUS_GENERIC_STRING_PREAMBLE (real) 118 119/** @} */ 120 121/** 122 * @addtogroup DBusString 123 * @{ 124 */ 125 126static void 127fixup_alignment (DBusRealString *real) 128{ 129 char *aligned; 130 char *real_block; 131 unsigned int old_align_offset; 132 133 /* we have to have extra space in real->allocated for the align offset and nul byte */ 134 _dbus_assert (real->len <= real->allocated - ALLOCATION_PADDING); 135 136 old_align_offset = real->align_offset; 137 real_block = real->str - old_align_offset; 138 139 aligned = _DBUS_ALIGN_ADDRESS (real_block, 8); 140 141 real->align_offset = aligned - real_block; 142 real->str = aligned; 143 144 if (old_align_offset != real->align_offset) 145 { 146 /* Here comes the suck */ 147 memmove (real_block + real->align_offset, 148 real_block + old_align_offset, 149 real->len + 1); 150 } 151 152 _dbus_assert (real->align_offset < 8); 153 _dbus_assert (_DBUS_ALIGN_ADDRESS (real->str, 8) == real->str); 154} 155 156static void 157undo_alignment (DBusRealString *real) 158{ 159 if (real->align_offset != 0) 160 { 161 memmove (real->str - real->align_offset, 162 real->str, 163 real->len + 1); 164 165 real->str = real->str - real->align_offset; 166 real->align_offset = 0; 167 } 168} 169 170/** 171 * Initializes a string. The string starts life with zero length. The 172 * string must eventually be freed with _dbus_string_free(). 173 * 174 * @param str memory to hold the string 175 * @returns #TRUE on success, #FALSE if no memory 176 */ 177dbus_bool_t 178_dbus_string_init (DBusString *str) 179{ 180 DBusRealString *real; 181 182 _dbus_assert (str != NULL); 183 184 _dbus_assert (sizeof (DBusString) == sizeof (DBusRealString)); 185 186 real = (DBusRealString*) str; 187 188 /* It's very important not to touch anything 189 * other than real->str if we're going to fail, 190 * since we also use this function to reset 191 * an existing string, e.g. in _dbus_string_steal_data() 192 */ 193 194 real->str = dbus_malloc (ALLOCATION_PADDING); 195 if (real->str == NULL) 196 return FALSE; 197 198 real->allocated = ALLOCATION_PADDING; 199 real->len = 0; 200 real->str[real->len] = '\0'; 201 202 real->max_length = MAX_MAX_LENGTH; 203 real->constant = FALSE; 204 real->locked = FALSE; 205 real->invalid = FALSE; 206 real->align_offset = 0; 207 208 fixup_alignment (real); 209 210 return TRUE; 211} 212 213/* The max length thing is sort of a historical artifact 214 * from a feature that turned out to be dumb; perhaps 215 * we should purge it entirely. The problem with 216 * the feature is that it looks like memory allocation 217 * failure, but is not a transient or resolvable failure. 218 */ 219static void 220set_max_length (DBusString *str, 221 int max_length) 222{ 223 DBusRealString *real; 224 225 real = (DBusRealString*) str; 226 227 real->max_length = max_length; 228} 229 230/** 231 * Initializes a constant string. The value parameter is not copied 232 * (should be static), and the string may never be modified. 233 * It is safe but not necessary to call _dbus_string_free() 234 * on a const string. The string has a length limit of MAXINT - 8. 235 * 236 * @param str memory to use for the string 237 * @param value a string to be stored in str (not copied!!!) 238 */ 239void 240_dbus_string_init_const (DBusString *str, 241 const char *value) 242{ 243 _dbus_assert (value != NULL); 244 245 _dbus_string_init_const_len (str, value, 246 strlen (value)); 247} 248 249/** 250 * Initializes a constant string with a length. The value parameter is 251 * not copied (should be static), and the string may never be 252 * modified. It is safe but not necessary to call _dbus_string_free() 253 * on a const string. 254 * 255 * @param str memory to use for the string 256 * @param value a string to be stored in str (not copied!!!) 257 * @param len the length to use 258 */ 259void 260_dbus_string_init_const_len (DBusString *str, 261 const char *value, 262 int len) 263{ 264 DBusRealString *real; 265 266 _dbus_assert (str != NULL); 267 _dbus_assert (value != NULL); 268 _dbus_assert (len <= MAX_MAX_LENGTH); 269 _dbus_assert (len >= 0); 270 271 real = (DBusRealString*) str; 272 273 real->str = (char*) value; 274 real->len = len; 275 real->allocated = real->len + ALLOCATION_PADDING; /* a lie, just to avoid special-case assertions... */ 276 real->max_length = real->len + 1; 277 real->constant = TRUE; 278 real->invalid = FALSE; 279 280 /* We don't require const strings to be 8-byte aligned as the 281 * memory is coming from elsewhere. 282 */ 283} 284 285/** 286 * Frees a string created by _dbus_string_init(). 287 * 288 * @param str memory where the string is stored. 289 */ 290void 291_dbus_string_free (DBusString *str) 292{ 293 DBusRealString *real = (DBusRealString*) str; 294 DBUS_GENERIC_STRING_PREAMBLE (real); 295 296 if (real->constant) 297 return; 298 dbus_free (real->str - real->align_offset); 299 300 real->invalid = TRUE; 301} 302 303/** 304 * Locks a string such that any attempts to change the string will 305 * result in aborting the program. Also, if the string is wasting a 306 * lot of memory (allocation is sufficiently larger than what the 307 * string is really using), _dbus_string_lock() will realloc the 308 * string's data to "compact" it. 309 * 310 * @param str the string to lock. 311 */ 312void 313_dbus_string_lock (DBusString *str) 314{ 315 DBUS_LOCKED_STRING_PREAMBLE (str); /* can lock multiple times */ 316 317 real->locked = TRUE; 318 319 /* Try to realloc to avoid excess memory usage, since 320 * we know we won't change the string further 321 */ 322#define MAX_WASTE 48 323 if (real->allocated - MAX_WASTE > real->len) 324 { 325 char *new_str; 326 int new_allocated; 327 328 new_allocated = real->len + ALLOCATION_PADDING; 329 330 new_str = dbus_realloc (real->str - real->align_offset, 331 new_allocated); 332 if (new_str != NULL) 333 { 334 real->str = new_str + real->align_offset; 335 real->allocated = new_allocated; 336 fixup_alignment (real); 337 } 338 } 339} 340 341static dbus_bool_t 342set_length (DBusRealString *real, 343 int new_length) 344{ 345 /* Note, we are setting the length without nul termination */ 346 347 /* exceeding max length is the same as failure to allocate memory */ 348 if (new_length > real->max_length) 349 return FALSE; 350 351 if (new_length > (real->allocated - ALLOCATION_PADDING)) 352 { 353 int new_allocated; 354 char *new_str; 355 356 /* at least double our old allocation to avoid O(n), avoiding 357 * overflow 358 */ 359 if (real->allocated > (MAX_MAX_LENGTH + ALLOCATION_PADDING) / 2) 360 new_allocated = MAX_MAX_LENGTH + ALLOCATION_PADDING; 361 else 362 new_allocated = real->allocated * 2; 363 364 /* if you change the code just above here, run the tests without 365 * the following before you commit 366 */ 367#ifdef DBUS_BUILD_TESTS 368 new_allocated = 0; /* ensure a realloc every time so that we go 369 * through all malloc failure codepaths 370 */ 371#endif 372 373 /* But be sure we always alloc at least space for the new length */ 374 new_allocated = MAX (new_allocated, new_length + ALLOCATION_PADDING); 375 376 new_str = dbus_realloc (real->str - real->align_offset, new_allocated); 377 if (new_str == NULL) 378 return FALSE; 379 380 real->str = new_str + real->align_offset; 381 real->allocated = new_allocated; 382 fixup_alignment (real); 383 } 384 385 real->len = new_length; 386 real->str[real->len] = '\0'; 387 388 return TRUE; 389} 390 391static dbus_bool_t 392open_gap (int len, 393 DBusRealString *dest, 394 int insert_at) 395{ 396 if (len == 0) 397 return TRUE; 398 399 if (len > dest->max_length - dest->len) 400 return FALSE; /* detected overflow of dest->len + len below */ 401 402 if (!set_length (dest, dest->len + len)) 403 return FALSE; 404 405 memmove (dest->str + insert_at + len, 406 dest->str + insert_at, 407 dest->len - len - insert_at); 408 409 return TRUE; 410} 411 412/** 413 * Gets the raw character buffer from the string. The returned buffer 414 * will be nul-terminated, but note that strings may contain binary 415 * data so there may be extra nul characters prior to the termination. 416 * This function should be little-used, extend DBusString or add 417 * stuff to dbus-sysdeps.c instead. It's an error to use this 418 * function on a const string. 419 * 420 * @param str the string 421 * @returns the data 422 */ 423char* 424_dbus_string_get_data (DBusString *str) 425{ 426 DBUS_STRING_PREAMBLE (str); 427 428 return real->str; 429} 430 431/** 432 * Gets the raw character buffer from a const string. 433 * 434 * @param str the string 435 * @returns the string data 436 */ 437const char* 438_dbus_string_get_const_data (const DBusString *str) 439{ 440 DBUS_CONST_STRING_PREAMBLE (str); 441 442 return real->str; 443} 444 445/** 446 * Gets a sub-portion of the raw character buffer from the 447 * string. The "len" field is required simply for error 448 * checking, to be sure you don't try to use more 449 * string than exists. The nul termination of the 450 * returned buffer remains at the end of the entire 451 * string, not at start + len. 452 * 453 * @param str the string 454 * @param start byte offset to return 455 * @param len length of segment to return 456 * @returns the string data 457 */ 458char* 459_dbus_string_get_data_len (DBusString *str, 460 int start, 461 int len) 462{ 463 DBUS_STRING_PREAMBLE (str); 464 _dbus_assert (start >= 0); 465 _dbus_assert (len >= 0); 466 _dbus_assert (start <= real->len); 467 _dbus_assert (len <= real->len - start); 468 469 return real->str + start; 470} 471 472/** 473 * const version of _dbus_string_get_data_len(). 474 * 475 * @param str the string 476 * @param start byte offset to return 477 * @param len length of segment to return 478 * @returns the string data 479 */ 480const char* 481_dbus_string_get_const_data_len (const DBusString *str, 482 int start, 483 int len) 484{ 485 DBUS_CONST_STRING_PREAMBLE (str); 486 _dbus_assert (start >= 0); 487 _dbus_assert (len >= 0); 488 _dbus_assert (start <= real->len); 489 _dbus_assert (len <= real->len - start); 490 491 return real->str + start; 492} 493 494/** 495 * Sets the value of the byte at the given position. 496 * 497 * @param str the string 498 * @param i the position 499 * @param byte the new value 500 */ 501void 502_dbus_string_set_byte (DBusString *str, 503 int i, 504 unsigned char byte) 505{ 506 DBUS_STRING_PREAMBLE (str); 507 _dbus_assert (i < real->len); 508 _dbus_assert (i >= 0); 509 510 real->str[i] = byte; 511} 512 513/** 514 * Gets the byte at the given position. 515 * 516 * @param str the string 517 * @param start the position 518 * @returns the byte at that position 519 */ 520unsigned char 521_dbus_string_get_byte (const DBusString *str, 522 int start) 523{ 524 DBUS_CONST_STRING_PREAMBLE (str); 525 _dbus_assert (start < real->len); 526 _dbus_assert (start >= 0); 527 528 return real->str[start]; 529} 530 531/** 532 * Inserts the given byte at the given position. 533 * 534 * @param str the string 535 * @param i the position 536 * @param byte the value to insert 537 * @returns #TRUE on success 538 */ 539dbus_bool_t 540_dbus_string_insert_byte (DBusString *str, 541 int i, 542 unsigned char byte) 543{ 544 DBUS_STRING_PREAMBLE (str); 545 _dbus_assert (i <= real->len); 546 _dbus_assert (i >= 0); 547 548 if (!open_gap (1, real, i)) 549 return FALSE; 550 551 real->str[i] = byte; 552 553 return TRUE; 554} 555 556/** 557 * Like _dbus_string_get_data(), but removes the 558 * gotten data from the original string. The caller 559 * must free the data returned. This function may 560 * fail due to lack of memory, and return #FALSE. 561 * 562 * @param str the string 563 * @param data_return location to return the buffer 564 * @returns #TRUE on success 565 */ 566dbus_bool_t 567_dbus_string_steal_data (DBusString *str, 568 char **data_return) 569{ 570 int old_max_length; 571 DBUS_STRING_PREAMBLE (str); 572 _dbus_assert (data_return != NULL); 573 574 undo_alignment (real); 575 576 *data_return = real->str; 577 578 old_max_length = real->max_length; 579 580 /* reset the string */ 581 if (!_dbus_string_init (str)) 582 { 583 /* hrm, put it back then */ 584 real->str = *data_return; 585 *data_return = NULL; 586 fixup_alignment (real); 587 return FALSE; 588 } 589 590 real->max_length = old_max_length; 591 592 return TRUE; 593} 594 595/** 596 * Like _dbus_string_get_data_len(), but removes the gotten data from 597 * the original string. The caller must free the data returned. This 598 * function may fail due to lack of memory, and return #FALSE. 599 * The returned string is nul-terminated and has length len. 600 * 601 * @todo this function is broken because on failure it 602 * may corrupt the source string. 603 * 604 * @param str the string 605 * @param data_return location to return the buffer 606 * @param start the start of segment to steal 607 * @param len the length of segment to steal 608 * @returns #TRUE on success 609 */ 610dbus_bool_t 611_dbus_string_steal_data_len (DBusString *str, 612 char **data_return, 613 int start, 614 int len) 615{ 616 DBusString dest; 617 DBUS_STRING_PREAMBLE (str); 618 _dbus_assert (data_return != NULL); 619 _dbus_assert (start >= 0); 620 _dbus_assert (len >= 0); 621 _dbus_assert (start <= real->len); 622 _dbus_assert (len <= real->len - start); 623 624 if (!_dbus_string_init (&dest)) 625 return FALSE; 626 627 set_max_length (&dest, real->max_length); 628 629 if (!_dbus_string_move_len (str, start, len, &dest, 0)) 630 { 631 _dbus_string_free (&dest); 632 return FALSE; 633 } 634 635 _dbus_warn ("Broken code in _dbus_string_steal_data_len(), see @todo, FIXME\n"); 636 if (!_dbus_string_steal_data (&dest, data_return)) 637 { 638 _dbus_string_free (&dest); 639 return FALSE; 640 } 641 642 _dbus_string_free (&dest); 643 return TRUE; 644} 645 646 647/** 648 * Copies the data from the string into a char* 649 * 650 * @param str the string 651 * @param data_return place to return the data 652 * @returns #TRUE on success, #FALSE on no memory 653 */ 654dbus_bool_t 655_dbus_string_copy_data (const DBusString *str, 656 char **data_return) 657{ 658 DBUS_CONST_STRING_PREAMBLE (str); 659 _dbus_assert (data_return != NULL); 660 661 *data_return = dbus_malloc (real->len + 1); 662 if (*data_return == NULL) 663 return FALSE; 664 665 memcpy (*data_return, real->str, real->len + 1); 666 667 return TRUE; 668} 669 670/** 671 * Copies a segment of the string into a char* 672 * 673 * @param str the string 674 * @param data_return place to return the data 675 * @param start start index 676 * @param len length to copy 677 * @returns #FALSE if no memory 678 */ 679dbus_bool_t 680_dbus_string_copy_data_len (const DBusString *str, 681 char **data_return, 682 int start, 683 int len) 684{ 685 DBusString dest; 686 687 DBUS_CONST_STRING_PREAMBLE (str); 688 _dbus_assert (data_return != NULL); 689 _dbus_assert (start >= 0); 690 _dbus_assert (len >= 0); 691 _dbus_assert (start <= real->len); 692 _dbus_assert (len <= real->len - start); 693 694 if (!_dbus_string_init (&dest)) 695 return FALSE; 696 697 set_max_length (&dest, real->max_length); 698 699 if (!_dbus_string_copy_len (str, start, len, &dest, 0)) 700 { 701 _dbus_string_free (&dest); 702 return FALSE; 703 } 704 705 if (!_dbus_string_steal_data (&dest, data_return)) 706 { 707 _dbus_string_free (&dest); 708 return FALSE; 709 } 710 711 _dbus_string_free (&dest); 712 return TRUE; 713} 714 715/** 716 * Gets the length of a string (not including nul termination). 717 * 718 * @returns the length. 719 */ 720int 721_dbus_string_get_length (const DBusString *str) 722{ 723 DBUS_CONST_STRING_PREAMBLE (str); 724 725 return real->len; 726} 727 728/** 729 * Makes a string longer by the given number of bytes. Checks whether 730 * adding additional_length to the current length would overflow an 731 * integer, and checks for exceeding a string's max length. 732 * The new bytes are not initialized, other than nul-terminating 733 * the end of the string. The uninitialized bytes may contain 734 * nul bytes or other junk. 735 * 736 * @param str a string 737 * @param additional_length length to add to the string. 738 * @returns #TRUE on success. 739 */ 740dbus_bool_t 741_dbus_string_lengthen (DBusString *str, 742 int additional_length) 743{ 744 DBUS_STRING_PREAMBLE (str); 745 _dbus_assert (additional_length >= 0); 746 747 if (additional_length > real->max_length - real->len) 748 return FALSE; /* would overflow */ 749 750 return set_length (real, 751 real->len + additional_length); 752} 753 754/** 755 * Makes a string shorter by the given number of bytes. 756 * 757 * @param str a string 758 * @param length_to_remove length to remove from the string. 759 */ 760void 761_dbus_string_shorten (DBusString *str, 762 int length_to_remove) 763{ 764 DBUS_STRING_PREAMBLE (str); 765 _dbus_assert (length_to_remove >= 0); 766 _dbus_assert (length_to_remove <= real->len); 767 768 set_length (real, 769 real->len - length_to_remove); 770} 771 772/** 773 * Sets the length of a string. Can be used to truncate or lengthen 774 * the string. If the string is lengthened, the function may fail and 775 * return #FALSE. Newly-added bytes are not initialized, as with 776 * _dbus_string_lengthen(). 777 * 778 * @param str a string 779 * @param length new length of the string. 780 * @returns #FALSE on failure. 781 */ 782dbus_bool_t 783_dbus_string_set_length (DBusString *str, 784 int length) 785{ 786 DBUS_STRING_PREAMBLE (str); 787 _dbus_assert (length >= 0); 788 789 return set_length (real, length); 790} 791 792/** 793 * Align the length of a string to a specific alignment (typically 4 or 8) 794 * by appending nul bytes to the string. 795 * 796 * @param str a string 797 * @param alignment the alignment 798 * @returns #FALSE if no memory 799 */ 800dbus_bool_t 801_dbus_string_align_length (DBusString *str, 802 int alignment) 803{ 804 unsigned long new_len; /* ulong to avoid _DBUS_ALIGN_VALUE overflow */ 805 int delta; 806 DBUS_STRING_PREAMBLE (str); 807 _dbus_assert (alignment >= 1); 808 _dbus_assert (alignment <= 8); /* it has to be a bug if > 8 */ 809 810 new_len = _DBUS_ALIGN_VALUE (real->len, alignment); 811 if (new_len > (unsigned long) real->max_length) 812 return FALSE; 813 814 delta = new_len - real->len; 815 _dbus_assert (delta >= 0); 816 817 if (delta == 0) 818 return TRUE; 819 820 if (!set_length (real, new_len)) 821 return FALSE; 822 823 memset (real->str + (new_len - delta), 824 '\0', delta); 825 826 return TRUE; 827} 828 829static dbus_bool_t 830append (DBusRealString *real, 831 const char *buffer, 832 int buffer_len) 833{ 834 if (buffer_len == 0) 835 return TRUE; 836 837 if (!_dbus_string_lengthen ((DBusString*)real, buffer_len)) 838 return FALSE; 839 840 memcpy (real->str + (real->len - buffer_len), 841 buffer, 842 buffer_len); 843 844 return TRUE; 845} 846 847/** 848 * Appends a nul-terminated C-style string to a DBusString. 849 * 850 * @param str the DBusString 851 * @param buffer the nul-terminated characters to append 852 * @returns #FALSE if not enough memory. 853 */ 854dbus_bool_t 855_dbus_string_append (DBusString *str, 856 const char *buffer) 857{ 858 unsigned long buffer_len; 859 860 DBUS_STRING_PREAMBLE (str); 861 _dbus_assert (buffer != NULL); 862 863 buffer_len = strlen (buffer); 864 if (buffer_len > (unsigned long) real->max_length) 865 return FALSE; 866 867 return append (real, buffer, buffer_len); 868} 869 870/** 871 * Appends block of bytes with the given length to a DBusString. 872 * 873 * @param str the DBusString 874 * @param buffer the bytes to append 875 * @param len the number of bytes to append 876 * @returns #FALSE if not enough memory. 877 */ 878dbus_bool_t 879_dbus_string_append_len (DBusString *str, 880 const char *buffer, 881 int len) 882{ 883 DBUS_STRING_PREAMBLE (str); 884 _dbus_assert (buffer != NULL); 885 _dbus_assert (len >= 0); 886 887 return append (real, buffer, len); 888} 889 890/** 891 * Appends a single byte to the string, returning #FALSE 892 * if not enough memory. 893 * 894 * @param str the string 895 * @param byte the byte to append 896 * @returns #TRUE on success 897 */ 898dbus_bool_t 899_dbus_string_append_byte (DBusString *str, 900 unsigned char byte) 901{ 902 DBUS_STRING_PREAMBLE (str); 903 904 if (!set_length (real, real->len + 1)) 905 return FALSE; 906 907 real->str[real->len-1] = byte; 908 909 return TRUE; 910} 911 912/** 913 * Appends a single Unicode character, encoding the character 914 * in UTF-8 format. 915 * 916 * @param str the string 917 * @param ch the Unicode character 918 */ 919dbus_bool_t 920_dbus_string_append_unichar (DBusString *str, 921 dbus_unichar_t ch) 922{ 923 int len; 924 int first; 925 int i; 926 char *out; 927 928 DBUS_STRING_PREAMBLE (str); 929 930 /* this code is from GLib but is pretty standard I think */ 931 932 len = 0; 933 934 if (ch < 0x80) 935 { 936 first = 0; 937 len = 1; 938 } 939 else if (ch < 0x800) 940 { 941 first = 0xc0; 942 len = 2; 943 } 944 else if (ch < 0x10000) 945 { 946 first = 0xe0; 947 len = 3; 948 } 949 else if (ch < 0x200000) 950 { 951 first = 0xf0; 952 len = 4; 953 } 954 else if (ch < 0x4000000) 955 { 956 first = 0xf8; 957 len = 5; 958 } 959 else 960 { 961 first = 0xfc; 962 len = 6; 963 } 964 965 if (len > (real->max_length - real->len)) 966 return FALSE; /* real->len + len would overflow */ 967 968 if (!set_length (real, real->len + len)) 969 return FALSE; 970 971 out = real->str + (real->len - len); 972 973 for (i = len - 1; i > 0; --i) 974 { 975 out[i] = (ch & 0x3f) | 0x80; 976 ch >>= 6; 977 } 978 out[0] = ch | first; 979 980 return TRUE; 981} 982 983static void 984delete (DBusRealString *real, 985 int start, 986 int len) 987{ 988 if (len == 0) 989 return; 990 991 memmove (real->str + start, real->str + start + len, real->len - (start + len)); 992 real->len -= len; 993 real->str[real->len] = '\0'; 994} 995 996/** 997 * Deletes a segment of a DBusString with length len starting at 998 * start. (Hint: to clear an entire string, setting length to 0 999 * with _dbus_string_set_length() is easier.) 1000 * 1001 * @param str the DBusString 1002 * @param start where to start deleting 1003 * @param len the number of bytes to delete 1004 */ 1005void 1006_dbus_string_delete (DBusString *str, 1007 int start, 1008 int len) 1009{ 1010 DBUS_STRING_PREAMBLE (str); 1011 _dbus_assert (start >= 0); 1012 _dbus_assert (len >= 0); 1013 _dbus_assert (start <= real->len); 1014 _dbus_assert (len <= real->len - start); 1015 1016 delete (real, start, len); 1017} 1018 1019static dbus_bool_t 1020copy (DBusRealString *source, 1021 int start, 1022 int len, 1023 DBusRealString *dest, 1024 int insert_at) 1025{ 1026 if (len == 0) 1027 return TRUE; 1028 1029 if (!open_gap (len, dest, insert_at)) 1030 return FALSE; 1031 1032 memcpy (dest->str + insert_at, 1033 source->str + start, 1034 len); 1035 1036 return TRUE; 1037} 1038 1039/** 1040 * Checks assertions for two strings we're copying a segment between, 1041 * and declares real_source/real_dest variables. 1042 * 1043 * @param source the source string 1044 * @param start the starting offset 1045 * @param dest the dest string 1046 * @param insert_at where the copied segment is inserted 1047 */ 1048#define DBUS_STRING_COPY_PREAMBLE(source, start, dest, insert_at) \ 1049 DBusRealString *real_source = (DBusRealString*) source; \ 1050 DBusRealString *real_dest = (DBusRealString*) dest; \ 1051 _dbus_assert ((source) != (dest)); \ 1052 DBUS_GENERIC_STRING_PREAMBLE (real_source); \ 1053 DBUS_GENERIC_STRING_PREAMBLE (real_dest); \ 1054 _dbus_assert (!real_dest->constant); \ 1055 _dbus_assert (!real_dest->locked); \ 1056 _dbus_assert ((start) >= 0); \ 1057 _dbus_assert ((start) <= real_source->len); \ 1058 _dbus_assert ((insert_at) >= 0); \ 1059 _dbus_assert ((insert_at) <= real_dest->len) 1060 1061/** 1062 * Moves the end of one string into another string. Both strings 1063 * must be initialized, valid strings. 1064 * 1065 * @param source the source string 1066 * @param start where to chop off the source string 1067 * @param dest the destination string 1068 * @param insert_at where to move the chopped-off part of source string 1069 * @returns #FALSE if not enough memory 1070 */ 1071dbus_bool_t 1072_dbus_string_move (DBusString *source, 1073 int start, 1074 DBusString *dest, 1075 int insert_at) 1076{ 1077 DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at); 1078 1079 if (!copy (real_source, start, 1080 real_source->len - start, 1081 real_dest, 1082 insert_at)) 1083 return FALSE; 1084 1085 delete (real_source, start, 1086 real_source->len - start); 1087 1088 return TRUE; 1089} 1090 1091/** 1092 * Like _dbus_string_move(), but does not delete the section 1093 * of the source string that's copied to the dest string. 1094 * 1095 * @param source the source string 1096 * @param start where to start copying the source string 1097 * @param dest the destination string 1098 * @param insert_at where to place the copied part of source string 1099 * @returns #FALSE if not enough memory 1100 */ 1101dbus_bool_t 1102_dbus_string_copy (const DBusString *source, 1103 int start, 1104 DBusString *dest, 1105 int insert_at) 1106{ 1107 DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at); 1108 1109 return copy (real_source, start, 1110 real_source->len - start, 1111 real_dest, 1112 insert_at); 1113} 1114 1115/** 1116 * Like _dbus_string_move(), but can move a segment from 1117 * the middle of the source string. 1118 * 1119 * @param source the source string 1120 * @param start first byte of source string to move 1121 * @param len length of segment to move 1122 * @param dest the destination string 1123 * @param insert_at where to move the bytes from the source string 1124 * @returns #FALSE if not enough memory 1125 */ 1126dbus_bool_t 1127_dbus_string_move_len (DBusString *source, 1128 int start, 1129 int len, 1130 DBusString *dest, 1131 int insert_at) 1132 1133{ 1134 DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at); 1135 _dbus_assert (len >= 0); 1136 _dbus_assert ((start + len) <= real_source->len); 1137 1138 if (!copy (real_source, start, len, 1139 real_dest, 1140 insert_at)) 1141 return FALSE; 1142 1143 delete (real_source, start, 1144 len); 1145 1146 return TRUE; 1147} 1148 1149/** 1150 * Like _dbus_string_copy(), but can copy a segment from the middle of 1151 * the source string. 1152 * 1153 * @param source the source string 1154 * @param start where to start copying the source string 1155 * @param len length of segment to copy 1156 * @param dest the destination string 1157 * @param insert_at where to place the copied segment of source string 1158 * @returns #FALSE if not enough memory 1159 */ 1160dbus_bool_t 1161_dbus_string_copy_len (const DBusString *source, 1162 int start, 1163 int len, 1164 DBusString *dest, 1165 int insert_at) 1166{ 1167 DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at); 1168 _dbus_assert (len >= 0); 1169 _dbus_assert (start <= real_source->len); 1170 _dbus_assert (len <= real_source->len - start); 1171 1172 return copy (real_source, start, len, 1173 real_dest, 1174 insert_at); 1175} 1176 1177/** 1178 * Replaces a segment of dest string with a segment of source string. 1179 * 1180 * @todo optimize the case where the two lengths are the same, and 1181 * avoid memmoving the data in the trailing part of the string twice. 1182 * 1183 * @todo avoid inserting the source into dest, then deleting 1184 * the replaced chunk of dest (which creates a potentially large 1185 * intermediate string). Instead, extend the replaced chunk 1186 * of dest with padding to the same size as the source chunk, 1187 * then copy in the source bytes. 1188 * 1189 * @param source the source string 1190 * @param start where to start copying the source string 1191 * @param len length of segment to copy 1192 * @param dest the destination string 1193 * @param replace_at start of segment of dest string to replace 1194 * @param replace_len length of segment of dest string to replace 1195 * @returns #FALSE if not enough memory 1196 * 1197 */ 1198dbus_bool_t 1199_dbus_string_replace_len (const DBusString *source, 1200 int start, 1201 int len, 1202 DBusString *dest, 1203 int replace_at, 1204 int replace_len) 1205{ 1206 DBUS_STRING_COPY_PREAMBLE (source, start, dest, replace_at); 1207 _dbus_assert (len >= 0); 1208 _dbus_assert (start <= real_source->len); 1209 _dbus_assert (len <= real_source->len - start); 1210 _dbus_assert (replace_at >= 0); 1211 _dbus_assert (replace_at <= real_dest->len); 1212 _dbus_assert (replace_len <= real_dest->len - replace_at); 1213 1214 if (!copy (real_source, start, len, 1215 real_dest, replace_at)) 1216 return FALSE; 1217 1218 delete (real_dest, replace_at + len, replace_len); 1219 1220 return TRUE; 1221} 1222 1223/* Unicode macros and utf8_validate() from GLib Owen Taylor, Havoc 1224 * Pennington, and Tom Tromey are the authors and authorized relicense. 1225 */ 1226 1227/** computes length and mask of a unicode character 1228 * @param Char the char 1229 * @param Mask the mask variable to assign to 1230 * @param Len the length variable to assign to 1231 */ 1232#define UTF8_COMPUTE(Char, Mask, Len) \ 1233 if (Char < 128) \ 1234 { \ 1235 Len = 1; \ 1236 Mask = 0x7f; \ 1237 } \ 1238 else if ((Char & 0xe0) == 0xc0) \ 1239 { \ 1240 Len = 2; \ 1241 Mask = 0x1f; \ 1242 } \ 1243 else if ((Char & 0xf0) == 0xe0) \ 1244 { \ 1245 Len = 3; \ 1246 Mask = 0x0f; \ 1247 } \ 1248 else if ((Char & 0xf8) == 0xf0) \ 1249 { \ 1250 Len = 4; \ 1251 Mask = 0x07; \ 1252 } \ 1253 else if ((Char & 0xfc) == 0xf8) \ 1254 { \ 1255 Len = 5; \ 1256 Mask = 0x03; \ 1257 } \ 1258 else if ((Char & 0xfe) == 0xfc) \ 1259 { \ 1260 Len = 6; \ 1261 Mask = 0x01; \ 1262 } \ 1263 else \ 1264 Len = -1; 1265 1266/** 1267 * computes length of a unicode character in UTF-8 1268 * @param Char the char 1269 */ 1270#define UTF8_LENGTH(Char) \ 1271 ((Char) < 0x80 ? 1 : \ 1272 ((Char) < 0x800 ? 2 : \ 1273 ((Char) < 0x10000 ? 3 : \ 1274 ((Char) < 0x200000 ? 4 : \ 1275 ((Char) < 0x4000000 ? 5 : 6))))) 1276 1277/** 1278 * Gets a UTF-8 value. 1279 * 1280 * @param Result variable for extracted unicode char. 1281 * @param Chars the bytes to decode 1282 * @param Count counter variable 1283 * @param Mask mask for this char 1284 * @param Len length for this char in bytes 1285 */ 1286#define UTF8_GET(Result, Chars, Count, Mask, Len) \ 1287 (Result) = (Chars)[0] & (Mask); \ 1288 for ((Count) = 1; (Count) < (Len); ++(Count)) \ 1289 { \ 1290 if (((Chars)[(Count)] & 0xc0) != 0x80) \ 1291 { \ 1292 (Result) = -1; \ 1293 break; \ 1294 } \ 1295 (Result) <<= 6; \ 1296 (Result) |= ((Chars)[(Count)] & 0x3f); \ 1297 } 1298 1299/** 1300 * Check whether a unicode char is in a valid range. 1301 * 1302 * @param Char the character 1303 */ 1304#define UNICODE_VALID(Char) \ 1305 ((Char) < 0x110000 && \ 1306 (((Char) & 0xFFFFF800) != 0xD800) && \ 1307 ((Char) < 0xFDD0 || (Char) > 0xFDEF) && \ 1308 ((Char) & 0xFFFF) != 0xFFFF) 1309 1310/** 1311 * Gets a unicode character from a UTF-8 string. Does no validation; 1312 * you must verify that the string is valid UTF-8 in advance and must 1313 * pass in the start of a character. 1314 * 1315 * @param str the string 1316 * @param start the start of the UTF-8 character. 1317 * @param ch_return location to return the character 1318 * @param end_return location to return the byte index of next character 1319 */ 1320void 1321_dbus_string_get_unichar (const DBusString *str, 1322 int start, 1323 dbus_unichar_t *ch_return, 1324 int *end_return) 1325{ 1326 int i, mask, len; 1327 dbus_unichar_t result; 1328 unsigned char c; 1329 unsigned char *p; 1330 DBUS_CONST_STRING_PREAMBLE (str); 1331 _dbus_assert (start >= 0); 1332 _dbus_assert (start <= real->len); 1333 1334 if (ch_return) 1335 *ch_return = 0; 1336 if (end_return) 1337 *end_return = real->len; 1338 1339 mask = 0; 1340 p = real->str + start; 1341 c = *p; 1342 1343 UTF8_COMPUTE (c, mask, len); 1344 if (len == -1) 1345 return; 1346 UTF8_GET (result, p, i, mask, len); 1347 1348 if (result == (dbus_unichar_t)-1) 1349 return; 1350 1351 if (ch_return) 1352 *ch_return = result; 1353 if (end_return) 1354 *end_return = start + len; 1355} 1356 1357/** 1358 * Finds the given substring in the string, 1359 * returning #TRUE and filling in the byte index 1360 * where the substring was found, if it was found. 1361 * Returns #FALSE if the substring wasn't found. 1362 * Sets *start to the length of the string if the substring 1363 * is not found. 1364 * 1365 * @param str the string 1366 * @param start where to start looking 1367 * @param substr the substring 1368 * @param found return location for where it was found, or #NULL 1369 * @returns #TRUE if found 1370 */ 1371dbus_bool_t 1372_dbus_string_find (const DBusString *str, 1373 int start, 1374 const char *substr, 1375 int *found) 1376{ 1377 return _dbus_string_find_to (str, start, 1378 ((const DBusRealString*)str)->len, 1379 substr, found); 1380} 1381 1382/** 1383 * Finds the given substring in the string, 1384 * up to a certain position, 1385 * returning #TRUE and filling in the byte index 1386 * where the substring was found, if it was found. 1387 * Returns #FALSE if the substring wasn't found. 1388 * Sets *start to the length of the string if the substring 1389 * is not found. 1390 * 1391 * @param str the string 1392 * @param start where to start looking 1393 * @param end where to stop looking 1394 * @param substr the substring 1395 * @param found return location for where it was found, or #NULL 1396 * @returns #TRUE if found 1397 */ 1398dbus_bool_t 1399_dbus_string_find_to (const DBusString *str, 1400 int start, 1401 int end, 1402 const char *substr, 1403 int *found) 1404{ 1405 int i; 1406 DBUS_CONST_STRING_PREAMBLE (str); 1407 _dbus_assert (substr != NULL); 1408 _dbus_assert (start <= real->len); 1409 _dbus_assert (start >= 0); 1410 _dbus_assert (substr != NULL); 1411 _dbus_assert (end <= real->len); 1412 _dbus_assert (start <= end); 1413 1414 /* we always "find" an empty string */ 1415 if (*substr == '\0') 1416 { 1417 if (found) 1418 *found = start; 1419 return TRUE; 1420 } 1421 1422 i = start; 1423 while (i < end) 1424 { 1425 if (real->str[i] == substr[0]) 1426 { 1427 int j = i + 1; 1428 1429 while (j < end) 1430 { 1431 if (substr[j - i] == '\0') 1432 break; 1433 else if (real->str[j] != substr[j - i]) 1434 break; 1435 1436 ++j; 1437 } 1438 1439 if (substr[j - i] == '\0') 1440 { 1441 if (found) 1442 *found = i; 1443 return TRUE; 1444 } 1445 } 1446 1447 ++i; 1448 } 1449 1450 if (found) 1451 *found = end; 1452 1453 return FALSE; 1454} 1455 1456/** 1457 * Find the given byte scanning backward from the given start. 1458 * Sets *found to -1 if the byte is not found. 1459 * 1460 * @param str the string 1461 * @param start the place to start scanning (will not find the byte at this point) 1462 * @param byte the byte to find 1463 * @param found return location for where it was found 1464 * @returns #TRUE if found 1465 */ 1466dbus_bool_t 1467_dbus_string_find_byte_backward (const DBusString *str, 1468 int start, 1469 unsigned char byte, 1470 int *found) 1471{ 1472 int i; 1473 DBUS_CONST_STRING_PREAMBLE (str); 1474 _dbus_assert (start <= real->len); 1475 _dbus_assert (start >= 0); 1476 _dbus_assert (found != NULL); 1477 1478 i = start - 1; 1479 while (i >= 0) 1480 { 1481 if (real->str[i] == byte) 1482 break; 1483 1484 --i; 1485 } 1486 1487 if (found) 1488 *found = i; 1489 1490 return i >= 0; 1491} 1492 1493/** 1494 * Finds a blank (space or tab) in the string. Returns #TRUE 1495 * if found, #FALSE otherwise. If a blank is not found sets 1496 * *found to the length of the string. 1497 * 1498 * @param str the string 1499 * @param start byte index to start looking 1500 * @param found place to store the location of the first blank 1501 * @returns #TRUE if a blank was found 1502 */ 1503dbus_bool_t 1504_dbus_string_find_blank (const DBusString *str, 1505 int start, 1506 int *found) 1507{ 1508 int i; 1509 DBUS_CONST_STRING_PREAMBLE (str); 1510 _dbus_assert (start <= real->len); 1511 _dbus_assert (start >= 0); 1512 1513 i = start; 1514 while (i < real->len) 1515 { 1516 if (real->str[i] == ' ' || 1517 real->str[i] == '\t') 1518 { 1519 if (found) 1520 *found = i; 1521 return TRUE; 1522 } 1523 1524 ++i; 1525 } 1526 1527 if (found) 1528 *found = real->len; 1529 1530 return FALSE; 1531} 1532 1533/** 1534 * Skips blanks from start, storing the first non-blank in *end 1535 * (blank is space or tab). 1536 * 1537 * @param str the string 1538 * @param start where to start 1539 * @param end where to store the first non-blank byte index 1540 */ 1541void 1542_dbus_string_skip_blank (const DBusString *str, 1543 int start, 1544 int *end) 1545{ 1546 int i; 1547 DBUS_CONST_STRING_PREAMBLE (str); 1548 _dbus_assert (start <= real->len); 1549 _dbus_assert (start >= 0); 1550 1551 i = start; 1552 while (i < real->len) 1553 { 1554 if (!(real->str[i] == ' ' || 1555 real->str[i] == '\t')) 1556 break; 1557 1558 ++i; 1559 } 1560 1561 _dbus_assert (i == real->len || !(real->str[i] == ' ' || 1562 real->str[i] == '\t')); 1563 1564 if (end) 1565 *end = i; 1566} 1567 1568/** 1569 * Skips whitespace from start, storing the first non-whitespace in *end. 1570 * (whitespace is space, tab, newline, CR). 1571 * 1572 * @param str the string 1573 * @param start where to start 1574 * @param end where to store the first non-whitespace byte index 1575 */ 1576void 1577_dbus_string_skip_white (const DBusString *str, 1578 int start, 1579 int *end) 1580{ 1581 int i; 1582 DBUS_CONST_STRING_PREAMBLE (str); 1583 _dbus_assert (start <= real->len); 1584 _dbus_assert (start >= 0); 1585 1586 i = start; 1587 while (i < real->len) 1588 { 1589 if (!(real->str[i] == ' ' || 1590 real->str[i] == '\n' || 1591 real->str[i] == '\r' || 1592 real->str[i] == '\t')) 1593 break; 1594 1595 ++i; 1596 } 1597 1598 _dbus_assert (i == real->len || !(real->str[i] == ' ' || 1599 real->str[i] == '\t')); 1600 1601 if (end) 1602 *end = i; 1603} 1604 1605/** 1606 * Assigns a newline-terminated or \r\n-terminated line from the front 1607 * of the string to the given dest string. The dest string's previous 1608 * contents are deleted. If the source string contains no newline, 1609 * moves the entire source string to the dest string. 1610 * 1611 * @todo owen correctly notes that this is a stupid function (it was 1612 * written purely for test code, 1613 * e.g. dbus-message-builder.c). Probably should be enforced as test 1614 * code only with #ifdef DBUS_BUILD_TESTS 1615 * 1616 * @param source the source string 1617 * @param dest the destination string (contents are replaced) 1618 * @returns #FALSE if no memory, or source has length 0 1619 */ 1620dbus_bool_t 1621_dbus_string_pop_line (DBusString *source, 1622 DBusString *dest) 1623{ 1624 int eol; 1625 dbus_bool_t have_newline; 1626 1627 _dbus_string_set_length (dest, 0); 1628 1629 eol = 0; 1630 if (_dbus_string_find (source, 0, "\n", &eol)) 1631 { 1632 have_newline = TRUE; 1633 eol += 1; /* include newline */ 1634 } 1635 else 1636 { 1637 eol = _dbus_string_get_length (source); 1638 have_newline = FALSE; 1639 } 1640 1641 if (eol == 0) 1642 return FALSE; /* eof */ 1643 1644 if (!_dbus_string_move_len (source, 0, eol, 1645 dest, 0)) 1646 { 1647 return FALSE; 1648 } 1649 1650 /* dump the newline and the \r if we have one */ 1651 if (have_newline) 1652 { 1653 dbus_bool_t have_cr; 1654 1655 _dbus_assert (_dbus_string_get_length (dest) > 0); 1656 1657 if (_dbus_string_get_length (dest) > 1 && 1658 _dbus_string_get_byte (dest, 1659 _dbus_string_get_length (dest) - 2) == '\r') 1660 have_cr = TRUE; 1661 else 1662 have_cr = FALSE; 1663 1664 _dbus_string_set_length (dest, 1665 _dbus_string_get_length (dest) - 1666 (have_cr ? 2 : 1)); 1667 } 1668 1669 return TRUE; 1670} 1671 1672/** 1673 * Deletes up to and including the first blank space 1674 * in the string. 1675 * 1676 * @param str the string 1677 */ 1678void 1679_dbus_string_delete_first_word (DBusString *str) 1680{ 1681 int i; 1682 1683 if (_dbus_string_find_blank (str, 0, &i)) 1684 _dbus_string_skip_blank (str, i, &i); 1685 1686 _dbus_string_delete (str, 0, i); 1687} 1688 1689/** 1690 * Deletes any leading blanks in the string 1691 * 1692 * @param str the string 1693 */ 1694void 1695_dbus_string_delete_leading_blanks (DBusString *str) 1696{ 1697 int i; 1698 1699 _dbus_string_skip_blank (str, 0, &i); 1700 1701 if (i > 0) 1702 _dbus_string_delete (str, 0, i); 1703} 1704 1705/** 1706 * Tests two DBusString for equality. 1707 * 1708 * @todo memcmp is probably faster 1709 * 1710 * @param a first string 1711 * @param b second string 1712 * @returns #TRUE if equal 1713 */ 1714dbus_bool_t 1715_dbus_string_equal (const DBusString *a, 1716 const DBusString *b) 1717{ 1718 const unsigned char *ap; 1719 const unsigned char *bp; 1720 const unsigned char *a_end; 1721 const DBusRealString *real_a = (const DBusRealString*) a; 1722 const DBusRealString *real_b = (const DBusRealString*) b; 1723 DBUS_GENERIC_STRING_PREAMBLE (real_a); 1724 DBUS_GENERIC_STRING_PREAMBLE (real_b); 1725 1726 if (real_a->len != real_b->len) 1727 return FALSE; 1728 1729 ap = real_a->str; 1730 bp = real_b->str; 1731 a_end = real_a->str + real_a->len; 1732 while (ap != a_end) 1733 { 1734 if (*ap != *bp) 1735 return FALSE; 1736 1737 ++ap; 1738 ++bp; 1739 } 1740 1741 return TRUE; 1742} 1743 1744/** 1745 * Tests two DBusString for equality up to the given length. 1746 * 1747 * @todo write a unit test 1748 * 1749 * @todo memcmp is probably faster 1750 * 1751 * @param a first string 1752 * @param b second string 1753 * @param len the lengh 1754 * @returns #TRUE if equal for the given number of bytes 1755 */ 1756dbus_bool_t 1757_dbus_string_equal_len (const DBusString *a, 1758 const DBusString *b, 1759 int len) 1760{ 1761 const unsigned char *ap; 1762 const unsigned char *bp; 1763 const unsigned char *a_end; 1764 const DBusRealString *real_a = (const DBusRealString*) a; 1765 const DBusRealString *real_b = (const DBusRealString*) b; 1766 DBUS_GENERIC_STRING_PREAMBLE (real_a); 1767 DBUS_GENERIC_STRING_PREAMBLE (real_b); 1768 1769 if (real_a->len != real_b->len && 1770 (real_a->len < len || real_b->len < len)) 1771 return FALSE; 1772 1773 ap = real_a->str; 1774 bp = real_b->str; 1775 a_end = real_a->str + MIN (real_a->len, len); 1776 while (ap != a_end) 1777 { 1778 if (*ap != *bp) 1779 return FALSE; 1780 1781 ++ap; 1782 ++bp; 1783 } 1784 1785 return TRUE; 1786} 1787 1788/** 1789 * Checks whether a string is equal to a C string. 1790 * 1791 * @param a the string 1792 * @param c_str the C string 1793 * @returns #TRUE if equal 1794 */ 1795dbus_bool_t 1796_dbus_string_equal_c_str (const DBusString *a, 1797 const char *c_str) 1798{ 1799 const unsigned char *ap; 1800 const unsigned char *bp; 1801 const unsigned char *a_end; 1802 const DBusRealString *real_a = (const DBusRealString*) a; 1803 DBUS_GENERIC_STRING_PREAMBLE (real_a); 1804 _dbus_assert (c_str != NULL); 1805 1806 ap = real_a->str; 1807 bp = (const unsigned char*) c_str; 1808 a_end = real_a->str + real_a->len; 1809 while (ap != a_end && *bp) 1810 { 1811 if (*ap != *bp) 1812 return FALSE; 1813 1814 ++ap; 1815 ++bp; 1816 } 1817 1818 if (ap != a_end || *bp) 1819 return FALSE; 1820 1821 return TRUE; 1822} 1823 1824/** 1825 * Checks whether a string starts with the given C string. 1826 * 1827 * @param a the string 1828 * @param c_str the C string 1829 * @returns #TRUE if string starts with it 1830 */ 1831dbus_bool_t 1832_dbus_string_starts_with_c_str (const DBusString *a, 1833 const char *c_str) 1834{ 1835 const unsigned char *ap; 1836 const unsigned char *bp; 1837 const unsigned char *a_end; 1838 const DBusRealString *real_a = (const DBusRealString*) a; 1839 DBUS_GENERIC_STRING_PREAMBLE (real_a); 1840 _dbus_assert (c_str != NULL); 1841 1842 ap = real_a->str; 1843 bp = (const unsigned char*) c_str; 1844 a_end = real_a->str + real_a->len; 1845 while (ap != a_end && *bp) 1846 { 1847 if (*ap != *bp) 1848 return FALSE; 1849 1850 ++ap; 1851 ++bp; 1852 } 1853 1854 if (*bp == '\0') 1855 return TRUE; 1856 else 1857 return FALSE; 1858} 1859 1860/** 1861 * Returns whether a string ends with the given suffix 1862 * 1863 * @todo memcmp might make this faster. 1864 * 1865 * @param a the string 1866 * @param c_str the C-style string 1867 * @returns #TRUE if the string ends with the suffix 1868 */ 1869dbus_bool_t 1870_dbus_string_ends_with_c_str (const DBusString *a, 1871 const char *c_str) 1872{ 1873 const unsigned char *ap; 1874 const unsigned char *bp; 1875 const unsigned char *a_end; 1876 unsigned long c_str_len; 1877 const DBusRealString *real_a = (const DBusRealString*) a; 1878 DBUS_GENERIC_STRING_PREAMBLE (real_a); 1879 _dbus_assert (c_str != NULL); 1880 1881 c_str_len = strlen (c_str); 1882 if (((unsigned long)real_a->len) < c_str_len) 1883 return FALSE; 1884 1885 ap = real_a->str + (real_a->len - c_str_len); 1886 bp = (const unsigned char*) c_str; 1887 a_end = real_a->str + real_a->len; 1888 while (ap != a_end) 1889 { 1890 if (*ap != *bp) 1891 return FALSE; 1892 1893 ++ap; 1894 ++bp; 1895 } 1896 1897 _dbus_assert (*ap == '\0'); 1898 _dbus_assert (*bp == '\0'); 1899 1900 return TRUE; 1901} 1902 1903static const signed char base64_table[] = { 1904 /* 0 */ 'A', 1905 /* 1 */ 'B', 1906 /* 2 */ 'C', 1907 /* 3 */ 'D', 1908 /* 4 */ 'E', 1909 /* 5 */ 'F', 1910 /* 6 */ 'G', 1911 /* 7 */ 'H', 1912 /* 8 */ 'I', 1913 /* 9 */ 'J', 1914 /* 10 */ 'K', 1915 /* 11 */ 'L', 1916 /* 12 */ 'M', 1917 /* 13 */ 'N', 1918 /* 14 */ 'O', 1919 /* 15 */ 'P', 1920 /* 16 */ 'Q', 1921 /* 17 */ 'R', 1922 /* 18 */ 'S', 1923 /* 19 */ 'T', 1924 /* 20 */ 'U', 1925 /* 21 */ 'V', 1926 /* 22 */ 'W', 1927 /* 23 */ 'X', 1928 /* 24 */ 'Y', 1929 /* 25 */ 'Z', 1930 /* 26 */ 'a', 1931 /* 27 */ 'b', 1932 /* 28 */ 'c', 1933 /* 29 */ 'd', 1934 /* 30 */ 'e', 1935 /* 31 */ 'f', 1936 /* 32 */ 'g', 1937 /* 33 */ 'h', 1938 /* 34 */ 'i', 1939 /* 35 */ 'j', 1940 /* 36 */ 'k', 1941 /* 37 */ 'l', 1942 /* 38 */ 'm', 1943 /* 39 */ 'n', 1944 /* 40 */ 'o', 1945 /* 41 */ 'p', 1946 /* 42 */ 'q', 1947 /* 43 */ 'r', 1948 /* 44 */ 's', 1949 /* 45 */ 't', 1950 /* 46 */ 'u', 1951 /* 47 */ 'v', 1952 /* 48 */ 'w', 1953 /* 49 */ 'x', 1954 /* 50 */ 'y', 1955 /* 51 */ 'z', 1956 /* 52 */ '0', 1957 /* 53 */ '1', 1958 /* 54 */ '2', 1959 /* 55 */ '3', 1960 /* 56 */ '4', 1961 /* 57 */ '5', 1962 /* 58 */ '6', 1963 /* 59 */ '7', 1964 /* 60 */ '8', 1965 /* 61 */ '9', 1966 /* 62 */ '+', 1967 /* 63 */ '/' 1968}; 1969 1970/** The minimum char that's a valid char in Base64-encoded text */ 1971#define UNBASE64_MIN_CHAR (43) 1972/** The maximum char that's a valid char in Base64-encoded text */ 1973#define UNBASE64_MAX_CHAR (122) 1974/** Must subtract this from a char's integer value before offsetting 1975 * into unbase64_table 1976 */ 1977#define UNBASE64_TABLE_OFFSET UNBASE64_MIN_CHAR 1978static const signed char unbase64_table[] = { 1979 /* 43 + */ 62, 1980 /* 44 , */ -1, 1981 /* 45 - */ -1, 1982 /* 46 . */ -1, 1983 /* 47 / */ 63, 1984 /* 48 0 */ 52, 1985 /* 49 1 */ 53, 1986 /* 50 2 */ 54, 1987 /* 51 3 */ 55, 1988 /* 52 4 */ 56, 1989 /* 53 5 */ 57, 1990 /* 54 6 */ 58, 1991 /* 55 7 */ 59, 1992 /* 56 8 */ 60, 1993 /* 57 9 */ 61, 1994 /* 58 : */ -1, 1995 /* 59 ; */ -1, 1996 /* 60 < */ -1, 1997 /* 61 = */ -1, 1998 /* 62 > */ -1, 1999 /* 63 ? */ -1, 2000 /* 64 @ */ -1, 2001 /* 65 A */ 0, 2002 /* 66 B */ 1, 2003 /* 67 C */ 2, 2004 /* 68 D */ 3, 2005 /* 69 E */ 4, 2006 /* 70 F */ 5, 2007 /* 71 G */ 6, 2008 /* 72 H */ 7, 2009 /* 73 I */ 8, 2010 /* 74 J */ 9, 2011 /* 75 K */ 10, 2012 /* 76 L */ 11, 2013 /* 77 M */ 12, 2014 /* 78 N */ 13, 2015 /* 79 O */ 14, 2016 /* 80 P */ 15, 2017 /* 81 Q */ 16, 2018 /* 82 R */ 17, 2019 /* 83 S */ 18, 2020 /* 84 T */ 19, 2021 /* 85 U */ 20, 2022 /* 86 V */ 21, 2023 /* 87 W */ 22, 2024 /* 88 X */ 23, 2025 /* 89 Y */ 24, 2026 /* 90 Z */ 25, 2027 /* 91 [ */ -1, 2028 /* 92 \ */ -1, 2029 /* 93 ] */ -1, 2030 /* 94 ^ */ -1, 2031 /* 95 _ */ -1, 2032 /* 96 ` */ -1, 2033 /* 97 a */ 26, 2034 /* 98 b */ 27, 2035 /* 99 c */ 28, 2036 /* 100 d */ 29, 2037 /* 101 e */ 30, 2038 /* 102 f */ 31, 2039 /* 103 g */ 32, 2040 /* 104 h */ 33, 2041 /* 105 i */ 34, 2042 /* 106 j */ 35, 2043 /* 107 k */ 36, 2044 /* 108 l */ 37, 2045 /* 109 m */ 38, 2046 /* 110 n */ 39, 2047 /* 111 o */ 40, 2048 /* 112 p */ 41, 2049 /* 113 q */ 42, 2050 /* 114 r */ 43, 2051 /* 115 s */ 44, 2052 /* 116 t */ 45, 2053 /* 117 u */ 46, 2054 /* 118 v */ 47, 2055 /* 119 w */ 48, 2056 /* 120 x */ 49, 2057 /* 121 y */ 50, 2058 /* 122 z */ 51 2059}; 2060 2061/** 2062 * Encodes a string using Base64, as documented in RFC 2045. 2063 * 2064 * @param source the string to encode 2065 * @param start byte index to start encoding 2066 * @param dest string where encoded data should be placed 2067 * @param insert_at where to place encoded data 2068 * @returns #TRUE if encoding was successful, #FALSE if no memory etc. 2069 */ 2070dbus_bool_t 2071_dbus_string_base64_encode (const DBusString *source, 2072 int start, 2073 DBusString *dest, 2074 int insert_at) 2075{ 2076 int source_len; 2077 unsigned int dest_len; /* unsigned for overflow checks below */ 2078 const unsigned char *s; 2079 unsigned char *d; 2080 const unsigned char *triplet_end; 2081 const unsigned char *final_end; 2082 DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at); 2083 _dbus_assert (source != dest); 2084 2085 /* For each 24 bits (3 bytes) of input, we have 4 bytes of 2086 * output. 2087 */ 2088 source_len = real_source->len - start; 2089 dest_len = (source_len / 3) * 4; 2090 if (source_len % 3 != 0) 2091 dest_len += 4; 2092 2093 if (dest_len > (unsigned int) real_dest->max_length) 2094 return FALSE; 2095 2096 if (source_len == 0) 2097 return TRUE; 2098 2099 if (!open_gap (dest_len, real_dest, insert_at)) 2100 return FALSE; 2101 2102 d = real_dest->str + insert_at; 2103 s = real_source->str + start; 2104 final_end = real_source->str + (start + source_len); 2105 triplet_end = final_end - (source_len % 3); 2106 _dbus_assert (triplet_end <= final_end); 2107 _dbus_assert ((final_end - triplet_end) < 3); 2108 2109#define ENCODE_64(v) (base64_table[ (unsigned char) (v) ]) 2110#define SIX_BITS_MASK (0x3f) 2111 _dbus_assert (SIX_BITS_MASK < _DBUS_N_ELEMENTS (base64_table)); 2112 2113 while (s != triplet_end) 2114 { 2115 unsigned int triplet; 2116 2117 triplet = s[2] | (s[1] << 8) | (s[0] << 16); 2118 2119 /* Encode each 6 bits. */ 2120 2121 *d++ = ENCODE_64 (triplet >> 18); 2122 *d++ = ENCODE_64 ((triplet >> 12) & SIX_BITS_MASK); 2123 *d++ = ENCODE_64 ((triplet >> 6) & SIX_BITS_MASK); 2124 *d++ = ENCODE_64 (triplet & SIX_BITS_MASK); 2125 2126 s += 3; 2127 } 2128 2129 switch (final_end - triplet_end) 2130 { 2131 case 2: 2132 { 2133 unsigned int doublet; 2134 2135 doublet = s[1] | (s[0] << 8); 2136 2137 *d++ = ENCODE_64 (doublet >> 12); 2138 *d++ = ENCODE_64 ((doublet >> 6) & SIX_BITS_MASK); 2139 *d++ = ENCODE_64 (doublet & SIX_BITS_MASK); 2140 *d++ = '='; 2141 } 2142 break; 2143 case 1: 2144 { 2145 unsigned int singlet; 2146 2147 singlet = s[0]; 2148 2149 *d++ = ENCODE_64 ((singlet >> 6) & SIX_BITS_MASK); 2150 *d++ = ENCODE_64 (singlet & SIX_BITS_MASK); 2151 *d++ = '='; 2152 *d++ = '='; 2153 } 2154 break; 2155 case 0: 2156 break; 2157 } 2158 2159 _dbus_assert (d == (real_dest->str + (insert_at + dest_len))); 2160 2161 return TRUE; 2162} 2163 2164/** 2165 * Decodes a string from Base64, as documented in RFC 2045. 2166 * 2167 * @todo sort out the AUDIT comment in here. The case it mentions 2168 * ("====" or "x===") is not allowed in correct base64, so need to 2169 * decide what to do with that kind of input. Probably ignore it 2170 * since we ignore any other junk seen. 2171 * 2172 * @param source the string to decode 2173 * @param start byte index to start decode 2174 * @param dest string where decoded data should be placed 2175 * @param insert_at where to place decoded data 2176 * @returns #TRUE if decoding was successful, #FALSE if no memory etc. 2177 */ 2178dbus_bool_t 2179_dbus_string_base64_decode (const DBusString *source, 2180 int start, 2181 DBusString *dest, 2182 int insert_at) 2183{ 2184 int source_len; 2185 const char *s; 2186 const char *end; 2187 DBusString result; 2188 unsigned int triplet = 0; 2189 int sextet_count; 2190 int pad_count; 2191 DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at); 2192 _dbus_assert (source != dest); 2193 2194 source_len = real_source->len - start; 2195 s = real_source->str + start; 2196 end = real_source->str + source_len; 2197 2198 if (source_len == 0) 2199 return TRUE; 2200 2201 if (!_dbus_string_init (&result)) 2202 return FALSE; 2203 2204 pad_count = 0; 2205 sextet_count = 0; 2206 while (s != end) 2207 { 2208 /* The idea is to just skip anything that isn't 2209 * a base64 char - it's allowed to have whitespace, 2210 * newlines, etc. in here. We also ignore trailing 2211 * base64 chars, though that's suspicious. 2212 */ 2213 2214 if (*s >= UNBASE64_MIN_CHAR && 2215 *s <= UNBASE64_MAX_CHAR) 2216 { 2217 if (*s == '=') 2218 { 2219 /* '=' is padding, doesn't represent additional data 2220 * but does increment our count. 2221 */ 2222 pad_count += 1; 2223 sextet_count += 1; 2224 } 2225 else 2226 { 2227 int val; 2228 2229 val = unbase64_table[(*s) - UNBASE64_TABLE_OFFSET]; 2230 2231 if (val >= 0) 2232 { 2233 triplet <<= 6; 2234 triplet |= (unsigned int) val; 2235 sextet_count += 1; 2236 } 2237 } 2238 2239 if (sextet_count == 4) 2240 { 2241 /* no pad = 3 bytes, 1 pad = 2 bytes, 2 pad = 1 byte */ 2242 2243 2244 /* AUDIT: Comment doesn't mention 4 pad => 0, 2245 * 3 pad => 1 byte, though the code should 2246 * work fine if those are the required outputs. 2247 * 2248 * I assume that the spec requires dropping 2249 * the top two bits of, say, ///= which is > 2 2250 * bytes worth of bits. (Or otherwise, you couldn't 2251 * actually represent 2 byte sequences. 2252 */ 2253 2254 if (pad_count < 1) 2255 { 2256 if (!_dbus_string_append_byte (&result, 2257 triplet >> 16)) 2258 goto failed; 2259 } 2260 2261 if (pad_count < 2) 2262 { 2263 if (!_dbus_string_append_byte (&result, 2264 (triplet >> 8) & 0xff)) 2265 goto failed; 2266 } 2267 2268 if (!_dbus_string_append_byte (&result, 2269 triplet & 0xff)) 2270 goto failed; 2271 2272 sextet_count = 0; 2273 pad_count = 0; 2274 triplet = 0; 2275 } 2276 } 2277 2278 ++s; 2279 } 2280 2281 if (!_dbus_string_move (&result, 0, dest, insert_at)) 2282 { 2283 _dbus_string_free (&result); 2284 return FALSE; 2285 } 2286 2287 _dbus_string_free (&result); 2288 2289 return TRUE; 2290 2291 failed: 2292 _dbus_string_free (&result); 2293 2294 return FALSE; 2295} 2296 2297/** 2298 * Encodes a string in hex, the way MD5 and SHA-1 are usually 2299 * encoded. (Each byte is two hex digits.) 2300 * 2301 * @param source the string to encode 2302 * @param start byte index to start encoding 2303 * @param dest string where encoded data should be placed 2304 * @param insert_at where to place encoded data 2305 * @returns #TRUE if encoding was successful, #FALSE if no memory etc. 2306 */ 2307dbus_bool_t 2308_dbus_string_hex_encode (const DBusString *source, 2309 int start, 2310 DBusString *dest, 2311 int insert_at) 2312{ 2313 DBusString result; 2314 const char hexdigits[16] = { 2315 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 2316 'a', 'b', 'c', 'd', 'e', 'f' 2317 }; 2318 const unsigned char *p; 2319 const unsigned char *end; 2320 dbus_bool_t retval; 2321 2322 _dbus_assert (start <= _dbus_string_get_length (source)); 2323 2324 if (!_dbus_string_init (&result)) 2325 return FALSE; 2326 2327 retval = FALSE; 2328 2329 p = (const unsigned char*) _dbus_string_get_const_data (source); 2330 end = p + _dbus_string_get_length (source); 2331 p += start; 2332 2333 while (p != end) 2334 { 2335 if (!_dbus_string_append_byte (&result, 2336 hexdigits[(*p >> 4)])) 2337 goto out; 2338 2339 if (!_dbus_string_append_byte (&result, 2340 hexdigits[(*p & 0x0f)])) 2341 goto out; 2342 2343 ++p; 2344 } 2345 2346 if (!_dbus_string_move (&result, 0, dest, insert_at)) 2347 goto out; 2348 2349 retval = TRUE; 2350 2351 out: 2352 _dbus_string_free (&result); 2353 return retval; 2354} 2355 2356/** 2357 * Decodes a string from hex encoding. 2358 * 2359 * @param source the string to decode 2360 * @param start byte index to start decode 2361 * @param dest string where decoded data should be placed 2362 * @param insert_at where to place decoded data 2363 * @returns #TRUE if decoding was successful, #FALSE if no memory etc. 2364 */ 2365dbus_bool_t 2366_dbus_string_hex_decode (const DBusString *source, 2367 int start, 2368 DBusString *dest, 2369 int insert_at) 2370{ 2371 DBusString result; 2372 const unsigned char *p; 2373 const unsigned char *end; 2374 dbus_bool_t retval; 2375 dbus_bool_t high_bits; 2376 2377 _dbus_assert (start <= _dbus_string_get_length (source)); 2378 2379 if (!_dbus_string_init (&result)) 2380 return FALSE; 2381 2382 retval = FALSE; 2383 2384 high_bits = TRUE; 2385 p = (const unsigned char*) _dbus_string_get_const_data (source); 2386 end = p + _dbus_string_get_length (source); 2387 p += start; 2388 2389 while (p != end) 2390 { 2391 unsigned int val; 2392 2393 switch (*p) 2394 { 2395 case '0': 2396 val = 0; 2397 break; 2398 case '1': 2399 val = 1; 2400 break; 2401 case '2': 2402 val = 2; 2403 break; 2404 case '3': 2405 val = 3; 2406 break; 2407 case '4': 2408 val = 4; 2409 break; 2410 case '5': 2411 val = 5; 2412 break; 2413 case '6': 2414 val = 6; 2415 break; 2416 case '7': 2417 val = 7; 2418 break; 2419 case '8': 2420 val = 8; 2421 break; 2422 case '9': 2423 val = 9; 2424 break; 2425 case 'a': 2426 case 'A': 2427 val = 10; 2428 break; 2429 case 'b': 2430 case 'B': 2431 val = 11; 2432 break; 2433 case 'c': 2434 case 'C': 2435 val = 12; 2436 break; 2437 case 'd': 2438 case 'D': 2439 val = 13; 2440 break; 2441 case 'e': 2442 case 'E': 2443 val = 14; 2444 break; 2445 case 'f': 2446 case 'F': 2447 val = 15; 2448 break; 2449 default: 2450 val = 0; 2451 _dbus_verbose ("invalid character '%c' in hex encoded text\n", 2452 *p); 2453 goto out; 2454 } 2455 2456 if (high_bits) 2457 { 2458 if (!_dbus_string_append_byte (&result, 2459 val << 4)) 2460 goto out; 2461 } 2462 else 2463 { 2464 int len; 2465 unsigned char b; 2466 2467 len = _dbus_string_get_length (&result); 2468 2469 b = _dbus_string_get_byte (&result, len - 1); 2470 2471 b |= val; 2472 2473 _dbus_string_set_byte (&result, len - 1, b); 2474 } 2475 2476 high_bits = !high_bits; 2477 2478 ++p; 2479 } 2480 2481 if (!_dbus_string_move (&result, 0, dest, insert_at)) 2482 goto out; 2483 2484 retval = TRUE; 2485 2486 out: 2487 _dbus_string_free (&result); 2488 return retval; 2489} 2490 2491/** 2492 * Checks that the given range of the string is valid ASCII with no 2493 * nul bytes. If the given range is not entirely contained in the 2494 * string, returns #FALSE. 2495 * 2496 * @todo this is inconsistent with most of DBusString in that 2497 * it allows a start,len range that isn't in the string. 2498 * 2499 * @param str the string 2500 * @param start first byte index to check 2501 * @param len number of bytes to check 2502 * @returns #TRUE if the byte range exists and is all valid ASCII 2503 */ 2504dbus_bool_t 2505_dbus_string_validate_ascii (const DBusString *str, 2506 int start, 2507 int len) 2508{ 2509 const unsigned char *s; 2510 const unsigned char *end; 2511 DBUS_CONST_STRING_PREAMBLE (str); 2512 _dbus_assert (start >= 0); 2513 _dbus_assert (start <= real->len); 2514 _dbus_assert (len >= 0); 2515 2516 if (len > real->len - start) 2517 return FALSE; 2518 2519 s = real->str + start; 2520 end = s + len; 2521 while (s != end) 2522 { 2523 if (*s == '\0' || 2524 ((*s & ~0x7f) != 0)) 2525 return FALSE; 2526 2527 ++s; 2528 } 2529 2530 return TRUE; 2531} 2532 2533/** 2534 * Checks that the given range of the string is valid UTF-8. If the 2535 * given range is not entirely contained in the string, returns 2536 * #FALSE. If the string contains any nul bytes in the given range, 2537 * returns #FALSE. If the start and start+len are not on character 2538 * boundaries, returns #FALSE. 2539 * 2540 * @todo this is inconsistent with most of DBusString in that 2541 * it allows a start,len range that isn't in the string. 2542 * 2543 * @param str the string 2544 * @param start first byte index to check 2545 * @param len number of bytes to check 2546 * @returns #TRUE if the byte range exists and is all valid UTF-8 2547 */ 2548dbus_bool_t 2549_dbus_string_validate_utf8 (const DBusString *str, 2550 int start, 2551 int len) 2552{ 2553 const unsigned char *p; 2554 const unsigned char *end; 2555 DBUS_CONST_STRING_PREAMBLE (str); 2556 _dbus_assert (start >= 0); 2557 _dbus_assert (start <= real->len); 2558 _dbus_assert (len >= 0); 2559 2560 if (len > real->len - start) 2561 return FALSE; 2562 2563 p = real->str + start; 2564 end = p + len; 2565 2566 while (p < end) 2567 { 2568 int i, mask = 0, char_len; 2569 dbus_unichar_t result; 2570 unsigned char c = (unsigned char) *p; 2571 2572 UTF8_COMPUTE (c, mask, char_len); 2573 2574 if (char_len == -1) 2575 break; 2576 2577 /* check that the expected number of bytes exists in the remaining length */ 2578 if ((end - p) < char_len) 2579 break; 2580 2581 UTF8_GET (result, p, i, mask, char_len); 2582 2583 if (UTF8_LENGTH (result) != char_len) /* Check for overlong UTF-8 */ 2584 break; 2585 2586 if (result == (dbus_unichar_t)-1) 2587 break; 2588 2589 if (!UNICODE_VALID (result)) 2590 break; 2591 2592 p += char_len; 2593 } 2594 2595 /* See that we covered the entire length if a length was 2596 * passed in 2597 */ 2598 if (p != end) 2599 return FALSE; 2600 else 2601 return TRUE; 2602} 2603 2604/** 2605 * Checks that the given range of the string is all nul bytes. If the 2606 * given range is not entirely contained in the string, returns 2607 * #FALSE. 2608 * 2609 * @todo this is inconsistent with most of DBusString in that 2610 * it allows a start,len range that isn't in the string. 2611 * 2612 * @param str the string 2613 * @param start first byte index to check 2614 * @param len number of bytes to check 2615 * @returns #TRUE if the byte range exists and is all nul bytes 2616 */ 2617dbus_bool_t 2618_dbus_string_validate_nul (const DBusString *str, 2619 int start, 2620 int len) 2621{ 2622 const unsigned char *s; 2623 const unsigned char *end; 2624 DBUS_CONST_STRING_PREAMBLE (str); 2625 _dbus_assert (start >= 0); 2626 _dbus_assert (len >= 0); 2627 _dbus_assert (start <= real->len); 2628 2629 if (len > real->len - start) 2630 return FALSE; 2631 2632 s = real->str + start; 2633 end = s + len; 2634 while (s != end) 2635 { 2636 if (*s != '\0') 2637 return FALSE; 2638 ++s; 2639 } 2640 2641 return TRUE; 2642} 2643 2644/** 2645 * Clears all allocated bytes in the string to zero. 2646 * 2647 * @param str the string 2648 */ 2649void 2650_dbus_string_zero (DBusString *str) 2651{ 2652 DBUS_STRING_PREAMBLE (str); 2653 2654 memset (real->str, '\0', real->allocated); 2655} 2656/** @} */ 2657 2658#ifdef DBUS_BUILD_TESTS 2659#include "dbus-test.h" 2660#include <stdio.h> 2661 2662static void 2663test_max_len (DBusString *str, 2664 int max_len) 2665{ 2666 if (max_len > 0) 2667 { 2668 if (!_dbus_string_set_length (str, max_len - 1)) 2669 _dbus_assert_not_reached ("setting len to one less than max should have worked"); 2670 } 2671 2672 if (!_dbus_string_set_length (str, max_len)) 2673 _dbus_assert_not_reached ("setting len to max len should have worked"); 2674 2675 if (_dbus_string_set_length (str, max_len + 1)) 2676 _dbus_assert_not_reached ("setting len to one more than max len should not have worked"); 2677 2678 if (!_dbus_string_set_length (str, 0)) 2679 _dbus_assert_not_reached ("setting len to zero should have worked"); 2680} 2681 2682static void 2683test_base64_roundtrip (const unsigned char *data, 2684 int len) 2685{ 2686 DBusString orig; 2687 DBusString encoded; 2688 DBusString decoded; 2689 2690 if (len < 0) 2691 len = strlen (data); 2692 2693 if (!_dbus_string_init (&orig)) 2694 _dbus_assert_not_reached ("could not init string"); 2695 2696 if (!_dbus_string_init (&encoded)) 2697 _dbus_assert_not_reached ("could not init string"); 2698 2699 if (!_dbus_string_init (&decoded)) 2700 _dbus_assert_not_reached ("could not init string"); 2701 2702 if (!_dbus_string_append_len (&orig, data, len)) 2703 _dbus_assert_not_reached ("couldn't append orig data"); 2704 2705 if (!_dbus_string_base64_encode (&orig, 0, &encoded, 0)) 2706 _dbus_assert_not_reached ("could not encode"); 2707 2708 if (!_dbus_string_base64_decode (&encoded, 0, &decoded, 0)) 2709 _dbus_assert_not_reached ("could not decode"); 2710 2711 if (!_dbus_string_equal (&orig, &decoded)) 2712 { 2713 const char *s; 2714 2715 printf ("Original string %d bytes encoded %d bytes decoded %d bytes\n", 2716 _dbus_string_get_length (&orig), 2717 _dbus_string_get_length (&encoded), 2718 _dbus_string_get_length (&decoded)); 2719 printf ("Original: %s\n", data); 2720 s = _dbus_string_get_const_data (&decoded); 2721 printf ("Decoded: %s\n", s); 2722 _dbus_assert_not_reached ("original string not the same as string decoded from base64"); 2723 } 2724 2725 _dbus_string_free (&orig); 2726 _dbus_string_free (&encoded); 2727 _dbus_string_free (&decoded); 2728} 2729 2730static void 2731test_hex_roundtrip (const unsigned char *data, 2732 int len) 2733{ 2734 DBusString orig; 2735 DBusString encoded; 2736 DBusString decoded; 2737 2738 if (len < 0) 2739 len = strlen (data); 2740 2741 if (!_dbus_string_init (&orig)) 2742 _dbus_assert_not_reached ("could not init string"); 2743 2744 if (!_dbus_string_init (&encoded)) 2745 _dbus_assert_not_reached ("could not init string"); 2746 2747 if (!_dbus_string_init (&decoded)) 2748 _dbus_assert_not_reached ("could not init string"); 2749 2750 if (!_dbus_string_append_len (&orig, data, len)) 2751 _dbus_assert_not_reached ("couldn't append orig data"); 2752 2753 if (!_dbus_string_hex_encode (&orig, 0, &encoded, 0)) 2754 _dbus_assert_not_reached ("could not encode"); 2755 2756 if (!_dbus_string_hex_decode (&encoded, 0, &decoded, 0)) 2757 _dbus_assert_not_reached ("could not decode"); 2758 2759 if (!_dbus_string_equal (&orig, &decoded)) 2760 { 2761 const char *s; 2762 2763 printf ("Original string %d bytes encoded %d bytes decoded %d bytes\n", 2764 _dbus_string_get_length (&orig), 2765 _dbus_string_get_length (&encoded), 2766 _dbus_string_get_length (&decoded)); 2767 printf ("Original: %s\n", data); 2768 s = _dbus_string_get_const_data (&decoded); 2769 printf ("Decoded: %s\n", s); 2770 _dbus_assert_not_reached ("original string not the same as string decoded from base64"); 2771 } 2772 2773 _dbus_string_free (&orig); 2774 _dbus_string_free (&encoded); 2775 _dbus_string_free (&decoded); 2776} 2777 2778typedef void (* TestRoundtripFunc) (const unsigned char *data, 2779 int len); 2780static void 2781test_roundtrips (TestRoundtripFunc func) 2782{ 2783 (* func) ("Hello this is a string\n", -1); 2784 (* func) ("Hello this is a string\n1", -1); 2785 (* func) ("Hello this is a string\n12", -1); 2786 (* func) ("Hello this is a string\n123", -1); 2787 (* func) ("Hello this is a string\n1234", -1); 2788 (* func) ("Hello this is a string\n12345", -1); 2789 (* func) ("", 0); 2790 (* func) ("1", 1); 2791 (* func) ("12", 2); 2792 (* func) ("123", 3); 2793 (* func) ("1234", 4); 2794 (* func) ("12345", 5); 2795 (* func) ("", 1); 2796 (* func) ("1", 2); 2797 (* func) ("12", 3); 2798 (* func) ("123", 4); 2799 (* func) ("1234", 5); 2800 (* func) ("12345", 6); 2801 { 2802 unsigned char buf[512]; 2803 int i; 2804 2805 i = 0; 2806 while (i < _DBUS_N_ELEMENTS (buf)) 2807 { 2808 buf[i] = i; 2809 ++i; 2810 } 2811 i = 0; 2812 while (i < _DBUS_N_ELEMENTS (buf)) 2813 { 2814 (* func) (buf, i); 2815 ++i; 2816 } 2817 } 2818} 2819 2820 2821/** 2822 * @ingroup DBusStringInternals 2823 * Unit test for DBusString. 2824 * 2825 * @todo Need to write tests for _dbus_string_copy() and 2826 * _dbus_string_move() moving to/from each of start/middle/end of a 2827 * string. Also need tests for _dbus_string_move_len () 2828 * 2829 * @returns #TRUE on success. 2830 */ 2831dbus_bool_t 2832_dbus_string_test (void) 2833{ 2834 DBusString str; 2835 DBusString other; 2836 int i, end; 2837 long v; 2838 double d; 2839 int lens[] = { 0, 1, 2, 3, 4, 5, 10, 16, 17, 18, 25, 31, 32, 33, 34, 35, 63, 64, 65, 66, 67, 68, 69, 70, 71, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136 }; 2840 char *s; 2841 dbus_unichar_t ch; 2842 2843 i = 0; 2844 while (i < _DBUS_N_ELEMENTS (lens)) 2845 { 2846 if (!_dbus_string_init (&str)) 2847 _dbus_assert_not_reached ("failed to init string"); 2848 2849 set_max_length (&str, lens[i]); 2850 2851 test_max_len (&str, lens[i]); 2852 _dbus_string_free (&str); 2853 2854 ++i; 2855 } 2856 2857 /* Test shortening and setting length */ 2858 i = 0; 2859 while (i < _DBUS_N_ELEMENTS (lens)) 2860 { 2861 int j; 2862 2863 if (!_dbus_string_init (&str)) 2864 _dbus_assert_not_reached ("failed to init string"); 2865 2866 set_max_length (&str, lens[i]); 2867 2868 if (!_dbus_string_set_length (&str, lens[i])) 2869 _dbus_assert_not_reached ("failed to set string length"); 2870 2871 j = lens[i]; 2872 while (j > 0) 2873 { 2874 _dbus_assert (_dbus_string_get_length (&str) == j); 2875 if (j > 0) 2876 { 2877 _dbus_string_shorten (&str, 1); 2878 _dbus_assert (_dbus_string_get_length (&str) == (j - 1)); 2879 } 2880 --j; 2881 } 2882 2883 _dbus_string_free (&str); 2884 2885 ++i; 2886 } 2887 2888 /* Test appending data */ 2889 if (!_dbus_string_init (&str)) 2890 _dbus_assert_not_reached ("failed to init string"); 2891 2892 i = 0; 2893 while (i < 10) 2894 { 2895 if (!_dbus_string_append (&str, "a")) 2896 _dbus_assert_not_reached ("failed to append string to string\n"); 2897 2898 _dbus_assert (_dbus_string_get_length (&str) == i * 2 + 1); 2899 2900 if (!_dbus_string_append_byte (&str, 'b')) 2901 _dbus_assert_not_reached ("failed to append byte to string\n"); 2902 2903 _dbus_assert (_dbus_string_get_length (&str) == i * 2 + 2); 2904 2905 ++i; 2906 } 2907 2908 _dbus_string_free (&str); 2909 2910 /* Check steal_data */ 2911 2912 if (!_dbus_string_init (&str)) 2913 _dbus_assert_not_reached ("failed to init string"); 2914 2915 if (!_dbus_string_append (&str, "Hello World")) 2916 _dbus_assert_not_reached ("could not append to string"); 2917 2918 i = _dbus_string_get_length (&str); 2919 2920 if (!_dbus_string_steal_data (&str, &s)) 2921 _dbus_assert_not_reached ("failed to steal data"); 2922 2923 _dbus_assert (_dbus_string_get_length (&str) == 0); 2924 _dbus_assert (((int)strlen (s)) == i); 2925 2926 dbus_free (s); 2927 2928 /* Check move */ 2929 2930 if (!_dbus_string_append (&str, "Hello World")) 2931 _dbus_assert_not_reached ("could not append to string"); 2932 2933 i = _dbus_string_get_length (&str); 2934 2935 if (!_dbus_string_init (&other)) 2936 _dbus_assert_not_reached ("could not init string"); 2937 2938 if (!_dbus_string_move (&str, 0, &other, 0)) 2939 _dbus_assert_not_reached ("could not move"); 2940 2941 _dbus_assert (_dbus_string_get_length (&str) == 0); 2942 _dbus_assert (_dbus_string_get_length (&other) == i); 2943 2944 if (!_dbus_string_append (&str, "Hello World")) 2945 _dbus_assert_not_reached ("could not append to string"); 2946 2947 if (!_dbus_string_move (&str, 0, &other, _dbus_string_get_length (&other))) 2948 _dbus_assert_not_reached ("could not move"); 2949 2950 _dbus_assert (_dbus_string_get_length (&str) == 0); 2951 _dbus_assert (_dbus_string_get_length (&other) == i * 2); 2952 2953 if (!_dbus_string_append (&str, "Hello World")) 2954 _dbus_assert_not_reached ("could not append to string"); 2955 2956 if (!_dbus_string_move (&str, 0, &other, _dbus_string_get_length (&other) / 2)) 2957 _dbus_assert_not_reached ("could not move"); 2958 2959 _dbus_assert (_dbus_string_get_length (&str) == 0); 2960 _dbus_assert (_dbus_string_get_length (&other) == i * 3); 2961 2962 _dbus_string_free (&other); 2963 2964 /* Check copy */ 2965 2966 if (!_dbus_string_append (&str, "Hello World")) 2967 _dbus_assert_not_reached ("could not append to string"); 2968 2969 i = _dbus_string_get_length (&str); 2970 2971 if (!_dbus_string_init (&other)) 2972 _dbus_assert_not_reached ("could not init string"); 2973 2974 if (!_dbus_string_copy (&str, 0, &other, 0)) 2975 _dbus_assert_not_reached ("could not copy"); 2976 2977 _dbus_assert (_dbus_string_get_length (&str) == i); 2978 _dbus_assert (_dbus_string_get_length (&other) == i); 2979 2980 if (!_dbus_string_copy (&str, 0, &other, _dbus_string_get_length (&other))) 2981 _dbus_assert_not_reached ("could not copy"); 2982 2983 _dbus_assert (_dbus_string_get_length (&str) == i); 2984 _dbus_assert (_dbus_string_get_length (&other) == i * 2); 2985 _dbus_assert (_dbus_string_equal_c_str (&other, 2986 "Hello WorldHello World")); 2987 2988 if (!_dbus_string_copy (&str, 0, &other, _dbus_string_get_length (&other) / 2)) 2989 _dbus_assert_not_reached ("could not copy"); 2990 2991 _dbus_assert (_dbus_string_get_length (&str) == i); 2992 _dbus_assert (_dbus_string_get_length (&other) == i * 3); 2993 _dbus_assert (_dbus_string_equal_c_str (&other, 2994 "Hello WorldHello WorldHello World")); 2995 2996 _dbus_string_free (&str); 2997 _dbus_string_free (&other); 2998 2999 /* Check replace */ 3000 3001 if (!_dbus_string_init (&str)) 3002 _dbus_assert_not_reached ("failed to init string"); 3003 3004 if (!_dbus_string_append (&str, "Hello World")) 3005 _dbus_assert_not_reached ("could not append to string"); 3006 3007 i = _dbus_string_get_length (&str); 3008 3009 if (!_dbus_string_init (&other)) 3010 _dbus_assert_not_reached ("could not init string"); 3011 3012 if (!_dbus_string_replace_len (&str, 0, _dbus_string_get_length (&str), 3013 &other, 0, _dbus_string_get_length (&other))) 3014 _dbus_assert_not_reached ("could not replace"); 3015 3016 _dbus_assert (_dbus_string_get_length (&str) == i); 3017 _dbus_assert (_dbus_string_get_length (&other) == i); 3018 _dbus_assert (_dbus_string_equal_c_str (&other, "Hello World")); 3019 3020 if (!_dbus_string_replace_len (&str, 0, _dbus_string_get_length (&str), 3021 &other, 5, 1)) 3022 _dbus_assert_not_reached ("could not replace center space"); 3023 3024 _dbus_assert (_dbus_string_get_length (&str) == i); 3025 _dbus_assert (_dbus_string_get_length (&other) == i * 2 - 1); 3026 _dbus_assert (_dbus_string_equal_c_str (&other, 3027 "HelloHello WorldWorld")); 3028 3029 3030 if (!_dbus_string_replace_len (&str, 1, 1, 3031 &other, 3032 _dbus_string_get_length (&other) - 1, 3033 1)) 3034 _dbus_assert_not_reached ("could not replace end character"); 3035 3036 _dbus_assert (_dbus_string_get_length (&str) == i); 3037 _dbus_assert (_dbus_string_get_length (&other) == i * 2 - 1); 3038 _dbus_assert (_dbus_string_equal_c_str (&other, 3039 "HelloHello WorldWorle")); 3040 3041 _dbus_string_free (&str); 3042 _dbus_string_free (&other); 3043 3044 /* Check append/get unichar */ 3045 3046 if (!_dbus_string_init (&str)) 3047 _dbus_assert_not_reached ("failed to init string"); 3048 3049 ch = 0; 3050 if (!_dbus_string_append_unichar (&str, 0xfffc)) 3051 _dbus_assert_not_reached ("failed to append unichar"); 3052 3053 _dbus_string_get_unichar (&str, 0, &ch, &i); 3054 3055 _dbus_assert (ch == 0xfffc); 3056 _dbus_assert (i == _dbus_string_get_length (&str)); 3057 3058 _dbus_string_free (&str); 3059 3060 /* Check insert/set/get byte */ 3061 3062 if (!_dbus_string_init (&str)) 3063 _dbus_assert_not_reached ("failed to init string"); 3064 3065 if (!_dbus_string_append (&str, "Hello")) 3066 _dbus_assert_not_reached ("failed to append Hello"); 3067 3068 _dbus_assert (_dbus_string_get_byte (&str, 0) == 'H'); 3069 _dbus_assert (_dbus_string_get_byte (&str, 1) == 'e'); 3070 _dbus_assert (_dbus_string_get_byte (&str, 2) == 'l'); 3071 _dbus_assert (_dbus_string_get_byte (&str, 3) == 'l'); 3072 _dbus_assert (_dbus_string_get_byte (&str, 4) == 'o'); 3073 3074 _dbus_string_set_byte (&str, 1, 'q'); 3075 _dbus_assert (_dbus_string_get_byte (&str, 1) == 'q'); 3076 3077 if (!_dbus_string_insert_byte (&str, 0, 255)) 3078 _dbus_assert_not_reached ("can't insert byte"); 3079 3080 if (!_dbus_string_insert_byte (&str, 2, 'Z')) 3081 _dbus_assert_not_reached ("can't insert byte"); 3082 3083 if (!_dbus_string_insert_byte (&str, _dbus_string_get_length (&str), 'W')) 3084 _dbus_assert_not_reached ("can't insert byte"); 3085 3086 _dbus_assert (_dbus_string_get_byte (&str, 0) == 255); 3087 _dbus_assert (_dbus_string_get_byte (&str, 1) == 'H'); 3088 _dbus_assert (_dbus_string_get_byte (&str, 2) == 'Z'); 3089 _dbus_assert (_dbus_string_get_byte (&str, 3) == 'q'); 3090 _dbus_assert (_dbus_string_get_byte (&str, 4) == 'l'); 3091 _dbus_assert (_dbus_string_get_byte (&str, 5) == 'l'); 3092 _dbus_assert (_dbus_string_get_byte (&str, 6) == 'o'); 3093 _dbus_assert (_dbus_string_get_byte (&str, 7) == 'W'); 3094 3095 _dbus_string_free (&str); 3096 3097 /* Check append/parse int/double */ 3098 3099 if (!_dbus_string_init (&str)) 3100 _dbus_assert_not_reached ("failed to init string"); 3101 3102 if (!_dbus_string_append_int (&str, 27)) 3103 _dbus_assert_not_reached ("failed to append int"); 3104 3105 i = _dbus_string_get_length (&str); 3106 3107 if (!_dbus_string_parse_int (&str, 0, &v, &end)) 3108 _dbus_assert_not_reached ("failed to parse int"); 3109 3110 _dbus_assert (v == 27); 3111 _dbus_assert (end == i); 3112 3113 _dbus_string_free (&str); 3114 3115 if (!_dbus_string_init (&str)) 3116 _dbus_assert_not_reached ("failed to init string"); 3117 3118 if (!_dbus_string_append_double (&str, 50.3)) 3119 _dbus_assert_not_reached ("failed to append float"); 3120 3121 i = _dbus_string_get_length (&str); 3122 3123 if (!_dbus_string_parse_double (&str, 0, &d, &end)) 3124 _dbus_assert_not_reached ("failed to parse float"); 3125 3126 _dbus_assert (d > (50.3 - 1e-6) && d < (50.3 + 1e-6)); 3127 _dbus_assert (end == i); 3128 3129 _dbus_string_free (&str); 3130 3131 /* Test find */ 3132 if (!_dbus_string_init (&str)) 3133 _dbus_assert_not_reached ("failed to init string"); 3134 3135 if (!_dbus_string_append (&str, "Hello")) 3136 _dbus_assert_not_reached ("couldn't append to string"); 3137 3138 if (!_dbus_string_find (&str, 0, "He", &i)) 3139 _dbus_assert_not_reached ("didn't find 'He'"); 3140 _dbus_assert (i == 0); 3141 3142 if (!_dbus_string_find (&str, 0, "Hello", &i)) 3143 _dbus_assert_not_reached ("didn't find 'Hello'"); 3144 _dbus_assert (i == 0); 3145 3146 if (!_dbus_string_find (&str, 0, "ello", &i)) 3147 _dbus_assert_not_reached ("didn't find 'ello'"); 3148 _dbus_assert (i == 1); 3149 3150 if (!_dbus_string_find (&str, 0, "lo", &i)) 3151 _dbus_assert_not_reached ("didn't find 'lo'"); 3152 _dbus_assert (i == 3); 3153 3154 if (!_dbus_string_find (&str, 2, "lo", &i)) 3155 _dbus_assert_not_reached ("didn't find 'lo'"); 3156 _dbus_assert (i == 3); 3157 3158 if (_dbus_string_find (&str, 4, "lo", &i)) 3159 _dbus_assert_not_reached ("did find 'lo'"); 3160 3161 if (!_dbus_string_find (&str, 0, "l", &i)) 3162 _dbus_assert_not_reached ("didn't find 'l'"); 3163 _dbus_assert (i == 2); 3164 3165 if (!_dbus_string_find (&str, 0, "H", &i)) 3166 _dbus_assert_not_reached ("didn't find 'H'"); 3167 _dbus_assert (i == 0); 3168 3169 if (!_dbus_string_find (&str, 0, "", &i)) 3170 _dbus_assert_not_reached ("didn't find ''"); 3171 _dbus_assert (i == 0); 3172 3173 if (_dbus_string_find (&str, 0, "Hello!", NULL)) 3174 _dbus_assert_not_reached ("Did find 'Hello!'"); 3175 3176 if (_dbus_string_find (&str, 0, "Oh, Hello", NULL)) 3177 _dbus_assert_not_reached ("Did find 'Oh, Hello'"); 3178 3179 if (_dbus_string_find (&str, 0, "ill", NULL)) 3180 _dbus_assert_not_reached ("Did find 'ill'"); 3181 3182 if (_dbus_string_find (&str, 0, "q", NULL)) 3183 _dbus_assert_not_reached ("Did find 'q'"); 3184 3185 if (!_dbus_string_find_to (&str, 0, 2, "He", NULL)) 3186 _dbus_assert_not_reached ("Didn't find 'He'"); 3187 3188 if (_dbus_string_find_to (&str, 0, 2, "Hello", NULL)) 3189 _dbus_assert_not_reached ("Did find 'Hello'"); 3190 3191 if (!_dbus_string_find_byte_backward (&str, _dbus_string_get_length (&str), 'H', &i)) 3192 _dbus_assert_not_reached ("Did not find 'H'"); 3193 _dbus_assert (i == 0); 3194 3195 if (!_dbus_string_find_byte_backward (&str, _dbus_string_get_length (&str), 'o', &i)) 3196 _dbus_assert_not_reached ("Did not find 'o'"); 3197 _dbus_assert (i == _dbus_string_get_length (&str) - 1); 3198 3199 if (_dbus_string_find_byte_backward (&str, _dbus_string_get_length (&str) - 1, 'o', &i)) 3200 _dbus_assert_not_reached ("Did find 'o'"); 3201 _dbus_assert (i == -1); 3202 3203 if (_dbus_string_find_byte_backward (&str, 1, 'e', &i)) 3204 _dbus_assert_not_reached ("Did find 'e'"); 3205 _dbus_assert (i == -1); 3206 3207 if (!_dbus_string_find_byte_backward (&str, 2, 'e', &i)) 3208 _dbus_assert_not_reached ("Didn't find 'e'"); 3209 _dbus_assert (i == 1); 3210 3211 _dbus_string_free (&str); 3212 3213 /* Base 64 and Hex encoding */ 3214 test_roundtrips (test_base64_roundtrip); 3215 test_roundtrips (test_hex_roundtrip); 3216 3217 return TRUE; 3218} 3219 3220#endif /* DBUS_BUILD_TESTS */ 3221