D-Bus
1.10.12
|
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ 00002 /* dbus-string.c String utility class (internal to D-Bus implementation) 00003 * 00004 * Copyright (C) 2002, 2003, 2004, 2005 Red Hat, Inc. 00005 * Copyright (C) 2006 Ralf Habacker <ralf.habacker@freenet.de> 00006 * 00007 * Licensed under the Academic Free License version 2.1 00008 * 00009 * This program is free software; you can redistribute it and/or modify 00010 * it under the terms of the GNU General Public License as published by 00011 * the Free Software Foundation; either version 2 of the License, or 00012 * (at your option) any later version. 00013 * 00014 * This program is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 * GNU General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU General Public License 00020 * along with this program; if not, write to the Free Software 00021 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00022 * 00023 */ 00024 00025 #include <config.h> 00026 #include "dbus-internals.h" 00027 #include "dbus-string.h" 00028 /* we allow a system header here, for speed/convenience */ 00029 #include <string.h> 00030 /* for vsnprintf */ 00031 #include <stdio.h> 00032 #define DBUS_CAN_USE_DBUS_STRING_PRIVATE 1 00033 #include "dbus-string-private.h" 00034 #include "dbus-marshal-basic.h" /* probably should be removed by moving the usage of DBUS_TYPE 00035 * into the marshaling-related files 00036 */ 00037 /* for DBUS_VA_COPY */ 00038 #include "dbus-sysdeps.h" 00039 00078 static void 00079 fixup_alignment (DBusRealString *real) 00080 { 00081 unsigned char *aligned; 00082 unsigned char *real_block; 00083 unsigned int old_align_offset; 00084 00085 /* we have to have extra space in real->allocated for the align offset and nul byte */ 00086 _dbus_assert (real->len <= real->allocated - _DBUS_STRING_ALLOCATION_PADDING); 00087 00088 old_align_offset = real->align_offset; 00089 real_block = real->str - old_align_offset; 00090 00091 aligned = _DBUS_ALIGN_ADDRESS (real_block, 8); 00092 00093 real->align_offset = aligned - real_block; 00094 real->str = aligned; 00095 00096 if (old_align_offset != real->align_offset) 00097 { 00098 /* Here comes the suck */ 00099 memmove (real_block + real->align_offset, 00100 real_block + old_align_offset, 00101 real->len + 1); 00102 } 00103 00104 _dbus_assert (real->align_offset < 8); 00105 _dbus_assert (_DBUS_ALIGN_ADDRESS (real->str, 8) == real->str); 00106 } 00107 00108 static void 00109 undo_alignment (DBusRealString *real) 00110 { 00111 if (real->align_offset != 0) 00112 { 00113 memmove (real->str - real->align_offset, 00114 real->str, 00115 real->len + 1); 00116 00117 real->str = real->str - real->align_offset; 00118 real->align_offset = 0; 00119 } 00120 } 00121 00131 dbus_bool_t 00132 _dbus_string_init_preallocated (DBusString *str, 00133 int allocate_size) 00134 { 00135 DBusRealString *real; 00136 00137 _DBUS_STATIC_ASSERT (sizeof (DBusString) == sizeof (DBusRealString)); 00138 00139 _dbus_assert (str != NULL); 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 00244 dbus_bool_t 00245 _dbus_string_init_from_string(DBusString *str, 00246 const DBusString *from) 00247 { 00248 if (!_dbus_string_init (str)) 00249 return FALSE; 00250 return _dbus_string_append (str, _dbus_string_get_const_data (from)); 00251 } 00252 00258 void 00259 _dbus_string_free (DBusString *str) 00260 { 00261 DBusRealString *real = (DBusRealString*) str; 00262 DBUS_GENERIC_STRING_PREAMBLE (real); 00263 00264 if (real->constant) 00265 return; 00266 00267 /* so it's safe if @p str returned by a failed 00268 * _dbus_string_init call 00269 * Bug: https://bugs.freedesktop.org/show_bug.cgi?id=65959 00270 */ 00271 if (real->str == NULL) 00272 return; 00273 00274 dbus_free (real->str - real->align_offset); 00275 00276 real->invalid = TRUE; 00277 } 00278 00279 static dbus_bool_t 00280 compact (DBusRealString *real, 00281 int max_waste) 00282 { 00283 unsigned char *new_str; 00284 int new_allocated; 00285 int waste; 00286 00287 waste = real->allocated - (real->len + _DBUS_STRING_ALLOCATION_PADDING); 00288 00289 if (waste <= max_waste) 00290 return TRUE; 00291 00292 new_allocated = real->len + _DBUS_STRING_ALLOCATION_PADDING; 00293 00294 new_str = dbus_realloc (real->str - real->align_offset, new_allocated); 00295 if (_DBUS_UNLIKELY (new_str == NULL)) 00296 return FALSE; 00297 00298 real->str = new_str + real->align_offset; 00299 real->allocated = new_allocated; 00300 fixup_alignment (real); 00301 00302 return TRUE; 00303 } 00304 00305 #ifdef DBUS_ENABLE_EMBEDDED_TESTS 00306 /* Not using this feature at the moment, 00307 * so marked DBUS_ENABLE_EMBEDDED_TESTS-only 00308 */ 00318 void 00319 _dbus_string_lock (DBusString *str) 00320 { 00321 DBUS_LOCKED_STRING_PREAMBLE (str); /* can lock multiple times */ 00322 00323 real->locked = TRUE; 00324 00325 /* Try to realloc to avoid excess memory usage, since 00326 * we know we won't change the string further 00327 */ 00328 #define MAX_WASTE 48 00329 compact (real, MAX_WASTE); 00330 } 00331 #endif /* DBUS_ENABLE_EMBEDDED_TESTS */ 00332 00333 static dbus_bool_t 00334 reallocate_for_length (DBusRealString *real, 00335 int new_length) 00336 { 00337 int new_allocated; 00338 unsigned char *new_str; 00339 00340 /* at least double our old allocation to avoid O(n), avoiding 00341 * overflow 00342 */ 00343 if (real->allocated > (_DBUS_STRING_MAX_LENGTH + _DBUS_STRING_ALLOCATION_PADDING) / 2) 00344 new_allocated = _DBUS_STRING_MAX_LENGTH + _DBUS_STRING_ALLOCATION_PADDING; 00345 else 00346 new_allocated = real->allocated * 2; 00347 00348 /* if you change the code just above here, run the tests without 00349 * the following assert-only hack before you commit 00350 */ 00351 /* This is keyed off asserts in addition to tests so when you 00352 * disable asserts to profile, you don't get this destroyer 00353 * of profiles. 00354 */ 00355 #if defined (DBUS_ENABLE_EMBEDDED_TESTS) && !defined (DBUS_DISABLE_ASSERT) 00356 new_allocated = 0; /* ensure a realloc every time so that we go 00357 * through all malloc failure codepaths 00358 */ 00359 #endif 00360 00361 /* But be sure we always alloc at least space for the new length */ 00362 new_allocated = MAX (new_allocated, 00363 new_length + _DBUS_STRING_ALLOCATION_PADDING); 00364 00365 _dbus_assert (new_allocated >= real->allocated); /* code relies on this */ 00366 new_str = dbus_realloc (real->str - real->align_offset, new_allocated); 00367 if (_DBUS_UNLIKELY (new_str == NULL)) 00368 return FALSE; 00369 00370 real->str = new_str + real->align_offset; 00371 real->allocated = new_allocated; 00372 fixup_alignment (real); 00373 00374 return TRUE; 00375 } 00376 00388 dbus_bool_t 00389 _dbus_string_compact (DBusString *str, 00390 int max_waste) 00391 { 00392 DBUS_STRING_PREAMBLE (str); 00393 00394 return compact (real, max_waste); 00395 } 00396 00397 static dbus_bool_t 00398 set_length (DBusRealString *real, 00399 int new_length) 00400 { 00401 /* Note, we are setting the length not including nul termination */ 00402 00403 /* exceeding max length is the same as failure to allocate memory */ 00404 if (_DBUS_UNLIKELY (new_length > _DBUS_STRING_MAX_LENGTH)) 00405 return FALSE; 00406 else if (new_length > (real->allocated - _DBUS_STRING_ALLOCATION_PADDING) && 00407 _DBUS_UNLIKELY (!reallocate_for_length (real, new_length))) 00408 return FALSE; 00409 else 00410 { 00411 real->len = new_length; 00412 real->str[new_length] = '\0'; 00413 return TRUE; 00414 } 00415 } 00416 00417 static dbus_bool_t 00418 open_gap (int len, 00419 DBusRealString *dest, 00420 int insert_at) 00421 { 00422 if (len == 0) 00423 return TRUE; 00424 00425 if (len > _DBUS_STRING_MAX_LENGTH - dest->len) 00426 return FALSE; /* detected overflow of dest->len + len below */ 00427 00428 if (!set_length (dest, dest->len + len)) 00429 return FALSE; 00430 00431 memmove (dest->str + insert_at + len, 00432 dest->str + insert_at, 00433 dest->len - len - insert_at); 00434 00435 return TRUE; 00436 } 00437 00438 #ifndef _dbus_string_get_data 00439 00450 char* 00451 _dbus_string_get_data (DBusString *str) 00452 { 00453 DBUS_STRING_PREAMBLE (str); 00454 00455 return (char*) real->str; 00456 } 00457 #endif /* _dbus_string_get_data */ 00458 00459 /* only do the function if we don't have the macro */ 00460 #ifndef _dbus_string_get_const_data 00461 00467 const char* 00468 _dbus_string_get_const_data (const DBusString *str) 00469 { 00470 DBUS_CONST_STRING_PREAMBLE (str); 00471 00472 return (const char*) real->str; 00473 } 00474 #endif /* _dbus_string_get_const_data */ 00475 00489 char* 00490 _dbus_string_get_data_len (DBusString *str, 00491 int start, 00492 int len) 00493 { 00494 DBUS_STRING_PREAMBLE (str); 00495 _dbus_assert (start >= 0); 00496 _dbus_assert (len >= 0); 00497 _dbus_assert (start <= real->len); 00498 _dbus_assert (len <= real->len - start); 00499 00500 return (char*) real->str + start; 00501 } 00502 00503 /* only do the function if we don't have the macro */ 00504 #ifndef _dbus_string_get_const_data_len 00505 00513 const char* 00514 _dbus_string_get_const_data_len (const DBusString *str, 00515 int start, 00516 int len) 00517 { 00518 DBUS_CONST_STRING_PREAMBLE (str); 00519 _dbus_assert (start >= 0); 00520 _dbus_assert (len >= 0); 00521 _dbus_assert (start <= real->len); 00522 _dbus_assert (len <= real->len - start); 00523 00524 return (const char*) real->str + start; 00525 } 00526 #endif /* _dbus_string_get_const_data_len */ 00527 00528 /* only do the function if we don't have the macro */ 00529 #ifndef _dbus_string_set_byte 00530 00537 void 00538 _dbus_string_set_byte (DBusString *str, 00539 int i, 00540 unsigned char byte) 00541 { 00542 DBUS_STRING_PREAMBLE (str); 00543 _dbus_assert (i < real->len); 00544 _dbus_assert (i >= 0); 00545 00546 real->str[i] = byte; 00547 } 00548 #endif /* _dbus_string_set_byte */ 00549 00550 /* only have the function if we didn't create a macro */ 00551 #ifndef _dbus_string_get_byte 00552 00561 unsigned char 00562 _dbus_string_get_byte (const DBusString *str, 00563 int start) 00564 { 00565 DBUS_CONST_STRING_PREAMBLE (str); 00566 _dbus_assert (start <= real->len); 00567 _dbus_assert (start >= 0); 00568 00569 return real->str[start]; 00570 } 00571 #endif /* _dbus_string_get_byte */ 00572 00583 dbus_bool_t 00584 _dbus_string_insert_bytes (DBusString *str, 00585 int i, 00586 int n_bytes, 00587 unsigned char byte) 00588 { 00589 DBUS_STRING_PREAMBLE (str); 00590 _dbus_assert (i <= real->len); 00591 _dbus_assert (i >= 0); 00592 _dbus_assert (n_bytes >= 0); 00593 00594 if (n_bytes == 0) 00595 return TRUE; 00596 00597 if (!open_gap (n_bytes, real, i)) 00598 return FALSE; 00599 00600 memset (real->str + i, byte, n_bytes); 00601 00602 return TRUE; 00603 } 00604 00613 dbus_bool_t 00614 _dbus_string_insert_byte (DBusString *str, 00615 int i, 00616 unsigned char byte) 00617 { 00618 DBUS_STRING_PREAMBLE (str); 00619 _dbus_assert (i <= real->len); 00620 _dbus_assert (i >= 0); 00621 00622 if (!open_gap (1, real, i)) 00623 return FALSE; 00624 00625 real->str[i] = byte; 00626 00627 return TRUE; 00628 } 00629 00640 dbus_bool_t 00641 _dbus_string_steal_data (DBusString *str, 00642 char **data_return) 00643 { 00644 DBUS_STRING_PREAMBLE (str); 00645 _dbus_assert (data_return != NULL); 00646 00647 undo_alignment (real); 00648 00649 *data_return = (char*) real->str; 00650 00651 /* reset the string */ 00652 if (!_dbus_string_init (str)) 00653 { 00654 /* hrm, put it back then */ 00655 real->str = (unsigned char*) *data_return; 00656 *data_return = NULL; 00657 fixup_alignment (real); 00658 return FALSE; 00659 } 00660 00661 return TRUE; 00662 } 00663 00671 dbus_bool_t 00672 _dbus_string_copy_data (const DBusString *str, 00673 char **data_return) 00674 { 00675 DBUS_CONST_STRING_PREAMBLE (str); 00676 _dbus_assert (data_return != NULL); 00677 00678 *data_return = dbus_malloc (real->len + 1); 00679 if (*data_return == NULL) 00680 return FALSE; 00681 00682 memcpy (*data_return, real->str, real->len + 1); 00683 00684 return TRUE; 00685 } 00686 00696 void 00697 _dbus_string_copy_to_buffer (const DBusString *str, 00698 char *buffer, 00699 int avail_len) 00700 { 00701 DBUS_CONST_STRING_PREAMBLE (str); 00702 00703 _dbus_assert (avail_len >= 0); 00704 _dbus_assert (avail_len >= real->len); 00705 00706 memcpy (buffer, real->str, real->len); 00707 } 00708 00718 void 00719 _dbus_string_copy_to_buffer_with_nul (const DBusString *str, 00720 char *buffer, 00721 int avail_len) 00722 { 00723 DBUS_CONST_STRING_PREAMBLE (str); 00724 00725 _dbus_assert (avail_len >= 0); 00726 _dbus_assert (avail_len > real->len); 00727 00728 memcpy (buffer, real->str, real->len+1); 00729 } 00730 00731 /* Only have the function if we don't have the macro */ 00732 #ifndef _dbus_string_get_length 00733 00738 int 00739 _dbus_string_get_length (const DBusString *str) 00740 { 00741 DBUS_CONST_STRING_PREAMBLE (str); 00742 00743 return real->len; 00744 } 00745 #endif /* !_dbus_string_get_length */ 00746 00759 dbus_bool_t 00760 _dbus_string_lengthen (DBusString *str, 00761 int additional_length) 00762 { 00763 DBUS_STRING_PREAMBLE (str); 00764 _dbus_assert (additional_length >= 0); 00765 00766 if (_DBUS_UNLIKELY (additional_length > _DBUS_STRING_MAX_LENGTH - real->len)) 00767 return FALSE; /* would overflow */ 00768 00769 return set_length (real, 00770 real->len + additional_length); 00771 } 00772 00779 void 00780 _dbus_string_shorten (DBusString *str, 00781 int length_to_remove) 00782 { 00783 DBUS_STRING_PREAMBLE (str); 00784 _dbus_assert (length_to_remove >= 0); 00785 _dbus_assert (length_to_remove <= real->len); 00786 00787 set_length (real, 00788 real->len - length_to_remove); 00789 } 00790 00801 dbus_bool_t 00802 _dbus_string_set_length (DBusString *str, 00803 int length) 00804 { 00805 DBUS_STRING_PREAMBLE (str); 00806 _dbus_assert (length >= 0); 00807 00808 return set_length (real, length); 00809 } 00810 00811 static dbus_bool_t 00812 align_insert_point_then_open_gap (DBusString *str, 00813 int *insert_at_p, 00814 int alignment, 00815 int gap_size) 00816 { 00817 unsigned long new_len; /* ulong to avoid _DBUS_ALIGN_VALUE overflow */ 00818 unsigned long gap_pos; 00819 int insert_at; 00820 int delta; 00821 DBUS_STRING_PREAMBLE (str); 00822 _dbus_assert (alignment >= 1); 00823 _dbus_assert (alignment <= 8); /* it has to be a bug if > 8 */ 00824 00825 insert_at = *insert_at_p; 00826 00827 _dbus_assert (insert_at <= real->len); 00828 00829 gap_pos = _DBUS_ALIGN_VALUE (insert_at, alignment); 00830 new_len = real->len + (gap_pos - insert_at) + gap_size; 00831 00832 if (_DBUS_UNLIKELY (new_len > (unsigned long) _DBUS_STRING_MAX_LENGTH)) 00833 return FALSE; 00834 00835 delta = new_len - real->len; 00836 _dbus_assert (delta >= 0); 00837 00838 if (delta == 0) /* only happens if gap_size == 0 and insert_at is aligned already */ 00839 { 00840 _dbus_assert (((unsigned long) *insert_at_p) == gap_pos); 00841 return TRUE; 00842 } 00843 00844 if (_DBUS_UNLIKELY (!open_gap (new_len - real->len, 00845 real, insert_at))) 00846 return FALSE; 00847 00848 /* nul the padding if we had to add any padding */ 00849 if (gap_size < delta) 00850 { 00851 memset (&real->str[insert_at], '\0', 00852 gap_pos - insert_at); 00853 } 00854 00855 *insert_at_p = gap_pos; 00856 00857 return TRUE; 00858 } 00859 00860 static dbus_bool_t 00861 align_length_then_lengthen (DBusString *str, 00862 int alignment, 00863 int then_lengthen_by) 00864 { 00865 int insert_at; 00866 00867 insert_at = _dbus_string_get_length (str); 00868 00869 return align_insert_point_then_open_gap (str, 00870 &insert_at, 00871 alignment, then_lengthen_by); 00872 } 00873 00882 dbus_bool_t 00883 _dbus_string_align_length (DBusString *str, 00884 int alignment) 00885 { 00886 return align_length_then_lengthen (str, alignment, 0); 00887 } 00888 00898 dbus_bool_t 00899 _dbus_string_alloc_space (DBusString *str, 00900 int extra_bytes) 00901 { 00902 if (!_dbus_string_lengthen (str, extra_bytes)) 00903 return FALSE; 00904 _dbus_string_shorten (str, extra_bytes); 00905 00906 return TRUE; 00907 } 00908 00909 static dbus_bool_t 00910 append (DBusRealString *real, 00911 const char *buffer, 00912 int buffer_len) 00913 { 00914 if (buffer_len == 0) 00915 return TRUE; 00916 00917 if (!_dbus_string_lengthen ((DBusString*)real, buffer_len)) 00918 return FALSE; 00919 00920 memcpy (real->str + (real->len - buffer_len), 00921 buffer, 00922 buffer_len); 00923 00924 return TRUE; 00925 } 00926 00934 dbus_bool_t 00935 _dbus_string_append (DBusString *str, 00936 const char *buffer) 00937 { 00938 unsigned long buffer_len; 00939 00940 DBUS_STRING_PREAMBLE (str); 00941 _dbus_assert (buffer != NULL); 00942 00943 buffer_len = strlen (buffer); 00944 if (buffer_len > (unsigned long) _DBUS_STRING_MAX_LENGTH) 00945 return FALSE; 00946 00947 return append (real, buffer, buffer_len); 00948 } 00949 00951 #define ASSIGN_2_OCTETS(p, octets) \ 00952 *((dbus_uint16_t*)(p)) = *((dbus_uint16_t*)(octets)); 00953 00955 #define ASSIGN_4_OCTETS(p, octets) \ 00956 *((dbus_uint32_t*)(p)) = *((dbus_uint32_t*)(octets)); 00957 00959 #define ASSIGN_8_OCTETS(p, octets) \ 00960 *((dbus_uint64_t*)(p)) = *((dbus_uint64_t*)(octets)); 00961 00971 dbus_bool_t 00972 _dbus_string_insert_2_aligned (DBusString *str, 00973 int insert_at, 00974 const unsigned char octets[2]) 00975 { 00976 DBUS_STRING_PREAMBLE (str); 00977 00978 if (!align_insert_point_then_open_gap (str, &insert_at, 2, 2)) 00979 return FALSE; 00980 00981 ASSIGN_2_OCTETS (real->str + insert_at, octets); 00982 00983 return TRUE; 00984 } 00985 00995 dbus_bool_t 00996 _dbus_string_insert_4_aligned (DBusString *str, 00997 int insert_at, 00998 const unsigned char octets[4]) 00999 { 01000 DBUS_STRING_PREAMBLE (str); 01001 01002 if (!align_insert_point_then_open_gap (str, &insert_at, 4, 4)) 01003 return FALSE; 01004 01005 ASSIGN_4_OCTETS (real->str + insert_at, octets); 01006 01007 return TRUE; 01008 } 01009 01019 dbus_bool_t 01020 _dbus_string_insert_8_aligned (DBusString *str, 01021 int insert_at, 01022 const unsigned char octets[8]) 01023 { 01024 DBUS_STRING_PREAMBLE (str); 01025 01026 if (!align_insert_point_then_open_gap (str, &insert_at, 8, 8)) 01027 return FALSE; 01028 01029 _dbus_assert (_DBUS_ALIGN_VALUE (insert_at, 8) == (unsigned) insert_at); 01030 01031 ASSIGN_8_OCTETS (real->str + insert_at, octets); 01032 01033 return TRUE; 01034 } 01035 01036 01047 dbus_bool_t 01048 _dbus_string_insert_alignment (DBusString *str, 01049 int *insert_at, 01050 int alignment) 01051 { 01052 DBUS_STRING_PREAMBLE (str); 01053 01054 if (!align_insert_point_then_open_gap (str, insert_at, alignment, 0)) 01055 return FALSE; 01056 01057 _dbus_assert (_DBUS_ALIGN_VALUE (*insert_at, alignment) == (unsigned) *insert_at); 01058 01059 return TRUE; 01060 } 01061 01071 dbus_bool_t 01072 _dbus_string_append_printf_valist (DBusString *str, 01073 const char *format, 01074 va_list args) 01075 { 01076 dbus_bool_t ret = FALSE; 01077 int len; 01078 va_list args_copy; 01079 01080 DBUS_STRING_PREAMBLE (str); 01081 01082 DBUS_VA_COPY (args_copy, args); 01083 01084 /* Measure the message length without terminating nul */ 01085 len = _dbus_printf_string_upper_bound (format, args); 01086 01087 if (len < 0) 01088 goto out; 01089 01090 if (!_dbus_string_lengthen (str, len)) 01091 { 01092 goto out; 01093 } 01094 01095 vsprintf ((char*) (real->str + (real->len - len)), 01096 format, args_copy); 01097 ret = TRUE; 01098 01099 out: 01100 va_end (args_copy); 01101 01102 return ret; 01103 } 01104 01113 dbus_bool_t 01114 _dbus_string_append_printf (DBusString *str, 01115 const char *format, 01116 ...) 01117 { 01118 va_list args; 01119 dbus_bool_t retval; 01120 01121 va_start (args, format); 01122 retval = _dbus_string_append_printf_valist (str, format, args); 01123 va_end (args); 01124 01125 return retval; 01126 } 01127 01136 dbus_bool_t 01137 _dbus_string_append_len (DBusString *str, 01138 const char *buffer, 01139 int len) 01140 { 01141 DBUS_STRING_PREAMBLE (str); 01142 _dbus_assert (buffer != NULL); 01143 _dbus_assert (len >= 0); 01144 01145 return append (real, buffer, len); 01146 } 01147 01156 dbus_bool_t 01157 _dbus_string_append_byte (DBusString *str, 01158 unsigned char byte) 01159 { 01160 DBUS_STRING_PREAMBLE (str); 01161 01162 if (!set_length (real, real->len + 1)) 01163 return FALSE; 01164 01165 real->str[real->len-1] = byte; 01166 01167 return TRUE; 01168 } 01169 01170 static void 01171 delete (DBusRealString *real, 01172 int start, 01173 int len) 01174 { 01175 if (len == 0) 01176 return; 01177 01178 memmove (real->str + start, real->str + start + len, real->len - (start + len)); 01179 real->len -= len; 01180 real->str[real->len] = '\0'; 01181 } 01182 01192 void 01193 _dbus_string_delete (DBusString *str, 01194 int start, 01195 int len) 01196 { 01197 DBUS_STRING_PREAMBLE (str); 01198 _dbus_assert (start >= 0); 01199 _dbus_assert (len >= 0); 01200 _dbus_assert (start <= real->len); 01201 _dbus_assert (len <= real->len - start); 01202 01203 delete (real, start, len); 01204 } 01205 01206 static dbus_bool_t 01207 copy (DBusRealString *source, 01208 int start, 01209 int len, 01210 DBusRealString *dest, 01211 int insert_at) 01212 { 01213 if (len == 0) 01214 return TRUE; 01215 01216 if (!open_gap (len, dest, insert_at)) 01217 return FALSE; 01218 01219 memmove (dest->str + insert_at, 01220 source->str + start, 01221 len); 01222 01223 return TRUE; 01224 } 01225 01235 #define DBUS_STRING_COPY_PREAMBLE(source, start, dest, insert_at) \ 01236 DBusRealString *real_source = (DBusRealString*) source; \ 01237 DBusRealString *real_dest = (DBusRealString*) dest; \ 01238 _dbus_assert ((source) != (dest)); \ 01239 DBUS_GENERIC_STRING_PREAMBLE (real_source); \ 01240 DBUS_GENERIC_STRING_PREAMBLE (real_dest); \ 01241 _dbus_assert (!real_dest->constant); \ 01242 _dbus_assert (!real_dest->locked); \ 01243 _dbus_assert ((start) >= 0); \ 01244 _dbus_assert ((start) <= real_source->len); \ 01245 _dbus_assert ((insert_at) >= 0); \ 01246 _dbus_assert ((insert_at) <= real_dest->len) 01247 01258 dbus_bool_t 01259 _dbus_string_move (DBusString *source, 01260 int start, 01261 DBusString *dest, 01262 int insert_at) 01263 { 01264 DBusRealString *real_source = (DBusRealString*) source; 01265 _dbus_assert (start <= real_source->len); 01266 01267 return _dbus_string_move_len (source, start, 01268 real_source->len - start, 01269 dest, insert_at); 01270 } 01271 01282 dbus_bool_t 01283 _dbus_string_copy (const DBusString *source, 01284 int start, 01285 DBusString *dest, 01286 int insert_at) 01287 { 01288 DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at); 01289 01290 return copy (real_source, start, 01291 real_source->len - start, 01292 real_dest, 01293 insert_at); 01294 } 01295 01307 dbus_bool_t 01308 _dbus_string_move_len (DBusString *source, 01309 int start, 01310 int len, 01311 DBusString *dest, 01312 int insert_at) 01313 01314 { 01315 DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at); 01316 _dbus_assert (len >= 0); 01317 _dbus_assert ((start + len) <= real_source->len); 01318 01319 01320 if (len == 0) 01321 { 01322 return TRUE; 01323 } 01324 else if (start == 0 && 01325 len == real_source->len && 01326 real_dest->len == 0) 01327 { 01328 /* Short-circuit moving an entire existing string to an empty string 01329 * by just swapping the buffers. 01330 */ 01331 /* we assume ->constant doesn't matter as you can't have 01332 * a constant string involved in a move. 01333 */ 01334 #define ASSIGN_DATA(a, b) do { \ 01335 (a)->str = (b)->str; \ 01336 (a)->len = (b)->len; \ 01337 (a)->allocated = (b)->allocated; \ 01338 (a)->align_offset = (b)->align_offset; \ 01339 } while (0) 01340 01341 DBusRealString tmp; 01342 01343 ASSIGN_DATA (&tmp, real_source); 01344 ASSIGN_DATA (real_source, real_dest); 01345 ASSIGN_DATA (real_dest, &tmp); 01346 01347 return TRUE; 01348 } 01349 else 01350 { 01351 if (!copy (real_source, start, len, 01352 real_dest, 01353 insert_at)) 01354 return FALSE; 01355 01356 delete (real_source, start, 01357 len); 01358 01359 return TRUE; 01360 } 01361 } 01362 01374 dbus_bool_t 01375 _dbus_string_copy_len (const DBusString *source, 01376 int start, 01377 int len, 01378 DBusString *dest, 01379 int insert_at) 01380 { 01381 DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at); 01382 _dbus_assert (len >= 0); 01383 _dbus_assert (start <= real_source->len); 01384 _dbus_assert (len <= real_source->len - start); 01385 01386 return copy (real_source, start, len, 01387 real_dest, 01388 insert_at); 01389 } 01390 01403 dbus_bool_t 01404 _dbus_string_replace_len (const DBusString *source, 01405 int start, 01406 int len, 01407 DBusString *dest, 01408 int replace_at, 01409 int replace_len) 01410 { 01411 DBUS_STRING_COPY_PREAMBLE (source, start, dest, replace_at); 01412 _dbus_assert (len >= 0); 01413 _dbus_assert (start <= real_source->len); 01414 _dbus_assert (len <= real_source->len - start); 01415 _dbus_assert (replace_at >= 0); 01416 _dbus_assert (replace_at <= real_dest->len); 01417 _dbus_assert (replace_len <= real_dest->len - replace_at); 01418 01419 if (len == replace_len) 01420 { 01421 memmove (real_dest->str + replace_at, 01422 real_source->str + start, len); 01423 } 01424 else if (len < replace_len) 01425 { 01426 memmove (real_dest->str + replace_at, 01427 real_source->str + start, len); 01428 delete (real_dest, replace_at + len, 01429 replace_len - len); 01430 } 01431 else 01432 { 01433 int diff; 01434 01435 _dbus_assert (len > replace_len); 01436 01437 diff = len - replace_len; 01438 01439 /* First of all we check if destination string can be enlarged as 01440 * required, then we overwrite previous bytes 01441 */ 01442 01443 if (!copy (real_source, start + replace_len, diff, 01444 real_dest, replace_at + replace_len)) 01445 return FALSE; 01446 01447 memmove (real_dest->str + replace_at, 01448 real_source->str + start, replace_len); 01449 } 01450 01451 return TRUE; 01452 } 01453 01466 dbus_bool_t 01467 _dbus_string_split_on_byte (DBusString *source, 01468 unsigned char byte, 01469 DBusString *tail) 01470 { 01471 int byte_position; 01472 char byte_string[2] = ""; 01473 int head_length; 01474 int tail_length; 01475 01476 byte_string[0] = (char) byte; 01477 01478 if (!_dbus_string_find (source, 0, byte_string, &byte_position)) 01479 return FALSE; 01480 01481 head_length = byte_position; 01482 tail_length = _dbus_string_get_length (source) - head_length - 1; 01483 01484 if (!_dbus_string_move_len (source, byte_position + 1, tail_length, 01485 tail, 0)) 01486 return FALSE; 01487 01488 /* remove the trailing delimiter byte from the head now. 01489 */ 01490 if (!_dbus_string_set_length (source, head_length)) 01491 return FALSE; 01492 01493 return TRUE; 01494 } 01495 01496 /* Unicode macros and utf8_validate() from GLib Owen Taylor, Havoc 01497 * Pennington, and Tom Tromey are the authors and authorized relicense. 01498 */ 01499 01505 #define UTF8_COMPUTE(Char, Mask, Len) \ 01506 if (Char < 128) \ 01507 { \ 01508 Len = 1; \ 01509 Mask = 0x7f; \ 01510 } \ 01511 else if ((Char & 0xe0) == 0xc0) \ 01512 { \ 01513 Len = 2; \ 01514 Mask = 0x1f; \ 01515 } \ 01516 else if ((Char & 0xf0) == 0xe0) \ 01517 { \ 01518 Len = 3; \ 01519 Mask = 0x0f; \ 01520 } \ 01521 else if ((Char & 0xf8) == 0xf0) \ 01522 { \ 01523 Len = 4; \ 01524 Mask = 0x07; \ 01525 } \ 01526 else if ((Char & 0xfc) == 0xf8) \ 01527 { \ 01528 Len = 5; \ 01529 Mask = 0x03; \ 01530 } \ 01531 else if ((Char & 0xfe) == 0xfc) \ 01532 { \ 01533 Len = 6; \ 01534 Mask = 0x01; \ 01535 } \ 01536 else \ 01537 { \ 01538 Len = 0; \ 01539 Mask = 0; \ 01540 } 01541 01546 #define UTF8_LENGTH(Char) \ 01547 ((Char) < 0x80 ? 1 : \ 01548 ((Char) < 0x800 ? 2 : \ 01549 ((Char) < 0x10000 ? 3 : \ 01550 ((Char) < 0x200000 ? 4 : \ 01551 ((Char) < 0x4000000 ? 5 : 6))))) 01552 01562 #define UTF8_GET(Result, Chars, Count, Mask, Len) \ 01563 (Result) = (Chars)[0] & (Mask); \ 01564 for ((Count) = 1; (Count) < (Len); ++(Count)) \ 01565 { \ 01566 if (((Chars)[(Count)] & 0xc0) != 0x80) \ 01567 { \ 01568 (Result) = -1; \ 01569 break; \ 01570 } \ 01571 (Result) <<= 6; \ 01572 (Result) |= ((Chars)[(Count)] & 0x3f); \ 01573 } 01574 01585 #define UNICODE_VALID(Char) \ 01586 ((Char) < 0x110000 && \ 01587 (((Char) & 0xFFFFF800) != 0xD800)) 01588 01603 dbus_bool_t 01604 _dbus_string_find (const DBusString *str, 01605 int start, 01606 const char *substr, 01607 int *found) 01608 { 01609 return _dbus_string_find_to (str, start, 01610 ((const DBusRealString*)str)->len, 01611 substr, found); 01612 } 01613 01626 dbus_bool_t 01627 _dbus_string_find_eol (const DBusString *str, 01628 int start, 01629 int *found, 01630 int *found_len) 01631 { 01632 int i; 01633 01634 DBUS_CONST_STRING_PREAMBLE (str); 01635 _dbus_assert (start <= real->len); 01636 _dbus_assert (start >= 0); 01637 01638 i = start; 01639 while (i < real->len) 01640 { 01641 if (real->str[i] == '\r') 01642 { 01643 if ((i+1) < real->len && real->str[i+1] == '\n') /* "\r\n" */ 01644 { 01645 if (found) 01646 *found = i; 01647 if (found_len) 01648 *found_len = 2; 01649 return TRUE; 01650 } 01651 else /* only "\r" */ 01652 { 01653 if (found) 01654 *found = i; 01655 if (found_len) 01656 *found_len = 1; 01657 return TRUE; 01658 } 01659 } 01660 else if (real->str[i] == '\n') /* only "\n" */ 01661 { 01662 if (found) 01663 *found = i; 01664 if (found_len) 01665 *found_len = 1; 01666 return TRUE; 01667 } 01668 ++i; 01669 } 01670 01671 if (found) 01672 *found = real->len; 01673 01674 if (found_len) 01675 *found_len = 0; 01676 01677 return FALSE; 01678 } 01679 01696 dbus_bool_t 01697 _dbus_string_find_to (const DBusString *str, 01698 int start, 01699 int end, 01700 const char *substr, 01701 int *found) 01702 { 01703 int i; 01704 DBUS_CONST_STRING_PREAMBLE (str); 01705 _dbus_assert (substr != NULL); 01706 _dbus_assert (start <= real->len); 01707 _dbus_assert (start >= 0); 01708 _dbus_assert (substr != NULL); 01709 _dbus_assert (end <= real->len); 01710 _dbus_assert (start <= end); 01711 01712 /* we always "find" an empty string */ 01713 if (*substr == '\0') 01714 { 01715 if (found) 01716 *found = start; 01717 return TRUE; 01718 } 01719 01720 i = start; 01721 while (i < end) 01722 { 01723 if (real->str[i] == substr[0]) 01724 { 01725 int j = i + 1; 01726 01727 while (j < end) 01728 { 01729 if (substr[j - i] == '\0') 01730 break; 01731 else if (real->str[j] != substr[j - i]) 01732 break; 01733 01734 ++j; 01735 } 01736 01737 if (substr[j - i] == '\0') 01738 { 01739 if (found) 01740 *found = i; 01741 return TRUE; 01742 } 01743 } 01744 01745 ++i; 01746 } 01747 01748 if (found) 01749 *found = end; 01750 01751 return FALSE; 01752 } 01753 01764 dbus_bool_t 01765 _dbus_string_find_blank (const DBusString *str, 01766 int start, 01767 int *found) 01768 { 01769 int i; 01770 DBUS_CONST_STRING_PREAMBLE (str); 01771 _dbus_assert (start <= real->len); 01772 _dbus_assert (start >= 0); 01773 01774 i = start; 01775 while (i < real->len) 01776 { 01777 if (real->str[i] == ' ' || 01778 real->str[i] == '\t') 01779 { 01780 if (found) 01781 *found = i; 01782 return TRUE; 01783 } 01784 01785 ++i; 01786 } 01787 01788 if (found) 01789 *found = real->len; 01790 01791 return FALSE; 01792 } 01793 01802 void 01803 _dbus_string_skip_blank (const DBusString *str, 01804 int start, 01805 int *end) 01806 { 01807 int i; 01808 DBUS_CONST_STRING_PREAMBLE (str); 01809 _dbus_assert (start <= real->len); 01810 _dbus_assert (start >= 0); 01811 01812 i = start; 01813 while (i < real->len) 01814 { 01815 if (!DBUS_IS_ASCII_BLANK (real->str[i])) 01816 break; 01817 01818 ++i; 01819 } 01820 01821 _dbus_assert (i == real->len || !DBUS_IS_ASCII_WHITE (real->str[i])); 01822 01823 if (end) 01824 *end = i; 01825 } 01826 01827 01836 void 01837 _dbus_string_skip_white (const DBusString *str, 01838 int start, 01839 int *end) 01840 { 01841 int i; 01842 DBUS_CONST_STRING_PREAMBLE (str); 01843 _dbus_assert (start <= real->len); 01844 _dbus_assert (start >= 0); 01845 01846 i = start; 01847 while (i < real->len) 01848 { 01849 if (!DBUS_IS_ASCII_WHITE (real->str[i])) 01850 break; 01851 01852 ++i; 01853 } 01854 01855 _dbus_assert (i == real->len || !(DBUS_IS_ASCII_WHITE (real->str[i]))); 01856 01857 if (end) 01858 *end = i; 01859 } 01860 01869 void 01870 _dbus_string_skip_white_reverse (const DBusString *str, 01871 int end, 01872 int *start) 01873 { 01874 int i; 01875 DBUS_CONST_STRING_PREAMBLE (str); 01876 _dbus_assert (end <= real->len); 01877 _dbus_assert (end >= 0); 01878 01879 i = end; 01880 while (i > 0) 01881 { 01882 if (!DBUS_IS_ASCII_WHITE (real->str[i-1])) 01883 break; 01884 --i; 01885 } 01886 01887 _dbus_assert (i >= 0 && (i == 0 || !(DBUS_IS_ASCII_WHITE (real->str[i-1])))); 01888 01889 if (start) 01890 *start = i; 01891 } 01892 01908 dbus_bool_t 01909 _dbus_string_pop_line (DBusString *source, 01910 DBusString *dest) 01911 { 01912 int eol, eol_len; 01913 01914 _dbus_string_set_length (dest, 0); 01915 01916 eol = 0; 01917 eol_len = 0; 01918 if (!_dbus_string_find_eol (source, 0, &eol, &eol_len)) 01919 { 01920 _dbus_assert (eol == _dbus_string_get_length (source)); 01921 if (eol == 0) 01922 { 01923 /* If there's no newline and source has zero length, we're done */ 01924 return FALSE; 01925 } 01926 /* otherwise, the last line of the file has no eol characters */ 01927 } 01928 01929 /* remember eol can be 0 if it's an empty line, but eol_len should not be zero also 01930 * since find_eol returned TRUE 01931 */ 01932 01933 if (!_dbus_string_move_len (source, 0, eol + eol_len, dest, 0)) 01934 return FALSE; 01935 01936 /* remove line ending */ 01937 if (!_dbus_string_set_length (dest, eol)) 01938 { 01939 _dbus_assert_not_reached ("out of memory when shortening a string"); 01940 return FALSE; 01941 } 01942 01943 return TRUE; 01944 } 01945 01946 #ifdef DBUS_ENABLE_EMBEDDED_TESTS 01947 01953 void 01954 _dbus_string_delete_first_word (DBusString *str) 01955 { 01956 int i; 01957 01958 if (_dbus_string_find_blank (str, 0, &i)) 01959 _dbus_string_skip_blank (str, i, &i); 01960 01961 _dbus_string_delete (str, 0, i); 01962 } 01963 #endif 01964 01965 #ifdef DBUS_ENABLE_EMBEDDED_TESTS 01966 01971 void 01972 _dbus_string_delete_leading_blanks (DBusString *str) 01973 { 01974 int i; 01975 01976 _dbus_string_skip_blank (str, 0, &i); 01977 01978 if (i > 0) 01979 _dbus_string_delete (str, 0, i); 01980 } 01981 #endif 01982 01988 void 01989 _dbus_string_chop_white(DBusString *str) 01990 { 01991 int i; 01992 01993 _dbus_string_skip_white (str, 0, &i); 01994 01995 if (i > 0) 01996 _dbus_string_delete (str, 0, i); 01997 01998 _dbus_string_skip_white_reverse (str, _dbus_string_get_length (str), &i); 01999 02000 _dbus_string_set_length (str, i); 02001 } 02002 02012 dbus_bool_t 02013 _dbus_string_equal (const DBusString *a, 02014 const DBusString *b) 02015 { 02016 const unsigned char *ap; 02017 const unsigned char *bp; 02018 const unsigned char *a_end; 02019 const DBusRealString *real_a = (const DBusRealString*) a; 02020 const DBusRealString *real_b = (const DBusRealString*) b; 02021 DBUS_GENERIC_STRING_PREAMBLE (real_a); 02022 DBUS_GENERIC_STRING_PREAMBLE (real_b); 02023 02024 if (real_a->len != real_b->len) 02025 return FALSE; 02026 02027 ap = real_a->str; 02028 bp = real_b->str; 02029 a_end = real_a->str + real_a->len; 02030 while (ap != a_end) 02031 { 02032 if (*ap != *bp) 02033 return FALSE; 02034 02035 ++ap; 02036 ++bp; 02037 } 02038 02039 return TRUE; 02040 } 02041 02055 dbus_bool_t 02056 _dbus_string_equal_len (const DBusString *a, 02057 const DBusString *b, 02058 int len) 02059 { 02060 const unsigned char *ap; 02061 const unsigned char *bp; 02062 const unsigned char *a_end; 02063 const DBusRealString *real_a = (const DBusRealString*) a; 02064 const DBusRealString *real_b = (const DBusRealString*) b; 02065 DBUS_GENERIC_STRING_PREAMBLE (real_a); 02066 DBUS_GENERIC_STRING_PREAMBLE (real_b); 02067 02068 if (real_a->len != real_b->len && 02069 (real_a->len < len || real_b->len < len)) 02070 return FALSE; 02071 02072 ap = real_a->str; 02073 bp = real_b->str; 02074 a_end = real_a->str + MIN (real_a->len, len); 02075 while (ap != a_end) 02076 { 02077 if (*ap != *bp) 02078 return FALSE; 02079 02080 ++ap; 02081 ++bp; 02082 } 02083 02084 return TRUE; 02085 } 02086 02103 dbus_bool_t 02104 _dbus_string_equal_substring (const DBusString *a, 02105 int a_start, 02106 int a_len, 02107 const DBusString *b, 02108 int b_start) 02109 { 02110 const unsigned char *ap; 02111 const unsigned char *bp; 02112 const unsigned char *a_end; 02113 const DBusRealString *real_a = (const DBusRealString*) a; 02114 const DBusRealString *real_b = (const DBusRealString*) b; 02115 DBUS_GENERIC_STRING_PREAMBLE (real_a); 02116 DBUS_GENERIC_STRING_PREAMBLE (real_b); 02117 _dbus_assert (a_start >= 0); 02118 _dbus_assert (a_len >= 0); 02119 _dbus_assert (a_start <= real_a->len); 02120 _dbus_assert (a_len <= real_a->len - a_start); 02121 _dbus_assert (b_start >= 0); 02122 _dbus_assert (b_start <= real_b->len); 02123 02124 if (a_len > real_b->len - b_start) 02125 return FALSE; 02126 02127 ap = real_a->str + a_start; 02128 bp = real_b->str + b_start; 02129 a_end = ap + a_len; 02130 while (ap != a_end) 02131 { 02132 if (*ap != *bp) 02133 return FALSE; 02134 02135 ++ap; 02136 ++bp; 02137 } 02138 02139 _dbus_assert (bp <= (real_b->str + real_b->len)); 02140 02141 return TRUE; 02142 } 02143 02151 dbus_bool_t 02152 _dbus_string_equal_c_str (const DBusString *a, 02153 const char *c_str) 02154 { 02155 const unsigned char *ap; 02156 const unsigned char *bp; 02157 const unsigned char *a_end; 02158 const DBusRealString *real_a = (const DBusRealString*) a; 02159 DBUS_GENERIC_STRING_PREAMBLE (real_a); 02160 _dbus_assert (c_str != NULL); 02161 02162 ap = real_a->str; 02163 bp = (const unsigned char*) c_str; 02164 a_end = real_a->str + real_a->len; 02165 while (ap != a_end && *bp) 02166 { 02167 if (*ap != *bp) 02168 return FALSE; 02169 02170 ++ap; 02171 ++bp; 02172 } 02173 02174 if (ap != a_end || *bp) 02175 return FALSE; 02176 02177 return TRUE; 02178 } 02179 02187 dbus_bool_t 02188 _dbus_string_starts_with_c_str (const DBusString *a, 02189 const char *c_str) 02190 { 02191 const unsigned char *ap; 02192 const unsigned char *bp; 02193 const unsigned char *a_end; 02194 const DBusRealString *real_a = (const DBusRealString*) a; 02195 DBUS_GENERIC_STRING_PREAMBLE (real_a); 02196 _dbus_assert (c_str != NULL); 02197 02198 ap = real_a->str; 02199 bp = (const unsigned char*) c_str; 02200 a_end = real_a->str + real_a->len; 02201 while (ap != a_end && *bp) 02202 { 02203 if (*ap != *bp) 02204 return FALSE; 02205 02206 ++ap; 02207 ++bp; 02208 } 02209 02210 if (*bp == '\0') 02211 return TRUE; 02212 else 02213 return FALSE; 02214 } 02215 02224 dbus_bool_t 02225 _dbus_string_append_byte_as_hex (DBusString *str, 02226 unsigned char byte) 02227 { 02228 const char hexdigits[16] = { 02229 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 02230 'a', 'b', 'c', 'd', 'e', 'f' 02231 }; 02232 02233 if (!_dbus_string_append_byte (str, 02234 hexdigits[(byte >> 4)])) 02235 return FALSE; 02236 02237 if (!_dbus_string_append_byte (str, 02238 hexdigits[(byte & 0x0f)])) 02239 { 02240 _dbus_string_set_length (str, 02241 _dbus_string_get_length (str) - 1); 02242 return FALSE; 02243 } 02244 02245 return TRUE; 02246 } 02247 02258 dbus_bool_t 02259 _dbus_string_hex_encode (const DBusString *source, 02260 int start, 02261 DBusString *dest, 02262 int insert_at) 02263 { 02264 DBusString result; 02265 const unsigned char *p; 02266 const unsigned char *end; 02267 dbus_bool_t retval; 02268 02269 _dbus_assert (start <= _dbus_string_get_length (source)); 02270 02271 if (!_dbus_string_init (&result)) 02272 return FALSE; 02273 02274 retval = FALSE; 02275 02276 p = (const unsigned char*) _dbus_string_get_const_data (source); 02277 end = p + _dbus_string_get_length (source); 02278 p += start; 02279 02280 while (p != end) 02281 { 02282 if (!_dbus_string_append_byte_as_hex (&result, *p)) 02283 goto out; 02284 02285 ++p; 02286 } 02287 02288 if (!_dbus_string_move (&result, 0, dest, insert_at)) 02289 goto out; 02290 02291 retval = TRUE; 02292 02293 out: 02294 _dbus_string_free (&result); 02295 return retval; 02296 } 02297 02308 dbus_bool_t 02309 _dbus_string_hex_decode (const DBusString *source, 02310 int start, 02311 int *end_return, 02312 DBusString *dest, 02313 int insert_at) 02314 { 02315 DBusString result; 02316 const unsigned char *p; 02317 const unsigned char *end; 02318 dbus_bool_t retval; 02319 dbus_bool_t high_bits; 02320 02321 _dbus_assert (start <= _dbus_string_get_length (source)); 02322 02323 if (!_dbus_string_init (&result)) 02324 return FALSE; 02325 02326 retval = FALSE; 02327 02328 high_bits = TRUE; 02329 p = (const unsigned char*) _dbus_string_get_const_data (source); 02330 end = p + _dbus_string_get_length (source); 02331 p += start; 02332 02333 while (p != end) 02334 { 02335 unsigned int val; 02336 02337 switch (*p) 02338 { 02339 case '0': 02340 val = 0; 02341 break; 02342 case '1': 02343 val = 1; 02344 break; 02345 case '2': 02346 val = 2; 02347 break; 02348 case '3': 02349 val = 3; 02350 break; 02351 case '4': 02352 val = 4; 02353 break; 02354 case '5': 02355 val = 5; 02356 break; 02357 case '6': 02358 val = 6; 02359 break; 02360 case '7': 02361 val = 7; 02362 break; 02363 case '8': 02364 val = 8; 02365 break; 02366 case '9': 02367 val = 9; 02368 break; 02369 case 'a': 02370 case 'A': 02371 val = 10; 02372 break; 02373 case 'b': 02374 case 'B': 02375 val = 11; 02376 break; 02377 case 'c': 02378 case 'C': 02379 val = 12; 02380 break; 02381 case 'd': 02382 case 'D': 02383 val = 13; 02384 break; 02385 case 'e': 02386 case 'E': 02387 val = 14; 02388 break; 02389 case 'f': 02390 case 'F': 02391 val = 15; 02392 break; 02393 default: 02394 goto done; 02395 } 02396 02397 if (high_bits) 02398 { 02399 if (!_dbus_string_append_byte (&result, 02400 val << 4)) 02401 goto out; 02402 } 02403 else 02404 { 02405 int len; 02406 unsigned char b; 02407 02408 len = _dbus_string_get_length (&result); 02409 02410 b = _dbus_string_get_byte (&result, len - 1); 02411 02412 b |= val; 02413 02414 _dbus_string_set_byte (&result, len - 1, b); 02415 } 02416 02417 high_bits = !high_bits; 02418 02419 ++p; 02420 } 02421 02422 done: 02423 if (!_dbus_string_move (&result, 0, dest, insert_at)) 02424 goto out; 02425 02426 if (end_return) 02427 *end_return = p - (const unsigned char*) _dbus_string_get_const_data (source); 02428 02429 retval = TRUE; 02430 02431 out: 02432 _dbus_string_free (&result); 02433 return retval; 02434 } 02435 02449 dbus_bool_t 02450 _dbus_string_validate_ascii (const DBusString *str, 02451 int start, 02452 int len) 02453 { 02454 const unsigned char *s; 02455 const unsigned char *end; 02456 DBUS_CONST_STRING_PREAMBLE (str); 02457 _dbus_assert (start >= 0); 02458 _dbus_assert (start <= real->len); 02459 _dbus_assert (len >= 0); 02460 02461 if (len > real->len - start) 02462 return FALSE; 02463 02464 s = real->str + start; 02465 end = s + len; 02466 while (s != end) 02467 { 02468 if (_DBUS_UNLIKELY (!_DBUS_ISASCII (*s))) 02469 return FALSE; 02470 02471 ++s; 02472 } 02473 02474 return TRUE; 02475 } 02476 02484 void 02485 _dbus_string_tolower_ascii (const DBusString *str, 02486 int start, 02487 int len) 02488 { 02489 unsigned char *s; 02490 unsigned char *end; 02491 DBUS_STRING_PREAMBLE (str); 02492 _dbus_assert (start >= 0); 02493 _dbus_assert (start <= real->len); 02494 _dbus_assert (len >= 0); 02495 _dbus_assert (len <= real->len - start); 02496 02497 s = real->str + start; 02498 end = s + len; 02499 02500 while (s != end) 02501 { 02502 if (*s >= 'A' && *s <= 'Z') 02503 *s += 'a' - 'A'; 02504 ++s; 02505 } 02506 } 02507 02515 void 02516 _dbus_string_toupper_ascii (const DBusString *str, 02517 int start, 02518 int len) 02519 { 02520 unsigned char *s; 02521 unsigned char *end; 02522 DBUS_STRING_PREAMBLE (str); 02523 _dbus_assert (start >= 0); 02524 _dbus_assert (start <= real->len); 02525 _dbus_assert (len >= 0); 02526 _dbus_assert (len <= real->len - start); 02527 02528 s = real->str + start; 02529 end = s + len; 02530 02531 while (s != end) 02532 { 02533 if (*s >= 'a' && *s <= 'z') 02534 *s += 'A' - 'a'; 02535 ++s; 02536 } 02537 } 02538 02554 dbus_bool_t 02555 _dbus_string_validate_utf8 (const DBusString *str, 02556 int start, 02557 int len) 02558 { 02559 const unsigned char *p; 02560 const unsigned char *end; 02561 DBUS_CONST_STRING_PREAMBLE (str); 02562 _dbus_assert (start >= 0); 02563 _dbus_assert (start <= real->len); 02564 _dbus_assert (len >= 0); 02565 02566 /* we are doing _DBUS_UNLIKELY() here which might be 02567 * dubious in a generic library like GLib, but in D-Bus 02568 * we know we're validating messages and that it would 02569 * only be evil/broken apps that would have invalid 02570 * UTF-8. Also, this function seems to be a performance 02571 * bottleneck in profiles. 02572 */ 02573 02574 if (_DBUS_UNLIKELY (len > real->len - start)) 02575 return FALSE; 02576 02577 p = real->str + start; 02578 end = p + len; 02579 02580 while (p < end) 02581 { 02582 int i, mask, char_len; 02583 dbus_unichar_t result; 02584 02585 /* nul bytes considered invalid */ 02586 if (*p == '\0') 02587 break; 02588 02589 /* Special-case ASCII; this makes us go a lot faster in 02590 * D-Bus profiles where we are typically validating 02591 * function names and such. We have to know that 02592 * all following checks will pass for ASCII though, 02593 * comments follow ... 02594 */ 02595 if (*p < 128) 02596 { 02597 ++p; 02598 continue; 02599 } 02600 02601 UTF8_COMPUTE (*p, mask, char_len); 02602 02603 if (_DBUS_UNLIKELY (char_len == 0)) /* ASCII: char_len == 1 */ 02604 break; 02605 02606 /* check that the expected number of bytes exists in the remaining length */ 02607 if (_DBUS_UNLIKELY ((end - p) < char_len)) /* ASCII: p < end and char_len == 1 */ 02608 break; 02609 02610 UTF8_GET (result, p, i, mask, char_len); 02611 02612 /* Check for overlong UTF-8 */ 02613 if (_DBUS_UNLIKELY (UTF8_LENGTH (result) != char_len)) /* ASCII: UTF8_LENGTH == 1 */ 02614 break; 02615 #if 0 02616 /* The UNICODE_VALID check below will catch this */ 02617 if (_DBUS_UNLIKELY (result == (dbus_unichar_t)-1)) /* ASCII: result = ascii value */ 02618 break; 02619 #endif 02620 02621 if (_DBUS_UNLIKELY (!UNICODE_VALID (result))) /* ASCII: always valid */ 02622 break; 02623 02624 /* UNICODE_VALID should have caught it */ 02625 _dbus_assert (result != (dbus_unichar_t)-1); 02626 02627 p += char_len; 02628 } 02629 02630 /* See that we covered the entire length if a length was 02631 * passed in 02632 */ 02633 if (_DBUS_UNLIKELY (p != end)) 02634 return FALSE; 02635 else 02636 return TRUE; 02637 } 02638 02652 dbus_bool_t 02653 _dbus_string_validate_nul (const DBusString *str, 02654 int start, 02655 int len) 02656 { 02657 const unsigned char *s; 02658 const unsigned char *end; 02659 DBUS_CONST_STRING_PREAMBLE (str); 02660 _dbus_assert (start >= 0); 02661 _dbus_assert (len >= 0); 02662 _dbus_assert (start <= real->len); 02663 02664 if (len > real->len - start) 02665 return FALSE; 02666 02667 s = real->str + start; 02668 end = s + len; 02669 while (s != end) 02670 { 02671 if (_DBUS_UNLIKELY (*s != '\0')) 02672 return FALSE; 02673 ++s; 02674 } 02675 02676 return TRUE; 02677 } 02678 02684 void 02685 _dbus_string_zero (DBusString *str) 02686 { 02687 DBUS_STRING_PREAMBLE (str); 02688 02689 memset (real->str - real->align_offset, '\0', real->allocated); 02690 } 02693 /* tests are in dbus-string-util.c */