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 (len < 0)
01259 return FALSE;
01260
01261 if (!_dbus_string_lengthen (str, len))
01262 {
01263
01264 va_end (args_copy);
01265 return FALSE;
01266 }
01267
01268 vsprintf ((char*) (real->str + (real->len - len)),
01269 format, args_copy);
01270
01271 va_end (args_copy);
01272
01273 return TRUE;
01274 }
01275
01284 dbus_bool_t
01285 _dbus_string_append_printf (DBusString *str,
01286 const char *format,
01287 ...)
01288 {
01289 va_list args;
01290 dbus_bool_t retval;
01291
01292 va_start (args, format);
01293 retval = _dbus_string_append_printf_valist (str, format, args);
01294 va_end (args);
01295
01296 return retval;
01297 }
01298
01307 dbus_bool_t
01308 _dbus_string_append_len (DBusString *str,
01309 const char *buffer,
01310 int len)
01311 {
01312 DBUS_STRING_PREAMBLE (str);
01313 _dbus_assert (buffer != NULL);
01314 _dbus_assert (len >= 0);
01315
01316 return append (real, buffer, len);
01317 }
01318
01327 dbus_bool_t
01328 _dbus_string_append_byte (DBusString *str,
01329 unsigned char byte)
01330 {
01331 DBUS_STRING_PREAMBLE (str);
01332
01333 if (!set_length (real, real->len + 1))
01334 return FALSE;
01335
01336 real->str[real->len-1] = byte;
01337
01338 return TRUE;
01339 }
01340
01341 #ifdef DBUS_BUILD_TESTS
01342
01349 dbus_bool_t
01350 _dbus_string_append_unichar (DBusString *str,
01351 dbus_unichar_t ch)
01352 {
01353 int len;
01354 int first;
01355 int i;
01356 unsigned char *out;
01357
01358 DBUS_STRING_PREAMBLE (str);
01359
01360
01361
01362 len = 0;
01363
01364 if (ch < 0x80)
01365 {
01366 first = 0;
01367 len = 1;
01368 }
01369 else if (ch < 0x800)
01370 {
01371 first = 0xc0;
01372 len = 2;
01373 }
01374 else if (ch < 0x10000)
01375 {
01376 first = 0xe0;
01377 len = 3;
01378 }
01379 else if (ch < 0x200000)
01380 {
01381 first = 0xf0;
01382 len = 4;
01383 }
01384 else if (ch < 0x4000000)
01385 {
01386 first = 0xf8;
01387 len = 5;
01388 }
01389 else
01390 {
01391 first = 0xfc;
01392 len = 6;
01393 }
01394
01395 if (len > (real->max_length - real->len))
01396 return FALSE;
01397
01398 if (!set_length (real, real->len + len))
01399 return FALSE;
01400
01401 out = real->str + (real->len - len);
01402
01403 for (i = len - 1; i > 0; --i)
01404 {
01405 out[i] = (ch & 0x3f) | 0x80;
01406 ch >>= 6;
01407 }
01408 out[0] = ch | first;
01409
01410 return TRUE;
01411 }
01412 #endif
01413
01414 static void
01415 delete (DBusRealString *real,
01416 int start,
01417 int len)
01418 {
01419 if (len == 0)
01420 return;
01421
01422 memmove (real->str + start, real->str + start + len, real->len - (start + len));
01423 real->len -= len;
01424 real->str[real->len] = '\0';
01425 }
01426
01436 void
01437 _dbus_string_delete (DBusString *str,
01438 int start,
01439 int len)
01440 {
01441 DBUS_STRING_PREAMBLE (str);
01442 _dbus_assert (start >= 0);
01443 _dbus_assert (len >= 0);
01444 _dbus_assert (start <= real->len);
01445 _dbus_assert (len <= real->len - start);
01446
01447 delete (real, start, len);
01448 }
01449
01450 static dbus_bool_t
01451 copy (DBusRealString *source,
01452 int start,
01453 int len,
01454 DBusRealString *dest,
01455 int insert_at)
01456 {
01457 if (len == 0)
01458 return TRUE;
01459
01460 if (!open_gap (len, dest, insert_at))
01461 return FALSE;
01462
01463 memmove (dest->str + insert_at,
01464 source->str + start,
01465 len);
01466
01467 return TRUE;
01468 }
01469
01479 #define DBUS_STRING_COPY_PREAMBLE(source, start, dest, insert_at) \
01480 DBusRealString *real_source = (DBusRealString*) source; \
01481 DBusRealString *real_dest = (DBusRealString*) dest; \
01482 _dbus_assert ((source) != (dest)); \
01483 DBUS_GENERIC_STRING_PREAMBLE (real_source); \
01484 DBUS_GENERIC_STRING_PREAMBLE (real_dest); \
01485 _dbus_assert (!real_dest->constant); \
01486 _dbus_assert (!real_dest->locked); \
01487 _dbus_assert ((start) >= 0); \
01488 _dbus_assert ((start) <= real_source->len); \
01489 _dbus_assert ((insert_at) >= 0); \
01490 _dbus_assert ((insert_at) <= real_dest->len)
01491
01502 dbus_bool_t
01503 _dbus_string_move (DBusString *source,
01504 int start,
01505 DBusString *dest,
01506 int insert_at)
01507 {
01508 DBusRealString *real_source = (DBusRealString*) source;
01509 _dbus_assert (start <= real_source->len);
01510
01511 return _dbus_string_move_len (source, start,
01512 real_source->len - start,
01513 dest, insert_at);
01514 }
01515
01526 dbus_bool_t
01527 _dbus_string_copy (const DBusString *source,
01528 int start,
01529 DBusString *dest,
01530 int insert_at)
01531 {
01532 DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
01533
01534 return copy (real_source, start,
01535 real_source->len - start,
01536 real_dest,
01537 insert_at);
01538 }
01539
01554 dbus_bool_t
01555 _dbus_string_move_len (DBusString *source,
01556 int start,
01557 int len,
01558 DBusString *dest,
01559 int insert_at)
01560
01561 {
01562 DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
01563 _dbus_assert (len >= 0);
01564 _dbus_assert ((start + len) <= real_source->len);
01565
01566
01567 if (len == 0)
01568 {
01569 return TRUE;
01570 }
01571 else if (start == 0 &&
01572 len == real_source->len &&
01573 real_dest->len == 0)
01574 {
01575
01576
01577
01578
01579
01580
01581 #define ASSIGN_DATA(a, b) do { \
01582 (a)->str = (b)->str; \
01583 (a)->len = (b)->len; \
01584 (a)->allocated = (b)->allocated; \
01585 (a)->align_offset = (b)->align_offset; \
01586 } while (0)
01587
01588 DBusRealString tmp;
01589
01590 ASSIGN_DATA (&tmp, real_source);
01591 ASSIGN_DATA (real_source, real_dest);
01592 ASSIGN_DATA (real_dest, &tmp);
01593
01594 return TRUE;
01595 }
01596 else
01597 {
01598 if (!copy (real_source, start, len,
01599 real_dest,
01600 insert_at))
01601 return FALSE;
01602
01603 delete (real_source, start,
01604 len);
01605
01606 return TRUE;
01607 }
01608 }
01609
01621 dbus_bool_t
01622 _dbus_string_copy_len (const DBusString *source,
01623 int start,
01624 int len,
01625 DBusString *dest,
01626 int insert_at)
01627 {
01628 DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
01629 _dbus_assert (len >= 0);
01630 _dbus_assert (start <= real_source->len);
01631 _dbus_assert (len <= real_source->len - start);
01632
01633 return copy (real_source, start, len,
01634 real_dest,
01635 insert_at);
01636 }
01637
01659 dbus_bool_t
01660 _dbus_string_replace_len (const DBusString *source,
01661 int start,
01662 int len,
01663 DBusString *dest,
01664 int replace_at,
01665 int replace_len)
01666 {
01667 DBUS_STRING_COPY_PREAMBLE (source, start, dest, replace_at);
01668 _dbus_assert (len >= 0);
01669 _dbus_assert (start <= real_source->len);
01670 _dbus_assert (len <= real_source->len - start);
01671 _dbus_assert (replace_at >= 0);
01672 _dbus_assert (replace_at <= real_dest->len);
01673 _dbus_assert (replace_len <= real_dest->len - replace_at);
01674
01675 if (!copy (real_source, start, len,
01676 real_dest, replace_at))
01677 return FALSE;
01678
01679 delete (real_dest, replace_at + len, replace_len);
01680
01681 return TRUE;
01682 }
01683
01696 dbus_bool_t
01697 _dbus_string_split_on_byte (DBusString *source,
01698 unsigned char byte,
01699 DBusString *tail)
01700 {
01701 int byte_position;
01702 char byte_string[2] = "";
01703 int head_length;
01704 int tail_length;
01705
01706 byte_string[0] = (char) byte;
01707
01708 if (!_dbus_string_find (source, 0, byte_string, &byte_position))
01709 return FALSE;
01710
01711 head_length = byte_position;
01712 tail_length = _dbus_string_get_length (source) - head_length - 1;
01713
01714 if (!_dbus_string_move_len (source, byte_position + 1, tail_length,
01715 tail, 0))
01716 return FALSE;
01717
01718
01719
01720 if (!_dbus_string_set_length (source, head_length))
01721 return FALSE;
01722
01723 return TRUE;
01724 }
01725
01726
01727
01728
01729
01735 #define UTF8_COMPUTE(Char, Mask, Len) \
01736 if (Char < 128) \
01737 { \
01738 Len = 1; \
01739 Mask = 0x7f; \
01740 } \
01741 else if ((Char & 0xe0) == 0xc0) \
01742 { \
01743 Len = 2; \
01744 Mask = 0x1f; \
01745 } \
01746 else if ((Char & 0xf0) == 0xe0) \
01747 { \
01748 Len = 3; \
01749 Mask = 0x0f; \
01750 } \
01751 else if ((Char & 0xf8) == 0xf0) \
01752 { \
01753 Len = 4; \
01754 Mask = 0x07; \
01755 } \
01756 else if ((Char & 0xfc) == 0xf8) \
01757 { \
01758 Len = 5; \
01759 Mask = 0x03; \
01760 } \
01761 else if ((Char & 0xfe) == 0xfc) \
01762 { \
01763 Len = 6; \
01764 Mask = 0x01; \
01765 } \
01766 else \
01767 { \
01768 Len = 0; \
01769 Mask = 0; \
01770 }
01771
01776 #define UTF8_LENGTH(Char) \
01777 ((Char) < 0x80 ? 1 : \
01778 ((Char) < 0x800 ? 2 : \
01779 ((Char) < 0x10000 ? 3 : \
01780 ((Char) < 0x200000 ? 4 : \
01781 ((Char) < 0x4000000 ? 5 : 6)))))
01782
01792 #define UTF8_GET(Result, Chars, Count, Mask, Len) \
01793 (Result) = (Chars)[0] & (Mask); \
01794 for ((Count) = 1; (Count) < (Len); ++(Count)) \
01795 { \
01796 if (((Chars)[(Count)] & 0xc0) != 0x80) \
01797 { \
01798 (Result) = -1; \
01799 break; \
01800 } \
01801 (Result) <<= 6; \
01802 (Result) |= ((Chars)[(Count)] & 0x3f); \
01803 }
01804
01821 #define UNICODE_VALID(Char) \
01822 ((Char) < 0x110000 && \
01823 (((Char) & 0xFFFFF800) != 0xD800) && \
01824 ((Char) < 0xFDD0 || (Char) > 0xFDEF) && \
01825 ((Char) & 0xFFFE) != 0xFFFE)
01826
01827 #ifdef DBUS_BUILD_TESTS
01828
01838 void
01839 _dbus_string_get_unichar (const DBusString *str,
01840 int start,
01841 dbus_unichar_t *ch_return,
01842 int *end_return)
01843 {
01844 int i, mask, len;
01845 dbus_unichar_t result;
01846 unsigned char c;
01847 unsigned char *p;
01848 DBUS_CONST_STRING_PREAMBLE (str);
01849 _dbus_assert (start >= 0);
01850 _dbus_assert (start <= real->len);
01851
01852 if (ch_return)
01853 *ch_return = 0;
01854 if (end_return)
01855 *end_return = real->len;
01856
01857 mask = 0;
01858 p = real->str + start;
01859 c = *p;
01860
01861 UTF8_COMPUTE (c, mask, len);
01862 if (len == 0)
01863 return;
01864 UTF8_GET (result, p, i, mask, len);
01865
01866 if (result == (dbus_unichar_t)-1)
01867 return;
01868
01869 if (ch_return)
01870 *ch_return = result;
01871 if (end_return)
01872 *end_return = start + len;
01873 }
01874 #endif
01875
01890 dbus_bool_t
01891 _dbus_string_find (const DBusString *str,
01892 int start,
01893 const char *substr,
01894 int *found)
01895 {
01896 return _dbus_string_find_to (str, start,
01897 ((const DBusRealString*)str)->len,
01898 substr, found);
01899 }
01900
01913 dbus_bool_t
01914 _dbus_string_find_eol (const DBusString *str,
01915 int start,
01916 int *found,
01917 int *found_len)
01918 {
01919 int i;
01920
01921 DBUS_CONST_STRING_PREAMBLE (str);
01922 _dbus_assert (start <= real->len);
01923 _dbus_assert (start >= 0);
01924
01925 i = start;
01926 while (i < real->len)
01927 {
01928 if (real->str[i] == '\r')
01929 {
01930 if ((i+1) < real->len && real->str[i+1] == '\n')
01931 {
01932 if (found)
01933 *found = i;
01934 if (found_len)
01935 *found_len = 2;
01936 return TRUE;
01937 }
01938 else
01939 {
01940 if (found)
01941 *found = i;
01942 if (found_len)
01943 *found_len = 1;
01944 return TRUE;
01945 }
01946 }
01947 else if (real->str[i] == '\n')
01948 {
01949 if (found)
01950 *found = i;
01951 if (found_len)
01952 *found_len = 1;
01953 return TRUE;
01954 }
01955 ++i;
01956 }
01957
01958 if (found)
01959 *found = real->len;
01960
01961 if (found_len)
01962 *found_len = 0;
01963
01964 return FALSE;
01965 }
01966
01983 dbus_bool_t
01984 _dbus_string_find_to (const DBusString *str,
01985 int start,
01986 int end,
01987 const char *substr,
01988 int *found)
01989 {
01990 int i;
01991 DBUS_CONST_STRING_PREAMBLE (str);
01992 _dbus_assert (substr != NULL);
01993 _dbus_assert (start <= real->len);
01994 _dbus_assert (start >= 0);
01995 _dbus_assert (substr != NULL);
01996 _dbus_assert (end <= real->len);
01997 _dbus_assert (start <= end);
01998
01999
02000 if (*substr == '\0')
02001 {
02002 if (found)
02003 *found = start;
02004 return TRUE;
02005 }
02006
02007 i = start;
02008 while (i < end)
02009 {
02010 if (real->str[i] == substr[0])
02011 {
02012 int j = i + 1;
02013
02014 while (j < end)
02015 {
02016 if (substr[j - i] == '\0')
02017 break;
02018 else if (real->str[j] != substr[j - i])
02019 break;
02020
02021 ++j;
02022 }
02023
02024 if (substr[j - i] == '\0')
02025 {
02026 if (found)
02027 *found = i;
02028 return TRUE;
02029 }
02030 }
02031
02032 ++i;
02033 }
02034
02035 if (found)
02036 *found = end;
02037
02038 return FALSE;
02039 }
02040
02051 dbus_bool_t
02052 _dbus_string_find_blank (const DBusString *str,
02053 int start,
02054 int *found)
02055 {
02056 int i;
02057 DBUS_CONST_STRING_PREAMBLE (str);
02058 _dbus_assert (start <= real->len);
02059 _dbus_assert (start >= 0);
02060
02061 i = start;
02062 while (i < real->len)
02063 {
02064 if (real->str[i] == ' ' ||
02065 real->str[i] == '\t')
02066 {
02067 if (found)
02068 *found = i;
02069 return TRUE;
02070 }
02071
02072 ++i;
02073 }
02074
02075 if (found)
02076 *found = real->len;
02077
02078 return FALSE;
02079 }
02080
02089 void
02090 _dbus_string_skip_blank (const DBusString *str,
02091 int start,
02092 int *end)
02093 {
02094 int i;
02095 DBUS_CONST_STRING_PREAMBLE (str);
02096 _dbus_assert (start <= real->len);
02097 _dbus_assert (start >= 0);
02098
02099 i = start;
02100 while (i < real->len)
02101 {
02102 if (!DBUS_IS_ASCII_BLANK (real->str[i]))
02103 break;
02104
02105 ++i;
02106 }
02107
02108 _dbus_assert (i == real->len || !DBUS_IS_ASCII_WHITE (real->str[i]));
02109
02110 if (end)
02111 *end = i;
02112 }
02113
02114
02123 void
02124 _dbus_string_skip_white (const DBusString *str,
02125 int start,
02126 int *end)
02127 {
02128 int i;
02129 DBUS_CONST_STRING_PREAMBLE (str);
02130 _dbus_assert (start <= real->len);
02131 _dbus_assert (start >= 0);
02132
02133 i = start;
02134 while (i < real->len)
02135 {
02136 if (!DBUS_IS_ASCII_WHITE (real->str[i]))
02137 break;
02138
02139 ++i;
02140 }
02141
02142 _dbus_assert (i == real->len || !(DBUS_IS_ASCII_WHITE (real->str[i])));
02143
02144 if (end)
02145 *end = i;
02146 }
02147
02156 void
02157 _dbus_string_skip_white_reverse (const DBusString *str,
02158 int end,
02159 int *start)
02160 {
02161 int i;
02162 DBUS_CONST_STRING_PREAMBLE (str);
02163 _dbus_assert (end <= real->len);
02164 _dbus_assert (end >= 0);
02165
02166 i = end;
02167 while (i > 0)
02168 {
02169 if (!DBUS_IS_ASCII_WHITE (real->str[i-1]))
02170 break;
02171 --i;
02172 }
02173
02174 _dbus_assert (i >= 0 && (i == 0 || !(DBUS_IS_ASCII_WHITE (real->str[i-1]))));
02175
02176 if (start)
02177 *start = i;
02178 }
02179
02195 dbus_bool_t
02196 _dbus_string_pop_line (DBusString *source,
02197 DBusString *dest)
02198 {
02199 int eol, eol_len;
02200
02201 _dbus_string_set_length (dest, 0);
02202
02203 eol = 0;
02204 eol_len = 0;
02205 if (!_dbus_string_find_eol (source, 0, &eol, &eol_len))
02206 {
02207 _dbus_assert (eol == _dbus_string_get_length (source));
02208 if (eol == 0)
02209 {
02210
02211 return FALSE;
02212 }
02213
02214 }
02215
02216
02217
02218
02219
02220 if (!_dbus_string_move_len (source, 0, eol + eol_len, dest, 0))
02221 return FALSE;
02222
02223
02224 if (!_dbus_string_set_length (dest, eol))
02225 {
02226 _dbus_assert_not_reached ("out of memory when shortening a string");
02227 return FALSE;
02228 }
02229
02230 return TRUE;
02231 }
02232
02233 #ifdef DBUS_BUILD_TESTS
02234
02240 void
02241 _dbus_string_delete_first_word (DBusString *str)
02242 {
02243 int i;
02244
02245 if (_dbus_string_find_blank (str, 0, &i))
02246 _dbus_string_skip_blank (str, i, &i);
02247
02248 _dbus_string_delete (str, 0, i);
02249 }
02250 #endif
02251
02252 #ifdef DBUS_BUILD_TESTS
02253
02258 void
02259 _dbus_string_delete_leading_blanks (DBusString *str)
02260 {
02261 int i;
02262
02263 _dbus_string_skip_blank (str, 0, &i);
02264
02265 if (i > 0)
02266 _dbus_string_delete (str, 0, i);
02267 }
02268 #endif
02269
02275 void
02276 _dbus_string_chop_white(DBusString *str)
02277 {
02278 int i;
02279
02280 _dbus_string_skip_white (str, 0, &i);
02281
02282 if (i > 0)
02283 _dbus_string_delete (str, 0, i);
02284
02285 _dbus_string_skip_white_reverse (str, _dbus_string_get_length (str), &i);
02286
02287 _dbus_string_set_length (str, i);
02288 }
02289
02299 dbus_bool_t
02300 _dbus_string_equal (const DBusString *a,
02301 const DBusString *b)
02302 {
02303 const unsigned char *ap;
02304 const unsigned char *bp;
02305 const unsigned char *a_end;
02306 const DBusRealString *real_a = (const DBusRealString*) a;
02307 const DBusRealString *real_b = (const DBusRealString*) b;
02308 DBUS_GENERIC_STRING_PREAMBLE (real_a);
02309 DBUS_GENERIC_STRING_PREAMBLE (real_b);
02310
02311 if (real_a->len != real_b->len)
02312 return FALSE;
02313
02314 ap = real_a->str;
02315 bp = real_b->str;
02316 a_end = real_a->str + real_a->len;
02317 while (ap != a_end)
02318 {
02319 if (*ap != *bp)
02320 return FALSE;
02321
02322 ++ap;
02323 ++bp;
02324 }
02325
02326 return TRUE;
02327 }
02328
02342 dbus_bool_t
02343 _dbus_string_equal_len (const DBusString *a,
02344 const DBusString *b,
02345 int len)
02346 {
02347 const unsigned char *ap;
02348 const unsigned char *bp;
02349 const unsigned char *a_end;
02350 const DBusRealString *real_a = (const DBusRealString*) a;
02351 const DBusRealString *real_b = (const DBusRealString*) b;
02352 DBUS_GENERIC_STRING_PREAMBLE (real_a);
02353 DBUS_GENERIC_STRING_PREAMBLE (real_b);
02354
02355 if (real_a->len != real_b->len &&
02356 (real_a->len < len || real_b->len < len))
02357 return FALSE;
02358
02359 ap = real_a->str;
02360 bp = real_b->str;
02361 a_end = real_a->str + MIN (real_a->len, len);
02362 while (ap != a_end)
02363 {
02364 if (*ap != *bp)
02365 return FALSE;
02366
02367 ++ap;
02368 ++bp;
02369 }
02370
02371 return TRUE;
02372 }
02373
02390 dbus_bool_t
02391 _dbus_string_equal_substring (const DBusString *a,
02392 int a_start,
02393 int a_len,
02394 const DBusString *b,
02395 int b_start)
02396 {
02397 const unsigned char *ap;
02398 const unsigned char *bp;
02399 const unsigned char *a_end;
02400 const DBusRealString *real_a = (const DBusRealString*) a;
02401 const DBusRealString *real_b = (const DBusRealString*) b;
02402 DBUS_GENERIC_STRING_PREAMBLE (real_a);
02403 DBUS_GENERIC_STRING_PREAMBLE (real_b);
02404 _dbus_assert (a_start >= 0);
02405 _dbus_assert (a_len >= 0);
02406 _dbus_assert (a_start <= real_a->len);
02407 _dbus_assert (a_len <= real_a->len - a_start);
02408 _dbus_assert (b_start >= 0);
02409 _dbus_assert (b_start <= real_b->len);
02410
02411 if (a_len > real_b->len - b_start)
02412 return FALSE;
02413
02414 ap = real_a->str + a_start;
02415 bp = real_b->str + b_start;
02416 a_end = ap + a_len;
02417 while (ap != a_end)
02418 {
02419 if (*ap != *bp)
02420 return FALSE;
02421
02422 ++ap;
02423 ++bp;
02424 }
02425
02426 _dbus_assert (bp <= (real_b->str + real_b->len));
02427
02428 return TRUE;
02429 }
02430
02438 dbus_bool_t
02439 _dbus_string_equal_c_str (const DBusString *a,
02440 const char *c_str)
02441 {
02442 const unsigned char *ap;
02443 const unsigned char *bp;
02444 const unsigned char *a_end;
02445 const DBusRealString *real_a = (const DBusRealString*) a;
02446 DBUS_GENERIC_STRING_PREAMBLE (real_a);
02447 _dbus_assert (c_str != NULL);
02448
02449 ap = real_a->str;
02450 bp = (const unsigned char*) c_str;
02451 a_end = real_a->str + real_a->len;
02452 while (ap != a_end && *bp)
02453 {
02454 if (*ap != *bp)
02455 return FALSE;
02456
02457 ++ap;
02458 ++bp;
02459 }
02460
02461 if (ap != a_end || *bp)
02462 return FALSE;
02463
02464 return TRUE;
02465 }
02466
02467 #ifdef DBUS_BUILD_TESTS
02468
02475 dbus_bool_t
02476 _dbus_string_starts_with_c_str (const DBusString *a,
02477 const char *c_str)
02478 {
02479 const unsigned char *ap;
02480 const unsigned char *bp;
02481 const unsigned char *a_end;
02482 const DBusRealString *real_a = (const DBusRealString*) a;
02483 DBUS_GENERIC_STRING_PREAMBLE (real_a);
02484 _dbus_assert (c_str != NULL);
02485
02486 ap = real_a->str;
02487 bp = (const unsigned char*) c_str;
02488 a_end = real_a->str + real_a->len;
02489 while (ap != a_end && *bp)
02490 {
02491 if (*ap != *bp)
02492 return FALSE;
02493
02494 ++ap;
02495 ++bp;
02496 }
02497
02498 if (*bp == '\0')
02499 return TRUE;
02500 else
02501 return FALSE;
02502 }
02503 #endif
02504
02513 dbus_bool_t
02514 _dbus_string_append_byte_as_hex (DBusString *str,
02515 int byte)
02516 {
02517 const char hexdigits[16] = {
02518 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
02519 'a', 'b', 'c', 'd', 'e', 'f'
02520 };
02521
02522 if (!_dbus_string_append_byte (str,
02523 hexdigits[(byte >> 4)]))
02524 return FALSE;
02525
02526 if (!_dbus_string_append_byte (str,
02527 hexdigits[(byte & 0x0f)]))
02528 {
02529 _dbus_string_set_length (str,
02530 _dbus_string_get_length (str) - 1);
02531 return FALSE;
02532 }
02533
02534 return TRUE;
02535 }
02536
02547 dbus_bool_t
02548 _dbus_string_hex_encode (const DBusString *source,
02549 int start,
02550 DBusString *dest,
02551 int insert_at)
02552 {
02553 DBusString result;
02554 const unsigned char *p;
02555 const unsigned char *end;
02556 dbus_bool_t retval;
02557
02558 _dbus_assert (start <= _dbus_string_get_length (source));
02559
02560 if (!_dbus_string_init (&result))
02561 return FALSE;
02562
02563 retval = FALSE;
02564
02565 p = (const unsigned char*) _dbus_string_get_const_data (source);
02566 end = p + _dbus_string_get_length (source);
02567 p += start;
02568
02569 while (p != end)
02570 {
02571 if (!_dbus_string_append_byte_as_hex (&result, *p))
02572 goto out;
02573
02574 ++p;
02575 }
02576
02577 if (!_dbus_string_move (&result, 0, dest, insert_at))
02578 goto out;
02579
02580 retval = TRUE;
02581
02582 out:
02583 _dbus_string_free (&result);
02584 return retval;
02585 }
02586
02597 dbus_bool_t
02598 _dbus_string_hex_decode (const DBusString *source,
02599 int start,
02600 int *end_return,
02601 DBusString *dest,
02602 int insert_at)
02603 {
02604 DBusString result;
02605 const unsigned char *p;
02606 const unsigned char *end;
02607 dbus_bool_t retval;
02608 dbus_bool_t high_bits;
02609
02610 _dbus_assert (start <= _dbus_string_get_length (source));
02611
02612 if (!_dbus_string_init (&result))
02613 return FALSE;
02614
02615 retval = FALSE;
02616
02617 high_bits = TRUE;
02618 p = (const unsigned char*) _dbus_string_get_const_data (source);
02619 end = p + _dbus_string_get_length (source);
02620 p += start;
02621
02622 while (p != end)
02623 {
02624 unsigned int val;
02625
02626 switch (*p)
02627 {
02628 case '0':
02629 val = 0;
02630 break;
02631 case '1':
02632 val = 1;
02633 break;
02634 case '2':
02635 val = 2;
02636 break;
02637 case '3':
02638 val = 3;
02639 break;
02640 case '4':
02641 val = 4;
02642 break;
02643 case '5':
02644 val = 5;
02645 break;
02646 case '6':
02647 val = 6;
02648 break;
02649 case '7':
02650 val = 7;
02651 break;
02652 case '8':
02653 val = 8;
02654 break;
02655 case '9':
02656 val = 9;
02657 break;
02658 case 'a':
02659 case 'A':
02660 val = 10;
02661 break;
02662 case 'b':
02663 case 'B':
02664 val = 11;
02665 break;
02666 case 'c':
02667 case 'C':
02668 val = 12;
02669 break;
02670 case 'd':
02671 case 'D':
02672 val = 13;
02673 break;
02674 case 'e':
02675 case 'E':
02676 val = 14;
02677 break;
02678 case 'f':
02679 case 'F':
02680 val = 15;
02681 break;
02682 default:
02683 goto done;
02684 }
02685
02686 if (high_bits)
02687 {
02688 if (!_dbus_string_append_byte (&result,
02689 val << 4))
02690 goto out;
02691 }
02692 else
02693 {
02694 int len;
02695 unsigned char b;
02696
02697 len = _dbus_string_get_length (&result);
02698
02699 b = _dbus_string_get_byte (&result, len - 1);
02700
02701 b |= val;
02702
02703 _dbus_string_set_byte (&result, len - 1, b);
02704 }
02705
02706 high_bits = !high_bits;
02707
02708 ++p;
02709 }
02710
02711 done:
02712 if (!_dbus_string_move (&result, 0, dest, insert_at))
02713 goto out;
02714
02715 if (end_return)
02716 *end_return = p - (const unsigned char*) _dbus_string_get_const_data (source);
02717
02718 retval = TRUE;
02719
02720 out:
02721 _dbus_string_free (&result);
02722 return retval;
02723 }
02724
02738 dbus_bool_t
02739 _dbus_string_validate_ascii (const DBusString *str,
02740 int start,
02741 int len)
02742 {
02743 const unsigned char *s;
02744 const unsigned char *end;
02745 DBUS_CONST_STRING_PREAMBLE (str);
02746 _dbus_assert (start >= 0);
02747 _dbus_assert (start <= real->len);
02748 _dbus_assert (len >= 0);
02749
02750 if (len > real->len - start)
02751 return FALSE;
02752
02753 s = real->str + start;
02754 end = s + len;
02755 while (s != end)
02756 {
02757 if (_DBUS_UNLIKELY (!_DBUS_ISASCII (*s)))
02758 return FALSE;
02759
02760 ++s;
02761 }
02762
02763 return TRUE;
02764 }
02765
02773 void
02774 _dbus_string_tolower_ascii (const DBusString *str,
02775 int start,
02776 int len)
02777 {
02778 unsigned char *s;
02779 unsigned char *end;
02780 DBUS_STRING_PREAMBLE (str);
02781 _dbus_assert (start >= 0);
02782 _dbus_assert (start <= real->len);
02783 _dbus_assert (len >= 0);
02784 _dbus_assert (len <= real->len - start);
02785
02786 s = real->str + start;
02787 end = s + len;
02788
02789 while (s != end)
02790 {
02791 if (*s >= 'A' && *s <= 'Z')
02792 *s += 'a' - 'A';
02793 ++s;
02794 }
02795 }
02796
02804 void
02805 _dbus_string_toupper_ascii (const DBusString *str,
02806 int start,
02807 int len)
02808 {
02809 unsigned char *s;
02810 unsigned char *end;
02811 DBUS_STRING_PREAMBLE (str);
02812 _dbus_assert (start >= 0);
02813 _dbus_assert (start <= real->len);
02814 _dbus_assert (len >= 0);
02815 _dbus_assert (len <= real->len - start);
02816
02817 s = real->str + start;
02818 end = s + len;
02819
02820 while (s != end)
02821 {
02822 if (*s >= 'a' && *s <= 'z')
02823 *s += 'A' - 'a';
02824 ++s;
02825 }
02826 }
02827
02843 dbus_bool_t
02844 _dbus_string_validate_utf8 (const DBusString *str,
02845 int start,
02846 int len)
02847 {
02848 const unsigned char *p;
02849 const unsigned char *end;
02850 DBUS_CONST_STRING_PREAMBLE (str);
02851 _dbus_assert (start >= 0);
02852 _dbus_assert (start <= real->len);
02853 _dbus_assert (len >= 0);
02854
02855
02856
02857
02858
02859
02860
02861
02862
02863 if (_DBUS_UNLIKELY (len > real->len - start))
02864 return FALSE;
02865
02866 p = real->str + start;
02867 end = p + len;
02868
02869 while (p < end)
02870 {
02871 int i, mask, char_len;
02872 dbus_unichar_t result;
02873
02874
02875 if (*p == '\0')
02876 break;
02877
02878
02879
02880
02881
02882
02883
02884 if (*p < 128)
02885 {
02886 ++p;
02887 continue;
02888 }
02889
02890 UTF8_COMPUTE (*p, mask, char_len);
02891
02892 if (_DBUS_UNLIKELY (char_len == 0))
02893 break;
02894
02895
02896 if (_DBUS_UNLIKELY ((end - p) < char_len))
02897 break;
02898
02899 UTF8_GET (result, p, i, mask, char_len);
02900
02901
02902 if (_DBUS_UNLIKELY (UTF8_LENGTH (result) != char_len))
02903 break;
02904 #if 0
02905
02906 if (_DBUS_UNLIKELY (result == (dbus_unichar_t)-1))
02907 break;
02908 #endif
02909
02910 if (_DBUS_UNLIKELY (!UNICODE_VALID (result)))
02911 break;
02912
02913
02914 _dbus_assert (result != (dbus_unichar_t)-1);
02915
02916 p += char_len;
02917 }
02918
02919
02920
02921
02922 if (_DBUS_UNLIKELY (p != end))
02923 return FALSE;
02924 else
02925 return TRUE;
02926 }
02927
02941 dbus_bool_t
02942 _dbus_string_validate_nul (const DBusString *str,
02943 int start,
02944 int len)
02945 {
02946 const unsigned char *s;
02947 const unsigned char *end;
02948 DBUS_CONST_STRING_PREAMBLE (str);
02949 _dbus_assert (start >= 0);
02950 _dbus_assert (len >= 0);
02951 _dbus_assert (start <= real->len);
02952
02953 if (len > real->len - start)
02954 return FALSE;
02955
02956 s = real->str + start;
02957 end = s + len;
02958 while (s != end)
02959 {
02960 if (_DBUS_UNLIKELY (*s != '\0'))
02961 return FALSE;
02962 ++s;
02963 }
02964
02965 return TRUE;
02966 }
02967
02973 void
02974 _dbus_string_zero (DBusString *str)
02975 {
02976 DBUS_STRING_PREAMBLE (str);
02977
02978 memset (real->str - real->align_offset, '\0', real->allocated);
02979 }
02982