dbus-string.c revision ff5283ab92c668453fd2f28c1715a1e0e9b949f5
1/* -*- mode: C; c-file-style: "gnu" -*- */ 2/* dbus-string.c String utility class (internal to D-BUS implementation) 3 * 4 * Copyright (C) 2002 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 29/** 30 * @defgroup DBusString string class 31 * @ingroup DBusInternals 32 * @brief DBusString data structure 33 * 34 * Types and functions related to DBusString. DBusString is intended 35 * to be a string class that makes it hard to mess up security issues 36 * (and just in general harder to write buggy code). It should be 37 * used (or extended and then used) rather than the libc stuff in 38 * string.h. The string class is a bit inconvenient at spots because 39 * it handles out-of-memory failures and tries to be extra-robust. 40 * 41 * A DBusString has a maximum length set at initialization time; this 42 * can be used to ensure that a buffer doesn't get too big. The 43 * _dbus_string_lengthen() method checks for overflow, and for max 44 * length being exceeded. 45 * 46 * Try to avoid conversion to a plain C string, i.e. add methods on 47 * the string object instead, only convert to C string when passing 48 * things out to the public API. In particular, no sprintf, strcpy, 49 * strcat, any of that should be used. The GString feature of 50 * accepting negative numbers for "length of string" is also absent, 51 * because it could keep us from detecting bogus huge lengths. i.e. if 52 * we passed in some bogus huge length it would be taken to mean 53 * "current length of string" instead of "broken crack" 54 */ 55 56/** 57 * @defgroup DBusStringInternals DBusString implementation details 58 * @ingroup DBusInternals 59 * @brief DBusString implementation details 60 * 61 * The guts of DBusString. 62 * 63 * @{ 64 */ 65 66/** 67 * @brief Internals of DBusString. 68 * 69 * DBusString internals. DBusString is an opaque objects, it must be 70 * used via accessor functions. 71 */ 72typedef struct 73{ 74 unsigned char *str; /**< String data, plus nul termination */ 75 int len; /**< Length without nul */ 76 int allocated; /**< Allocated size of data */ 77 int max_length; /**< Max length of this string. */ 78 unsigned int constant : 1; /**< String data is not owned by DBusString */ 79 unsigned int locked : 1; /**< DBusString has been locked and can't be changed */ 80 unsigned int invalid : 1; /**< DBusString is invalid (e.g. already freed) */ 81} DBusRealString; 82 83/** 84 * Checks a bunch of assertions about a string object 85 * 86 * @param real the DBusRealString 87 */ 88#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); _dbus_assert ((real)->len <= (real)->max_length) 89 90/** 91 * Checks assertions about a string object that needs to be 92 * modifiable - may not be locked or const. Also declares 93 * the "real" variable pointing to DBusRealString. 94 * @param str the string 95 */ 96#define DBUS_STRING_PREAMBLE(str) DBusRealString *real = (DBusRealString*) str; \ 97 DBUS_GENERIC_STRING_PREAMBLE (real); \ 98 _dbus_assert (!(real)->constant); \ 99 _dbus_assert (!(real)->locked) 100 101/** 102 * Checks assertions about a string object that may be locked but 103 * can't be const. i.e. a string object that we can free. Also 104 * declares the "real" variable pointing to DBusRealString. 105 * 106 * @param str the string 107 */ 108#define DBUS_LOCKED_STRING_PREAMBLE(str) DBusRealString *real = (DBusRealString*) str; \ 109 DBUS_GENERIC_STRING_PREAMBLE (real); \ 110 _dbus_assert (!(real)->constant) 111 112/** 113 * Checks assertions about a string that may be const or locked. Also 114 * declares the "real" variable pointing to DBusRealString. 115 * @param str the string. 116 */ 117#define DBUS_CONST_STRING_PREAMBLE(str) const DBusRealString *real = (DBusRealString*) str; \ 118 DBUS_GENERIC_STRING_PREAMBLE (real) 119 120/** @} */ 121 122/** 123 * @addtogroup DBusString 124 * @{ 125 */ 126 127/** 128 * Initializes a string. The maximum length may be _DBUS_INT_MAX for 129 * no maximum. The string starts life with zero length. 130 * The string must eventually be freed with _dbus_string_free(). 131 * 132 * @param str memory to hold the string 133 * @param max_length the maximum size of the string 134 * @returns #TRUE on success 135 */ 136dbus_bool_t 137_dbus_string_init (DBusString *str, 138 int max_length) 139{ 140 DBusRealString *real; 141 142 _dbus_assert (str != NULL); 143 _dbus_assert (max_length >= 0); 144 145 _dbus_assert (sizeof (DBusString) == sizeof (DBusRealString)); 146 147 real = (DBusRealString*) str; 148 149 /* It's very important not to touch anything 150 * other than real->str if we're going to fail, 151 * since we also use this function to reset 152 * an existing string, e.g. in _dbus_string_steal_data() 153 */ 154 155#define INITIAL_ALLOC 2 156 157 real->str = dbus_malloc (INITIAL_ALLOC); 158 if (real->str == NULL) 159 return FALSE; 160 161 real->allocated = INITIAL_ALLOC; 162 real->len = 0; 163 real->str[real->len] = '\0'; 164 165 real->max_length = max_length; 166 real->constant = FALSE; 167 real->locked = FALSE; 168 real->invalid = FALSE; 169 170 return TRUE; 171} 172 173/** 174 * Initializes a constant string. The value parameter is not copied 175 * (should be static), and the string may never be modified. 176 * It is safe but not necessary to call _dbus_string_free() 177 * on a const string. 178 * 179 * @param str memory to use for the string 180 * @param value a string to be stored in str (not copied!!!) 181 */ 182void 183_dbus_string_init_const (DBusString *str, 184 const char *value) 185{ 186 DBusRealString *real; 187 188 _dbus_assert (str != NULL); 189 _dbus_assert (value != NULL); 190 191 real = (DBusRealString*) str; 192 193 real->str = (char*) value; 194 real->len = strlen (real->str); 195 real->allocated = real->len; 196 real->max_length = real->len; 197 real->constant = TRUE; 198 real->invalid = FALSE; 199} 200 201/** 202 * Frees a string created by _dbus_string_init(). 203 * 204 * @param str memory where the string is stored. 205 */ 206void 207_dbus_string_free (DBusString *str) 208{ 209 DBUS_LOCKED_STRING_PREAMBLE (str); 210 211 if (real->constant) 212 return; 213 214 dbus_free (real->str); 215 216 real->invalid = TRUE; 217} 218 219/** 220 * Locks a string such that any attempts to change the string 221 * will result in aborting the program. Also, if the string 222 * is wasting a lot of memory (allocation is larger than what 223 * the string is really using), _dbus_string_lock() will realloc 224 * the string's data to "compact" it. 225 * 226 * @param str the string to lock. 227 */ 228void 229_dbus_string_lock (DBusString *str) 230{ 231 DBUS_LOCKED_STRING_PREAMBLE (str); /* can lock multiple times */ 232 233 real->locked = TRUE; 234 235 /* Try to realloc to avoid excess memory usage, since 236 * we know we won't change the string further 237 */ 238#define MAX_WASTE 24 239 if (real->allocated > (real->len + MAX_WASTE)) 240 { 241 char *new_str; 242 int new_allocated; 243 244 new_allocated = real->len + 1; 245 246 new_str = dbus_realloc (real->str, new_allocated); 247 if (new_str != NULL) 248 { 249 real->str = new_str; 250 real->allocated = new_allocated; 251 } 252 } 253} 254 255/** 256 * Gets the raw character buffer from the string. The returned buffer 257 * will be nul-terminated, but note that strings may contain binary 258 * data so there may be extra nul characters prior to the termination. 259 * This function should be little-used, extend DBusString or add 260 * stuff to dbus-sysdeps.c instead. It's an error to use this 261 * function on a const string. 262 * 263 * @param str the string 264 * @param data_return place to store the returned data 265 */ 266void 267_dbus_string_get_data (DBusString *str, 268 char **data_return) 269{ 270 DBUS_STRING_PREAMBLE (str); 271 _dbus_assert (data_return != NULL); 272 273 *data_return = real->str; 274} 275 276/** 277 * Gets the raw character buffer from a const string. 278 * 279 * @param str the string 280 * @param data_return location to store returned data 281 */ 282void 283_dbus_string_get_const_data (const DBusString *str, 284 const char **data_return) 285{ 286 DBUS_CONST_STRING_PREAMBLE (str); 287 _dbus_assert (data_return != NULL); 288 289 *data_return = real->str; 290} 291 292/** 293 * Gets a sub-portion of the raw character buffer from the 294 * string. The "len" field is required simply for error 295 * checking, to be sure you don't try to use more 296 * string than exists. The nul termination of the 297 * returned buffer remains at the end of the entire 298 * string, not at start + len. 299 * 300 * @param str the string 301 * @param data_return location to return the buffer 302 * @param start byte offset to return 303 * @param len length of segment to return 304 */ 305void 306_dbus_string_get_data_len (DBusString *str, 307 char **data_return, 308 int start, 309 int len) 310{ 311 DBUS_STRING_PREAMBLE (str); 312 _dbus_assert (data_return != NULL); 313 _dbus_assert (start >= 0); 314 _dbus_assert (len >= 0); 315 _dbus_assert ((start + len) <= real->len); 316 317 *data_return = real->str + start; 318} 319 320/** 321 * const version of _dbus_string_get_data_len(). 322 * 323 * @param str the string 324 * @param data_return location to return the buffer 325 * @param start byte offset to return 326 * @param len length of segment to return 327 */ 328void 329_dbus_string_get_const_data_len (const DBusString *str, 330 const char **data_return, 331 int start, 332 int len) 333{ 334 DBUS_CONST_STRING_PREAMBLE (str); 335 _dbus_assert (data_return != NULL); 336 _dbus_assert (start >= 0); 337 _dbus_assert (len >= 0); 338 _dbus_assert ((start + len) <= real->len); 339 340 *data_return = real->str + start; 341} 342 343/** 344 * Like _dbus_string_get_data(), but removes the 345 * gotten data from the original string. The caller 346 * must free the data returned. This function may 347 * fail due to lack of memory, and return #FALSE. 348 * 349 * @param str the string 350 * @param data_return location to return the buffer 351 * @returns #TRUE on success 352 */ 353dbus_bool_t 354_dbus_string_steal_data (DBusString *str, 355 char **data_return) 356{ 357 DBUS_STRING_PREAMBLE (str); 358 _dbus_assert (data_return != NULL); 359 360 *data_return = real->str; 361 362 /* reset the string */ 363 if (!_dbus_string_init (str, real->max_length)) 364 { 365 /* hrm, put it back then */ 366 real->str = *data_return; 367 *data_return = NULL; 368 return FALSE; 369 } 370 371 return TRUE; 372} 373 374/** 375 * Like _dbus_string_get_data_len(), but removes the gotten data from 376 * the original string. The caller must free the data returned. This 377 * function may fail due to lack of memory, and return #FALSE. 378 * The returned string is nul-terminated and has length len. 379 * 380 * @param str the string 381 * @param data_return location to return the buffer 382 * @param start the start of segment to steal 383 * @param len the length of segment to steal 384 * @returns #TRUE on success 385 */ 386dbus_bool_t 387_dbus_string_steal_data_len (DBusString *str, 388 char **data_return, 389 int start, 390 int len) 391{ 392 DBusString dest; 393 394 DBUS_STRING_PREAMBLE (str); 395 _dbus_assert (data_return != NULL); 396 _dbus_assert (start >= 0); 397 _dbus_assert (len >= 0); 398 _dbus_assert ((start + len) <= real->len); 399 400 if (!_dbus_string_init (&dest, real->max_length)) 401 return FALSE; 402 403 if (!_dbus_string_move_len (str, start, len, &dest, 0)) 404 { 405 _dbus_string_free (&dest); 406 return FALSE; 407 } 408 409 if (!_dbus_string_steal_data (&dest, data_return)) 410 { 411 _dbus_string_free (&dest); 412 return FALSE; 413 } 414 415 _dbus_string_free (&dest); 416 return TRUE; 417} 418 419/** 420 * Gets the length of a string (not including nul termination). 421 * 422 * @returns the length. 423 */ 424int 425_dbus_string_get_length (const DBusString *str) 426{ 427 DBUS_CONST_STRING_PREAMBLE (str); 428 429 return real->len; 430} 431 432static dbus_bool_t 433set_length (DBusRealString *real, 434 int new_length) 435{ 436 /* Note, we are setting the length without nul termination */ 437 438 /* exceeding max length is the same as failure to allocate memory */ 439 if (new_length > real->max_length) 440 return FALSE; 441 442 while (new_length >= real->allocated) 443 { 444 int new_allocated; 445 char *new_str; 446 447 new_allocated = 2 + real->allocated * 2; 448 if (new_allocated < real->allocated) 449 return FALSE; /* overflow */ 450 451 new_str = dbus_realloc (real->str, new_allocated); 452 if (new_str == NULL) 453 return FALSE; 454 455 real->str = new_str; 456 real->allocated = new_allocated; 457 } 458 459 real->len = new_length; 460 real->str[real->len] = '\0'; 461 462 return TRUE; 463} 464 465/** 466 * Makes a string longer by the given number of bytes. Checks whether 467 * adding additional_length to the current length would overflow an 468 * integer, and checks for exceeding a string's max length. 469 * The new bytes are not initialized, other than nul-terminating 470 * the end of the string. The uninitialized bytes may contain 471 * unexpected nul bytes or other junk. 472 * 473 * @param str a string 474 * @param additional_length length to add to the string. 475 * @returns #TRUE on success. 476 */ 477dbus_bool_t 478_dbus_string_lengthen (DBusString *str, 479 int additional_length) 480{ 481 DBUS_STRING_PREAMBLE (str); 482 _dbus_assert (additional_length >= 0); 483 484 if ((real->len + additional_length) < real->len) 485 return FALSE; /* overflow */ 486 487 return set_length (real, 488 real->len + additional_length); 489} 490 491/** 492 * Makes a string shorter by the given number of bytes. 493 * 494 * @param str a string 495 * @param length_to_remove length to remove from the string. 496 */ 497void 498_dbus_string_shorten (DBusString *str, 499 int length_to_remove) 500{ 501 DBUS_STRING_PREAMBLE (str); 502 _dbus_assert (length_to_remove >= 0); 503 _dbus_assert (length_to_remove <= real->len); 504 505 set_length (real, 506 real->len - length_to_remove); 507} 508 509/** 510 * Sets the length of a string. Can be used to truncate or lengthen 511 * the string. If the string is lengthened, the function may fail and 512 * return #FALSE. Newly-added bytes are not initialized, as with 513 * _dbus_string_lengthen(). 514 * 515 * @param str a string 516 * @param length new length of the string. 517 * @returns #FALSE on failure. 518 */ 519dbus_bool_t 520_dbus_string_set_length (DBusString *str, 521 int length) 522{ 523 DBUS_STRING_PREAMBLE (str); 524 _dbus_assert (length >= 0); 525 526 return set_length (real, length); 527} 528 529static dbus_bool_t 530append (DBusRealString *real, 531 const char *buffer, 532 int buffer_len) 533{ 534 if (buffer_len == 0) 535 return TRUE; 536 537 if (!_dbus_string_lengthen ((DBusString*)real, buffer_len)) 538 return FALSE; 539 540 memcpy (real->str + (real->len - buffer_len), 541 buffer, 542 buffer_len); 543 544 return TRUE; 545} 546 547/** 548 * Appends a nul-terminated C-style string to a DBusString. 549 * 550 * @param str the DBusString 551 * @param buffer the nul-terminated characters to append 552 * @returns #FALSE if not enough memory. 553 */ 554dbus_bool_t 555_dbus_string_append (DBusString *str, 556 const char *buffer) 557{ 558 int buffer_len; 559 560 DBUS_STRING_PREAMBLE (str); 561 _dbus_assert (buffer != NULL); 562 563 buffer_len = strlen (buffer); 564 565 return append (real, buffer, buffer_len); 566} 567 568/** 569 * Appends block of bytes with the given length to a DBusString. 570 * 571 * @param str the DBusString 572 * @param buffer the bytes to append 573 * @param len the number of bytes to append 574 * @returns #FALSE if not enough memory. 575 */ 576dbus_bool_t 577_dbus_string_append_len (DBusString *str, 578 const char *buffer, 579 int len) 580{ 581 DBUS_STRING_PREAMBLE (str); 582 _dbus_assert (buffer != NULL); 583 _dbus_assert (len >= 0); 584 585 return append (real, buffer, len); 586} 587 588/** 589 * Appends a single byte to the string, returning #FALSE 590 * if not enough memory. 591 * 592 * @param str the string 593 * @param byte the byte to append 594 * @returns #TRUE on success 595 */ 596dbus_bool_t 597_dbus_string_append_byte (DBusString *str, 598 unsigned char byte) 599{ 600 DBUS_STRING_PREAMBLE (str); 601 602 if (!set_length (real, real->len + 1)) 603 return FALSE; 604 605 real->str[real->len-1] = byte; 606 607 return TRUE; 608} 609 610/** 611 * Appends a single Unicode character, encoding the character 612 * in UTF-8 format. 613 * 614 * @param str the string 615 * @param ch the Unicode character 616 */ 617dbus_bool_t 618_dbus_string_append_unichar (DBusString *str, 619 dbus_unichar_t ch) 620{ 621 int len; 622 int first; 623 int i; 624 char *out; 625 626 DBUS_STRING_PREAMBLE (str); 627 628 /* this code is from GLib but is pretty standard I think */ 629 630 len = 0; 631 632 if (ch < 0x80) 633 { 634 first = 0; 635 len = 1; 636 } 637 else if (ch < 0x800) 638 { 639 first = 0xc0; 640 len = 2; 641 } 642 else if (ch < 0x10000) 643 { 644 first = 0xe0; 645 len = 3; 646 } 647 else if (ch < 0x200000) 648 { 649 first = 0xf0; 650 len = 4; 651 } 652 else if (ch < 0x4000000) 653 { 654 first = 0xf8; 655 len = 5; 656 } 657 else 658 { 659 first = 0xfc; 660 len = 6; 661 } 662 663 if (!set_length (real, real->len + len)) 664 return FALSE; 665 666 out = real->str + (real->len - len); 667 668 for (i = len - 1; i > 0; --i) 669 { 670 out[i] = (ch & 0x3f) | 0x80; 671 ch >>= 6; 672 } 673 out[0] = ch | first; 674 675 return TRUE; 676} 677 678static void 679delete (DBusRealString *real, 680 int start, 681 int len) 682{ 683 if (len == 0) 684 return; 685 686 memmove (real->str + start, real->str + start + len, real->len - (start + len)); 687 real->len -= len; 688 real->str[real->len] = '\0'; 689} 690 691/** 692 * Deletes a segment of a DBusString with length len starting at 693 * start. (Hint: to clear an entire string, setting length to 0 694 * with _dbus_string_set_length() is easier.) 695 * 696 * @param str the DBusString 697 * @param start where to start deleting 698 * @param len the number of bytes to delete 699 */ 700void 701_dbus_string_delete (DBusString *str, 702 int start, 703 int len) 704{ 705 DBUS_STRING_PREAMBLE (str); 706 _dbus_assert (start >= 0); 707 _dbus_assert (len >= 0); 708 _dbus_assert ((start + len) <= real->len); 709 710 delete (real, start, len); 711} 712 713static dbus_bool_t 714open_gap (int len, 715 DBusRealString *dest, 716 int insert_at) 717{ 718 if (len == 0) 719 return TRUE; 720 721 if (!set_length (dest, dest->len + len)) 722 return FALSE; 723 724 memmove (dest->str + insert_at + len, 725 dest->str + insert_at, 726 dest->len - len - insert_at); 727 728 return TRUE; 729} 730 731static dbus_bool_t 732copy (DBusRealString *source, 733 int start, 734 int len, 735 DBusRealString *dest, 736 int insert_at) 737{ 738 if (!open_gap (len, dest, insert_at)) 739 return FALSE; 740 741 memcpy (dest->str + insert_at, 742 source->str + start, 743 len); 744 745 return TRUE; 746} 747 748/** 749 * Checks assertions for two strings we're copying a segment between, 750 * and declares real_source/real_dest variables. 751 * 752 * @param source the source string 753 * @param start the starting offset 754 * @param dest the dest string 755 * @param insert_at where the copied segment is inserted 756 */ 757#define DBUS_STRING_COPY_PREAMBLE(source, start, dest, insert_at) \ 758 DBusRealString *real_source = (DBusRealString*) source; \ 759 DBusRealString *real_dest = (DBusRealString*) dest; \ 760 _dbus_assert ((source) != (dest)); \ 761 DBUS_GENERIC_STRING_PREAMBLE (real_source); \ 762 DBUS_GENERIC_STRING_PREAMBLE (real_dest); \ 763 _dbus_assert (!real_source->constant); \ 764 _dbus_assert (!real_source->locked); \ 765 _dbus_assert (!real_dest->constant); \ 766 _dbus_assert (!real_dest->locked); \ 767 _dbus_assert ((start) >= 0); \ 768 _dbus_assert ((start) <= real_source->len); \ 769 _dbus_assert ((insert_at) >= 0); \ 770 _dbus_assert ((insert_at) <= real_dest->len) 771 772/** 773 * Moves the end of one string into another string. Both strings 774 * must be initialized, valid strings. 775 * 776 * @param source the source string 777 * @param start where to chop off the source string 778 * @param dest the destination string 779 * @param insert_at where to move the chopped-off part of source string 780 * @returns #FALSE if not enough memory 781 */ 782dbus_bool_t 783_dbus_string_move (DBusString *source, 784 int start, 785 DBusString *dest, 786 int insert_at) 787{ 788 DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at); 789 790 if (!copy (real_source, start, 791 real_source->len - start, 792 real_dest, 793 insert_at)) 794 return FALSE; 795 796 delete (real_source, start, 797 real_source->len - start); 798 799 return TRUE; 800} 801 802/** 803 * Like _dbus_string_move(), but does not delete the section 804 * of the source string that's copied to the dest string. 805 * 806 * @param source the source string 807 * @param start where to start copying the source string 808 * @param dest the destination string 809 * @param insert_at where to place the copied part of source string 810 * @returns #FALSE if not enough memory 811 */ 812dbus_bool_t 813_dbus_string_copy (const DBusString *source, 814 int start, 815 DBusString *dest, 816 int insert_at) 817{ 818 DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at); 819 820 return copy (real_source, start, 821 real_source->len - start, 822 real_dest, 823 insert_at); 824} 825 826/** 827 * Like _dbus_string_move(), but can move a segment from 828 * the middle of the source string. 829 * 830 * @param source the source string 831 * @param start first byte of source string to move 832 * @param len length of segment to move 833 * @param dest the destination string 834 * @param insert_at where to move the bytes from the source string 835 * @returns #FALSE if not enough memory 836 */ 837dbus_bool_t 838_dbus_string_move_len (DBusString *source, 839 int start, 840 int len, 841 DBusString *dest, 842 int insert_at) 843 844{ 845 DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at); 846 _dbus_assert (len >= 0); 847 _dbus_assert ((start + len) <= real_source->len); 848 849 if (!copy (real_source, start, len, 850 real_dest, 851 insert_at)) 852 return FALSE; 853 854 delete (real_source, start, 855 real_source->len - start); 856 857 return TRUE; 858} 859 860/** 861 * Like _dbus_string_copy(), but can copy a segment from the middle of 862 * the source string. 863 * 864 * @param source the source string 865 * @param start where to start copying the source string 866 * @param len length of segment to copy 867 * @param dest the destination string 868 * @param insert_at where to place the copied segment of source string 869 * @returns #FALSE if not enough memory 870 */ 871dbus_bool_t 872_dbus_string_copy_len (const DBusString *source, 873 int start, 874 int len, 875 DBusString *dest, 876 int insert_at) 877{ 878 DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at); 879 _dbus_assert (len >= 0); 880 _dbus_assert ((start + len) <= real_source->len); 881 882 return copy (real_source, start, len, 883 real_dest, 884 insert_at); 885} 886 887/* Unicode macros from GLib */ 888 889/** computes length and mask of a unicode character 890 * @param Char the char 891 * @param Mask the mask variable to assign to 892 * @param Len the length variable to assign to 893 */ 894#define UTF8_COMPUTE(Char, Mask, Len) \ 895 if (Char < 128) \ 896 { \ 897 Len = 1; \ 898 Mask = 0x7f; \ 899 } \ 900 else if ((Char & 0xe0) == 0xc0) \ 901 { \ 902 Len = 2; \ 903 Mask = 0x1f; \ 904 } \ 905 else if ((Char & 0xf0) == 0xe0) \ 906 { \ 907 Len = 3; \ 908 Mask = 0x0f; \ 909 } \ 910 else if ((Char & 0xf8) == 0xf0) \ 911 { \ 912 Len = 4; \ 913 Mask = 0x07; \ 914 } \ 915 else if ((Char & 0xfc) == 0xf8) \ 916 { \ 917 Len = 5; \ 918 Mask = 0x03; \ 919 } \ 920 else if ((Char & 0xfe) == 0xfc) \ 921 { \ 922 Len = 6; \ 923 Mask = 0x01; \ 924 } \ 925 else \ 926 Len = -1; 927 928/** 929 * computes length of a unicode character in UTF-8 930 * @param Char the char 931 */ 932#define UTF8_LENGTH(Char) \ 933 ((Char) < 0x80 ? 1 : \ 934 ((Char) < 0x800 ? 2 : \ 935 ((Char) < 0x10000 ? 3 : \ 936 ((Char) < 0x200000 ? 4 : \ 937 ((Char) < 0x4000000 ? 5 : 6))))) 938 939/** 940 * Gets a UTF-8 value. 941 * 942 * @param Result variable for extracted unicode char. 943 * @param Chars the bytes to decode 944 * @param Count counter variable 945 * @param Mask mask for this char 946 * @param Len length for this char in bytes 947 */ 948#define UTF8_GET(Result, Chars, Count, Mask, Len) \ 949 (Result) = (Chars)[0] & (Mask); \ 950 for ((Count) = 1; (Count) < (Len); ++(Count)) \ 951 { \ 952 if (((Chars)[(Count)] & 0xc0) != 0x80) \ 953 { \ 954 (Result) = -1; \ 955 break; \ 956 } \ 957 (Result) <<= 6; \ 958 (Result) |= ((Chars)[(Count)] & 0x3f); \ 959 } 960 961/** 962 * Check whether a unicode char is in a valid range. 963 * 964 * @param Char the character 965 */ 966#define UNICODE_VALID(Char) \ 967 ((Char) < 0x110000 && \ 968 ((Char) < 0xD800 || (Char) >= 0xE000) && \ 969 (Char) != 0xFFFE && (Char) != 0xFFFF) 970 971/** 972 * Gets a unicode character from a UTF-8 string. Does no validation; 973 * you must verify that the string is valid UTF-8 in advance and must 974 * pass in the start of a character. 975 * 976 * @param str the string 977 * @param start the start of the UTF-8 character. 978 * @param ch_return location to return the character 979 * @param end_return location to return the byte index of next character 980 * @returns #TRUE on success, #FALSE otherwise. 981 */ 982void 983_dbus_string_get_unichar (const DBusString *str, 984 int start, 985 dbus_unichar_t *ch_return, 986 int *end_return) 987{ 988 int i, mask, len; 989 dbus_unichar_t result; 990 unsigned char c; 991 unsigned char *p; 992 DBUS_CONST_STRING_PREAMBLE (str); 993 994 if (ch_return) 995 *ch_return = 0; 996 if (end_return) 997 *end_return = real->len; 998 999 mask = 0; 1000 p = real->str + start; 1001 c = *p; 1002 1003 UTF8_COMPUTE (c, mask, len); 1004 if (len == -1) 1005 return; 1006 UTF8_GET (result, p, i, mask, len); 1007 1008 if (result == (dbus_unichar_t)-1) 1009 return; 1010 1011 if (ch_return) 1012 *ch_return = result; 1013 if (end_return) 1014 *end_return = start + len; 1015} 1016 1017/** 1018 * Finds the given substring in the string, 1019 * returning #TRUE and filling in the byte index 1020 * where the substring was found, if it was found. 1021 * Returns #FALSE if the substring wasn't found. 1022 * Sets *start to the length of the string if the substring 1023 * is not found. 1024 * 1025 * @param str the string 1026 * @param start where to start looking 1027 * @param substr the substring 1028 * @param found return location for where it was found, or #NULL 1029 * @returns #TRUE if found 1030 */ 1031dbus_bool_t 1032_dbus_string_find (const DBusString *str, 1033 int start, 1034 const char *substr, 1035 int *found) 1036{ 1037 int i; 1038 DBUS_CONST_STRING_PREAMBLE (str); 1039 _dbus_assert (substr != NULL); 1040 _dbus_assert (start <= real->len); 1041 1042 /* we always "find" an empty string */ 1043 if (*substr == '\0') 1044 { 1045 if (found) 1046 *found = 0; 1047 return TRUE; 1048 } 1049 1050 i = start; 1051 while (i < real->len) 1052 { 1053 if (real->str[i] == substr[0]) 1054 { 1055 int j = i + 1; 1056 1057 while (j < real->len) 1058 { 1059 if (substr[j - i] == '\0') 1060 break; 1061 else if (real->str[j] != substr[j - i]) 1062 break; 1063 1064 ++j; 1065 } 1066 1067 if (substr[j - i] == '\0') 1068 { 1069 if (found) 1070 *found = i; 1071 return TRUE; 1072 } 1073 } 1074 1075 ++i; 1076 } 1077 1078 if (found) 1079 *found = real->len; 1080 1081 return FALSE; 1082} 1083 1084/** 1085 * Finds a blank (space or tab) in the string. Returns #TRUE 1086 * if found, #FALSE otherwise. If a blank is not found sets 1087 * *found to the length of the string. 1088 * 1089 * @param str the string 1090 * @param start byte index to start looking 1091 * @param found place to store the location of the first blank 1092 * @returns #TRUE if a blank was found 1093 */ 1094dbus_bool_t 1095_dbus_string_find_blank (const DBusString *str, 1096 int start, 1097 int *found) 1098{ 1099 int i; 1100 DBUS_CONST_STRING_PREAMBLE (str); 1101 _dbus_assert (start <= real->len); 1102 1103 i = start; 1104 while (i < real->len) 1105 { 1106 if (real->str[i] == ' ' || 1107 real->str[i] == '\t') 1108 { 1109 if (found) 1110 *found = i; 1111 return TRUE; 1112 } 1113 1114 ++i; 1115 } 1116 1117 if (found) 1118 *found = real->len; 1119 1120 return FALSE; 1121} 1122 1123/** 1124 * Skips blanks from start, storing the first non-blank in *end 1125 * 1126 * @param str the string 1127 * @param start where to start 1128 * @param end where to store the first non-blank byte index 1129 */ 1130void 1131_dbus_string_skip_blank (const DBusString *str, 1132 int start, 1133 int *end) 1134{ 1135 int i; 1136 DBUS_CONST_STRING_PREAMBLE (str); 1137 _dbus_assert (start <= real->len); 1138 1139 i = start; 1140 while (i < real->len) 1141 { 1142 if (!(real->str[i] == ' ' || 1143 real->str[i] == '\t')) 1144 break; 1145 1146 ++i; 1147 } 1148 1149 _dbus_assert (i == real->len || !(real->str[i] == ' ' || 1150 real->str[i] == '\t')); 1151 1152 if (end) 1153 *end = i; 1154} 1155 1156/** 1157 * Tests two DBusString for equality. 1158 * 1159 * @param a first string 1160 * @param b second string 1161 * @returns #TRUE if equal 1162 */ 1163dbus_bool_t 1164_dbus_string_equal (const DBusString *a, 1165 const DBusString *b) 1166{ 1167 const unsigned char *ap; 1168 const unsigned char *bp; 1169 const unsigned char *a_end; 1170 const DBusRealString *real_a = (const DBusRealString*) a; 1171 const DBusRealString *real_b = (const DBusRealString*) b; 1172 DBUS_GENERIC_STRING_PREAMBLE (real_a); 1173 DBUS_GENERIC_STRING_PREAMBLE (real_b); 1174 1175 if (real_a->len != real_b->len) 1176 return FALSE; 1177 1178 ap = real_a->str; 1179 bp = real_b->str; 1180 a_end = real_a->str + real_a->len; 1181 while (ap != a_end) 1182 { 1183 if (*ap != *bp) 1184 return FALSE; 1185 1186 ++ap; 1187 ++bp; 1188 } 1189 1190 return TRUE; 1191} 1192 1193/** 1194 * Checks whether a string is equal to a C string. 1195 * 1196 * @param a the string 1197 * @param c_str the C string 1198 * @returns #TRUE if equal 1199 */ 1200dbus_bool_t 1201_dbus_string_equal_c_str (const DBusString *a, 1202 const char *c_str) 1203{ 1204 const unsigned char *ap; 1205 const unsigned char *bp; 1206 const unsigned char *a_end; 1207 const DBusRealString *real_a = (const DBusRealString*) a; 1208 DBUS_GENERIC_STRING_PREAMBLE (real_a); 1209 1210 ap = real_a->str; 1211 bp = (const unsigned char*) c_str; 1212 a_end = real_a->str + real_a->len; 1213 while (ap != a_end && *bp) 1214 { 1215 if (*ap != *bp) 1216 return FALSE; 1217 1218 ++ap; 1219 ++bp; 1220 } 1221 1222 if (*ap && *bp == '\0') 1223 return FALSE; 1224 else if (ap == a_end && *bp) 1225 return FALSE; 1226 1227 return TRUE; 1228} 1229 1230static const signed char base64_table[] = { 1231 /* 0 */ 'A', 1232 /* 1 */ 'B', 1233 /* 2 */ 'C', 1234 /* 3 */ 'D', 1235 /* 4 */ 'E', 1236 /* 5 */ 'F', 1237 /* 6 */ 'G', 1238 /* 7 */ 'H', 1239 /* 8 */ 'I', 1240 /* 9 */ 'J', 1241 /* 10 */ 'K', 1242 /* 11 */ 'L', 1243 /* 12 */ 'M', 1244 /* 13 */ 'N', 1245 /* 14 */ 'O', 1246 /* 15 */ 'P', 1247 /* 16 */ 'Q', 1248 /* 17 */ 'R', 1249 /* 18 */ 'S', 1250 /* 19 */ 'T', 1251 /* 20 */ 'U', 1252 /* 21 */ 'V', 1253 /* 22 */ 'W', 1254 /* 23 */ 'X', 1255 /* 24 */ 'Y', 1256 /* 25 */ 'Z', 1257 /* 26 */ 'a', 1258 /* 27 */ 'b', 1259 /* 28 */ 'c', 1260 /* 29 */ 'd', 1261 /* 30 */ 'e', 1262 /* 31 */ 'f', 1263 /* 32 */ 'g', 1264 /* 33 */ 'h', 1265 /* 34 */ 'i', 1266 /* 35 */ 'j', 1267 /* 36 */ 'k', 1268 /* 37 */ 'l', 1269 /* 38 */ 'm', 1270 /* 39 */ 'n', 1271 /* 40 */ 'o', 1272 /* 41 */ 'p', 1273 /* 42 */ 'q', 1274 /* 43 */ 'r', 1275 /* 44 */ 's', 1276 /* 45 */ 't', 1277 /* 46 */ 'u', 1278 /* 47 */ 'v', 1279 /* 48 */ 'w', 1280 /* 49 */ 'x', 1281 /* 50 */ 'y', 1282 /* 51 */ 'z', 1283 /* 52 */ '0', 1284 /* 53 */ '1', 1285 /* 54 */ '2', 1286 /* 55 */ '3', 1287 /* 56 */ '4', 1288 /* 57 */ '5', 1289 /* 58 */ '6', 1290 /* 59 */ '7', 1291 /* 60 */ '8', 1292 /* 61 */ '9', 1293 /* 62 */ '+', 1294 /* 63 */ '/' 1295}; 1296 1297/** The minimum char that's a valid char in Base64-encoded text */ 1298#define UNBASE64_MIN_CHAR (43) 1299/** The maximum char that's a valid char in Base64-encoded text */ 1300#define UNBASE64_MAX_CHAR (122) 1301/** Must subtract this from a char's integer value before offsetting 1302 * into unbase64_table 1303 */ 1304#define UNBASE64_TABLE_OFFSET UNBASE64_MIN_CHAR 1305static const signed char unbase64_table[] = { 1306 /* 43 + */ 62, 1307 /* 44 , */ -1, 1308 /* 45 - */ -1, 1309 /* 46 . */ -1, 1310 /* 47 / */ 63, 1311 /* 48 0 */ 52, 1312 /* 49 1 */ 53, 1313 /* 50 2 */ 54, 1314 /* 51 3 */ 55, 1315 /* 52 4 */ 56, 1316 /* 53 5 */ 57, 1317 /* 54 6 */ 58, 1318 /* 55 7 */ 59, 1319 /* 56 8 */ 60, 1320 /* 57 9 */ 61, 1321 /* 58 : */ -1, 1322 /* 59 ; */ -1, 1323 /* 60 < */ -1, 1324 /* 61 = */ -1, 1325 /* 62 > */ -1, 1326 /* 63 ? */ -1, 1327 /* 64 @ */ -1, 1328 /* 65 A */ 0, 1329 /* 66 B */ 1, 1330 /* 67 C */ 2, 1331 /* 68 D */ 3, 1332 /* 69 E */ 4, 1333 /* 70 F */ 5, 1334 /* 71 G */ 6, 1335 /* 72 H */ 7, 1336 /* 73 I */ 8, 1337 /* 74 J */ 9, 1338 /* 75 K */ 10, 1339 /* 76 L */ 11, 1340 /* 77 M */ 12, 1341 /* 78 N */ 13, 1342 /* 79 O */ 14, 1343 /* 80 P */ 15, 1344 /* 81 Q */ 16, 1345 /* 82 R */ 17, 1346 /* 83 S */ 18, 1347 /* 84 T */ 19, 1348 /* 85 U */ 20, 1349 /* 86 V */ 21, 1350 /* 87 W */ 22, 1351 /* 88 X */ 23, 1352 /* 89 Y */ 24, 1353 /* 90 Z */ 25, 1354 /* 91 [ */ -1, 1355 /* 92 \ */ -1, 1356 /* 93 ] */ -1, 1357 /* 94 ^ */ -1, 1358 /* 95 _ */ -1, 1359 /* 96 ` */ -1, 1360 /* 97 a */ 26, 1361 /* 98 b */ 27, 1362 /* 99 c */ 28, 1363 /* 100 d */ 29, 1364 /* 101 e */ 30, 1365 /* 102 f */ 31, 1366 /* 103 g */ 32, 1367 /* 104 h */ 33, 1368 /* 105 i */ 34, 1369 /* 106 j */ 35, 1370 /* 107 k */ 36, 1371 /* 108 l */ 37, 1372 /* 109 m */ 38, 1373 /* 110 n */ 39, 1374 /* 111 o */ 40, 1375 /* 112 p */ 41, 1376 /* 113 q */ 42, 1377 /* 114 r */ 43, 1378 /* 115 s */ 44, 1379 /* 116 t */ 45, 1380 /* 117 u */ 46, 1381 /* 118 v */ 47, 1382 /* 119 w */ 48, 1383 /* 120 x */ 49, 1384 /* 121 y */ 50, 1385 /* 122 z */ 51 1386}; 1387 1388/** 1389 * Encodes a string using Base64, as documented in RFC 2045. 1390 * 1391 * @param source the string to encode 1392 * @param start byte index to start encoding 1393 * @param dest string where encoded data should be placed 1394 * @param insert_at where to place encoded data 1395 * @returns #TRUE if encoding was successful, #FALSE if no memory etc. 1396 */ 1397dbus_bool_t 1398_dbus_string_base64_encode (const DBusString *source, 1399 int start, 1400 DBusString *dest, 1401 int insert_at) 1402{ 1403 int source_len; 1404 int dest_len; 1405 const unsigned char *s; 1406 unsigned char *d; 1407 const unsigned char *triplet_end; 1408 const unsigned char *final_end; 1409 DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at); 1410 1411 /* For each 24 bits (3 bytes) of input, we have 4 chars of 1412 * output. 1413 */ 1414 source_len = real_source->len - start; 1415 dest_len = (source_len / 3) * 4; 1416 if (source_len % 3 != 0) 1417 dest_len += 4; 1418 1419 if (source_len == 0) 1420 return TRUE; 1421 1422 if (!open_gap (dest_len, real_dest, insert_at)) 1423 return FALSE; 1424 1425 d = real_dest->str + insert_at; 1426 s = real_source->str + start; 1427 final_end = real_source->str + (start + source_len); 1428 triplet_end = final_end - (source_len % 3); 1429 _dbus_assert (triplet_end <= final_end); 1430 _dbus_assert ((final_end - triplet_end) < 3); 1431 1432#define ENCODE_64(v) (base64_table[ (unsigned char) (v) ]) 1433#define SIX_BITS_MASK (0x3f) 1434 _dbus_assert (SIX_BITS_MASK < _DBUS_N_ELEMENTS (base64_table)); 1435 1436 while (s != triplet_end) 1437 { 1438 unsigned int triplet; 1439 1440 triplet = s[0] | (s[1] << 8) | (s[2] << 16); 1441 1442 /* Encode each 6 bits */ 1443 1444 *d++ = ENCODE_64 (triplet >> 18); 1445 *d++ = ENCODE_64 ((triplet >> 12) & SIX_BITS_MASK); 1446 *d++ = ENCODE_64 ((triplet >> 6) & SIX_BITS_MASK); 1447 *d++ = ENCODE_64 (triplet & SIX_BITS_MASK); 1448 1449 s += 3; 1450 } 1451 1452 switch (final_end - triplet_end) 1453 { 1454 case 2: 1455 { 1456 unsigned int doublet; 1457 1458 doublet = s[0] | (s[1] << 8); 1459 1460 *d++ = ENCODE_64 (doublet >> 12); 1461 *d++ = ENCODE_64 ((doublet >> 6) & SIX_BITS_MASK); 1462 *d++ = ENCODE_64 (doublet & SIX_BITS_MASK); 1463 *d++ = '='; 1464 } 1465 break; 1466 case 1: 1467 { 1468 unsigned int singlet; 1469 1470 singlet = s[0]; 1471 1472 *d++ = ENCODE_64 ((singlet >> 6) & SIX_BITS_MASK); 1473 *d++ = ENCODE_64 (singlet & SIX_BITS_MASK); 1474 *d++ = '='; 1475 *d++ = '='; 1476 } 1477 break; 1478 case 0: 1479 break; 1480 } 1481 1482 _dbus_assert (d == (real_dest->str + (insert_at + dest_len))); 1483 1484 return TRUE; 1485} 1486 1487 1488/** 1489 * Decodes a string from Base64, as documented in RFC 2045. 1490 * 1491 * @param source the string to decode 1492 * @param start byte index to start decode 1493 * @param dest string where decoded data should be placed 1494 * @param insert_at where to place decoded data 1495 * @returns #TRUE if decoding was successful, #FALSE if no memory etc. 1496 */ 1497dbus_bool_t 1498_dbus_string_base64_decode (const DBusString *source, 1499 int start, 1500 DBusString *dest, 1501 int insert_at) 1502{ 1503 int source_len; 1504 const char *s; 1505 const char *end; 1506 DBusString result; 1507 unsigned int triplet = 0; 1508 int sextet_count; 1509 int pad_count; 1510 DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at); 1511 1512 source_len = real_source->len - start; 1513 s = real_source->str + start; 1514 end = real_source->str + source_len; 1515 1516 if (source_len == 0) 1517 return TRUE; 1518 1519 if (!_dbus_string_init (&result, _DBUS_INT_MAX)) 1520 return FALSE; 1521 1522 pad_count = 0; 1523 sextet_count = 0; 1524 while (s != end) 1525 { 1526 /* The idea is to just skip anything that isn't 1527 * a base64 char - it's allowed to have whitespace, 1528 * newlines, etc. in here. We also ignore trailing 1529 * base64 chars, though that's suspicious. 1530 */ 1531 1532 if (*s >= UNBASE64_MIN_CHAR && 1533 *s <= UNBASE64_MAX_CHAR) 1534 { 1535 if (*s == '=') 1536 { 1537 /* '=' is padding, doesn't represent additional data 1538 * but does increment our count. 1539 */ 1540 pad_count += 1; 1541 sextet_count += 1; 1542 } 1543 else 1544 { 1545 int val; 1546 1547 val = unbase64_table[(*s) - UNBASE64_TABLE_OFFSET]; 1548 1549 if (val >= 0) 1550 { 1551 triplet <<= 6; 1552 triplet |= (unsigned int) val; 1553 sextet_count += 1; 1554 } 1555 } 1556 1557 if (sextet_count == 4) 1558 { 1559 /* no pad = 3 bytes, 1 pad = 2 bytes, 2 pad = 1 byte */ 1560 1561 _dbus_string_append_byte (&result, 1562 triplet & 0xff); 1563 1564 if (pad_count < 2) 1565 _dbus_string_append_byte (&result, 1566 (triplet >> 8) & 0xff); 1567 1568 if (pad_count < 1) 1569 _dbus_string_append_byte (&result, 1570 triplet >> 16); 1571 1572 sextet_count = 0; 1573 pad_count = 0; 1574 triplet = 0; 1575 } 1576 } 1577 1578 ++s; 1579 } 1580 1581 if (!_dbus_string_move (&result, 0, dest, insert_at)) 1582 { 1583 _dbus_string_free (&result); 1584 return FALSE; 1585 } 1586 1587 _dbus_string_free (&result); 1588 1589 return TRUE; 1590} 1591 1592/** 1593 * Checks that the given range of the string 1594 * is valid ASCII. If the given range is not contained 1595 * in the string, returns #FALSE. 1596 * 1597 * @param str the string 1598 * @param start first byte index to check 1599 * @param len number of bytes to check 1600 * @returns #TRUE if the byte range exists and is all valid ASCII 1601 */ 1602dbus_bool_t 1603_dbus_string_validate_ascii (const DBusString *str, 1604 int start, 1605 int len) 1606{ 1607 const unsigned char *s; 1608 const unsigned char *end; 1609 DBUS_CONST_STRING_PREAMBLE (str); 1610 _dbus_assert (start >= 0); 1611 _dbus_assert (len >= 0); 1612 1613 if ((start + len) > real->len) 1614 return FALSE; 1615 1616 s = real->str + start; 1617 end = s + len; 1618 while (s != end) 1619 { 1620 if (*s == '\0' || 1621 ((*s & ~0x7f) != 0)) 1622 return FALSE; 1623 1624 ++s; 1625 } 1626 1627 return TRUE; 1628} 1629 1630/** @} */ 1631 1632#ifdef DBUS_BUILD_TESTS 1633#include "dbus-test.h" 1634#include <stdio.h> 1635 1636static void 1637test_max_len (DBusString *str, 1638 int max_len) 1639{ 1640 if (max_len > 0) 1641 { 1642 if (!_dbus_string_set_length (str, max_len - 1)) 1643 _dbus_assert_not_reached ("setting len to one less than max should have worked"); 1644 } 1645 1646 if (!_dbus_string_set_length (str, max_len)) 1647 _dbus_assert_not_reached ("setting len to max len should have worked"); 1648 1649 if (_dbus_string_set_length (str, max_len + 1)) 1650 _dbus_assert_not_reached ("setting len to one more than max len should not have worked"); 1651 1652 if (!_dbus_string_set_length (str, 0)) 1653 _dbus_assert_not_reached ("setting len to zero should have worked"); 1654} 1655 1656static void 1657test_base64_roundtrip (const unsigned char *data, 1658 int len) 1659{ 1660 DBusString orig; 1661 DBusString encoded; 1662 DBusString decoded; 1663 1664 if (len < 0) 1665 len = strlen (data); 1666 1667 if (!_dbus_string_init (&orig, _DBUS_INT_MAX)) 1668 _dbus_assert_not_reached ("could not init string"); 1669 1670 if (!_dbus_string_init (&encoded, _DBUS_INT_MAX)) 1671 _dbus_assert_not_reached ("could not init string"); 1672 1673 if (!_dbus_string_init (&decoded, _DBUS_INT_MAX)) 1674 _dbus_assert_not_reached ("could not init string"); 1675 1676 if (!_dbus_string_append_len (&orig, data, len)) 1677 _dbus_assert_not_reached ("couldn't append orig data"); 1678 1679 if (!_dbus_string_base64_encode (&orig, 0, &encoded, 0)) 1680 _dbus_assert_not_reached ("could not encode"); 1681 1682 if (!_dbus_string_base64_decode (&encoded, 0, &decoded, 0)) 1683 _dbus_assert_not_reached ("could not decode"); 1684 1685 if (!_dbus_string_equal (&orig, &decoded)) 1686 { 1687 const char *s; 1688 1689 printf ("Original string %d bytes encoded %d bytes decoded %d bytes\n", 1690 _dbus_string_get_length (&orig), 1691 _dbus_string_get_length (&encoded), 1692 _dbus_string_get_length (&decoded)); 1693 printf ("Original: %s\n", data); 1694 _dbus_string_get_const_data (&decoded, &s); 1695 printf ("Decoded: %s\n", s); 1696 _dbus_assert_not_reached ("original string not the same as string decoded from base64"); 1697 } 1698 1699 _dbus_string_free (&orig); 1700 _dbus_string_free (&encoded); 1701 _dbus_string_free (&decoded); 1702} 1703 1704/** 1705 * @ingroup DBusStringInternals 1706 * Unit test for DBusString. 1707 * 1708 * @todo Need to write tests for _dbus_string_copy() and 1709 * _dbus_string_move() moving to/from each of start/middle/end of a 1710 * string. 1711 * 1712 * @returns #TRUE on success. 1713 */ 1714dbus_bool_t 1715_dbus_string_test (void) 1716{ 1717 DBusString str; 1718 DBusString other; 1719 int i, end; 1720 long v; 1721 double d; 1722 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 }; 1723 char *s; 1724 dbus_unichar_t ch; 1725 1726 i = 0; 1727 while (i < _DBUS_N_ELEMENTS (lens)) 1728 { 1729 if (!_dbus_string_init (&str, lens[i])) 1730 _dbus_assert_not_reached ("failed to init string"); 1731 1732 test_max_len (&str, lens[i]); 1733 _dbus_string_free (&str); 1734 1735 ++i; 1736 } 1737 1738 /* Test shortening and setting length */ 1739 i = 0; 1740 while (i < _DBUS_N_ELEMENTS (lens)) 1741 { 1742 int j; 1743 1744 if (!_dbus_string_init (&str, lens[i])) 1745 _dbus_assert_not_reached ("failed to init string"); 1746 1747 if (!_dbus_string_set_length (&str, lens[i])) 1748 _dbus_assert_not_reached ("failed to set string length"); 1749 1750 j = lens[i]; 1751 while (j > 0) 1752 { 1753 _dbus_assert (_dbus_string_get_length (&str) == j); 1754 if (j > 0) 1755 { 1756 _dbus_string_shorten (&str, 1); 1757 _dbus_assert (_dbus_string_get_length (&str) == (j - 1)); 1758 } 1759 --j; 1760 } 1761 1762 _dbus_string_free (&str); 1763 1764 ++i; 1765 } 1766 1767 /* Test appending data */ 1768 if (!_dbus_string_init (&str, _DBUS_INT_MAX)) 1769 _dbus_assert_not_reached ("failed to init string"); 1770 1771 i = 0; 1772 while (i < 10) 1773 { 1774 if (!_dbus_string_append (&str, "a")) 1775 _dbus_assert_not_reached ("failed to append string to string\n"); 1776 1777 _dbus_assert (_dbus_string_get_length (&str) == i * 2 + 1); 1778 1779 if (!_dbus_string_append_byte (&str, 'b')) 1780 _dbus_assert_not_reached ("failed to append byte to string\n"); 1781 1782 _dbus_assert (_dbus_string_get_length (&str) == i * 2 + 2); 1783 1784 ++i; 1785 } 1786 1787 _dbus_string_free (&str); 1788 1789 /* Check steal_data */ 1790 1791 if (!_dbus_string_init (&str, _DBUS_INT_MAX)) 1792 _dbus_assert_not_reached ("failed to init string"); 1793 1794 if (!_dbus_string_append (&str, "Hello World")) 1795 _dbus_assert_not_reached ("could not append to string"); 1796 1797 i = _dbus_string_get_length (&str); 1798 1799 if (!_dbus_string_steal_data (&str, &s)) 1800 _dbus_assert_not_reached ("failed to steal data"); 1801 1802 _dbus_assert (_dbus_string_get_length (&str) == 0); 1803 _dbus_assert (((int)strlen (s)) == i); 1804 1805 dbus_free (s); 1806 1807 /* Check move */ 1808 1809 if (!_dbus_string_append (&str, "Hello World")) 1810 _dbus_assert_not_reached ("could not append to string"); 1811 1812 i = _dbus_string_get_length (&str); 1813 1814 if (!_dbus_string_init (&other, _DBUS_INT_MAX)) 1815 _dbus_assert_not_reached ("could not init string"); 1816 1817 if (!_dbus_string_move (&str, 0, &other, 0)) 1818 _dbus_assert_not_reached ("could not move"); 1819 1820 _dbus_assert (_dbus_string_get_length (&str) == 0); 1821 _dbus_assert (_dbus_string_get_length (&other) == i); 1822 1823 if (!_dbus_string_append (&str, "Hello World")) 1824 _dbus_assert_not_reached ("could not append to string"); 1825 1826 if (!_dbus_string_move (&str, 0, &other, _dbus_string_get_length (&other))) 1827 _dbus_assert_not_reached ("could not move"); 1828 1829 _dbus_assert (_dbus_string_get_length (&str) == 0); 1830 _dbus_assert (_dbus_string_get_length (&other) == i * 2); 1831 1832 if (!_dbus_string_append (&str, "Hello World")) 1833 _dbus_assert_not_reached ("could not append to string"); 1834 1835 if (!_dbus_string_move (&str, 0, &other, _dbus_string_get_length (&other) / 2)) 1836 _dbus_assert_not_reached ("could not move"); 1837 1838 _dbus_assert (_dbus_string_get_length (&str) == 0); 1839 _dbus_assert (_dbus_string_get_length (&other) == i * 3); 1840 1841 _dbus_string_free (&other); 1842 1843 /* Check copy */ 1844 1845 if (!_dbus_string_append (&str, "Hello World")) 1846 _dbus_assert_not_reached ("could not append to string"); 1847 1848 i = _dbus_string_get_length (&str); 1849 1850 if (!_dbus_string_init (&other, _DBUS_INT_MAX)) 1851 _dbus_assert_not_reached ("could not init string"); 1852 1853 if (!_dbus_string_copy (&str, 0, &other, 0)) 1854 _dbus_assert_not_reached ("could not copy"); 1855 1856 _dbus_assert (_dbus_string_get_length (&str) == i); 1857 _dbus_assert (_dbus_string_get_length (&other) == i); 1858 1859 if (!_dbus_string_copy (&str, 0, &other, _dbus_string_get_length (&other))) 1860 _dbus_assert_not_reached ("could not copy"); 1861 1862 _dbus_assert (_dbus_string_get_length (&str) == i); 1863 _dbus_assert (_dbus_string_get_length (&other) == i * 2); 1864 _dbus_assert (_dbus_string_equal_c_str (&other, 1865 "Hello WorldHello World")); 1866 1867 if (!_dbus_string_copy (&str, 0, &other, _dbus_string_get_length (&other) / 2)) 1868 _dbus_assert_not_reached ("could not copy"); 1869 1870 _dbus_assert (_dbus_string_get_length (&str) == i); 1871 _dbus_assert (_dbus_string_get_length (&other) == i * 3); 1872 _dbus_assert (_dbus_string_equal_c_str (&other, 1873 "Hello WorldHello WorldHello World")); 1874 1875 _dbus_string_free (&str); 1876 _dbus_string_free (&other); 1877 1878 /* Check append/get unichar */ 1879 1880 if (!_dbus_string_init (&str, _DBUS_INT_MAX)) 1881 _dbus_assert_not_reached ("failed to init string"); 1882 1883 ch = 0; 1884 if (!_dbus_string_append_unichar (&str, 0xfffc)) 1885 _dbus_assert_not_reached ("failed to append unichar"); 1886 1887 _dbus_string_get_unichar (&str, 0, &ch, &i); 1888 1889 _dbus_assert (ch == 0xfffc); 1890 _dbus_assert (i == _dbus_string_get_length (&str)); 1891 1892 _dbus_string_free (&str); 1893 1894 /* Check append/parse int/double */ 1895 1896 if (!_dbus_string_init (&str, _DBUS_INT_MAX)) 1897 _dbus_assert_not_reached ("failed to init string"); 1898 1899 if (!_dbus_string_append_int (&str, 27)) 1900 _dbus_assert_not_reached ("failed to append int"); 1901 1902 i = _dbus_string_get_length (&str); 1903 1904 if (!_dbus_string_parse_int (&str, 0, &v, &end)) 1905 _dbus_assert_not_reached ("failed to parse int"); 1906 1907 _dbus_assert (v == 27); 1908 _dbus_assert (end == i); 1909 1910 _dbus_string_free (&str); 1911 1912 if (!_dbus_string_init (&str, _DBUS_INT_MAX)) 1913 _dbus_assert_not_reached ("failed to init string"); 1914 1915 if (!_dbus_string_append_double (&str, 50.3)) 1916 _dbus_assert_not_reached ("failed to append float"); 1917 1918 i = _dbus_string_get_length (&str); 1919 1920 if (!_dbus_string_parse_double (&str, 0, &d, &end)) 1921 _dbus_assert_not_reached ("failed to parse float"); 1922 1923 _dbus_assert (d > (50.3 - 1e-6) && d < (50.3 + 1e-6)); 1924 _dbus_assert (end == i); 1925 1926 _dbus_string_free (&str); 1927 1928 /* Test find */ 1929 if (!_dbus_string_init (&str, _DBUS_INT_MAX)) 1930 _dbus_assert_not_reached ("failed to init string"); 1931 1932 if (!_dbus_string_append (&str, "Hello")) 1933 _dbus_assert_not_reached ("couldn't append to string"); 1934 1935 if (!_dbus_string_find (&str, 0, "He", &i)) 1936 _dbus_assert_not_reached ("didn't find 'He'"); 1937 _dbus_assert (i == 0); 1938 1939 if (!_dbus_string_find (&str, 0, "ello", &i)) 1940 _dbus_assert_not_reached ("didn't find 'ello'"); 1941 _dbus_assert (i == 1); 1942 1943 if (!_dbus_string_find (&str, 0, "lo", &i)) 1944 _dbus_assert_not_reached ("didn't find 'lo'"); 1945 _dbus_assert (i == 3); 1946 1947 if (!_dbus_string_find (&str, 2, "lo", &i)) 1948 _dbus_assert_not_reached ("didn't find 'lo'"); 1949 _dbus_assert (i == 3); 1950 1951 if (_dbus_string_find (&str, 4, "lo", &i)) 1952 _dbus_assert_not_reached ("did find 'lo'"); 1953 1954 if (!_dbus_string_find (&str, 0, "l", &i)) 1955 _dbus_assert_not_reached ("didn't find 'l'"); 1956 _dbus_assert (i == 2); 1957 1958 if (!_dbus_string_find (&str, 0, "H", &i)) 1959 _dbus_assert_not_reached ("didn't find 'H'"); 1960 _dbus_assert (i == 0); 1961 1962 if (!_dbus_string_find (&str, 0, "", &i)) 1963 _dbus_assert_not_reached ("didn't find ''"); 1964 _dbus_assert (i == 0); 1965 1966 if (_dbus_string_find (&str, 0, "Hello!", NULL)) 1967 _dbus_assert_not_reached ("Did find 'Hello!'"); 1968 1969 if (_dbus_string_find (&str, 0, "Oh, Hello", NULL)) 1970 _dbus_assert_not_reached ("Did find 'Oh, Hello'"); 1971 1972 if (_dbus_string_find (&str, 0, "ill", NULL)) 1973 _dbus_assert_not_reached ("Did find 'ill'"); 1974 1975 if (_dbus_string_find (&str, 0, "q", NULL)) 1976 _dbus_assert_not_reached ("Did find 'q'"); 1977 1978 _dbus_string_free (&str); 1979 1980 /* Base 64 */ 1981 test_base64_roundtrip ("Hello this is a string\n", -1); 1982 test_base64_roundtrip ("Hello this is a string\n1", -1); 1983 test_base64_roundtrip ("Hello this is a string\n12", -1); 1984 test_base64_roundtrip ("Hello this is a string\n123", -1); 1985 test_base64_roundtrip ("Hello this is a string\n1234", -1); 1986 test_base64_roundtrip ("Hello this is a string\n12345", -1); 1987 test_base64_roundtrip ("", 0); 1988 test_base64_roundtrip ("1", 1); 1989 test_base64_roundtrip ("12", 2); 1990 test_base64_roundtrip ("123", 3); 1991 test_base64_roundtrip ("1234", 4); 1992 test_base64_roundtrip ("12345", 5); 1993 test_base64_roundtrip ("", 1); 1994 test_base64_roundtrip ("1", 2); 1995 test_base64_roundtrip ("12", 3); 1996 test_base64_roundtrip ("123", 4); 1997 test_base64_roundtrip ("1234", 5); 1998 test_base64_roundtrip ("12345", 6); 1999 { 2000 unsigned char buf[512]; 2001 i = 0; 2002 while (i < _DBUS_N_ELEMENTS (buf)) 2003 { 2004 buf[i] = i; 2005 ++i; 2006 } 2007 i = 0; 2008 while (i < _DBUS_N_ELEMENTS (buf)) 2009 { 2010 test_base64_roundtrip (buf, i); 2011 ++i; 2012 } 2013 } 2014 2015 return TRUE; 2016} 2017 2018#endif /* DBUS_BUILD_TESTS */ 2019