|
D-Bus
1.6.30
|
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 00250 /* so it's safe if @p str returned by a failed 00251 * _dbus_string_init call 00252 * Bug: https://bugs.freedesktop.org/show_bug.cgi?id=65959 00253 */ 00254 if (real->str == NULL) 00255 return; 00256 00257 dbus_free (real->str - real->align_offset); 00258 00259 real->invalid = TRUE; 00260 } 00261 00262 static dbus_bool_t 00263 compact (DBusRealString *real, 00264 int max_waste) 00265 { 00266 unsigned char *new_str; 00267 int new_allocated; 00268 int waste; 00269 00270 waste = real->allocated - (real->len + _DBUS_STRING_ALLOCATION_PADDING); 00271 00272 if (waste <= max_waste) 00273 return TRUE; 00274 00275 new_allocated = real->len + _DBUS_STRING_ALLOCATION_PADDING; 00276 00277 new_str = dbus_realloc (real->str - real->align_offset, new_allocated); 00278 if (_DBUS_UNLIKELY (new_str == NULL)) 00279 return FALSE; 00280 00281 real->str = new_str + real->align_offset; 00282 real->allocated = new_allocated; 00283 fixup_alignment (real); 00284 00285 return TRUE; 00286 } 00287 00288 #ifdef DBUS_BUILD_TESTS 00289 /* Not using this feature at the moment, 00290 * so marked DBUS_BUILD_TESTS-only 00291 */ 00301 void 00302 _dbus_string_lock (DBusString *str) 00303 { 00304 DBUS_LOCKED_STRING_PREAMBLE (str); /* can lock multiple times */ 00305 00306 real->locked = TRUE; 00307 00308 /* Try to realloc to avoid excess memory usage, since 00309 * we know we won't change the string further 00310 */ 00311 #define MAX_WASTE 48 00312 compact (real, MAX_WASTE); 00313 } 00314 #endif /* DBUS_BUILD_TESTS */ 00315 00316 static dbus_bool_t 00317 reallocate_for_length (DBusRealString *real, 00318 int new_length) 00319 { 00320 int new_allocated; 00321 unsigned char *new_str; 00322 00323 /* at least double our old allocation to avoid O(n), avoiding 00324 * overflow 00325 */ 00326 if (real->allocated > (_DBUS_STRING_MAX_LENGTH + _DBUS_STRING_ALLOCATION_PADDING) / 2) 00327 new_allocated = _DBUS_STRING_MAX_LENGTH + _DBUS_STRING_ALLOCATION_PADDING; 00328 else 00329 new_allocated = real->allocated * 2; 00330 00331 /* if you change the code just above here, run the tests without 00332 * the following assert-only hack before you commit 00333 */ 00334 /* This is keyed off asserts in addition to tests so when you 00335 * disable asserts to profile, you don't get this destroyer 00336 * of profiles. 00337 */ 00338 #ifdef DBUS_DISABLE_ASSERT 00339 #else 00340 #ifdef DBUS_BUILD_TESTS 00341 new_allocated = 0; /* ensure a realloc every time so that we go 00342 * through all malloc failure codepaths 00343 */ 00344 #endif /* DBUS_BUILD_TESTS */ 00345 #endif /* !DBUS_DISABLE_ASSERT */ 00346 00347 /* But be sure we always alloc at least space for the new length */ 00348 new_allocated = MAX (new_allocated, 00349 new_length + _DBUS_STRING_ALLOCATION_PADDING); 00350 00351 _dbus_assert (new_allocated >= real->allocated); /* code relies on this */ 00352 new_str = dbus_realloc (real->str - real->align_offset, new_allocated); 00353 if (_DBUS_UNLIKELY (new_str == NULL)) 00354 return FALSE; 00355 00356 real->str = new_str + real->align_offset; 00357 real->allocated = new_allocated; 00358 fixup_alignment (real); 00359 00360 return TRUE; 00361 } 00362 00374 dbus_bool_t 00375 _dbus_string_compact (DBusString *str, 00376 int max_waste) 00377 { 00378 DBUS_STRING_PREAMBLE (str); 00379 00380 return compact (real, max_waste); 00381 } 00382 00383 static dbus_bool_t 00384 set_length (DBusRealString *real, 00385 int new_length) 00386 { 00387 /* Note, we are setting the length not including nul termination */ 00388 00389 /* exceeding max length is the same as failure to allocate memory */ 00390 if (_DBUS_UNLIKELY (new_length > _DBUS_STRING_MAX_LENGTH)) 00391 return FALSE; 00392 else if (new_length > (real->allocated - _DBUS_STRING_ALLOCATION_PADDING) && 00393 _DBUS_UNLIKELY (!reallocate_for_length (real, new_length))) 00394 return FALSE; 00395 else 00396 { 00397 real->len = new_length; 00398 real->str[new_length] = '\0'; 00399 return TRUE; 00400 } 00401 } 00402 00403 static dbus_bool_t 00404 open_gap (int len, 00405 DBusRealString *dest, 00406 int insert_at) 00407 { 00408 if (len == 0) 00409 return TRUE; 00410 00411 if (len > _DBUS_STRING_MAX_LENGTH - dest->len) 00412 return FALSE; /* detected overflow of dest->len + len below */ 00413 00414 if (!set_length (dest, dest->len + len)) 00415 return FALSE; 00416 00417 memmove (dest->str + insert_at + len, 00418 dest->str + insert_at, 00419 dest->len - len - insert_at); 00420 00421 return TRUE; 00422 } 00423 00424 #ifndef _dbus_string_get_data 00425 00436 char* 00437 _dbus_string_get_data (DBusString *str) 00438 { 00439 DBUS_STRING_PREAMBLE (str); 00440 00441 return (char*) real->str; 00442 } 00443 #endif /* _dbus_string_get_data */ 00444 00445 /* only do the function if we don't have the macro */ 00446 #ifndef _dbus_string_get_const_data 00447 00453 const char* 00454 _dbus_string_get_const_data (const DBusString *str) 00455 { 00456 DBUS_CONST_STRING_PREAMBLE (str); 00457 00458 return (const char*) real->str; 00459 } 00460 #endif /* _dbus_string_get_const_data */ 00461 00475 char* 00476 _dbus_string_get_data_len (DBusString *str, 00477 int start, 00478 int len) 00479 { 00480 DBUS_STRING_PREAMBLE (str); 00481 _dbus_assert (start >= 0); 00482 _dbus_assert (len >= 0); 00483 _dbus_assert (start <= real->len); 00484 _dbus_assert (len <= real->len - start); 00485 00486 return (char*) real->str + start; 00487 } 00488 00489 /* only do the function if we don't have the macro */ 00490 #ifndef _dbus_string_get_const_data_len 00491 00499 const char* 00500 _dbus_string_get_const_data_len (const DBusString *str, 00501 int start, 00502 int len) 00503 { 00504 DBUS_CONST_STRING_PREAMBLE (str); 00505 _dbus_assert (start >= 0); 00506 _dbus_assert (len >= 0); 00507 _dbus_assert (start <= real->len); 00508 _dbus_assert (len <= real->len - start); 00509 00510 return (const char*) real->str + start; 00511 } 00512 #endif /* _dbus_string_get_const_data_len */ 00513 00514 /* only do the function if we don't have the macro */ 00515 #ifndef _dbus_string_set_byte 00516 00523 void 00524 _dbus_string_set_byte (DBusString *str, 00525 int i, 00526 unsigned char byte) 00527 { 00528 DBUS_STRING_PREAMBLE (str); 00529 _dbus_assert (i < real->len); 00530 _dbus_assert (i >= 0); 00531 00532 real->str[i] = byte; 00533 } 00534 #endif /* _dbus_string_set_byte */ 00535 00536 /* only have the function if we didn't create a macro */ 00537 #ifndef _dbus_string_get_byte 00538 00547 unsigned char 00548 _dbus_string_get_byte (const DBusString *str, 00549 int start) 00550 { 00551 DBUS_CONST_STRING_PREAMBLE (str); 00552 _dbus_assert (start <= real->len); 00553 _dbus_assert (start >= 0); 00554 00555 return real->str[start]; 00556 } 00557 #endif /* _dbus_string_get_byte */ 00558 00569 dbus_bool_t 00570 _dbus_string_insert_bytes (DBusString *str, 00571 int i, 00572 int n_bytes, 00573 unsigned char byte) 00574 { 00575 DBUS_STRING_PREAMBLE (str); 00576 _dbus_assert (i <= real->len); 00577 _dbus_assert (i >= 0); 00578 _dbus_assert (n_bytes >= 0); 00579 00580 if (n_bytes == 0) 00581 return TRUE; 00582 00583 if (!open_gap (n_bytes, real, i)) 00584 return FALSE; 00585 00586 memset (real->str + i, byte, n_bytes); 00587 00588 return TRUE; 00589 } 00590 00599 dbus_bool_t 00600 _dbus_string_insert_byte (DBusString *str, 00601 int i, 00602 unsigned char byte) 00603 { 00604 DBUS_STRING_PREAMBLE (str); 00605 _dbus_assert (i <= real->len); 00606 _dbus_assert (i >= 0); 00607 00608 if (!open_gap (1, real, i)) 00609 return FALSE; 00610 00611 real->str[i] = byte; 00612 00613 return TRUE; 00614 } 00615 00626 dbus_bool_t 00627 _dbus_string_steal_data (DBusString *str, 00628 char **data_return) 00629 { 00630 DBUS_STRING_PREAMBLE (str); 00631 _dbus_assert (data_return != NULL); 00632 00633 undo_alignment (real); 00634 00635 *data_return = (char*) real->str; 00636 00637 /* reset the string */ 00638 if (!_dbus_string_init (str)) 00639 { 00640 /* hrm, put it back then */ 00641 real->str = (unsigned char*) *data_return; 00642 *data_return = NULL; 00643 fixup_alignment (real); 00644 return FALSE; 00645 } 00646 00647 return TRUE; 00648 } 00649 00657 dbus_bool_t 00658 _dbus_string_copy_data (const DBusString *str, 00659 char **data_return) 00660 { 00661 DBUS_CONST_STRING_PREAMBLE (str); 00662 _dbus_assert (data_return != NULL); 00663 00664 *data_return = dbus_malloc (real->len + 1); 00665 if (*data_return == NULL) 00666 return FALSE; 00667 00668 memcpy (*data_return, real->str, real->len + 1); 00669 00670 return TRUE; 00671 } 00672 00682 void 00683 _dbus_string_copy_to_buffer (const DBusString *str, 00684 char *buffer, 00685 int avail_len) 00686 { 00687 DBUS_CONST_STRING_PREAMBLE (str); 00688 00689 _dbus_assert (avail_len >= 0); 00690 _dbus_assert (avail_len >= real->len); 00691 00692 memcpy (buffer, real->str, real->len); 00693 } 00694 00704 void 00705 _dbus_string_copy_to_buffer_with_nul (const DBusString *str, 00706 char *buffer, 00707 int avail_len) 00708 { 00709 DBUS_CONST_STRING_PREAMBLE (str); 00710 00711 _dbus_assert (avail_len >= 0); 00712 _dbus_assert (avail_len > real->len); 00713 00714 memcpy (buffer, real->str, real->len+1); 00715 } 00716 00717 /* Only have the function if we don't have the macro */ 00718 #ifndef _dbus_string_get_length 00719 00724 int 00725 _dbus_string_get_length (const DBusString *str) 00726 { 00727 DBUS_CONST_STRING_PREAMBLE (str); 00728 00729 return real->len; 00730 } 00731 #endif /* !_dbus_string_get_length */ 00732 00745 dbus_bool_t 00746 _dbus_string_lengthen (DBusString *str, 00747 int additional_length) 00748 { 00749 DBUS_STRING_PREAMBLE (str); 00750 _dbus_assert (additional_length >= 0); 00751 00752 if (_DBUS_UNLIKELY (additional_length > _DBUS_STRING_MAX_LENGTH - real->len)) 00753 return FALSE; /* would overflow */ 00754 00755 return set_length (real, 00756 real->len + additional_length); 00757 } 00758 00765 void 00766 _dbus_string_shorten (DBusString *str, 00767 int length_to_remove) 00768 { 00769 DBUS_STRING_PREAMBLE (str); 00770 _dbus_assert (length_to_remove >= 0); 00771 _dbus_assert (length_to_remove <= real->len); 00772 00773 set_length (real, 00774 real->len - length_to_remove); 00775 } 00776 00787 dbus_bool_t 00788 _dbus_string_set_length (DBusString *str, 00789 int length) 00790 { 00791 DBUS_STRING_PREAMBLE (str); 00792 _dbus_assert (length >= 0); 00793 00794 return set_length (real, length); 00795 } 00796 00797 static dbus_bool_t 00798 align_insert_point_then_open_gap (DBusString *str, 00799 int *insert_at_p, 00800 int alignment, 00801 int gap_size) 00802 { 00803 unsigned long new_len; /* ulong to avoid _DBUS_ALIGN_VALUE overflow */ 00804 unsigned long gap_pos; 00805 int insert_at; 00806 int delta; 00807 DBUS_STRING_PREAMBLE (str); 00808 _dbus_assert (alignment >= 1); 00809 _dbus_assert (alignment <= 8); /* it has to be a bug if > 8 */ 00810 00811 insert_at = *insert_at_p; 00812 00813 _dbus_assert (insert_at <= real->len); 00814 00815 gap_pos = _DBUS_ALIGN_VALUE (insert_at, alignment); 00816 new_len = real->len + (gap_pos - insert_at) + gap_size; 00817 00818 if (_DBUS_UNLIKELY (new_len > (unsigned long) _DBUS_STRING_MAX_LENGTH)) 00819 return FALSE; 00820 00821 delta = new_len - real->len; 00822 _dbus_assert (delta >= 0); 00823 00824 if (delta == 0) /* only happens if gap_size == 0 and insert_at is aligned already */ 00825 { 00826 _dbus_assert (((unsigned long) *insert_at_p) == gap_pos); 00827 return TRUE; 00828 } 00829 00830 if (_DBUS_UNLIKELY (!open_gap (new_len - real->len, 00831 real, insert_at))) 00832 return FALSE; 00833 00834 /* nul the padding if we had to add any padding */ 00835 if (gap_size < delta) 00836 { 00837 memset (&real->str[insert_at], '\0', 00838 gap_pos - insert_at); 00839 } 00840 00841 *insert_at_p = gap_pos; 00842 00843 return TRUE; 00844 } 00845 00846 static dbus_bool_t 00847 align_length_then_lengthen (DBusString *str, 00848 int alignment, 00849 int then_lengthen_by) 00850 { 00851 int insert_at; 00852 00853 insert_at = _dbus_string_get_length (str); 00854 00855 return align_insert_point_then_open_gap (str, 00856 &insert_at, 00857 alignment, then_lengthen_by); 00858 } 00859 00868 dbus_bool_t 00869 _dbus_string_align_length (DBusString *str, 00870 int alignment) 00871 { 00872 return align_length_then_lengthen (str, alignment, 0); 00873 } 00874 00884 dbus_bool_t 00885 _dbus_string_alloc_space (DBusString *str, 00886 int extra_bytes) 00887 { 00888 if (!_dbus_string_lengthen (str, extra_bytes)) 00889 return FALSE; 00890 _dbus_string_shorten (str, extra_bytes); 00891 00892 return TRUE; 00893 } 00894 00895 static dbus_bool_t 00896 append (DBusRealString *real, 00897 const char *buffer, 00898 int buffer_len) 00899 { 00900 if (buffer_len == 0) 00901 return TRUE; 00902 00903 if (!_dbus_string_lengthen ((DBusString*)real, buffer_len)) 00904 return FALSE; 00905 00906 memcpy (real->str + (real->len - buffer_len), 00907 buffer, 00908 buffer_len); 00909 00910 return TRUE; 00911 } 00912 00920 dbus_bool_t 00921 _dbus_string_append (DBusString *str, 00922 const char *buffer) 00923 { 00924 unsigned long buffer_len; 00925 00926 DBUS_STRING_PREAMBLE (str); 00927 _dbus_assert (buffer != NULL); 00928 00929 buffer_len = strlen (buffer); 00930 if (buffer_len > (unsigned long) _DBUS_STRING_MAX_LENGTH) 00931 return FALSE; 00932 00933 return append (real, buffer, buffer_len); 00934 } 00935 00937 #define ASSIGN_2_OCTETS(p, octets) \ 00938 *((dbus_uint16_t*)(p)) = *((dbus_uint16_t*)(octets)); 00939 00941 #define ASSIGN_4_OCTETS(p, octets) \ 00942 *((dbus_uint32_t*)(p)) = *((dbus_uint32_t*)(octets)); 00943 00944 #ifdef DBUS_HAVE_INT64 00945 00946 #define ASSIGN_8_OCTETS(p, octets) \ 00947 *((dbus_uint64_t*)(p)) = *((dbus_uint64_t*)(octets)); 00948 #else 00949 00950 #define ASSIGN_8_OCTETS(p, octets) \ 00951 do { \ 00952 unsigned char *b; \ 00953 \ 00954 b = p; \ 00955 \ 00956 *b++ = octets[0]; \ 00957 *b++ = octets[1]; \ 00958 *b++ = octets[2]; \ 00959 *b++ = octets[3]; \ 00960 *b++ = octets[4]; \ 00961 *b++ = octets[5]; \ 00962 *b++ = octets[6]; \ 00963 *b++ = octets[7]; \ 00964 _dbus_assert (b == p + 8); \ 00965 } while (0) 00966 #endif /* DBUS_HAVE_INT64 */ 00967 00977 dbus_bool_t 00978 _dbus_string_insert_2_aligned (DBusString *str, 00979 int insert_at, 00980 const unsigned char octets[4]) 00981 { 00982 DBUS_STRING_PREAMBLE (str); 00983 00984 if (!align_insert_point_then_open_gap (str, &insert_at, 2, 2)) 00985 return FALSE; 00986 00987 ASSIGN_2_OCTETS (real->str + insert_at, octets); 00988 00989 return TRUE; 00990 } 00991 01001 dbus_bool_t 01002 _dbus_string_insert_4_aligned (DBusString *str, 01003 int insert_at, 01004 const unsigned char octets[4]) 01005 { 01006 DBUS_STRING_PREAMBLE (str); 01007 01008 if (!align_insert_point_then_open_gap (str, &insert_at, 4, 4)) 01009 return FALSE; 01010 01011 ASSIGN_4_OCTETS (real->str + insert_at, octets); 01012 01013 return TRUE; 01014 } 01015 01025 dbus_bool_t 01026 _dbus_string_insert_8_aligned (DBusString *str, 01027 int insert_at, 01028 const unsigned char octets[8]) 01029 { 01030 DBUS_STRING_PREAMBLE (str); 01031 01032 if (!align_insert_point_then_open_gap (str, &insert_at, 8, 8)) 01033 return FALSE; 01034 01035 _dbus_assert (_DBUS_ALIGN_VALUE (insert_at, 8) == (unsigned) insert_at); 01036 01037 ASSIGN_8_OCTETS (real->str + insert_at, octets); 01038 01039 return TRUE; 01040 } 01041 01042 01053 dbus_bool_t 01054 _dbus_string_insert_alignment (DBusString *str, 01055 int *insert_at, 01056 int alignment) 01057 { 01058 DBUS_STRING_PREAMBLE (str); 01059 01060 if (!align_insert_point_then_open_gap (str, insert_at, alignment, 0)) 01061 return FALSE; 01062 01063 _dbus_assert (_DBUS_ALIGN_VALUE (*insert_at, alignment) == (unsigned) *insert_at); 01064 01065 return TRUE; 01066 } 01067 01077 dbus_bool_t 01078 _dbus_string_append_printf_valist (DBusString *str, 01079 const char *format, 01080 va_list args) 01081 { 01082 int len; 01083 va_list args_copy; 01084 01085 DBUS_STRING_PREAMBLE (str); 01086 01087 DBUS_VA_COPY (args_copy, args); 01088 01089 /* Measure the message length without terminating nul */ 01090 len = _dbus_printf_string_upper_bound (format, args); 01091 01092 if (len < 0) 01093 return FALSE; 01094 01095 if (!_dbus_string_lengthen (str, len)) 01096 { 01097 /* don't leak the copy */ 01098 va_end (args_copy); 01099 return FALSE; 01100 } 01101 01102 vsprintf ((char*) (real->str + (real->len - len)), 01103 format, args_copy); 01104 01105 va_end (args_copy); 01106 01107 return TRUE; 01108 } 01109 01118 dbus_bool_t 01119 _dbus_string_append_printf (DBusString *str, 01120 const char *format, 01121 ...) 01122 { 01123 va_list args; 01124 dbus_bool_t retval; 01125 01126 va_start (args, format); 01127 retval = _dbus_string_append_printf_valist (str, format, args); 01128 va_end (args); 01129 01130 return retval; 01131 } 01132 01141 dbus_bool_t 01142 _dbus_string_append_len (DBusString *str, 01143 const char *buffer, 01144 int len) 01145 { 01146 DBUS_STRING_PREAMBLE (str); 01147 _dbus_assert (buffer != NULL); 01148 _dbus_assert (len >= 0); 01149 01150 return append (real, buffer, len); 01151 } 01152 01161 dbus_bool_t 01162 _dbus_string_append_byte (DBusString *str, 01163 unsigned char byte) 01164 { 01165 DBUS_STRING_PREAMBLE (str); 01166 01167 if (!set_length (real, real->len + 1)) 01168 return FALSE; 01169 01170 real->str[real->len-1] = byte; 01171 01172 return TRUE; 01173 } 01174 01175 static void 01176 delete (DBusRealString *real, 01177 int start, 01178 int len) 01179 { 01180 if (len == 0) 01181 return; 01182 01183 memmove (real->str + start, real->str + start + len, real->len - (start + len)); 01184 real->len -= len; 01185 real->str[real->len] = '\0'; 01186 } 01187 01197 void 01198 _dbus_string_delete (DBusString *str, 01199 int start, 01200 int len) 01201 { 01202 DBUS_STRING_PREAMBLE (str); 01203 _dbus_assert (start >= 0); 01204 _dbus_assert (len >= 0); 01205 _dbus_assert (start <= real->len); 01206 _dbus_assert (len <= real->len - start); 01207 01208 delete (real, start, len); 01209 } 01210 01211 static dbus_bool_t 01212 copy (DBusRealString *source, 01213 int start, 01214 int len, 01215 DBusRealString *dest, 01216 int insert_at) 01217 { 01218 if (len == 0) 01219 return TRUE; 01220 01221 if (!open_gap (len, dest, insert_at)) 01222 return FALSE; 01223 01224 memmove (dest->str + insert_at, 01225 source->str + start, 01226 len); 01227 01228 return TRUE; 01229 } 01230 01240 #define DBUS_STRING_COPY_PREAMBLE(source, start, dest, insert_at) \ 01241 DBusRealString *real_source = (DBusRealString*) source; \ 01242 DBusRealString *real_dest = (DBusRealString*) dest; \ 01243 _dbus_assert ((source) != (dest)); \ 01244 DBUS_GENERIC_STRING_PREAMBLE (real_source); \ 01245 DBUS_GENERIC_STRING_PREAMBLE (real_dest); \ 01246 _dbus_assert (!real_dest->constant); \ 01247 _dbus_assert (!real_dest->locked); \ 01248 _dbus_assert ((start) >= 0); \ 01249 _dbus_assert ((start) <= real_source->len); \ 01250 _dbus_assert ((insert_at) >= 0); \ 01251 _dbus_assert ((insert_at) <= real_dest->len) 01252 01263 dbus_bool_t 01264 _dbus_string_move (DBusString *source, 01265 int start, 01266 DBusString *dest, 01267 int insert_at) 01268 { 01269 DBusRealString *real_source = (DBusRealString*) source; 01270 _dbus_assert (start <= real_source->len); 01271 01272 return _dbus_string_move_len (source, start, 01273 real_source->len - start, 01274 dest, insert_at); 01275 } 01276 01287 dbus_bool_t 01288 _dbus_string_copy (const DBusString *source, 01289 int start, 01290 DBusString *dest, 01291 int insert_at) 01292 { 01293 DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at); 01294 01295 return copy (real_source, start, 01296 real_source->len - start, 01297 real_dest, 01298 insert_at); 01299 } 01300 01312 dbus_bool_t 01313 _dbus_string_move_len (DBusString *source, 01314 int start, 01315 int len, 01316 DBusString *dest, 01317 int insert_at) 01318 01319 { 01320 DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at); 01321 _dbus_assert (len >= 0); 01322 _dbus_assert ((start + len) <= real_source->len); 01323 01324 01325 if (len == 0) 01326 { 01327 return TRUE; 01328 } 01329 else if (start == 0 && 01330 len == real_source->len && 01331 real_dest->len == 0) 01332 { 01333 /* Short-circuit moving an entire existing string to an empty string 01334 * by just swapping the buffers. 01335 */ 01336 /* we assume ->constant doesn't matter as you can't have 01337 * a constant string involved in a move. 01338 */ 01339 #define ASSIGN_DATA(a, b) do { \ 01340 (a)->str = (b)->str; \ 01341 (a)->len = (b)->len; \ 01342 (a)->allocated = (b)->allocated; \ 01343 (a)->align_offset = (b)->align_offset; \ 01344 } while (0) 01345 01346 DBusRealString tmp; 01347 01348 ASSIGN_DATA (&tmp, real_source); 01349 ASSIGN_DATA (real_source, real_dest); 01350 ASSIGN_DATA (real_dest, &tmp); 01351 01352 return TRUE; 01353 } 01354 else 01355 { 01356 if (!copy (real_source, start, len, 01357 real_dest, 01358 insert_at)) 01359 return FALSE; 01360 01361 delete (real_source, start, 01362 len); 01363 01364 return TRUE; 01365 } 01366 } 01367 01379 dbus_bool_t 01380 _dbus_string_copy_len (const DBusString *source, 01381 int start, 01382 int len, 01383 DBusString *dest, 01384 int insert_at) 01385 { 01386 DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at); 01387 _dbus_assert (len >= 0); 01388 _dbus_assert (start <= real_source->len); 01389 _dbus_assert (len <= real_source->len - start); 01390 01391 return copy (real_source, start, len, 01392 real_dest, 01393 insert_at); 01394 } 01395 01408 dbus_bool_t 01409 _dbus_string_replace_len (const DBusString *source, 01410 int start, 01411 int len, 01412 DBusString *dest, 01413 int replace_at, 01414 int replace_len) 01415 { 01416 DBUS_STRING_COPY_PREAMBLE (source, start, dest, replace_at); 01417 _dbus_assert (len >= 0); 01418 _dbus_assert (start <= real_source->len); 01419 _dbus_assert (len <= real_source->len - start); 01420 _dbus_assert (replace_at >= 0); 01421 _dbus_assert (replace_at <= real_dest->len); 01422 _dbus_assert (replace_len <= real_dest->len - replace_at); 01423 01424 if (len == replace_len) 01425 { 01426 memmove (real_dest->str + replace_at, 01427 real_source->str + start, len); 01428 } 01429 else if (len < replace_len) 01430 { 01431 memmove (real_dest->str + replace_at, 01432 real_source->str + start, len); 01433 delete (real_dest, replace_at + len, 01434 replace_len - len); 01435 } 01436 else 01437 { 01438 int diff; 01439 01440 _dbus_assert (len > replace_len); 01441 01442 diff = len - replace_len; 01443 01444 /* First of all we check if destination string can be enlarged as 01445 * required, then we overwrite previous bytes 01446 */ 01447 01448 if (!copy (real_source, start + replace_len, diff, 01449 real_dest, replace_at + replace_len)) 01450 return FALSE; 01451 01452 memmove (real_dest->str + replace_at, 01453 real_source->str + start, replace_len); 01454 } 01455 01456 return TRUE; 01457 } 01458 01471 dbus_bool_t 01472 _dbus_string_split_on_byte (DBusString *source, 01473 unsigned char byte, 01474 DBusString *tail) 01475 { 01476 int byte_position; 01477 char byte_string[2] = ""; 01478 int head_length; 01479 int tail_length; 01480 01481 byte_string[0] = (char) byte; 01482 01483 if (!_dbus_string_find (source, 0, byte_string, &byte_position)) 01484 return FALSE; 01485 01486 head_length = byte_position; 01487 tail_length = _dbus_string_get_length (source) - head_length - 1; 01488 01489 if (!_dbus_string_move_len (source, byte_position + 1, tail_length, 01490 tail, 0)) 01491 return FALSE; 01492 01493 /* remove the trailing delimiter byte from the head now. 01494 */ 01495 if (!_dbus_string_set_length (source, head_length)) 01496 return FALSE; 01497 01498 return TRUE; 01499 } 01500 01501 /* Unicode macros and utf8_validate() from GLib Owen Taylor, Havoc 01502 * Pennington, and Tom Tromey are the authors and authorized relicense. 01503 */ 01504 01510 #define UTF8_COMPUTE(Char, Mask, Len) \ 01511 if (Char < 128) \ 01512 { \ 01513 Len = 1; \ 01514 Mask = 0x7f; \ 01515 } \ 01516 else if ((Char & 0xe0) == 0xc0) \ 01517 { \ 01518 Len = 2; \ 01519 Mask = 0x1f; \ 01520 } \ 01521 else if ((Char & 0xf0) == 0xe0) \ 01522 { \ 01523 Len = 3; \ 01524 Mask = 0x0f; \ 01525 } \ 01526 else if ((Char & 0xf8) == 0xf0) \ 01527 { \ 01528 Len = 4; \ 01529 Mask = 0x07; \ 01530 } \ 01531 else if ((Char & 0xfc) == 0xf8) \ 01532 { \ 01533 Len = 5; \ 01534 Mask = 0x03; \ 01535 } \ 01536 else if ((Char & 0xfe) == 0xfc) \ 01537 { \ 01538 Len = 6; \ 01539 Mask = 0x01; \ 01540 } \ 01541 else \ 01542 { \ 01543 Len = 0; \ 01544 Mask = 0; \ 01545 } 01546 01551 #define UTF8_LENGTH(Char) \ 01552 ((Char) < 0x80 ? 1 : \ 01553 ((Char) < 0x800 ? 2 : \ 01554 ((Char) < 0x10000 ? 3 : \ 01555 ((Char) < 0x200000 ? 4 : \ 01556 ((Char) < 0x4000000 ? 5 : 6))))) 01557 01567 #define UTF8_GET(Result, Chars, Count, Mask, Len) \ 01568 (Result) = (Chars)[0] & (Mask); \ 01569 for ((Count) = 1; (Count) < (Len); ++(Count)) \ 01570 { \ 01571 if (((Chars)[(Count)] & 0xc0) != 0x80) \ 01572 { \ 01573 (Result) = -1; \ 01574 break; \ 01575 } \ 01576 (Result) <<= 6; \ 01577 (Result) |= ((Chars)[(Count)] & 0x3f); \ 01578 } 01579 01590 #define UNICODE_VALID(Char) \ 01591 ((Char) < 0x110000 && \ 01592 (((Char) & 0xFFFFF800) != 0xD800)) 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 unsigned char 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 */
1.7.6.1