00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <config.h>
00026 #include "dbus-internals.h"
00027 #include "dbus-string.h"
00028
00029 #include <string.h>
00030
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"
00035
00036
00037
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
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
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
00144
00145
00146
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->max_length = _DBUS_STRING_MAX_MAX_LENGTH;
00158 real->constant = FALSE;
00159 real->locked = FALSE;
00160 real->invalid = FALSE;
00161 real->align_offset = 0;
00162
00163 fixup_alignment (real);
00164
00165 return TRUE;
00166 }
00167
00175 dbus_bool_t
00176 _dbus_string_init (DBusString *str)
00177 {
00178 return _dbus_string_init_preallocated (str, 0);
00179 }
00180
00181 #ifdef DBUS_BUILD_TESTS
00182
00183
00184
00185
00186
00187
00188 static void
00189 set_max_length (DBusString *str,
00190 int max_length)
00191 {
00192 DBusRealString *real;
00193
00194 real = (DBusRealString*) str;
00195
00196 real->max_length = max_length;
00197 }
00198 #endif
00199
00209 void
00210 _dbus_string_init_const (DBusString *str,
00211 const char *value)
00212 {
00213 _dbus_assert (value != NULL);
00214
00215 _dbus_string_init_const_len (str, value,
00216 strlen (value));
00217 }
00218
00229 void
00230 _dbus_string_init_const_len (DBusString *str,
00231 const char *value,
00232 int len)
00233 {
00234 DBusRealString *real;
00235
00236 _dbus_assert (str != NULL);
00237 _dbus_assert (len == 0 || value != NULL);
00238 _dbus_assert (len <= _DBUS_STRING_MAX_MAX_LENGTH);
00239 _dbus_assert (len >= 0);
00240
00241 real = (DBusRealString*) str;
00242
00243 real->str = (unsigned char*) value;
00244 real->len = len;
00245 real->allocated = real->len + _DBUS_STRING_ALLOCATION_PADDING;
00246 real->max_length = real->len + 1;
00247 real->constant = TRUE;
00248 real->locked = TRUE;
00249 real->invalid = FALSE;
00250 real->align_offset = 0;
00251
00252
00253
00254
00255 }
00256
00262 void
00263 _dbus_string_free (DBusString *str)
00264 {
00265 DBusRealString *real = (DBusRealString*) str;
00266 DBUS_GENERIC_STRING_PREAMBLE (real);
00267
00268 if (real->constant)
00269 return;
00270 dbus_free (real->str - real->align_offset);
00271
00272 real->invalid = TRUE;
00273 }
00274
00275 static dbus_bool_t
00276 compact (DBusRealString *real,
00277 int max_waste)
00278 {
00279 unsigned char *new_str;
00280 int new_allocated;
00281 int waste;
00282
00283 waste = real->allocated - (real->len + _DBUS_STRING_ALLOCATION_PADDING);
00284
00285 if (waste <= max_waste)
00286 return TRUE;
00287
00288 new_allocated = real->len + _DBUS_STRING_ALLOCATION_PADDING;
00289
00290 new_str = dbus_realloc (real->str - real->align_offset, new_allocated);
00291 if (_DBUS_UNLIKELY (new_str == NULL))
00292 return FALSE;
00293
00294 real->str = new_str + real->align_offset;
00295 real->allocated = new_allocated;
00296 fixup_alignment (real);
00297
00298 return TRUE;
00299 }
00300
00301 #ifdef DBUS_BUILD_TESTS
00302
00303
00304
00314 void
00315 _dbus_string_lock (DBusString *str)
00316 {
00317 DBUS_LOCKED_STRING_PREAMBLE (str);
00318
00319 real->locked = TRUE;
00320
00321
00322
00323
00324 #define MAX_WASTE 48
00325 compact (real, MAX_WASTE);
00326 }
00327 #endif
00328
00329 static dbus_bool_t
00330 reallocate_for_length (DBusRealString *real,
00331 int new_length)
00332 {
00333 int new_allocated;
00334 unsigned char *new_str;
00335
00336
00337
00338
00339 if (real->allocated > (_DBUS_STRING_MAX_MAX_LENGTH + _DBUS_STRING_ALLOCATION_PADDING) / 2)
00340 new_allocated = _DBUS_STRING_MAX_MAX_LENGTH + _DBUS_STRING_ALLOCATION_PADDING;
00341 else
00342 new_allocated = real->allocated * 2;
00343
00344
00345
00346
00347
00348
00349
00350
00351 #ifdef DBUS_DISABLE_ASSERT
00352 #else
00353 #ifdef DBUS_BUILD_TESTS
00354 new_allocated = 0;
00355
00356
00357 #endif
00358 #endif
00359
00360
00361 new_allocated = MAX (new_allocated,
00362 new_length + _DBUS_STRING_ALLOCATION_PADDING);
00363
00364 _dbus_assert (new_allocated >= real->allocated);
00365 new_str = dbus_realloc (real->str - real->align_offset, new_allocated);
00366 if (_DBUS_UNLIKELY (new_str == NULL))
00367 return FALSE;
00368
00369 real->str = new_str + real->align_offset;
00370 real->allocated = new_allocated;
00371 fixup_alignment (real);
00372
00373 return TRUE;
00374 }
00375
00387 dbus_bool_t
00388 _dbus_string_compact (DBusString *str,
00389 int max_waste)
00390 {
00391 DBUS_STRING_PREAMBLE (str);
00392
00393 return compact (real, max_waste);
00394 }
00395
00396 static dbus_bool_t
00397 set_length (DBusRealString *real,
00398 int new_length)
00399 {
00400
00401
00402
00403 if (_DBUS_UNLIKELY (new_length > real->max_length))
00404 return FALSE;
00405 else if (new_length > (real->allocated - _DBUS_STRING_ALLOCATION_PADDING) &&
00406 _DBUS_UNLIKELY (!reallocate_for_length (real, new_length)))
00407 return FALSE;
00408 else
00409 {
00410 real->len = new_length;
00411 real->str[new_length] = '\0';
00412 return TRUE;
00413 }
00414 }
00415
00416 static dbus_bool_t
00417 open_gap (int len,
00418 DBusRealString *dest,
00419 int insert_at)
00420 {
00421 if (len == 0)
00422 return TRUE;
00423
00424 if (len > dest->max_length - dest->len)
00425 return FALSE;
00426
00427 if (!set_length (dest, dest->len + len))
00428 return FALSE;
00429
00430 memmove (dest->str + insert_at + len,
00431 dest->str + insert_at,
00432 dest->len - len - insert_at);
00433
00434 return TRUE;
00435 }
00436
00437 #ifndef _dbus_string_get_data
00438
00449 char*
00450 _dbus_string_get_data (DBusString *str)
00451 {
00452 DBUS_STRING_PREAMBLE (str);
00453
00454 return (char*) real->str;
00455 }
00456 #endif
00457
00458
00459 #ifndef _dbus_string_get_const_data
00460
00466 const char*
00467 _dbus_string_get_const_data (const DBusString *str)
00468 {
00469 DBUS_CONST_STRING_PREAMBLE (str);
00470
00471 return (const char*) real->str;
00472 }
00473 #endif
00474
00488 char*
00489 _dbus_string_get_data_len (DBusString *str,
00490 int start,
00491 int len)
00492 {
00493 DBUS_STRING_PREAMBLE (str);
00494 _dbus_assert (start >= 0);
00495 _dbus_assert (len >= 0);
00496 _dbus_assert (start <= real->len);
00497 _dbus_assert (len <= real->len - start);
00498
00499 return (char*) real->str + start;
00500 }
00501
00502
00503 #ifndef _dbus_string_get_const_data_len
00504
00512 const char*
00513 _dbus_string_get_const_data_len (const DBusString *str,
00514 int start,
00515 int len)
00516 {
00517 DBUS_CONST_STRING_PREAMBLE (str);
00518 _dbus_assert (start >= 0);
00519 _dbus_assert (len >= 0);
00520 _dbus_assert (start <= real->len);
00521 _dbus_assert (len <= real->len - start);
00522
00523 return (const char*) real->str + start;
00524 }
00525 #endif
00526
00527
00528 #ifndef _dbus_string_set_byte
00529
00536 void
00537 _dbus_string_set_byte (DBusString *str,
00538 int i,
00539 unsigned char byte)
00540 {
00541 DBUS_STRING_PREAMBLE (str);
00542 _dbus_assert (i < real->len);
00543 _dbus_assert (i >= 0);
00544
00545 real->str[i] = byte;
00546 }
00547 #endif
00548
00549
00550 #ifndef _dbus_string_get_byte
00551
00560 unsigned char
00561 _dbus_string_get_byte (const DBusString *str,
00562 int start)
00563 {
00564 DBUS_CONST_STRING_PREAMBLE (str);
00565 _dbus_assert (start <= real->len);
00566 _dbus_assert (start >= 0);
00567
00568 return real->str[start];
00569 }
00570 #endif
00571
00582 dbus_bool_t
00583 _dbus_string_insert_bytes (DBusString *str,
00584 int i,
00585 int n_bytes,
00586 unsigned char byte)
00587 {
00588 DBUS_STRING_PREAMBLE (str);
00589 _dbus_assert (i <= real->len);
00590 _dbus_assert (i >= 0);
00591 _dbus_assert (n_bytes >= 0);
00592
00593 if (n_bytes == 0)
00594 return TRUE;
00595
00596 if (!open_gap (n_bytes, real, i))
00597 return FALSE;
00598
00599 memset (real->str + i, byte, n_bytes);
00600
00601 return TRUE;
00602 }
00603
00612 dbus_bool_t
00613 _dbus_string_insert_byte (DBusString *str,
00614 int i,
00615 unsigned char byte)
00616 {
00617 DBUS_STRING_PREAMBLE (str);
00618 _dbus_assert (i <= real->len);
00619 _dbus_assert (i >= 0);
00620
00621 if (!open_gap (1, real, i))
00622 return FALSE;
00623
00624 real->str[i] = byte;
00625
00626 return TRUE;
00627 }
00628
00639 dbus_bool_t
00640 _dbus_string_steal_data (DBusString *str,
00641 char **data_return)
00642 {
00643 int old_max_length;
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 old_max_length = real->max_length;
00652
00653
00654 if (!_dbus_string_init (str))
00655 {
00656
00657 real->str = (unsigned char*) *data_return;
00658 *data_return = NULL;
00659 fixup_alignment (real);
00660 return FALSE;
00661 }
00662
00663 real->max_length = old_max_length;
00664
00665 return TRUE;
00666 }
00667
00668 #ifdef DBUS_BUILD_TESTS
00669
00684 dbus_bool_t
00685 _dbus_string_steal_data_len (DBusString *str,
00686 char **data_return,
00687 int start,
00688 int len)
00689 {
00690 DBusString dest;
00691 DBUS_STRING_PREAMBLE (str);
00692 _dbus_assert (data_return != NULL);
00693 _dbus_assert (start >= 0);
00694 _dbus_assert (len >= 0);
00695 _dbus_assert (start <= real->len);
00696 _dbus_assert (len <= real->len - start);
00697
00698 if (!_dbus_string_init (&dest))
00699 return FALSE;
00700
00701 set_max_length (&dest, real->max_length);
00702
00703 if (!_dbus_string_move_len (str, start, len, &dest, 0))
00704 {
00705 _dbus_string_free (&dest);
00706 return FALSE;
00707 }
00708
00709 _dbus_warn ("Broken code in _dbus_string_steal_data_len(), see @todo, FIXME\n");
00710 if (!_dbus_string_steal_data (&dest, data_return))
00711 {
00712 _dbus_string_free (&dest);
00713 return FALSE;
00714 }
00715
00716 _dbus_string_free (&dest);
00717 return TRUE;
00718 }
00719 #endif
00720
00728 dbus_bool_t
00729 _dbus_string_copy_data (const DBusString *str,
00730 char **data_return)
00731 {
00732 DBUS_CONST_STRING_PREAMBLE (str);
00733 _dbus_assert (data_return != NULL);
00734
00735 *data_return = dbus_malloc (real->len + 1);
00736 if (*data_return == NULL)
00737 return FALSE;
00738
00739 memcpy (*data_return, real->str, real->len + 1);
00740
00741 return TRUE;
00742 }
00743
00753 void
00754 _dbus_string_copy_to_buffer (const DBusString *str,
00755 char *buffer,
00756 int avail_len)
00757 {
00758 DBUS_CONST_STRING_PREAMBLE (str);
00759
00760 _dbus_assert (avail_len >= 0);
00761 _dbus_assert (avail_len >= real->len);
00762
00763 memcpy (buffer, real->str, real->len);
00764 }
00765
00775 void
00776 _dbus_string_copy_to_buffer_with_nul (const DBusString *str,
00777 char *buffer,
00778 int avail_len)
00779 {
00780 DBUS_CONST_STRING_PREAMBLE (str);
00781
00782 _dbus_assert (avail_len >= 0);
00783 _dbus_assert (avail_len > real->len);
00784
00785 memcpy (buffer, real->str, real->len+1);
00786 }
00787
00788 #ifdef DBUS_BUILD_TESTS
00789
00798 dbus_bool_t
00799 _dbus_string_copy_data_len (const DBusString *str,
00800 char **data_return,
00801 int start,
00802 int len)
00803 {
00804 DBusString dest;
00805
00806 DBUS_CONST_STRING_PREAMBLE (str);
00807 _dbus_assert (data_return != NULL);
00808 _dbus_assert (start >= 0);
00809 _dbus_assert (len >= 0);
00810 _dbus_assert (start <= real->len);
00811 _dbus_assert (len <= real->len - start);
00812
00813 if (!_dbus_string_init (&dest))
00814 return FALSE;
00815
00816 set_max_length (&dest, real->max_length);
00817
00818 if (!_dbus_string_copy_len (str, start, len, &dest, 0))
00819 {
00820 _dbus_string_free (&dest);
00821 return FALSE;
00822 }
00823
00824 if (!_dbus_string_steal_data (&dest, data_return))
00825 {
00826 _dbus_string_free (&dest);
00827 return FALSE;
00828 }
00829
00830 _dbus_string_free (&dest);
00831 return TRUE;
00832 }
00833 #endif
00834
00835
00836 #ifndef _dbus_string_get_length
00837
00842 int
00843 _dbus_string_get_length (const DBusString *str)
00844 {
00845 DBUS_CONST_STRING_PREAMBLE (str);
00846
00847 return real->len;
00848 }
00849 #endif
00850
00863 dbus_bool_t
00864 _dbus_string_lengthen (DBusString *str,
00865 int additional_length)
00866 {
00867 DBUS_STRING_PREAMBLE (str);
00868 _dbus_assert (additional_length >= 0);
00869
00870 if (_DBUS_UNLIKELY (additional_length > real->max_length - real->len))
00871 return FALSE;
00872
00873 return set_length (real,
00874 real->len + additional_length);
00875 }
00876
00883 void
00884 _dbus_string_shorten (DBusString *str,
00885 int length_to_remove)
00886 {
00887 DBUS_STRING_PREAMBLE (str);
00888 _dbus_assert (length_to_remove >= 0);
00889 _dbus_assert (length_to_remove <= real->len);
00890
00891 set_length (real,
00892 real->len - length_to_remove);
00893 }
00894
00905 dbus_bool_t
00906 _dbus_string_set_length (DBusString *str,
00907 int length)
00908 {
00909 DBUS_STRING_PREAMBLE (str);
00910 _dbus_assert (length >= 0);
00911
00912 return set_length (real, length);
00913 }
00914
00915 static dbus_bool_t
00916 align_insert_point_then_open_gap (DBusString *str,
00917 int *insert_at_p,
00918 int alignment,
00919 int gap_size)
00920 {
00921 unsigned long new_len;
00922 unsigned long gap_pos;
00923 int insert_at;
00924 int delta;
00925 DBUS_STRING_PREAMBLE (str);
00926 _dbus_assert (alignment >= 1);
00927 _dbus_assert (alignment <= 8);
00928
00929 insert_at = *insert_at_p;
00930
00931 _dbus_assert (insert_at <= real->len);
00932
00933 gap_pos = _DBUS_ALIGN_VALUE (insert_at, alignment);
00934 new_len = real->len + (gap_pos - insert_at) + gap_size;
00935
00936 if (_DBUS_UNLIKELY (new_len > (unsigned long) real->max_length))
00937 return FALSE;
00938
00939 delta = new_len - real->len;
00940 _dbus_assert (delta >= 0);
00941
00942 if (delta == 0)
00943 {
00944 _dbus_assert (((unsigned long) *insert_at_p) == gap_pos);
00945 return TRUE;
00946 }
00947
00948 if (_DBUS_UNLIKELY (!open_gap (new_len - real->len,
00949 real, insert_at)))
00950 return FALSE;
00951
00952
00953 if (gap_size < delta)
00954 {
00955 memset (&real->str[insert_at], '\0',
00956 gap_pos - insert_at);
00957 }
00958
00959 *insert_at_p = gap_pos;
00960
00961 return TRUE;
00962 }
00963
00964 static dbus_bool_t
00965 align_length_then_lengthen (DBusString *str,
00966 int alignment,
00967 int then_lengthen_by)
00968 {
00969 int insert_at;
00970
00971 insert_at = _dbus_string_get_length (str);
00972
00973 return align_insert_point_then_open_gap (str,
00974 &insert_at,
00975 alignment, then_lengthen_by);
00976 }
00977
00986 dbus_bool_t
00987 _dbus_string_align_length (DBusString *str,
00988 int alignment)
00989 {
00990 return align_length_then_lengthen (str, alignment, 0);
00991 }
00992
01002 dbus_bool_t
01003 _dbus_string_alloc_space (DBusString *str,
01004 int extra_bytes)
01005 {
01006 if (!_dbus_string_lengthen (str, extra_bytes))
01007 return FALSE;
01008 _dbus_string_shorten (str, extra_bytes);
01009
01010 return TRUE;
01011 }
01012
01013 static dbus_bool_t
01014 append (DBusRealString *real,
01015 const char *buffer,
01016 int buffer_len)
01017 {
01018 if (buffer_len == 0)
01019 return TRUE;
01020
01021 if (!_dbus_string_lengthen ((DBusString*)real, buffer_len))
01022 return FALSE;
01023
01024 memcpy (real->str + (real->len - buffer_len),
01025 buffer,
01026 buffer_len);
01027
01028 return TRUE;
01029 }
01030
01038 dbus_bool_t
01039 _dbus_string_append (DBusString *str,
01040 const char *buffer)
01041 {
01042 unsigned long buffer_len;
01043
01044 DBUS_STRING_PREAMBLE (str);
01045 _dbus_assert (buffer != NULL);
01046
01047 buffer_len = strlen (buffer);
01048 if (buffer_len > (unsigned long) real->max_length)
01049 return FALSE;
01050
01051 return append (real, buffer, buffer_len);
01052 }
01053
01055 #define ASSIGN_2_OCTETS(p, octets) \
01056 *((dbus_uint16_t*)(p)) = *((dbus_uint16_t*)(octets));
01057
01059 #define ASSIGN_4_OCTETS(p, octets) \
01060 *((dbus_uint32_t*)(p)) = *((dbus_uint32_t*)(octets));
01061
01062 #ifdef DBUS_HAVE_INT64
01063
01064 #define ASSIGN_8_OCTETS(p, octets) \
01065 *((dbus_uint64_t*)(p)) = *((dbus_uint64_t*)(octets));
01066 #else
01067
01068 #define ASSIGN_8_OCTETS(p, octets) \
01069 do { \
01070 unsigned char *b; \
01071 \
01072 b = p; \
01073 \
01074 *b++ = octets[0]; \
01075 *b++ = octets[1]; \
01076 *b++ = octets[2]; \
01077 *b++ = octets[3]; \
01078 *b++ = octets[4]; \
01079 *b++ = octets[5]; \
01080 *b++ = octets[6]; \
01081 *b++ = octets[7]; \
01082 _dbus_assert (b == p + 8); \
01083 } while (0)
01084 #endif
01085
01086 #ifdef DBUS_BUILD_TESTS
01087
01095 dbus_bool_t
01096 _dbus_string_append_4_aligned (DBusString *str,
01097 const unsigned char octets[4])
01098 {
01099 DBUS_STRING_PREAMBLE (str);
01100
01101 if (!align_length_then_lengthen (str, 4, 4))
01102 return FALSE;
01103
01104 ASSIGN_4_OCTETS (real->str + (real->len - 4), octets);
01105
01106 return TRUE;
01107 }
01108 #endif
01109
01110 #ifdef DBUS_BUILD_TESTS
01111
01119 dbus_bool_t
01120 _dbus_string_append_8_aligned (DBusString *str,
01121 const unsigned char octets[8])
01122 {
01123 DBUS_STRING_PREAMBLE (str);
01124
01125 if (!align_length_then_lengthen (str, 8, 8))
01126 return FALSE;
01127
01128 ASSIGN_8_OCTETS (real->str + (real->len - 8), octets);
01129
01130 return TRUE;
01131 }
01132 #endif
01133
01143 dbus_bool_t
01144 _dbus_string_insert_2_aligned (DBusString *str,
01145 int insert_at,
01146 const unsigned char octets[4])
01147 {
01148 DBUS_STRING_PREAMBLE (str);
01149
01150 if (!align_insert_point_then_open_gap (str, &insert_at, 2, 2))
01151 return FALSE;
01152
01153 ASSIGN_2_OCTETS (real->str + insert_at, octets);
01154
01155 return TRUE;
01156 }
01157
01167 dbus_bool_t
01168 _dbus_string_insert_4_aligned (DBusString *str,
01169 int insert_at,
01170 const unsigned char octets[4])
01171 {
01172 DBUS_STRING_PREAMBLE (str);
01173
01174 if (!align_insert_point_then_open_gap (str, &insert_at, 4, 4))
01175 return FALSE;
01176
01177 ASSIGN_4_OCTETS (real->str + insert_at, octets);
01178
01179 return TRUE;
01180 }
01181
01191 dbus_bool_t
01192 _dbus_string_insert_8_aligned (DBusString *str,
01193 int insert_at,
01194 const unsigned char octets[8])
01195 {
01196 DBUS_STRING_PREAMBLE (str);
01197
01198 if (!align_insert_point_then_open_gap (str, &insert_at, 8, 8))
01199 return FALSE;
01200
01201 _dbus_assert (_DBUS_ALIGN_VALUE (insert_at, 8) == (unsigned) insert_at);
01202
01203 ASSIGN_8_OCTETS (real->str + insert_at, octets);
01204
01205 return TRUE;
01206 }
01207
01208
01219 dbus_bool_t
01220 _dbus_string_insert_alignment (DBusString *str,
01221 int *insert_at,
01222 int alignment)
01223 {
01224 DBUS_STRING_PREAMBLE (str);
01225
01226 if (!align_insert_point_then_open_gap (str, insert_at, alignment, 0))
01227 return FALSE;
01228
01229 _dbus_assert (_DBUS_ALIGN_VALUE (*insert_at, alignment) == (unsigned) *insert_at);
01230
01231 return TRUE;
01232 }
01233
01243 dbus_bool_t
01244 _dbus_string_append_printf_valist (DBusString *str,
01245 const char *format,
01246 va_list args)
01247 {
01248 int len;
01249 va_list args_copy;
01250
01251 DBUS_STRING_PREAMBLE (str);
01252
01253 DBUS_VA_COPY (args_copy, args);
01254
01255
01256 len = _dbus_printf_string_upper_bound (format, args);
01257
01258 if (!_dbus_string_lengthen (str, len))
01259 {
01260
01261 va_end (args_copy);
01262 return FALSE;
01263 }
01264
01265 vsprintf ((char*) (real->str + (real->len - len)),
01266 format, args_copy);
01267
01268 va_end (args_copy);
01269
01270 return TRUE;
01271 }
01272
01281 dbus_bool_t
01282 _dbus_string_append_printf (DBusString *str,
01283 const char *format,
01284 ...)
01285 {
01286 va_list args;
01287 dbus_bool_t retval;
01288
01289 va_start (args, format);
01290 retval = _dbus_string_append_printf_valist (str, format, args);
01291 va_end (args);
01292
01293 return retval;
01294 }
01295
01304 dbus_bool_t
01305 _dbus_string_append_len (DBusString *str,
01306 const char *buffer,
01307 int len)
01308 {
01309 DBUS_STRING_PREAMBLE (str);
01310 _dbus_assert (buffer != NULL);
01311 _dbus_assert (len >= 0);
01312
01313 return append (real, buffer, len);
01314 }
01315
01324 dbus_bool_t
01325 _dbus_string_append_byte (DBusString *str,
01326 unsigned char byte)
01327 {
01328 DBUS_STRING_PREAMBLE (str);
01329
01330 if (!set_length (real, real->len + 1))
01331 return FALSE;
01332
01333 real->str[real->len-1] = byte;
01334
01335 return TRUE;
01336 }
01337
01338 #ifdef DBUS_BUILD_TESTS
01339
01346 dbus_bool_t
01347 _dbus_string_append_unichar (DBusString *str,
01348 dbus_unichar_t ch)
01349 {
01350 int len;
01351 int first;
01352 int i;
01353 unsigned char *out;
01354
01355 DBUS_STRING_PREAMBLE (str);
01356
01357
01358
01359 len = 0;
01360
01361 if (ch < 0x80)
01362 {
01363 first = 0;
01364 len = 1;
01365 }
01366 else if (ch < 0x800)
01367 {
01368 first = 0xc0;
01369 len = 2;
01370 }
01371 else if (ch < 0x10000)
01372 {
01373 first = 0xe0;
01374 len = 3;
01375 }
01376 else if (ch < 0x200000)
01377 {
01378 first = 0xf0;
01379 len = 4;
01380 }
01381 else if (ch < 0x4000000)
01382 {
01383 first = 0xf8;
01384 len = 5;
01385 }
01386 else
01387 {
01388 first = 0xfc;
01389 len = 6;
01390 }
01391
01392 if (len > (real->max_length - real->len))
01393 return FALSE;
01394
01395 if (!set_length (real, real->len + len))
01396 return FALSE;
01397
01398 out = real->str + (real->len - len);
01399
01400 for (i = len - 1; i > 0; --i)
01401 {
01402 out[i] = (ch & 0x3f) | 0x80;
01403 ch >>= 6;
01404 }
01405 out[0] = ch | first;
01406
01407 return TRUE;
01408 }
01409 #endif
01410
01411 static void
01412 delete (DBusRealString *real,
01413 int start,
01414 int len)
01415 {
01416 if (len == 0)
01417 return;
01418
01419 memmove (real->str + start, real->str + start + len, real->len - (start + len));
01420 real->len -= len;
01421 real->str[real->len] = '\0';
01422 }
01423
01433 void
01434 _dbus_string_delete (DBusString *str,
01435 int start,
01436 int len)
01437 {
01438 DBUS_STRING_PREAMBLE (str);
01439 _dbus_assert (start >= 0);
01440 _dbus_assert (len >= 0);
01441 _dbus_assert (start <= real->len);
01442 _dbus_assert (len <= real->len - start);
01443
01444 delete (real, start, len);
01445 }
01446
01447 static dbus_bool_t
01448 copy (DBusRealString *source,
01449 int start,
01450 int len,
01451 DBusRealString *dest,
01452 int insert_at)
01453 {
01454 if (len == 0)
01455 return TRUE;
01456
01457 if (!open_gap (len, dest, insert_at))
01458 return FALSE;
01459
01460 memmove (dest->str + insert_at,
01461 source->str + start,
01462 len);
01463
01464 return TRUE;
01465 }
01466
01476 #define DBUS_STRING_COPY_PREAMBLE(source, start, dest, insert_at) \
01477 DBusRealString *real_source = (DBusRealString*) source; \
01478 DBusRealString *real_dest = (DBusRealString*) dest; \
01479 _dbus_assert ((source) != (dest)); \
01480 DBUS_GENERIC_STRING_PREAMBLE (real_source); \
01481 DBUS_GENERIC_STRING_PREAMBLE (real_dest); \
01482 _dbus_assert (!real_dest->constant); \
01483 _dbus_assert (!real_dest->locked); \
01484 _dbus_assert ((start) >= 0); \
01485 _dbus_assert ((start) <= real_source->len); \
01486 _dbus_assert ((insert_at) >= 0); \
01487 _dbus_assert ((insert_at) <= real_dest->len)
01488
01499 dbus_bool_t
01500 _dbus_string_move (DBusString *source,
01501 int start,
01502 DBusString *dest,
01503 int insert_at)
01504 {
01505 DBusRealString *real_source = (DBusRealString*) source;
01506 _dbus_assert (start <= real_source->len);
01507
01508 return _dbus_string_move_len (source, start,
01509 real_source->len - start,
01510 dest, insert_at);
01511 }
01512
01523 dbus_bool_t
01524 _dbus_string_copy (const DBusString *source,
01525 int start,
01526 DBusString *dest,
01527 int insert_at)
01528 {
01529 DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
01530
01531 return copy (real_source, start,
01532 real_source->len - start,
01533 real_dest,
01534 insert_at);
01535 }
01536
01551 dbus_bool_t
01552 _dbus_string_move_len (DBusString *source,
01553 int start,
01554 int len,
01555 DBusString *dest,
01556 int insert_at)
01557
01558 {
01559 DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
01560 _dbus_assert (len >= 0);
01561 _dbus_assert ((start + len) <= real_source->len);
01562
01563
01564 if (len == 0)
01565 {
01566 return TRUE;
01567 }
01568 else if (start == 0 &&
01569 len == real_source->len &&
01570 real_dest->len == 0)
01571 {
01572
01573
01574
01575
01576
01577
01578 #define ASSIGN_DATA(a, b) do { \
01579 (a)->str = (b)->str; \
01580 (a)->len = (b)->len; \
01581 (a)->allocated = (b)->allocated; \
01582 (a)->align_offset = (b)->align_offset; \
01583 } while (0)
01584
01585 DBusRealString tmp;
01586
01587 ASSIGN_DATA (&tmp, real_source);
01588 ASSIGN_DATA (real_source, real_dest);
01589 ASSIGN_DATA (real_dest, &tmp);
01590
01591 return TRUE;
01592 }
01593 else
01594 {
01595 if (!copy (real_source, start, len,
01596 real_dest,
01597 insert_at))
01598 return FALSE;
01599
01600 delete (real_source, start,
01601 len);
01602
01603 return TRUE;
01604 }
01605 }
01606
01618 dbus_bool_t
01619 _dbus_string_copy_len (const DBusString *source,
01620 int start,
01621 int len,
01622 DBusString *dest,
01623 int insert_at)
01624 {
01625 DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
01626 _dbus_assert (len >= 0);
01627 _dbus_assert (start <= real_source->len);
01628 _dbus_assert (len <= real_source->len - start);
01629
01630 return copy (real_source, start, len,
01631 real_dest,
01632 insert_at);
01633 }
01634
01656 dbus_bool_t
01657 _dbus_string_replace_len (const DBusString *source,
01658 int start,
01659 int len,
01660 DBusString *dest,
01661 int replace_at,
01662 int replace_len)
01663 {
01664 DBUS_STRING_COPY_PREAMBLE (source, start, dest, replace_at);
01665 _dbus_assert (len >= 0);
01666 _dbus_assert (start <= real_source->len);
01667 _dbus_assert (len <= real_source->len - start);
01668 _dbus_assert (replace_at >= 0);
01669 _dbus_assert (replace_at <= real_dest->len);
01670 _dbus_assert (replace_len <= real_dest->len - replace_at);
01671
01672 if (!copy (real_source, start, len,
01673 real_dest, replace_at))
01674 return FALSE;
01675
01676 delete (real_dest, replace_at + len, replace_len);
01677
01678 return TRUE;
01679 }
01680
01693 dbus_bool_t
01694 _dbus_string_split_on_byte (DBusString *source,
01695 unsigned char byte,
01696 DBusString *tail)
01697 {
01698 int byte_position;
01699 char byte_string[2] = "";
01700 int head_length;
01701 int tail_length;
01702
01703 byte_string[0] = (char) byte;
01704
01705 if (!_dbus_string_find (source, 0, byte_string, &byte_position))
01706 return FALSE;
01707
01708 head_length = byte_position;
01709 tail_length = _dbus_string_get_length (source) - head_length - 1;
01710
01711 if (!_dbus_string_move_len (source, byte_position + 1, tail_length,
01712 tail, 0))
01713 return FALSE;
01714
01715
01716
01717 if (!_dbus_string_set_length (source, head_length))
01718 return FALSE;
01719
01720 return TRUE;
01721 }
01722
01723
01724
01725
01726
01732 #define UTF8_COMPUTE(Char, Mask, Len) \
01733 if (Char < 128) \
01734 { \
01735 Len = 1; \
01736 Mask = 0x7f; \
01737 } \
01738 else if ((Char & 0xe0) == 0xc0) \
01739 { \
01740 Len = 2; \
01741 Mask = 0x1f; \
01742 } \
01743 else if ((Char & 0xf0) == 0xe0) \
01744 { \
01745 Len = 3; \
01746 Mask = 0x0f; \
01747 } \
01748 else if ((Char & 0xf8) == 0xf0) \
01749 { \
01750 Len = 4; \
01751 Mask = 0x07; \
01752 } \
01753 else if ((Char & 0xfc) == 0xf8) \
01754 { \
01755 Len = 5; \
01756 Mask = 0x03; \
01757 } \
01758 else if ((Char & 0xfe) == 0xfc) \
01759 { \
01760 Len = 6; \
01761 Mask = 0x01; \
01762 } \
01763 else \
01764 { \
01765 Len = 0; \
01766 Mask = 0; \
01767 }
01768
01773 #define UTF8_LENGTH(Char) \
01774 ((Char) < 0x80 ? 1 : \
01775 ((Char) < 0x800 ? 2 : \
01776 ((Char) < 0x10000 ? 3 : \
01777 ((Char) < 0x200000 ? 4 : \
01778 ((Char) < 0x4000000 ? 5 : 6)))))
01779
01789 #define UTF8_GET(Result, Chars, Count, Mask, Len) \
01790 (Result) = (Chars)[0] & (Mask); \
01791 for ((Count) = 1; (Count) < (Len); ++(Count)) \
01792 { \
01793 if (((Chars)[(Count)] & 0xc0) != 0x80) \
01794 { \
01795 (Result) = -1; \
01796 break; \
01797 } \
01798 (Result) <<= 6; \
01799 (Result) |= ((Chars)[(Count)] & 0x3f); \
01800 }
01801
01818 #define UNICODE_VALID(Char) \
01819 ((Char) < 0x110000 && \
01820 (((Char) & 0xFFFFF800) != 0xD800) && \
01821 ((Char) < 0xFDD0 || (Char) > 0xFDEF) && \
01822 ((Char) & 0xFFFE) != 0xFFFE)
01823
01824 #ifdef DBUS_BUILD_TESTS
01825
01835 void
01836 _dbus_string_get_unichar (const DBusString *str,
01837 int start,
01838 dbus_unichar_t *ch_return,
01839 int *end_return)
01840 {
01841 int i, mask, len;
01842 dbus_unichar_t result;
01843 unsigned char c;
01844 unsigned char *p;
01845 DBUS_CONST_STRING_PREAMBLE (str);
01846 _dbus_assert (start >= 0);
01847 _dbus_assert (start <= real->len);
01848
01849 if (ch_return)
01850 *ch_return = 0;
01851 if (end_return)
01852 *end_return = real->len;
01853
01854 mask = 0;
01855 p = real->str + start;
01856 c = *p;
01857
01858 UTF8_COMPUTE (c, mask, len);
01859 if (len == 0)
01860 return;
01861 UTF8_GET (result, p, i, mask, len);
01862
01863 if (result == (dbus_unichar_t)-1)
01864 return;
01865
01866 if (ch_return)
01867 *ch_return = result;
01868 if (end_return)
01869 *end_return = start + len;
01870 }
01871 #endif
01872
01887 dbus_bool_t
01888 _dbus_string_find (const DBusString *str,
01889 int start,
01890 const char *substr,
01891 int *found)
01892 {
01893 return _dbus_string_find_to (str, start,
01894 ((const DBusRealString*)str)->len,
01895 substr, found);
01896 }
01897
01910 dbus_bool_t
01911 _dbus_string_find_eol (const DBusString *str,
01912 int start,
01913 int *found,
01914 int *found_len)
01915 {
01916 int i;
01917
01918 DBUS_CONST_STRING_PREAMBLE (str);
01919 _dbus_assert (start <= real->len);
01920 _dbus_assert (start >= 0);
01921
01922 i = start;
01923 while (i < real->len)
01924 {
01925 if (real->str[i] == '\r')
01926 {
01927 if ((i+1) < real->len && real->str[i+1] == '\n')
01928 {
01929 if (found)
01930 *found = i;
01931 if (found_len)
01932 *found_len = 2;
01933 return TRUE;
01934 }
01935 else
01936 {
01937 if (found)
01938 *found = i;
01939 if (found_len)
01940 *found_len = 1;
01941 return TRUE;
01942 }
01943 }
01944 else if (real->str[i] == '\n')
01945 {
01946 if (found)
01947 *found = i;
01948 if (found_len)
01949 *found_len = 1;
01950 return TRUE;
01951 }
01952 ++i;
01953 }
01954
01955 if (found)
01956 *found = real->len;
01957
01958 if (found_len)
01959 *found_len = 0;
01960
01961 return FALSE;
01962 }
01963
01980 dbus_bool_t
01981 _dbus_string_find_to (const DBusString *str,
01982 int start,
01983 int end,
01984 const char *substr,
01985 int *found)
01986 {
01987 int i;
01988 DBUS_CONST_STRING_PREAMBLE (str);
01989 _dbus_assert (substr != NULL);
01990 _dbus_assert (start <= real->len);
01991 _dbus_assert (start >= 0);
01992 _dbus_assert (substr != NULL);
01993 _dbus_assert (end <= real->len);
01994 _dbus_assert (start <= end);
01995
01996
01997 if (*substr == '\0')
01998 {
01999 if (found)
02000 *found = start;
02001 return TRUE;
02002 }
02003
02004 i = start;
02005 while (i < end)
02006 {
02007 if (real->str[i] == substr[0])
02008 {
02009 int j = i + 1;
02010
02011 while (j < end)
02012 {
02013 if (substr[j - i] == '\0')
02014 break;
02015 else if (real->str[j] != substr[j - i])
02016 break;
02017
02018 ++j;
02019 }
02020
02021 if (substr[j - i] == '\0')
02022 {
02023 if (found)
02024 *found = i;
02025 return TRUE;
02026 }
02027 }
02028
02029 ++i;
02030 }
02031
02032 if (found)
02033 *found = end;
02034
02035 return FALSE;
02036 }
02037
02048 dbus_bool_t
02049 _dbus_string_find_blank (const DBusString *str,
02050 int start,
02051 int *found)
02052 {
02053 int i;
02054 DBUS_CONST_STRING_PREAMBLE (str);
02055 _dbus_assert (start <= real->len);
02056 _dbus_assert (start >= 0);
02057
02058 i = start;
02059 while (i < real->len)
02060 {
02061 if (real->str[i] == ' ' ||
02062 real->str[i] == '\t')
02063 {
02064 if (found)
02065 *found = i;
02066 return TRUE;
02067 }
02068
02069 ++i;
02070 }
02071
02072 if (found)
02073 *found = real->len;
02074
02075 return FALSE;
02076 }
02077
02086 void
02087 _dbus_string_skip_blank (const DBusString *str,
02088 int start,
02089 int *end)
02090 {
02091 int i;
02092 DBUS_CONST_STRING_PREAMBLE (str);
02093 _dbus_assert (start <= real->len);
02094 _dbus_assert (start >= 0);
02095
02096 i = start;
02097 while (i < real->len)
02098 {
02099 if (!DBUS_IS_ASCII_BLANK (real->str[i]))
02100 break;
02101
02102 ++i;
02103 }
02104
02105 _dbus_assert (i == real->len || !DBUS_IS_ASCII_WHITE (real->str[i]));
02106
02107 if (end)
02108 *end = i;
02109 }
02110
02111
02120 void
02121 _dbus_string_skip_white (const DBusString *str,
02122 int start,
02123 int *end)
02124 {
02125 int i;
02126 DBUS_CONST_STRING_PREAMBLE (str);
02127 _dbus_assert (start <= real->len);
02128 _dbus_assert (start >= 0);
02129
02130 i = start;
02131 while (i < real->len)
02132 {
02133 if (!DBUS_IS_ASCII_WHITE (real->str[i]))
02134 break;
02135
02136 ++i;
02137 }
02138
02139 _dbus_assert (i == real->len || !(DBUS_IS_ASCII_WHITE (real->str[i])));
02140
02141 if (end)
02142 *end = i;
02143 }
02144
02153 void
02154 _dbus_string_skip_white_reverse (const DBusString *str,
02155 int end,
02156 int *start)
02157 {
02158 int i;
02159 DBUS_CONST_STRING_PREAMBLE (str);
02160 _dbus_assert (end <= real->len);
02161 _dbus_assert (end >= 0);
02162
02163 i = end;
02164 while (i > 0)
02165 {
02166 if (!DBUS_IS_ASCII_WHITE (real->str[i-1]))
02167 break;
02168 --i;
02169 }
02170
02171 _dbus_assert (i >= 0 && (i == 0 || !(DBUS_IS_ASCII_WHITE (real->str[i-1]))));
02172
02173 if (start)
02174 *start = i;
02175 }
02176
02192 dbus_bool_t
02193 _dbus_string_pop_line (DBusString *source,
02194 DBusString *dest)
02195 {
02196 int eol, eol_len;
02197
02198 _dbus_string_set_length (dest, 0);
02199
02200 eol = 0;
02201 eol_len = 0;
02202 if (!_dbus_string_find_eol (source, 0, &eol, &eol_len))
02203 {
02204 _dbus_assert (eol == _dbus_string_get_length (source));
02205 if (eol == 0)
02206 {
02207
02208 return FALSE;
02209 }
02210
02211 }
02212
02213
02214
02215
02216
02217 if (!_dbus_string_move_len (source, 0, eol + eol_len, dest, 0))
02218 return FALSE;
02219
02220
02221 if (!_dbus_string_set_length (dest, eol))
02222 {
02223 _dbus_assert_not_reached ("out of memory when shortening a string");
02224 return FALSE;
02225 }
02226
02227 return TRUE;
02228 }
02229
02230 #ifdef DBUS_BUILD_TESTS
02231
02237 void
02238 _dbus_string_delete_first_word (DBusString *str)
02239 {
02240 int i;
02241
02242 if (_dbus_string_find_blank (str, 0, &i))
02243 _dbus_string_skip_blank (str, i, &i);
02244
02245 _dbus_string_delete (str, 0, i);
02246 }
02247 #endif
02248
02249 #ifdef DBUS_BUILD_TESTS
02250
02255 void
02256 _dbus_string_delete_leading_blanks (DBusString *str)
02257 {
02258 int i;
02259
02260 _dbus_string_skip_blank (str, 0, &i);
02261
02262 if (i > 0)
02263 _dbus_string_delete (str, 0, i);
02264 }
02265 #endif
02266
02272 void
02273 _dbus_string_chop_white(DBusString *str)
02274 {
02275 int i;
02276
02277 _dbus_string_skip_white (str, 0, &i);
02278
02279 if (i > 0)
02280 _dbus_string_delete (str, 0, i);
02281
02282 _dbus_string_skip_white_reverse (str, _dbus_string_get_length (str), &i);
02283
02284 _dbus_string_set_length (str, i);
02285 }
02286
02296 dbus_bool_t
02297 _dbus_string_equal (const DBusString *a,
02298 const DBusString *b)
02299 {
02300 const unsigned char *ap;
02301 const unsigned char *bp;
02302 const unsigned char *a_end;
02303 const DBusRealString *real_a = (const DBusRealString*) a;
02304 const DBusRealString *real_b = (const DBusRealString*) b;
02305 DBUS_GENERIC_STRING_PREAMBLE (real_a);
02306 DBUS_GENERIC_STRING_PREAMBLE (real_b);
02307
02308 if (real_a->len != real_b->len)
02309 return FALSE;
02310
02311 ap = real_a->str;
02312 bp = real_b->str;
02313 a_end = real_a->str + real_a->len;
02314 while (ap != a_end)
02315 {
02316 if (*ap != *bp)
02317 return FALSE;
02318
02319 ++ap;
02320 ++bp;
02321 }
02322
02323 return TRUE;
02324 }
02325
02339 dbus_bool_t
02340 _dbus_string_equal_len (const DBusString *a,
02341 const DBusString *b,
02342 int len)
02343 {
02344 const unsigned char *ap;
02345 const unsigned char *bp;
02346 const unsigned char *a_end;
02347 const DBusRealString *real_a = (const DBusRealString*) a;
02348 const DBusRealString *real_b = (const DBusRealString*) b;
02349 DBUS_GENERIC_STRING_PREAMBLE (real_a);
02350 DBUS_GENERIC_STRING_PREAMBLE (real_b);
02351
02352 if (real_a->len != real_b->len &&
02353 (real_a->len < len || real_b->len < len))
02354 return FALSE;
02355
02356 ap = real_a->str;
02357 bp = real_b->str;
02358 a_end = real_a->str + MIN (real_a->len, len);
02359 while (ap != a_end)
02360 {
02361 if (*ap != *bp)
02362 return FALSE;
02363
02364 ++ap;
02365 ++bp;
02366 }
02367
02368 return TRUE;
02369 }
02370
02387 dbus_bool_t
02388 _dbus_string_equal_substring (const DBusString *a,
02389 int a_start,
02390 int a_len,
02391 const DBusString *b,
02392 int b_start)
02393 {
02394 const unsigned char *ap;
02395 const unsigned char *bp;
02396 const unsigned char *a_end;
02397 const DBusRealString *real_a = (const DBusRealString*) a;
02398 const DBusRealString *real_b = (const DBusRealString*) b;
02399 DBUS_GENERIC_STRING_PREAMBLE (real_a);
02400 DBUS_GENERIC_STRING_PREAMBLE (real_b);
02401 _dbus_assert (a_start >= 0);
02402 _dbus_assert (a_len >= 0);
02403 _dbus_assert (a_start <= real_a->len);
02404 _dbus_assert (a_len <= real_a->len - a_start);
02405 _dbus_assert (b_start >= 0);
02406 _dbus_assert (b_start <= real_b->len);
02407
02408 if (a_len > real_b->len - b_start)
02409 return FALSE;
02410
02411 ap = real_a->str + a_start;
02412 bp = real_b->str + b_start;
02413 a_end = ap + a_len;
02414 while (ap != a_end)
02415 {
02416 if (*ap != *bp)
02417 return FALSE;
02418
02419 ++ap;
02420 ++bp;
02421 }
02422
02423 _dbus_assert (bp <= (real_b->str + real_b->len));
02424
02425 return TRUE;
02426 }
02427
02435 dbus_bool_t
02436 _dbus_string_equal_c_str (const DBusString *a,
02437 const char *c_str)
02438 {
02439 const unsigned char *ap;
02440 const unsigned char *bp;
02441 const unsigned char *a_end;
02442 const DBusRealString *real_a = (const DBusRealString*) a;
02443 DBUS_GENERIC_STRING_PREAMBLE (real_a);
02444 _dbus_assert (c_str != NULL);
02445
02446 ap = real_a->str;
02447 bp = (const unsigned char*) c_str;
02448 a_end = real_a->str + real_a->len;
02449 while (ap != a_end && *bp)
02450 {
02451 if (*ap != *bp)
02452 return FALSE;
02453
02454 ++ap;
02455 ++bp;
02456 }
02457
02458 if (ap != a_end || *bp)
02459 return FALSE;
02460
02461 return TRUE;
02462 }
02463
02464 #ifdef DBUS_BUILD_TESTS
02465
02472 dbus_bool_t
02473 _dbus_string_starts_with_c_str (const DBusString *a,
02474 const char *c_str)
02475 {
02476 const unsigned char *ap;
02477 const unsigned char *bp;
02478 const unsigned char *a_end;
02479 const DBusRealString *real_a = (const DBusRealString*) a;
02480 DBUS_GENERIC_STRING_PREAMBLE (real_a);
02481 _dbus_assert (c_str != NULL);
02482
02483 ap = real_a->str;
02484 bp = (const unsigned char*) c_str;
02485 a_end = real_a->str + real_a->len;
02486 while (ap != a_end && *bp)
02487 {
02488 if (*ap != *bp)
02489 return FALSE;
02490
02491 ++ap;
02492 ++bp;
02493 }
02494
02495 if (*bp == '\0')
02496 return TRUE;
02497 else
02498 return FALSE;
02499 }
02500 #endif
02501
02510 dbus_bool_t
02511 _dbus_string_append_byte_as_hex (DBusString *str,
02512 int byte)
02513 {
02514 const char hexdigits[16] = {
02515 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
02516 'a', 'b', 'c', 'd', 'e', 'f'
02517 };
02518
02519 if (!_dbus_string_append_byte (str,
02520 hexdigits[(byte >> 4)]))
02521 return FALSE;
02522
02523 if (!_dbus_string_append_byte (str,
02524 hexdigits[(byte & 0x0f)]))
02525 {
02526 _dbus_string_set_length (str,
02527 _dbus_string_get_length (str) - 1);
02528 return FALSE;
02529 }
02530
02531 return TRUE;
02532 }
02533
02544 dbus_bool_t
02545 _dbus_string_hex_encode (const DBusString *source,
02546 int start,
02547 DBusString *dest,
02548 int insert_at)
02549 {
02550 DBusString result;
02551 const unsigned char *p;
02552 const unsigned char *end;
02553 dbus_bool_t retval;
02554
02555 _dbus_assert (start <= _dbus_string_get_length (source));
02556
02557 if (!_dbus_string_init (&result))
02558 return FALSE;
02559
02560 retval = FALSE;
02561
02562 p = (const unsigned char*) _dbus_string_get_const_data (source);
02563 end = p + _dbus_string_get_length (source);
02564 p += start;
02565
02566 while (p != end)
02567 {
02568 if (!_dbus_string_append_byte_as_hex (&result, *p))
02569 goto out;
02570
02571 ++p;
02572 }
02573
02574 if (!_dbus_string_move (&result, 0, dest, insert_at))
02575 goto out;
02576
02577 retval = TRUE;
02578
02579 out:
02580 _dbus_string_free (&result);
02581 return retval;
02582 }
02583
02594 dbus_bool_t
02595 _dbus_string_hex_decode (const DBusString *source,
02596 int start,
02597 int *end_return,
02598 DBusString *dest,
02599 int insert_at)
02600 {
02601 DBusString result;
02602 const unsigned char *p;
02603 const unsigned char *end;
02604 dbus_bool_t retval;
02605 dbus_bool_t high_bits;
02606
02607 _dbus_assert (start <= _dbus_string_get_length (source));
02608
02609 if (!_dbus_string_init (&result))
02610 return FALSE;
02611
02612 retval = FALSE;
02613
02614 high_bits = TRUE;
02615 p = (const unsigned char*) _dbus_string_get_const_data (source);
02616 end = p + _dbus_string_get_length (source);
02617 p += start;
02618
02619 while (p != end)
02620 {
02621 unsigned int val;
02622
02623 switch (*p)
02624 {
02625 case '0':
02626 val = 0;
02627 break;
02628 case '1':
02629 val = 1;
02630 break;
02631 case '2':
02632 val = 2;
02633 break;
02634 case '3':
02635 val = 3;
02636 break;
02637 case '4':
02638 val = 4;
02639 break;
02640 case '5':
02641 val = 5;
02642 break;
02643 case '6':
02644 val = 6;
02645 break;
02646 case '7':
02647 val = 7;
02648 break;
02649 case '8':
02650 val = 8;
02651 break;
02652 case '9':
02653 val = 9;
02654 break;
02655 case 'a':
02656 case 'A':
02657 val = 10;
02658 break;
02659 case 'b':
02660 case 'B':
02661 val = 11;
02662 break;
02663 case 'c':
02664 case 'C':
02665 val = 12;
02666 break;
02667 case 'd':
02668 case 'D':
02669 val = 13;
02670 break;
02671 case 'e':
02672 case 'E':
02673 val = 14;
02674 break;
02675 case 'f':
02676 case 'F':
02677 val = 15;
02678 break;
02679 default:
02680 goto done;
02681 }
02682
02683 if (high_bits)
02684 {
02685 if (!_dbus_string_append_byte (&result,
02686 val << 4))
02687 goto out;
02688 }
02689 else
02690 {
02691 int len;
02692 unsigned char b;
02693
02694 len = _dbus_string_get_length (&result);
02695
02696 b = _dbus_string_get_byte (&result, len - 1);
02697
02698 b |= val;
02699
02700 _dbus_string_set_byte (&result, len - 1, b);
02701 }
02702
02703 high_bits = !high_bits;
02704
02705 ++p;
02706 }
02707
02708 done:
02709 if (!_dbus_string_move (&result, 0, dest, insert_at))
02710 goto out;
02711
02712 if (end_return)
02713 *end_return = p - (const unsigned char*) _dbus_string_get_const_data (source);
02714
02715 retval = TRUE;
02716
02717 out:
02718 _dbus_string_free (&result);
02719 return retval;
02720 }
02721
02735 dbus_bool_t
02736 _dbus_string_validate_ascii (const DBusString *str,
02737 int start,
02738 int len)
02739 {
02740 const unsigned char *s;
02741 const unsigned char *end;
02742 DBUS_CONST_STRING_PREAMBLE (str);
02743 _dbus_assert (start >= 0);
02744 _dbus_assert (start <= real->len);
02745 _dbus_assert (len >= 0);
02746
02747 if (len > real->len - start)
02748 return FALSE;
02749
02750 s = real->str + start;
02751 end = s + len;
02752 while (s != end)
02753 {
02754 if (_DBUS_UNLIKELY (!_DBUS_ISASCII (*s)))
02755 return FALSE;
02756
02757 ++s;
02758 }
02759
02760 return TRUE;
02761 }
02762
02770 void
02771 _dbus_string_tolower_ascii (const DBusString *str,
02772 int start,
02773 int len)
02774 {
02775 unsigned char *s;
02776 unsigned char *end;
02777 DBUS_STRING_PREAMBLE (str);
02778 _dbus_assert (start >= 0);
02779 _dbus_assert (start <= real->len);
02780 _dbus_assert (len >= 0);
02781 _dbus_assert (len <= real->len - start);
02782
02783 s = real->str + start;
02784 end = s + len;
02785
02786 while (s != end)
02787 {
02788 if (*s >= 'A' && *s <= 'Z')
02789 *s += 'a' - 'A';
02790 ++s;
02791 }
02792 }
02793
02801 void
02802 _dbus_string_toupper_ascii (const DBusString *str,
02803 int start,
02804 int len)
02805 {
02806 unsigned char *s;
02807 unsigned char *end;
02808 DBUS_STRING_PREAMBLE (str);
02809 _dbus_assert (start >= 0);
02810 _dbus_assert (start <= real->len);
02811 _dbus_assert (len >= 0);
02812 _dbus_assert (len <= real->len - start);
02813
02814 s = real->str + start;
02815 end = s + len;
02816
02817 while (s != end)
02818 {
02819 if (*s >= 'a' && *s <= 'z')
02820 *s += 'A' - 'a';
02821 ++s;
02822 }
02823 }
02824
02840 dbus_bool_t
02841 _dbus_string_validate_utf8 (const DBusString *str,
02842 int start,
02843 int len)
02844 {
02845 const unsigned char *p;
02846 const unsigned char *end;
02847 DBUS_CONST_STRING_PREAMBLE (str);
02848 _dbus_assert (start >= 0);
02849 _dbus_assert (start <= real->len);
02850 _dbus_assert (len >= 0);
02851
02852
02853
02854
02855
02856
02857
02858
02859
02860 if (_DBUS_UNLIKELY (len > real->len - start))
02861 return FALSE;
02862
02863 p = real->str + start;
02864 end = p + len;
02865
02866 while (p < end)
02867 {
02868 int i, mask, char_len;
02869 dbus_unichar_t result;
02870
02871
02872 if (*p == '\0')
02873 break;
02874
02875
02876
02877
02878
02879
02880
02881 if (*p < 128)
02882 {
02883 ++p;
02884 continue;
02885 }
02886
02887 UTF8_COMPUTE (*p, mask, char_len);
02888
02889 if (_DBUS_UNLIKELY (char_len == 0))
02890 break;
02891
02892
02893 if (_DBUS_UNLIKELY ((end - p) < char_len))
02894 break;
02895
02896 UTF8_GET (result, p, i, mask, char_len);
02897
02898
02899 if (_DBUS_UNLIKELY (UTF8_LENGTH (result) != char_len))
02900 break;
02901 #if 0
02902
02903 if (_DBUS_UNLIKELY (result == (dbus_unichar_t)-1))
02904 break;
02905 #endif
02906
02907 if (_DBUS_UNLIKELY (!UNICODE_VALID (result)))
02908 break;
02909
02910
02911 _dbus_assert (result != (dbus_unichar_t)-1);
02912
02913 p += char_len;
02914 }
02915
02916
02917
02918
02919 if (_DBUS_UNLIKELY (p != end))
02920 return FALSE;
02921 else
02922 return TRUE;
02923 }
02924
02938 dbus_bool_t
02939 _dbus_string_validate_nul (const DBusString *str,
02940 int start,
02941 int len)
02942 {
02943 const unsigned char *s;
02944 const unsigned char *end;
02945 DBUS_CONST_STRING_PREAMBLE (str);
02946 _dbus_assert (start >= 0);
02947 _dbus_assert (len >= 0);
02948 _dbus_assert (start <= real->len);
02949
02950 if (len > real->len - start)
02951 return FALSE;
02952
02953 s = real->str + start;
02954 end = s + len;
02955 while (s != end)
02956 {
02957 if (_DBUS_UNLIKELY (*s != '\0'))
02958 return FALSE;
02959 ++s;
02960 }
02961
02962 return TRUE;
02963 }
02964
02970 void
02971 _dbus_string_zero (DBusString *str)
02972 {
02973 DBUS_STRING_PREAMBLE (str);
02974
02975 memset (real->str - real->align_offset, '\0', real->allocated);
02976 }
02979