|
D-Bus
1.5.8
|
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->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 00189 void 00190 _dbus_string_init_const (DBusString *str, 00191 const char *value) 00192 { 00193 _dbus_assert (value != NULL); 00194 00195 _dbus_string_init_const_len (str, value, 00196 strlen (value)); 00197 } 00198 00209 void 00210 _dbus_string_init_const_len (DBusString *str, 00211 const char *value, 00212 int len) 00213 { 00214 DBusRealString *real; 00215 00216 _dbus_assert (str != NULL); 00217 _dbus_assert (len == 0 || value != NULL); 00218 _dbus_assert (len <= _DBUS_STRING_MAX_LENGTH); 00219 _dbus_assert (len >= 0); 00220 00221 real = (DBusRealString*) str; 00222 00223 real->str = (unsigned char*) value; 00224 real->len = len; 00225 real->allocated = real->len + _DBUS_STRING_ALLOCATION_PADDING; /* a lie, just to avoid special-case assertions... */ 00226 real->constant = TRUE; 00227 real->locked = TRUE; 00228 real->invalid = FALSE; 00229 real->align_offset = 0; 00230 00231 /* We don't require const strings to be 8-byte aligned as the 00232 * memory is coming from elsewhere. 00233 */ 00234 } 00235 00241 void 00242 _dbus_string_free (DBusString *str) 00243 { 00244 DBusRealString *real = (DBusRealString*) str; 00245 DBUS_GENERIC_STRING_PREAMBLE (real); 00246 00247 if (real->constant) 00248 return; 00249 dbus_free (real->str - real->align_offset); 00250 00251 real->invalid = TRUE; 00252 } 00253 00254 static dbus_bool_t 00255 compact (DBusRealString *real, 00256 int max_waste) 00257 { 00258 unsigned char *new_str; 00259 int new_allocated; 00260 int waste; 00261 00262 waste = real->allocated - (real->len + _DBUS_STRING_ALLOCATION_PADDING); 00263 00264 if (waste <= max_waste) 00265 return TRUE; 00266 00267 new_allocated = real->len + _DBUS_STRING_ALLOCATION_PADDING; 00268 00269 new_str = dbus_realloc (real->str - real->align_offset, new_allocated); 00270 if (_DBUS_UNLIKELY (new_str == NULL)) 00271 return FALSE; 00272 00273 real->str = new_str + real->align_offset; 00274 real->allocated = new_allocated; 00275 fixup_alignment (real); 00276 00277 return TRUE; 00278 } 00279 00280 #ifdef DBUS_BUILD_TESTS 00281 /* Not using this feature at the moment, 00282 * so marked DBUS_BUILD_TESTS-only 00283 */ 00293 void 00294 _dbus_string_lock (DBusString *str) 00295 { 00296 DBUS_LOCKED_STRING_PREAMBLE (str); /* can lock multiple times */ 00297 00298 real->locked = TRUE; 00299 00300 /* Try to realloc to avoid excess memory usage, since 00301 * we know we won't change the string further 00302 */ 00303 #define MAX_WASTE 48 00304 compact (real, MAX_WASTE); 00305 } 00306 #endif /* DBUS_BUILD_TESTS */ 00307 00308 static dbus_bool_t 00309 reallocate_for_length (DBusRealString *real, 00310 int new_length) 00311 { 00312 int new_allocated; 00313 unsigned char *new_str; 00314 00315 /* at least double our old allocation to avoid O(n), avoiding 00316 * overflow 00317 */ 00318 if (real->allocated > (_DBUS_STRING_MAX_LENGTH + _DBUS_STRING_ALLOCATION_PADDING) / 2) 00319 new_allocated = _DBUS_STRING_MAX_LENGTH + _DBUS_STRING_ALLOCATION_PADDING; 00320 else 00321 new_allocated = real->allocated * 2; 00322 00323 /* if you change the code just above here, run the tests without 00324 * the following assert-only hack before you commit 00325 */ 00326 /* This is keyed off asserts in addition to tests so when you 00327 * disable asserts to profile, you don't get this destroyer 00328 * of profiles. 00329 */ 00330 #ifdef DBUS_DISABLE_ASSERT 00331 #else 00332 #ifdef DBUS_BUILD_TESTS 00333 new_allocated = 0; /* ensure a realloc every time so that we go 00334 * through all malloc failure codepaths 00335 */ 00336 #endif /* DBUS_BUILD_TESTS */ 00337 #endif /* !DBUS_DISABLE_ASSERT */ 00338 00339 /* But be sure we always alloc at least space for the new length */ 00340 new_allocated = MAX (new_allocated, 00341 new_length + _DBUS_STRING_ALLOCATION_PADDING); 00342 00343 _dbus_assert (new_allocated >= real->allocated); /* code relies on this */ 00344 new_str = dbus_realloc (real->str - real->align_offset, new_allocated); 00345 if (_DBUS_UNLIKELY (new_str == NULL)) 00346 return FALSE; 00347 00348 real->str = new_str + real->align_offset; 00349 real->allocated = new_allocated; 00350 fixup_alignment (real); 00351 00352 return TRUE; 00353 } 00354 00366 dbus_bool_t 00367 _dbus_string_compact (DBusString *str, 00368 int max_waste) 00369 { 00370 DBUS_STRING_PREAMBLE (str); 00371 00372 return compact (real, max_waste); 00373 } 00374 00375 static dbus_bool_t 00376 set_length (DBusRealString *real, 00377 int new_length) 00378 { 00379 /* Note, we are setting the length not including nul termination */ 00380 00381 /* exceeding max length is the same as failure to allocate memory */ 00382 if (_DBUS_UNLIKELY (new_length > _DBUS_STRING_MAX_LENGTH)) 00383 return FALSE; 00384 else if (new_length > (real->allocated - _DBUS_STRING_ALLOCATION_PADDING) && 00385 _DBUS_UNLIKELY (!reallocate_for_length (real, new_length))) 00386 return FALSE; 00387 else 00388 { 00389 real->len = new_length; 00390 real->str[new_length] = '\0'; 00391 return TRUE; 00392 } 00393 } 00394 00395 static dbus_bool_t 00396 open_gap (int len, 00397 DBusRealString *dest, 00398 int insert_at) 00399 { 00400 if (len == 0) 00401 return TRUE; 00402 00403 if (len > _DBUS_STRING_MAX_LENGTH - dest->len) 00404 return FALSE; /* detected overflow of dest->len + len below */ 00405 00406 if (!set_length (dest, dest->len + len)) 00407 return FALSE; 00408 00409 memmove (dest->str + insert_at + len, 00410 dest->str + insert_at, 00411 dest->len - len - insert_at); 00412 00413 return TRUE; 00414 } 00415 00416 #ifndef _dbus_string_get_data 00417 00428 char* 00429 _dbus_string_get_data (DBusString *str) 00430 { 00431 DBUS_STRING_PREAMBLE (str); 00432 00433 return (char*) real->str; 00434 } 00435 #endif /* _dbus_string_get_data */ 00436 00437 /* only do the function if we don't have the macro */ 00438 #ifndef _dbus_string_get_const_data 00439 00445 const char* 00446 _dbus_string_get_const_data (const DBusString *str) 00447 { 00448 DBUS_CONST_STRING_PREAMBLE (str); 00449 00450 return (const char*) real->str; 00451 } 00452 #endif /* _dbus_string_get_const_data */ 00453 00467 char* 00468 _dbus_string_get_data_len (DBusString *str, 00469 int start, 00470 int len) 00471 { 00472 DBUS_STRING_PREAMBLE (str); 00473 _dbus_assert (start >= 0); 00474 _dbus_assert (len >= 0); 00475 _dbus_assert (start <= real->len); 00476 _dbus_assert (len <= real->len - start); 00477 00478 return (char*) real->str + start; 00479 } 00480 00481 /* only do the function if we don't have the macro */ 00482 #ifndef _dbus_string_get_const_data_len 00483 00491 const char* 00492 _dbus_string_get_const_data_len (const DBusString *str, 00493 int start, 00494 int len) 00495 { 00496 DBUS_CONST_STRING_PREAMBLE (str); 00497 _dbus_assert (start >= 0); 00498 _dbus_assert (len >= 0); 00499 _dbus_assert (start <= real->len); 00500 _dbus_assert (len <= real->len - start); 00501 00502 return (const char*) real->str + start; 00503 } 00504 #endif /* _dbus_string_get_const_data_len */ 00505 00506 /* only do the function if we don't have the macro */ 00507 #ifndef _dbus_string_set_byte 00508 00515 void 00516 _dbus_string_set_byte (DBusString *str, 00517 int i, 00518 unsigned char byte) 00519 { 00520 DBUS_STRING_PREAMBLE (str); 00521 _dbus_assert (i < real->len); 00522 _dbus_assert (i >= 0); 00523 00524 real->str[i] = byte; 00525 } 00526 #endif /* _dbus_string_set_byte */ 00527 00528 /* only have the function if we didn't create a macro */ 00529 #ifndef _dbus_string_get_byte 00530 00539 unsigned char 00540 _dbus_string_get_byte (const DBusString *str, 00541 int start) 00542 { 00543 DBUS_CONST_STRING_PREAMBLE (str); 00544 _dbus_assert (start <= real->len); 00545 _dbus_assert (start >= 0); 00546 00547 return real->str[start]; 00548 } 00549 #endif /* _dbus_string_get_byte */ 00550 00561 dbus_bool_t 00562 _dbus_string_insert_bytes (DBusString *str, 00563 int i, 00564 int n_bytes, 00565 unsigned char byte) 00566 { 00567 DBUS_STRING_PREAMBLE (str); 00568 _dbus_assert (i <= real->len); 00569 _dbus_assert (i >= 0); 00570 _dbus_assert (n_bytes >= 0); 00571 00572 if (n_bytes == 0) 00573 return TRUE; 00574 00575 if (!open_gap (n_bytes, real, i)) 00576 return FALSE; 00577 00578 memset (real->str + i, byte, n_bytes); 00579 00580 return TRUE; 00581 } 00582 00591 dbus_bool_t 00592 _dbus_string_insert_byte (DBusString *str, 00593 int i, 00594 unsigned char byte) 00595 { 00596 DBUS_STRING_PREAMBLE (str); 00597 _dbus_assert (i <= real->len); 00598 _dbus_assert (i >= 0); 00599 00600 if (!open_gap (1, real, i)) 00601 return FALSE; 00602 00603 real->str[i] = byte; 00604 00605 return TRUE; 00606 } 00607 00618 dbus_bool_t 00619 _dbus_string_steal_data (DBusString *str, 00620 char **data_return) 00621 { 00622 DBUS_STRING_PREAMBLE (str); 00623 _dbus_assert (data_return != NULL); 00624 00625 undo_alignment (real); 00626 00627 *data_return = (char*) real->str; 00628 00629 /* reset the string */ 00630 if (!_dbus_string_init (str)) 00631 { 00632 /* hrm, put it back then */ 00633 real->str = (unsigned char*) *data_return; 00634 *data_return = NULL; 00635 fixup_alignment (real); 00636 return FALSE; 00637 } 00638 00639 return TRUE; 00640 } 00641 00649 dbus_bool_t 00650 _dbus_string_copy_data (const DBusString *str, 00651 char **data_return) 00652 { 00653 DBUS_CONST_STRING_PREAMBLE (str); 00654 _dbus_assert (data_return != NULL); 00655 00656 *data_return = dbus_malloc (real->len + 1); 00657 if (*data_return == NULL) 00658 return FALSE; 00659 00660 memcpy (*data_return, real->str, real->len + 1); 00661 00662 return TRUE; 00663 } 00664 00674 void 00675 _dbus_string_copy_to_buffer (const DBusString *str, 00676 char *buffer, 00677 int avail_len) 00678 { 00679 DBUS_CONST_STRING_PREAMBLE (str); 00680 00681 _dbus_assert (avail_len >= 0); 00682 _dbus_assert (avail_len >= real->len); 00683 00684 memcpy (buffer, real->str, real->len); 00685 } 00686 00696 void 00697 _dbus_string_copy_to_buffer_with_nul (const DBusString *str, 00698 char *buffer, 00699 int avail_len) 00700 { 00701 DBUS_CONST_STRING_PREAMBLE (str); 00702 00703 _dbus_assert (avail_len >= 0); 00704 _dbus_assert (avail_len > real->len); 00705 00706 memcpy (buffer, real->str, real->len+1); 00707 } 00708 00709 /* Only have the function if we don't have the macro */ 00710 #ifndef _dbus_string_get_length 00711 00716 int 00717 _dbus_string_get_length (const DBusString *str) 00718 { 00719 DBUS_CONST_STRING_PREAMBLE (str); 00720 00721 return real->len; 00722 } 00723 #endif /* !_dbus_string_get_length */ 00724 00737 dbus_bool_t 00738 _dbus_string_lengthen (DBusString *str, 00739 int additional_length) 00740 { 00741 DBUS_STRING_PREAMBLE (str); 00742 _dbus_assert (additional_length >= 0); 00743 00744 if (_DBUS_UNLIKELY (additional_length > _DBUS_STRING_MAX_LENGTH - real->len)) 00745 return FALSE; /* would overflow */ 00746 00747 return set_length (real, 00748 real->len + additional_length); 00749 } 00750 00757 void 00758 _dbus_string_shorten (DBusString *str, 00759 int length_to_remove) 00760 { 00761 DBUS_STRING_PREAMBLE (str); 00762 _dbus_assert (length_to_remove >= 0); 00763 _dbus_assert (length_to_remove <= real->len); 00764 00765 set_length (real, 00766 real->len - length_to_remove); 00767 } 00768 00779 dbus_bool_t 00780 _dbus_string_set_length (DBusString *str, 00781 int length) 00782 { 00783 DBUS_STRING_PREAMBLE (str); 00784 _dbus_assert (length >= 0); 00785 00786 return set_length (real, length); 00787 } 00788 00789 static dbus_bool_t 00790 align_insert_point_then_open_gap (DBusString *str, 00791 int *insert_at_p, 00792 int alignment, 00793 int gap_size) 00794 { 00795 unsigned long new_len; /* ulong to avoid _DBUS_ALIGN_VALUE overflow */ 00796 unsigned long gap_pos; 00797 int insert_at; 00798 int delta; 00799 DBUS_STRING_PREAMBLE (str); 00800 _dbus_assert (alignment >= 1); 00801 _dbus_assert (alignment <= 8); /* it has to be a bug if > 8 */ 00802 00803 insert_at = *insert_at_p; 00804 00805 _dbus_assert (insert_at <= real->len); 00806 00807 gap_pos = _DBUS_ALIGN_VALUE (insert_at, alignment); 00808 new_len = real->len + (gap_pos - insert_at) + gap_size; 00809 00810 if (_DBUS_UNLIKELY (new_len > (unsigned long) _DBUS_STRING_MAX_LENGTH)) 00811 return FALSE; 00812 00813 delta = new_len - real->len; 00814 _dbus_assert (delta >= 0); 00815 00816 if (delta == 0) /* only happens if gap_size == 0 and insert_at is aligned already */ 00817 { 00818 _dbus_assert (((unsigned long) *insert_at_p) == gap_pos); 00819 return TRUE; 00820 } 00821 00822 if (_DBUS_UNLIKELY (!open_gap (new_len - real->len, 00823 real, insert_at))) 00824 return FALSE; 00825 00826 /* nul the padding if we had to add any padding */ 00827 if (gap_size < delta) 00828 { 00829 memset (&real->str[insert_at], '\0', 00830 gap_pos - insert_at); 00831 } 00832 00833 *insert_at_p = gap_pos; 00834 00835 return TRUE; 00836 } 00837 00838 static dbus_bool_t 00839 align_length_then_lengthen (DBusString *str, 00840 int alignment, 00841 int then_lengthen_by) 00842 { 00843 int insert_at; 00844 00845 insert_at = _dbus_string_get_length (str); 00846 00847 return align_insert_point_then_open_gap (str, 00848 &insert_at, 00849 alignment, then_lengthen_by); 00850 } 00851 00860 dbus_bool_t 00861 _dbus_string_align_length (DBusString *str, 00862 int alignment) 00863 { 00864 return align_length_then_lengthen (str, alignment, 0); 00865 } 00866 00876 dbus_bool_t 00877 _dbus_string_alloc_space (DBusString *str, 00878 int extra_bytes) 00879 { 00880 if (!_dbus_string_lengthen (str, extra_bytes)) 00881 return FALSE; 00882 _dbus_string_shorten (str, extra_bytes); 00883 00884 return TRUE; 00885 } 00886 00887 static dbus_bool_t 00888 append (DBusRealString *real, 00889 const char *buffer, 00890 int buffer_len) 00891 { 00892 if (buffer_len == 0) 00893 return TRUE; 00894 00895 if (!_dbus_string_lengthen ((DBusString*)real, buffer_len)) 00896 return FALSE; 00897 00898 memcpy (real->str + (real->len - buffer_len), 00899 buffer, 00900 buffer_len); 00901 00902 return TRUE; 00903 } 00904 00912 dbus_bool_t 00913 _dbus_string_append (DBusString *str, 00914 const char *buffer) 00915 { 00916 unsigned long buffer_len; 00917 00918 DBUS_STRING_PREAMBLE (str); 00919 _dbus_assert (buffer != NULL); 00920 00921 buffer_len = strlen (buffer); 00922 if (buffer_len > (unsigned long) _DBUS_STRING_MAX_LENGTH) 00923 return FALSE; 00924 00925 return append (real, buffer, buffer_len); 00926 } 00927 00929 #define ASSIGN_2_OCTETS(p, octets) \ 00930 *((dbus_uint16_t*)(p)) = *((dbus_uint16_t*)(octets)); 00931 00933 #define ASSIGN_4_OCTETS(p, octets) \ 00934 *((dbus_uint32_t*)(p)) = *((dbus_uint32_t*)(octets)); 00935 00936 #ifdef DBUS_HAVE_INT64 00937 00938 #define ASSIGN_8_OCTETS(p, octets) \ 00939 *((dbus_uint64_t*)(p)) = *((dbus_uint64_t*)(octets)); 00940 #else 00941 00942 #define ASSIGN_8_OCTETS(p, octets) \ 00943 do { \ 00944 unsigned char *b; \ 00945 \ 00946 b = p; \ 00947 \ 00948 *b++ = octets[0]; \ 00949 *b++ = octets[1]; \ 00950 *b++ = octets[2]; \ 00951 *b++ = octets[3]; \ 00952 *b++ = octets[4]; \ 00953 *b++ = octets[5]; \ 00954 *b++ = octets[6]; \ 00955 *b++ = octets[7]; \ 00956 _dbus_assert (b == p + 8); \ 00957 } while (0) 00958 #endif /* DBUS_HAVE_INT64 */ 00959 00960 #ifdef DBUS_BUILD_TESTS 00961 00969 dbus_bool_t 00970 _dbus_string_append_4_aligned (DBusString *str, 00971 const unsigned char octets[4]) 00972 { 00973 DBUS_STRING_PREAMBLE (str); 00974 00975 if (!align_length_then_lengthen (str, 4, 4)) 00976 return FALSE; 00977 00978 ASSIGN_4_OCTETS (real->str + (real->len - 4), octets); 00979 00980 return TRUE; 00981 } 00982 #endif /* DBUS_BUILD_TESTS */ 00983 00984 #ifdef DBUS_BUILD_TESTS 00985 00993 dbus_bool_t 00994 _dbus_string_append_8_aligned (DBusString *str, 00995 const unsigned char octets[8]) 00996 { 00997 DBUS_STRING_PREAMBLE (str); 00998 00999 if (!align_length_then_lengthen (str, 8, 8)) 01000 return FALSE; 01001 01002 ASSIGN_8_OCTETS (real->str + (real->len - 8), octets); 01003 01004 return TRUE; 01005 } 01006 #endif /* DBUS_BUILD_TESTS */ 01007 01017 dbus_bool_t 01018 _dbus_string_insert_2_aligned (DBusString *str, 01019 int insert_at, 01020 const unsigned char octets[4]) 01021 { 01022 DBUS_STRING_PREAMBLE (str); 01023 01024 if (!align_insert_point_then_open_gap (str, &insert_at, 2, 2)) 01025 return FALSE; 01026 01027 ASSIGN_2_OCTETS (real->str + insert_at, octets); 01028 01029 return TRUE; 01030 } 01031 01041 dbus_bool_t 01042 _dbus_string_insert_4_aligned (DBusString *str, 01043 int insert_at, 01044 const unsigned char octets[4]) 01045 { 01046 DBUS_STRING_PREAMBLE (str); 01047 01048 if (!align_insert_point_then_open_gap (str, &insert_at, 4, 4)) 01049 return FALSE; 01050 01051 ASSIGN_4_OCTETS (real->str + insert_at, octets); 01052 01053 return TRUE; 01054 } 01055 01065 dbus_bool_t 01066 _dbus_string_insert_8_aligned (DBusString *str, 01067 int insert_at, 01068 const unsigned char octets[8]) 01069 { 01070 DBUS_STRING_PREAMBLE (str); 01071 01072 if (!align_insert_point_then_open_gap (str, &insert_at, 8, 8)) 01073 return FALSE; 01074 01075 _dbus_assert (_DBUS_ALIGN_VALUE (insert_at, 8) == (unsigned) insert_at); 01076 01077 ASSIGN_8_OCTETS (real->str + insert_at, octets); 01078 01079 return TRUE; 01080 } 01081 01082 01093 dbus_bool_t 01094 _dbus_string_insert_alignment (DBusString *str, 01095 int *insert_at, 01096 int alignment) 01097 { 01098 DBUS_STRING_PREAMBLE (str); 01099 01100 if (!align_insert_point_then_open_gap (str, insert_at, alignment, 0)) 01101 return FALSE; 01102 01103 _dbus_assert (_DBUS_ALIGN_VALUE (*insert_at, alignment) == (unsigned) *insert_at); 01104 01105 return TRUE; 01106 } 01107 01117 dbus_bool_t 01118 _dbus_string_append_printf_valist (DBusString *str, 01119 const char *format, 01120 va_list args) 01121 { 01122 int len; 01123 va_list args_copy; 01124 01125 DBUS_STRING_PREAMBLE (str); 01126 01127 DBUS_VA_COPY (args_copy, args); 01128 01129 /* Measure the message length without terminating nul */ 01130 len = _dbus_printf_string_upper_bound (format, args); 01131 01132 if (len < 0) 01133 return FALSE; 01134 01135 if (!_dbus_string_lengthen (str, len)) 01136 { 01137 /* don't leak the copy */ 01138 va_end (args_copy); 01139 return FALSE; 01140 } 01141 01142 vsprintf ((char*) (real->str + (real->len - len)), 01143 format, args_copy); 01144 01145 va_end (args_copy); 01146 01147 return TRUE; 01148 } 01149 01158 dbus_bool_t 01159 _dbus_string_append_printf (DBusString *str, 01160 const char *format, 01161 ...) 01162 { 01163 va_list args; 01164 dbus_bool_t retval; 01165 01166 va_start (args, format); 01167 retval = _dbus_string_append_printf_valist (str, format, args); 01168 va_end (args); 01169 01170 return retval; 01171 } 01172 01181 dbus_bool_t 01182 _dbus_string_append_len (DBusString *str, 01183 const char *buffer, 01184 int len) 01185 { 01186 DBUS_STRING_PREAMBLE (str); 01187 _dbus_assert (buffer != NULL); 01188 _dbus_assert (len >= 0); 01189 01190 return append (real, buffer, len); 01191 } 01192 01201 dbus_bool_t 01202 _dbus_string_append_byte (DBusString *str, 01203 unsigned char byte) 01204 { 01205 DBUS_STRING_PREAMBLE (str); 01206 01207 if (!set_length (real, real->len + 1)) 01208 return FALSE; 01209 01210 real->str[real->len-1] = byte; 01211 01212 return TRUE; 01213 } 01214 01215 #ifdef DBUS_BUILD_TESTS 01216 01223 dbus_bool_t 01224 _dbus_string_append_unichar (DBusString *str, 01225 dbus_unichar_t ch) 01226 { 01227 int len; 01228 int first; 01229 int i; 01230 unsigned char *out; 01231 01232 DBUS_STRING_PREAMBLE (str); 01233 01234 /* this code is from GLib but is pretty standard I think */ 01235 01236 len = 0; 01237 01238 if (ch < 0x80) 01239 { 01240 first = 0; 01241 len = 1; 01242 } 01243 else if (ch < 0x800) 01244 { 01245 first = 0xc0; 01246 len = 2; 01247 } 01248 else if (ch < 0x10000) 01249 { 01250 first = 0xe0; 01251 len = 3; 01252 } 01253 else if (ch < 0x200000) 01254 { 01255 first = 0xf0; 01256 len = 4; 01257 } 01258 else if (ch < 0x4000000) 01259 { 01260 first = 0xf8; 01261 len = 5; 01262 } 01263 else 01264 { 01265 first = 0xfc; 01266 len = 6; 01267 } 01268 01269 if (len > (_DBUS_STRING_MAX_LENGTH - real->len)) 01270 return FALSE; /* real->len + len would overflow */ 01271 01272 if (!set_length (real, real->len + len)) 01273 return FALSE; 01274 01275 out = real->str + (real->len - len); 01276 01277 for (i = len - 1; i > 0; --i) 01278 { 01279 out[i] = (ch & 0x3f) | 0x80; 01280 ch >>= 6; 01281 } 01282 out[0] = ch | first; 01283 01284 return TRUE; 01285 } 01286 #endif /* DBUS_BUILD_TESTS */ 01287 01288 static void 01289 delete (DBusRealString *real, 01290 int start, 01291 int len) 01292 { 01293 if (len == 0) 01294 return; 01295 01296 memmove (real->str + start, real->str + start + len, real->len - (start + len)); 01297 real->len -= len; 01298 real->str[real->len] = '\0'; 01299 } 01300 01310 void 01311 _dbus_string_delete (DBusString *str, 01312 int start, 01313 int len) 01314 { 01315 DBUS_STRING_PREAMBLE (str); 01316 _dbus_assert (start >= 0); 01317 _dbus_assert (len >= 0); 01318 _dbus_assert (start <= real->len); 01319 _dbus_assert (len <= real->len - start); 01320 01321 delete (real, start, len); 01322 } 01323 01324 static dbus_bool_t 01325 copy (DBusRealString *source, 01326 int start, 01327 int len, 01328 DBusRealString *dest, 01329 int insert_at) 01330 { 01331 if (len == 0) 01332 return TRUE; 01333 01334 if (!open_gap (len, dest, insert_at)) 01335 return FALSE; 01336 01337 memmove (dest->str + insert_at, 01338 source->str + start, 01339 len); 01340 01341 return TRUE; 01342 } 01343 01353 #define DBUS_STRING_COPY_PREAMBLE(source, start, dest, insert_at) \ 01354 DBusRealString *real_source = (DBusRealString*) source; \ 01355 DBusRealString *real_dest = (DBusRealString*) dest; \ 01356 _dbus_assert ((source) != (dest)); \ 01357 DBUS_GENERIC_STRING_PREAMBLE (real_source); \ 01358 DBUS_GENERIC_STRING_PREAMBLE (real_dest); \ 01359 _dbus_assert (!real_dest->constant); \ 01360 _dbus_assert (!real_dest->locked); \ 01361 _dbus_assert ((start) >= 0); \ 01362 _dbus_assert ((start) <= real_source->len); \ 01363 _dbus_assert ((insert_at) >= 0); \ 01364 _dbus_assert ((insert_at) <= real_dest->len) 01365 01376 dbus_bool_t 01377 _dbus_string_move (DBusString *source, 01378 int start, 01379 DBusString *dest, 01380 int insert_at) 01381 { 01382 DBusRealString *real_source = (DBusRealString*) source; 01383 _dbus_assert (start <= real_source->len); 01384 01385 return _dbus_string_move_len (source, start, 01386 real_source->len - start, 01387 dest, insert_at); 01388 } 01389 01400 dbus_bool_t 01401 _dbus_string_copy (const DBusString *source, 01402 int start, 01403 DBusString *dest, 01404 int insert_at) 01405 { 01406 DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at); 01407 01408 return copy (real_source, start, 01409 real_source->len - start, 01410 real_dest, 01411 insert_at); 01412 } 01413 01425 dbus_bool_t 01426 _dbus_string_move_len (DBusString *source, 01427 int start, 01428 int len, 01429 DBusString *dest, 01430 int insert_at) 01431 01432 { 01433 DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at); 01434 _dbus_assert (len >= 0); 01435 _dbus_assert ((start + len) <= real_source->len); 01436 01437 01438 if (len == 0) 01439 { 01440 return TRUE; 01441 } 01442 else if (start == 0 && 01443 len == real_source->len && 01444 real_dest->len == 0) 01445 { 01446 /* Short-circuit moving an entire existing string to an empty string 01447 * by just swapping the buffers. 01448 */ 01449 /* we assume ->constant doesn't matter as you can't have 01450 * a constant string involved in a move. 01451 */ 01452 #define ASSIGN_DATA(a, b) do { \ 01453 (a)->str = (b)->str; \ 01454 (a)->len = (b)->len; \ 01455 (a)->allocated = (b)->allocated; \ 01456 (a)->align_offset = (b)->align_offset; \ 01457 } while (0) 01458 01459 DBusRealString tmp; 01460 01461 ASSIGN_DATA (&tmp, real_source); 01462 ASSIGN_DATA (real_source, real_dest); 01463 ASSIGN_DATA (real_dest, &tmp); 01464 01465 return TRUE; 01466 } 01467 else 01468 { 01469 if (!copy (real_source, start, len, 01470 real_dest, 01471 insert_at)) 01472 return FALSE; 01473 01474 delete (real_source, start, 01475 len); 01476 01477 return TRUE; 01478 } 01479 } 01480 01492 dbus_bool_t 01493 _dbus_string_copy_len (const DBusString *source, 01494 int start, 01495 int len, 01496 DBusString *dest, 01497 int insert_at) 01498 { 01499 DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at); 01500 _dbus_assert (len >= 0); 01501 _dbus_assert (start <= real_source->len); 01502 _dbus_assert (len <= real_source->len - start); 01503 01504 return copy (real_source, start, len, 01505 real_dest, 01506 insert_at); 01507 } 01508 01521 dbus_bool_t 01522 _dbus_string_replace_len (const DBusString *source, 01523 int start, 01524 int len, 01525 DBusString *dest, 01526 int replace_at, 01527 int replace_len) 01528 { 01529 DBUS_STRING_COPY_PREAMBLE (source, start, dest, replace_at); 01530 _dbus_assert (len >= 0); 01531 _dbus_assert (start <= real_source->len); 01532 _dbus_assert (len <= real_source->len - start); 01533 _dbus_assert (replace_at >= 0); 01534 _dbus_assert (replace_at <= real_dest->len); 01535 _dbus_assert (replace_len <= real_dest->len - replace_at); 01536 01537 if (len == replace_len) 01538 { 01539 memmove (real_dest->str + replace_at, 01540 real_source->str + start, len); 01541 } 01542 else if (len < replace_len) 01543 { 01544 memmove (real_dest->str + replace_at, 01545 real_source->str + start, len); 01546 delete (real_dest, replace_at + len, 01547 replace_len - len); 01548 } 01549 else 01550 { 01551 int diff; 01552 01553 _dbus_assert (len > replace_len); 01554 01555 diff = len - replace_len; 01556 01557 /* First of all we check if destination string can be enlarged as 01558 * required, then we overwrite previous bytes 01559 */ 01560 01561 if (!copy (real_source, start + replace_len, diff, 01562 real_dest, replace_at + replace_len)) 01563 return FALSE; 01564 01565 memmove (real_dest->str + replace_at, 01566 real_source->str + start, replace_len); 01567 } 01568 01569 return TRUE; 01570 } 01571 01584 dbus_bool_t 01585 _dbus_string_split_on_byte (DBusString *source, 01586 unsigned char byte, 01587 DBusString *tail) 01588 { 01589 int byte_position; 01590 char byte_string[2] = ""; 01591 int head_length; 01592 int tail_length; 01593 01594 byte_string[0] = (char) byte; 01595 01596 if (!_dbus_string_find (source, 0, byte_string, &byte_position)) 01597 return FALSE; 01598 01599 head_length = byte_position; 01600 tail_length = _dbus_string_get_length (source) - head_length - 1; 01601 01602 if (!_dbus_string_move_len (source, byte_position + 1, tail_length, 01603 tail, 0)) 01604 return FALSE; 01605 01606 /* remove the trailing delimiter byte from the head now. 01607 */ 01608 if (!_dbus_string_set_length (source, head_length)) 01609 return FALSE; 01610 01611 return TRUE; 01612 } 01613 01614 /* Unicode macros and utf8_validate() from GLib Owen Taylor, Havoc 01615 * Pennington, and Tom Tromey are the authors and authorized relicense. 01616 */ 01617 01623 #define UTF8_COMPUTE(Char, Mask, Len) \ 01624 if (Char < 128) \ 01625 { \ 01626 Len = 1; \ 01627 Mask = 0x7f; \ 01628 } \ 01629 else if ((Char & 0xe0) == 0xc0) \ 01630 { \ 01631 Len = 2; \ 01632 Mask = 0x1f; \ 01633 } \ 01634 else if ((Char & 0xf0) == 0xe0) \ 01635 { \ 01636 Len = 3; \ 01637 Mask = 0x0f; \ 01638 } \ 01639 else if ((Char & 0xf8) == 0xf0) \ 01640 { \ 01641 Len = 4; \ 01642 Mask = 0x07; \ 01643 } \ 01644 else if ((Char & 0xfc) == 0xf8) \ 01645 { \ 01646 Len = 5; \ 01647 Mask = 0x03; \ 01648 } \ 01649 else if ((Char & 0xfe) == 0xfc) \ 01650 { \ 01651 Len = 6; \ 01652 Mask = 0x01; \ 01653 } \ 01654 else \ 01655 { \ 01656 Len = 0; \ 01657 Mask = 0; \ 01658 } 01659 01664 #define UTF8_LENGTH(Char) \ 01665 ((Char) < 0x80 ? 1 : \ 01666 ((Char) < 0x800 ? 2 : \ 01667 ((Char) < 0x10000 ? 3 : \ 01668 ((Char) < 0x200000 ? 4 : \ 01669 ((Char) < 0x4000000 ? 5 : 6))))) 01670 01680 #define UTF8_GET(Result, Chars, Count, Mask, Len) \ 01681 (Result) = (Chars)[0] & (Mask); \ 01682 for ((Count) = 1; (Count) < (Len); ++(Count)) \ 01683 { \ 01684 if (((Chars)[(Count)] & 0xc0) != 0x80) \ 01685 { \ 01686 (Result) = -1; \ 01687 break; \ 01688 } \ 01689 (Result) <<= 6; \ 01690 (Result) |= ((Chars)[(Count)] & 0x3f); \ 01691 } 01692 01709 #define UNICODE_VALID(Char) \ 01710 ((Char) < 0x110000 && \ 01711 (((Char) & 0xFFFFF800) != 0xD800) && \ 01712 ((Char) < 0xFDD0 || (Char) > 0xFDEF) && \ 01713 ((Char) & 0xFFFE) != 0xFFFE) 01714 01715 #ifdef DBUS_BUILD_TESTS 01716 01726 void 01727 _dbus_string_get_unichar (const DBusString *str, 01728 int start, 01729 dbus_unichar_t *ch_return, 01730 int *end_return) 01731 { 01732 int i, mask, len; 01733 dbus_unichar_t result; 01734 unsigned char c; 01735 unsigned char *p; 01736 DBUS_CONST_STRING_PREAMBLE (str); 01737 _dbus_assert (start >= 0); 01738 _dbus_assert (start <= real->len); 01739 01740 if (ch_return) 01741 *ch_return = 0; 01742 if (end_return) 01743 *end_return = real->len; 01744 01745 mask = 0; 01746 p = real->str + start; 01747 c = *p; 01748 01749 UTF8_COMPUTE (c, mask, len); 01750 if (len == 0) 01751 return; 01752 UTF8_GET (result, p, i, mask, len); 01753 01754 if (result == (dbus_unichar_t)-1) 01755 return; 01756 01757 if (ch_return) 01758 *ch_return = result; 01759 if (end_return) 01760 *end_return = start + len; 01761 } 01762 #endif /* DBUS_BUILD_TESTS */ 01763 01778 dbus_bool_t 01779 _dbus_string_find (const DBusString *str, 01780 int start, 01781 const char *substr, 01782 int *found) 01783 { 01784 return _dbus_string_find_to (str, start, 01785 ((const DBusRealString*)str)->len, 01786 substr, found); 01787 } 01788 01801 dbus_bool_t 01802 _dbus_string_find_eol (const DBusString *str, 01803 int start, 01804 int *found, 01805 int *found_len) 01806 { 01807 int i; 01808 01809 DBUS_CONST_STRING_PREAMBLE (str); 01810 _dbus_assert (start <= real->len); 01811 _dbus_assert (start >= 0); 01812 01813 i = start; 01814 while (i < real->len) 01815 { 01816 if (real->str[i] == '\r') 01817 { 01818 if ((i+1) < real->len && real->str[i+1] == '\n') /* "\r\n" */ 01819 { 01820 if (found) 01821 *found = i; 01822 if (found_len) 01823 *found_len = 2; 01824 return TRUE; 01825 } 01826 else /* only "\r" */ 01827 { 01828 if (found) 01829 *found = i; 01830 if (found_len) 01831 *found_len = 1; 01832 return TRUE; 01833 } 01834 } 01835 else if (real->str[i] == '\n') /* only "\n" */ 01836 { 01837 if (found) 01838 *found = i; 01839 if (found_len) 01840 *found_len = 1; 01841 return TRUE; 01842 } 01843 ++i; 01844 } 01845 01846 if (found) 01847 *found = real->len; 01848 01849 if (found_len) 01850 *found_len = 0; 01851 01852 return FALSE; 01853 } 01854 01871 dbus_bool_t 01872 _dbus_string_find_to (const DBusString *str, 01873 int start, 01874 int end, 01875 const char *substr, 01876 int *found) 01877 { 01878 int i; 01879 DBUS_CONST_STRING_PREAMBLE (str); 01880 _dbus_assert (substr != NULL); 01881 _dbus_assert (start <= real->len); 01882 _dbus_assert (start >= 0); 01883 _dbus_assert (substr != NULL); 01884 _dbus_assert (end <= real->len); 01885 _dbus_assert (start <= end); 01886 01887 /* we always "find" an empty string */ 01888 if (*substr == '\0') 01889 { 01890 if (found) 01891 *found = start; 01892 return TRUE; 01893 } 01894 01895 i = start; 01896 while (i < end) 01897 { 01898 if (real->str[i] == substr[0]) 01899 { 01900 int j = i + 1; 01901 01902 while (j < end) 01903 { 01904 if (substr[j - i] == '\0') 01905 break; 01906 else if (real->str[j] != substr[j - i]) 01907 break; 01908 01909 ++j; 01910 } 01911 01912 if (substr[j - i] == '\0') 01913 { 01914 if (found) 01915 *found = i; 01916 return TRUE; 01917 } 01918 } 01919 01920 ++i; 01921 } 01922 01923 if (found) 01924 *found = end; 01925 01926 return FALSE; 01927 } 01928 01939 dbus_bool_t 01940 _dbus_string_find_blank (const DBusString *str, 01941 int start, 01942 int *found) 01943 { 01944 int i; 01945 DBUS_CONST_STRING_PREAMBLE (str); 01946 _dbus_assert (start <= real->len); 01947 _dbus_assert (start >= 0); 01948 01949 i = start; 01950 while (i < real->len) 01951 { 01952 if (real->str[i] == ' ' || 01953 real->str[i] == '\t') 01954 { 01955 if (found) 01956 *found = i; 01957 return TRUE; 01958 } 01959 01960 ++i; 01961 } 01962 01963 if (found) 01964 *found = real->len; 01965 01966 return FALSE; 01967 } 01968 01977 void 01978 _dbus_string_skip_blank (const DBusString *str, 01979 int start, 01980 int *end) 01981 { 01982 int i; 01983 DBUS_CONST_STRING_PREAMBLE (str); 01984 _dbus_assert (start <= real->len); 01985 _dbus_assert (start >= 0); 01986 01987 i = start; 01988 while (i < real->len) 01989 { 01990 if (!DBUS_IS_ASCII_BLANK (real->str[i])) 01991 break; 01992 01993 ++i; 01994 } 01995 01996 _dbus_assert (i == real->len || !DBUS_IS_ASCII_WHITE (real->str[i])); 01997 01998 if (end) 01999 *end = i; 02000 } 02001 02002 02011 void 02012 _dbus_string_skip_white (const DBusString *str, 02013 int start, 02014 int *end) 02015 { 02016 int i; 02017 DBUS_CONST_STRING_PREAMBLE (str); 02018 _dbus_assert (start <= real->len); 02019 _dbus_assert (start >= 0); 02020 02021 i = start; 02022 while (i < real->len) 02023 { 02024 if (!DBUS_IS_ASCII_WHITE (real->str[i])) 02025 break; 02026 02027 ++i; 02028 } 02029 02030 _dbus_assert (i == real->len || !(DBUS_IS_ASCII_WHITE (real->str[i]))); 02031 02032 if (end) 02033 *end = i; 02034 } 02035 02044 void 02045 _dbus_string_skip_white_reverse (const DBusString *str, 02046 int end, 02047 int *start) 02048 { 02049 int i; 02050 DBUS_CONST_STRING_PREAMBLE (str); 02051 _dbus_assert (end <= real->len); 02052 _dbus_assert (end >= 0); 02053 02054 i = end; 02055 while (i > 0) 02056 { 02057 if (!DBUS_IS_ASCII_WHITE (real->str[i-1])) 02058 break; 02059 --i; 02060 } 02061 02062 _dbus_assert (i >= 0 && (i == 0 || !(DBUS_IS_ASCII_WHITE (real->str[i-1])))); 02063 02064 if (start) 02065 *start = i; 02066 } 02067 02083 dbus_bool_t 02084 _dbus_string_pop_line (DBusString *source, 02085 DBusString *dest) 02086 { 02087 int eol, eol_len; 02088 02089 _dbus_string_set_length (dest, 0); 02090 02091 eol = 0; 02092 eol_len = 0; 02093 if (!_dbus_string_find_eol (source, 0, &eol, &eol_len)) 02094 { 02095 _dbus_assert (eol == _dbus_string_get_length (source)); 02096 if (eol == 0) 02097 { 02098 /* If there's no newline and source has zero length, we're done */ 02099 return FALSE; 02100 } 02101 /* otherwise, the last line of the file has no eol characters */ 02102 } 02103 02104 /* remember eol can be 0 if it's an empty line, but eol_len should not be zero also 02105 * since find_eol returned TRUE 02106 */ 02107 02108 if (!_dbus_string_move_len (source, 0, eol + eol_len, dest, 0)) 02109 return FALSE; 02110 02111 /* remove line ending */ 02112 if (!_dbus_string_set_length (dest, eol)) 02113 { 02114 _dbus_assert_not_reached ("out of memory when shortening a string"); 02115 return FALSE; 02116 } 02117 02118 return TRUE; 02119 } 02120 02121 #ifdef DBUS_BUILD_TESTS 02122 02128 void 02129 _dbus_string_delete_first_word (DBusString *str) 02130 { 02131 int i; 02132 02133 if (_dbus_string_find_blank (str, 0, &i)) 02134 _dbus_string_skip_blank (str, i, &i); 02135 02136 _dbus_string_delete (str, 0, i); 02137 } 02138 #endif 02139 02140 #ifdef DBUS_BUILD_TESTS 02141 02146 void 02147 _dbus_string_delete_leading_blanks (DBusString *str) 02148 { 02149 int i; 02150 02151 _dbus_string_skip_blank (str, 0, &i); 02152 02153 if (i > 0) 02154 _dbus_string_delete (str, 0, i); 02155 } 02156 #endif 02157 02163 void 02164 _dbus_string_chop_white(DBusString *str) 02165 { 02166 int i; 02167 02168 _dbus_string_skip_white (str, 0, &i); 02169 02170 if (i > 0) 02171 _dbus_string_delete (str, 0, i); 02172 02173 _dbus_string_skip_white_reverse (str, _dbus_string_get_length (str), &i); 02174 02175 _dbus_string_set_length (str, i); 02176 } 02177 02187 dbus_bool_t 02188 _dbus_string_equal (const DBusString *a, 02189 const DBusString *b) 02190 { 02191 const unsigned char *ap; 02192 const unsigned char *bp; 02193 const unsigned char *a_end; 02194 const DBusRealString *real_a = (const DBusRealString*) a; 02195 const DBusRealString *real_b = (const DBusRealString*) b; 02196 DBUS_GENERIC_STRING_PREAMBLE (real_a); 02197 DBUS_GENERIC_STRING_PREAMBLE (real_b); 02198 02199 if (real_a->len != real_b->len) 02200 return FALSE; 02201 02202 ap = real_a->str; 02203 bp = real_b->str; 02204 a_end = real_a->str + real_a->len; 02205 while (ap != a_end) 02206 { 02207 if (*ap != *bp) 02208 return FALSE; 02209 02210 ++ap; 02211 ++bp; 02212 } 02213 02214 return TRUE; 02215 } 02216 02230 dbus_bool_t 02231 _dbus_string_equal_len (const DBusString *a, 02232 const DBusString *b, 02233 int len) 02234 { 02235 const unsigned char *ap; 02236 const unsigned char *bp; 02237 const unsigned char *a_end; 02238 const DBusRealString *real_a = (const DBusRealString*) a; 02239 const DBusRealString *real_b = (const DBusRealString*) b; 02240 DBUS_GENERIC_STRING_PREAMBLE (real_a); 02241 DBUS_GENERIC_STRING_PREAMBLE (real_b); 02242 02243 if (real_a->len != real_b->len && 02244 (real_a->len < len || real_b->len < len)) 02245 return FALSE; 02246 02247 ap = real_a->str; 02248 bp = real_b->str; 02249 a_end = real_a->str + MIN (real_a->len, len); 02250 while (ap != a_end) 02251 { 02252 if (*ap != *bp) 02253 return FALSE; 02254 02255 ++ap; 02256 ++bp; 02257 } 02258 02259 return TRUE; 02260 } 02261 02278 dbus_bool_t 02279 _dbus_string_equal_substring (const DBusString *a, 02280 int a_start, 02281 int a_len, 02282 const DBusString *b, 02283 int b_start) 02284 { 02285 const unsigned char *ap; 02286 const unsigned char *bp; 02287 const unsigned char *a_end; 02288 const DBusRealString *real_a = (const DBusRealString*) a; 02289 const DBusRealString *real_b = (const DBusRealString*) b; 02290 DBUS_GENERIC_STRING_PREAMBLE (real_a); 02291 DBUS_GENERIC_STRING_PREAMBLE (real_b); 02292 _dbus_assert (a_start >= 0); 02293 _dbus_assert (a_len >= 0); 02294 _dbus_assert (a_start <= real_a->len); 02295 _dbus_assert (a_len <= real_a->len - a_start); 02296 _dbus_assert (b_start >= 0); 02297 _dbus_assert (b_start <= real_b->len); 02298 02299 if (a_len > real_b->len - b_start) 02300 return FALSE; 02301 02302 ap = real_a->str + a_start; 02303 bp = real_b->str + b_start; 02304 a_end = ap + a_len; 02305 while (ap != a_end) 02306 { 02307 if (*ap != *bp) 02308 return FALSE; 02309 02310 ++ap; 02311 ++bp; 02312 } 02313 02314 _dbus_assert (bp <= (real_b->str + real_b->len)); 02315 02316 return TRUE; 02317 } 02318 02326 dbus_bool_t 02327 _dbus_string_equal_c_str (const DBusString *a, 02328 const char *c_str) 02329 { 02330 const unsigned char *ap; 02331 const unsigned char *bp; 02332 const unsigned char *a_end; 02333 const DBusRealString *real_a = (const DBusRealString*) a; 02334 DBUS_GENERIC_STRING_PREAMBLE (real_a); 02335 _dbus_assert (c_str != NULL); 02336 02337 ap = real_a->str; 02338 bp = (const unsigned char*) c_str; 02339 a_end = real_a->str + real_a->len; 02340 while (ap != a_end && *bp) 02341 { 02342 if (*ap != *bp) 02343 return FALSE; 02344 02345 ++ap; 02346 ++bp; 02347 } 02348 02349 if (ap != a_end || *bp) 02350 return FALSE; 02351 02352 return TRUE; 02353 } 02354 02355 #ifdef DBUS_BUILD_TESTS 02356 02363 dbus_bool_t 02364 _dbus_string_starts_with_c_str (const DBusString *a, 02365 const char *c_str) 02366 { 02367 const unsigned char *ap; 02368 const unsigned char *bp; 02369 const unsigned char *a_end; 02370 const DBusRealString *real_a = (const DBusRealString*) a; 02371 DBUS_GENERIC_STRING_PREAMBLE (real_a); 02372 _dbus_assert (c_str != NULL); 02373 02374 ap = real_a->str; 02375 bp = (const unsigned char*) c_str; 02376 a_end = real_a->str + real_a->len; 02377 while (ap != a_end && *bp) 02378 { 02379 if (*ap != *bp) 02380 return FALSE; 02381 02382 ++ap; 02383 ++bp; 02384 } 02385 02386 if (*bp == '\0') 02387 return TRUE; 02388 else 02389 return FALSE; 02390 } 02391 #endif /* DBUS_BUILD_TESTS */ 02392 02401 dbus_bool_t 02402 _dbus_string_append_byte_as_hex (DBusString *str, 02403 int byte) 02404 { 02405 const char hexdigits[16] = { 02406 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 02407 'a', 'b', 'c', 'd', 'e', 'f' 02408 }; 02409 02410 if (!_dbus_string_append_byte (str, 02411 hexdigits[(byte >> 4)])) 02412 return FALSE; 02413 02414 if (!_dbus_string_append_byte (str, 02415 hexdigits[(byte & 0x0f)])) 02416 { 02417 _dbus_string_set_length (str, 02418 _dbus_string_get_length (str) - 1); 02419 return FALSE; 02420 } 02421 02422 return TRUE; 02423 } 02424 02435 dbus_bool_t 02436 _dbus_string_hex_encode (const DBusString *source, 02437 int start, 02438 DBusString *dest, 02439 int insert_at) 02440 { 02441 DBusString result; 02442 const unsigned char *p; 02443 const unsigned char *end; 02444 dbus_bool_t retval; 02445 02446 _dbus_assert (start <= _dbus_string_get_length (source)); 02447 02448 if (!_dbus_string_init (&result)) 02449 return FALSE; 02450 02451 retval = FALSE; 02452 02453 p = (const unsigned char*) _dbus_string_get_const_data (source); 02454 end = p + _dbus_string_get_length (source); 02455 p += start; 02456 02457 while (p != end) 02458 { 02459 if (!_dbus_string_append_byte_as_hex (&result, *p)) 02460 goto out; 02461 02462 ++p; 02463 } 02464 02465 if (!_dbus_string_move (&result, 0, dest, insert_at)) 02466 goto out; 02467 02468 retval = TRUE; 02469 02470 out: 02471 _dbus_string_free (&result); 02472 return retval; 02473 } 02474 02485 dbus_bool_t 02486 _dbus_string_hex_decode (const DBusString *source, 02487 int start, 02488 int *end_return, 02489 DBusString *dest, 02490 int insert_at) 02491 { 02492 DBusString result; 02493 const unsigned char *p; 02494 const unsigned char *end; 02495 dbus_bool_t retval; 02496 dbus_bool_t high_bits; 02497 02498 _dbus_assert (start <= _dbus_string_get_length (source)); 02499 02500 if (!_dbus_string_init (&result)) 02501 return FALSE; 02502 02503 retval = FALSE; 02504 02505 high_bits = TRUE; 02506 p = (const unsigned char*) _dbus_string_get_const_data (source); 02507 end = p + _dbus_string_get_length (source); 02508 p += start; 02509 02510 while (p != end) 02511 { 02512 unsigned int val; 02513 02514 switch (*p) 02515 { 02516 case '0': 02517 val = 0; 02518 break; 02519 case '1': 02520 val = 1; 02521 break; 02522 case '2': 02523 val = 2; 02524 break; 02525 case '3': 02526 val = 3; 02527 break; 02528 case '4': 02529 val = 4; 02530 break; 02531 case '5': 02532 val = 5; 02533 break; 02534 case '6': 02535 val = 6; 02536 break; 02537 case '7': 02538 val = 7; 02539 break; 02540 case '8': 02541 val = 8; 02542 break; 02543 case '9': 02544 val = 9; 02545 break; 02546 case 'a': 02547 case 'A': 02548 val = 10; 02549 break; 02550 case 'b': 02551 case 'B': 02552 val = 11; 02553 break; 02554 case 'c': 02555 case 'C': 02556 val = 12; 02557 break; 02558 case 'd': 02559 case 'D': 02560 val = 13; 02561 break; 02562 case 'e': 02563 case 'E': 02564 val = 14; 02565 break; 02566 case 'f': 02567 case 'F': 02568 val = 15; 02569 break; 02570 default: 02571 goto done; 02572 } 02573 02574 if (high_bits) 02575 { 02576 if (!_dbus_string_append_byte (&result, 02577 val << 4)) 02578 goto out; 02579 } 02580 else 02581 { 02582 int len; 02583 unsigned char b; 02584 02585 len = _dbus_string_get_length (&result); 02586 02587 b = _dbus_string_get_byte (&result, len - 1); 02588 02589 b |= val; 02590 02591 _dbus_string_set_byte (&result, len - 1, b); 02592 } 02593 02594 high_bits = !high_bits; 02595 02596 ++p; 02597 } 02598 02599 done: 02600 if (!_dbus_string_move (&result, 0, dest, insert_at)) 02601 goto out; 02602 02603 if (end_return) 02604 *end_return = p - (const unsigned char*) _dbus_string_get_const_data (source); 02605 02606 retval = TRUE; 02607 02608 out: 02609 _dbus_string_free (&result); 02610 return retval; 02611 } 02612 02626 dbus_bool_t 02627 _dbus_string_validate_ascii (const DBusString *str, 02628 int start, 02629 int len) 02630 { 02631 const unsigned char *s; 02632 const unsigned char *end; 02633 DBUS_CONST_STRING_PREAMBLE (str); 02634 _dbus_assert (start >= 0); 02635 _dbus_assert (start <= real->len); 02636 _dbus_assert (len >= 0); 02637 02638 if (len > real->len - start) 02639 return FALSE; 02640 02641 s = real->str + start; 02642 end = s + len; 02643 while (s != end) 02644 { 02645 if (_DBUS_UNLIKELY (!_DBUS_ISASCII (*s))) 02646 return FALSE; 02647 02648 ++s; 02649 } 02650 02651 return TRUE; 02652 } 02653 02661 void 02662 _dbus_string_tolower_ascii (const DBusString *str, 02663 int start, 02664 int len) 02665 { 02666 unsigned char *s; 02667 unsigned char *end; 02668 DBUS_STRING_PREAMBLE (str); 02669 _dbus_assert (start >= 0); 02670 _dbus_assert (start <= real->len); 02671 _dbus_assert (len >= 0); 02672 _dbus_assert (len <= real->len - start); 02673 02674 s = real->str + start; 02675 end = s + len; 02676 02677 while (s != end) 02678 { 02679 if (*s >= 'A' && *s <= 'Z') 02680 *s += 'a' - 'A'; 02681 ++s; 02682 } 02683 } 02684 02692 void 02693 _dbus_string_toupper_ascii (const DBusString *str, 02694 int start, 02695 int len) 02696 { 02697 unsigned char *s; 02698 unsigned char *end; 02699 DBUS_STRING_PREAMBLE (str); 02700 _dbus_assert (start >= 0); 02701 _dbus_assert (start <= real->len); 02702 _dbus_assert (len >= 0); 02703 _dbus_assert (len <= real->len - start); 02704 02705 s = real->str + start; 02706 end = s + len; 02707 02708 while (s != end) 02709 { 02710 if (*s >= 'a' && *s <= 'z') 02711 *s += 'A' - 'a'; 02712 ++s; 02713 } 02714 } 02715 02731 dbus_bool_t 02732 _dbus_string_validate_utf8 (const DBusString *str, 02733 int start, 02734 int len) 02735 { 02736 const unsigned char *p; 02737 const unsigned char *end; 02738 DBUS_CONST_STRING_PREAMBLE (str); 02739 _dbus_assert (start >= 0); 02740 _dbus_assert (start <= real->len); 02741 _dbus_assert (len >= 0); 02742 02743 /* we are doing _DBUS_UNLIKELY() here which might be 02744 * dubious in a generic library like GLib, but in D-Bus 02745 * we know we're validating messages and that it would 02746 * only be evil/broken apps that would have invalid 02747 * UTF-8. Also, this function seems to be a performance 02748 * bottleneck in profiles. 02749 */ 02750 02751 if (_DBUS_UNLIKELY (len > real->len - start)) 02752 return FALSE; 02753 02754 p = real->str + start; 02755 end = p + len; 02756 02757 while (p < end) 02758 { 02759 int i, mask, char_len; 02760 dbus_unichar_t result; 02761 02762 /* nul bytes considered invalid */ 02763 if (*p == '\0') 02764 break; 02765 02766 /* Special-case ASCII; this makes us go a lot faster in 02767 * D-Bus profiles where we are typically validating 02768 * function names and such. We have to know that 02769 * all following checks will pass for ASCII though, 02770 * comments follow ... 02771 */ 02772 if (*p < 128) 02773 { 02774 ++p; 02775 continue; 02776 } 02777 02778 UTF8_COMPUTE (*p, mask, char_len); 02779 02780 if (_DBUS_UNLIKELY (char_len == 0)) /* ASCII: char_len == 1 */ 02781 break; 02782 02783 /* check that the expected number of bytes exists in the remaining length */ 02784 if (_DBUS_UNLIKELY ((end - p) < char_len)) /* ASCII: p < end and char_len == 1 */ 02785 break; 02786 02787 UTF8_GET (result, p, i, mask, char_len); 02788 02789 /* Check for overlong UTF-8 */ 02790 if (_DBUS_UNLIKELY (UTF8_LENGTH (result) != char_len)) /* ASCII: UTF8_LENGTH == 1 */ 02791 break; 02792 #if 0 02793 /* The UNICODE_VALID check below will catch this */ 02794 if (_DBUS_UNLIKELY (result == (dbus_unichar_t)-1)) /* ASCII: result = ascii value */ 02795 break; 02796 #endif 02797 02798 if (_DBUS_UNLIKELY (!UNICODE_VALID (result))) /* ASCII: always valid */ 02799 break; 02800 02801 /* UNICODE_VALID should have caught it */ 02802 _dbus_assert (result != (dbus_unichar_t)-1); 02803 02804 p += char_len; 02805 } 02806 02807 /* See that we covered the entire length if a length was 02808 * passed in 02809 */ 02810 if (_DBUS_UNLIKELY (p != end)) 02811 return FALSE; 02812 else 02813 return TRUE; 02814 } 02815 02829 dbus_bool_t 02830 _dbus_string_validate_nul (const DBusString *str, 02831 int start, 02832 int len) 02833 { 02834 const unsigned char *s; 02835 const unsigned char *end; 02836 DBUS_CONST_STRING_PREAMBLE (str); 02837 _dbus_assert (start >= 0); 02838 _dbus_assert (len >= 0); 02839 _dbus_assert (start <= real->len); 02840 02841 if (len > real->len - start) 02842 return FALSE; 02843 02844 s = real->str + start; 02845 end = s + len; 02846 while (s != end) 02847 { 02848 if (_DBUS_UNLIKELY (*s != '\0')) 02849 return FALSE; 02850 ++s; 02851 } 02852 02853 return TRUE; 02854 } 02855 02861 void 02862 _dbus_string_zero (DBusString *str) 02863 { 02864 DBUS_STRING_PREAMBLE (str); 02865 02866 memset (real->str - real->align_offset, '\0', real->allocated); 02867 } 02870 /* tests are in dbus-string-util.c */
1.7.5.1