D-Bus 1.6.12
|
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 00969 dbus_bool_t 00970 _dbus_string_insert_2_aligned (DBusString *str, 00971 int insert_at, 00972 const unsigned char octets[4]) 00973 { 00974 DBUS_STRING_PREAMBLE (str); 00975 00976 if (!align_insert_point_then_open_gap (str, &insert_at, 2, 2)) 00977 return FALSE; 00978 00979 ASSIGN_2_OCTETS (real->str + insert_at, octets); 00980 00981 return TRUE; 00982 } 00983 00993 dbus_bool_t 00994 _dbus_string_insert_4_aligned (DBusString *str, 00995 int insert_at, 00996 const unsigned char octets[4]) 00997 { 00998 DBUS_STRING_PREAMBLE (str); 00999 01000 if (!align_insert_point_then_open_gap (str, &insert_at, 4, 4)) 01001 return FALSE; 01002 01003 ASSIGN_4_OCTETS (real->str + insert_at, octets); 01004 01005 return TRUE; 01006 } 01007 01017 dbus_bool_t 01018 _dbus_string_insert_8_aligned (DBusString *str, 01019 int insert_at, 01020 const unsigned char octets[8]) 01021 { 01022 DBUS_STRING_PREAMBLE (str); 01023 01024 if (!align_insert_point_then_open_gap (str, &insert_at, 8, 8)) 01025 return FALSE; 01026 01027 _dbus_assert (_DBUS_ALIGN_VALUE (insert_at, 8) == (unsigned) insert_at); 01028 01029 ASSIGN_8_OCTETS (real->str + insert_at, octets); 01030 01031 return TRUE; 01032 } 01033 01034 01045 dbus_bool_t 01046 _dbus_string_insert_alignment (DBusString *str, 01047 int *insert_at, 01048 int alignment) 01049 { 01050 DBUS_STRING_PREAMBLE (str); 01051 01052 if (!align_insert_point_then_open_gap (str, insert_at, alignment, 0)) 01053 return FALSE; 01054 01055 _dbus_assert (_DBUS_ALIGN_VALUE (*insert_at, alignment) == (unsigned) *insert_at); 01056 01057 return TRUE; 01058 } 01059 01069 dbus_bool_t 01070 _dbus_string_append_printf_valist (DBusString *str, 01071 const char *format, 01072 va_list args) 01073 { 01074 int len; 01075 va_list args_copy; 01076 01077 DBUS_STRING_PREAMBLE (str); 01078 01079 DBUS_VA_COPY (args_copy, args); 01080 01081 /* Measure the message length without terminating nul */ 01082 len = _dbus_printf_string_upper_bound (format, args); 01083 01084 if (len < 0) 01085 return FALSE; 01086 01087 if (!_dbus_string_lengthen (str, len)) 01088 { 01089 /* don't leak the copy */ 01090 va_end (args_copy); 01091 return FALSE; 01092 } 01093 01094 vsprintf ((char*) (real->str + (real->len - len)), 01095 format, args_copy); 01096 01097 va_end (args_copy); 01098 01099 return TRUE; 01100 } 01101 01110 dbus_bool_t 01111 _dbus_string_append_printf (DBusString *str, 01112 const char *format, 01113 ...) 01114 { 01115 va_list args; 01116 dbus_bool_t retval; 01117 01118 va_start (args, format); 01119 retval = _dbus_string_append_printf_valist (str, format, args); 01120 va_end (args); 01121 01122 return retval; 01123 } 01124 01133 dbus_bool_t 01134 _dbus_string_append_len (DBusString *str, 01135 const char *buffer, 01136 int len) 01137 { 01138 DBUS_STRING_PREAMBLE (str); 01139 _dbus_assert (buffer != NULL); 01140 _dbus_assert (len >= 0); 01141 01142 return append (real, buffer, len); 01143 } 01144 01153 dbus_bool_t 01154 _dbus_string_append_byte (DBusString *str, 01155 unsigned char byte) 01156 { 01157 DBUS_STRING_PREAMBLE (str); 01158 01159 if (!set_length (real, real->len + 1)) 01160 return FALSE; 01161 01162 real->str[real->len-1] = byte; 01163 01164 return TRUE; 01165 } 01166 01167 static void 01168 delete (DBusRealString *real, 01169 int start, 01170 int len) 01171 { 01172 if (len == 0) 01173 return; 01174 01175 memmove (real->str + start, real->str + start + len, real->len - (start + len)); 01176 real->len -= len; 01177 real->str[real->len] = '\0'; 01178 } 01179 01189 void 01190 _dbus_string_delete (DBusString *str, 01191 int start, 01192 int len) 01193 { 01194 DBUS_STRING_PREAMBLE (str); 01195 _dbus_assert (start >= 0); 01196 _dbus_assert (len >= 0); 01197 _dbus_assert (start <= real->len); 01198 _dbus_assert (len <= real->len - start); 01199 01200 delete (real, start, len); 01201 } 01202 01203 static dbus_bool_t 01204 copy (DBusRealString *source, 01205 int start, 01206 int len, 01207 DBusRealString *dest, 01208 int insert_at) 01209 { 01210 if (len == 0) 01211 return TRUE; 01212 01213 if (!open_gap (len, dest, insert_at)) 01214 return FALSE; 01215 01216 memmove (dest->str + insert_at, 01217 source->str + start, 01218 len); 01219 01220 return TRUE; 01221 } 01222 01232 #define DBUS_STRING_COPY_PREAMBLE(source, start, dest, insert_at) \ 01233 DBusRealString *real_source = (DBusRealString*) source; \ 01234 DBusRealString *real_dest = (DBusRealString*) dest; \ 01235 _dbus_assert ((source) != (dest)); \ 01236 DBUS_GENERIC_STRING_PREAMBLE (real_source); \ 01237 DBUS_GENERIC_STRING_PREAMBLE (real_dest); \ 01238 _dbus_assert (!real_dest->constant); \ 01239 _dbus_assert (!real_dest->locked); \ 01240 _dbus_assert ((start) >= 0); \ 01241 _dbus_assert ((start) <= real_source->len); \ 01242 _dbus_assert ((insert_at) >= 0); \ 01243 _dbus_assert ((insert_at) <= real_dest->len) 01244 01255 dbus_bool_t 01256 _dbus_string_move (DBusString *source, 01257 int start, 01258 DBusString *dest, 01259 int insert_at) 01260 { 01261 DBusRealString *real_source = (DBusRealString*) source; 01262 _dbus_assert (start <= real_source->len); 01263 01264 return _dbus_string_move_len (source, start, 01265 real_source->len - start, 01266 dest, insert_at); 01267 } 01268 01279 dbus_bool_t 01280 _dbus_string_copy (const DBusString *source, 01281 int start, 01282 DBusString *dest, 01283 int insert_at) 01284 { 01285 DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at); 01286 01287 return copy (real_source, start, 01288 real_source->len - start, 01289 real_dest, 01290 insert_at); 01291 } 01292 01304 dbus_bool_t 01305 _dbus_string_move_len (DBusString *source, 01306 int start, 01307 int len, 01308 DBusString *dest, 01309 int insert_at) 01310 01311 { 01312 DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at); 01313 _dbus_assert (len >= 0); 01314 _dbus_assert ((start + len) <= real_source->len); 01315 01316 01317 if (len == 0) 01318 { 01319 return TRUE; 01320 } 01321 else if (start == 0 && 01322 len == real_source->len && 01323 real_dest->len == 0) 01324 { 01325 /* Short-circuit moving an entire existing string to an empty string 01326 * by just swapping the buffers. 01327 */ 01328 /* we assume ->constant doesn't matter as you can't have 01329 * a constant string involved in a move. 01330 */ 01331 #define ASSIGN_DATA(a, b) do { \ 01332 (a)->str = (b)->str; \ 01333 (a)->len = (b)->len; \ 01334 (a)->allocated = (b)->allocated; \ 01335 (a)->align_offset = (b)->align_offset; \ 01336 } while (0) 01337 01338 DBusRealString tmp; 01339 01340 ASSIGN_DATA (&tmp, real_source); 01341 ASSIGN_DATA (real_source, real_dest); 01342 ASSIGN_DATA (real_dest, &tmp); 01343 01344 return TRUE; 01345 } 01346 else 01347 { 01348 if (!copy (real_source, start, len, 01349 real_dest, 01350 insert_at)) 01351 return FALSE; 01352 01353 delete (real_source, start, 01354 len); 01355 01356 return TRUE; 01357 } 01358 } 01359 01371 dbus_bool_t 01372 _dbus_string_copy_len (const DBusString *source, 01373 int start, 01374 int len, 01375 DBusString *dest, 01376 int insert_at) 01377 { 01378 DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at); 01379 _dbus_assert (len >= 0); 01380 _dbus_assert (start <= real_source->len); 01381 _dbus_assert (len <= real_source->len - start); 01382 01383 return copy (real_source, start, len, 01384 real_dest, 01385 insert_at); 01386 } 01387 01400 dbus_bool_t 01401 _dbus_string_replace_len (const DBusString *source, 01402 int start, 01403 int len, 01404 DBusString *dest, 01405 int replace_at, 01406 int replace_len) 01407 { 01408 DBUS_STRING_COPY_PREAMBLE (source, start, dest, replace_at); 01409 _dbus_assert (len >= 0); 01410 _dbus_assert (start <= real_source->len); 01411 _dbus_assert (len <= real_source->len - start); 01412 _dbus_assert (replace_at >= 0); 01413 _dbus_assert (replace_at <= real_dest->len); 01414 _dbus_assert (replace_len <= real_dest->len - replace_at); 01415 01416 if (len == replace_len) 01417 { 01418 memmove (real_dest->str + replace_at, 01419 real_source->str + start, len); 01420 } 01421 else if (len < replace_len) 01422 { 01423 memmove (real_dest->str + replace_at, 01424 real_source->str + start, len); 01425 delete (real_dest, replace_at + len, 01426 replace_len - len); 01427 } 01428 else 01429 { 01430 int diff; 01431 01432 _dbus_assert (len > replace_len); 01433 01434 diff = len - replace_len; 01435 01436 /* First of all we check if destination string can be enlarged as 01437 * required, then we overwrite previous bytes 01438 */ 01439 01440 if (!copy (real_source, start + replace_len, diff, 01441 real_dest, replace_at + replace_len)) 01442 return FALSE; 01443 01444 memmove (real_dest->str + replace_at, 01445 real_source->str + start, replace_len); 01446 } 01447 01448 return TRUE; 01449 } 01450 01463 dbus_bool_t 01464 _dbus_string_split_on_byte (DBusString *source, 01465 unsigned char byte, 01466 DBusString *tail) 01467 { 01468 int byte_position; 01469 char byte_string[2] = ""; 01470 int head_length; 01471 int tail_length; 01472 01473 byte_string[0] = (char) byte; 01474 01475 if (!_dbus_string_find (source, 0, byte_string, &byte_position)) 01476 return FALSE; 01477 01478 head_length = byte_position; 01479 tail_length = _dbus_string_get_length (source) - head_length - 1; 01480 01481 if (!_dbus_string_move_len (source, byte_position + 1, tail_length, 01482 tail, 0)) 01483 return FALSE; 01484 01485 /* remove the trailing delimiter byte from the head now. 01486 */ 01487 if (!_dbus_string_set_length (source, head_length)) 01488 return FALSE; 01489 01490 return TRUE; 01491 } 01492 01493 /* Unicode macros and utf8_validate() from GLib Owen Taylor, Havoc 01494 * Pennington, and Tom Tromey are the authors and authorized relicense. 01495 */ 01496 01502 #define UTF8_COMPUTE(Char, Mask, Len) \ 01503 if (Char < 128) \ 01504 { \ 01505 Len = 1; \ 01506 Mask = 0x7f; \ 01507 } \ 01508 else if ((Char & 0xe0) == 0xc0) \ 01509 { \ 01510 Len = 2; \ 01511 Mask = 0x1f; \ 01512 } \ 01513 else if ((Char & 0xf0) == 0xe0) \ 01514 { \ 01515 Len = 3; \ 01516 Mask = 0x0f; \ 01517 } \ 01518 else if ((Char & 0xf8) == 0xf0) \ 01519 { \ 01520 Len = 4; \ 01521 Mask = 0x07; \ 01522 } \ 01523 else if ((Char & 0xfc) == 0xf8) \ 01524 { \ 01525 Len = 5; \ 01526 Mask = 0x03; \ 01527 } \ 01528 else if ((Char & 0xfe) == 0xfc) \ 01529 { \ 01530 Len = 6; \ 01531 Mask = 0x01; \ 01532 } \ 01533 else \ 01534 { \ 01535 Len = 0; \ 01536 Mask = 0; \ 01537 } 01538 01543 #define UTF8_LENGTH(Char) \ 01544 ((Char) < 0x80 ? 1 : \ 01545 ((Char) < 0x800 ? 2 : \ 01546 ((Char) < 0x10000 ? 3 : \ 01547 ((Char) < 0x200000 ? 4 : \ 01548 ((Char) < 0x4000000 ? 5 : 6))))) 01549 01559 #define UTF8_GET(Result, Chars, Count, Mask, Len) \ 01560 (Result) = (Chars)[0] & (Mask); \ 01561 for ((Count) = 1; (Count) < (Len); ++(Count)) \ 01562 { \ 01563 if (((Chars)[(Count)] & 0xc0) != 0x80) \ 01564 { \ 01565 (Result) = -1; \ 01566 break; \ 01567 } \ 01568 (Result) <<= 6; \ 01569 (Result) |= ((Chars)[(Count)] & 0x3f); \ 01570 } 01571 01582 #define UNICODE_VALID(Char) \ 01583 ((Char) < 0x110000 && \ 01584 (((Char) & 0xFFFFF800) != 0xD800)) 01585 01600 dbus_bool_t 01601 _dbus_string_find (const DBusString *str, 01602 int start, 01603 const char *substr, 01604 int *found) 01605 { 01606 return _dbus_string_find_to (str, start, 01607 ((const DBusRealString*)str)->len, 01608 substr, found); 01609 } 01610 01623 dbus_bool_t 01624 _dbus_string_find_eol (const DBusString *str, 01625 int start, 01626 int *found, 01627 int *found_len) 01628 { 01629 int i; 01630 01631 DBUS_CONST_STRING_PREAMBLE (str); 01632 _dbus_assert (start <= real->len); 01633 _dbus_assert (start >= 0); 01634 01635 i = start; 01636 while (i < real->len) 01637 { 01638 if (real->str[i] == '\r') 01639 { 01640 if ((i+1) < real->len && real->str[i+1] == '\n') /* "\r\n" */ 01641 { 01642 if (found) 01643 *found = i; 01644 if (found_len) 01645 *found_len = 2; 01646 return TRUE; 01647 } 01648 else /* only "\r" */ 01649 { 01650 if (found) 01651 *found = i; 01652 if (found_len) 01653 *found_len = 1; 01654 return TRUE; 01655 } 01656 } 01657 else if (real->str[i] == '\n') /* only "\n" */ 01658 { 01659 if (found) 01660 *found = i; 01661 if (found_len) 01662 *found_len = 1; 01663 return TRUE; 01664 } 01665 ++i; 01666 } 01667 01668 if (found) 01669 *found = real->len; 01670 01671 if (found_len) 01672 *found_len = 0; 01673 01674 return FALSE; 01675 } 01676 01693 dbus_bool_t 01694 _dbus_string_find_to (const DBusString *str, 01695 int start, 01696 int end, 01697 const char *substr, 01698 int *found) 01699 { 01700 int i; 01701 DBUS_CONST_STRING_PREAMBLE (str); 01702 _dbus_assert (substr != NULL); 01703 _dbus_assert (start <= real->len); 01704 _dbus_assert (start >= 0); 01705 _dbus_assert (substr != NULL); 01706 _dbus_assert (end <= real->len); 01707 _dbus_assert (start <= end); 01708 01709 /* we always "find" an empty string */ 01710 if (*substr == '\0') 01711 { 01712 if (found) 01713 *found = start; 01714 return TRUE; 01715 } 01716 01717 i = start; 01718 while (i < end) 01719 { 01720 if (real->str[i] == substr[0]) 01721 { 01722 int j = i + 1; 01723 01724 while (j < end) 01725 { 01726 if (substr[j - i] == '\0') 01727 break; 01728 else if (real->str[j] != substr[j - i]) 01729 break; 01730 01731 ++j; 01732 } 01733 01734 if (substr[j - i] == '\0') 01735 { 01736 if (found) 01737 *found = i; 01738 return TRUE; 01739 } 01740 } 01741 01742 ++i; 01743 } 01744 01745 if (found) 01746 *found = end; 01747 01748 return FALSE; 01749 } 01750 01761 dbus_bool_t 01762 _dbus_string_find_blank (const DBusString *str, 01763 int start, 01764 int *found) 01765 { 01766 int i; 01767 DBUS_CONST_STRING_PREAMBLE (str); 01768 _dbus_assert (start <= real->len); 01769 _dbus_assert (start >= 0); 01770 01771 i = start; 01772 while (i < real->len) 01773 { 01774 if (real->str[i] == ' ' || 01775 real->str[i] == '\t') 01776 { 01777 if (found) 01778 *found = i; 01779 return TRUE; 01780 } 01781 01782 ++i; 01783 } 01784 01785 if (found) 01786 *found = real->len; 01787 01788 return FALSE; 01789 } 01790 01799 void 01800 _dbus_string_skip_blank (const DBusString *str, 01801 int start, 01802 int *end) 01803 { 01804 int i; 01805 DBUS_CONST_STRING_PREAMBLE (str); 01806 _dbus_assert (start <= real->len); 01807 _dbus_assert (start >= 0); 01808 01809 i = start; 01810 while (i < real->len) 01811 { 01812 if (!DBUS_IS_ASCII_BLANK (real->str[i])) 01813 break; 01814 01815 ++i; 01816 } 01817 01818 _dbus_assert (i == real->len || !DBUS_IS_ASCII_WHITE (real->str[i])); 01819 01820 if (end) 01821 *end = i; 01822 } 01823 01824 01833 void 01834 _dbus_string_skip_white (const DBusString *str, 01835 int start, 01836 int *end) 01837 { 01838 int i; 01839 DBUS_CONST_STRING_PREAMBLE (str); 01840 _dbus_assert (start <= real->len); 01841 _dbus_assert (start >= 0); 01842 01843 i = start; 01844 while (i < real->len) 01845 { 01846 if (!DBUS_IS_ASCII_WHITE (real->str[i])) 01847 break; 01848 01849 ++i; 01850 } 01851 01852 _dbus_assert (i == real->len || !(DBUS_IS_ASCII_WHITE (real->str[i]))); 01853 01854 if (end) 01855 *end = i; 01856 } 01857 01866 void 01867 _dbus_string_skip_white_reverse (const DBusString *str, 01868 int end, 01869 int *start) 01870 { 01871 int i; 01872 DBUS_CONST_STRING_PREAMBLE (str); 01873 _dbus_assert (end <= real->len); 01874 _dbus_assert (end >= 0); 01875 01876 i = end; 01877 while (i > 0) 01878 { 01879 if (!DBUS_IS_ASCII_WHITE (real->str[i-1])) 01880 break; 01881 --i; 01882 } 01883 01884 _dbus_assert (i >= 0 && (i == 0 || !(DBUS_IS_ASCII_WHITE (real->str[i-1])))); 01885 01886 if (start) 01887 *start = i; 01888 } 01889 01905 dbus_bool_t 01906 _dbus_string_pop_line (DBusString *source, 01907 DBusString *dest) 01908 { 01909 int eol, eol_len; 01910 01911 _dbus_string_set_length (dest, 0); 01912 01913 eol = 0; 01914 eol_len = 0; 01915 if (!_dbus_string_find_eol (source, 0, &eol, &eol_len)) 01916 { 01917 _dbus_assert (eol == _dbus_string_get_length (source)); 01918 if (eol == 0) 01919 { 01920 /* If there's no newline and source has zero length, we're done */ 01921 return FALSE; 01922 } 01923 /* otherwise, the last line of the file has no eol characters */ 01924 } 01925 01926 /* remember eol can be 0 if it's an empty line, but eol_len should not be zero also 01927 * since find_eol returned TRUE 01928 */ 01929 01930 if (!_dbus_string_move_len (source, 0, eol + eol_len, dest, 0)) 01931 return FALSE; 01932 01933 /* remove line ending */ 01934 if (!_dbus_string_set_length (dest, eol)) 01935 { 01936 _dbus_assert_not_reached ("out of memory when shortening a string"); 01937 return FALSE; 01938 } 01939 01940 return TRUE; 01941 } 01942 01943 #ifdef DBUS_BUILD_TESTS 01944 01950 void 01951 _dbus_string_delete_first_word (DBusString *str) 01952 { 01953 int i; 01954 01955 if (_dbus_string_find_blank (str, 0, &i)) 01956 _dbus_string_skip_blank (str, i, &i); 01957 01958 _dbus_string_delete (str, 0, i); 01959 } 01960 #endif 01961 01962 #ifdef DBUS_BUILD_TESTS 01963 01968 void 01969 _dbus_string_delete_leading_blanks (DBusString *str) 01970 { 01971 int i; 01972 01973 _dbus_string_skip_blank (str, 0, &i); 01974 01975 if (i > 0) 01976 _dbus_string_delete (str, 0, i); 01977 } 01978 #endif 01979 01985 void 01986 _dbus_string_chop_white(DBusString *str) 01987 { 01988 int i; 01989 01990 _dbus_string_skip_white (str, 0, &i); 01991 01992 if (i > 0) 01993 _dbus_string_delete (str, 0, i); 01994 01995 _dbus_string_skip_white_reverse (str, _dbus_string_get_length (str), &i); 01996 01997 _dbus_string_set_length (str, i); 01998 } 01999 02009 dbus_bool_t 02010 _dbus_string_equal (const DBusString *a, 02011 const DBusString *b) 02012 { 02013 const unsigned char *ap; 02014 const unsigned char *bp; 02015 const unsigned char *a_end; 02016 const DBusRealString *real_a = (const DBusRealString*) a; 02017 const DBusRealString *real_b = (const DBusRealString*) b; 02018 DBUS_GENERIC_STRING_PREAMBLE (real_a); 02019 DBUS_GENERIC_STRING_PREAMBLE (real_b); 02020 02021 if (real_a->len != real_b->len) 02022 return FALSE; 02023 02024 ap = real_a->str; 02025 bp = real_b->str; 02026 a_end = real_a->str + real_a->len; 02027 while (ap != a_end) 02028 { 02029 if (*ap != *bp) 02030 return FALSE; 02031 02032 ++ap; 02033 ++bp; 02034 } 02035 02036 return TRUE; 02037 } 02038 02052 dbus_bool_t 02053 _dbus_string_equal_len (const DBusString *a, 02054 const DBusString *b, 02055 int len) 02056 { 02057 const unsigned char *ap; 02058 const unsigned char *bp; 02059 const unsigned char *a_end; 02060 const DBusRealString *real_a = (const DBusRealString*) a; 02061 const DBusRealString *real_b = (const DBusRealString*) b; 02062 DBUS_GENERIC_STRING_PREAMBLE (real_a); 02063 DBUS_GENERIC_STRING_PREAMBLE (real_b); 02064 02065 if (real_a->len != real_b->len && 02066 (real_a->len < len || real_b->len < len)) 02067 return FALSE; 02068 02069 ap = real_a->str; 02070 bp = real_b->str; 02071 a_end = real_a->str + MIN (real_a->len, len); 02072 while (ap != a_end) 02073 { 02074 if (*ap != *bp) 02075 return FALSE; 02076 02077 ++ap; 02078 ++bp; 02079 } 02080 02081 return TRUE; 02082 } 02083 02100 dbus_bool_t 02101 _dbus_string_equal_substring (const DBusString *a, 02102 int a_start, 02103 int a_len, 02104 const DBusString *b, 02105 int b_start) 02106 { 02107 const unsigned char *ap; 02108 const unsigned char *bp; 02109 const unsigned char *a_end; 02110 const DBusRealString *real_a = (const DBusRealString*) a; 02111 const DBusRealString *real_b = (const DBusRealString*) b; 02112 DBUS_GENERIC_STRING_PREAMBLE (real_a); 02113 DBUS_GENERIC_STRING_PREAMBLE (real_b); 02114 _dbus_assert (a_start >= 0); 02115 _dbus_assert (a_len >= 0); 02116 _dbus_assert (a_start <= real_a->len); 02117 _dbus_assert (a_len <= real_a->len - a_start); 02118 _dbus_assert (b_start >= 0); 02119 _dbus_assert (b_start <= real_b->len); 02120 02121 if (a_len > real_b->len - b_start) 02122 return FALSE; 02123 02124 ap = real_a->str + a_start; 02125 bp = real_b->str + b_start; 02126 a_end = ap + a_len; 02127 while (ap != a_end) 02128 { 02129 if (*ap != *bp) 02130 return FALSE; 02131 02132 ++ap; 02133 ++bp; 02134 } 02135 02136 _dbus_assert (bp <= (real_b->str + real_b->len)); 02137 02138 return TRUE; 02139 } 02140 02148 dbus_bool_t 02149 _dbus_string_equal_c_str (const DBusString *a, 02150 const char *c_str) 02151 { 02152 const unsigned char *ap; 02153 const unsigned char *bp; 02154 const unsigned char *a_end; 02155 const DBusRealString *real_a = (const DBusRealString*) a; 02156 DBUS_GENERIC_STRING_PREAMBLE (real_a); 02157 _dbus_assert (c_str != NULL); 02158 02159 ap = real_a->str; 02160 bp = (const unsigned char*) c_str; 02161 a_end = real_a->str + real_a->len; 02162 while (ap != a_end && *bp) 02163 { 02164 if (*ap != *bp) 02165 return FALSE; 02166 02167 ++ap; 02168 ++bp; 02169 } 02170 02171 if (ap != a_end || *bp) 02172 return FALSE; 02173 02174 return TRUE; 02175 } 02176 02184 dbus_bool_t 02185 _dbus_string_starts_with_c_str (const DBusString *a, 02186 const char *c_str) 02187 { 02188 const unsigned char *ap; 02189 const unsigned char *bp; 02190 const unsigned char *a_end; 02191 const DBusRealString *real_a = (const DBusRealString*) a; 02192 DBUS_GENERIC_STRING_PREAMBLE (real_a); 02193 _dbus_assert (c_str != NULL); 02194 02195 ap = real_a->str; 02196 bp = (const unsigned char*) c_str; 02197 a_end = real_a->str + real_a->len; 02198 while (ap != a_end && *bp) 02199 { 02200 if (*ap != *bp) 02201 return FALSE; 02202 02203 ++ap; 02204 ++bp; 02205 } 02206 02207 if (*bp == '\0') 02208 return TRUE; 02209 else 02210 return FALSE; 02211 } 02212 02221 dbus_bool_t 02222 _dbus_string_append_byte_as_hex (DBusString *str, 02223 int byte) 02224 { 02225 const char hexdigits[16] = { 02226 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 02227 'a', 'b', 'c', 'd', 'e', 'f' 02228 }; 02229 02230 if (!_dbus_string_append_byte (str, 02231 hexdigits[(byte >> 4)])) 02232 return FALSE; 02233 02234 if (!_dbus_string_append_byte (str, 02235 hexdigits[(byte & 0x0f)])) 02236 { 02237 _dbus_string_set_length (str, 02238 _dbus_string_get_length (str) - 1); 02239 return FALSE; 02240 } 02241 02242 return TRUE; 02243 } 02244 02255 dbus_bool_t 02256 _dbus_string_hex_encode (const DBusString *source, 02257 int start, 02258 DBusString *dest, 02259 int insert_at) 02260 { 02261 DBusString result; 02262 const unsigned char *p; 02263 const unsigned char *end; 02264 dbus_bool_t retval; 02265 02266 _dbus_assert (start <= _dbus_string_get_length (source)); 02267 02268 if (!_dbus_string_init (&result)) 02269 return FALSE; 02270 02271 retval = FALSE; 02272 02273 p = (const unsigned char*) _dbus_string_get_const_data (source); 02274 end = p + _dbus_string_get_length (source); 02275 p += start; 02276 02277 while (p != end) 02278 { 02279 if (!_dbus_string_append_byte_as_hex (&result, *p)) 02280 goto out; 02281 02282 ++p; 02283 } 02284 02285 if (!_dbus_string_move (&result, 0, dest, insert_at)) 02286 goto out; 02287 02288 retval = TRUE; 02289 02290 out: 02291 _dbus_string_free (&result); 02292 return retval; 02293 } 02294 02305 dbus_bool_t 02306 _dbus_string_hex_decode (const DBusString *source, 02307 int start, 02308 int *end_return, 02309 DBusString *dest, 02310 int insert_at) 02311 { 02312 DBusString result; 02313 const unsigned char *p; 02314 const unsigned char *end; 02315 dbus_bool_t retval; 02316 dbus_bool_t high_bits; 02317 02318 _dbus_assert (start <= _dbus_string_get_length (source)); 02319 02320 if (!_dbus_string_init (&result)) 02321 return FALSE; 02322 02323 retval = FALSE; 02324 02325 high_bits = TRUE; 02326 p = (const unsigned char*) _dbus_string_get_const_data (source); 02327 end = p + _dbus_string_get_length (source); 02328 p += start; 02329 02330 while (p != end) 02331 { 02332 unsigned int val; 02333 02334 switch (*p) 02335 { 02336 case '0': 02337 val = 0; 02338 break; 02339 case '1': 02340 val = 1; 02341 break; 02342 case '2': 02343 val = 2; 02344 break; 02345 case '3': 02346 val = 3; 02347 break; 02348 case '4': 02349 val = 4; 02350 break; 02351 case '5': 02352 val = 5; 02353 break; 02354 case '6': 02355 val = 6; 02356 break; 02357 case '7': 02358 val = 7; 02359 break; 02360 case '8': 02361 val = 8; 02362 break; 02363 case '9': 02364 val = 9; 02365 break; 02366 case 'a': 02367 case 'A': 02368 val = 10; 02369 break; 02370 case 'b': 02371 case 'B': 02372 val = 11; 02373 break; 02374 case 'c': 02375 case 'C': 02376 val = 12; 02377 break; 02378 case 'd': 02379 case 'D': 02380 val = 13; 02381 break; 02382 case 'e': 02383 case 'E': 02384 val = 14; 02385 break; 02386 case 'f': 02387 case 'F': 02388 val = 15; 02389 break; 02390 default: 02391 goto done; 02392 } 02393 02394 if (high_bits) 02395 { 02396 if (!_dbus_string_append_byte (&result, 02397 val << 4)) 02398 goto out; 02399 } 02400 else 02401 { 02402 int len; 02403 unsigned char b; 02404 02405 len = _dbus_string_get_length (&result); 02406 02407 b = _dbus_string_get_byte (&result, len - 1); 02408 02409 b |= val; 02410 02411 _dbus_string_set_byte (&result, len - 1, b); 02412 } 02413 02414 high_bits = !high_bits; 02415 02416 ++p; 02417 } 02418 02419 done: 02420 if (!_dbus_string_move (&result, 0, dest, insert_at)) 02421 goto out; 02422 02423 if (end_return) 02424 *end_return = p - (const unsigned char*) _dbus_string_get_const_data (source); 02425 02426 retval = TRUE; 02427 02428 out: 02429 _dbus_string_free (&result); 02430 return retval; 02431 } 02432 02446 dbus_bool_t 02447 _dbus_string_validate_ascii (const DBusString *str, 02448 int start, 02449 int len) 02450 { 02451 const unsigned char *s; 02452 const unsigned char *end; 02453 DBUS_CONST_STRING_PREAMBLE (str); 02454 _dbus_assert (start >= 0); 02455 _dbus_assert (start <= real->len); 02456 _dbus_assert (len >= 0); 02457 02458 if (len > real->len - start) 02459 return FALSE; 02460 02461 s = real->str + start; 02462 end = s + len; 02463 while (s != end) 02464 { 02465 if (_DBUS_UNLIKELY (!_DBUS_ISASCII (*s))) 02466 return FALSE; 02467 02468 ++s; 02469 } 02470 02471 return TRUE; 02472 } 02473 02481 void 02482 _dbus_string_tolower_ascii (const DBusString *str, 02483 int start, 02484 int len) 02485 { 02486 unsigned char *s; 02487 unsigned char *end; 02488 DBUS_STRING_PREAMBLE (str); 02489 _dbus_assert (start >= 0); 02490 _dbus_assert (start <= real->len); 02491 _dbus_assert (len >= 0); 02492 _dbus_assert (len <= real->len - start); 02493 02494 s = real->str + start; 02495 end = s + len; 02496 02497 while (s != end) 02498 { 02499 if (*s >= 'A' && *s <= 'Z') 02500 *s += 'a' - 'A'; 02501 ++s; 02502 } 02503 } 02504 02512 void 02513 _dbus_string_toupper_ascii (const DBusString *str, 02514 int start, 02515 int len) 02516 { 02517 unsigned char *s; 02518 unsigned char *end; 02519 DBUS_STRING_PREAMBLE (str); 02520 _dbus_assert (start >= 0); 02521 _dbus_assert (start <= real->len); 02522 _dbus_assert (len >= 0); 02523 _dbus_assert (len <= real->len - start); 02524 02525 s = real->str + start; 02526 end = s + len; 02527 02528 while (s != end) 02529 { 02530 if (*s >= 'a' && *s <= 'z') 02531 *s += 'A' - 'a'; 02532 ++s; 02533 } 02534 } 02535 02551 dbus_bool_t 02552 _dbus_string_validate_utf8 (const DBusString *str, 02553 int start, 02554 int len) 02555 { 02556 const unsigned char *p; 02557 const unsigned char *end; 02558 DBUS_CONST_STRING_PREAMBLE (str); 02559 _dbus_assert (start >= 0); 02560 _dbus_assert (start <= real->len); 02561 _dbus_assert (len >= 0); 02562 02563 /* we are doing _DBUS_UNLIKELY() here which might be 02564 * dubious in a generic library like GLib, but in D-Bus 02565 * we know we're validating messages and that it would 02566 * only be evil/broken apps that would have invalid 02567 * UTF-8. Also, this function seems to be a performance 02568 * bottleneck in profiles. 02569 */ 02570 02571 if (_DBUS_UNLIKELY (len > real->len - start)) 02572 return FALSE; 02573 02574 p = real->str + start; 02575 end = p + len; 02576 02577 while (p < end) 02578 { 02579 int i, mask, char_len; 02580 dbus_unichar_t result; 02581 02582 /* nul bytes considered invalid */ 02583 if (*p == '\0') 02584 break; 02585 02586 /* Special-case ASCII; this makes us go a lot faster in 02587 * D-Bus profiles where we are typically validating 02588 * function names and such. We have to know that 02589 * all following checks will pass for ASCII though, 02590 * comments follow ... 02591 */ 02592 if (*p < 128) 02593 { 02594 ++p; 02595 continue; 02596 } 02597 02598 UTF8_COMPUTE (*p, mask, char_len); 02599 02600 if (_DBUS_UNLIKELY (char_len == 0)) /* ASCII: char_len == 1 */ 02601 break; 02602 02603 /* check that the expected number of bytes exists in the remaining length */ 02604 if (_DBUS_UNLIKELY ((end - p) < char_len)) /* ASCII: p < end and char_len == 1 */ 02605 break; 02606 02607 UTF8_GET (result, p, i, mask, char_len); 02608 02609 /* Check for overlong UTF-8 */ 02610 if (_DBUS_UNLIKELY (UTF8_LENGTH (result) != char_len)) /* ASCII: UTF8_LENGTH == 1 */ 02611 break; 02612 #if 0 02613 /* The UNICODE_VALID check below will catch this */ 02614 if (_DBUS_UNLIKELY (result == (dbus_unichar_t)-1)) /* ASCII: result = ascii value */ 02615 break; 02616 #endif 02617 02618 if (_DBUS_UNLIKELY (!UNICODE_VALID (result))) /* ASCII: always valid */ 02619 break; 02620 02621 /* UNICODE_VALID should have caught it */ 02622 _dbus_assert (result != (dbus_unichar_t)-1); 02623 02624 p += char_len; 02625 } 02626 02627 /* See that we covered the entire length if a length was 02628 * passed in 02629 */ 02630 if (_DBUS_UNLIKELY (p != end)) 02631 return FALSE; 02632 else 02633 return TRUE; 02634 } 02635 02649 dbus_bool_t 02650 _dbus_string_validate_nul (const DBusString *str, 02651 int start, 02652 int len) 02653 { 02654 const unsigned char *s; 02655 const unsigned char *end; 02656 DBUS_CONST_STRING_PREAMBLE (str); 02657 _dbus_assert (start >= 0); 02658 _dbus_assert (len >= 0); 02659 _dbus_assert (start <= real->len); 02660 02661 if (len > real->len - start) 02662 return FALSE; 02663 02664 s = real->str + start; 02665 end = s + len; 02666 while (s != end) 02667 { 02668 if (_DBUS_UNLIKELY (*s != '\0')) 02669 return FALSE; 02670 ++s; 02671 } 02672 02673 return TRUE; 02674 } 02675 02681 void 02682 _dbus_string_zero (DBusString *str) 02683 { 02684 DBUS_STRING_PREAMBLE (str); 02685 02686 memset (real->str - real->align_offset, '\0', real->allocated); 02687 } 02690 /* tests are in dbus-string-util.c */