D-Bus
1.6.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 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 01588 #define UNICODE_VALID(Char) \ 01589 ((Char) < 0x110000 && \ 01590 (((Char) & 0xFFFFF800) != 0xD800) && \ 01591 ((Char) < 0xFDD0 || (Char) > 0xFDEF) && \ 01592 ((Char) & 0xFFFE) != 0xFFFE) 01593 01608 dbus_bool_t 01609 _dbus_string_find (const DBusString *str, 01610 int start, 01611 const char *substr, 01612 int *found) 01613 { 01614 return _dbus_string_find_to (str, start, 01615 ((const DBusRealString*)str)->len, 01616 substr, found); 01617 } 01618 01631 dbus_bool_t 01632 _dbus_string_find_eol (const DBusString *str, 01633 int start, 01634 int *found, 01635 int *found_len) 01636 { 01637 int i; 01638 01639 DBUS_CONST_STRING_PREAMBLE (str); 01640 _dbus_assert (start <= real->len); 01641 _dbus_assert (start >= 0); 01642 01643 i = start; 01644 while (i < real->len) 01645 { 01646 if (real->str[i] == '\r') 01647 { 01648 if ((i+1) < real->len && real->str[i+1] == '\n') /* "\r\n" */ 01649 { 01650 if (found) 01651 *found = i; 01652 if (found_len) 01653 *found_len = 2; 01654 return TRUE; 01655 } 01656 else /* only "\r" */ 01657 { 01658 if (found) 01659 *found = i; 01660 if (found_len) 01661 *found_len = 1; 01662 return TRUE; 01663 } 01664 } 01665 else if (real->str[i] == '\n') /* only "\n" */ 01666 { 01667 if (found) 01668 *found = i; 01669 if (found_len) 01670 *found_len = 1; 01671 return TRUE; 01672 } 01673 ++i; 01674 } 01675 01676 if (found) 01677 *found = real->len; 01678 01679 if (found_len) 01680 *found_len = 0; 01681 01682 return FALSE; 01683 } 01684 01701 dbus_bool_t 01702 _dbus_string_find_to (const DBusString *str, 01703 int start, 01704 int end, 01705 const char *substr, 01706 int *found) 01707 { 01708 int i; 01709 DBUS_CONST_STRING_PREAMBLE (str); 01710 _dbus_assert (substr != NULL); 01711 _dbus_assert (start <= real->len); 01712 _dbus_assert (start >= 0); 01713 _dbus_assert (substr != NULL); 01714 _dbus_assert (end <= real->len); 01715 _dbus_assert (start <= end); 01716 01717 /* we always "find" an empty string */ 01718 if (*substr == '\0') 01719 { 01720 if (found) 01721 *found = start; 01722 return TRUE; 01723 } 01724 01725 i = start; 01726 while (i < end) 01727 { 01728 if (real->str[i] == substr[0]) 01729 { 01730 int j = i + 1; 01731 01732 while (j < end) 01733 { 01734 if (substr[j - i] == '\0') 01735 break; 01736 else if (real->str[j] != substr[j - i]) 01737 break; 01738 01739 ++j; 01740 } 01741 01742 if (substr[j - i] == '\0') 01743 { 01744 if (found) 01745 *found = i; 01746 return TRUE; 01747 } 01748 } 01749 01750 ++i; 01751 } 01752 01753 if (found) 01754 *found = end; 01755 01756 return FALSE; 01757 } 01758 01769 dbus_bool_t 01770 _dbus_string_find_blank (const DBusString *str, 01771 int start, 01772 int *found) 01773 { 01774 int i; 01775 DBUS_CONST_STRING_PREAMBLE (str); 01776 _dbus_assert (start <= real->len); 01777 _dbus_assert (start >= 0); 01778 01779 i = start; 01780 while (i < real->len) 01781 { 01782 if (real->str[i] == ' ' || 01783 real->str[i] == '\t') 01784 { 01785 if (found) 01786 *found = i; 01787 return TRUE; 01788 } 01789 01790 ++i; 01791 } 01792 01793 if (found) 01794 *found = real->len; 01795 01796 return FALSE; 01797 } 01798 01807 void 01808 _dbus_string_skip_blank (const DBusString *str, 01809 int start, 01810 int *end) 01811 { 01812 int i; 01813 DBUS_CONST_STRING_PREAMBLE (str); 01814 _dbus_assert (start <= real->len); 01815 _dbus_assert (start >= 0); 01816 01817 i = start; 01818 while (i < real->len) 01819 { 01820 if (!DBUS_IS_ASCII_BLANK (real->str[i])) 01821 break; 01822 01823 ++i; 01824 } 01825 01826 _dbus_assert (i == real->len || !DBUS_IS_ASCII_WHITE (real->str[i])); 01827 01828 if (end) 01829 *end = i; 01830 } 01831 01832 01841 void 01842 _dbus_string_skip_white (const DBusString *str, 01843 int start, 01844 int *end) 01845 { 01846 int i; 01847 DBUS_CONST_STRING_PREAMBLE (str); 01848 _dbus_assert (start <= real->len); 01849 _dbus_assert (start >= 0); 01850 01851 i = start; 01852 while (i < real->len) 01853 { 01854 if (!DBUS_IS_ASCII_WHITE (real->str[i])) 01855 break; 01856 01857 ++i; 01858 } 01859 01860 _dbus_assert (i == real->len || !(DBUS_IS_ASCII_WHITE (real->str[i]))); 01861 01862 if (end) 01863 *end = i; 01864 } 01865 01874 void 01875 _dbus_string_skip_white_reverse (const DBusString *str, 01876 int end, 01877 int *start) 01878 { 01879 int i; 01880 DBUS_CONST_STRING_PREAMBLE (str); 01881 _dbus_assert (end <= real->len); 01882 _dbus_assert (end >= 0); 01883 01884 i = end; 01885 while (i > 0) 01886 { 01887 if (!DBUS_IS_ASCII_WHITE (real->str[i-1])) 01888 break; 01889 --i; 01890 } 01891 01892 _dbus_assert (i >= 0 && (i == 0 || !(DBUS_IS_ASCII_WHITE (real->str[i-1])))); 01893 01894 if (start) 01895 *start = i; 01896 } 01897 01913 dbus_bool_t 01914 _dbus_string_pop_line (DBusString *source, 01915 DBusString *dest) 01916 { 01917 int eol, eol_len; 01918 01919 _dbus_string_set_length (dest, 0); 01920 01921 eol = 0; 01922 eol_len = 0; 01923 if (!_dbus_string_find_eol (source, 0, &eol, &eol_len)) 01924 { 01925 _dbus_assert (eol == _dbus_string_get_length (source)); 01926 if (eol == 0) 01927 { 01928 /* If there's no newline and source has zero length, we're done */ 01929 return FALSE; 01930 } 01931 /* otherwise, the last line of the file has no eol characters */ 01932 } 01933 01934 /* remember eol can be 0 if it's an empty line, but eol_len should not be zero also 01935 * since find_eol returned TRUE 01936 */ 01937 01938 if (!_dbus_string_move_len (source, 0, eol + eol_len, dest, 0)) 01939 return FALSE; 01940 01941 /* remove line ending */ 01942 if (!_dbus_string_set_length (dest, eol)) 01943 { 01944 _dbus_assert_not_reached ("out of memory when shortening a string"); 01945 return FALSE; 01946 } 01947 01948 return TRUE; 01949 } 01950 01951 #ifdef DBUS_BUILD_TESTS 01952 01958 void 01959 _dbus_string_delete_first_word (DBusString *str) 01960 { 01961 int i; 01962 01963 if (_dbus_string_find_blank (str, 0, &i)) 01964 _dbus_string_skip_blank (str, i, &i); 01965 01966 _dbus_string_delete (str, 0, i); 01967 } 01968 #endif 01969 01970 #ifdef DBUS_BUILD_TESTS 01971 01976 void 01977 _dbus_string_delete_leading_blanks (DBusString *str) 01978 { 01979 int i; 01980 01981 _dbus_string_skip_blank (str, 0, &i); 01982 01983 if (i > 0) 01984 _dbus_string_delete (str, 0, i); 01985 } 01986 #endif 01987 01993 void 01994 _dbus_string_chop_white(DBusString *str) 01995 { 01996 int i; 01997 01998 _dbus_string_skip_white (str, 0, &i); 01999 02000 if (i > 0) 02001 _dbus_string_delete (str, 0, i); 02002 02003 _dbus_string_skip_white_reverse (str, _dbus_string_get_length (str), &i); 02004 02005 _dbus_string_set_length (str, i); 02006 } 02007 02017 dbus_bool_t 02018 _dbus_string_equal (const DBusString *a, 02019 const DBusString *b) 02020 { 02021 const unsigned char *ap; 02022 const unsigned char *bp; 02023 const unsigned char *a_end; 02024 const DBusRealString *real_a = (const DBusRealString*) a; 02025 const DBusRealString *real_b = (const DBusRealString*) b; 02026 DBUS_GENERIC_STRING_PREAMBLE (real_a); 02027 DBUS_GENERIC_STRING_PREAMBLE (real_b); 02028 02029 if (real_a->len != real_b->len) 02030 return FALSE; 02031 02032 ap = real_a->str; 02033 bp = real_b->str; 02034 a_end = real_a->str + real_a->len; 02035 while (ap != a_end) 02036 { 02037 if (*ap != *bp) 02038 return FALSE; 02039 02040 ++ap; 02041 ++bp; 02042 } 02043 02044 return TRUE; 02045 } 02046 02060 dbus_bool_t 02061 _dbus_string_equal_len (const DBusString *a, 02062 const DBusString *b, 02063 int len) 02064 { 02065 const unsigned char *ap; 02066 const unsigned char *bp; 02067 const unsigned char *a_end; 02068 const DBusRealString *real_a = (const DBusRealString*) a; 02069 const DBusRealString *real_b = (const DBusRealString*) b; 02070 DBUS_GENERIC_STRING_PREAMBLE (real_a); 02071 DBUS_GENERIC_STRING_PREAMBLE (real_b); 02072 02073 if (real_a->len != real_b->len && 02074 (real_a->len < len || real_b->len < len)) 02075 return FALSE; 02076 02077 ap = real_a->str; 02078 bp = real_b->str; 02079 a_end = real_a->str + MIN (real_a->len, len); 02080 while (ap != a_end) 02081 { 02082 if (*ap != *bp) 02083 return FALSE; 02084 02085 ++ap; 02086 ++bp; 02087 } 02088 02089 return TRUE; 02090 } 02091 02108 dbus_bool_t 02109 _dbus_string_equal_substring (const DBusString *a, 02110 int a_start, 02111 int a_len, 02112 const DBusString *b, 02113 int b_start) 02114 { 02115 const unsigned char *ap; 02116 const unsigned char *bp; 02117 const unsigned char *a_end; 02118 const DBusRealString *real_a = (const DBusRealString*) a; 02119 const DBusRealString *real_b = (const DBusRealString*) b; 02120 DBUS_GENERIC_STRING_PREAMBLE (real_a); 02121 DBUS_GENERIC_STRING_PREAMBLE (real_b); 02122 _dbus_assert (a_start >= 0); 02123 _dbus_assert (a_len >= 0); 02124 _dbus_assert (a_start <= real_a->len); 02125 _dbus_assert (a_len <= real_a->len - a_start); 02126 _dbus_assert (b_start >= 0); 02127 _dbus_assert (b_start <= real_b->len); 02128 02129 if (a_len > real_b->len - b_start) 02130 return FALSE; 02131 02132 ap = real_a->str + a_start; 02133 bp = real_b->str + b_start; 02134 a_end = ap + a_len; 02135 while (ap != a_end) 02136 { 02137 if (*ap != *bp) 02138 return FALSE; 02139 02140 ++ap; 02141 ++bp; 02142 } 02143 02144 _dbus_assert (bp <= (real_b->str + real_b->len)); 02145 02146 return TRUE; 02147 } 02148 02156 dbus_bool_t 02157 _dbus_string_equal_c_str (const DBusString *a, 02158 const char *c_str) 02159 { 02160 const unsigned char *ap; 02161 const unsigned char *bp; 02162 const unsigned char *a_end; 02163 const DBusRealString *real_a = (const DBusRealString*) a; 02164 DBUS_GENERIC_STRING_PREAMBLE (real_a); 02165 _dbus_assert (c_str != NULL); 02166 02167 ap = real_a->str; 02168 bp = (const unsigned char*) c_str; 02169 a_end = real_a->str + real_a->len; 02170 while (ap != a_end && *bp) 02171 { 02172 if (*ap != *bp) 02173 return FALSE; 02174 02175 ++ap; 02176 ++bp; 02177 } 02178 02179 if (ap != a_end || *bp) 02180 return FALSE; 02181 02182 return TRUE; 02183 } 02184 02192 dbus_bool_t 02193 _dbus_string_starts_with_c_str (const DBusString *a, 02194 const char *c_str) 02195 { 02196 const unsigned char *ap; 02197 const unsigned char *bp; 02198 const unsigned char *a_end; 02199 const DBusRealString *real_a = (const DBusRealString*) a; 02200 DBUS_GENERIC_STRING_PREAMBLE (real_a); 02201 _dbus_assert (c_str != NULL); 02202 02203 ap = real_a->str; 02204 bp = (const unsigned char*) c_str; 02205 a_end = real_a->str + real_a->len; 02206 while (ap != a_end && *bp) 02207 { 02208 if (*ap != *bp) 02209 return FALSE; 02210 02211 ++ap; 02212 ++bp; 02213 } 02214 02215 if (*bp == '\0') 02216 return TRUE; 02217 else 02218 return FALSE; 02219 } 02220 02229 dbus_bool_t 02230 _dbus_string_append_byte_as_hex (DBusString *str, 02231 int byte) 02232 { 02233 const char hexdigits[16] = { 02234 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 02235 'a', 'b', 'c', 'd', 'e', 'f' 02236 }; 02237 02238 if (!_dbus_string_append_byte (str, 02239 hexdigits[(byte >> 4)])) 02240 return FALSE; 02241 02242 if (!_dbus_string_append_byte (str, 02243 hexdigits[(byte & 0x0f)])) 02244 { 02245 _dbus_string_set_length (str, 02246 _dbus_string_get_length (str) - 1); 02247 return FALSE; 02248 } 02249 02250 return TRUE; 02251 } 02252 02263 dbus_bool_t 02264 _dbus_string_hex_encode (const DBusString *source, 02265 int start, 02266 DBusString *dest, 02267 int insert_at) 02268 { 02269 DBusString result; 02270 const unsigned char *p; 02271 const unsigned char *end; 02272 dbus_bool_t retval; 02273 02274 _dbus_assert (start <= _dbus_string_get_length (source)); 02275 02276 if (!_dbus_string_init (&result)) 02277 return FALSE; 02278 02279 retval = FALSE; 02280 02281 p = (const unsigned char*) _dbus_string_get_const_data (source); 02282 end = p + _dbus_string_get_length (source); 02283 p += start; 02284 02285 while (p != end) 02286 { 02287 if (!_dbus_string_append_byte_as_hex (&result, *p)) 02288 goto out; 02289 02290 ++p; 02291 } 02292 02293 if (!_dbus_string_move (&result, 0, dest, insert_at)) 02294 goto out; 02295 02296 retval = TRUE; 02297 02298 out: 02299 _dbus_string_free (&result); 02300 return retval; 02301 } 02302 02313 dbus_bool_t 02314 _dbus_string_hex_decode (const DBusString *source, 02315 int start, 02316 int *end_return, 02317 DBusString *dest, 02318 int insert_at) 02319 { 02320 DBusString result; 02321 const unsigned char *p; 02322 const unsigned char *end; 02323 dbus_bool_t retval; 02324 dbus_bool_t high_bits; 02325 02326 _dbus_assert (start <= _dbus_string_get_length (source)); 02327 02328 if (!_dbus_string_init (&result)) 02329 return FALSE; 02330 02331 retval = FALSE; 02332 02333 high_bits = TRUE; 02334 p = (const unsigned char*) _dbus_string_get_const_data (source); 02335 end = p + _dbus_string_get_length (source); 02336 p += start; 02337 02338 while (p != end) 02339 { 02340 unsigned int val; 02341 02342 switch (*p) 02343 { 02344 case '0': 02345 val = 0; 02346 break; 02347 case '1': 02348 val = 1; 02349 break; 02350 case '2': 02351 val = 2; 02352 break; 02353 case '3': 02354 val = 3; 02355 break; 02356 case '4': 02357 val = 4; 02358 break; 02359 case '5': 02360 val = 5; 02361 break; 02362 case '6': 02363 val = 6; 02364 break; 02365 case '7': 02366 val = 7; 02367 break; 02368 case '8': 02369 val = 8; 02370 break; 02371 case '9': 02372 val = 9; 02373 break; 02374 case 'a': 02375 case 'A': 02376 val = 10; 02377 break; 02378 case 'b': 02379 case 'B': 02380 val = 11; 02381 break; 02382 case 'c': 02383 case 'C': 02384 val = 12; 02385 break; 02386 case 'd': 02387 case 'D': 02388 val = 13; 02389 break; 02390 case 'e': 02391 case 'E': 02392 val = 14; 02393 break; 02394 case 'f': 02395 case 'F': 02396 val = 15; 02397 break; 02398 default: 02399 goto done; 02400 } 02401 02402 if (high_bits) 02403 { 02404 if (!_dbus_string_append_byte (&result, 02405 val << 4)) 02406 goto out; 02407 } 02408 else 02409 { 02410 int len; 02411 unsigned char b; 02412 02413 len = _dbus_string_get_length (&result); 02414 02415 b = _dbus_string_get_byte (&result, len - 1); 02416 02417 b |= val; 02418 02419 _dbus_string_set_byte (&result, len - 1, b); 02420 } 02421 02422 high_bits = !high_bits; 02423 02424 ++p; 02425 } 02426 02427 done: 02428 if (!_dbus_string_move (&result, 0, dest, insert_at)) 02429 goto out; 02430 02431 if (end_return) 02432 *end_return = p - (const unsigned char*) _dbus_string_get_const_data (source); 02433 02434 retval = TRUE; 02435 02436 out: 02437 _dbus_string_free (&result); 02438 return retval; 02439 } 02440 02454 dbus_bool_t 02455 _dbus_string_validate_ascii (const DBusString *str, 02456 int start, 02457 int len) 02458 { 02459 const unsigned char *s; 02460 const unsigned char *end; 02461 DBUS_CONST_STRING_PREAMBLE (str); 02462 _dbus_assert (start >= 0); 02463 _dbus_assert (start <= real->len); 02464 _dbus_assert (len >= 0); 02465 02466 if (len > real->len - start) 02467 return FALSE; 02468 02469 s = real->str + start; 02470 end = s + len; 02471 while (s != end) 02472 { 02473 if (_DBUS_UNLIKELY (!_DBUS_ISASCII (*s))) 02474 return FALSE; 02475 02476 ++s; 02477 } 02478 02479 return TRUE; 02480 } 02481 02489 void 02490 _dbus_string_tolower_ascii (const DBusString *str, 02491 int start, 02492 int len) 02493 { 02494 unsigned char *s; 02495 unsigned char *end; 02496 DBUS_STRING_PREAMBLE (str); 02497 _dbus_assert (start >= 0); 02498 _dbus_assert (start <= real->len); 02499 _dbus_assert (len >= 0); 02500 _dbus_assert (len <= real->len - start); 02501 02502 s = real->str + start; 02503 end = s + len; 02504 02505 while (s != end) 02506 { 02507 if (*s >= 'A' && *s <= 'Z') 02508 *s += 'a' - 'A'; 02509 ++s; 02510 } 02511 } 02512 02520 void 02521 _dbus_string_toupper_ascii (const DBusString *str, 02522 int start, 02523 int len) 02524 { 02525 unsigned char *s; 02526 unsigned char *end; 02527 DBUS_STRING_PREAMBLE (str); 02528 _dbus_assert (start >= 0); 02529 _dbus_assert (start <= real->len); 02530 _dbus_assert (len >= 0); 02531 _dbus_assert (len <= real->len - start); 02532 02533 s = real->str + start; 02534 end = s + len; 02535 02536 while (s != end) 02537 { 02538 if (*s >= 'a' && *s <= 'z') 02539 *s += 'A' - 'a'; 02540 ++s; 02541 } 02542 } 02543 02559 dbus_bool_t 02560 _dbus_string_validate_utf8 (const DBusString *str, 02561 int start, 02562 int len) 02563 { 02564 const unsigned char *p; 02565 const unsigned char *end; 02566 DBUS_CONST_STRING_PREAMBLE (str); 02567 _dbus_assert (start >= 0); 02568 _dbus_assert (start <= real->len); 02569 _dbus_assert (len >= 0); 02570 02571 /* we are doing _DBUS_UNLIKELY() here which might be 02572 * dubious in a generic library like GLib, but in D-Bus 02573 * we know we're validating messages and that it would 02574 * only be evil/broken apps that would have invalid 02575 * UTF-8. Also, this function seems to be a performance 02576 * bottleneck in profiles. 02577 */ 02578 02579 if (_DBUS_UNLIKELY (len > real->len - start)) 02580 return FALSE; 02581 02582 p = real->str + start; 02583 end = p + len; 02584 02585 while (p < end) 02586 { 02587 int i, mask, char_len; 02588 dbus_unichar_t result; 02589 02590 /* nul bytes considered invalid */ 02591 if (*p == '\0') 02592 break; 02593 02594 /* Special-case ASCII; this makes us go a lot faster in 02595 * D-Bus profiles where we are typically validating 02596 * function names and such. We have to know that 02597 * all following checks will pass for ASCII though, 02598 * comments follow ... 02599 */ 02600 if (*p < 128) 02601 { 02602 ++p; 02603 continue; 02604 } 02605 02606 UTF8_COMPUTE (*p, mask, char_len); 02607 02608 if (_DBUS_UNLIKELY (char_len == 0)) /* ASCII: char_len == 1 */ 02609 break; 02610 02611 /* check that the expected number of bytes exists in the remaining length */ 02612 if (_DBUS_UNLIKELY ((end - p) < char_len)) /* ASCII: p < end and char_len == 1 */ 02613 break; 02614 02615 UTF8_GET (result, p, i, mask, char_len); 02616 02617 /* Check for overlong UTF-8 */ 02618 if (_DBUS_UNLIKELY (UTF8_LENGTH (result) != char_len)) /* ASCII: UTF8_LENGTH == 1 */ 02619 break; 02620 #if 0 02621 /* The UNICODE_VALID check below will catch this */ 02622 if (_DBUS_UNLIKELY (result == (dbus_unichar_t)-1)) /* ASCII: result = ascii value */ 02623 break; 02624 #endif 02625 02626 if (_DBUS_UNLIKELY (!UNICODE_VALID (result))) /* ASCII: always valid */ 02627 break; 02628 02629 /* UNICODE_VALID should have caught it */ 02630 _dbus_assert (result != (dbus_unichar_t)-1); 02631 02632 p += char_len; 02633 } 02634 02635 /* See that we covered the entire length if a length was 02636 * passed in 02637 */ 02638 if (_DBUS_UNLIKELY (p != end)) 02639 return FALSE; 02640 else 02641 return TRUE; 02642 } 02643 02657 dbus_bool_t 02658 _dbus_string_validate_nul (const DBusString *str, 02659 int start, 02660 int len) 02661 { 02662 const unsigned char *s; 02663 const unsigned char *end; 02664 DBUS_CONST_STRING_PREAMBLE (str); 02665 _dbus_assert (start >= 0); 02666 _dbus_assert (len >= 0); 02667 _dbus_assert (start <= real->len); 02668 02669 if (len > real->len - start) 02670 return FALSE; 02671 02672 s = real->str + start; 02673 end = s + len; 02674 while (s != end) 02675 { 02676 if (_DBUS_UNLIKELY (*s != '\0')) 02677 return FALSE; 02678 ++s; 02679 } 02680 02681 return TRUE; 02682 } 02683 02689 void 02690 _dbus_string_zero (DBusString *str) 02691 { 02692 DBUS_STRING_PREAMBLE (str); 02693 02694 memset (real->str - real->align_offset, '\0', real->allocated); 02695 } 02698 /* tests are in dbus-string-util.c */