Main Page | Modules | Data Structures | File List | Data Fields | Related Pages

dbus-string.c

00001 /* -*- mode: C; c-file-style: "gnu" -*- */ 00002 /* dbus-string.c String utility class (internal to D-BUS implementation) 00003 * 00004 * Copyright (C) 2002, 2003 Red Hat, Inc. 00005 * 00006 * Licensed under the Academic Free License version 2.1 00007 * 00008 * This program is free software; you can redistribute it and/or modify 00009 * it under the terms of the GNU General Public License as published by 00010 * the Free Software Foundation; either version 2 of the License, or 00011 * (at your option) any later version. 00012 * 00013 * This program is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 * GNU General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU General Public License 00019 * along with this program; if not, write to the Free Software 00020 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00021 * 00022 */ 00023 00024 #include "dbus-internals.h" 00025 #include "dbus-string.h" 00026 /* we allow a system header here, for speed/convenience */ 00027 #include <string.h> 00028 /* for vsnprintf */ 00029 #include <stdio.h> 00030 #include "dbus-marshal.h" 00031 #define DBUS_CAN_USE_DBUS_STRING_PRIVATE 1 00032 #include "dbus-string-private.h" 00033 #include "dbus-protocol.h" 00034 /* for DBUS_VA_COPY */ 00035 #include "dbus-sysdeps.h" 00036 00079 #define ALLOCATION_PADDING 8 00080 00085 #define MAX_MAX_LENGTH (_DBUS_INT_MAX - ALLOCATION_PADDING) 00086 00092 #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) 00093 00100 #define DBUS_STRING_PREAMBLE(str) DBusRealString *real = (DBusRealString*) str; \ 00101 DBUS_GENERIC_STRING_PREAMBLE (real); \ 00102 _dbus_assert (!(real)->constant); \ 00103 _dbus_assert (!(real)->locked) 00104 00112 #define DBUS_LOCKED_STRING_PREAMBLE(str) DBusRealString *real = (DBusRealString*) str; \ 00113 DBUS_GENERIC_STRING_PREAMBLE (real); \ 00114 _dbus_assert (!(real)->constant) 00115 00121 #define DBUS_CONST_STRING_PREAMBLE(str) const DBusRealString *real = (DBusRealString*) str; \ 00122 DBUS_GENERIC_STRING_PREAMBLE (real) 00123 00131 static void 00132 fixup_alignment (DBusRealString *real) 00133 { 00134 char *aligned; 00135 char *real_block; 00136 unsigned int old_align_offset; 00137 00138 /* we have to have extra space in real->allocated for the align offset and nul byte */ 00139 _dbus_assert (real->len <= real->allocated - ALLOCATION_PADDING); 00140 00141 old_align_offset = real->align_offset; 00142 real_block = real->str - old_align_offset; 00143 00144 aligned = _DBUS_ALIGN_ADDRESS (real_block, 8); 00145 00146 real->align_offset = aligned - real_block; 00147 real->str = aligned; 00148 00149 if (old_align_offset != real->align_offset) 00150 { 00151 /* Here comes the suck */ 00152 memmove (real_block + real->align_offset, 00153 real_block + old_align_offset, 00154 real->len + 1); 00155 } 00156 00157 _dbus_assert (real->align_offset < 8); 00158 _dbus_assert (_DBUS_ALIGN_ADDRESS (real->str, 8) == real->str); 00159 } 00160 00161 static void 00162 undo_alignment (DBusRealString *real) 00163 { 00164 if (real->align_offset != 0) 00165 { 00166 memmove (real->str - real->align_offset, 00167 real->str, 00168 real->len + 1); 00169 00170 real->str = real->str - real->align_offset; 00171 real->align_offset = 0; 00172 } 00173 } 00174 00184 dbus_bool_t 00185 _dbus_string_init_preallocated (DBusString *str, 00186 int allocate_size) 00187 { 00188 DBusRealString *real; 00189 00190 _dbus_assert (str != NULL); 00191 00192 _dbus_assert (sizeof (DBusString) == sizeof (DBusRealString)); 00193 00194 real = (DBusRealString*) str; 00195 00196 /* It's very important not to touch anything 00197 * other than real->str if we're going to fail, 00198 * since we also use this function to reset 00199 * an existing string, e.g. in _dbus_string_steal_data() 00200 */ 00201 00202 real->str = dbus_malloc (ALLOCATION_PADDING + allocate_size); 00203 if (real->str == NULL) 00204 return FALSE; 00205 00206 real->allocated = ALLOCATION_PADDING + allocate_size; 00207 real->len = 0; 00208 real->str[real->len] = '\0'; 00209 00210 real->max_length = MAX_MAX_LENGTH; 00211 real->constant = FALSE; 00212 real->locked = FALSE; 00213 real->invalid = FALSE; 00214 real->align_offset = 0; 00215 00216 fixup_alignment (real); 00217 00218 return TRUE; 00219 } 00220 00228 dbus_bool_t 00229 _dbus_string_init (DBusString *str) 00230 { 00231 return _dbus_string_init_preallocated (str, 0); 00232 } 00233 00234 /* The max length thing is sort of a historical artifact 00235 * from a feature that turned out to be dumb; perhaps 00236 * we should purge it entirely. The problem with 00237 * the feature is that it looks like memory allocation 00238 * failure, but is not a transient or resolvable failure. 00239 */ 00240 static void 00241 set_max_length (DBusString *str, 00242 int max_length) 00243 { 00244 DBusRealString *real; 00245 00246 real = (DBusRealString*) str; 00247 00248 real->max_length = max_length; 00249 } 00250 00260 void 00261 _dbus_string_init_const (DBusString *str, 00262 const char *value) 00263 { 00264 _dbus_assert (value != NULL); 00265 00266 _dbus_string_init_const_len (str, value, 00267 strlen (value)); 00268 } 00269 00280 void 00281 _dbus_string_init_const_len (DBusString *str, 00282 const char *value, 00283 int len) 00284 { 00285 DBusRealString *real; 00286 00287 _dbus_assert (str != NULL); 00288 _dbus_assert (value != NULL); 00289 _dbus_assert (len <= MAX_MAX_LENGTH); 00290 _dbus_assert (len >= 0); 00291 00292 real = (DBusRealString*) str; 00293 00294 real->str = (char*) value; 00295 real->len = len; 00296 real->allocated = real->len + ALLOCATION_PADDING; /* a lie, just to avoid special-case assertions... */ 00297 real->max_length = real->len + 1; 00298 real->constant = TRUE; 00299 real->invalid = FALSE; 00300 00301 /* We don't require const strings to be 8-byte aligned as the 00302 * memory is coming from elsewhere. 00303 */ 00304 } 00305 00311 void 00312 _dbus_string_free (DBusString *str) 00313 { 00314 DBusRealString *real = (DBusRealString*) str; 00315 DBUS_GENERIC_STRING_PREAMBLE (real); 00316 00317 if (real->constant) 00318 return; 00319 dbus_free (real->str - real->align_offset); 00320 00321 real->invalid = TRUE; 00322 } 00323 00324 #ifdef DBUS_BUILD_TESTS 00325 /* Not using this feature at the moment, 00326 * so marked DBUS_BUILD_TESTS-only 00327 */ 00337 void 00338 _dbus_string_lock (DBusString *str) 00339 { 00340 DBUS_LOCKED_STRING_PREAMBLE (str); /* can lock multiple times */ 00341 00342 real->locked = TRUE; 00343 00344 /* Try to realloc to avoid excess memory usage, since 00345 * we know we won't change the string further 00346 */ 00347 #define MAX_WASTE 48 00348 if (real->allocated - MAX_WASTE > real->len) 00349 { 00350 char *new_str; 00351 int new_allocated; 00352 00353 new_allocated = real->len + ALLOCATION_PADDING; 00354 00355 new_str = dbus_realloc (real->str - real->align_offset, 00356 new_allocated); 00357 if (new_str != NULL) 00358 { 00359 real->str = new_str + real->align_offset; 00360 real->allocated = new_allocated; 00361 fixup_alignment (real); 00362 } 00363 } 00364 } 00365 #endif /* DBUS_BUILD_TESTS */ 00366 00367 static dbus_bool_t 00368 reallocate_for_length (DBusRealString *real, 00369 int new_length) 00370 { 00371 int new_allocated; 00372 char *new_str; 00373 00374 /* at least double our old allocation to avoid O(n), avoiding 00375 * overflow 00376 */ 00377 if (real->allocated > (MAX_MAX_LENGTH + ALLOCATION_PADDING) / 2) 00378 new_allocated = MAX_MAX_LENGTH + ALLOCATION_PADDING; 00379 else 00380 new_allocated = real->allocated * 2; 00381 00382 /* if you change the code just above here, run the tests without 00383 * the following before you commit 00384 */ 00385 #ifdef DBUS_BUILD_TESTS 00386 new_allocated = 0; /* ensure a realloc every time so that we go 00387 * through all malloc failure codepaths 00388 */ 00389 #endif 00390 00391 /* But be sure we always alloc at least space for the new length */ 00392 new_allocated = MAX (new_allocated, new_length + ALLOCATION_PADDING); 00393 00394 _dbus_assert (new_allocated >= real->allocated); /* code relies on this */ 00395 new_str = dbus_realloc (real->str - real->align_offset, new_allocated); 00396 if (new_str == NULL) 00397 return FALSE; 00398 00399 real->str = new_str + real->align_offset; 00400 real->allocated = new_allocated; 00401 fixup_alignment (real); 00402 00403 return TRUE; 00404 } 00405 00406 static dbus_bool_t 00407 set_length (DBusRealString *real, 00408 int new_length) 00409 { 00410 /* Note, we are setting the length not including nul termination */ 00411 00412 /* exceeding max length is the same as failure to allocate memory */ 00413 if (new_length > real->max_length) 00414 return FALSE; 00415 else if (new_length > (real->allocated - ALLOCATION_PADDING) && 00416 !reallocate_for_length (real, new_length)) 00417 return FALSE; 00418 else 00419 { 00420 real->len = new_length; 00421 real->str[real->len] = '\0'; 00422 return TRUE; 00423 } 00424 } 00425 00426 static dbus_bool_t 00427 open_gap (int len, 00428 DBusRealString *dest, 00429 int insert_at) 00430 { 00431 if (len == 0) 00432 return TRUE; 00433 00434 if (len > dest->max_length - dest->len) 00435 return FALSE; /* detected overflow of dest->len + len below */ 00436 00437 if (!set_length (dest, dest->len + len)) 00438 return FALSE; 00439 00440 memmove (dest->str + insert_at + len, 00441 dest->str + insert_at, 00442 dest->len - len - insert_at); 00443 00444 return TRUE; 00445 } 00446 00458 char* 00459 _dbus_string_get_data (DBusString *str) 00460 { 00461 DBUS_STRING_PREAMBLE (str); 00462 00463 return real->str; 00464 } 00465 00472 const char* 00473 _dbus_string_get_const_data (const DBusString *str) 00474 { 00475 DBUS_CONST_STRING_PREAMBLE (str); 00476 00477 return real->str; 00478 } 00479 00493 char* 00494 _dbus_string_get_data_len (DBusString *str, 00495 int start, 00496 int len) 00497 { 00498 DBUS_STRING_PREAMBLE (str); 00499 _dbus_assert (start >= 0); 00500 _dbus_assert (len >= 0); 00501 _dbus_assert (start <= real->len); 00502 _dbus_assert (len <= real->len - start); 00503 00504 return real->str + start; 00505 } 00506 00515 const char* 00516 _dbus_string_get_const_data_len (const DBusString *str, 00517 int start, 00518 int len) 00519 { 00520 DBUS_CONST_STRING_PREAMBLE (str); 00521 _dbus_assert (start >= 0); 00522 _dbus_assert (len >= 0); 00523 _dbus_assert (start <= real->len); 00524 _dbus_assert (len <= real->len - start); 00525 00526 return real->str + start; 00527 } 00528 00536 void 00537 _dbus_string_set_byte (DBusString *str, 00538 int i, 00539 unsigned char byte) 00540 { 00541 DBUS_STRING_PREAMBLE (str); 00542 _dbus_assert (i < real->len); 00543 _dbus_assert (i >= 0); 00544 00545 real->str[i] = byte; 00546 } 00547 00557 unsigned char 00558 _dbus_string_get_byte (const DBusString *str, 00559 int start) 00560 { 00561 DBUS_CONST_STRING_PREAMBLE (str); 00562 _dbus_assert (start <= real->len); 00563 _dbus_assert (start >= 0); 00564 00565 return real->str[start]; 00566 } 00567 00578 dbus_bool_t 00579 _dbus_string_insert_bytes (DBusString *str, 00580 int i, 00581 int n_bytes, 00582 unsigned char byte) 00583 { 00584 DBUS_STRING_PREAMBLE (str); 00585 _dbus_assert (i <= real->len); 00586 _dbus_assert (i >= 0); 00587 _dbus_assert (n_bytes >= 0); 00588 00589 if (n_bytes == 0) 00590 return TRUE; 00591 00592 if (!open_gap (n_bytes, real, i)) 00593 return FALSE; 00594 00595 memset (real->str + i, byte, n_bytes); 00596 00597 return TRUE; 00598 } 00599 00610 dbus_bool_t 00611 _dbus_string_steal_data (DBusString *str, 00612 char **data_return) 00613 { 00614 int old_max_length; 00615 DBUS_STRING_PREAMBLE (str); 00616 _dbus_assert (data_return != NULL); 00617 00618 undo_alignment (real); 00619 00620 *data_return = real->str; 00621 00622 old_max_length = real->max_length; 00623 00624 /* reset the string */ 00625 if (!_dbus_string_init (str)) 00626 { 00627 /* hrm, put it back then */ 00628 real->str = *data_return; 00629 *data_return = NULL; 00630 fixup_alignment (real); 00631 return FALSE; 00632 } 00633 00634 real->max_length = old_max_length; 00635 00636 return TRUE; 00637 } 00638 00654 dbus_bool_t 00655 _dbus_string_steal_data_len (DBusString *str, 00656 char **data_return, 00657 int start, 00658 int len) 00659 { 00660 DBusString dest; 00661 DBUS_STRING_PREAMBLE (str); 00662 _dbus_assert (data_return != NULL); 00663 _dbus_assert (start >= 0); 00664 _dbus_assert (len >= 0); 00665 _dbus_assert (start <= real->len); 00666 _dbus_assert (len <= real->len - start); 00667 00668 if (!_dbus_string_init (&dest)) 00669 return FALSE; 00670 00671 set_max_length (&dest, real->max_length); 00672 00673 if (!_dbus_string_move_len (str, start, len, &dest, 0)) 00674 { 00675 _dbus_string_free (&dest); 00676 return FALSE; 00677 } 00678 00679 _dbus_warn ("Broken code in _dbus_string_steal_data_len(), see @todo, FIXME\n"); 00680 if (!_dbus_string_steal_data (&dest, data_return)) 00681 { 00682 _dbus_string_free (&dest); 00683 return FALSE; 00684 } 00685 00686 _dbus_string_free (&dest); 00687 return TRUE; 00688 } 00689 00690 00698 dbus_bool_t 00699 _dbus_string_copy_data (const DBusString *str, 00700 char **data_return) 00701 { 00702 DBUS_CONST_STRING_PREAMBLE (str); 00703 _dbus_assert (data_return != NULL); 00704 00705 *data_return = dbus_malloc (real->len + 1); 00706 if (*data_return == NULL) 00707 return FALSE; 00708 00709 memcpy (*data_return, real->str, real->len + 1); 00710 00711 return TRUE; 00712 } 00713 00723 dbus_bool_t 00724 _dbus_string_copy_data_len (const DBusString *str, 00725 char **data_return, 00726 int start, 00727 int len) 00728 { 00729 DBusString dest; 00730 00731 DBUS_CONST_STRING_PREAMBLE (str); 00732 _dbus_assert (data_return != NULL); 00733 _dbus_assert (start >= 0); 00734 _dbus_assert (len >= 0); 00735 _dbus_assert (start <= real->len); 00736 _dbus_assert (len <= real->len - start); 00737 00738 if (!_dbus_string_init (&dest)) 00739 return FALSE; 00740 00741 set_max_length (&dest, real->max_length); 00742 00743 if (!_dbus_string_copy_len (str, start, len, &dest, 0)) 00744 { 00745 _dbus_string_free (&dest); 00746 return FALSE; 00747 } 00748 00749 if (!_dbus_string_steal_data (&dest, data_return)) 00750 { 00751 _dbus_string_free (&dest); 00752 return FALSE; 00753 } 00754 00755 _dbus_string_free (&dest); 00756 return TRUE; 00757 } 00758 00764 int 00765 _dbus_string_get_length (const DBusString *str) 00766 { 00767 DBUS_CONST_STRING_PREAMBLE (str); 00768 00769 return real->len; 00770 } 00771 00784 dbus_bool_t 00785 _dbus_string_lengthen (DBusString *str, 00786 int additional_length) 00787 { 00788 DBUS_STRING_PREAMBLE (str); 00789 _dbus_assert (additional_length >= 0); 00790 00791 if (additional_length > real->max_length - real->len) 00792 return FALSE; /* would overflow */ 00793 00794 return set_length (real, 00795 real->len + additional_length); 00796 } 00797 00804 void 00805 _dbus_string_shorten (DBusString *str, 00806 int length_to_remove) 00807 { 00808 DBUS_STRING_PREAMBLE (str); 00809 _dbus_assert (length_to_remove >= 0); 00810 _dbus_assert (length_to_remove <= real->len); 00811 00812 set_length (real, 00813 real->len - length_to_remove); 00814 } 00815 00826 dbus_bool_t 00827 _dbus_string_set_length (DBusString *str, 00828 int length) 00829 { 00830 DBUS_STRING_PREAMBLE (str); 00831 _dbus_assert (length >= 0); 00832 00833 return set_length (real, length); 00834 } 00835 00836 static dbus_bool_t 00837 align_length_then_lengthen (DBusString *str, 00838 int alignment, 00839 int then_lengthen_by) 00840 { 00841 unsigned long new_len; /* ulong to avoid _DBUS_ALIGN_VALUE overflow */ 00842 int delta; 00843 DBUS_STRING_PREAMBLE (str); 00844 _dbus_assert (alignment >= 1); 00845 _dbus_assert (alignment <= 8); /* it has to be a bug if > 8 */ 00846 00847 new_len = _DBUS_ALIGN_VALUE (real->len, alignment); 00848 if (new_len > (unsigned long) real->max_length - then_lengthen_by) 00849 return FALSE; 00850 new_len += then_lengthen_by; 00851 00852 delta = new_len - real->len; 00853 _dbus_assert (delta >= 0); 00854 00855 if (delta == 0) 00856 return TRUE; 00857 00858 if (!set_length (real, new_len)) 00859 return FALSE; 00860 00861 /* delta == padding + then_lengthen_by 00862 * new_len == old_len + padding + then_lengthen_by 00863 */ 00864 if (then_lengthen_by < delta) 00865 { 00866 unsigned int i; 00867 i = new_len - delta; 00868 while (i < (new_len - then_lengthen_by)) 00869 { 00870 real->str[i] = '\0'; 00871 ++i; 00872 } 00873 } 00874 00875 return TRUE; 00876 } 00877 00886 dbus_bool_t 00887 _dbus_string_align_length (DBusString *str, 00888 int alignment) 00889 { 00890 return align_length_then_lengthen (str, alignment, 0); 00891 } 00892 00893 static dbus_bool_t 00894 append (DBusRealString *real, 00895 const char *buffer, 00896 int buffer_len) 00897 { 00898 if (buffer_len == 0) 00899 return TRUE; 00900 00901 if (!_dbus_string_lengthen ((DBusString*)real, buffer_len)) 00902 return FALSE; 00903 00904 memcpy (real->str + (real->len - buffer_len), 00905 buffer, 00906 buffer_len); 00907 00908 return TRUE; 00909 } 00910 00918 dbus_bool_t 00919 _dbus_string_append (DBusString *str, 00920 const char *buffer) 00921 { 00922 unsigned long buffer_len; 00923 00924 DBUS_STRING_PREAMBLE (str); 00925 _dbus_assert (buffer != NULL); 00926 00927 buffer_len = strlen (buffer); 00928 if (buffer_len > (unsigned long) real->max_length) 00929 return FALSE; 00930 00931 return append (real, buffer, buffer_len); 00932 } 00933 00942 dbus_bool_t 00943 _dbus_string_append_4_aligned (DBusString *str, 00944 const unsigned char octets[4]) 00945 { 00946 dbus_uint32_t *p; 00947 DBUS_STRING_PREAMBLE (str); 00948 00949 if (!align_length_then_lengthen (str, 4, 4)) 00950 return FALSE; 00951 00952 p = (dbus_uint32_t*) (real->str + (real->len - 4)); 00953 *p = *((dbus_uint32_t*)octets); 00954 00955 return TRUE; 00956 } 00957 00966 dbus_bool_t 00967 _dbus_string_append_8_aligned (DBusString *str, 00968 const unsigned char octets[8]) 00969 { 00970 #ifdef DBUS_HAVE_INT64 00971 dbus_uint64_t *p; 00972 DBUS_STRING_PREAMBLE (str); 00973 00974 if (!align_length_then_lengthen (str, 8, 8)) 00975 return FALSE; 00976 00977 p = (dbus_uint64_t*) (real->str + (real->len - 8)); 00978 *p = *((dbus_uint64_t*)octets); 00979 #else 00980 unsigned char *p; 00981 DBUS_STRING_PREAMBLE (str); 00982 00983 if (!align_length_then_lengthen (str, 8, 8)) 00984 return FALSE; 00985 00986 p = real->str + (real->len - 8); 00987 00988 *p++ = octets[0]; 00989 *p++ = octets[1]; 00990 *p++ = octets[2]; 00991 *p++ = octets[3]; 00992 *p++ = octets[4]; 00993 *p++ = octets[5]; 00994 *p++ = octets[6]; 00995 *p++ = octets[7]; 00996 _dbus_assert (p == (real->str + real->len)); 00997 #endif 00998 00999 return TRUE; 01000 } 01001 01011 dbus_bool_t 01012 _dbus_string_append_printf_valist (DBusString *str, 01013 const char *format, 01014 va_list args) 01015 { 01016 int len; 01017 char c; 01018 va_list args_copy; 01019 01020 DBUS_STRING_PREAMBLE (str); 01021 01022 DBUS_VA_COPY (args_copy, args); 01023 01024 /* Measure the message length without terminating nul */ 01025 len = vsnprintf (&c, 1, format, args); 01026 01027 if (!_dbus_string_lengthen (str, len)) 01028 { 01029 /* don't leak the copy */ 01030 va_end (args_copy); 01031 return FALSE; 01032 } 01033 01034 vsprintf (real->str + (real->len - len), 01035 format, args_copy); 01036 01037 va_end (args_copy); 01038 01039 return TRUE; 01040 } 01041 01050 dbus_bool_t 01051 _dbus_string_append_printf (DBusString *str, 01052 const char *format, 01053 ...) 01054 { 01055 va_list args; 01056 dbus_bool_t retval; 01057 01058 va_start (args, format); 01059 retval = _dbus_string_append_printf_valist (str, format, args); 01060 va_end (args); 01061 01062 return retval; 01063 } 01064 01073 dbus_bool_t 01074 _dbus_string_append_len (DBusString *str, 01075 const char *buffer, 01076 int len) 01077 { 01078 DBUS_STRING_PREAMBLE (str); 01079 _dbus_assert (buffer != NULL); 01080 _dbus_assert (len >= 0); 01081 01082 return append (real, buffer, len); 01083 } 01084 01093 dbus_bool_t 01094 _dbus_string_append_byte (DBusString *str, 01095 unsigned char byte) 01096 { 01097 DBUS_STRING_PREAMBLE (str); 01098 01099 if (!set_length (real, real->len + 1)) 01100 return FALSE; 01101 01102 real->str[real->len-1] = byte; 01103 01104 return TRUE; 01105 } 01106 01114 dbus_bool_t 01115 _dbus_string_append_unichar (DBusString *str, 01116 dbus_unichar_t ch) 01117 { 01118 int len; 01119 int first; 01120 int i; 01121 char *out; 01122 01123 DBUS_STRING_PREAMBLE (str); 01124 01125 /* this code is from GLib but is pretty standard I think */ 01126 01127 len = 0; 01128 01129 if (ch < 0x80) 01130 { 01131 first = 0; 01132 len = 1; 01133 } 01134 else if (ch < 0x800) 01135 { 01136 first = 0xc0; 01137 len = 2; 01138 } 01139 else if (ch < 0x10000) 01140 { 01141 first = 0xe0; 01142 len = 3; 01143 } 01144 else if (ch < 0x200000) 01145 { 01146 first = 0xf0; 01147 len = 4; 01148 } 01149 else if (ch < 0x4000000) 01150 { 01151 first = 0xf8; 01152 len = 5; 01153 } 01154 else 01155 { 01156 first = 0xfc; 01157 len = 6; 01158 } 01159 01160 if (len > (real->max_length - real->len)) 01161 return FALSE; /* real->len + len would overflow */ 01162 01163 if (!set_length (real, real->len + len)) 01164 return FALSE; 01165 01166 out = real->str + (real->len - len); 01167 01168 for (i = len - 1; i > 0; --i) 01169 { 01170 out[i] = (ch & 0x3f) | 0x80; 01171 ch >>= 6; 01172 } 01173 out[0] = ch | first; 01174 01175 return TRUE; 01176 } 01177 01178 static void 01179 delete (DBusRealString *real, 01180 int start, 01181 int len) 01182 { 01183 if (len == 0) 01184 return; 01185 01186 memmove (real->str + start, real->str + start + len, real->len - (start + len)); 01187 real->len -= len; 01188 real->str[real->len] = '\0'; 01189 } 01190 01200 void 01201 _dbus_string_delete (DBusString *str, 01202 int start, 01203 int len) 01204 { 01205 DBUS_STRING_PREAMBLE (str); 01206 _dbus_assert (start >= 0); 01207 _dbus_assert (len >= 0); 01208 _dbus_assert (start <= real->len); 01209 _dbus_assert (len <= real->len - start); 01210 01211 delete (real, start, len); 01212 } 01213 01214 static dbus_bool_t 01215 copy (DBusRealString *source, 01216 int start, 01217 int len, 01218 DBusRealString *dest, 01219 int insert_at) 01220 { 01221 if (len == 0) 01222 return TRUE; 01223 01224 if (!open_gap (len, dest, insert_at)) 01225 return FALSE; 01226 01227 memcpy (dest->str + insert_at, 01228 source->str + start, 01229 len); 01230 01231 return TRUE; 01232 } 01233 01243 #define DBUS_STRING_COPY_PREAMBLE(source, start, dest, insert_at) \ 01244 DBusRealString *real_source = (DBusRealString*) source; \ 01245 DBusRealString *real_dest = (DBusRealString*) dest; \ 01246 _dbus_assert ((source) != (dest)); \ 01247 DBUS_GENERIC_STRING_PREAMBLE (real_source); \ 01248 DBUS_GENERIC_STRING_PREAMBLE (real_dest); \ 01249 _dbus_assert (!real_dest->constant); \ 01250 _dbus_assert (!real_dest->locked); \ 01251 _dbus_assert ((start) >= 0); \ 01252 _dbus_assert ((start) <= real_source->len); \ 01253 _dbus_assert ((insert_at) >= 0); \ 01254 _dbus_assert ((insert_at) <= real_dest->len) 01255 01266 dbus_bool_t 01267 _dbus_string_move (DBusString *source, 01268 int start, 01269 DBusString *dest, 01270 int insert_at) 01271 { 01272 DBusRealString *real_source = (DBusRealString*) source; 01273 _dbus_assert (start <= real_source->len); 01274 01275 return _dbus_string_move_len (source, start, 01276 real_source->len - start, 01277 dest, insert_at); 01278 } 01279 01290 dbus_bool_t 01291 _dbus_string_copy (const DBusString *source, 01292 int start, 01293 DBusString *dest, 01294 int insert_at) 01295 { 01296 DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at); 01297 01298 return copy (real_source, start, 01299 real_source->len - start, 01300 real_dest, 01301 insert_at); 01302 } 01303 01318 dbus_bool_t 01319 _dbus_string_move_len (DBusString *source, 01320 int start, 01321 int len, 01322 DBusString *dest, 01323 int insert_at) 01324 01325 { 01326 DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at); 01327 _dbus_assert (len >= 0); 01328 _dbus_assert ((start + len) <= real_source->len); 01329 01330 01331 if (len == 0) 01332 { 01333 return TRUE; 01334 } 01335 else if (start == 0 && 01336 len == real_source->len && 01337 real_dest->len == 0) 01338 { 01339 /* Short-circuit moving an entire existing string to an empty string 01340 * by just swapping the buffers. 01341 */ 01342 /* we assume ->constant doesn't matter as you can't have 01343 * a constant string involved in a move. 01344 */ 01345 #define ASSIGN_DATA(a, b) do { \ 01346 (a)->str = (b)->str; \ 01347 (a)->len = (b)->len; \ 01348 (a)->allocated = (b)->allocated; \ 01349 (a)->align_offset = (b)->align_offset; \ 01350 } while (0) 01351 01352 DBusRealString tmp; 01353 01354 ASSIGN_DATA (&tmp, real_source); 01355 ASSIGN_DATA (real_source, real_dest); 01356 ASSIGN_DATA (real_dest, &tmp); 01357 01358 return TRUE; 01359 } 01360 else 01361 { 01362 if (!copy (real_source, start, len, 01363 real_dest, 01364 insert_at)) 01365 return FALSE; 01366 01367 delete (real_source, start, 01368 len); 01369 01370 return TRUE; 01371 } 01372 } 01373 01385 dbus_bool_t 01386 _dbus_string_copy_len (const DBusString *source, 01387 int start, 01388 int len, 01389 DBusString *dest, 01390 int insert_at) 01391 { 01392 DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at); 01393 _dbus_assert (len >= 0); 01394 _dbus_assert (start <= real_source->len); 01395 _dbus_assert (len <= real_source->len - start); 01396 01397 return copy (real_source, start, len, 01398 real_dest, 01399 insert_at); 01400 } 01401 01423 dbus_bool_t 01424 _dbus_string_replace_len (const DBusString *source, 01425 int start, 01426 int len, 01427 DBusString *dest, 01428 int replace_at, 01429 int replace_len) 01430 { 01431 DBUS_STRING_COPY_PREAMBLE (source, start, dest, replace_at); 01432 _dbus_assert (len >= 0); 01433 _dbus_assert (start <= real_source->len); 01434 _dbus_assert (len <= real_source->len - start); 01435 _dbus_assert (replace_at >= 0); 01436 _dbus_assert (replace_at <= real_dest->len); 01437 _dbus_assert (replace_len <= real_dest->len - replace_at); 01438 01439 if (!copy (real_source, start, len, 01440 real_dest, replace_at)) 01441 return FALSE; 01442 01443 delete (real_dest, replace_at + len, replace_len); 01444 01445 return TRUE; 01446 } 01447 01448 /* Unicode macros and utf8_validate() from GLib Owen Taylor, Havoc 01449 * Pennington, and Tom Tromey are the authors and authorized relicense. 01450 */ 01451 01457 #define UTF8_COMPUTE(Char, Mask, Len) \ 01458 if (Char < 128) \ 01459 { \ 01460 Len = 1; \ 01461 Mask = 0x7f; \ 01462 } \ 01463 else if ((Char & 0xe0) == 0xc0) \ 01464 { \ 01465 Len = 2; \ 01466 Mask = 0x1f; \ 01467 } \ 01468 else if ((Char & 0xf0) == 0xe0) \ 01469 { \ 01470 Len = 3; \ 01471 Mask = 0x0f; \ 01472 } \ 01473 else if ((Char & 0xf8) == 0xf0) \ 01474 { \ 01475 Len = 4; \ 01476 Mask = 0x07; \ 01477 } \ 01478 else if ((Char & 0xfc) == 0xf8) \ 01479 { \ 01480 Len = 5; \ 01481 Mask = 0x03; \ 01482 } \ 01483 else if ((Char & 0xfe) == 0xfc) \ 01484 { \ 01485 Len = 6; \ 01486 Mask = 0x01; \ 01487 } \ 01488 else \ 01489 Len = -1; 01490 01495 #define UTF8_LENGTH(Char) \ 01496 ((Char) < 0x80 ? 1 : \ 01497 ((Char) < 0x800 ? 2 : \ 01498 ((Char) < 0x10000 ? 3 : \ 01499 ((Char) < 0x200000 ? 4 : \ 01500 ((Char) < 0x4000000 ? 5 : 6))))) 01501 01511 #define UTF8_GET(Result, Chars, Count, Mask, Len) \ 01512 (Result) = (Chars)[0] & (Mask); \ 01513 for ((Count) = 1; (Count) < (Len); ++(Count)) \ 01514 { \ 01515 if (((Chars)[(Count)] & 0xc0) != 0x80) \ 01516 { \ 01517 (Result) = -1; \ 01518 break; \ 01519 } \ 01520 (Result) <<= 6; \ 01521 (Result) |= ((Chars)[(Count)] & 0x3f); \ 01522 } 01523 01529 #define UNICODE_VALID(Char) \ 01530 ((Char) < 0x110000 && \ 01531 (((Char) & 0xFFFFF800) != 0xD800) && \ 01532 ((Char) < 0xFDD0 || (Char) > 0xFDEF) && \ 01533 ((Char) & 0xFFFF) != 0xFFFF) 01534 01545 void 01546 _dbus_string_get_unichar (const DBusString *str, 01547 int start, 01548 dbus_unichar_t *ch_return, 01549 int *end_return) 01550 { 01551 int i, mask, len; 01552 dbus_unichar_t result; 01553 unsigned char c; 01554 unsigned char *p; 01555 DBUS_CONST_STRING_PREAMBLE (str); 01556 _dbus_assert (start >= 0); 01557 _dbus_assert (start <= real->len); 01558 01559 if (ch_return) 01560 *ch_return = 0; 01561 if (end_return) 01562 *end_return = real->len; 01563 01564 mask = 0; 01565 p = real->str + start; 01566 c = *p; 01567 01568 UTF8_COMPUTE (c, mask, len); 01569 if (len == -1) 01570 return; 01571 UTF8_GET (result, p, i, mask, len); 01572 01573 if (result == (dbus_unichar_t)-1) 01574 return; 01575 01576 if (ch_return) 01577 *ch_return = result; 01578 if (end_return) 01579 *end_return = start + len; 01580 } 01581 01596 dbus_bool_t 01597 _dbus_string_find (const DBusString *str, 01598 int start, 01599 const char *substr, 01600 int *found) 01601 { 01602 return _dbus_string_find_to (str, start, 01603 ((const DBusRealString*)str)->len, 01604 substr, found); 01605 } 01606 01623 dbus_bool_t 01624 _dbus_string_find_to (const DBusString *str, 01625 int start, 01626 int end, 01627 const char *substr, 01628 int *found) 01629 { 01630 int i; 01631 DBUS_CONST_STRING_PREAMBLE (str); 01632 _dbus_assert (substr != NULL); 01633 _dbus_assert (start <= real->len); 01634 _dbus_assert (start >= 0); 01635 _dbus_assert (substr != NULL); 01636 _dbus_assert (end <= real->len); 01637 _dbus_assert (start <= end); 01638 01639 /* we always "find" an empty string */ 01640 if (*substr == '\0') 01641 { 01642 if (found) 01643 *found = start; 01644 return TRUE; 01645 } 01646 01647 i = start; 01648 while (i < end) 01649 { 01650 if (real->str[i] == substr[0]) 01651 { 01652 int j = i + 1; 01653 01654 while (j < end) 01655 { 01656 if (substr[j - i] == '\0') 01657 break; 01658 else if (real->str[j] != substr[j - i]) 01659 break; 01660 01661 ++j; 01662 } 01663 01664 if (substr[j - i] == '\0') 01665 { 01666 if (found) 01667 *found = i; 01668 return TRUE; 01669 } 01670 } 01671 01672 ++i; 01673 } 01674 01675 if (found) 01676 *found = end; 01677 01678 return FALSE; 01679 } 01680 01691 dbus_bool_t 01692 _dbus_string_find_byte_backward (const DBusString *str, 01693 int start, 01694 unsigned char byte, 01695 int *found) 01696 { 01697 int i; 01698 DBUS_CONST_STRING_PREAMBLE (str); 01699 _dbus_assert (start <= real->len); 01700 _dbus_assert (start >= 0); 01701 _dbus_assert (found != NULL); 01702 01703 i = start - 1; 01704 while (i >= 0) 01705 { 01706 if (real->str[i] == byte) 01707 break; 01708 01709 --i; 01710 } 01711 01712 if (found) 01713 *found = i; 01714 01715 return i >= 0; 01716 } 01717 01728 dbus_bool_t 01729 _dbus_string_find_blank (const DBusString *str, 01730 int start, 01731 int *found) 01732 { 01733 int i; 01734 DBUS_CONST_STRING_PREAMBLE (str); 01735 _dbus_assert (start <= real->len); 01736 _dbus_assert (start >= 0); 01737 01738 i = start; 01739 while (i < real->len) 01740 { 01741 if (real->str[i] == ' ' || 01742 real->str[i] == '\t') 01743 { 01744 if (found) 01745 *found = i; 01746 return TRUE; 01747 } 01748 01749 ++i; 01750 } 01751 01752 if (found) 01753 *found = real->len; 01754 01755 return FALSE; 01756 } 01757 01766 void 01767 _dbus_string_skip_blank (const DBusString *str, 01768 int start, 01769 int *end) 01770 { 01771 int i; 01772 DBUS_CONST_STRING_PREAMBLE (str); 01773 _dbus_assert (start <= real->len); 01774 _dbus_assert (start >= 0); 01775 01776 i = start; 01777 while (i < real->len) 01778 { 01779 if (!(real->str[i] == ' ' || 01780 real->str[i] == '\t')) 01781 break; 01782 01783 ++i; 01784 } 01785 01786 _dbus_assert (i == real->len || !(real->str[i] == ' ' || 01787 real->str[i] == '\t')); 01788 01789 if (end) 01790 *end = i; 01791 } 01792 01801 void 01802 _dbus_string_skip_white (const DBusString *str, 01803 int start, 01804 int *end) 01805 { 01806 int i; 01807 DBUS_CONST_STRING_PREAMBLE (str); 01808 _dbus_assert (start <= real->len); 01809 _dbus_assert (start >= 0); 01810 01811 i = start; 01812 while (i < real->len) 01813 { 01814 if (!(real->str[i] == ' ' || 01815 real->str[i] == '\n' || 01816 real->str[i] == '\r' || 01817 real->str[i] == '\t')) 01818 break; 01819 01820 ++i; 01821 } 01822 01823 _dbus_assert (i == real->len || !(real->str[i] == ' ' || 01824 real->str[i] == '\t')); 01825 01826 if (end) 01827 *end = i; 01828 } 01829 01845 dbus_bool_t 01846 _dbus_string_pop_line (DBusString *source, 01847 DBusString *dest) 01848 { 01849 int eol; 01850 dbus_bool_t have_newline; 01851 01852 _dbus_string_set_length (dest, 0); 01853 01854 eol = 0; 01855 if (_dbus_string_find (source, 0, "\n", &eol)) 01856 { 01857 have_newline = TRUE; 01858 eol += 1; /* include newline */ 01859 } 01860 else 01861 { 01862 eol = _dbus_string_get_length (source); 01863 have_newline = FALSE; 01864 } 01865 01866 if (eol == 0) 01867 return FALSE; /* eof */ 01868 01869 if (!_dbus_string_move_len (source, 0, eol, 01870 dest, 0)) 01871 { 01872 return FALSE; 01873 } 01874 01875 /* dump the newline and the \r if we have one */ 01876 if (have_newline) 01877 { 01878 dbus_bool_t have_cr; 01879 01880 _dbus_assert (_dbus_string_get_length (dest) > 0); 01881 01882 if (_dbus_string_get_length (dest) > 1 && 01883 _dbus_string_get_byte (dest, 01884 _dbus_string_get_length (dest) - 2) == '\r') 01885 have_cr = TRUE; 01886 else 01887 have_cr = FALSE; 01888 01889 _dbus_string_set_length (dest, 01890 _dbus_string_get_length (dest) - 01891 (have_cr ? 2 : 1)); 01892 } 01893 01894 return TRUE; 01895 } 01896 01903 void 01904 _dbus_string_delete_first_word (DBusString *str) 01905 { 01906 int i; 01907 01908 if (_dbus_string_find_blank (str, 0, &i)) 01909 _dbus_string_skip_blank (str, i, &i); 01910 01911 _dbus_string_delete (str, 0, i); 01912 } 01913 01919 void 01920 _dbus_string_delete_leading_blanks (DBusString *str) 01921 { 01922 int i; 01923 01924 _dbus_string_skip_blank (str, 0, &i); 01925 01926 if (i > 0) 01927 _dbus_string_delete (str, 0, i); 01928 } 01929 01939 dbus_bool_t 01940 _dbus_string_equal (const DBusString *a, 01941 const DBusString *b) 01942 { 01943 const unsigned char *ap; 01944 const unsigned char *bp; 01945 const unsigned char *a_end; 01946 const DBusRealString *real_a = (const DBusRealString*) a; 01947 const DBusRealString *real_b = (const DBusRealString*) b; 01948 DBUS_GENERIC_STRING_PREAMBLE (real_a); 01949 DBUS_GENERIC_STRING_PREAMBLE (real_b); 01950 01951 if (real_a->len != real_b->len) 01952 return FALSE; 01953 01954 ap = real_a->str; 01955 bp = real_b->str; 01956 a_end = real_a->str + real_a->len; 01957 while (ap != a_end) 01958 { 01959 if (*ap != *bp) 01960 return FALSE; 01961 01962 ++ap; 01963 ++bp; 01964 } 01965 01966 return TRUE; 01967 } 01968 01981 dbus_bool_t 01982 _dbus_string_equal_len (const DBusString *a, 01983 const DBusString *b, 01984 int len) 01985 { 01986 const unsigned char *ap; 01987 const unsigned char *bp; 01988 const unsigned char *a_end; 01989 const DBusRealString *real_a = (const DBusRealString*) a; 01990 const DBusRealString *real_b = (const DBusRealString*) b; 01991 DBUS_GENERIC_STRING_PREAMBLE (real_a); 01992 DBUS_GENERIC_STRING_PREAMBLE (real_b); 01993 01994 if (real_a->len != real_b->len && 01995 (real_a->len < len || real_b->len < len)) 01996 return FALSE; 01997 01998 ap = real_a->str; 01999 bp = real_b->str; 02000 a_end = real_a->str + MIN (real_a->len, len); 02001 while (ap != a_end) 02002 { 02003 if (*ap != *bp) 02004 return FALSE; 02005 02006 ++ap; 02007 ++bp; 02008 } 02009 02010 return TRUE; 02011 } 02012 02020 dbus_bool_t 02021 _dbus_string_equal_c_str (const DBusString *a, 02022 const char *c_str) 02023 { 02024 const unsigned char *ap; 02025 const unsigned char *bp; 02026 const unsigned char *a_end; 02027 const DBusRealString *real_a = (const DBusRealString*) a; 02028 DBUS_GENERIC_STRING_PREAMBLE (real_a); 02029 _dbus_assert (c_str != NULL); 02030 02031 ap = real_a->str; 02032 bp = (const unsigned char*) c_str; 02033 a_end = real_a->str + real_a->len; 02034 while (ap != a_end && *bp) 02035 { 02036 if (*ap != *bp) 02037 return FALSE; 02038 02039 ++ap; 02040 ++bp; 02041 } 02042 02043 if (ap != a_end || *bp) 02044 return FALSE; 02045 02046 return TRUE; 02047 } 02048 02056 dbus_bool_t 02057 _dbus_string_starts_with_c_str (const DBusString *a, 02058 const char *c_str) 02059 { 02060 const unsigned char *ap; 02061 const unsigned char *bp; 02062 const unsigned char *a_end; 02063 const DBusRealString *real_a = (const DBusRealString*) a; 02064 DBUS_GENERIC_STRING_PREAMBLE (real_a); 02065 _dbus_assert (c_str != NULL); 02066 02067 ap = real_a->str; 02068 bp = (const unsigned char*) c_str; 02069 a_end = real_a->str + real_a->len; 02070 while (ap != a_end && *bp) 02071 { 02072 if (*ap != *bp) 02073 return FALSE; 02074 02075 ++ap; 02076 ++bp; 02077 } 02078 02079 if (*bp == '\0') 02080 return TRUE; 02081 else 02082 return FALSE; 02083 } 02084 02094 dbus_bool_t 02095 _dbus_string_ends_with_c_str (const DBusString *a, 02096 const char *c_str) 02097 { 02098 const unsigned char *ap; 02099 const unsigned char *bp; 02100 const unsigned char *a_end; 02101 unsigned long c_str_len; 02102 const DBusRealString *real_a = (const DBusRealString*) a; 02103 DBUS_GENERIC_STRING_PREAMBLE (real_a); 02104 _dbus_assert (c_str != NULL); 02105 02106 c_str_len = strlen (c_str); 02107 if (((unsigned long)real_a->len) < c_str_len) 02108 return FALSE; 02109 02110 ap = real_a->str + (real_a->len - c_str_len); 02111 bp = (const unsigned char*) c_str; 02112 a_end = real_a->str + real_a->len; 02113 while (ap != a_end) 02114 { 02115 if (*ap != *bp) 02116 return FALSE; 02117 02118 ++ap; 02119 ++bp; 02120 } 02121 02122 _dbus_assert (*ap == '\0'); 02123 _dbus_assert (*bp == '\0'); 02124 02125 return TRUE; 02126 } 02127 02138 dbus_bool_t 02139 _dbus_string_hex_encode (const DBusString *source, 02140 int start, 02141 DBusString *dest, 02142 int insert_at) 02143 { 02144 DBusString result; 02145 const char hexdigits[16] = { 02146 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 02147 'a', 'b', 'c', 'd', 'e', 'f' 02148 }; 02149 const unsigned char *p; 02150 const unsigned char *end; 02151 dbus_bool_t retval; 02152 02153 _dbus_assert (start <= _dbus_string_get_length (source)); 02154 02155 if (!_dbus_string_init (&result)) 02156 return FALSE; 02157 02158 retval = FALSE; 02159 02160 p = (const unsigned char*) _dbus_string_get_const_data (source); 02161 end = p + _dbus_string_get_length (source); 02162 p += start; 02163 02164 while (p != end) 02165 { 02166 if (!_dbus_string_append_byte (&result, 02167 hexdigits[(*p >> 4)])) 02168 goto out; 02169 02170 if (!_dbus_string_append_byte (&result, 02171 hexdigits[(*p & 0x0f)])) 02172 goto out; 02173 02174 ++p; 02175 } 02176 02177 if (!_dbus_string_move (&result, 0, dest, insert_at)) 02178 goto out; 02179 02180 retval = TRUE; 02181 02182 out: 02183 _dbus_string_free (&result); 02184 return retval; 02185 } 02186 02197 dbus_bool_t 02198 _dbus_string_hex_decode (const DBusString *source, 02199 int start, 02200 int *end_return, 02201 DBusString *dest, 02202 int insert_at) 02203 { 02204 DBusString result; 02205 const unsigned char *p; 02206 const unsigned char *end; 02207 dbus_bool_t retval; 02208 dbus_bool_t high_bits; 02209 02210 _dbus_assert (start <= _dbus_string_get_length (source)); 02211 02212 if (!_dbus_string_init (&result)) 02213 return FALSE; 02214 02215 retval = FALSE; 02216 02217 high_bits = TRUE; 02218 p = (const unsigned char*) _dbus_string_get_const_data (source); 02219 end = p + _dbus_string_get_length (source); 02220 p += start; 02221 02222 while (p != end) 02223 { 02224 unsigned int val; 02225 02226 switch (*p) 02227 { 02228 case '0': 02229 val = 0; 02230 break; 02231 case '1': 02232 val = 1; 02233 break; 02234 case '2': 02235 val = 2; 02236 break; 02237 case '3': 02238 val = 3; 02239 break; 02240 case '4': 02241 val = 4; 02242 break; 02243 case '5': 02244 val = 5; 02245 break; 02246 case '6': 02247 val = 6; 02248 break; 02249 case '7': 02250 val = 7; 02251 break; 02252 case '8': 02253 val = 8; 02254 break; 02255 case '9': 02256 val = 9; 02257 break; 02258 case 'a': 02259 case 'A': 02260 val = 10; 02261 break; 02262 case 'b': 02263 case 'B': 02264 val = 11; 02265 break; 02266 case 'c': 02267 case 'C': 02268 val = 12; 02269 break; 02270 case 'd': 02271 case 'D': 02272 val = 13; 02273 break; 02274 case 'e': 02275 case 'E': 02276 val = 14; 02277 break; 02278 case 'f': 02279 case 'F': 02280 val = 15; 02281 break; 02282 default: 02283 goto done; 02284 } 02285 02286 if (high_bits) 02287 { 02288 if (!_dbus_string_append_byte (&result, 02289 val << 4)) 02290 goto out; 02291 } 02292 else 02293 { 02294 int len; 02295 unsigned char b; 02296 02297 len = _dbus_string_get_length (&result); 02298 02299 b = _dbus_string_get_byte (&result, len - 1); 02300 02301 b |= val; 02302 02303 _dbus_string_set_byte (&result, len - 1, b); 02304 } 02305 02306 high_bits = !high_bits; 02307 02308 ++p; 02309 } 02310 02311 done: 02312 if (!_dbus_string_move (&result, 0, dest, insert_at)) 02313 goto out; 02314 02315 if (end_return) 02316 *end_return = p - (const unsigned char*) _dbus_string_get_const_data (source); 02317 02318 retval = TRUE; 02319 02320 out: 02321 _dbus_string_free (&result); 02322 return retval; 02323 } 02324 02338 dbus_bool_t 02339 _dbus_string_validate_ascii (const DBusString *str, 02340 int start, 02341 int len) 02342 { 02343 const unsigned char *s; 02344 const unsigned char *end; 02345 DBUS_CONST_STRING_PREAMBLE (str); 02346 _dbus_assert (start >= 0); 02347 _dbus_assert (start <= real->len); 02348 _dbus_assert (len >= 0); 02349 02350 if (len > real->len - start) 02351 return FALSE; 02352 02353 s = real->str + start; 02354 end = s + len; 02355 while (s != end) 02356 { 02357 if (_DBUS_UNLIKELY (*s == '\0' || 02358 ((*s & ~0x7f) != 0))) 02359 return FALSE; 02360 02361 ++s; 02362 } 02363 02364 return TRUE; 02365 } 02366 02382 dbus_bool_t 02383 _dbus_string_validate_utf8 (const DBusString *str, 02384 int start, 02385 int len) 02386 { 02387 const unsigned char *p; 02388 const unsigned char *end; 02389 DBUS_CONST_STRING_PREAMBLE (str); 02390 _dbus_assert (start >= 0); 02391 _dbus_assert (start <= real->len); 02392 _dbus_assert (len >= 0); 02393 02394 /* we are doing _DBUS_UNLIKELY() here which might be 02395 * dubious in a generic library like GLib, but in D-BUS 02396 * we know we're validating messages and that it would 02397 * only be evil/broken apps that would have invalid 02398 * UTF-8. Also, this function seems to be a performance 02399 * bottleneck in profiles. 02400 */ 02401 02402 if (_DBUS_UNLIKELY (len > real->len - start)) 02403 return FALSE; 02404 02405 p = real->str + start; 02406 end = p + len; 02407 02408 while (p < end) 02409 { 02410 int i, mask = 0, char_len; 02411 dbus_unichar_t result; 02412 unsigned char c = (unsigned char) *p; 02413 02414 UTF8_COMPUTE (c, mask, char_len); 02415 02416 if (_DBUS_UNLIKELY (char_len == -1)) 02417 break; 02418 02419 /* check that the expected number of bytes exists in the remaining length */ 02420 if (_DBUS_UNLIKELY ((end - p) < char_len)) 02421 break; 02422 02423 UTF8_GET (result, p, i, mask, char_len); 02424 02425 if (_DBUS_UNLIKELY (UTF8_LENGTH (result) != char_len)) /* Check for overlong UTF-8 */ 02426 break; 02427 02428 if (_DBUS_UNLIKELY (result == (dbus_unichar_t)-1)) 02429 break; 02430 02431 if (_DBUS_UNLIKELY (!UNICODE_VALID (result))) 02432 break; 02433 02434 p += char_len; 02435 } 02436 02437 /* See that we covered the entire length if a length was 02438 * passed in 02439 */ 02440 if (_DBUS_UNLIKELY (p != end)) 02441 return FALSE; 02442 else 02443 return TRUE; 02444 } 02445 02459 dbus_bool_t 02460 _dbus_string_validate_nul (const DBusString *str, 02461 int start, 02462 int len) 02463 { 02464 const unsigned char *s; 02465 const unsigned char *end; 02466 DBUS_CONST_STRING_PREAMBLE (str); 02467 _dbus_assert (start >= 0); 02468 _dbus_assert (len >= 0); 02469 _dbus_assert (start <= real->len); 02470 02471 if (len > real->len - start) 02472 return FALSE; 02473 02474 s = real->str + start; 02475 end = s + len; 02476 while (s != end) 02477 { 02478 if (_DBUS_UNLIKELY (*s != '\0')) 02479 return FALSE; 02480 ++s; 02481 } 02482 02483 return TRUE; 02484 } 02485 02503 dbus_bool_t 02504 _dbus_string_validate_path (const DBusString *str, 02505 int start, 02506 int len) 02507 { 02508 const unsigned char *s; 02509 const unsigned char *end; 02510 const unsigned char *last_slash; 02511 02512 DBUS_CONST_STRING_PREAMBLE (str); 02513 _dbus_assert (start >= 0); 02514 _dbus_assert (len >= 0); 02515 _dbus_assert (start <= real->len); 02516 02517 if (len > real->len - start) 02518 return FALSE; 02519 02520 if (len > DBUS_MAXIMUM_NAME_LENGTH) 02521 return FALSE; 02522 02523 if (len == 0) 02524 return FALSE; 02525 02526 s = real->str + start; 02527 end = s + len; 02528 02529 if (*s != '/') 02530 return FALSE; 02531 last_slash = s; 02532 ++s; 02533 02534 while (s != end) 02535 { 02536 if (*s == '/') 02537 { 02538 if ((s - last_slash) < 2) 02539 return FALSE; /* no empty path components allowed */ 02540 02541 last_slash = s; 02542 } 02543 02544 ++s; 02545 } 02546 02547 if ((end - last_slash) < 2 && 02548 len > 1) 02549 return FALSE; /* trailing slash not allowed unless the string is "/" */ 02550 02551 return TRUE; 02552 } 02553 02558 #define VALID_INITIAL_NAME_CHARACTER(c) \ 02559 ( ((c) >= 'A' && (c) <= 'Z') || \ 02560 ((c) >= 'a' && (c) <= 'z') || \ 02561 ((c) == '_') ) 02562 02567 #define VALID_NAME_CHARACTER(c) \ 02568 ( ((c) >= '0' && (c) <= '9') || \ 02569 ((c) >= 'A' && (c) <= 'Z') || \ 02570 ((c) >= 'a' && (c) <= 'z') || \ 02571 ((c) == '_') ) 02572 02586 dbus_bool_t 02587 _dbus_string_validate_interface (const DBusString *str, 02588 int start, 02589 int len) 02590 { 02591 const unsigned char *s; 02592 const unsigned char *end; 02593 const unsigned char *iface; 02594 const unsigned char *last_dot; 02595 02596 DBUS_CONST_STRING_PREAMBLE (str); 02597 _dbus_assert (start >= 0); 02598 _dbus_assert (len >= 0); 02599 _dbus_assert (start <= real->len); 02600 02601 if (len > real->len - start) 02602 return FALSE; 02603 02604 if (len > DBUS_MAXIMUM_NAME_LENGTH) 02605 return FALSE; 02606 02607 if (len == 0) 02608 return FALSE; 02609 02610 last_dot = NULL; 02611 iface = real->str + start; 02612 end = iface + len; 02613 s = iface; 02614 02615 /* check special cases of first char so it doesn't have to be done 02616 * in the loop. Note we know len > 0 02617 */ 02618 if (_DBUS_UNLIKELY (*s == '.')) /* disallow starting with a . */ 02619 return FALSE; 02620 else if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*s))) 02621 return FALSE; 02622 else 02623 ++s; 02624 02625 while (s != end) 02626 { 02627 if (*s == '.') 02628 { 02629 if (_DBUS_UNLIKELY ((s + 1) == end)) 02630 return FALSE; 02631 else if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*(s + 1)))) 02632 return FALSE; 02633 last_dot = s; 02634 ++s; /* we just validated the next char, so skip two */ 02635 } 02636 else if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s))) 02637 { 02638 return FALSE; 02639 } 02640 02641 ++s; 02642 } 02643 02644 if (_DBUS_UNLIKELY (last_dot == NULL)) 02645 return FALSE; 02646 02647 return TRUE; 02648 } 02649 02663 dbus_bool_t 02664 _dbus_string_validate_member (const DBusString *str, 02665 int start, 02666 int len) 02667 { 02668 const unsigned char *s; 02669 const unsigned char *end; 02670 const unsigned char *member; 02671 02672 DBUS_CONST_STRING_PREAMBLE (str); 02673 _dbus_assert (start >= 0); 02674 _dbus_assert (len >= 0); 02675 _dbus_assert (start <= real->len); 02676 02677 if (len > real->len - start) 02678 return FALSE; 02679 02680 if (len > DBUS_MAXIMUM_NAME_LENGTH) 02681 return FALSE; 02682 02683 if (len == 0) 02684 return FALSE; 02685 02686 member = real->str + start; 02687 end = member + len; 02688 s = member; 02689 02690 /* check special cases of first char so it doesn't have to be done 02691 * in the loop. Note we know len > 0 02692 */ 02693 02694 if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*s))) 02695 return FALSE; 02696 else 02697 ++s; 02698 02699 while (s != end) 02700 { 02701 if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s))) 02702 { 02703 return FALSE; 02704 } 02705 02706 ++s; 02707 } 02708 02709 return TRUE; 02710 } 02711 02725 dbus_bool_t 02726 _dbus_string_validate_error_name (const DBusString *str, 02727 int start, 02728 int len) 02729 { 02730 /* Same restrictions as interface name at the moment */ 02731 return _dbus_string_validate_interface (str, start, len); 02732 } 02733 02734 /* This assumes the first char exists and is ':' */ 02735 static dbus_bool_t 02736 _dbus_string_validate_base_service (const DBusString *str, 02737 int start, 02738 int len) 02739 { 02740 const unsigned char *s; 02741 const unsigned char *end; 02742 const unsigned char *service; 02743 02744 DBUS_CONST_STRING_PREAMBLE (str); 02745 _dbus_assert (start >= 0); 02746 _dbus_assert (len >= 0); 02747 _dbus_assert (start <= real->len); 02748 02749 if (len > real->len - start) 02750 return FALSE; 02751 02752 if (len > DBUS_MAXIMUM_NAME_LENGTH) 02753 return FALSE; 02754 02755 _dbus_assert (len > 0); 02756 02757 service = real->str + start; 02758 end = service + len; 02759 _dbus_assert (*service == ':'); 02760 s = service + 1; 02761 02762 while (s != end) 02763 { 02764 if (*s == '.') 02765 { 02766 if (_DBUS_UNLIKELY ((s + 1) == end)) 02767 return FALSE; 02768 if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*(s + 1)))) 02769 return FALSE; 02770 ++s; /* we just validated the next char, so skip two */ 02771 } 02772 else if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s))) 02773 { 02774 return FALSE; 02775 } 02776 02777 ++s; 02778 } 02779 02780 return TRUE; 02781 } 02782 02796 dbus_bool_t 02797 _dbus_string_validate_service (const DBusString *str, 02798 int start, 02799 int len) 02800 { 02801 if (_DBUS_UNLIKELY (len == 0)) 02802 return FALSE; 02803 if (_dbus_string_get_byte (str, start) == ':') 02804 return _dbus_string_validate_base_service (str, start, len); 02805 else 02806 return _dbus_string_validate_interface (str, start, len); 02807 } 02808 02814 void 02815 _dbus_string_zero (DBusString *str) 02816 { 02817 DBUS_STRING_PREAMBLE (str); 02818 02819 memset (real->str - real->align_offset, '\0', real->allocated); 02820 } 02823 #ifdef DBUS_BUILD_TESTS 02824 #include "dbus-test.h" 02825 #include <stdio.h> 02826 02840 dbus_bool_t 02841 _dbus_string_parse_basic_type (const DBusString *str, 02842 char type, 02843 int start, 02844 void *value, 02845 int *end_return) 02846 { 02847 int end = start; 02848 02849 switch (type) 02850 { 02851 case DBUS_TYPE_BOOLEAN: 02852 { 02853 int len = _dbus_string_get_length (str) - start; 02854 if (len >= 5 && _dbus_string_find_to (str, start, start + 5, "false", NULL)) 02855 { 02856 end += 5; 02857 *(unsigned char *) value = TRUE; 02858 } 02859 else if (len >= 4 && _dbus_string_find_to (str, start, start + 4, "true", NULL)) 02860 { 02861 end += 4; 02862 *(unsigned char *) value = FALSE; 02863 } 02864 else 02865 _dbus_warn ("could not parse BOOLEAN\n"); 02866 break; 02867 } 02868 case DBUS_TYPE_BYTE: 02869 { 02870 long val = 0; 02871 02872 if (_dbus_string_get_byte (str, start) == '\'' && 02873 _dbus_string_get_length (str) >= start + 4 && 02874 _dbus_string_get_byte (str, start + 1) == '\\' && 02875 _dbus_string_get_byte (str, start + 2) == '\'' && 02876 _dbus_string_get_byte (str, start + 3) == '\'') 02877 { 02878 val = '\''; 02879 end += 4; 02880 } 02881 else if (_dbus_string_get_byte (str, start) == '\'' && 02882 _dbus_string_get_length (str) >= start + 3 && 02883 _dbus_string_get_byte (str, start + 2) == '\'') 02884 { 02885 val = _dbus_string_get_byte (str, start + 1); 02886 end += 3; 02887 } 02888 else 02889 { 02890 if (!_dbus_string_parse_int (str, start, &val, &end)) 02891 _dbus_warn ("Failed to parse integer for BYTE\n"); 02892 } 02893 02894 if (val > 255) 02895 _dbus_warn ("A byte must be in range 0-255 not %ld\n", val); 02896 02897 *(unsigned char *) value = val; 02898 break; 02899 } 02900 case DBUS_TYPE_INT32: 02901 { 02902 long val; 02903 if (_dbus_string_parse_int (str, start, &val, &end)) 02904 *(dbus_int32_t *)value = val; 02905 break; 02906 } 02907 case DBUS_TYPE_UINT32: 02908 { 02909 unsigned long val; 02910 if (_dbus_string_parse_uint (str, start, &val, &end)) 02911 *(dbus_uint32_t *)value = val; 02912 break; 02913 } 02914 #ifdef DBUS_HAVE_INT64 02915 case DBUS_TYPE_INT64: 02916 case DBUS_TYPE_UINT64: 02917 /* use stroll oull */ 02918 _dbus_assert_not_reached ("string -> [u]int64 not supported yet"); 02919 break; 02920 #endif /* DBUS_HAVE_INT64 */ 02921 case DBUS_TYPE_DOUBLE: 02922 _dbus_string_parse_double (str, start, value, &end); 02923 break; 02924 default: 02925 _dbus_assert_not_reached ("not a basic type"); 02926 break; 02927 } 02928 if (end_return) 02929 *end_return = end; 02930 02931 return end != start; 02932 } 02933 02934 static void 02935 test_max_len (DBusString *str, 02936 int max_len) 02937 { 02938 if (max_len > 0) 02939 { 02940 if (!_dbus_string_set_length (str, max_len - 1)) 02941 _dbus_assert_not_reached ("setting len to one less than max should have worked"); 02942 } 02943 02944 if (!_dbus_string_set_length (str, max_len)) 02945 _dbus_assert_not_reached ("setting len to max len should have worked"); 02946 02947 if (_dbus_string_set_length (str, max_len + 1)) 02948 _dbus_assert_not_reached ("setting len to one more than max len should not have worked"); 02949 02950 if (!_dbus_string_set_length (str, 0)) 02951 _dbus_assert_not_reached ("setting len to zero should have worked"); 02952 } 02953 02954 static void 02955 test_hex_roundtrip (const unsigned char *data, 02956 int len) 02957 { 02958 DBusString orig; 02959 DBusString encoded; 02960 DBusString decoded; 02961 int end; 02962 02963 if (len < 0) 02964 len = strlen (data); 02965 02966 if (!_dbus_string_init (&orig)) 02967 _dbus_assert_not_reached ("could not init string"); 02968 02969 if (!_dbus_string_init (&encoded)) 02970 _dbus_assert_not_reached ("could not init string"); 02971 02972 if (!_dbus_string_init (&decoded)) 02973 _dbus_assert_not_reached ("could not init string"); 02974 02975 if (!_dbus_string_append_len (&orig, data, len)) 02976 _dbus_assert_not_reached ("couldn't append orig data"); 02977 02978 if (!_dbus_string_hex_encode (&orig, 0, &encoded, 0)) 02979 _dbus_assert_not_reached ("could not encode"); 02980 02981 if (!_dbus_string_hex_decode (&encoded, 0, &end, &decoded, 0)) 02982 _dbus_assert_not_reached ("could not decode"); 02983 02984 _dbus_assert (_dbus_string_get_length (&encoded) == end); 02985 02986 if (!_dbus_string_equal (&orig, &decoded)) 02987 { 02988 const char *s; 02989 02990 printf ("Original string %d bytes encoded %d bytes decoded %d bytes\n", 02991 _dbus_string_get_length (&orig), 02992 _dbus_string_get_length (&encoded), 02993 _dbus_string_get_length (&decoded)); 02994 printf ("Original: %s\n", data); 02995 s = _dbus_string_get_const_data (&decoded); 02996 printf ("Decoded: %s\n", s); 02997 _dbus_assert_not_reached ("original string not the same as string decoded from hex"); 02998 } 02999 03000 _dbus_string_free (&orig); 03001 _dbus_string_free (&encoded); 03002 _dbus_string_free (&decoded); 03003 } 03004 03005 typedef void (* TestRoundtripFunc) (const unsigned char *data, 03006 int len); 03007 static void 03008 test_roundtrips (TestRoundtripFunc func) 03009 { 03010 (* func) ("Hello this is a string\n", -1); 03011 (* func) ("Hello this is a string\n1", -1); 03012 (* func) ("Hello this is a string\n12", -1); 03013 (* func) ("Hello this is a string\n123", -1); 03014 (* func) ("Hello this is a string\n1234", -1); 03015 (* func) ("Hello this is a string\n12345", -1); 03016 (* func) ("", 0); 03017 (* func) ("1", 1); 03018 (* func) ("12", 2); 03019 (* func) ("123", 3); 03020 (* func) ("1234", 4); 03021 (* func) ("12345", 5); 03022 (* func) ("", 1); 03023 (* func) ("1", 2); 03024 (* func) ("12", 3); 03025 (* func) ("123", 4); 03026 (* func) ("1234", 5); 03027 (* func) ("12345", 6); 03028 { 03029 unsigned char buf[512]; 03030 int i; 03031 03032 i = 0; 03033 while (i < _DBUS_N_ELEMENTS (buf)) 03034 { 03035 buf[i] = i; 03036 ++i; 03037 } 03038 i = 0; 03039 while (i < _DBUS_N_ELEMENTS (buf)) 03040 { 03041 (* func) (buf, i); 03042 ++i; 03043 } 03044 } 03045 } 03046 03047 03058 dbus_bool_t 03059 _dbus_string_test (void) 03060 { 03061 DBusString str; 03062 DBusString other; 03063 int i, end; 03064 long v; 03065 double d; 03066 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 }; 03067 char *s; 03068 dbus_unichar_t ch; 03069 const char *valid_paths[] = { 03070 "/", 03071 "/foo/bar", 03072 "/foo", 03073 "/foo/bar/baz" 03074 }; 03075 const char *invalid_paths[] = { 03076 "bar", 03077 "bar/baz", 03078 "/foo/bar/", 03079 "/foo/" 03080 "foo/", 03081 "boo//blah", 03082 "//", 03083 " 03084 "foo 03085 "Hello World", 03086 "", 03087 " ", 03088 "foo bar" 03089 }; 03090 03091 const char *valid_interfaces[] = { 03092 "org.freedesktop.Foo", 03093 "Bar.Baz", 03094 "Blah.Blah.Blah.Blah.Blah", 03095 "a.b", 03096 "a.b.c.d.e.f.g", 03097 "a0.b1.c2.d3.e4.f5.g6", 03098 "abc123.foo27" 03099 }; 03100 const char *invalid_interfaces[] = { 03101 ".", 03102 "", 03103 "..", 03104 ".Foo.Bar", 03105 "..Foo.Bar", 03106 "Foo.Bar.", 03107 "Foo.Bar..", 03108 "Foo", 03109 "9foo.bar.baz", 03110 "foo.bar..baz", 03111 "foo.bar...baz", 03112 "foo.bar.b..blah", 03113 ":", 03114 ":0-1", 03115 "10", 03116 ":11.34324", 03117 "0.0.0", 03118 "0..0", 03119 "foo.Bar.%", 03120 "foo.Bar!!", 03121 "!Foo.bar.bz", 03122 "foo.$.blah", 03123 "", 03124 " ", 03125 "foo bar" 03126 }; 03127 03128 const char *valid_base_services[] = { 03129 ":0", 03130 ":a", 03131 ":", 03132 ":.a", 03133 ":.1", 03134 ":0.1", 03135 ":000.2222", 03136 ":.blah", 03137 ":abce.freedesktop.blah" 03138 }; 03139 const char *invalid_base_services[] = { 03140 ":-", 03141 ":!", 03142 ":0-10", 03143 ":blah.", 03144 ":blah.", 03145 ":blah..org", 03146 ":blah.org..", 03147 ":..blah.org", 03148 "", 03149 " ", 03150 "foo bar" 03151 }; 03152 03153 const char *valid_members[] = { 03154 "Hello", 03155 "Bar", 03156 "foobar", 03157 "_foobar", 03158 "foo89" 03159 }; 03160 03161 const char *invalid_members[] = { 03162 "9Hello", 03163 "10", 03164 "1", 03165 "foo-bar", 03166 "blah.org", 03167 ".blah", 03168 "blah.", 03169 "Hello.", 03170 "!foo", 03171 "", 03172 " ", 03173 "foo bar" 03174 }; 03175 03176 i = 0; 03177 while (i < _DBUS_N_ELEMENTS (lens)) 03178 { 03179 if (!_dbus_string_init (&str)) 03180 _dbus_assert_not_reached ("failed to init string"); 03181 03182 set_max_length (&str, lens[i]); 03183 03184 test_max_len (&str, lens[i]); 03185 _dbus_string_free (&str); 03186 03187 ++i; 03188 } 03189 03190 /* Test shortening and setting length */ 03191 i = 0; 03192 while (i < _DBUS_N_ELEMENTS (lens)) 03193 { 03194 int j; 03195 03196 if (!_dbus_string_init (&str)) 03197 _dbus_assert_not_reached ("failed to init string"); 03198 03199 set_max_length (&str, lens[i]); 03200 03201 if (!_dbus_string_set_length (&str, lens[i])) 03202 _dbus_assert_not_reached ("failed to set string length"); 03203 03204 j = lens[i]; 03205 while (j > 0) 03206 { 03207 _dbus_assert (_dbus_string_get_length (&str) == j); 03208 if (j > 0) 03209 { 03210 _dbus_string_shorten (&str, 1); 03211 _dbus_assert (_dbus_string_get_length (&str) == (j - 1)); 03212 } 03213 --j; 03214 } 03215 03216 _dbus_string_free (&str); 03217 03218 ++i; 03219 } 03220 03221 /* Test appending data */ 03222 if (!_dbus_string_init (&str)) 03223 _dbus_assert_not_reached ("failed to init string"); 03224 03225 i = 0; 03226 while (i < 10) 03227 { 03228 if (!_dbus_string_append (&str, "a")) 03229 _dbus_assert_not_reached ("failed to append string to string\n"); 03230 03231 _dbus_assert (_dbus_string_get_length (&str) == i * 2 + 1); 03232 03233 if (!_dbus_string_append_byte (&str, 'b')) 03234 _dbus_assert_not_reached ("failed to append byte to string\n"); 03235 03236 _dbus_assert (_dbus_string_get_length (&str) == i * 2 + 2); 03237 03238 ++i; 03239 } 03240 03241 _dbus_string_free (&str); 03242 03243 /* Check steal_data */ 03244 03245 if (!_dbus_string_init (&str)) 03246 _dbus_assert_not_reached ("failed to init string"); 03247 03248 if (!_dbus_string_append (&str, "Hello World")) 03249 _dbus_assert_not_reached ("could not append to string"); 03250 03251 i = _dbus_string_get_length (&str); 03252 03253 if (!_dbus_string_steal_data (&str, &s)) 03254 _dbus_assert_not_reached ("failed to steal data"); 03255 03256 _dbus_assert (_dbus_string_get_length (&str) == 0); 03257 _dbus_assert (((int)strlen (s)) == i); 03258 03259 dbus_free (s); 03260 03261 /* Check move */ 03262 03263 if (!_dbus_string_append (&str, "Hello World")) 03264 _dbus_assert_not_reached ("could not append to string"); 03265 03266 i = _dbus_string_get_length (&str); 03267 03268 if (!_dbus_string_init (&other)) 03269 _dbus_assert_not_reached ("could not init string"); 03270 03271 if (!_dbus_string_move (&str, 0, &other, 0)) 03272 _dbus_assert_not_reached ("could not move"); 03273 03274 _dbus_assert (_dbus_string_get_length (&str) == 0); 03275 _dbus_assert (_dbus_string_get_length (&other) == i); 03276 03277 if (!_dbus_string_append (&str, "Hello World")) 03278 _dbus_assert_not_reached ("could not append to string"); 03279 03280 if (!_dbus_string_move (&str, 0, &other, _dbus_string_get_length (&other))) 03281 _dbus_assert_not_reached ("could not move"); 03282 03283 _dbus_assert (_dbus_string_get_length (&str) == 0); 03284 _dbus_assert (_dbus_string_get_length (&other) == i * 2); 03285 03286 if (!_dbus_string_append (&str, "Hello World")) 03287 _dbus_assert_not_reached ("could not append to string"); 03288 03289 if (!_dbus_string_move (&str, 0, &other, _dbus_string_get_length (&other) / 2)) 03290 _dbus_assert_not_reached ("could not move"); 03291 03292 _dbus_assert (_dbus_string_get_length (&str) == 0); 03293 _dbus_assert (_dbus_string_get_length (&other) == i * 3); 03294 03295 _dbus_string_free (&other); 03296 03297 /* Check copy */ 03298 03299 if (!_dbus_string_append (&str, "Hello World")) 03300 _dbus_assert_not_reached ("could not append to string"); 03301 03302 i = _dbus_string_get_length (&str); 03303 03304 if (!_dbus_string_init (&other)) 03305 _dbus_assert_not_reached ("could not init string"); 03306 03307 if (!_dbus_string_copy (&str, 0, &other, 0)) 03308 _dbus_assert_not_reached ("could not copy"); 03309 03310 _dbus_assert (_dbus_string_get_length (&str) == i); 03311 _dbus_assert (_dbus_string_get_length (&other) == i); 03312 03313 if (!_dbus_string_copy (&str, 0, &other, _dbus_string_get_length (&other))) 03314 _dbus_assert_not_reached ("could not copy"); 03315 03316 _dbus_assert (_dbus_string_get_length (&str) == i); 03317 _dbus_assert (_dbus_string_get_length (&other) == i * 2); 03318 _dbus_assert (_dbus_string_equal_c_str (&other, 03319 "Hello WorldHello World")); 03320 03321 if (!_dbus_string_copy (&str, 0, &other, _dbus_string_get_length (&other) / 2)) 03322 _dbus_assert_not_reached ("could not copy"); 03323 03324 _dbus_assert (_dbus_string_get_length (&str) == i); 03325 _dbus_assert (_dbus_string_get_length (&other) == i * 3); 03326 _dbus_assert (_dbus_string_equal_c_str (&other, 03327 "Hello WorldHello WorldHello World")); 03328 03329 _dbus_string_free (&str); 03330 _dbus_string_free (&other); 03331 03332 /* Check replace */ 03333 03334 if (!_dbus_string_init (&str)) 03335 _dbus_assert_not_reached ("failed to init string"); 03336 03337 if (!_dbus_string_append (&str, "Hello World")) 03338 _dbus_assert_not_reached ("could not append to string"); 03339 03340 i = _dbus_string_get_length (&str); 03341 03342 if (!_dbus_string_init (&other)) 03343 _dbus_assert_not_reached ("could not init string"); 03344 03345 if (!_dbus_string_replace_len (&str, 0, _dbus_string_get_length (&str), 03346 &other, 0, _dbus_string_get_length (&other))) 03347 _dbus_assert_not_reached ("could not replace"); 03348 03349 _dbus_assert (_dbus_string_get_length (&str) == i); 03350 _dbus_assert (_dbus_string_get_length (&other) == i); 03351 _dbus_assert (_dbus_string_equal_c_str (&other, "Hello World")); 03352 03353 if (!_dbus_string_replace_len (&str, 0, _dbus_string_get_length (&str), 03354 &other, 5, 1)) 03355 _dbus_assert_not_reached ("could not replace center space"); 03356 03357 _dbus_assert (_dbus_string_get_length (&str) == i); 03358 _dbus_assert (_dbus_string_get_length (&other) == i * 2 - 1); 03359 _dbus_assert (_dbus_string_equal_c_str (&other, 03360 "HelloHello WorldWorld")); 03361 03362 03363 if (!_dbus_string_replace_len (&str, 1, 1, 03364 &other, 03365 _dbus_string_get_length (&other) - 1, 03366 1)) 03367 _dbus_assert_not_reached ("could not replace end character"); 03368 03369 _dbus_assert (_dbus_string_get_length (&str) == i); 03370 _dbus_assert (_dbus_string_get_length (&other) == i * 2 - 1); 03371 _dbus_assert (_dbus_string_equal_c_str (&other, 03372 "HelloHello WorldWorle")); 03373 03374 _dbus_string_free (&str); 03375 _dbus_string_free (&other); 03376 03377 /* Check append/get unichar */ 03378 03379 if (!_dbus_string_init (&str)) 03380 _dbus_assert_not_reached ("failed to init string"); 03381 03382 ch = 0; 03383 if (!_dbus_string_append_unichar (&str, 0xfffc)) 03384 _dbus_assert_not_reached ("failed to append unichar"); 03385 03386 _dbus_string_get_unichar (&str, 0, &ch, &i); 03387 03388 _dbus_assert (ch == 0xfffc); 03389 _dbus_assert (i == _dbus_string_get_length (&str)); 03390 03391 _dbus_string_free (&str); 03392 03393 /* Check insert/set/get byte */ 03394 03395 if (!_dbus_string_init (&str)) 03396 _dbus_assert_not_reached ("failed to init string"); 03397 03398 if (!_dbus_string_append (&str, "Hello")) 03399 _dbus_assert_not_reached ("failed to append Hello"); 03400 03401 _dbus_assert (_dbus_string_get_byte (&str, 0) == 'H'); 03402 _dbus_assert (_dbus_string_get_byte (&str, 1) == 'e'); 03403 _dbus_assert (_dbus_string_get_byte (&str, 2) == 'l'); 03404 _dbus_assert (_dbus_string_get_byte (&str, 3) == 'l'); 03405 _dbus_assert (_dbus_string_get_byte (&str, 4) == 'o'); 03406 03407 _dbus_string_set_byte (&str, 1, 'q'); 03408 _dbus_assert (_dbus_string_get_byte (&str, 1) == 'q'); 03409 03410 if (!_dbus_string_insert_bytes (&str, 0, 1, 255)) 03411 _dbus_assert_not_reached ("can't insert byte"); 03412 03413 if (!_dbus_string_insert_bytes (&str, 2, 4, 'Z')) 03414 _dbus_assert_not_reached ("can't insert byte"); 03415 03416 if (!_dbus_string_insert_bytes (&str, _dbus_string_get_length (&str), 1, 'W')) 03417 _dbus_assert_not_reached ("can't insert byte"); 03418 03419 _dbus_assert (_dbus_string_get_byte (&str, 0) == 255); 03420 _dbus_assert (_dbus_string_get_byte (&str, 1) == 'H'); 03421 _dbus_assert (_dbus_string_get_byte (&str, 2) == 'Z'); 03422 _dbus_assert (_dbus_string_get_byte (&str, 3) == 'Z'); 03423 _dbus_assert (_dbus_string_get_byte (&str, 4) == 'Z'); 03424 _dbus_assert (_dbus_string_get_byte (&str, 5) == 'Z'); 03425 _dbus_assert (_dbus_string_get_byte (&str, 6) == 'q'); 03426 _dbus_assert (_dbus_string_get_byte (&str, 7) == 'l'); 03427 _dbus_assert (_dbus_string_get_byte (&str, 8) == 'l'); 03428 _dbus_assert (_dbus_string_get_byte (&str, 9) == 'o'); 03429 _dbus_assert (_dbus_string_get_byte (&str, 10) == 'W'); 03430 03431 _dbus_string_free (&str); 03432 03433 /* Check append/parse int/double */ 03434 03435 if (!_dbus_string_init (&str)) 03436 _dbus_assert_not_reached ("failed to init string"); 03437 03438 if (!_dbus_string_append_int (&str, 27)) 03439 _dbus_assert_not_reached ("failed to append int"); 03440 03441 i = _dbus_string_get_length (&str); 03442 03443 if (!_dbus_string_parse_int (&str, 0, &v, &end)) 03444 _dbus_assert_not_reached ("failed to parse int"); 03445 03446 _dbus_assert (v == 27); 03447 _dbus_assert (end == i); 03448 03449 _dbus_string_free (&str); 03450 03451 if (!_dbus_string_init (&str)) 03452 _dbus_assert_not_reached ("failed to init string"); 03453 03454 if (!_dbus_string_append_double (&str, 50.3)) 03455 _dbus_assert_not_reached ("failed to append float"); 03456 03457 i = _dbus_string_get_length (&str); 03458 03459 if (!_dbus_string_parse_double (&str, 0, &d, &end)) 03460 _dbus_assert_not_reached ("failed to parse float"); 03461 03462 _dbus_assert (d > (50.3 - 1e-6) && d < (50.3 + 1e-6)); 03463 _dbus_assert (end == i); 03464 03465 _dbus_string_free (&str); 03466 03467 /* Test find */ 03468 if (!_dbus_string_init (&str)) 03469 _dbus_assert_not_reached ("failed to init string"); 03470 03471 if (!_dbus_string_append (&str, "Hello")) 03472 _dbus_assert_not_reached ("couldn't append to string"); 03473 03474 if (!_dbus_string_find (&str, 0, "He", &i)) 03475 _dbus_assert_not_reached ("didn't find 'He'"); 03476 _dbus_assert (i == 0); 03477 03478 if (!_dbus_string_find (&str, 0, "Hello", &i)) 03479 _dbus_assert_not_reached ("didn't find 'Hello'"); 03480 _dbus_assert (i == 0); 03481 03482 if (!_dbus_string_find (&str, 0, "ello", &i)) 03483 _dbus_assert_not_reached ("didn't find 'ello'"); 03484 _dbus_assert (i == 1); 03485 03486 if (!_dbus_string_find (&str, 0, "lo", &i)) 03487 _dbus_assert_not_reached ("didn't find 'lo'"); 03488 _dbus_assert (i == 3); 03489 03490 if (!_dbus_string_find (&str, 2, "lo", &i)) 03491 _dbus_assert_not_reached ("didn't find 'lo'"); 03492 _dbus_assert (i == 3); 03493 03494 if (_dbus_string_find (&str, 4, "lo", &i)) 03495 _dbus_assert_not_reached ("did find 'lo'"); 03496 03497 if (!_dbus_string_find (&str, 0, "l", &i)) 03498 _dbus_assert_not_reached ("didn't find 'l'"); 03499 _dbus_assert (i == 2); 03500 03501 if (!_dbus_string_find (&str, 0, "H", &i)) 03502 _dbus_assert_not_reached ("didn't find 'H'"); 03503 _dbus_assert (i == 0); 03504 03505 if (!_dbus_string_find (&str, 0, "", &i)) 03506 _dbus_assert_not_reached ("didn't find ''"); 03507 _dbus_assert (i == 0); 03508 03509 if (_dbus_string_find (&str, 0, "Hello!", NULL)) 03510 _dbus_assert_not_reached ("Did find 'Hello!'"); 03511 03512 if (_dbus_string_find (&str, 0, "Oh, Hello", NULL)) 03513 _dbus_assert_not_reached ("Did find 'Oh, Hello'"); 03514 03515 if (_dbus_string_find (&str, 0, "ill", NULL)) 03516 _dbus_assert_not_reached ("Did find 'ill'"); 03517 03518 if (_dbus_string_find (&str, 0, "q", NULL)) 03519 _dbus_assert_not_reached ("Did find 'q'"); 03520 03521 if (!_dbus_string_find_to (&str, 0, 2, "He", NULL)) 03522 _dbus_assert_not_reached ("Didn't find 'He'"); 03523 03524 if (_dbus_string_find_to (&str, 0, 2, "Hello", NULL)) 03525 _dbus_assert_not_reached ("Did find 'Hello'"); 03526 03527 if (!_dbus_string_find_byte_backward (&str, _dbus_string_get_length (&str), 'H', &i)) 03528 _dbus_assert_not_reached ("Did not find 'H'"); 03529 _dbus_assert (i == 0); 03530 03531 if (!_dbus_string_find_byte_backward (&str, _dbus_string_get_length (&str), 'o', &i)) 03532 _dbus_assert_not_reached ("Did not find 'o'"); 03533 _dbus_assert (i == _dbus_string_get_length (&str) - 1); 03534 03535 if (_dbus_string_find_byte_backward (&str, _dbus_string_get_length (&str) - 1, 'o', &i)) 03536 _dbus_assert_not_reached ("Did find 'o'"); 03537 _dbus_assert (i == -1); 03538 03539 if (_dbus_string_find_byte_backward (&str, 1, 'e', &i)) 03540 _dbus_assert_not_reached ("Did find 'e'"); 03541 _dbus_assert (i == -1); 03542 03543 if (!_dbus_string_find_byte_backward (&str, 2, 'e', &i)) 03544 _dbus_assert_not_reached ("Didn't find 'e'"); 03545 _dbus_assert (i == 1); 03546 03547 _dbus_string_free (&str); 03548 03549 /* Hex encoding */ 03550 _dbus_string_init_const (&str, "cafebabe, this is a bogus hex string"); 03551 if (!_dbus_string_init (&other)) 03552 _dbus_assert_not_reached ("could not init string"); 03553 03554 if (!_dbus_string_hex_decode (&str, 0, &end, &other, 0)) 03555 _dbus_assert_not_reached ("deccoded bogus hex string with no error"); 03556 03557 _dbus_assert (end == 8); 03558 03559 _dbus_string_free (&other); 03560 03561 test_roundtrips (test_hex_roundtrip); 03562 03563 /* Path validation */ 03564 i = 0; 03565 while (i < (int) _DBUS_N_ELEMENTS (valid_paths)) 03566 { 03567 _dbus_string_init_const (&str, valid_paths[i]); 03568 03569 if (!_dbus_string_validate_path (&str, 0, 03570 _dbus_string_get_length (&str))) 03571 { 03572 _dbus_warn ("Path \"%s\" should have been valid\n", valid_paths[i]); 03573 _dbus_assert_not_reached ("invalid path"); 03574 } 03575 03576 ++i; 03577 } 03578 03579 i = 0; 03580 while (i < (int) _DBUS_N_ELEMENTS (invalid_paths)) 03581 { 03582 _dbus_string_init_const (&str, invalid_paths[i]); 03583 03584 if (_dbus_string_validate_path (&str, 0, 03585 _dbus_string_get_length (&str))) 03586 { 03587 _dbus_warn ("Path \"%s\" should have been invalid\n", invalid_paths[i]); 03588 _dbus_assert_not_reached ("valid path"); 03589 } 03590 03591 ++i; 03592 } 03593 03594 /* Interface validation */ 03595 i = 0; 03596 while (i < (int) _DBUS_N_ELEMENTS (valid_interfaces)) 03597 { 03598 _dbus_string_init_const (&str, valid_interfaces[i]); 03599 03600 if (!_dbus_string_validate_interface (&str, 0, 03601 _dbus_string_get_length (&str))) 03602 { 03603 _dbus_warn ("Interface \"%s\" should have been valid\n", valid_interfaces[i]); 03604 _dbus_assert_not_reached ("invalid interface"); 03605 } 03606 03607 ++i; 03608 } 03609 03610 i = 0; 03611 while (i < (int) _DBUS_N_ELEMENTS (invalid_interfaces)) 03612 { 03613 _dbus_string_init_const (&str, invalid_interfaces[i]); 03614 03615 if (_dbus_string_validate_interface (&str, 0, 03616 _dbus_string_get_length (&str))) 03617 { 03618 _dbus_warn ("Interface \"%s\" should have been invalid\n", invalid_interfaces[i]); 03619 _dbus_assert_not_reached ("valid interface"); 03620 } 03621 03622 ++i; 03623 } 03624 03625 /* Service validation (check that valid interfaces are valid services, 03626 * and invalid interfaces are invalid services except if they start with ':') 03627 */ 03628 i = 0; 03629 while (i < (int) _DBUS_N_ELEMENTS (valid_interfaces)) 03630 { 03631 _dbus_string_init_const (&str, valid_interfaces[i]); 03632 03633 if (!_dbus_string_validate_service (&str, 0, 03634 _dbus_string_get_length (&str))) 03635 { 03636 _dbus_warn ("Service \"%s\" should have been valid\n", valid_interfaces[i]); 03637 _dbus_assert_not_reached ("invalid service"); 03638 } 03639 03640 ++i; 03641 } 03642 03643 i = 0; 03644 while (i < (int) _DBUS_N_ELEMENTS (invalid_interfaces)) 03645 { 03646 if (invalid_interfaces[i][0] != ':') 03647 { 03648 _dbus_string_init_const (&str, invalid_interfaces[i]); 03649 03650 if (_dbus_string_validate_service (&str, 0, 03651 _dbus_string_get_length (&str))) 03652 { 03653 _dbus_warn ("Service \"%s\" should have been invalid\n", invalid_interfaces[i]); 03654 _dbus_assert_not_reached ("valid service"); 03655 } 03656 } 03657 03658 ++i; 03659 } 03660 03661 /* Base service validation */ 03662 i = 0; 03663 while (i < (int) _DBUS_N_ELEMENTS (valid_base_services)) 03664 { 03665 _dbus_string_init_const (&str, valid_base_services[i]); 03666 03667 if (!_dbus_string_validate_service (&str, 0, 03668 _dbus_string_get_length (&str))) 03669 { 03670 _dbus_warn ("Service \"%s\" should have been valid\n", valid_base_services[i]); 03671 _dbus_assert_not_reached ("invalid base service"); 03672 } 03673 03674 ++i; 03675 } 03676 03677 i = 0; 03678 while (i < (int) _DBUS_N_ELEMENTS (invalid_base_services)) 03679 { 03680 _dbus_string_init_const (&str, invalid_base_services[i]); 03681 03682 if (_dbus_string_validate_service (&str, 0, 03683 _dbus_string_get_length (&str))) 03684 { 03685 _dbus_warn ("Service \"%s\" should have been invalid\n", invalid_base_services[i]); 03686 _dbus_assert_not_reached ("valid base service"); 03687 } 03688 03689 ++i; 03690 } 03691 03692 03693 /* Error name validation (currently identical to interfaces) 03694 */ 03695 i = 0; 03696 while (i < (int) _DBUS_N_ELEMENTS (valid_interfaces)) 03697 { 03698 _dbus_string_init_const (&str, valid_interfaces[i]); 03699 03700 if (!_dbus_string_validate_error_name (&str, 0, 03701 _dbus_string_get_length (&str))) 03702 { 03703 _dbus_warn ("Error name \"%s\" should have been valid\n", valid_interfaces[i]); 03704 _dbus_assert_not_reached ("invalid error name"); 03705 } 03706 03707 ++i; 03708 } 03709 03710 i = 0; 03711 while (i < (int) _DBUS_N_ELEMENTS (invalid_interfaces)) 03712 { 03713 if (invalid_interfaces[i][0] != ':') 03714 { 03715 _dbus_string_init_const (&str, invalid_interfaces[i]); 03716 03717 if (_dbus_string_validate_error_name (&str, 0, 03718 _dbus_string_get_length (&str))) 03719 { 03720 _dbus_warn ("Error name \"%s\" should have been invalid\n", invalid_interfaces[i]); 03721 _dbus_assert_not_reached ("valid error name"); 03722 } 03723 } 03724 03725 ++i; 03726 } 03727 03728 /* Member validation */ 03729 i = 0; 03730 while (i < (int) _DBUS_N_ELEMENTS (valid_members)) 03731 { 03732 _dbus_string_init_const (&str, valid_members[i]); 03733 03734 if (!_dbus_string_validate_member (&str, 0, 03735 _dbus_string_get_length (&str))) 03736 { 03737 _dbus_warn ("Member \"%s\" should have been valid\n", valid_members[i]); 03738 _dbus_assert_not_reached ("invalid member"); 03739 } 03740 03741 ++i; 03742 } 03743 03744 i = 0; 03745 while (i < (int) _DBUS_N_ELEMENTS (invalid_members)) 03746 { 03747 _dbus_string_init_const (&str, invalid_members[i]); 03748 03749 if (_dbus_string_validate_member (&str, 0, 03750 _dbus_string_get_length (&str))) 03751 { 03752 _dbus_warn ("Member \"%s\" should have been invalid\n", invalid_members[i]); 03753 _dbus_assert_not_reached ("valid member"); 03754 } 03755 03756 ++i; 03757 } 03758 03759 /* Validate claimed length longer than real length */ 03760 _dbus_string_init_const (&str, "abc.efg"); 03761 if (_dbus_string_validate_service (&str, 0, 8)) 03762 _dbus_assert_not_reached ("validated too-long string"); 03763 if (_dbus_string_validate_interface (&str, 0, 8)) 03764 _dbus_assert_not_reached ("validated too-long string"); 03765 if (_dbus_string_validate_error_name (&str, 0, 8)) 03766 _dbus_assert_not_reached ("validated too-long string"); 03767 03768 _dbus_string_init_const (&str, "abc"); 03769 if (_dbus_string_validate_member (&str, 0, 4)) 03770 _dbus_assert_not_reached ("validated too-long string"); 03771 03772 /* Validate string exceeding max name length */ 03773 if (!_dbus_string_init (&str)) 03774 _dbus_assert_not_reached ("no memory"); 03775 03776 while (_dbus_string_get_length (&str) <= DBUS_MAXIMUM_NAME_LENGTH) 03777 if (!_dbus_string_append (&str, "abc.def")) 03778 _dbus_assert_not_reached ("no memory"); 03779 03780 if (_dbus_string_validate_service (&str, 0, _dbus_string_get_length (&str))) 03781 _dbus_assert_not_reached ("validated overmax string"); 03782 if (_dbus_string_validate_interface (&str, 0, _dbus_string_get_length (&str))) 03783 _dbus_assert_not_reached ("validated overmax string"); 03784 if (_dbus_string_validate_error_name (&str, 0, _dbus_string_get_length (&str))) 03785 _dbus_assert_not_reached ("validated overmax string"); 03786 03787 /* overlong member */ 03788 _dbus_string_set_length (&str, 0); 03789 while (_dbus_string_get_length (&str) <= DBUS_MAXIMUM_NAME_LENGTH) 03790 if (!_dbus_string_append (&str, "abc")) 03791 _dbus_assert_not_reached ("no memory"); 03792 03793 if (_dbus_string_validate_member (&str, 0, _dbus_string_get_length (&str))) 03794 _dbus_assert_not_reached ("validated overmax string"); 03795 03796 /* overlong base service */ 03797 _dbus_string_set_length (&str, 0); 03798 _dbus_string_append (&str, ":"); 03799 while (_dbus_string_get_length (&str) <= DBUS_MAXIMUM_NAME_LENGTH) 03800 if (!_dbus_string_append (&str, "abc")) 03801 _dbus_assert_not_reached ("no memory"); 03802 03803 if (_dbus_string_validate_service (&str, 0, _dbus_string_get_length (&str))) 03804 _dbus_assert_not_reached ("validated overmax string"); 03805 03806 _dbus_string_free (&str); 03807 03808 return TRUE; 03809 } 03810 03811 #endif /* DBUS_BUILD_TESTS */

Generated on Mon Aug 16 17:40:11 2004 for D-BUS by doxygen 1.3.8