D-Bus 1.4.1
|
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ 00002 /* dbus-string.c String utility class (internal to D-Bus implementation) 00003 * 00004 * Copyright (C) 2002, 2003, 2004, 2005 Red Hat, Inc. 00005 * Copyright (C) 2006 Ralf Habacker <ralf.habacker@freenet.de> 00006 * 00007 * Licensed under the Academic Free License version 2.1 00008 * 00009 * This program is free software; you can redistribute it and/or modify 00010 * it under the terms of the GNU General Public License as published by 00011 * the Free Software Foundation; either version 2 of the License, or 00012 * (at your option) any later version. 00013 * 00014 * This program is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 * GNU General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU General Public License 00020 * along with this program; if not, write to the Free Software 00021 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00022 * 00023 */ 00024 00025 #include <config.h> 00026 #include "dbus-internals.h" 00027 #include "dbus-string.h" 00028 /* we allow a system header here, for speed/convenience */ 00029 #include <string.h> 00030 /* for vsnprintf */ 00031 #include <stdio.h> 00032 #define DBUS_CAN_USE_DBUS_STRING_PRIVATE 1 00033 #include "dbus-string-private.h" 00034 #include "dbus-marshal-basic.h" /* probably should be removed by moving the usage of DBUS_TYPE 00035 * into the marshaling-related files 00036 */ 00037 /* for DBUS_VA_COPY */ 00038 #include "dbus-sysdeps.h" 00039 00078 static void 00079 fixup_alignment (DBusRealString *real) 00080 { 00081 unsigned char *aligned; 00082 unsigned char *real_block; 00083 unsigned int old_align_offset; 00084 00085 /* we have to have extra space in real->allocated for the align offset and nul byte */ 00086 _dbus_assert (real->len <= real->allocated - _DBUS_STRING_ALLOCATION_PADDING); 00087 00088 old_align_offset = real->align_offset; 00089 real_block = real->str - old_align_offset; 00090 00091 aligned = _DBUS_ALIGN_ADDRESS (real_block, 8); 00092 00093 real->align_offset = aligned - real_block; 00094 real->str = aligned; 00095 00096 if (old_align_offset != real->align_offset) 00097 { 00098 /* Here comes the suck */ 00099 memmove (real_block + real->align_offset, 00100 real_block + old_align_offset, 00101 real->len + 1); 00102 } 00103 00104 _dbus_assert (real->align_offset < 8); 00105 _dbus_assert (_DBUS_ALIGN_ADDRESS (real->str, 8) == real->str); 00106 } 00107 00108 static void 00109 undo_alignment (DBusRealString *real) 00110 { 00111 if (real->align_offset != 0) 00112 { 00113 memmove (real->str - real->align_offset, 00114 real->str, 00115 real->len + 1); 00116 00117 real->str = real->str - real->align_offset; 00118 real->align_offset = 0; 00119 } 00120 } 00121 00131 dbus_bool_t 00132 _dbus_string_init_preallocated (DBusString *str, 00133 int allocate_size) 00134 { 00135 DBusRealString *real; 00136 00137 _dbus_assert (str != NULL); 00138 00139 _dbus_assert (sizeof (DBusString) == sizeof (DBusRealString)); 00140 00141 real = (DBusRealString*) str; 00142 00143 /* It's very important not to touch anything 00144 * other than real->str if we're going to fail, 00145 * since we also use this function to reset 00146 * an existing string, e.g. in _dbus_string_steal_data() 00147 */ 00148 00149 real->str = dbus_malloc (_DBUS_STRING_ALLOCATION_PADDING + allocate_size); 00150 if (real->str == NULL) 00151 return FALSE; 00152 00153 real->allocated = _DBUS_STRING_ALLOCATION_PADDING + allocate_size; 00154 real->len = 0; 00155 real->str[real->len] = '\0'; 00156 00157 real->max_length = _DBUS_STRING_MAX_MAX_LENGTH; 00158 real->constant = FALSE; 00159 real->locked = FALSE; 00160 real->invalid = FALSE; 00161 real->align_offset = 0; 00162 00163 fixup_alignment (real); 00164 00165 return TRUE; 00166 } 00167 00175 dbus_bool_t 00176 _dbus_string_init (DBusString *str) 00177 { 00178 return _dbus_string_init_preallocated (str, 0); 00179 } 00180 00181 #ifdef DBUS_BUILD_TESTS 00182 /* The max length thing is sort of a historical artifact 00183 * from a feature that turned out to be dumb; perhaps 00184 * we should purge it entirely. The problem with 00185 * the feature is that it looks like memory allocation 00186 * failure, but is not a transient or resolvable failure. 00187 */ 00188 static void 00189 set_max_length (DBusString *str, 00190 int max_length) 00191 { 00192 DBusRealString *real; 00193 00194 real = (DBusRealString*) str; 00195 00196 real->max_length = max_length; 00197 } 00198 #endif /* DBUS_BUILD_TESTS */ 00199 00209 void 00210 _dbus_string_init_const (DBusString *str, 00211 const char *value) 00212 { 00213 _dbus_assert (value != NULL); 00214 00215 _dbus_string_init_const_len (str, value, 00216 strlen (value)); 00217 } 00218 00229 void 00230 _dbus_string_init_const_len (DBusString *str, 00231 const char *value, 00232 int len) 00233 { 00234 DBusRealString *real; 00235 00236 _dbus_assert (str != NULL); 00237 _dbus_assert (len == 0 || value != NULL); 00238 _dbus_assert (len <= _DBUS_STRING_MAX_MAX_LENGTH); 00239 _dbus_assert (len >= 0); 00240 00241 real = (DBusRealString*) str; 00242 00243 real->str = (unsigned char*) value; 00244 real->len = len; 00245 real->allocated = real->len + _DBUS_STRING_ALLOCATION_PADDING; /* a lie, just to avoid special-case assertions... */ 00246 real->max_length = real->len + 1; 00247 real->constant = TRUE; 00248 real->locked = TRUE; 00249 real->invalid = FALSE; 00250 real->align_offset = 0; 00251 00252 /* We don't require const strings to be 8-byte aligned as the 00253 * memory is coming from elsewhere. 00254 */ 00255 } 00256 00262 void 00263 _dbus_string_free (DBusString *str) 00264 { 00265 DBusRealString *real = (DBusRealString*) str; 00266 DBUS_GENERIC_STRING_PREAMBLE (real); 00267 00268 if (real->constant) 00269 return; 00270 dbus_free (real->str - real->align_offset); 00271 00272 real->invalid = TRUE; 00273 } 00274 00275 static dbus_bool_t 00276 compact (DBusRealString *real, 00277 int max_waste) 00278 { 00279 unsigned char *new_str; 00280 int new_allocated; 00281 int waste; 00282 00283 waste = real->allocated - (real->len + _DBUS_STRING_ALLOCATION_PADDING); 00284 00285 if (waste <= max_waste) 00286 return TRUE; 00287 00288 new_allocated = real->len + _DBUS_STRING_ALLOCATION_PADDING; 00289 00290 new_str = dbus_realloc (real->str - real->align_offset, new_allocated); 00291 if (_DBUS_UNLIKELY (new_str == NULL)) 00292 return FALSE; 00293 00294 real->str = new_str + real->align_offset; 00295 real->allocated = new_allocated; 00296 fixup_alignment (real); 00297 00298 return TRUE; 00299 } 00300 00301 #ifdef DBUS_BUILD_TESTS 00302 /* Not using this feature at the moment, 00303 * so marked DBUS_BUILD_TESTS-only 00304 */ 00314 void 00315 _dbus_string_lock (DBusString *str) 00316 { 00317 DBUS_LOCKED_STRING_PREAMBLE (str); /* can lock multiple times */ 00318 00319 real->locked = TRUE; 00320 00321 /* Try to realloc to avoid excess memory usage, since 00322 * we know we won't change the string further 00323 */ 00324 #define MAX_WASTE 48 00325 compact (real, MAX_WASTE); 00326 } 00327 #endif /* DBUS_BUILD_TESTS */ 00328 00329 static dbus_bool_t 00330 reallocate_for_length (DBusRealString *real, 00331 int new_length) 00332 { 00333 int new_allocated; 00334 unsigned char *new_str; 00335 00336 /* at least double our old allocation to avoid O(n), avoiding 00337 * overflow 00338 */ 00339 if (real->allocated > (_DBUS_STRING_MAX_MAX_LENGTH + _DBUS_STRING_ALLOCATION_PADDING) / 2) 00340 new_allocated = _DBUS_STRING_MAX_MAX_LENGTH + _DBUS_STRING_ALLOCATION_PADDING; 00341 else 00342 new_allocated = real->allocated * 2; 00343 00344 /* if you change the code just above here, run the tests without 00345 * the following assert-only hack before you commit 00346 */ 00347 /* This is keyed off asserts in addition to tests so when you 00348 * disable asserts to profile, you don't get this destroyer 00349 * of profiles. 00350 */ 00351 #ifdef DBUS_DISABLE_ASSERT 00352 #else 00353 #ifdef DBUS_BUILD_TESTS 00354 new_allocated = 0; /* ensure a realloc every time so that we go 00355 * through all malloc failure codepaths 00356 */ 00357 #endif /* DBUS_BUILD_TESTS */ 00358 #endif /* !DBUS_DISABLE_ASSERT */ 00359 00360 /* But be sure we always alloc at least space for the new length */ 00361 new_allocated = MAX (new_allocated, 00362 new_length + _DBUS_STRING_ALLOCATION_PADDING); 00363 00364 _dbus_assert (new_allocated >= real->allocated); /* code relies on this */ 00365 new_str = dbus_realloc (real->str - real->align_offset, new_allocated); 00366 if (_DBUS_UNLIKELY (new_str == NULL)) 00367 return FALSE; 00368 00369 real->str = new_str + real->align_offset; 00370 real->allocated = new_allocated; 00371 fixup_alignment (real); 00372 00373 return TRUE; 00374 } 00375 00387 dbus_bool_t 00388 _dbus_string_compact (DBusString *str, 00389 int max_waste) 00390 { 00391 DBUS_STRING_PREAMBLE (str); 00392 00393 return compact (real, max_waste); 00394 } 00395 00396 static dbus_bool_t 00397 set_length (DBusRealString *real, 00398 int new_length) 00399 { 00400 /* Note, we are setting the length not including nul termination */ 00401 00402 /* exceeding max length is the same as failure to allocate memory */ 00403 if (_DBUS_UNLIKELY (new_length > real->max_length)) 00404 return FALSE; 00405 else if (new_length > (real->allocated - _DBUS_STRING_ALLOCATION_PADDING) && 00406 _DBUS_UNLIKELY (!reallocate_for_length (real, new_length))) 00407 return FALSE; 00408 else 00409 { 00410 real->len = new_length; 00411 real->str[new_length] = '\0'; 00412 return TRUE; 00413 } 00414 } 00415 00416 static dbus_bool_t 00417 open_gap (int len, 00418 DBusRealString *dest, 00419 int insert_at) 00420 { 00421 if (len == 0) 00422 return TRUE; 00423 00424 if (len > dest->max_length - dest->len) 00425 return FALSE; /* detected overflow of dest->len + len below */ 00426 00427 if (!set_length (dest, dest->len + len)) 00428 return FALSE; 00429 00430 memmove (dest->str + insert_at + len, 00431 dest->str + insert_at, 00432 dest->len - len - insert_at); 00433 00434 return TRUE; 00435 } 00436 00437 #ifndef _dbus_string_get_data 00438 00449 char* 00450 _dbus_string_get_data (DBusString *str) 00451 { 00452 DBUS_STRING_PREAMBLE (str); 00453 00454 return (char*) real->str; 00455 } 00456 #endif /* _dbus_string_get_data */ 00457 00458 /* only do the function if we don't have the macro */ 00459 #ifndef _dbus_string_get_const_data 00460 00466 const char* 00467 _dbus_string_get_const_data (const DBusString *str) 00468 { 00469 DBUS_CONST_STRING_PREAMBLE (str); 00470 00471 return (const char*) real->str; 00472 } 00473 #endif /* _dbus_string_get_const_data */ 00474 00488 char* 00489 _dbus_string_get_data_len (DBusString *str, 00490 int start, 00491 int len) 00492 { 00493 DBUS_STRING_PREAMBLE (str); 00494 _dbus_assert (start >= 0); 00495 _dbus_assert (len >= 0); 00496 _dbus_assert (start <= real->len); 00497 _dbus_assert (len <= real->len - start); 00498 00499 return (char*) real->str + start; 00500 } 00501 00502 /* only do the function if we don't have the macro */ 00503 #ifndef _dbus_string_get_const_data_len 00504 00512 const char* 00513 _dbus_string_get_const_data_len (const DBusString *str, 00514 int start, 00515 int len) 00516 { 00517 DBUS_CONST_STRING_PREAMBLE (str); 00518 _dbus_assert (start >= 0); 00519 _dbus_assert (len >= 0); 00520 _dbus_assert (start <= real->len); 00521 _dbus_assert (len <= real->len - start); 00522 00523 return (const char*) real->str + start; 00524 } 00525 #endif /* _dbus_string_get_const_data_len */ 00526 00527 /* only do the function if we don't have the macro */ 00528 #ifndef _dbus_string_set_byte 00529 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 #endif /* _dbus_string_set_byte */ 00548 00549 /* only have the function if we didn't create a macro */ 00550 #ifndef _dbus_string_get_byte 00551 00560 unsigned char 00561 _dbus_string_get_byte (const DBusString *str, 00562 int start) 00563 { 00564 DBUS_CONST_STRING_PREAMBLE (str); 00565 _dbus_assert (start <= real->len); 00566 _dbus_assert (start >= 0); 00567 00568 return real->str[start]; 00569 } 00570 #endif /* _dbus_string_get_byte */ 00571 00582 dbus_bool_t 00583 _dbus_string_insert_bytes (DBusString *str, 00584 int i, 00585 int n_bytes, 00586 unsigned char byte) 00587 { 00588 DBUS_STRING_PREAMBLE (str); 00589 _dbus_assert (i <= real->len); 00590 _dbus_assert (i >= 0); 00591 _dbus_assert (n_bytes >= 0); 00592 00593 if (n_bytes == 0) 00594 return TRUE; 00595 00596 if (!open_gap (n_bytes, real, i)) 00597 return FALSE; 00598 00599 memset (real->str + i, byte, n_bytes); 00600 00601 return TRUE; 00602 } 00603 00612 dbus_bool_t 00613 _dbus_string_insert_byte (DBusString *str, 00614 int i, 00615 unsigned char byte) 00616 { 00617 DBUS_STRING_PREAMBLE (str); 00618 _dbus_assert (i <= real->len); 00619 _dbus_assert (i >= 0); 00620 00621 if (!open_gap (1, real, i)) 00622 return FALSE; 00623 00624 real->str[i] = byte; 00625 00626 return TRUE; 00627 } 00628 00639 dbus_bool_t 00640 _dbus_string_steal_data (DBusString *str, 00641 char **data_return) 00642 { 00643 int old_max_length; 00644 DBUS_STRING_PREAMBLE (str); 00645 _dbus_assert (data_return != NULL); 00646 00647 undo_alignment (real); 00648 00649 *data_return = (char*) real->str; 00650 00651 old_max_length = real->max_length; 00652 00653 /* reset the string */ 00654 if (!_dbus_string_init (str)) 00655 { 00656 /* hrm, put it back then */ 00657 real->str = (unsigned char*) *data_return; 00658 *data_return = NULL; 00659 fixup_alignment (real); 00660 return FALSE; 00661 } 00662 00663 real->max_length = old_max_length; 00664 00665 return TRUE; 00666 } 00667 00668 #ifdef DBUS_BUILD_TESTS 00669 00684 dbus_bool_t 00685 _dbus_string_steal_data_len (DBusString *str, 00686 char **data_return, 00687 int start, 00688 int len) 00689 { 00690 DBusString dest; 00691 DBUS_STRING_PREAMBLE (str); 00692 _dbus_assert (data_return != NULL); 00693 _dbus_assert (start >= 0); 00694 _dbus_assert (len >= 0); 00695 _dbus_assert (start <= real->len); 00696 _dbus_assert (len <= real->len - start); 00697 00698 if (!_dbus_string_init (&dest)) 00699 return FALSE; 00700 00701 set_max_length (&dest, real->max_length); 00702 00703 if (!_dbus_string_move_len (str, start, len, &dest, 0)) 00704 { 00705 _dbus_string_free (&dest); 00706 return FALSE; 00707 } 00708 00709 _dbus_warn ("Broken code in _dbus_string_steal_data_len(), see @todo, FIXME\n"); 00710 if (!_dbus_string_steal_data (&dest, data_return)) 00711 { 00712 _dbus_string_free (&dest); 00713 return FALSE; 00714 } 00715 00716 _dbus_string_free (&dest); 00717 return TRUE; 00718 } 00719 #endif /* DBUS_BUILD_TESTS */ 00720 00728 dbus_bool_t 00729 _dbus_string_copy_data (const DBusString *str, 00730 char **data_return) 00731 { 00732 DBUS_CONST_STRING_PREAMBLE (str); 00733 _dbus_assert (data_return != NULL); 00734 00735 *data_return = dbus_malloc (real->len + 1); 00736 if (*data_return == NULL) 00737 return FALSE; 00738 00739 memcpy (*data_return, real->str, real->len + 1); 00740 00741 return TRUE; 00742 } 00743 00753 void 00754 _dbus_string_copy_to_buffer (const DBusString *str, 00755 char *buffer, 00756 int avail_len) 00757 { 00758 DBUS_CONST_STRING_PREAMBLE (str); 00759 00760 _dbus_assert (avail_len >= 0); 00761 _dbus_assert (avail_len >= real->len); 00762 00763 memcpy (buffer, real->str, real->len); 00764 } 00765 00775 void 00776 _dbus_string_copy_to_buffer_with_nul (const DBusString *str, 00777 char *buffer, 00778 int avail_len) 00779 { 00780 DBUS_CONST_STRING_PREAMBLE (str); 00781 00782 _dbus_assert (avail_len >= 0); 00783 _dbus_assert (avail_len > real->len); 00784 00785 memcpy (buffer, real->str, real->len+1); 00786 } 00787 00788 #ifdef DBUS_BUILD_TESTS 00789 00798 dbus_bool_t 00799 _dbus_string_copy_data_len (const DBusString *str, 00800 char **data_return, 00801 int start, 00802 int len) 00803 { 00804 DBusString dest; 00805 00806 DBUS_CONST_STRING_PREAMBLE (str); 00807 _dbus_assert (data_return != NULL); 00808 _dbus_assert (start >= 0); 00809 _dbus_assert (len >= 0); 00810 _dbus_assert (start <= real->len); 00811 _dbus_assert (len <= real->len - start); 00812 00813 if (!_dbus_string_init (&dest)) 00814 return FALSE; 00815 00816 set_max_length (&dest, real->max_length); 00817 00818 if (!_dbus_string_copy_len (str, start, len, &dest, 0)) 00819 { 00820 _dbus_string_free (&dest); 00821 return FALSE; 00822 } 00823 00824 if (!_dbus_string_steal_data (&dest, data_return)) 00825 { 00826 _dbus_string_free (&dest); 00827 return FALSE; 00828 } 00829 00830 _dbus_string_free (&dest); 00831 return TRUE; 00832 } 00833 #endif /* DBUS_BUILD_TESTS */ 00834 00835 /* Only have the function if we don't have the macro */ 00836 #ifndef _dbus_string_get_length 00837 00842 int 00843 _dbus_string_get_length (const DBusString *str) 00844 { 00845 DBUS_CONST_STRING_PREAMBLE (str); 00846 00847 return real->len; 00848 } 00849 #endif /* !_dbus_string_get_length */ 00850 00863 dbus_bool_t 00864 _dbus_string_lengthen (DBusString *str, 00865 int additional_length) 00866 { 00867 DBUS_STRING_PREAMBLE (str); 00868 _dbus_assert (additional_length >= 0); 00869 00870 if (_DBUS_UNLIKELY (additional_length > real->max_length - real->len)) 00871 return FALSE; /* would overflow */ 00872 00873 return set_length (real, 00874 real->len + additional_length); 00875 } 00876 00883 void 00884 _dbus_string_shorten (DBusString *str, 00885 int length_to_remove) 00886 { 00887 DBUS_STRING_PREAMBLE (str); 00888 _dbus_assert (length_to_remove >= 0); 00889 _dbus_assert (length_to_remove <= real->len); 00890 00891 set_length (real, 00892 real->len - length_to_remove); 00893 } 00894 00905 dbus_bool_t 00906 _dbus_string_set_length (DBusString *str, 00907 int length) 00908 { 00909 DBUS_STRING_PREAMBLE (str); 00910 _dbus_assert (length >= 0); 00911 00912 return set_length (real, length); 00913 } 00914 00915 static dbus_bool_t 00916 align_insert_point_then_open_gap (DBusString *str, 00917 int *insert_at_p, 00918 int alignment, 00919 int gap_size) 00920 { 00921 unsigned long new_len; /* ulong to avoid _DBUS_ALIGN_VALUE overflow */ 00922 unsigned long gap_pos; 00923 int insert_at; 00924 int delta; 00925 DBUS_STRING_PREAMBLE (str); 00926 _dbus_assert (alignment >= 1); 00927 _dbus_assert (alignment <= 8); /* it has to be a bug if > 8 */ 00928 00929 insert_at = *insert_at_p; 00930 00931 _dbus_assert (insert_at <= real->len); 00932 00933 gap_pos = _DBUS_ALIGN_VALUE (insert_at, alignment); 00934 new_len = real->len + (gap_pos - insert_at) + gap_size; 00935 00936 if (_DBUS_UNLIKELY (new_len > (unsigned long) real->max_length)) 00937 return FALSE; 00938 00939 delta = new_len - real->len; 00940 _dbus_assert (delta >= 0); 00941 00942 if (delta == 0) /* only happens if gap_size == 0 and insert_at is aligned already */ 00943 { 00944 _dbus_assert (((unsigned long) *insert_at_p) == gap_pos); 00945 return TRUE; 00946 } 00947 00948 if (_DBUS_UNLIKELY (!open_gap (new_len - real->len, 00949 real, insert_at))) 00950 return FALSE; 00951 00952 /* nul the padding if we had to add any padding */ 00953 if (gap_size < delta) 00954 { 00955 memset (&real->str[insert_at], '\0', 00956 gap_pos - insert_at); 00957 } 00958 00959 *insert_at_p = gap_pos; 00960 00961 return TRUE; 00962 } 00963 00964 static dbus_bool_t 00965 align_length_then_lengthen (DBusString *str, 00966 int alignment, 00967 int then_lengthen_by) 00968 { 00969 int insert_at; 00970 00971 insert_at = _dbus_string_get_length (str); 00972 00973 return align_insert_point_then_open_gap (str, 00974 &insert_at, 00975 alignment, then_lengthen_by); 00976 } 00977 00986 dbus_bool_t 00987 _dbus_string_align_length (DBusString *str, 00988 int alignment) 00989 { 00990 return align_length_then_lengthen (str, alignment, 0); 00991 } 00992 01002 dbus_bool_t 01003 _dbus_string_alloc_space (DBusString *str, 01004 int extra_bytes) 01005 { 01006 if (!_dbus_string_lengthen (str, extra_bytes)) 01007 return FALSE; 01008 _dbus_string_shorten (str, extra_bytes); 01009 01010 return TRUE; 01011 } 01012 01013 static dbus_bool_t 01014 append (DBusRealString *real, 01015 const char *buffer, 01016 int buffer_len) 01017 { 01018 if (buffer_len == 0) 01019 return TRUE; 01020 01021 if (!_dbus_string_lengthen ((DBusString*)real, buffer_len)) 01022 return FALSE; 01023 01024 memcpy (real->str + (real->len - buffer_len), 01025 buffer, 01026 buffer_len); 01027 01028 return TRUE; 01029 } 01030 01038 dbus_bool_t 01039 _dbus_string_append (DBusString *str, 01040 const char *buffer) 01041 { 01042 unsigned long buffer_len; 01043 01044 DBUS_STRING_PREAMBLE (str); 01045 _dbus_assert (buffer != NULL); 01046 01047 buffer_len = strlen (buffer); 01048 if (buffer_len > (unsigned long) real->max_length) 01049 return FALSE; 01050 01051 return append (real, buffer, buffer_len); 01052 } 01053 01055 #define ASSIGN_2_OCTETS(p, octets) \ 01056 *((dbus_uint16_t*)(p)) = *((dbus_uint16_t*)(octets)); 01057 01059 #define ASSIGN_4_OCTETS(p, octets) \ 01060 *((dbus_uint32_t*)(p)) = *((dbus_uint32_t*)(octets)); 01061 01062 #ifdef DBUS_HAVE_INT64 01063 01064 #define ASSIGN_8_OCTETS(p, octets) \ 01065 *((dbus_uint64_t*)(p)) = *((dbus_uint64_t*)(octets)); 01066 #else 01067 01068 #define ASSIGN_8_OCTETS(p, octets) \ 01069 do { \ 01070 unsigned char *b; \ 01071 \ 01072 b = p; \ 01073 \ 01074 *b++ = octets[0]; \ 01075 *b++ = octets[1]; \ 01076 *b++ = octets[2]; \ 01077 *b++ = octets[3]; \ 01078 *b++ = octets[4]; \ 01079 *b++ = octets[5]; \ 01080 *b++ = octets[6]; \ 01081 *b++ = octets[7]; \ 01082 _dbus_assert (b == p + 8); \ 01083 } while (0) 01084 #endif /* DBUS_HAVE_INT64 */ 01085 01086 #ifdef DBUS_BUILD_TESTS 01087 01095 dbus_bool_t 01096 _dbus_string_append_4_aligned (DBusString *str, 01097 const unsigned char octets[4]) 01098 { 01099 DBUS_STRING_PREAMBLE (str); 01100 01101 if (!align_length_then_lengthen (str, 4, 4)) 01102 return FALSE; 01103 01104 ASSIGN_4_OCTETS (real->str + (real->len - 4), octets); 01105 01106 return TRUE; 01107 } 01108 #endif /* DBUS_BUILD_TESTS */ 01109 01110 #ifdef DBUS_BUILD_TESTS 01111 01119 dbus_bool_t 01120 _dbus_string_append_8_aligned (DBusString *str, 01121 const unsigned char octets[8]) 01122 { 01123 DBUS_STRING_PREAMBLE (str); 01124 01125 if (!align_length_then_lengthen (str, 8, 8)) 01126 return FALSE; 01127 01128 ASSIGN_8_OCTETS (real->str + (real->len - 8), octets); 01129 01130 return TRUE; 01131 } 01132 #endif /* DBUS_BUILD_TESTS */ 01133 01143 dbus_bool_t 01144 _dbus_string_insert_2_aligned (DBusString *str, 01145 int insert_at, 01146 const unsigned char octets[4]) 01147 { 01148 DBUS_STRING_PREAMBLE (str); 01149 01150 if (!align_insert_point_then_open_gap (str, &insert_at, 2, 2)) 01151 return FALSE; 01152 01153 ASSIGN_2_OCTETS (real->str + insert_at, octets); 01154 01155 return TRUE; 01156 } 01157 01167 dbus_bool_t 01168 _dbus_string_insert_4_aligned (DBusString *str, 01169 int insert_at, 01170 const unsigned char octets[4]) 01171 { 01172 DBUS_STRING_PREAMBLE (str); 01173 01174 if (!align_insert_point_then_open_gap (str, &insert_at, 4, 4)) 01175 return FALSE; 01176 01177 ASSIGN_4_OCTETS (real->str + insert_at, octets); 01178 01179 return TRUE; 01180 } 01181 01191 dbus_bool_t 01192 _dbus_string_insert_8_aligned (DBusString *str, 01193 int insert_at, 01194 const unsigned char octets[8]) 01195 { 01196 DBUS_STRING_PREAMBLE (str); 01197 01198 if (!align_insert_point_then_open_gap (str, &insert_at, 8, 8)) 01199 return FALSE; 01200 01201 _dbus_assert (_DBUS_ALIGN_VALUE (insert_at, 8) == (unsigned) insert_at); 01202 01203 ASSIGN_8_OCTETS (real->str + insert_at, octets); 01204 01205 return TRUE; 01206 } 01207 01208 01219 dbus_bool_t 01220 _dbus_string_insert_alignment (DBusString *str, 01221 int *insert_at, 01222 int alignment) 01223 { 01224 DBUS_STRING_PREAMBLE (str); 01225 01226 if (!align_insert_point_then_open_gap (str, insert_at, alignment, 0)) 01227 return FALSE; 01228 01229 _dbus_assert (_DBUS_ALIGN_VALUE (*insert_at, alignment) == (unsigned) *insert_at); 01230 01231 return TRUE; 01232 } 01233 01243 dbus_bool_t 01244 _dbus_string_append_printf_valist (DBusString *str, 01245 const char *format, 01246 va_list args) 01247 { 01248 int len; 01249 va_list args_copy; 01250 01251 DBUS_STRING_PREAMBLE (str); 01252 01253 DBUS_VA_COPY (args_copy, args); 01254 01255 /* Measure the message length without terminating nul */ 01256 len = _dbus_printf_string_upper_bound (format, args); 01257 01258 if (!_dbus_string_lengthen (str, len)) 01259 { 01260 /* don't leak the copy */ 01261 va_end (args_copy); 01262 return FALSE; 01263 } 01264 01265 vsprintf ((char*) (real->str + (real->len - len)), 01266 format, args_copy); 01267 01268 va_end (args_copy); 01269 01270 return TRUE; 01271 } 01272 01281 dbus_bool_t 01282 _dbus_string_append_printf (DBusString *str, 01283 const char *format, 01284 ...) 01285 { 01286 va_list args; 01287 dbus_bool_t retval; 01288 01289 va_start (args, format); 01290 retval = _dbus_string_append_printf_valist (str, format, args); 01291 va_end (args); 01292 01293 return retval; 01294 } 01295 01304 dbus_bool_t 01305 _dbus_string_append_len (DBusString *str, 01306 const char *buffer, 01307 int len) 01308 { 01309 DBUS_STRING_PREAMBLE (str); 01310 _dbus_assert (buffer != NULL); 01311 _dbus_assert (len >= 0); 01312 01313 return append (real, buffer, len); 01314 } 01315 01324 dbus_bool_t 01325 _dbus_string_append_byte (DBusString *str, 01326 unsigned char byte) 01327 { 01328 DBUS_STRING_PREAMBLE (str); 01329 01330 if (!set_length (real, real->len + 1)) 01331 return FALSE; 01332 01333 real->str[real->len-1] = byte; 01334 01335 return TRUE; 01336 } 01337 01338 #ifdef DBUS_BUILD_TESTS 01339 01346 dbus_bool_t 01347 _dbus_string_append_unichar (DBusString *str, 01348 dbus_unichar_t ch) 01349 { 01350 int len; 01351 int first; 01352 int i; 01353 unsigned char *out; 01354 01355 DBUS_STRING_PREAMBLE (str); 01356 01357 /* this code is from GLib but is pretty standard I think */ 01358 01359 len = 0; 01360 01361 if (ch < 0x80) 01362 { 01363 first = 0; 01364 len = 1; 01365 } 01366 else if (ch < 0x800) 01367 { 01368 first = 0xc0; 01369 len = 2; 01370 } 01371 else if (ch < 0x10000) 01372 { 01373 first = 0xe0; 01374 len = 3; 01375 } 01376 else if (ch < 0x200000) 01377 { 01378 first = 0xf0; 01379 len = 4; 01380 } 01381 else if (ch < 0x4000000) 01382 { 01383 first = 0xf8; 01384 len = 5; 01385 } 01386 else 01387 { 01388 first = 0xfc; 01389 len = 6; 01390 } 01391 01392 if (len > (real->max_length - real->len)) 01393 return FALSE; /* real->len + len would overflow */ 01394 01395 if (!set_length (real, real->len + len)) 01396 return FALSE; 01397 01398 out = real->str + (real->len - len); 01399 01400 for (i = len - 1; i > 0; --i) 01401 { 01402 out[i] = (ch & 0x3f) | 0x80; 01403 ch >>= 6; 01404 } 01405 out[0] = ch | first; 01406 01407 return TRUE; 01408 } 01409 #endif /* DBUS_BUILD_TESTS */ 01410 01411 static void 01412 delete (DBusRealString *real, 01413 int start, 01414 int len) 01415 { 01416 if (len == 0) 01417 return; 01418 01419 memmove (real->str + start, real->str + start + len, real->len - (start + len)); 01420 real->len -= len; 01421 real->str[real->len] = '\0'; 01422 } 01423 01433 void 01434 _dbus_string_delete (DBusString *str, 01435 int start, 01436 int len) 01437 { 01438 DBUS_STRING_PREAMBLE (str); 01439 _dbus_assert (start >= 0); 01440 _dbus_assert (len >= 0); 01441 _dbus_assert (start <= real->len); 01442 _dbus_assert (len <= real->len - start); 01443 01444 delete (real, start, len); 01445 } 01446 01447 static dbus_bool_t 01448 copy (DBusRealString *source, 01449 int start, 01450 int len, 01451 DBusRealString *dest, 01452 int insert_at) 01453 { 01454 if (len == 0) 01455 return TRUE; 01456 01457 if (!open_gap (len, dest, insert_at)) 01458 return FALSE; 01459 01460 memmove (dest->str + insert_at, 01461 source->str + start, 01462 len); 01463 01464 return TRUE; 01465 } 01466 01476 #define DBUS_STRING_COPY_PREAMBLE(source, start, dest, insert_at) \ 01477 DBusRealString *real_source = (DBusRealString*) source; \ 01478 DBusRealString *real_dest = (DBusRealString*) dest; \ 01479 _dbus_assert ((source) != (dest)); \ 01480 DBUS_GENERIC_STRING_PREAMBLE (real_source); \ 01481 DBUS_GENERIC_STRING_PREAMBLE (real_dest); \ 01482 _dbus_assert (!real_dest->constant); \ 01483 _dbus_assert (!real_dest->locked); \ 01484 _dbus_assert ((start) >= 0); \ 01485 _dbus_assert ((start) <= real_source->len); \ 01486 _dbus_assert ((insert_at) >= 0); \ 01487 _dbus_assert ((insert_at) <= real_dest->len) 01488 01499 dbus_bool_t 01500 _dbus_string_move (DBusString *source, 01501 int start, 01502 DBusString *dest, 01503 int insert_at) 01504 { 01505 DBusRealString *real_source = (DBusRealString*) source; 01506 _dbus_assert (start <= real_source->len); 01507 01508 return _dbus_string_move_len (source, start, 01509 real_source->len - start, 01510 dest, insert_at); 01511 } 01512 01523 dbus_bool_t 01524 _dbus_string_copy (const DBusString *source, 01525 int start, 01526 DBusString *dest, 01527 int insert_at) 01528 { 01529 DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at); 01530 01531 return copy (real_source, start, 01532 real_source->len - start, 01533 real_dest, 01534 insert_at); 01535 } 01536 01551 dbus_bool_t 01552 _dbus_string_move_len (DBusString *source, 01553 int start, 01554 int len, 01555 DBusString *dest, 01556 int insert_at) 01557 01558 { 01559 DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at); 01560 _dbus_assert (len >= 0); 01561 _dbus_assert ((start + len) <= real_source->len); 01562 01563 01564 if (len == 0) 01565 { 01566 return TRUE; 01567 } 01568 else if (start == 0 && 01569 len == real_source->len && 01570 real_dest->len == 0) 01571 { 01572 /* Short-circuit moving an entire existing string to an empty string 01573 * by just swapping the buffers. 01574 */ 01575 /* we assume ->constant doesn't matter as you can't have 01576 * a constant string involved in a move. 01577 */ 01578 #define ASSIGN_DATA(a, b) do { \ 01579 (a)->str = (b)->str; \ 01580 (a)->len = (b)->len; \ 01581 (a)->allocated = (b)->allocated; \ 01582 (a)->align_offset = (b)->align_offset; \ 01583 } while (0) 01584 01585 DBusRealString tmp; 01586 01587 ASSIGN_DATA (&tmp, real_source); 01588 ASSIGN_DATA (real_source, real_dest); 01589 ASSIGN_DATA (real_dest, &tmp); 01590 01591 return TRUE; 01592 } 01593 else 01594 { 01595 if (!copy (real_source, start, len, 01596 real_dest, 01597 insert_at)) 01598 return FALSE; 01599 01600 delete (real_source, start, 01601 len); 01602 01603 return TRUE; 01604 } 01605 } 01606 01618 dbus_bool_t 01619 _dbus_string_copy_len (const DBusString *source, 01620 int start, 01621 int len, 01622 DBusString *dest, 01623 int insert_at) 01624 { 01625 DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at); 01626 _dbus_assert (len >= 0); 01627 _dbus_assert (start <= real_source->len); 01628 _dbus_assert (len <= real_source->len - start); 01629 01630 return copy (real_source, start, len, 01631 real_dest, 01632 insert_at); 01633 } 01634 01656 dbus_bool_t 01657 _dbus_string_replace_len (const DBusString *source, 01658 int start, 01659 int len, 01660 DBusString *dest, 01661 int replace_at, 01662 int replace_len) 01663 { 01664 DBUS_STRING_COPY_PREAMBLE (source, start, dest, replace_at); 01665 _dbus_assert (len >= 0); 01666 _dbus_assert (start <= real_source->len); 01667 _dbus_assert (len <= real_source->len - start); 01668 _dbus_assert (replace_at >= 0); 01669 _dbus_assert (replace_at <= real_dest->len); 01670 _dbus_assert (replace_len <= real_dest->len - replace_at); 01671 01672 if (!copy (real_source, start, len, 01673 real_dest, replace_at)) 01674 return FALSE; 01675 01676 delete (real_dest, replace_at + len, replace_len); 01677 01678 return TRUE; 01679 } 01680 01693 dbus_bool_t 01694 _dbus_string_split_on_byte (DBusString *source, 01695 unsigned char byte, 01696 DBusString *tail) 01697 { 01698 int byte_position; 01699 char byte_string[2] = ""; 01700 int head_length; 01701 int tail_length; 01702 01703 byte_string[0] = (char) byte; 01704 01705 if (!_dbus_string_find (source, 0, byte_string, &byte_position)) 01706 return FALSE; 01707 01708 head_length = byte_position; 01709 tail_length = _dbus_string_get_length (source) - head_length - 1; 01710 01711 if (!_dbus_string_move_len (source, byte_position + 1, tail_length, 01712 tail, 0)) 01713 return FALSE; 01714 01715 /* remove the trailing delimiter byte from the head now. 01716 */ 01717 if (!_dbus_string_set_length (source, head_length)) 01718 return FALSE; 01719 01720 return TRUE; 01721 } 01722 01723 /* Unicode macros and utf8_validate() from GLib Owen Taylor, Havoc 01724 * Pennington, and Tom Tromey are the authors and authorized relicense. 01725 */ 01726 01732 #define UTF8_COMPUTE(Char, Mask, Len) \ 01733 if (Char < 128) \ 01734 { \ 01735 Len = 1; \ 01736 Mask = 0x7f; \ 01737 } \ 01738 else if ((Char & 0xe0) == 0xc0) \ 01739 { \ 01740 Len = 2; \ 01741 Mask = 0x1f; \ 01742 } \ 01743 else if ((Char & 0xf0) == 0xe0) \ 01744 { \ 01745 Len = 3; \ 01746 Mask = 0x0f; \ 01747 } \ 01748 else if ((Char & 0xf8) == 0xf0) \ 01749 { \ 01750 Len = 4; \ 01751 Mask = 0x07; \ 01752 } \ 01753 else if ((Char & 0xfc) == 0xf8) \ 01754 { \ 01755 Len = 5; \ 01756 Mask = 0x03; \ 01757 } \ 01758 else if ((Char & 0xfe) == 0xfc) \ 01759 { \ 01760 Len = 6; \ 01761 Mask = 0x01; \ 01762 } \ 01763 else \ 01764 { \ 01765 Len = 0; \ 01766 Mask = 0; \ 01767 } 01768 01773 #define UTF8_LENGTH(Char) \ 01774 ((Char) < 0x80 ? 1 : \ 01775 ((Char) < 0x800 ? 2 : \ 01776 ((Char) < 0x10000 ? 3 : \ 01777 ((Char) < 0x200000 ? 4 : \ 01778 ((Char) < 0x4000000 ? 5 : 6))))) 01779 01789 #define UTF8_GET(Result, Chars, Count, Mask, Len) \ 01790 (Result) = (Chars)[0] & (Mask); \ 01791 for ((Count) = 1; (Count) < (Len); ++(Count)) \ 01792 { \ 01793 if (((Chars)[(Count)] & 0xc0) != 0x80) \ 01794 { \ 01795 (Result) = -1; \ 01796 break; \ 01797 } \ 01798 (Result) <<= 6; \ 01799 (Result) |= ((Chars)[(Count)] & 0x3f); \ 01800 } 01801 01818 #define UNICODE_VALID(Char) \ 01819 ((Char) < 0x110000 && \ 01820 (((Char) & 0xFFFFF800) != 0xD800) && \ 01821 ((Char) < 0xFDD0 || (Char) > 0xFDEF) && \ 01822 ((Char) & 0xFFFE) != 0xFFFE) 01823 01824 #ifdef DBUS_BUILD_TESTS 01825 01835 void 01836 _dbus_string_get_unichar (const DBusString *str, 01837 int start, 01838 dbus_unichar_t *ch_return, 01839 int *end_return) 01840 { 01841 int i, mask, len; 01842 dbus_unichar_t result; 01843 unsigned char c; 01844 unsigned char *p; 01845 DBUS_CONST_STRING_PREAMBLE (str); 01846 _dbus_assert (start >= 0); 01847 _dbus_assert (start <= real->len); 01848 01849 if (ch_return) 01850 *ch_return = 0; 01851 if (end_return) 01852 *end_return = real->len; 01853 01854 mask = 0; 01855 p = real->str + start; 01856 c = *p; 01857 01858 UTF8_COMPUTE (c, mask, len); 01859 if (len == 0) 01860 return; 01861 UTF8_GET (result, p, i, mask, len); 01862 01863 if (result == (dbus_unichar_t)-1) 01864 return; 01865 01866 if (ch_return) 01867 *ch_return = result; 01868 if (end_return) 01869 *end_return = start + len; 01870 } 01871 #endif /* DBUS_BUILD_TESTS */ 01872 01887 dbus_bool_t 01888 _dbus_string_find (const DBusString *str, 01889 int start, 01890 const char *substr, 01891 int *found) 01892 { 01893 return _dbus_string_find_to (str, start, 01894 ((const DBusRealString*)str)->len, 01895 substr, found); 01896 } 01897 01910 dbus_bool_t 01911 _dbus_string_find_eol (const DBusString *str, 01912 int start, 01913 int *found, 01914 int *found_len) 01915 { 01916 int i; 01917 01918 DBUS_CONST_STRING_PREAMBLE (str); 01919 _dbus_assert (start <= real->len); 01920 _dbus_assert (start >= 0); 01921 01922 i = start; 01923 while (i < real->len) 01924 { 01925 if (real->str[i] == '\r') 01926 { 01927 if ((i+1) < real->len && real->str[i+1] == '\n') /* "\r\n" */ 01928 { 01929 if (found) 01930 *found = i; 01931 if (found_len) 01932 *found_len = 2; 01933 return TRUE; 01934 } 01935 else /* only "\r" */ 01936 { 01937 if (found) 01938 *found = i; 01939 if (found_len) 01940 *found_len = 1; 01941 return TRUE; 01942 } 01943 } 01944 else if (real->str[i] == '\n') /* only "\n" */ 01945 { 01946 if (found) 01947 *found = i; 01948 if (found_len) 01949 *found_len = 1; 01950 return TRUE; 01951 } 01952 ++i; 01953 } 01954 01955 if (found) 01956 *found = real->len; 01957 01958 if (found_len) 01959 *found_len = 0; 01960 01961 return FALSE; 01962 } 01963 01980 dbus_bool_t 01981 _dbus_string_find_to (const DBusString *str, 01982 int start, 01983 int end, 01984 const char *substr, 01985 int *found) 01986 { 01987 int i; 01988 DBUS_CONST_STRING_PREAMBLE (str); 01989 _dbus_assert (substr != NULL); 01990 _dbus_assert (start <= real->len); 01991 _dbus_assert (start >= 0); 01992 _dbus_assert (substr != NULL); 01993 _dbus_assert (end <= real->len); 01994 _dbus_assert (start <= end); 01995 01996 /* we always "find" an empty string */ 01997 if (*substr == '\0') 01998 { 01999 if (found) 02000 *found = start; 02001 return TRUE; 02002 } 02003 02004 i = start; 02005 while (i < end) 02006 { 02007 if (real->str[i] == substr[0]) 02008 { 02009 int j = i + 1; 02010 02011 while (j < end) 02012 { 02013 if (substr[j - i] == '\0') 02014 break; 02015 else if (real->str[j] != substr[j - i]) 02016 break; 02017 02018 ++j; 02019 } 02020 02021 if (substr[j - i] == '\0') 02022 { 02023 if (found) 02024 *found = i; 02025 return TRUE; 02026 } 02027 } 02028 02029 ++i; 02030 } 02031 02032 if (found) 02033 *found = end; 02034 02035 return FALSE; 02036 } 02037 02048 dbus_bool_t 02049 _dbus_string_find_blank (const DBusString *str, 02050 int start, 02051 int *found) 02052 { 02053 int i; 02054 DBUS_CONST_STRING_PREAMBLE (str); 02055 _dbus_assert (start <= real->len); 02056 _dbus_assert (start >= 0); 02057 02058 i = start; 02059 while (i < real->len) 02060 { 02061 if (real->str[i] == ' ' || 02062 real->str[i] == '\t') 02063 { 02064 if (found) 02065 *found = i; 02066 return TRUE; 02067 } 02068 02069 ++i; 02070 } 02071 02072 if (found) 02073 *found = real->len; 02074 02075 return FALSE; 02076 } 02077 02086 void 02087 _dbus_string_skip_blank (const DBusString *str, 02088 int start, 02089 int *end) 02090 { 02091 int i; 02092 DBUS_CONST_STRING_PREAMBLE (str); 02093 _dbus_assert (start <= real->len); 02094 _dbus_assert (start >= 0); 02095 02096 i = start; 02097 while (i < real->len) 02098 { 02099 if (!DBUS_IS_ASCII_BLANK (real->str[i])) 02100 break; 02101 02102 ++i; 02103 } 02104 02105 _dbus_assert (i == real->len || !DBUS_IS_ASCII_WHITE (real->str[i])); 02106 02107 if (end) 02108 *end = i; 02109 } 02110 02111 02120 void 02121 _dbus_string_skip_white (const DBusString *str, 02122 int start, 02123 int *end) 02124 { 02125 int i; 02126 DBUS_CONST_STRING_PREAMBLE (str); 02127 _dbus_assert (start <= real->len); 02128 _dbus_assert (start >= 0); 02129 02130 i = start; 02131 while (i < real->len) 02132 { 02133 if (!DBUS_IS_ASCII_WHITE (real->str[i])) 02134 break; 02135 02136 ++i; 02137 } 02138 02139 _dbus_assert (i == real->len || !(DBUS_IS_ASCII_WHITE (real->str[i]))); 02140 02141 if (end) 02142 *end = i; 02143 } 02144 02153 void 02154 _dbus_string_skip_white_reverse (const DBusString *str, 02155 int end, 02156 int *start) 02157 { 02158 int i; 02159 DBUS_CONST_STRING_PREAMBLE (str); 02160 _dbus_assert (end <= real->len); 02161 _dbus_assert (end >= 0); 02162 02163 i = end; 02164 while (i > 0) 02165 { 02166 if (!DBUS_IS_ASCII_WHITE (real->str[i-1])) 02167 break; 02168 --i; 02169 } 02170 02171 _dbus_assert (i >= 0 && (i == 0 || !(DBUS_IS_ASCII_WHITE (real->str[i-1])))); 02172 02173 if (start) 02174 *start = i; 02175 } 02176 02192 dbus_bool_t 02193 _dbus_string_pop_line (DBusString *source, 02194 DBusString *dest) 02195 { 02196 int eol, eol_len; 02197 02198 _dbus_string_set_length (dest, 0); 02199 02200 eol = 0; 02201 eol_len = 0; 02202 if (!_dbus_string_find_eol (source, 0, &eol, &eol_len)) 02203 { 02204 _dbus_assert (eol == _dbus_string_get_length (source)); 02205 if (eol == 0) 02206 { 02207 /* If there's no newline and source has zero length, we're done */ 02208 return FALSE; 02209 } 02210 /* otherwise, the last line of the file has no eol characters */ 02211 } 02212 02213 /* remember eol can be 0 if it's an empty line, but eol_len should not be zero also 02214 * since find_eol returned TRUE 02215 */ 02216 02217 if (!_dbus_string_move_len (source, 0, eol + eol_len, dest, 0)) 02218 return FALSE; 02219 02220 /* remove line ending */ 02221 if (!_dbus_string_set_length (dest, eol)) 02222 { 02223 _dbus_assert_not_reached ("out of memory when shortening a string"); 02224 return FALSE; 02225 } 02226 02227 return TRUE; 02228 } 02229 02230 #ifdef DBUS_BUILD_TESTS 02231 02237 void 02238 _dbus_string_delete_first_word (DBusString *str) 02239 { 02240 int i; 02241 02242 if (_dbus_string_find_blank (str, 0, &i)) 02243 _dbus_string_skip_blank (str, i, &i); 02244 02245 _dbus_string_delete (str, 0, i); 02246 } 02247 #endif 02248 02249 #ifdef DBUS_BUILD_TESTS 02250 02255 void 02256 _dbus_string_delete_leading_blanks (DBusString *str) 02257 { 02258 int i; 02259 02260 _dbus_string_skip_blank (str, 0, &i); 02261 02262 if (i > 0) 02263 _dbus_string_delete (str, 0, i); 02264 } 02265 #endif 02266 02272 void 02273 _dbus_string_chop_white(DBusString *str) 02274 { 02275 int i; 02276 02277 _dbus_string_skip_white (str, 0, &i); 02278 02279 if (i > 0) 02280 _dbus_string_delete (str, 0, i); 02281 02282 _dbus_string_skip_white_reverse (str, _dbus_string_get_length (str), &i); 02283 02284 _dbus_string_set_length (str, i); 02285 } 02286 02296 dbus_bool_t 02297 _dbus_string_equal (const DBusString *a, 02298 const DBusString *b) 02299 { 02300 const unsigned char *ap; 02301 const unsigned char *bp; 02302 const unsigned char *a_end; 02303 const DBusRealString *real_a = (const DBusRealString*) a; 02304 const DBusRealString *real_b = (const DBusRealString*) b; 02305 DBUS_GENERIC_STRING_PREAMBLE (real_a); 02306 DBUS_GENERIC_STRING_PREAMBLE (real_b); 02307 02308 if (real_a->len != real_b->len) 02309 return FALSE; 02310 02311 ap = real_a->str; 02312 bp = real_b->str; 02313 a_end = real_a->str + real_a->len; 02314 while (ap != a_end) 02315 { 02316 if (*ap != *bp) 02317 return FALSE; 02318 02319 ++ap; 02320 ++bp; 02321 } 02322 02323 return TRUE; 02324 } 02325 02339 dbus_bool_t 02340 _dbus_string_equal_len (const DBusString *a, 02341 const DBusString *b, 02342 int len) 02343 { 02344 const unsigned char *ap; 02345 const unsigned char *bp; 02346 const unsigned char *a_end; 02347 const DBusRealString *real_a = (const DBusRealString*) a; 02348 const DBusRealString *real_b = (const DBusRealString*) b; 02349 DBUS_GENERIC_STRING_PREAMBLE (real_a); 02350 DBUS_GENERIC_STRING_PREAMBLE (real_b); 02351 02352 if (real_a->len != real_b->len && 02353 (real_a->len < len || real_b->len < len)) 02354 return FALSE; 02355 02356 ap = real_a->str; 02357 bp = real_b->str; 02358 a_end = real_a->str + MIN (real_a->len, len); 02359 while (ap != a_end) 02360 { 02361 if (*ap != *bp) 02362 return FALSE; 02363 02364 ++ap; 02365 ++bp; 02366 } 02367 02368 return TRUE; 02369 } 02370 02387 dbus_bool_t 02388 _dbus_string_equal_substring (const DBusString *a, 02389 int a_start, 02390 int a_len, 02391 const DBusString *b, 02392 int b_start) 02393 { 02394 const unsigned char *ap; 02395 const unsigned char *bp; 02396 const unsigned char *a_end; 02397 const DBusRealString *real_a = (const DBusRealString*) a; 02398 const DBusRealString *real_b = (const DBusRealString*) b; 02399 DBUS_GENERIC_STRING_PREAMBLE (real_a); 02400 DBUS_GENERIC_STRING_PREAMBLE (real_b); 02401 _dbus_assert (a_start >= 0); 02402 _dbus_assert (a_len >= 0); 02403 _dbus_assert (a_start <= real_a->len); 02404 _dbus_assert (a_len <= real_a->len - a_start); 02405 _dbus_assert (b_start >= 0); 02406 _dbus_assert (b_start <= real_b->len); 02407 02408 if (a_len > real_b->len - b_start) 02409 return FALSE; 02410 02411 ap = real_a->str + a_start; 02412 bp = real_b->str + b_start; 02413 a_end = ap + a_len; 02414 while (ap != a_end) 02415 { 02416 if (*ap != *bp) 02417 return FALSE; 02418 02419 ++ap; 02420 ++bp; 02421 } 02422 02423 _dbus_assert (bp <= (real_b->str + real_b->len)); 02424 02425 return TRUE; 02426 } 02427 02435 dbus_bool_t 02436 _dbus_string_equal_c_str (const DBusString *a, 02437 const char *c_str) 02438 { 02439 const unsigned char *ap; 02440 const unsigned char *bp; 02441 const unsigned char *a_end; 02442 const DBusRealString *real_a = (const DBusRealString*) a; 02443 DBUS_GENERIC_STRING_PREAMBLE (real_a); 02444 _dbus_assert (c_str != NULL); 02445 02446 ap = real_a->str; 02447 bp = (const unsigned char*) c_str; 02448 a_end = real_a->str + real_a->len; 02449 while (ap != a_end && *bp) 02450 { 02451 if (*ap != *bp) 02452 return FALSE; 02453 02454 ++ap; 02455 ++bp; 02456 } 02457 02458 if (ap != a_end || *bp) 02459 return FALSE; 02460 02461 return TRUE; 02462 } 02463 02464 #ifdef DBUS_BUILD_TESTS 02465 02472 dbus_bool_t 02473 _dbus_string_starts_with_c_str (const DBusString *a, 02474 const char *c_str) 02475 { 02476 const unsigned char *ap; 02477 const unsigned char *bp; 02478 const unsigned char *a_end; 02479 const DBusRealString *real_a = (const DBusRealString*) a; 02480 DBUS_GENERIC_STRING_PREAMBLE (real_a); 02481 _dbus_assert (c_str != NULL); 02482 02483 ap = real_a->str; 02484 bp = (const unsigned char*) c_str; 02485 a_end = real_a->str + real_a->len; 02486 while (ap != a_end && *bp) 02487 { 02488 if (*ap != *bp) 02489 return FALSE; 02490 02491 ++ap; 02492 ++bp; 02493 } 02494 02495 if (*bp == '\0') 02496 return TRUE; 02497 else 02498 return FALSE; 02499 } 02500 #endif /* DBUS_BUILD_TESTS */ 02501 02510 dbus_bool_t 02511 _dbus_string_append_byte_as_hex (DBusString *str, 02512 int byte) 02513 { 02514 const char hexdigits[16] = { 02515 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 02516 'a', 'b', 'c', 'd', 'e', 'f' 02517 }; 02518 02519 if (!_dbus_string_append_byte (str, 02520 hexdigits[(byte >> 4)])) 02521 return FALSE; 02522 02523 if (!_dbus_string_append_byte (str, 02524 hexdigits[(byte & 0x0f)])) 02525 { 02526 _dbus_string_set_length (str, 02527 _dbus_string_get_length (str) - 1); 02528 return FALSE; 02529 } 02530 02531 return TRUE; 02532 } 02533 02544 dbus_bool_t 02545 _dbus_string_hex_encode (const DBusString *source, 02546 int start, 02547 DBusString *dest, 02548 int insert_at) 02549 { 02550 DBusString result; 02551 const unsigned char *p; 02552 const unsigned char *end; 02553 dbus_bool_t retval; 02554 02555 _dbus_assert (start <= _dbus_string_get_length (source)); 02556 02557 if (!_dbus_string_init (&result)) 02558 return FALSE; 02559 02560 retval = FALSE; 02561 02562 p = (const unsigned char*) _dbus_string_get_const_data (source); 02563 end = p + _dbus_string_get_length (source); 02564 p += start; 02565 02566 while (p != end) 02567 { 02568 if (!_dbus_string_append_byte_as_hex (&result, *p)) 02569 goto out; 02570 02571 ++p; 02572 } 02573 02574 if (!_dbus_string_move (&result, 0, dest, insert_at)) 02575 goto out; 02576 02577 retval = TRUE; 02578 02579 out: 02580 _dbus_string_free (&result); 02581 return retval; 02582 } 02583 02594 dbus_bool_t 02595 _dbus_string_hex_decode (const DBusString *source, 02596 int start, 02597 int *end_return, 02598 DBusString *dest, 02599 int insert_at) 02600 { 02601 DBusString result; 02602 const unsigned char *p; 02603 const unsigned char *end; 02604 dbus_bool_t retval; 02605 dbus_bool_t high_bits; 02606 02607 _dbus_assert (start <= _dbus_string_get_length (source)); 02608 02609 if (!_dbus_string_init (&result)) 02610 return FALSE; 02611 02612 retval = FALSE; 02613 02614 high_bits = TRUE; 02615 p = (const unsigned char*) _dbus_string_get_const_data (source); 02616 end = p + _dbus_string_get_length (source); 02617 p += start; 02618 02619 while (p != end) 02620 { 02621 unsigned int val; 02622 02623 switch (*p) 02624 { 02625 case '0': 02626 val = 0; 02627 break; 02628 case '1': 02629 val = 1; 02630 break; 02631 case '2': 02632 val = 2; 02633 break; 02634 case '3': 02635 val = 3; 02636 break; 02637 case '4': 02638 val = 4; 02639 break; 02640 case '5': 02641 val = 5; 02642 break; 02643 case '6': 02644 val = 6; 02645 break; 02646 case '7': 02647 val = 7; 02648 break; 02649 case '8': 02650 val = 8; 02651 break; 02652 case '9': 02653 val = 9; 02654 break; 02655 case 'a': 02656 case 'A': 02657 val = 10; 02658 break; 02659 case 'b': 02660 case 'B': 02661 val = 11; 02662 break; 02663 case 'c': 02664 case 'C': 02665 val = 12; 02666 break; 02667 case 'd': 02668 case 'D': 02669 val = 13; 02670 break; 02671 case 'e': 02672 case 'E': 02673 val = 14; 02674 break; 02675 case 'f': 02676 case 'F': 02677 val = 15; 02678 break; 02679 default: 02680 goto done; 02681 } 02682 02683 if (high_bits) 02684 { 02685 if (!_dbus_string_append_byte (&result, 02686 val << 4)) 02687 goto out; 02688 } 02689 else 02690 { 02691 int len; 02692 unsigned char b; 02693 02694 len = _dbus_string_get_length (&result); 02695 02696 b = _dbus_string_get_byte (&result, len - 1); 02697 02698 b |= val; 02699 02700 _dbus_string_set_byte (&result, len - 1, b); 02701 } 02702 02703 high_bits = !high_bits; 02704 02705 ++p; 02706 } 02707 02708 done: 02709 if (!_dbus_string_move (&result, 0, dest, insert_at)) 02710 goto out; 02711 02712 if (end_return) 02713 *end_return = p - (const unsigned char*) _dbus_string_get_const_data (source); 02714 02715 retval = TRUE; 02716 02717 out: 02718 _dbus_string_free (&result); 02719 return retval; 02720 } 02721 02735 dbus_bool_t 02736 _dbus_string_validate_ascii (const DBusString *str, 02737 int start, 02738 int len) 02739 { 02740 const unsigned char *s; 02741 const unsigned char *end; 02742 DBUS_CONST_STRING_PREAMBLE (str); 02743 _dbus_assert (start >= 0); 02744 _dbus_assert (start <= real->len); 02745 _dbus_assert (len >= 0); 02746 02747 if (len > real->len - start) 02748 return FALSE; 02749 02750 s = real->str + start; 02751 end = s + len; 02752 while (s != end) 02753 { 02754 if (_DBUS_UNLIKELY (!_DBUS_ISASCII (*s))) 02755 return FALSE; 02756 02757 ++s; 02758 } 02759 02760 return TRUE; 02761 } 02762 02770 void 02771 _dbus_string_tolower_ascii (const DBusString *str, 02772 int start, 02773 int len) 02774 { 02775 unsigned char *s; 02776 unsigned char *end; 02777 DBUS_STRING_PREAMBLE (str); 02778 _dbus_assert (start >= 0); 02779 _dbus_assert (start <= real->len); 02780 _dbus_assert (len >= 0); 02781 _dbus_assert (len <= real->len - start); 02782 02783 s = real->str + start; 02784 end = s + len; 02785 02786 while (s != end) 02787 { 02788 if (*s >= 'A' && *s <= 'Z') 02789 *s += 'a' - 'A'; 02790 ++s; 02791 } 02792 } 02793 02801 void 02802 _dbus_string_toupper_ascii (const DBusString *str, 02803 int start, 02804 int len) 02805 { 02806 unsigned char *s; 02807 unsigned char *end; 02808 DBUS_STRING_PREAMBLE (str); 02809 _dbus_assert (start >= 0); 02810 _dbus_assert (start <= real->len); 02811 _dbus_assert (len >= 0); 02812 _dbus_assert (len <= real->len - start); 02813 02814 s = real->str + start; 02815 end = s + len; 02816 02817 while (s != end) 02818 { 02819 if (*s >= 'a' && *s <= 'z') 02820 *s += 'A' - 'a'; 02821 ++s; 02822 } 02823 } 02824 02840 dbus_bool_t 02841 _dbus_string_validate_utf8 (const DBusString *str, 02842 int start, 02843 int len) 02844 { 02845 const unsigned char *p; 02846 const unsigned char *end; 02847 DBUS_CONST_STRING_PREAMBLE (str); 02848 _dbus_assert (start >= 0); 02849 _dbus_assert (start <= real->len); 02850 _dbus_assert (len >= 0); 02851 02852 /* we are doing _DBUS_UNLIKELY() here which might be 02853 * dubious in a generic library like GLib, but in D-Bus 02854 * we know we're validating messages and that it would 02855 * only be evil/broken apps that would have invalid 02856 * UTF-8. Also, this function seems to be a performance 02857 * bottleneck in profiles. 02858 */ 02859 02860 if (_DBUS_UNLIKELY (len > real->len - start)) 02861 return FALSE; 02862 02863 p = real->str + start; 02864 end = p + len; 02865 02866 while (p < end) 02867 { 02868 int i, mask, char_len; 02869 dbus_unichar_t result; 02870 02871 /* nul bytes considered invalid */ 02872 if (*p == '\0') 02873 break; 02874 02875 /* Special-case ASCII; this makes us go a lot faster in 02876 * D-Bus profiles where we are typically validating 02877 * function names and such. We have to know that 02878 * all following checks will pass for ASCII though, 02879 * comments follow ... 02880 */ 02881 if (*p < 128) 02882 { 02883 ++p; 02884 continue; 02885 } 02886 02887 UTF8_COMPUTE (*p, mask, char_len); 02888 02889 if (_DBUS_UNLIKELY (char_len == 0)) /* ASCII: char_len == 1 */ 02890 break; 02891 02892 /* check that the expected number of bytes exists in the remaining length */ 02893 if (_DBUS_UNLIKELY ((end - p) < char_len)) /* ASCII: p < end and char_len == 1 */ 02894 break; 02895 02896 UTF8_GET (result, p, i, mask, char_len); 02897 02898 /* Check for overlong UTF-8 */ 02899 if (_DBUS_UNLIKELY (UTF8_LENGTH (result) != char_len)) /* ASCII: UTF8_LENGTH == 1 */ 02900 break; 02901 #if 0 02902 /* The UNICODE_VALID check below will catch this */ 02903 if (_DBUS_UNLIKELY (result == (dbus_unichar_t)-1)) /* ASCII: result = ascii value */ 02904 break; 02905 #endif 02906 02907 if (_DBUS_UNLIKELY (!UNICODE_VALID (result))) /* ASCII: always valid */ 02908 break; 02909 02910 /* UNICODE_VALID should have caught it */ 02911 _dbus_assert (result != (dbus_unichar_t)-1); 02912 02913 p += char_len; 02914 } 02915 02916 /* See that we covered the entire length if a length was 02917 * passed in 02918 */ 02919 if (_DBUS_UNLIKELY (p != end)) 02920 return FALSE; 02921 else 02922 return TRUE; 02923 } 02924 02938 dbus_bool_t 02939 _dbus_string_validate_nul (const DBusString *str, 02940 int start, 02941 int len) 02942 { 02943 const unsigned char *s; 02944 const unsigned char *end; 02945 DBUS_CONST_STRING_PREAMBLE (str); 02946 _dbus_assert (start >= 0); 02947 _dbus_assert (len >= 0); 02948 _dbus_assert (start <= real->len); 02949 02950 if (len > real->len - start) 02951 return FALSE; 02952 02953 s = real->str + start; 02954 end = s + len; 02955 while (s != end) 02956 { 02957 if (_DBUS_UNLIKELY (*s != '\0')) 02958 return FALSE; 02959 ++s; 02960 } 02961 02962 return TRUE; 02963 } 02964 02970 void 02971 _dbus_string_zero (DBusString *str) 02972 { 02973 DBUS_STRING_PREAMBLE (str); 02974 02975 memset (real->str - real->align_offset, '\0', real->allocated); 02976 } 02979 /* tests are in dbus-string-util.c */