|
D-Bus
1.8.20
|
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_ENABLE_EMBEDDED_TESTS 00289 /* Not using this feature at the moment, 00290 * so marked DBUS_ENABLE_EMBEDDED_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_ENABLE_EMBEDDED_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 #if defined (DBUS_ENABLE_EMBEDDED_TESTS) && !defined (DBUS_DISABLE_ASSERT) 00339 new_allocated = 0; /* ensure a realloc every time so that we go 00340 * through all malloc failure codepaths 00341 */ 00342 #endif 00343 00344 /* But be sure we always alloc at least space for the new length */ 00345 new_allocated = MAX (new_allocated, 00346 new_length + _DBUS_STRING_ALLOCATION_PADDING); 00347 00348 _dbus_assert (new_allocated >= real->allocated); /* code relies on this */ 00349 new_str = dbus_realloc (real->str - real->align_offset, new_allocated); 00350 if (_DBUS_UNLIKELY (new_str == NULL)) 00351 return FALSE; 00352 00353 real->str = new_str + real->align_offset; 00354 real->allocated = new_allocated; 00355 fixup_alignment (real); 00356 00357 return TRUE; 00358 } 00359 00371 dbus_bool_t 00372 _dbus_string_compact (DBusString *str, 00373 int max_waste) 00374 { 00375 DBUS_STRING_PREAMBLE (str); 00376 00377 return compact (real, max_waste); 00378 } 00379 00380 static dbus_bool_t 00381 set_length (DBusRealString *real, 00382 int new_length) 00383 { 00384 /* Note, we are setting the length not including nul termination */ 00385 00386 /* exceeding max length is the same as failure to allocate memory */ 00387 if (_DBUS_UNLIKELY (new_length > _DBUS_STRING_MAX_LENGTH)) 00388 return FALSE; 00389 else if (new_length > (real->allocated - _DBUS_STRING_ALLOCATION_PADDING) && 00390 _DBUS_UNLIKELY (!reallocate_for_length (real, new_length))) 00391 return FALSE; 00392 else 00393 { 00394 real->len = new_length; 00395 real->str[new_length] = '\0'; 00396 return TRUE; 00397 } 00398 } 00399 00400 static dbus_bool_t 00401 open_gap (int len, 00402 DBusRealString *dest, 00403 int insert_at) 00404 { 00405 if (len == 0) 00406 return TRUE; 00407 00408 if (len > _DBUS_STRING_MAX_LENGTH - dest->len) 00409 return FALSE; /* detected overflow of dest->len + len below */ 00410 00411 if (!set_length (dest, dest->len + len)) 00412 return FALSE; 00413 00414 memmove (dest->str + insert_at + len, 00415 dest->str + insert_at, 00416 dest->len - len - insert_at); 00417 00418 return TRUE; 00419 } 00420 00421 #ifndef _dbus_string_get_data 00422 00433 char* 00434 _dbus_string_get_data (DBusString *str) 00435 { 00436 DBUS_STRING_PREAMBLE (str); 00437 00438 return (char*) real->str; 00439 } 00440 #endif /* _dbus_string_get_data */ 00441 00442 /* only do the function if we don't have the macro */ 00443 #ifndef _dbus_string_get_const_data 00444 00450 const char* 00451 _dbus_string_get_const_data (const DBusString *str) 00452 { 00453 DBUS_CONST_STRING_PREAMBLE (str); 00454 00455 return (const char*) real->str; 00456 } 00457 #endif /* _dbus_string_get_const_data */ 00458 00472 char* 00473 _dbus_string_get_data_len (DBusString *str, 00474 int start, 00475 int len) 00476 { 00477 DBUS_STRING_PREAMBLE (str); 00478 _dbus_assert (start >= 0); 00479 _dbus_assert (len >= 0); 00480 _dbus_assert (start <= real->len); 00481 _dbus_assert (len <= real->len - start); 00482 00483 return (char*) real->str + start; 00484 } 00485 00486 /* only do the function if we don't have the macro */ 00487 #ifndef _dbus_string_get_const_data_len 00488 00496 const char* 00497 _dbus_string_get_const_data_len (const DBusString *str, 00498 int start, 00499 int len) 00500 { 00501 DBUS_CONST_STRING_PREAMBLE (str); 00502 _dbus_assert (start >= 0); 00503 _dbus_assert (len >= 0); 00504 _dbus_assert (start <= real->len); 00505 _dbus_assert (len <= real->len - start); 00506 00507 return (const char*) real->str + start; 00508 } 00509 #endif /* _dbus_string_get_const_data_len */ 00510 00511 /* only do the function if we don't have the macro */ 00512 #ifndef _dbus_string_set_byte 00513 00520 void 00521 _dbus_string_set_byte (DBusString *str, 00522 int i, 00523 unsigned char byte) 00524 { 00525 DBUS_STRING_PREAMBLE (str); 00526 _dbus_assert (i < real->len); 00527 _dbus_assert (i >= 0); 00528 00529 real->str[i] = byte; 00530 } 00531 #endif /* _dbus_string_set_byte */ 00532 00533 /* only have the function if we didn't create a macro */ 00534 #ifndef _dbus_string_get_byte 00535 00544 unsigned char 00545 _dbus_string_get_byte (const DBusString *str, 00546 int start) 00547 { 00548 DBUS_CONST_STRING_PREAMBLE (str); 00549 _dbus_assert (start <= real->len); 00550 _dbus_assert (start >= 0); 00551 00552 return real->str[start]; 00553 } 00554 #endif /* _dbus_string_get_byte */ 00555 00566 dbus_bool_t 00567 _dbus_string_insert_bytes (DBusString *str, 00568 int i, 00569 int n_bytes, 00570 unsigned char byte) 00571 { 00572 DBUS_STRING_PREAMBLE (str); 00573 _dbus_assert (i <= real->len); 00574 _dbus_assert (i >= 0); 00575 _dbus_assert (n_bytes >= 0); 00576 00577 if (n_bytes == 0) 00578 return TRUE; 00579 00580 if (!open_gap (n_bytes, real, i)) 00581 return FALSE; 00582 00583 memset (real->str + i, byte, n_bytes); 00584 00585 return TRUE; 00586 } 00587 00596 dbus_bool_t 00597 _dbus_string_insert_byte (DBusString *str, 00598 int i, 00599 unsigned char byte) 00600 { 00601 DBUS_STRING_PREAMBLE (str); 00602 _dbus_assert (i <= real->len); 00603 _dbus_assert (i >= 0); 00604 00605 if (!open_gap (1, real, i)) 00606 return FALSE; 00607 00608 real->str[i] = byte; 00609 00610 return TRUE; 00611 } 00612 00623 dbus_bool_t 00624 _dbus_string_steal_data (DBusString *str, 00625 char **data_return) 00626 { 00627 DBUS_STRING_PREAMBLE (str); 00628 _dbus_assert (data_return != NULL); 00629 00630 undo_alignment (real); 00631 00632 *data_return = (char*) real->str; 00633 00634 /* reset the string */ 00635 if (!_dbus_string_init (str)) 00636 { 00637 /* hrm, put it back then */ 00638 real->str = (unsigned char*) *data_return; 00639 *data_return = NULL; 00640 fixup_alignment (real); 00641 return FALSE; 00642 } 00643 00644 return TRUE; 00645 } 00646 00654 dbus_bool_t 00655 _dbus_string_copy_data (const DBusString *str, 00656 char **data_return) 00657 { 00658 DBUS_CONST_STRING_PREAMBLE (str); 00659 _dbus_assert (data_return != NULL); 00660 00661 *data_return = dbus_malloc (real->len + 1); 00662 if (*data_return == NULL) 00663 return FALSE; 00664 00665 memcpy (*data_return, real->str, real->len + 1); 00666 00667 return TRUE; 00668 } 00669 00679 void 00680 _dbus_string_copy_to_buffer (const DBusString *str, 00681 char *buffer, 00682 int avail_len) 00683 { 00684 DBUS_CONST_STRING_PREAMBLE (str); 00685 00686 _dbus_assert (avail_len >= 0); 00687 _dbus_assert (avail_len >= real->len); 00688 00689 memcpy (buffer, real->str, real->len); 00690 } 00691 00701 void 00702 _dbus_string_copy_to_buffer_with_nul (const DBusString *str, 00703 char *buffer, 00704 int avail_len) 00705 { 00706 DBUS_CONST_STRING_PREAMBLE (str); 00707 00708 _dbus_assert (avail_len >= 0); 00709 _dbus_assert (avail_len > real->len); 00710 00711 memcpy (buffer, real->str, real->len+1); 00712 } 00713 00714 /* Only have the function if we don't have the macro */ 00715 #ifndef _dbus_string_get_length 00716 00721 int 00722 _dbus_string_get_length (const DBusString *str) 00723 { 00724 DBUS_CONST_STRING_PREAMBLE (str); 00725 00726 return real->len; 00727 } 00728 #endif /* !_dbus_string_get_length */ 00729 00742 dbus_bool_t 00743 _dbus_string_lengthen (DBusString *str, 00744 int additional_length) 00745 { 00746 DBUS_STRING_PREAMBLE (str); 00747 _dbus_assert (additional_length >= 0); 00748 00749 if (_DBUS_UNLIKELY (additional_length > _DBUS_STRING_MAX_LENGTH - real->len)) 00750 return FALSE; /* would overflow */ 00751 00752 return set_length (real, 00753 real->len + additional_length); 00754 } 00755 00762 void 00763 _dbus_string_shorten (DBusString *str, 00764 int length_to_remove) 00765 { 00766 DBUS_STRING_PREAMBLE (str); 00767 _dbus_assert (length_to_remove >= 0); 00768 _dbus_assert (length_to_remove <= real->len); 00769 00770 set_length (real, 00771 real->len - length_to_remove); 00772 } 00773 00784 dbus_bool_t 00785 _dbus_string_set_length (DBusString *str, 00786 int length) 00787 { 00788 DBUS_STRING_PREAMBLE (str); 00789 _dbus_assert (length >= 0); 00790 00791 return set_length (real, length); 00792 } 00793 00794 static dbus_bool_t 00795 align_insert_point_then_open_gap (DBusString *str, 00796 int *insert_at_p, 00797 int alignment, 00798 int gap_size) 00799 { 00800 unsigned long new_len; /* ulong to avoid _DBUS_ALIGN_VALUE overflow */ 00801 unsigned long gap_pos; 00802 int insert_at; 00803 int delta; 00804 DBUS_STRING_PREAMBLE (str); 00805 _dbus_assert (alignment >= 1); 00806 _dbus_assert (alignment <= 8); /* it has to be a bug if > 8 */ 00807 00808 insert_at = *insert_at_p; 00809 00810 _dbus_assert (insert_at <= real->len); 00811 00812 gap_pos = _DBUS_ALIGN_VALUE (insert_at, alignment); 00813 new_len = real->len + (gap_pos - insert_at) + gap_size; 00814 00815 if (_DBUS_UNLIKELY (new_len > (unsigned long) _DBUS_STRING_MAX_LENGTH)) 00816 return FALSE; 00817 00818 delta = new_len - real->len; 00819 _dbus_assert (delta >= 0); 00820 00821 if (delta == 0) /* only happens if gap_size == 0 and insert_at is aligned already */ 00822 { 00823 _dbus_assert (((unsigned long) *insert_at_p) == gap_pos); 00824 return TRUE; 00825 } 00826 00827 if (_DBUS_UNLIKELY (!open_gap (new_len - real->len, 00828 real, insert_at))) 00829 return FALSE; 00830 00831 /* nul the padding if we had to add any padding */ 00832 if (gap_size < delta) 00833 { 00834 memset (&real->str[insert_at], '\0', 00835 gap_pos - insert_at); 00836 } 00837 00838 *insert_at_p = gap_pos; 00839 00840 return TRUE; 00841 } 00842 00843 static dbus_bool_t 00844 align_length_then_lengthen (DBusString *str, 00845 int alignment, 00846 int then_lengthen_by) 00847 { 00848 int insert_at; 00849 00850 insert_at = _dbus_string_get_length (str); 00851 00852 return align_insert_point_then_open_gap (str, 00853 &insert_at, 00854 alignment, then_lengthen_by); 00855 } 00856 00865 dbus_bool_t 00866 _dbus_string_align_length (DBusString *str, 00867 int alignment) 00868 { 00869 return align_length_then_lengthen (str, alignment, 0); 00870 } 00871 00881 dbus_bool_t 00882 _dbus_string_alloc_space (DBusString *str, 00883 int extra_bytes) 00884 { 00885 if (!_dbus_string_lengthen (str, extra_bytes)) 00886 return FALSE; 00887 _dbus_string_shorten (str, extra_bytes); 00888 00889 return TRUE; 00890 } 00891 00892 static dbus_bool_t 00893 append (DBusRealString *real, 00894 const char *buffer, 00895 int buffer_len) 00896 { 00897 if (buffer_len == 0) 00898 return TRUE; 00899 00900 if (!_dbus_string_lengthen ((DBusString*)real, buffer_len)) 00901 return FALSE; 00902 00903 memcpy (real->str + (real->len - buffer_len), 00904 buffer, 00905 buffer_len); 00906 00907 return TRUE; 00908 } 00909 00917 dbus_bool_t 00918 _dbus_string_append (DBusString *str, 00919 const char *buffer) 00920 { 00921 unsigned long buffer_len; 00922 00923 DBUS_STRING_PREAMBLE (str); 00924 _dbus_assert (buffer != NULL); 00925 00926 buffer_len = strlen (buffer); 00927 if (buffer_len > (unsigned long) _DBUS_STRING_MAX_LENGTH) 00928 return FALSE; 00929 00930 return append (real, buffer, buffer_len); 00931 } 00932 00934 #define ASSIGN_2_OCTETS(p, octets) \ 00935 *((dbus_uint16_t*)(p)) = *((dbus_uint16_t*)(octets)); 00936 00938 #define ASSIGN_4_OCTETS(p, octets) \ 00939 *((dbus_uint32_t*)(p)) = *((dbus_uint32_t*)(octets)); 00940 00942 #define ASSIGN_8_OCTETS(p, octets) \ 00943 *((dbus_uint64_t*)(p)) = *((dbus_uint64_t*)(octets)); 00944 00954 dbus_bool_t 00955 _dbus_string_insert_2_aligned (DBusString *str, 00956 int insert_at, 00957 const unsigned char octets[2]) 00958 { 00959 DBUS_STRING_PREAMBLE (str); 00960 00961 if (!align_insert_point_then_open_gap (str, &insert_at, 2, 2)) 00962 return FALSE; 00963 00964 ASSIGN_2_OCTETS (real->str + insert_at, octets); 00965 00966 return TRUE; 00967 } 00968 00978 dbus_bool_t 00979 _dbus_string_insert_4_aligned (DBusString *str, 00980 int insert_at, 00981 const unsigned char octets[4]) 00982 { 00983 DBUS_STRING_PREAMBLE (str); 00984 00985 if (!align_insert_point_then_open_gap (str, &insert_at, 4, 4)) 00986 return FALSE; 00987 00988 ASSIGN_4_OCTETS (real->str + insert_at, octets); 00989 00990 return TRUE; 00991 } 00992 01002 dbus_bool_t 01003 _dbus_string_insert_8_aligned (DBusString *str, 01004 int insert_at, 01005 const unsigned char octets[8]) 01006 { 01007 DBUS_STRING_PREAMBLE (str); 01008 01009 if (!align_insert_point_then_open_gap (str, &insert_at, 8, 8)) 01010 return FALSE; 01011 01012 _dbus_assert (_DBUS_ALIGN_VALUE (insert_at, 8) == (unsigned) insert_at); 01013 01014 ASSIGN_8_OCTETS (real->str + insert_at, octets); 01015 01016 return TRUE; 01017 } 01018 01019 01030 dbus_bool_t 01031 _dbus_string_insert_alignment (DBusString *str, 01032 int *insert_at, 01033 int alignment) 01034 { 01035 DBUS_STRING_PREAMBLE (str); 01036 01037 if (!align_insert_point_then_open_gap (str, insert_at, alignment, 0)) 01038 return FALSE; 01039 01040 _dbus_assert (_DBUS_ALIGN_VALUE (*insert_at, alignment) == (unsigned) *insert_at); 01041 01042 return TRUE; 01043 } 01044 01054 dbus_bool_t 01055 _dbus_string_append_printf_valist (DBusString *str, 01056 const char *format, 01057 va_list args) 01058 { 01059 int len; 01060 va_list args_copy; 01061 01062 DBUS_STRING_PREAMBLE (str); 01063 01064 DBUS_VA_COPY (args_copy, args); 01065 01066 /* Measure the message length without terminating nul */ 01067 len = _dbus_printf_string_upper_bound (format, args); 01068 01069 if (len < 0) 01070 return FALSE; 01071 01072 if (!_dbus_string_lengthen (str, len)) 01073 { 01074 /* don't leak the copy */ 01075 va_end (args_copy); 01076 return FALSE; 01077 } 01078 01079 vsprintf ((char*) (real->str + (real->len - len)), 01080 format, args_copy); 01081 01082 va_end (args_copy); 01083 01084 return TRUE; 01085 } 01086 01095 dbus_bool_t 01096 _dbus_string_append_printf (DBusString *str, 01097 const char *format, 01098 ...) 01099 { 01100 va_list args; 01101 dbus_bool_t retval; 01102 01103 va_start (args, format); 01104 retval = _dbus_string_append_printf_valist (str, format, args); 01105 va_end (args); 01106 01107 return retval; 01108 } 01109 01118 dbus_bool_t 01119 _dbus_string_append_len (DBusString *str, 01120 const char *buffer, 01121 int len) 01122 { 01123 DBUS_STRING_PREAMBLE (str); 01124 _dbus_assert (buffer != NULL); 01125 _dbus_assert (len >= 0); 01126 01127 return append (real, buffer, len); 01128 } 01129 01138 dbus_bool_t 01139 _dbus_string_append_byte (DBusString *str, 01140 unsigned char byte) 01141 { 01142 DBUS_STRING_PREAMBLE (str); 01143 01144 if (!set_length (real, real->len + 1)) 01145 return FALSE; 01146 01147 real->str[real->len-1] = byte; 01148 01149 return TRUE; 01150 } 01151 01152 static void 01153 delete (DBusRealString *real, 01154 int start, 01155 int len) 01156 { 01157 if (len == 0) 01158 return; 01159 01160 memmove (real->str + start, real->str + start + len, real->len - (start + len)); 01161 real->len -= len; 01162 real->str[real->len] = '\0'; 01163 } 01164 01174 void 01175 _dbus_string_delete (DBusString *str, 01176 int start, 01177 int len) 01178 { 01179 DBUS_STRING_PREAMBLE (str); 01180 _dbus_assert (start >= 0); 01181 _dbus_assert (len >= 0); 01182 _dbus_assert (start <= real->len); 01183 _dbus_assert (len <= real->len - start); 01184 01185 delete (real, start, len); 01186 } 01187 01188 static dbus_bool_t 01189 copy (DBusRealString *source, 01190 int start, 01191 int len, 01192 DBusRealString *dest, 01193 int insert_at) 01194 { 01195 if (len == 0) 01196 return TRUE; 01197 01198 if (!open_gap (len, dest, insert_at)) 01199 return FALSE; 01200 01201 memmove (dest->str + insert_at, 01202 source->str + start, 01203 len); 01204 01205 return TRUE; 01206 } 01207 01217 #define DBUS_STRING_COPY_PREAMBLE(source, start, dest, insert_at) \ 01218 DBusRealString *real_source = (DBusRealString*) source; \ 01219 DBusRealString *real_dest = (DBusRealString*) dest; \ 01220 _dbus_assert ((source) != (dest)); \ 01221 DBUS_GENERIC_STRING_PREAMBLE (real_source); \ 01222 DBUS_GENERIC_STRING_PREAMBLE (real_dest); \ 01223 _dbus_assert (!real_dest->constant); \ 01224 _dbus_assert (!real_dest->locked); \ 01225 _dbus_assert ((start) >= 0); \ 01226 _dbus_assert ((start) <= real_source->len); \ 01227 _dbus_assert ((insert_at) >= 0); \ 01228 _dbus_assert ((insert_at) <= real_dest->len) 01229 01240 dbus_bool_t 01241 _dbus_string_move (DBusString *source, 01242 int start, 01243 DBusString *dest, 01244 int insert_at) 01245 { 01246 DBusRealString *real_source = (DBusRealString*) source; 01247 _dbus_assert (start <= real_source->len); 01248 01249 return _dbus_string_move_len (source, start, 01250 real_source->len - start, 01251 dest, insert_at); 01252 } 01253 01264 dbus_bool_t 01265 _dbus_string_copy (const DBusString *source, 01266 int start, 01267 DBusString *dest, 01268 int insert_at) 01269 { 01270 DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at); 01271 01272 return copy (real_source, start, 01273 real_source->len - start, 01274 real_dest, 01275 insert_at); 01276 } 01277 01289 dbus_bool_t 01290 _dbus_string_move_len (DBusString *source, 01291 int start, 01292 int len, 01293 DBusString *dest, 01294 int insert_at) 01295 01296 { 01297 DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at); 01298 _dbus_assert (len >= 0); 01299 _dbus_assert ((start + len) <= real_source->len); 01300 01301 01302 if (len == 0) 01303 { 01304 return TRUE; 01305 } 01306 else if (start == 0 && 01307 len == real_source->len && 01308 real_dest->len == 0) 01309 { 01310 /* Short-circuit moving an entire existing string to an empty string 01311 * by just swapping the buffers. 01312 */ 01313 /* we assume ->constant doesn't matter as you can't have 01314 * a constant string involved in a move. 01315 */ 01316 #define ASSIGN_DATA(a, b) do { \ 01317 (a)->str = (b)->str; \ 01318 (a)->len = (b)->len; \ 01319 (a)->allocated = (b)->allocated; \ 01320 (a)->align_offset = (b)->align_offset; \ 01321 } while (0) 01322 01323 DBusRealString tmp; 01324 01325 ASSIGN_DATA (&tmp, real_source); 01326 ASSIGN_DATA (real_source, real_dest); 01327 ASSIGN_DATA (real_dest, &tmp); 01328 01329 return TRUE; 01330 } 01331 else 01332 { 01333 if (!copy (real_source, start, len, 01334 real_dest, 01335 insert_at)) 01336 return FALSE; 01337 01338 delete (real_source, start, 01339 len); 01340 01341 return TRUE; 01342 } 01343 } 01344 01356 dbus_bool_t 01357 _dbus_string_copy_len (const DBusString *source, 01358 int start, 01359 int len, 01360 DBusString *dest, 01361 int insert_at) 01362 { 01363 DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at); 01364 _dbus_assert (len >= 0); 01365 _dbus_assert (start <= real_source->len); 01366 _dbus_assert (len <= real_source->len - start); 01367 01368 return copy (real_source, start, len, 01369 real_dest, 01370 insert_at); 01371 } 01372 01385 dbus_bool_t 01386 _dbus_string_replace_len (const DBusString *source, 01387 int start, 01388 int len, 01389 DBusString *dest, 01390 int replace_at, 01391 int replace_len) 01392 { 01393 DBUS_STRING_COPY_PREAMBLE (source, start, dest, replace_at); 01394 _dbus_assert (len >= 0); 01395 _dbus_assert (start <= real_source->len); 01396 _dbus_assert (len <= real_source->len - start); 01397 _dbus_assert (replace_at >= 0); 01398 _dbus_assert (replace_at <= real_dest->len); 01399 _dbus_assert (replace_len <= real_dest->len - replace_at); 01400 01401 if (len == replace_len) 01402 { 01403 memmove (real_dest->str + replace_at, 01404 real_source->str + start, len); 01405 } 01406 else if (len < replace_len) 01407 { 01408 memmove (real_dest->str + replace_at, 01409 real_source->str + start, len); 01410 delete (real_dest, replace_at + len, 01411 replace_len - len); 01412 } 01413 else 01414 { 01415 int diff; 01416 01417 _dbus_assert (len > replace_len); 01418 01419 diff = len - replace_len; 01420 01421 /* First of all we check if destination string can be enlarged as 01422 * required, then we overwrite previous bytes 01423 */ 01424 01425 if (!copy (real_source, start + replace_len, diff, 01426 real_dest, replace_at + replace_len)) 01427 return FALSE; 01428 01429 memmove (real_dest->str + replace_at, 01430 real_source->str + start, replace_len); 01431 } 01432 01433 return TRUE; 01434 } 01435 01448 dbus_bool_t 01449 _dbus_string_split_on_byte (DBusString *source, 01450 unsigned char byte, 01451 DBusString *tail) 01452 { 01453 int byte_position; 01454 char byte_string[2] = ""; 01455 int head_length; 01456 int tail_length; 01457 01458 byte_string[0] = (char) byte; 01459 01460 if (!_dbus_string_find (source, 0, byte_string, &byte_position)) 01461 return FALSE; 01462 01463 head_length = byte_position; 01464 tail_length = _dbus_string_get_length (source) - head_length - 1; 01465 01466 if (!_dbus_string_move_len (source, byte_position + 1, tail_length, 01467 tail, 0)) 01468 return FALSE; 01469 01470 /* remove the trailing delimiter byte from the head now. 01471 */ 01472 if (!_dbus_string_set_length (source, head_length)) 01473 return FALSE; 01474 01475 return TRUE; 01476 } 01477 01478 /* Unicode macros and utf8_validate() from GLib Owen Taylor, Havoc 01479 * Pennington, and Tom Tromey are the authors and authorized relicense. 01480 */ 01481 01487 #define UTF8_COMPUTE(Char, Mask, Len) \ 01488 if (Char < 128) \ 01489 { \ 01490 Len = 1; \ 01491 Mask = 0x7f; \ 01492 } \ 01493 else if ((Char & 0xe0) == 0xc0) \ 01494 { \ 01495 Len = 2; \ 01496 Mask = 0x1f; \ 01497 } \ 01498 else if ((Char & 0xf0) == 0xe0) \ 01499 { \ 01500 Len = 3; \ 01501 Mask = 0x0f; \ 01502 } \ 01503 else if ((Char & 0xf8) == 0xf0) \ 01504 { \ 01505 Len = 4; \ 01506 Mask = 0x07; \ 01507 } \ 01508 else if ((Char & 0xfc) == 0xf8) \ 01509 { \ 01510 Len = 5; \ 01511 Mask = 0x03; \ 01512 } \ 01513 else if ((Char & 0xfe) == 0xfc) \ 01514 { \ 01515 Len = 6; \ 01516 Mask = 0x01; \ 01517 } \ 01518 else \ 01519 { \ 01520 Len = 0; \ 01521 Mask = 0; \ 01522 } 01523 01528 #define UTF8_LENGTH(Char) \ 01529 ((Char) < 0x80 ? 1 : \ 01530 ((Char) < 0x800 ? 2 : \ 01531 ((Char) < 0x10000 ? 3 : \ 01532 ((Char) < 0x200000 ? 4 : \ 01533 ((Char) < 0x4000000 ? 5 : 6))))) 01534 01544 #define UTF8_GET(Result, Chars, Count, Mask, Len) \ 01545 (Result) = (Chars)[0] & (Mask); \ 01546 for ((Count) = 1; (Count) < (Len); ++(Count)) \ 01547 { \ 01548 if (((Chars)[(Count)] & 0xc0) != 0x80) \ 01549 { \ 01550 (Result) = -1; \ 01551 break; \ 01552 } \ 01553 (Result) <<= 6; \ 01554 (Result) |= ((Chars)[(Count)] & 0x3f); \ 01555 } 01556 01567 #define UNICODE_VALID(Char) \ 01568 ((Char) < 0x110000 && \ 01569 (((Char) & 0xFFFFF800) != 0xD800)) 01570 01585 dbus_bool_t 01586 _dbus_string_find (const DBusString *str, 01587 int start, 01588 const char *substr, 01589 int *found) 01590 { 01591 return _dbus_string_find_to (str, start, 01592 ((const DBusRealString*)str)->len, 01593 substr, found); 01594 } 01595 01608 dbus_bool_t 01609 _dbus_string_find_eol (const DBusString *str, 01610 int start, 01611 int *found, 01612 int *found_len) 01613 { 01614 int i; 01615 01616 DBUS_CONST_STRING_PREAMBLE (str); 01617 _dbus_assert (start <= real->len); 01618 _dbus_assert (start >= 0); 01619 01620 i = start; 01621 while (i < real->len) 01622 { 01623 if (real->str[i] == '\r') 01624 { 01625 if ((i+1) < real->len && real->str[i+1] == '\n') /* "\r\n" */ 01626 { 01627 if (found) 01628 *found = i; 01629 if (found_len) 01630 *found_len = 2; 01631 return TRUE; 01632 } 01633 else /* only "\r" */ 01634 { 01635 if (found) 01636 *found = i; 01637 if (found_len) 01638 *found_len = 1; 01639 return TRUE; 01640 } 01641 } 01642 else if (real->str[i] == '\n') /* only "\n" */ 01643 { 01644 if (found) 01645 *found = i; 01646 if (found_len) 01647 *found_len = 1; 01648 return TRUE; 01649 } 01650 ++i; 01651 } 01652 01653 if (found) 01654 *found = real->len; 01655 01656 if (found_len) 01657 *found_len = 0; 01658 01659 return FALSE; 01660 } 01661 01678 dbus_bool_t 01679 _dbus_string_find_to (const DBusString *str, 01680 int start, 01681 int end, 01682 const char *substr, 01683 int *found) 01684 { 01685 int i; 01686 DBUS_CONST_STRING_PREAMBLE (str); 01687 _dbus_assert (substr != NULL); 01688 _dbus_assert (start <= real->len); 01689 _dbus_assert (start >= 0); 01690 _dbus_assert (substr != NULL); 01691 _dbus_assert (end <= real->len); 01692 _dbus_assert (start <= end); 01693 01694 /* we always "find" an empty string */ 01695 if (*substr == '\0') 01696 { 01697 if (found) 01698 *found = start; 01699 return TRUE; 01700 } 01701 01702 i = start; 01703 while (i < end) 01704 { 01705 if (real->str[i] == substr[0]) 01706 { 01707 int j = i + 1; 01708 01709 while (j < end) 01710 { 01711 if (substr[j - i] == '\0') 01712 break; 01713 else if (real->str[j] != substr[j - i]) 01714 break; 01715 01716 ++j; 01717 } 01718 01719 if (substr[j - i] == '\0') 01720 { 01721 if (found) 01722 *found = i; 01723 return TRUE; 01724 } 01725 } 01726 01727 ++i; 01728 } 01729 01730 if (found) 01731 *found = end; 01732 01733 return FALSE; 01734 } 01735 01746 dbus_bool_t 01747 _dbus_string_find_blank (const DBusString *str, 01748 int start, 01749 int *found) 01750 { 01751 int i; 01752 DBUS_CONST_STRING_PREAMBLE (str); 01753 _dbus_assert (start <= real->len); 01754 _dbus_assert (start >= 0); 01755 01756 i = start; 01757 while (i < real->len) 01758 { 01759 if (real->str[i] == ' ' || 01760 real->str[i] == '\t') 01761 { 01762 if (found) 01763 *found = i; 01764 return TRUE; 01765 } 01766 01767 ++i; 01768 } 01769 01770 if (found) 01771 *found = real->len; 01772 01773 return FALSE; 01774 } 01775 01784 void 01785 _dbus_string_skip_blank (const DBusString *str, 01786 int start, 01787 int *end) 01788 { 01789 int i; 01790 DBUS_CONST_STRING_PREAMBLE (str); 01791 _dbus_assert (start <= real->len); 01792 _dbus_assert (start >= 0); 01793 01794 i = start; 01795 while (i < real->len) 01796 { 01797 if (!DBUS_IS_ASCII_BLANK (real->str[i])) 01798 break; 01799 01800 ++i; 01801 } 01802 01803 _dbus_assert (i == real->len || !DBUS_IS_ASCII_WHITE (real->str[i])); 01804 01805 if (end) 01806 *end = i; 01807 } 01808 01809 01818 void 01819 _dbus_string_skip_white (const DBusString *str, 01820 int start, 01821 int *end) 01822 { 01823 int i; 01824 DBUS_CONST_STRING_PREAMBLE (str); 01825 _dbus_assert (start <= real->len); 01826 _dbus_assert (start >= 0); 01827 01828 i = start; 01829 while (i < real->len) 01830 { 01831 if (!DBUS_IS_ASCII_WHITE (real->str[i])) 01832 break; 01833 01834 ++i; 01835 } 01836 01837 _dbus_assert (i == real->len || !(DBUS_IS_ASCII_WHITE (real->str[i]))); 01838 01839 if (end) 01840 *end = i; 01841 } 01842 01851 void 01852 _dbus_string_skip_white_reverse (const DBusString *str, 01853 int end, 01854 int *start) 01855 { 01856 int i; 01857 DBUS_CONST_STRING_PREAMBLE (str); 01858 _dbus_assert (end <= real->len); 01859 _dbus_assert (end >= 0); 01860 01861 i = end; 01862 while (i > 0) 01863 { 01864 if (!DBUS_IS_ASCII_WHITE (real->str[i-1])) 01865 break; 01866 --i; 01867 } 01868 01869 _dbus_assert (i >= 0 && (i == 0 || !(DBUS_IS_ASCII_WHITE (real->str[i-1])))); 01870 01871 if (start) 01872 *start = i; 01873 } 01874 01890 dbus_bool_t 01891 _dbus_string_pop_line (DBusString *source, 01892 DBusString *dest) 01893 { 01894 int eol, eol_len; 01895 01896 _dbus_string_set_length (dest, 0); 01897 01898 eol = 0; 01899 eol_len = 0; 01900 if (!_dbus_string_find_eol (source, 0, &eol, &eol_len)) 01901 { 01902 _dbus_assert (eol == _dbus_string_get_length (source)); 01903 if (eol == 0) 01904 { 01905 /* If there's no newline and source has zero length, we're done */ 01906 return FALSE; 01907 } 01908 /* otherwise, the last line of the file has no eol characters */ 01909 } 01910 01911 /* remember eol can be 0 if it's an empty line, but eol_len should not be zero also 01912 * since find_eol returned TRUE 01913 */ 01914 01915 if (!_dbus_string_move_len (source, 0, eol + eol_len, dest, 0)) 01916 return FALSE; 01917 01918 /* remove line ending */ 01919 if (!_dbus_string_set_length (dest, eol)) 01920 { 01921 _dbus_assert_not_reached ("out of memory when shortening a string"); 01922 return FALSE; 01923 } 01924 01925 return TRUE; 01926 } 01927 01928 #ifdef DBUS_ENABLE_EMBEDDED_TESTS 01929 01935 void 01936 _dbus_string_delete_first_word (DBusString *str) 01937 { 01938 int i; 01939 01940 if (_dbus_string_find_blank (str, 0, &i)) 01941 _dbus_string_skip_blank (str, i, &i); 01942 01943 _dbus_string_delete (str, 0, i); 01944 } 01945 #endif 01946 01947 #ifdef DBUS_ENABLE_EMBEDDED_TESTS 01948 01953 void 01954 _dbus_string_delete_leading_blanks (DBusString *str) 01955 { 01956 int i; 01957 01958 _dbus_string_skip_blank (str, 0, &i); 01959 01960 if (i > 0) 01961 _dbus_string_delete (str, 0, i); 01962 } 01963 #endif 01964 01970 void 01971 _dbus_string_chop_white(DBusString *str) 01972 { 01973 int i; 01974 01975 _dbus_string_skip_white (str, 0, &i); 01976 01977 if (i > 0) 01978 _dbus_string_delete (str, 0, i); 01979 01980 _dbus_string_skip_white_reverse (str, _dbus_string_get_length (str), &i); 01981 01982 _dbus_string_set_length (str, i); 01983 } 01984 01994 dbus_bool_t 01995 _dbus_string_equal (const DBusString *a, 01996 const DBusString *b) 01997 { 01998 const unsigned char *ap; 01999 const unsigned char *bp; 02000 const unsigned char *a_end; 02001 const DBusRealString *real_a = (const DBusRealString*) a; 02002 const DBusRealString *real_b = (const DBusRealString*) b; 02003 DBUS_GENERIC_STRING_PREAMBLE (real_a); 02004 DBUS_GENERIC_STRING_PREAMBLE (real_b); 02005 02006 if (real_a->len != real_b->len) 02007 return FALSE; 02008 02009 ap = real_a->str; 02010 bp = real_b->str; 02011 a_end = real_a->str + real_a->len; 02012 while (ap != a_end) 02013 { 02014 if (*ap != *bp) 02015 return FALSE; 02016 02017 ++ap; 02018 ++bp; 02019 } 02020 02021 return TRUE; 02022 } 02023 02037 dbus_bool_t 02038 _dbus_string_equal_len (const DBusString *a, 02039 const DBusString *b, 02040 int len) 02041 { 02042 const unsigned char *ap; 02043 const unsigned char *bp; 02044 const unsigned char *a_end; 02045 const DBusRealString *real_a = (const DBusRealString*) a; 02046 const DBusRealString *real_b = (const DBusRealString*) b; 02047 DBUS_GENERIC_STRING_PREAMBLE (real_a); 02048 DBUS_GENERIC_STRING_PREAMBLE (real_b); 02049 02050 if (real_a->len != real_b->len && 02051 (real_a->len < len || real_b->len < len)) 02052 return FALSE; 02053 02054 ap = real_a->str; 02055 bp = real_b->str; 02056 a_end = real_a->str + MIN (real_a->len, len); 02057 while (ap != a_end) 02058 { 02059 if (*ap != *bp) 02060 return FALSE; 02061 02062 ++ap; 02063 ++bp; 02064 } 02065 02066 return TRUE; 02067 } 02068 02085 dbus_bool_t 02086 _dbus_string_equal_substring (const DBusString *a, 02087 int a_start, 02088 int a_len, 02089 const DBusString *b, 02090 int b_start) 02091 { 02092 const unsigned char *ap; 02093 const unsigned char *bp; 02094 const unsigned char *a_end; 02095 const DBusRealString *real_a = (const DBusRealString*) a; 02096 const DBusRealString *real_b = (const DBusRealString*) b; 02097 DBUS_GENERIC_STRING_PREAMBLE (real_a); 02098 DBUS_GENERIC_STRING_PREAMBLE (real_b); 02099 _dbus_assert (a_start >= 0); 02100 _dbus_assert (a_len >= 0); 02101 _dbus_assert (a_start <= real_a->len); 02102 _dbus_assert (a_len <= real_a->len - a_start); 02103 _dbus_assert (b_start >= 0); 02104 _dbus_assert (b_start <= real_b->len); 02105 02106 if (a_len > real_b->len - b_start) 02107 return FALSE; 02108 02109 ap = real_a->str + a_start; 02110 bp = real_b->str + b_start; 02111 a_end = ap + a_len; 02112 while (ap != a_end) 02113 { 02114 if (*ap != *bp) 02115 return FALSE; 02116 02117 ++ap; 02118 ++bp; 02119 } 02120 02121 _dbus_assert (bp <= (real_b->str + real_b->len)); 02122 02123 return TRUE; 02124 } 02125 02133 dbus_bool_t 02134 _dbus_string_equal_c_str (const DBusString *a, 02135 const char *c_str) 02136 { 02137 const unsigned char *ap; 02138 const unsigned char *bp; 02139 const unsigned char *a_end; 02140 const DBusRealString *real_a = (const DBusRealString*) a; 02141 DBUS_GENERIC_STRING_PREAMBLE (real_a); 02142 _dbus_assert (c_str != NULL); 02143 02144 ap = real_a->str; 02145 bp = (const unsigned char*) c_str; 02146 a_end = real_a->str + real_a->len; 02147 while (ap != a_end && *bp) 02148 { 02149 if (*ap != *bp) 02150 return FALSE; 02151 02152 ++ap; 02153 ++bp; 02154 } 02155 02156 if (ap != a_end || *bp) 02157 return FALSE; 02158 02159 return TRUE; 02160 } 02161 02169 dbus_bool_t 02170 _dbus_string_starts_with_c_str (const DBusString *a, 02171 const char *c_str) 02172 { 02173 const unsigned char *ap; 02174 const unsigned char *bp; 02175 const unsigned char *a_end; 02176 const DBusRealString *real_a = (const DBusRealString*) a; 02177 DBUS_GENERIC_STRING_PREAMBLE (real_a); 02178 _dbus_assert (c_str != NULL); 02179 02180 ap = real_a->str; 02181 bp = (const unsigned char*) c_str; 02182 a_end = real_a->str + real_a->len; 02183 while (ap != a_end && *bp) 02184 { 02185 if (*ap != *bp) 02186 return FALSE; 02187 02188 ++ap; 02189 ++bp; 02190 } 02191 02192 if (*bp == '\0') 02193 return TRUE; 02194 else 02195 return FALSE; 02196 } 02197 02206 dbus_bool_t 02207 _dbus_string_append_byte_as_hex (DBusString *str, 02208 unsigned char byte) 02209 { 02210 const char hexdigits[16] = { 02211 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 02212 'a', 'b', 'c', 'd', 'e', 'f' 02213 }; 02214 02215 if (!_dbus_string_append_byte (str, 02216 hexdigits[(byte >> 4)])) 02217 return FALSE; 02218 02219 if (!_dbus_string_append_byte (str, 02220 hexdigits[(byte & 0x0f)])) 02221 { 02222 _dbus_string_set_length (str, 02223 _dbus_string_get_length (str) - 1); 02224 return FALSE; 02225 } 02226 02227 return TRUE; 02228 } 02229 02240 dbus_bool_t 02241 _dbus_string_hex_encode (const DBusString *source, 02242 int start, 02243 DBusString *dest, 02244 int insert_at) 02245 { 02246 DBusString result; 02247 const unsigned char *p; 02248 const unsigned char *end; 02249 dbus_bool_t retval; 02250 02251 _dbus_assert (start <= _dbus_string_get_length (source)); 02252 02253 if (!_dbus_string_init (&result)) 02254 return FALSE; 02255 02256 retval = FALSE; 02257 02258 p = (const unsigned char*) _dbus_string_get_const_data (source); 02259 end = p + _dbus_string_get_length (source); 02260 p += start; 02261 02262 while (p != end) 02263 { 02264 if (!_dbus_string_append_byte_as_hex (&result, *p)) 02265 goto out; 02266 02267 ++p; 02268 } 02269 02270 if (!_dbus_string_move (&result, 0, dest, insert_at)) 02271 goto out; 02272 02273 retval = TRUE; 02274 02275 out: 02276 _dbus_string_free (&result); 02277 return retval; 02278 } 02279 02290 dbus_bool_t 02291 _dbus_string_hex_decode (const DBusString *source, 02292 int start, 02293 int *end_return, 02294 DBusString *dest, 02295 int insert_at) 02296 { 02297 DBusString result; 02298 const unsigned char *p; 02299 const unsigned char *end; 02300 dbus_bool_t retval; 02301 dbus_bool_t high_bits; 02302 02303 _dbus_assert (start <= _dbus_string_get_length (source)); 02304 02305 if (!_dbus_string_init (&result)) 02306 return FALSE; 02307 02308 retval = FALSE; 02309 02310 high_bits = TRUE; 02311 p = (const unsigned char*) _dbus_string_get_const_data (source); 02312 end = p + _dbus_string_get_length (source); 02313 p += start; 02314 02315 while (p != end) 02316 { 02317 unsigned int val; 02318 02319 switch (*p) 02320 { 02321 case '0': 02322 val = 0; 02323 break; 02324 case '1': 02325 val = 1; 02326 break; 02327 case '2': 02328 val = 2; 02329 break; 02330 case '3': 02331 val = 3; 02332 break; 02333 case '4': 02334 val = 4; 02335 break; 02336 case '5': 02337 val = 5; 02338 break; 02339 case '6': 02340 val = 6; 02341 break; 02342 case '7': 02343 val = 7; 02344 break; 02345 case '8': 02346 val = 8; 02347 break; 02348 case '9': 02349 val = 9; 02350 break; 02351 case 'a': 02352 case 'A': 02353 val = 10; 02354 break; 02355 case 'b': 02356 case 'B': 02357 val = 11; 02358 break; 02359 case 'c': 02360 case 'C': 02361 val = 12; 02362 break; 02363 case 'd': 02364 case 'D': 02365 val = 13; 02366 break; 02367 case 'e': 02368 case 'E': 02369 val = 14; 02370 break; 02371 case 'f': 02372 case 'F': 02373 val = 15; 02374 break; 02375 default: 02376 goto done; 02377 } 02378 02379 if (high_bits) 02380 { 02381 if (!_dbus_string_append_byte (&result, 02382 val << 4)) 02383 goto out; 02384 } 02385 else 02386 { 02387 int len; 02388 unsigned char b; 02389 02390 len = _dbus_string_get_length (&result); 02391 02392 b = _dbus_string_get_byte (&result, len - 1); 02393 02394 b |= val; 02395 02396 _dbus_string_set_byte (&result, len - 1, b); 02397 } 02398 02399 high_bits = !high_bits; 02400 02401 ++p; 02402 } 02403 02404 done: 02405 if (!_dbus_string_move (&result, 0, dest, insert_at)) 02406 goto out; 02407 02408 if (end_return) 02409 *end_return = p - (const unsigned char*) _dbus_string_get_const_data (source); 02410 02411 retval = TRUE; 02412 02413 out: 02414 _dbus_string_free (&result); 02415 return retval; 02416 } 02417 02431 dbus_bool_t 02432 _dbus_string_validate_ascii (const DBusString *str, 02433 int start, 02434 int len) 02435 { 02436 const unsigned char *s; 02437 const unsigned char *end; 02438 DBUS_CONST_STRING_PREAMBLE (str); 02439 _dbus_assert (start >= 0); 02440 _dbus_assert (start <= real->len); 02441 _dbus_assert (len >= 0); 02442 02443 if (len > real->len - start) 02444 return FALSE; 02445 02446 s = real->str + start; 02447 end = s + len; 02448 while (s != end) 02449 { 02450 if (_DBUS_UNLIKELY (!_DBUS_ISASCII (*s))) 02451 return FALSE; 02452 02453 ++s; 02454 } 02455 02456 return TRUE; 02457 } 02458 02466 void 02467 _dbus_string_tolower_ascii (const DBusString *str, 02468 int start, 02469 int len) 02470 { 02471 unsigned char *s; 02472 unsigned char *end; 02473 DBUS_STRING_PREAMBLE (str); 02474 _dbus_assert (start >= 0); 02475 _dbus_assert (start <= real->len); 02476 _dbus_assert (len >= 0); 02477 _dbus_assert (len <= real->len - start); 02478 02479 s = real->str + start; 02480 end = s + len; 02481 02482 while (s != end) 02483 { 02484 if (*s >= 'A' && *s <= 'Z') 02485 *s += 'a' - 'A'; 02486 ++s; 02487 } 02488 } 02489 02497 void 02498 _dbus_string_toupper_ascii (const DBusString *str, 02499 int start, 02500 int len) 02501 { 02502 unsigned char *s; 02503 unsigned char *end; 02504 DBUS_STRING_PREAMBLE (str); 02505 _dbus_assert (start >= 0); 02506 _dbus_assert (start <= real->len); 02507 _dbus_assert (len >= 0); 02508 _dbus_assert (len <= real->len - start); 02509 02510 s = real->str + start; 02511 end = s + len; 02512 02513 while (s != end) 02514 { 02515 if (*s >= 'a' && *s <= 'z') 02516 *s += 'A' - 'a'; 02517 ++s; 02518 } 02519 } 02520 02536 dbus_bool_t 02537 _dbus_string_validate_utf8 (const DBusString *str, 02538 int start, 02539 int len) 02540 { 02541 const unsigned char *p; 02542 const unsigned char *end; 02543 DBUS_CONST_STRING_PREAMBLE (str); 02544 _dbus_assert (start >= 0); 02545 _dbus_assert (start <= real->len); 02546 _dbus_assert (len >= 0); 02547 02548 /* we are doing _DBUS_UNLIKELY() here which might be 02549 * dubious in a generic library like GLib, but in D-Bus 02550 * we know we're validating messages and that it would 02551 * only be evil/broken apps that would have invalid 02552 * UTF-8. Also, this function seems to be a performance 02553 * bottleneck in profiles. 02554 */ 02555 02556 if (_DBUS_UNLIKELY (len > real->len - start)) 02557 return FALSE; 02558 02559 p = real->str + start; 02560 end = p + len; 02561 02562 while (p < end) 02563 { 02564 int i, mask, char_len; 02565 dbus_unichar_t result; 02566 02567 /* nul bytes considered invalid */ 02568 if (*p == '\0') 02569 break; 02570 02571 /* Special-case ASCII; this makes us go a lot faster in 02572 * D-Bus profiles where we are typically validating 02573 * function names and such. We have to know that 02574 * all following checks will pass for ASCII though, 02575 * comments follow ... 02576 */ 02577 if (*p < 128) 02578 { 02579 ++p; 02580 continue; 02581 } 02582 02583 UTF8_COMPUTE (*p, mask, char_len); 02584 02585 if (_DBUS_UNLIKELY (char_len == 0)) /* ASCII: char_len == 1 */ 02586 break; 02587 02588 /* check that the expected number of bytes exists in the remaining length */ 02589 if (_DBUS_UNLIKELY ((end - p) < char_len)) /* ASCII: p < end and char_len == 1 */ 02590 break; 02591 02592 UTF8_GET (result, p, i, mask, char_len); 02593 02594 /* Check for overlong UTF-8 */ 02595 if (_DBUS_UNLIKELY (UTF8_LENGTH (result) != char_len)) /* ASCII: UTF8_LENGTH == 1 */ 02596 break; 02597 #if 0 02598 /* The UNICODE_VALID check below will catch this */ 02599 if (_DBUS_UNLIKELY (result == (dbus_unichar_t)-1)) /* ASCII: result = ascii value */ 02600 break; 02601 #endif 02602 02603 if (_DBUS_UNLIKELY (!UNICODE_VALID (result))) /* ASCII: always valid */ 02604 break; 02605 02606 /* UNICODE_VALID should have caught it */ 02607 _dbus_assert (result != (dbus_unichar_t)-1); 02608 02609 p += char_len; 02610 } 02611 02612 /* See that we covered the entire length if a length was 02613 * passed in 02614 */ 02615 if (_DBUS_UNLIKELY (p != end)) 02616 return FALSE; 02617 else 02618 return TRUE; 02619 } 02620 02634 dbus_bool_t 02635 _dbus_string_validate_nul (const DBusString *str, 02636 int start, 02637 int len) 02638 { 02639 const unsigned char *s; 02640 const unsigned char *end; 02641 DBUS_CONST_STRING_PREAMBLE (str); 02642 _dbus_assert (start >= 0); 02643 _dbus_assert (len >= 0); 02644 _dbus_assert (start <= real->len); 02645 02646 if (len > real->len - start) 02647 return FALSE; 02648 02649 s = real->str + start; 02650 end = s + len; 02651 while (s != end) 02652 { 02653 if (_DBUS_UNLIKELY (*s != '\0')) 02654 return FALSE; 02655 ++s; 02656 } 02657 02658 return TRUE; 02659 } 02660 02666 void 02667 _dbus_string_zero (DBusString *str) 02668 { 02669 DBUS_STRING_PREAMBLE (str); 02670 02671 memset (real->str - real->align_offset, '\0', real->allocated); 02672 } 02675 /* tests are in dbus-string-util.c */
1.7.6.1