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