D-Bus 1.4.14
|
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 (len < 0) 01259 return FALSE; 01260 01261 if (!_dbus_string_lengthen (str, len)) 01262 { 01263 /* don't leak the copy */ 01264 va_end (args_copy); 01265 return FALSE; 01266 } 01267 01268 vsprintf ((char*) (real->str + (real->len - len)), 01269 format, args_copy); 01270 01271 va_end (args_copy); 01272 01273 return TRUE; 01274 } 01275 01284 dbus_bool_t 01285 _dbus_string_append_printf (DBusString *str, 01286 const char *format, 01287 ...) 01288 { 01289 va_list args; 01290 dbus_bool_t retval; 01291 01292 va_start (args, format); 01293 retval = _dbus_string_append_printf_valist (str, format, args); 01294 va_end (args); 01295 01296 return retval; 01297 } 01298 01307 dbus_bool_t 01308 _dbus_string_append_len (DBusString *str, 01309 const char *buffer, 01310 int len) 01311 { 01312 DBUS_STRING_PREAMBLE (str); 01313 _dbus_assert (buffer != NULL); 01314 _dbus_assert (len >= 0); 01315 01316 return append (real, buffer, len); 01317 } 01318 01327 dbus_bool_t 01328 _dbus_string_append_byte (DBusString *str, 01329 unsigned char byte) 01330 { 01331 DBUS_STRING_PREAMBLE (str); 01332 01333 if (!set_length (real, real->len + 1)) 01334 return FALSE; 01335 01336 real->str[real->len-1] = byte; 01337 01338 return TRUE; 01339 } 01340 01341 #ifdef DBUS_BUILD_TESTS 01342 01349 dbus_bool_t 01350 _dbus_string_append_unichar (DBusString *str, 01351 dbus_unichar_t ch) 01352 { 01353 int len; 01354 int first; 01355 int i; 01356 unsigned char *out; 01357 01358 DBUS_STRING_PREAMBLE (str); 01359 01360 /* this code is from GLib but is pretty standard I think */ 01361 01362 len = 0; 01363 01364 if (ch < 0x80) 01365 { 01366 first = 0; 01367 len = 1; 01368 } 01369 else if (ch < 0x800) 01370 { 01371 first = 0xc0; 01372 len = 2; 01373 } 01374 else if (ch < 0x10000) 01375 { 01376 first = 0xe0; 01377 len = 3; 01378 } 01379 else if (ch < 0x200000) 01380 { 01381 first = 0xf0; 01382 len = 4; 01383 } 01384 else if (ch < 0x4000000) 01385 { 01386 first = 0xf8; 01387 len = 5; 01388 } 01389 else 01390 { 01391 first = 0xfc; 01392 len = 6; 01393 } 01394 01395 if (len > (real->max_length - real->len)) 01396 return FALSE; /* real->len + len would overflow */ 01397 01398 if (!set_length (real, real->len + len)) 01399 return FALSE; 01400 01401 out = real->str + (real->len - len); 01402 01403 for (i = len - 1; i > 0; --i) 01404 { 01405 out[i] = (ch & 0x3f) | 0x80; 01406 ch >>= 6; 01407 } 01408 out[0] = ch | first; 01409 01410 return TRUE; 01411 } 01412 #endif /* DBUS_BUILD_TESTS */ 01413 01414 static void 01415 delete (DBusRealString *real, 01416 int start, 01417 int len) 01418 { 01419 if (len == 0) 01420 return; 01421 01422 memmove (real->str + start, real->str + start + len, real->len - (start + len)); 01423 real->len -= len; 01424 real->str[real->len] = '\0'; 01425 } 01426 01436 void 01437 _dbus_string_delete (DBusString *str, 01438 int start, 01439 int len) 01440 { 01441 DBUS_STRING_PREAMBLE (str); 01442 _dbus_assert (start >= 0); 01443 _dbus_assert (len >= 0); 01444 _dbus_assert (start <= real->len); 01445 _dbus_assert (len <= real->len - start); 01446 01447 delete (real, start, len); 01448 } 01449 01450 static dbus_bool_t 01451 copy (DBusRealString *source, 01452 int start, 01453 int len, 01454 DBusRealString *dest, 01455 int insert_at) 01456 { 01457 if (len == 0) 01458 return TRUE; 01459 01460 if (!open_gap (len, dest, insert_at)) 01461 return FALSE; 01462 01463 memmove (dest->str + insert_at, 01464 source->str + start, 01465 len); 01466 01467 return TRUE; 01468 } 01469 01479 #define DBUS_STRING_COPY_PREAMBLE(source, start, dest, insert_at) \ 01480 DBusRealString *real_source = (DBusRealString*) source; \ 01481 DBusRealString *real_dest = (DBusRealString*) dest; \ 01482 _dbus_assert ((source) != (dest)); \ 01483 DBUS_GENERIC_STRING_PREAMBLE (real_source); \ 01484 DBUS_GENERIC_STRING_PREAMBLE (real_dest); \ 01485 _dbus_assert (!real_dest->constant); \ 01486 _dbus_assert (!real_dest->locked); \ 01487 _dbus_assert ((start) >= 0); \ 01488 _dbus_assert ((start) <= real_source->len); \ 01489 _dbus_assert ((insert_at) >= 0); \ 01490 _dbus_assert ((insert_at) <= real_dest->len) 01491 01502 dbus_bool_t 01503 _dbus_string_move (DBusString *source, 01504 int start, 01505 DBusString *dest, 01506 int insert_at) 01507 { 01508 DBusRealString *real_source = (DBusRealString*) source; 01509 _dbus_assert (start <= real_source->len); 01510 01511 return _dbus_string_move_len (source, start, 01512 real_source->len - start, 01513 dest, insert_at); 01514 } 01515 01526 dbus_bool_t 01527 _dbus_string_copy (const DBusString *source, 01528 int start, 01529 DBusString *dest, 01530 int insert_at) 01531 { 01532 DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at); 01533 01534 return copy (real_source, start, 01535 real_source->len - start, 01536 real_dest, 01537 insert_at); 01538 } 01539 01554 dbus_bool_t 01555 _dbus_string_move_len (DBusString *source, 01556 int start, 01557 int len, 01558 DBusString *dest, 01559 int insert_at) 01560 01561 { 01562 DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at); 01563 _dbus_assert (len >= 0); 01564 _dbus_assert ((start + len) <= real_source->len); 01565 01566 01567 if (len == 0) 01568 { 01569 return TRUE; 01570 } 01571 else if (start == 0 && 01572 len == real_source->len && 01573 real_dest->len == 0) 01574 { 01575 /* Short-circuit moving an entire existing string to an empty string 01576 * by just swapping the buffers. 01577 */ 01578 /* we assume ->constant doesn't matter as you can't have 01579 * a constant string involved in a move. 01580 */ 01581 #define ASSIGN_DATA(a, b) do { \ 01582 (a)->str = (b)->str; \ 01583 (a)->len = (b)->len; \ 01584 (a)->allocated = (b)->allocated; \ 01585 (a)->align_offset = (b)->align_offset; \ 01586 } while (0) 01587 01588 DBusRealString tmp; 01589 01590 ASSIGN_DATA (&tmp, real_source); 01591 ASSIGN_DATA (real_source, real_dest); 01592 ASSIGN_DATA (real_dest, &tmp); 01593 01594 return TRUE; 01595 } 01596 else 01597 { 01598 if (!copy (real_source, start, len, 01599 real_dest, 01600 insert_at)) 01601 return FALSE; 01602 01603 delete (real_source, start, 01604 len); 01605 01606 return TRUE; 01607 } 01608 } 01609 01621 dbus_bool_t 01622 _dbus_string_copy_len (const DBusString *source, 01623 int start, 01624 int len, 01625 DBusString *dest, 01626 int insert_at) 01627 { 01628 DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at); 01629 _dbus_assert (len >= 0); 01630 _dbus_assert (start <= real_source->len); 01631 _dbus_assert (len <= real_source->len - start); 01632 01633 return copy (real_source, start, len, 01634 real_dest, 01635 insert_at); 01636 } 01637 01659 dbus_bool_t 01660 _dbus_string_replace_len (const DBusString *source, 01661 int start, 01662 int len, 01663 DBusString *dest, 01664 int replace_at, 01665 int replace_len) 01666 { 01667 DBUS_STRING_COPY_PREAMBLE (source, start, dest, replace_at); 01668 _dbus_assert (len >= 0); 01669 _dbus_assert (start <= real_source->len); 01670 _dbus_assert (len <= real_source->len - start); 01671 _dbus_assert (replace_at >= 0); 01672 _dbus_assert (replace_at <= real_dest->len); 01673 _dbus_assert (replace_len <= real_dest->len - replace_at); 01674 01675 if (!copy (real_source, start, len, 01676 real_dest, replace_at)) 01677 return FALSE; 01678 01679 delete (real_dest, replace_at + len, replace_len); 01680 01681 return TRUE; 01682 } 01683 01696 dbus_bool_t 01697 _dbus_string_split_on_byte (DBusString *source, 01698 unsigned char byte, 01699 DBusString *tail) 01700 { 01701 int byte_position; 01702 char byte_string[2] = ""; 01703 int head_length; 01704 int tail_length; 01705 01706 byte_string[0] = (char) byte; 01707 01708 if (!_dbus_string_find (source, 0, byte_string, &byte_position)) 01709 return FALSE; 01710 01711 head_length = byte_position; 01712 tail_length = _dbus_string_get_length (source) - head_length - 1; 01713 01714 if (!_dbus_string_move_len (source, byte_position + 1, tail_length, 01715 tail, 0)) 01716 return FALSE; 01717 01718 /* remove the trailing delimiter byte from the head now. 01719 */ 01720 if (!_dbus_string_set_length (source, head_length)) 01721 return FALSE; 01722 01723 return TRUE; 01724 } 01725 01726 /* Unicode macros and utf8_validate() from GLib Owen Taylor, Havoc 01727 * Pennington, and Tom Tromey are the authors and authorized relicense. 01728 */ 01729 01735 #define UTF8_COMPUTE(Char, Mask, Len) \ 01736 if (Char < 128) \ 01737 { \ 01738 Len = 1; \ 01739 Mask = 0x7f; \ 01740 } \ 01741 else if ((Char & 0xe0) == 0xc0) \ 01742 { \ 01743 Len = 2; \ 01744 Mask = 0x1f; \ 01745 } \ 01746 else if ((Char & 0xf0) == 0xe0) \ 01747 { \ 01748 Len = 3; \ 01749 Mask = 0x0f; \ 01750 } \ 01751 else if ((Char & 0xf8) == 0xf0) \ 01752 { \ 01753 Len = 4; \ 01754 Mask = 0x07; \ 01755 } \ 01756 else if ((Char & 0xfc) == 0xf8) \ 01757 { \ 01758 Len = 5; \ 01759 Mask = 0x03; \ 01760 } \ 01761 else if ((Char & 0xfe) == 0xfc) \ 01762 { \ 01763 Len = 6; \ 01764 Mask = 0x01; \ 01765 } \ 01766 else \ 01767 { \ 01768 Len = 0; \ 01769 Mask = 0; \ 01770 } 01771 01776 #define UTF8_LENGTH(Char) \ 01777 ((Char) < 0x80 ? 1 : \ 01778 ((Char) < 0x800 ? 2 : \ 01779 ((Char) < 0x10000 ? 3 : \ 01780 ((Char) < 0x200000 ? 4 : \ 01781 ((Char) < 0x4000000 ? 5 : 6))))) 01782 01792 #define UTF8_GET(Result, Chars, Count, Mask, Len) \ 01793 (Result) = (Chars)[0] & (Mask); \ 01794 for ((Count) = 1; (Count) < (Len); ++(Count)) \ 01795 { \ 01796 if (((Chars)[(Count)] & 0xc0) != 0x80) \ 01797 { \ 01798 (Result) = -1; \ 01799 break; \ 01800 } \ 01801 (Result) <<= 6; \ 01802 (Result) |= ((Chars)[(Count)] & 0x3f); \ 01803 } 01804 01821 #define UNICODE_VALID(Char) \ 01822 ((Char) < 0x110000 && \ 01823 (((Char) & 0xFFFFF800) != 0xD800) && \ 01824 ((Char) < 0xFDD0 || (Char) > 0xFDEF) && \ 01825 ((Char) & 0xFFFE) != 0xFFFE) 01826 01827 #ifdef DBUS_BUILD_TESTS 01828 01838 void 01839 _dbus_string_get_unichar (const DBusString *str, 01840 int start, 01841 dbus_unichar_t *ch_return, 01842 int *end_return) 01843 { 01844 int i, mask, len; 01845 dbus_unichar_t result; 01846 unsigned char c; 01847 unsigned char *p; 01848 DBUS_CONST_STRING_PREAMBLE (str); 01849 _dbus_assert (start >= 0); 01850 _dbus_assert (start <= real->len); 01851 01852 if (ch_return) 01853 *ch_return = 0; 01854 if (end_return) 01855 *end_return = real->len; 01856 01857 mask = 0; 01858 p = real->str + start; 01859 c = *p; 01860 01861 UTF8_COMPUTE (c, mask, len); 01862 if (len == 0) 01863 return; 01864 UTF8_GET (result, p, i, mask, len); 01865 01866 if (result == (dbus_unichar_t)-1) 01867 return; 01868 01869 if (ch_return) 01870 *ch_return = result; 01871 if (end_return) 01872 *end_return = start + len; 01873 } 01874 #endif /* DBUS_BUILD_TESTS */ 01875 01890 dbus_bool_t 01891 _dbus_string_find (const DBusString *str, 01892 int start, 01893 const char *substr, 01894 int *found) 01895 { 01896 return _dbus_string_find_to (str, start, 01897 ((const DBusRealString*)str)->len, 01898 substr, found); 01899 } 01900 01913 dbus_bool_t 01914 _dbus_string_find_eol (const DBusString *str, 01915 int start, 01916 int *found, 01917 int *found_len) 01918 { 01919 int i; 01920 01921 DBUS_CONST_STRING_PREAMBLE (str); 01922 _dbus_assert (start <= real->len); 01923 _dbus_assert (start >= 0); 01924 01925 i = start; 01926 while (i < real->len) 01927 { 01928 if (real->str[i] == '\r') 01929 { 01930 if ((i+1) < real->len && real->str[i+1] == '\n') /* "\r\n" */ 01931 { 01932 if (found) 01933 *found = i; 01934 if (found_len) 01935 *found_len = 2; 01936 return TRUE; 01937 } 01938 else /* only "\r" */ 01939 { 01940 if (found) 01941 *found = i; 01942 if (found_len) 01943 *found_len = 1; 01944 return TRUE; 01945 } 01946 } 01947 else if (real->str[i] == '\n') /* only "\n" */ 01948 { 01949 if (found) 01950 *found = i; 01951 if (found_len) 01952 *found_len = 1; 01953 return TRUE; 01954 } 01955 ++i; 01956 } 01957 01958 if (found) 01959 *found = real->len; 01960 01961 if (found_len) 01962 *found_len = 0; 01963 01964 return FALSE; 01965 } 01966 01983 dbus_bool_t 01984 _dbus_string_find_to (const DBusString *str, 01985 int start, 01986 int end, 01987 const char *substr, 01988 int *found) 01989 { 01990 int i; 01991 DBUS_CONST_STRING_PREAMBLE (str); 01992 _dbus_assert (substr != NULL); 01993 _dbus_assert (start <= real->len); 01994 _dbus_assert (start >= 0); 01995 _dbus_assert (substr != NULL); 01996 _dbus_assert (end <= real->len); 01997 _dbus_assert (start <= end); 01998 01999 /* we always "find" an empty string */ 02000 if (*substr == '\0') 02001 { 02002 if (found) 02003 *found = start; 02004 return TRUE; 02005 } 02006 02007 i = start; 02008 while (i < end) 02009 { 02010 if (real->str[i] == substr[0]) 02011 { 02012 int j = i + 1; 02013 02014 while (j < end) 02015 { 02016 if (substr[j - i] == '\0') 02017 break; 02018 else if (real->str[j] != substr[j - i]) 02019 break; 02020 02021 ++j; 02022 } 02023 02024 if (substr[j - i] == '\0') 02025 { 02026 if (found) 02027 *found = i; 02028 return TRUE; 02029 } 02030 } 02031 02032 ++i; 02033 } 02034 02035 if (found) 02036 *found = end; 02037 02038 return FALSE; 02039 } 02040 02051 dbus_bool_t 02052 _dbus_string_find_blank (const DBusString *str, 02053 int start, 02054 int *found) 02055 { 02056 int i; 02057 DBUS_CONST_STRING_PREAMBLE (str); 02058 _dbus_assert (start <= real->len); 02059 _dbus_assert (start >= 0); 02060 02061 i = start; 02062 while (i < real->len) 02063 { 02064 if (real->str[i] == ' ' || 02065 real->str[i] == '\t') 02066 { 02067 if (found) 02068 *found = i; 02069 return TRUE; 02070 } 02071 02072 ++i; 02073 } 02074 02075 if (found) 02076 *found = real->len; 02077 02078 return FALSE; 02079 } 02080 02089 void 02090 _dbus_string_skip_blank (const DBusString *str, 02091 int start, 02092 int *end) 02093 { 02094 int i; 02095 DBUS_CONST_STRING_PREAMBLE (str); 02096 _dbus_assert (start <= real->len); 02097 _dbus_assert (start >= 0); 02098 02099 i = start; 02100 while (i < real->len) 02101 { 02102 if (!DBUS_IS_ASCII_BLANK (real->str[i])) 02103 break; 02104 02105 ++i; 02106 } 02107 02108 _dbus_assert (i == real->len || !DBUS_IS_ASCII_WHITE (real->str[i])); 02109 02110 if (end) 02111 *end = i; 02112 } 02113 02114 02123 void 02124 _dbus_string_skip_white (const DBusString *str, 02125 int start, 02126 int *end) 02127 { 02128 int i; 02129 DBUS_CONST_STRING_PREAMBLE (str); 02130 _dbus_assert (start <= real->len); 02131 _dbus_assert (start >= 0); 02132 02133 i = start; 02134 while (i < real->len) 02135 { 02136 if (!DBUS_IS_ASCII_WHITE (real->str[i])) 02137 break; 02138 02139 ++i; 02140 } 02141 02142 _dbus_assert (i == real->len || !(DBUS_IS_ASCII_WHITE (real->str[i]))); 02143 02144 if (end) 02145 *end = i; 02146 } 02147 02156 void 02157 _dbus_string_skip_white_reverse (const DBusString *str, 02158 int end, 02159 int *start) 02160 { 02161 int i; 02162 DBUS_CONST_STRING_PREAMBLE (str); 02163 _dbus_assert (end <= real->len); 02164 _dbus_assert (end >= 0); 02165 02166 i = end; 02167 while (i > 0) 02168 { 02169 if (!DBUS_IS_ASCII_WHITE (real->str[i-1])) 02170 break; 02171 --i; 02172 } 02173 02174 _dbus_assert (i >= 0 && (i == 0 || !(DBUS_IS_ASCII_WHITE (real->str[i-1])))); 02175 02176 if (start) 02177 *start = i; 02178 } 02179 02195 dbus_bool_t 02196 _dbus_string_pop_line (DBusString *source, 02197 DBusString *dest) 02198 { 02199 int eol, eol_len; 02200 02201 _dbus_string_set_length (dest, 0); 02202 02203 eol = 0; 02204 eol_len = 0; 02205 if (!_dbus_string_find_eol (source, 0, &eol, &eol_len)) 02206 { 02207 _dbus_assert (eol == _dbus_string_get_length (source)); 02208 if (eol == 0) 02209 { 02210 /* If there's no newline and source has zero length, we're done */ 02211 return FALSE; 02212 } 02213 /* otherwise, the last line of the file has no eol characters */ 02214 } 02215 02216 /* remember eol can be 0 if it's an empty line, but eol_len should not be zero also 02217 * since find_eol returned TRUE 02218 */ 02219 02220 if (!_dbus_string_move_len (source, 0, eol + eol_len, dest, 0)) 02221 return FALSE; 02222 02223 /* remove line ending */ 02224 if (!_dbus_string_set_length (dest, eol)) 02225 { 02226 _dbus_assert_not_reached ("out of memory when shortening a string"); 02227 return FALSE; 02228 } 02229 02230 return TRUE; 02231 } 02232 02233 #ifdef DBUS_BUILD_TESTS 02234 02240 void 02241 _dbus_string_delete_first_word (DBusString *str) 02242 { 02243 int i; 02244 02245 if (_dbus_string_find_blank (str, 0, &i)) 02246 _dbus_string_skip_blank (str, i, &i); 02247 02248 _dbus_string_delete (str, 0, i); 02249 } 02250 #endif 02251 02252 #ifdef DBUS_BUILD_TESTS 02253 02258 void 02259 _dbus_string_delete_leading_blanks (DBusString *str) 02260 { 02261 int i; 02262 02263 _dbus_string_skip_blank (str, 0, &i); 02264 02265 if (i > 0) 02266 _dbus_string_delete (str, 0, i); 02267 } 02268 #endif 02269 02275 void 02276 _dbus_string_chop_white(DBusString *str) 02277 { 02278 int i; 02279 02280 _dbus_string_skip_white (str, 0, &i); 02281 02282 if (i > 0) 02283 _dbus_string_delete (str, 0, i); 02284 02285 _dbus_string_skip_white_reverse (str, _dbus_string_get_length (str), &i); 02286 02287 _dbus_string_set_length (str, i); 02288 } 02289 02299 dbus_bool_t 02300 _dbus_string_equal (const DBusString *a, 02301 const DBusString *b) 02302 { 02303 const unsigned char *ap; 02304 const unsigned char *bp; 02305 const unsigned char *a_end; 02306 const DBusRealString *real_a = (const DBusRealString*) a; 02307 const DBusRealString *real_b = (const DBusRealString*) b; 02308 DBUS_GENERIC_STRING_PREAMBLE (real_a); 02309 DBUS_GENERIC_STRING_PREAMBLE (real_b); 02310 02311 if (real_a->len != real_b->len) 02312 return FALSE; 02313 02314 ap = real_a->str; 02315 bp = real_b->str; 02316 a_end = real_a->str + real_a->len; 02317 while (ap != a_end) 02318 { 02319 if (*ap != *bp) 02320 return FALSE; 02321 02322 ++ap; 02323 ++bp; 02324 } 02325 02326 return TRUE; 02327 } 02328 02342 dbus_bool_t 02343 _dbus_string_equal_len (const DBusString *a, 02344 const DBusString *b, 02345 int len) 02346 { 02347 const unsigned char *ap; 02348 const unsigned char *bp; 02349 const unsigned char *a_end; 02350 const DBusRealString *real_a = (const DBusRealString*) a; 02351 const DBusRealString *real_b = (const DBusRealString*) b; 02352 DBUS_GENERIC_STRING_PREAMBLE (real_a); 02353 DBUS_GENERIC_STRING_PREAMBLE (real_b); 02354 02355 if (real_a->len != real_b->len && 02356 (real_a->len < len || real_b->len < len)) 02357 return FALSE; 02358 02359 ap = real_a->str; 02360 bp = real_b->str; 02361 a_end = real_a->str + MIN (real_a->len, len); 02362 while (ap != a_end) 02363 { 02364 if (*ap != *bp) 02365 return FALSE; 02366 02367 ++ap; 02368 ++bp; 02369 } 02370 02371 return TRUE; 02372 } 02373 02390 dbus_bool_t 02391 _dbus_string_equal_substring (const DBusString *a, 02392 int a_start, 02393 int a_len, 02394 const DBusString *b, 02395 int b_start) 02396 { 02397 const unsigned char *ap; 02398 const unsigned char *bp; 02399 const unsigned char *a_end; 02400 const DBusRealString *real_a = (const DBusRealString*) a; 02401 const DBusRealString *real_b = (const DBusRealString*) b; 02402 DBUS_GENERIC_STRING_PREAMBLE (real_a); 02403 DBUS_GENERIC_STRING_PREAMBLE (real_b); 02404 _dbus_assert (a_start >= 0); 02405 _dbus_assert (a_len >= 0); 02406 _dbus_assert (a_start <= real_a->len); 02407 _dbus_assert (a_len <= real_a->len - a_start); 02408 _dbus_assert (b_start >= 0); 02409 _dbus_assert (b_start <= real_b->len); 02410 02411 if (a_len > real_b->len - b_start) 02412 return FALSE; 02413 02414 ap = real_a->str + a_start; 02415 bp = real_b->str + b_start; 02416 a_end = ap + a_len; 02417 while (ap != a_end) 02418 { 02419 if (*ap != *bp) 02420 return FALSE; 02421 02422 ++ap; 02423 ++bp; 02424 } 02425 02426 _dbus_assert (bp <= (real_b->str + real_b->len)); 02427 02428 return TRUE; 02429 } 02430 02438 dbus_bool_t 02439 _dbus_string_equal_c_str (const DBusString *a, 02440 const char *c_str) 02441 { 02442 const unsigned char *ap; 02443 const unsigned char *bp; 02444 const unsigned char *a_end; 02445 const DBusRealString *real_a = (const DBusRealString*) a; 02446 DBUS_GENERIC_STRING_PREAMBLE (real_a); 02447 _dbus_assert (c_str != NULL); 02448 02449 ap = real_a->str; 02450 bp = (const unsigned char*) c_str; 02451 a_end = real_a->str + real_a->len; 02452 while (ap != a_end && *bp) 02453 { 02454 if (*ap != *bp) 02455 return FALSE; 02456 02457 ++ap; 02458 ++bp; 02459 } 02460 02461 if (ap != a_end || *bp) 02462 return FALSE; 02463 02464 return TRUE; 02465 } 02466 02467 #ifdef DBUS_BUILD_TESTS 02468 02475 dbus_bool_t 02476 _dbus_string_starts_with_c_str (const DBusString *a, 02477 const char *c_str) 02478 { 02479 const unsigned char *ap; 02480 const unsigned char *bp; 02481 const unsigned char *a_end; 02482 const DBusRealString *real_a = (const DBusRealString*) a; 02483 DBUS_GENERIC_STRING_PREAMBLE (real_a); 02484 _dbus_assert (c_str != NULL); 02485 02486 ap = real_a->str; 02487 bp = (const unsigned char*) c_str; 02488 a_end = real_a->str + real_a->len; 02489 while (ap != a_end && *bp) 02490 { 02491 if (*ap != *bp) 02492 return FALSE; 02493 02494 ++ap; 02495 ++bp; 02496 } 02497 02498 if (*bp == '\0') 02499 return TRUE; 02500 else 02501 return FALSE; 02502 } 02503 #endif /* DBUS_BUILD_TESTS */ 02504 02513 dbus_bool_t 02514 _dbus_string_append_byte_as_hex (DBusString *str, 02515 int byte) 02516 { 02517 const char hexdigits[16] = { 02518 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 02519 'a', 'b', 'c', 'd', 'e', 'f' 02520 }; 02521 02522 if (!_dbus_string_append_byte (str, 02523 hexdigits[(byte >> 4)])) 02524 return FALSE; 02525 02526 if (!_dbus_string_append_byte (str, 02527 hexdigits[(byte & 0x0f)])) 02528 { 02529 _dbus_string_set_length (str, 02530 _dbus_string_get_length (str) - 1); 02531 return FALSE; 02532 } 02533 02534 return TRUE; 02535 } 02536 02547 dbus_bool_t 02548 _dbus_string_hex_encode (const DBusString *source, 02549 int start, 02550 DBusString *dest, 02551 int insert_at) 02552 { 02553 DBusString result; 02554 const unsigned char *p; 02555 const unsigned char *end; 02556 dbus_bool_t retval; 02557 02558 _dbus_assert (start <= _dbus_string_get_length (source)); 02559 02560 if (!_dbus_string_init (&result)) 02561 return FALSE; 02562 02563 retval = FALSE; 02564 02565 p = (const unsigned char*) _dbus_string_get_const_data (source); 02566 end = p + _dbus_string_get_length (source); 02567 p += start; 02568 02569 while (p != end) 02570 { 02571 if (!_dbus_string_append_byte_as_hex (&result, *p)) 02572 goto out; 02573 02574 ++p; 02575 } 02576 02577 if (!_dbus_string_move (&result, 0, dest, insert_at)) 02578 goto out; 02579 02580 retval = TRUE; 02581 02582 out: 02583 _dbus_string_free (&result); 02584 return retval; 02585 } 02586 02597 dbus_bool_t 02598 _dbus_string_hex_decode (const DBusString *source, 02599 int start, 02600 int *end_return, 02601 DBusString *dest, 02602 int insert_at) 02603 { 02604 DBusString result; 02605 const unsigned char *p; 02606 const unsigned char *end; 02607 dbus_bool_t retval; 02608 dbus_bool_t high_bits; 02609 02610 _dbus_assert (start <= _dbus_string_get_length (source)); 02611 02612 if (!_dbus_string_init (&result)) 02613 return FALSE; 02614 02615 retval = FALSE; 02616 02617 high_bits = TRUE; 02618 p = (const unsigned char*) _dbus_string_get_const_data (source); 02619 end = p + _dbus_string_get_length (source); 02620 p += start; 02621 02622 while (p != end) 02623 { 02624 unsigned int val; 02625 02626 switch (*p) 02627 { 02628 case '0': 02629 val = 0; 02630 break; 02631 case '1': 02632 val = 1; 02633 break; 02634 case '2': 02635 val = 2; 02636 break; 02637 case '3': 02638 val = 3; 02639 break; 02640 case '4': 02641 val = 4; 02642 break; 02643 case '5': 02644 val = 5; 02645 break; 02646 case '6': 02647 val = 6; 02648 break; 02649 case '7': 02650 val = 7; 02651 break; 02652 case '8': 02653 val = 8; 02654 break; 02655 case '9': 02656 val = 9; 02657 break; 02658 case 'a': 02659 case 'A': 02660 val = 10; 02661 break; 02662 case 'b': 02663 case 'B': 02664 val = 11; 02665 break; 02666 case 'c': 02667 case 'C': 02668 val = 12; 02669 break; 02670 case 'd': 02671 case 'D': 02672 val = 13; 02673 break; 02674 case 'e': 02675 case 'E': 02676 val = 14; 02677 break; 02678 case 'f': 02679 case 'F': 02680 val = 15; 02681 break; 02682 default: 02683 goto done; 02684 } 02685 02686 if (high_bits) 02687 { 02688 if (!_dbus_string_append_byte (&result, 02689 val << 4)) 02690 goto out; 02691 } 02692 else 02693 { 02694 int len; 02695 unsigned char b; 02696 02697 len = _dbus_string_get_length (&result); 02698 02699 b = _dbus_string_get_byte (&result, len - 1); 02700 02701 b |= val; 02702 02703 _dbus_string_set_byte (&result, len - 1, b); 02704 } 02705 02706 high_bits = !high_bits; 02707 02708 ++p; 02709 } 02710 02711 done: 02712 if (!_dbus_string_move (&result, 0, dest, insert_at)) 02713 goto out; 02714 02715 if (end_return) 02716 *end_return = p - (const unsigned char*) _dbus_string_get_const_data (source); 02717 02718 retval = TRUE; 02719 02720 out: 02721 _dbus_string_free (&result); 02722 return retval; 02723 } 02724 02738 dbus_bool_t 02739 _dbus_string_validate_ascii (const DBusString *str, 02740 int start, 02741 int len) 02742 { 02743 const unsigned char *s; 02744 const unsigned char *end; 02745 DBUS_CONST_STRING_PREAMBLE (str); 02746 _dbus_assert (start >= 0); 02747 _dbus_assert (start <= real->len); 02748 _dbus_assert (len >= 0); 02749 02750 if (len > real->len - start) 02751 return FALSE; 02752 02753 s = real->str + start; 02754 end = s + len; 02755 while (s != end) 02756 { 02757 if (_DBUS_UNLIKELY (!_DBUS_ISASCII (*s))) 02758 return FALSE; 02759 02760 ++s; 02761 } 02762 02763 return TRUE; 02764 } 02765 02773 void 02774 _dbus_string_tolower_ascii (const DBusString *str, 02775 int start, 02776 int len) 02777 { 02778 unsigned char *s; 02779 unsigned char *end; 02780 DBUS_STRING_PREAMBLE (str); 02781 _dbus_assert (start >= 0); 02782 _dbus_assert (start <= real->len); 02783 _dbus_assert (len >= 0); 02784 _dbus_assert (len <= real->len - start); 02785 02786 s = real->str + start; 02787 end = s + len; 02788 02789 while (s != end) 02790 { 02791 if (*s >= 'A' && *s <= 'Z') 02792 *s += 'a' - 'A'; 02793 ++s; 02794 } 02795 } 02796 02804 void 02805 _dbus_string_toupper_ascii (const DBusString *str, 02806 int start, 02807 int len) 02808 { 02809 unsigned char *s; 02810 unsigned char *end; 02811 DBUS_STRING_PREAMBLE (str); 02812 _dbus_assert (start >= 0); 02813 _dbus_assert (start <= real->len); 02814 _dbus_assert (len >= 0); 02815 _dbus_assert (len <= real->len - start); 02816 02817 s = real->str + start; 02818 end = s + len; 02819 02820 while (s != end) 02821 { 02822 if (*s >= 'a' && *s <= 'z') 02823 *s += 'A' - 'a'; 02824 ++s; 02825 } 02826 } 02827 02843 dbus_bool_t 02844 _dbus_string_validate_utf8 (const DBusString *str, 02845 int start, 02846 int len) 02847 { 02848 const unsigned char *p; 02849 const unsigned char *end; 02850 DBUS_CONST_STRING_PREAMBLE (str); 02851 _dbus_assert (start >= 0); 02852 _dbus_assert (start <= real->len); 02853 _dbus_assert (len >= 0); 02854 02855 /* we are doing _DBUS_UNLIKELY() here which might be 02856 * dubious in a generic library like GLib, but in D-Bus 02857 * we know we're validating messages and that it would 02858 * only be evil/broken apps that would have invalid 02859 * UTF-8. Also, this function seems to be a performance 02860 * bottleneck in profiles. 02861 */ 02862 02863 if (_DBUS_UNLIKELY (len > real->len - start)) 02864 return FALSE; 02865 02866 p = real->str + start; 02867 end = p + len; 02868 02869 while (p < end) 02870 { 02871 int i, mask, char_len; 02872 dbus_unichar_t result; 02873 02874 /* nul bytes considered invalid */ 02875 if (*p == '\0') 02876 break; 02877 02878 /* Special-case ASCII; this makes us go a lot faster in 02879 * D-Bus profiles where we are typically validating 02880 * function names and such. We have to know that 02881 * all following checks will pass for ASCII though, 02882 * comments follow ... 02883 */ 02884 if (*p < 128) 02885 { 02886 ++p; 02887 continue; 02888 } 02889 02890 UTF8_COMPUTE (*p, mask, char_len); 02891 02892 if (_DBUS_UNLIKELY (char_len == 0)) /* ASCII: char_len == 1 */ 02893 break; 02894 02895 /* check that the expected number of bytes exists in the remaining length */ 02896 if (_DBUS_UNLIKELY ((end - p) < char_len)) /* ASCII: p < end and char_len == 1 */ 02897 break; 02898 02899 UTF8_GET (result, p, i, mask, char_len); 02900 02901 /* Check for overlong UTF-8 */ 02902 if (_DBUS_UNLIKELY (UTF8_LENGTH (result) != char_len)) /* ASCII: UTF8_LENGTH == 1 */ 02903 break; 02904 #if 0 02905 /* The UNICODE_VALID check below will catch this */ 02906 if (_DBUS_UNLIKELY (result == (dbus_unichar_t)-1)) /* ASCII: result = ascii value */ 02907 break; 02908 #endif 02909 02910 if (_DBUS_UNLIKELY (!UNICODE_VALID (result))) /* ASCII: always valid */ 02911 break; 02912 02913 /* UNICODE_VALID should have caught it */ 02914 _dbus_assert (result != (dbus_unichar_t)-1); 02915 02916 p += char_len; 02917 } 02918 02919 /* See that we covered the entire length if a length was 02920 * passed in 02921 */ 02922 if (_DBUS_UNLIKELY (p != end)) 02923 return FALSE; 02924 else 02925 return TRUE; 02926 } 02927 02941 dbus_bool_t 02942 _dbus_string_validate_nul (const DBusString *str, 02943 int start, 02944 int len) 02945 { 02946 const unsigned char *s; 02947 const unsigned char *end; 02948 DBUS_CONST_STRING_PREAMBLE (str); 02949 _dbus_assert (start >= 0); 02950 _dbus_assert (len >= 0); 02951 _dbus_assert (start <= real->len); 02952 02953 if (len > real->len - start) 02954 return FALSE; 02955 02956 s = real->str + start; 02957 end = s + len; 02958 while (s != end) 02959 { 02960 if (_DBUS_UNLIKELY (*s != '\0')) 02961 return FALSE; 02962 ++s; 02963 } 02964 02965 return TRUE; 02966 } 02967 02973 void 02974 _dbus_string_zero (DBusString *str) 02975 { 02976 DBUS_STRING_PREAMBLE (str); 02977 02978 memset (real->str - real->align_offset, '\0', real->allocated); 02979 } 02982 /* tests are in dbus-string-util.c */