D-Bus 1.14.10
dbus-string.c
1/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2/* dbus-string.c String utility class (internal to D-Bus implementation)
3 *
4 * Copyright 2002-2007 Red Hat, Inc.
5 * Copyright 2003 CodeFactory AB
6 * Copyright 2003 Mark McLoughlin
7 * Copyright 2004 Michael Meeks
8 * Copyright 2006-2014 Ralf Habacker <ralf.habacker@freenet.de>
9 * Copyright 2006-2018 Collabora Ltd.
10 * Copyright 2007 Allison Lortie
11 * Copyright 2011 Roberto Guido
12 * Copyright 2013 Chengwei Yang / Intel
13 *
14 * Licensed under the Academic Free License version 2.1
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29 *
30 */
31
32#include <config.h>
33#include "dbus-internals.h"
34#include "dbus-string.h"
35/* we allow a system header here, for speed/convenience */
36#include <string.h>
37/* for vsnprintf */
38#include <stdio.h>
39#define DBUS_CAN_USE_DBUS_STRING_PRIVATE 1
40#include "dbus-string-private.h"
41#include "dbus-marshal-basic.h" /* probably should be removed by moving the usage of DBUS_TYPE
42 * into the marshaling-related files
43 */
44/* for DBUS_VA_COPY */
45#include "dbus-sysdeps.h"
46
85static void
86fixup_alignment (DBusRealString *real)
87{
88 unsigned char *aligned;
89 unsigned char *real_block;
90 unsigned int old_align_offset;
91
92 /* we have to have extra space in real->allocated for the align offset and nul byte */
93 _dbus_assert (real->len <= real->allocated - _DBUS_STRING_ALLOCATION_PADDING);
94
95 old_align_offset = real->align_offset;
96 real_block = real->str - old_align_offset;
97
98 aligned = _DBUS_ALIGN_ADDRESS (real_block, 8);
99
100 real->align_offset = aligned - real_block;
101 real->str = aligned;
102
103 if (old_align_offset != real->align_offset)
104 {
105 /* Here comes the suck */
106 memmove (real_block + real->align_offset,
107 real_block + old_align_offset,
108 real->len + 1);
109 }
110
111 _dbus_assert (real->align_offset < 8);
112 _dbus_assert (_DBUS_ALIGN_ADDRESS (real->str, 8) == real->str);
113}
114
115static void
116undo_alignment (DBusRealString *real)
117{
118 if (real->align_offset != 0)
119 {
120 memmove (real->str - real->align_offset,
121 real->str,
122 real->len + 1);
123
124 real->str = real->str - real->align_offset;
125 real->align_offset = 0;
126 }
127}
128
140 int allocate_size)
141{
142 DBusRealString *real;
143
144 _DBUS_STATIC_ASSERT (sizeof (DBusString) == sizeof (DBusRealString));
145
146 _dbus_assert (str != NULL);
147
148 real = (DBusRealString*) str;
149
150 /* It's very important not to touch anything
151 * other than real->str if we're going to fail,
152 * since we also use this function to reset
153 * an existing string, e.g. in _dbus_string_steal_data()
154 */
155
156 real->str = dbus_malloc (_DBUS_STRING_ALLOCATION_PADDING + allocate_size);
157 if (real->str == NULL)
158 return FALSE;
159
160 real->allocated = _DBUS_STRING_ALLOCATION_PADDING + allocate_size;
161 real->len = 0;
162 real->str[real->len] = '\0';
163
164 real->constant = FALSE;
165 real->locked = FALSE;
166 real->valid = TRUE;
167 real->align_offset = 0;
168
169 fixup_alignment (real);
170
171 return TRUE;
172}
173
183{
184 return _dbus_string_init_preallocated (str, 0);
185}
186
196void
198 const char *value)
199{
200 _dbus_assert (value != NULL);
201
202 _dbus_string_init_const_len (str, value,
203 strlen (value));
204}
205
216void
218 const char *value,
219 int len)
220{
221 DBusRealString *real;
222
223 _dbus_assert (str != NULL);
224 _dbus_assert (len == 0 || value != NULL);
226 _dbus_assert (len >= 0);
227
228 real = (DBusRealString*) str;
229
230 real->str = (unsigned char*) value;
231 real->len = len;
232 real->allocated = real->len + _DBUS_STRING_ALLOCATION_PADDING; /* a lie, just to avoid special-case assertions... */
233 real->constant = TRUE;
234 real->locked = TRUE;
235 real->valid = TRUE;
236 real->align_offset = 0;
237
238 /* We don't require const strings to be 8-byte aligned as the
239 * memory is coming from elsewhere.
240 */
241}
242
255 const DBusString *from)
256{
257 if (!_dbus_string_init (str))
258 return FALSE;
259 if (!_dbus_string_append (str, _dbus_string_get_const_data (from)))
260 {
261 _dbus_string_free (str);
262 return FALSE;
263 }
264 return TRUE;
265}
266
277void
279{
280 DBusRealString *real = (DBusRealString*) str;
281 /* DBusRealString and DBusString have the same members in the same order,
282 * just differently-named */
283 DBusRealString invalid = _DBUS_STRING_INIT_INVALID;
284
285 /* Allow for the _DBUS_STRING_INIT_INVALID case */
286 if (real->str == NULL && real->len == 0 && real->allocated == 0 &&
287 !real->constant && !real->locked && !real->valid &&
288 real->align_offset == 0)
289 return;
290
292
293 if (real->constant)
294 goto wipe;
295
296 /* so it's safe if @p str returned by a failed
297 * _dbus_string_init call
298 * Bug: https://bugs.freedesktop.org/show_bug.cgi?id=65959
299 */
300 if (real->str == NULL)
301 goto wipe;
302
303 dbus_free (real->str - real->align_offset);
304
305wipe:
306 *real = invalid;
307 real->valid = FALSE;
308}
309
310static dbus_bool_t
311compact (DBusRealString *real,
312 int max_waste)
313{
314 unsigned char *new_str;
315 int new_allocated;
316 int waste;
317
318 waste = real->allocated - (real->len + _DBUS_STRING_ALLOCATION_PADDING);
319
320 if (waste <= max_waste)
321 return TRUE;
322
323 new_allocated = real->len + _DBUS_STRING_ALLOCATION_PADDING;
324
325 new_str = dbus_realloc (real->str - real->align_offset, new_allocated);
326 if (_DBUS_UNLIKELY (new_str == NULL))
327 return FALSE;
328
329 real->str = new_str + real->align_offset;
330 real->allocated = new_allocated;
331 fixup_alignment (real);
332
333 return TRUE;
334}
335
336#ifdef DBUS_ENABLE_EMBEDDED_TESTS
337/* Not using this feature at the moment,
338 * so marked DBUS_ENABLE_EMBEDDED_TESTS-only
339 */
349void
350_dbus_string_lock (DBusString *str)
351{
352 DBUS_LOCKED_STRING_PREAMBLE (str); /* can lock multiple times */
353
354 real->locked = TRUE;
355
356 /* Try to realloc to avoid excess memory usage, since
357 * we know we won't change the string further
358 */
359#define MAX_WASTE 48
360 compact (real, MAX_WASTE);
361}
362#endif /* DBUS_ENABLE_EMBEDDED_TESTS */
363
364static dbus_bool_t
365reallocate_for_length (DBusRealString *real,
366 int new_length)
367{
368 int new_allocated;
369 unsigned char *new_str;
370
371 /* at least double our old allocation to avoid O(n), avoiding
372 * overflow
373 */
374 if (real->allocated > (_DBUS_STRING_MAX_LENGTH + _DBUS_STRING_ALLOCATION_PADDING) / 2)
375 new_allocated = _DBUS_STRING_MAX_LENGTH + _DBUS_STRING_ALLOCATION_PADDING;
376 else
377 new_allocated = real->allocated * 2;
378
379 /* if you change the code just above here, run the tests without
380 * the following assert-only hack before you commit
381 */
382 /* This is keyed off asserts in addition to tests so when you
383 * disable asserts to profile, you don't get this destroyer
384 * of profiles.
385 */
386#if defined (DBUS_ENABLE_EMBEDDED_TESTS) && !defined (DBUS_DISABLE_ASSERT)
387 new_allocated = 0; /* ensure a realloc every time so that we go
388 * through all malloc failure codepaths
389 */
390#endif
391
392 /* But be sure we always alloc at least space for the new length */
393 new_allocated = MAX (new_allocated,
394 new_length + _DBUS_STRING_ALLOCATION_PADDING);
395
396 _dbus_assert (new_allocated >= real->allocated); /* code relies on this */
397 new_str = dbus_realloc (real->str - real->align_offset, new_allocated);
398 if (_DBUS_UNLIKELY (new_str == NULL))
399 return FALSE;
400
401 real->str = new_str + real->align_offset;
402 real->allocated = new_allocated;
403 fixup_alignment (real);
404
405 return TRUE;
406}
407
421 int max_waste)
422{
424
425 return compact (real, max_waste);
426}
427
428static dbus_bool_t
429set_length (DBusRealString *real,
430 int new_length)
431{
432 /* Note, we are setting the length not including nul termination */
433
434 /* exceeding max length is the same as failure to allocate memory */
435 if (_DBUS_UNLIKELY (new_length > _DBUS_STRING_MAX_LENGTH))
436 return FALSE;
437 else if (new_length > (real->allocated - _DBUS_STRING_ALLOCATION_PADDING) &&
438 _DBUS_UNLIKELY (!reallocate_for_length (real, new_length)))
439 return FALSE;
440 else
441 {
442 real->len = new_length;
443 real->str[new_length] = '\0';
444 return TRUE;
445 }
446}
447
448static dbus_bool_t
449open_gap (int len,
450 DBusRealString *dest,
451 int insert_at)
452{
453 if (len == 0)
454 return TRUE;
455
456 if (len > _DBUS_STRING_MAX_LENGTH - dest->len)
457 return FALSE; /* detected overflow of dest->len + len below */
458
459 if (!set_length (dest, dest->len + len))
460 return FALSE;
461
462 memmove (dest->str + insert_at + len,
463 dest->str + insert_at,
464 dest->len - len - insert_at);
465
466 return TRUE;
467}
468
469#ifndef _dbus_string_get_data
481char*
482_dbus_string_get_data (DBusString *str)
483{
485
486 return (char*) real->str;
487}
488#endif /* _dbus_string_get_data */
489
490/* only do the function if we don't have the macro */
491#ifndef _dbus_string_get_const_data
498const char*
499_dbus_string_get_const_data (const DBusString *str)
500{
502
503 return (const char*) real->str;
504}
505#endif /* _dbus_string_get_const_data */
506
520char*
522 int start,
523 int len)
524{
526 _dbus_assert (start >= 0);
527 _dbus_assert (len >= 0);
528 _dbus_assert (start <= real->len);
529 _dbus_assert (len <= real->len - start);
530
531 return (char*) real->str + start;
532}
533
534/* only do the function if we don't have the macro */
535#ifndef _dbus_string_get_const_data_len
544const char*
545_dbus_string_get_const_data_len (const DBusString *str,
546 int start,
547 int len)
548{
550 _dbus_assert (start >= 0);
551 _dbus_assert (len >= 0);
552 _dbus_assert (start <= real->len);
553 _dbus_assert (len <= real->len - start);
554
555 return (const char*) real->str + start;
556}
557#endif /* _dbus_string_get_const_data_len */
558
559/* only do the function if we don't have the macro */
560#ifndef _dbus_string_set_byte
568void
569_dbus_string_set_byte (DBusString *str,
570 int i,
571 unsigned char byte)
572{
574 _dbus_assert (i < real->len);
575 _dbus_assert (i >= 0);
576
577 real->str[i] = byte;
578}
579#endif /* _dbus_string_set_byte */
580
581/* only have the function if we didn't create a macro */
582#ifndef _dbus_string_get_byte
592unsigned char
593_dbus_string_get_byte (const DBusString *str,
594 int start)
595{
597 _dbus_assert (start <= real->len);
598 _dbus_assert (start >= 0);
599
600 return real->str[start];
601}
602#endif /* _dbus_string_get_byte */
603
616 int i,
617 int n_bytes,
618 unsigned char byte)
619{
621 _dbus_assert (i <= real->len);
622 _dbus_assert (i >= 0);
623 _dbus_assert (n_bytes >= 0);
624
625 if (n_bytes == 0)
626 return TRUE;
627
628 if (!open_gap (n_bytes, real, i))
629 return FALSE;
630
631 memset (real->str + i, byte, n_bytes);
632
633 return TRUE;
634}
635
646 int i,
647 unsigned char byte)
648{
650 _dbus_assert (i <= real->len);
651 _dbus_assert (i >= 0);
652
653 if (!open_gap (1, real, i))
654 return FALSE;
655
656 real->str[i] = byte;
657
658 return TRUE;
659}
660
673 char **data_return)
674{
676 _dbus_assert (data_return != NULL);
677
678 undo_alignment (real);
679
680 *data_return = (char*) real->str;
681
682 /* reset the string */
683 if (!_dbus_string_init (str))
684 {
685 /* hrm, put it back then */
686 real->str = (unsigned char*) *data_return;
687 *data_return = NULL;
688 fixup_alignment (real);
689 return FALSE;
690 }
691
692 return TRUE;
693}
694
704 char **data_return)
705{
707 _dbus_assert (data_return != NULL);
708
709 *data_return = dbus_malloc (real->len + 1);
710 if (*data_return == NULL)
711 return FALSE;
712
713 memcpy (*data_return, real->str, real->len + 1);
714
715 return TRUE;
716}
717
727void
729 char *buffer,
730 int avail_len)
731{
733
734 _dbus_assert (avail_len >= 0);
735 _dbus_assert (avail_len >= real->len);
736
737 memcpy (buffer, real->str, real->len);
738}
739
749void
751 char *buffer,
752 int avail_len)
753{
755
756 _dbus_assert (avail_len >= 0);
757 _dbus_assert (avail_len > real->len);
758
759 memcpy (buffer, real->str, real->len+1);
760}
761
762/* Only have the function if we don't have the macro */
763#ifndef _dbus_string_get_length
769int
770_dbus_string_get_length (const DBusString *str)
771{
773
774 return real->len;
775}
776#endif /* !_dbus_string_get_length */
777
792 int additional_length)
793{
795 _dbus_assert (additional_length >= 0);
796
797 if (_DBUS_UNLIKELY (additional_length > _DBUS_STRING_MAX_LENGTH - real->len))
798 return FALSE; /* would overflow */
799
800 return set_length (real,
801 real->len + additional_length);
802}
803
810void
812 int length_to_remove)
813{
815 _dbus_assert (length_to_remove >= 0);
816 _dbus_assert (length_to_remove <= real->len);
817
818 set_length (real,
819 real->len - length_to_remove);
820}
821
834 int length)
835{
837 _dbus_assert (length >= 0);
838
839 return set_length (real, length);
840}
841
842static dbus_bool_t
843align_insert_point_then_open_gap (DBusString *str,
844 int *insert_at_p,
845 int alignment,
846 int gap_size)
847{
848 unsigned long new_len; /* ulong to avoid _DBUS_ALIGN_VALUE overflow */
849 unsigned long gap_pos;
850 int insert_at;
851 int delta;
853 _dbus_assert (alignment >= 1);
854 _dbus_assert (alignment <= 8); /* it has to be a bug if > 8 */
855
856 insert_at = *insert_at_p;
857
858 _dbus_assert (insert_at <= real->len);
859
860 gap_pos = _DBUS_ALIGN_VALUE (insert_at, alignment);
861 new_len = real->len + (gap_pos - insert_at) + gap_size;
862
863 if (_DBUS_UNLIKELY (new_len > (unsigned long) _DBUS_STRING_MAX_LENGTH))
864 return FALSE;
865
866 delta = new_len - real->len;
867 _dbus_assert (delta >= 0);
868
869 if (delta == 0) /* only happens if gap_size == 0 and insert_at is aligned already */
870 {
871 _dbus_assert (((unsigned long) *insert_at_p) == gap_pos);
872 return TRUE;
873 }
874
875 if (_DBUS_UNLIKELY (!open_gap (new_len - real->len,
876 real, insert_at)))
877 return FALSE;
878
879 /* nul the padding if we had to add any padding */
880 if (gap_size < delta)
881 {
882 memset (&real->str[insert_at], '\0',
883 gap_pos - insert_at);
884 }
885
886 *insert_at_p = gap_pos;
887
888 return TRUE;
889}
890
891static dbus_bool_t
892align_length_then_lengthen (DBusString *str,
893 int alignment,
894 int then_lengthen_by)
895{
896 int insert_at;
897
898 insert_at = _dbus_string_get_length (str);
899
900 return align_insert_point_then_open_gap (str,
901 &insert_at,
902 alignment, then_lengthen_by);
903}
904
915 int alignment)
916{
917 return align_length_then_lengthen (str, alignment, 0);
918}
919
931 int extra_bytes)
932{
933 if (!_dbus_string_lengthen (str, extra_bytes))
934 return FALSE;
935 _dbus_string_shorten (str, extra_bytes);
936
937 return TRUE;
938}
939
940static dbus_bool_t
941append (DBusRealString *real,
942 const char *buffer,
943 int buffer_len)
944{
945 if (buffer_len == 0)
946 return TRUE;
947
948 if (!_dbus_string_lengthen ((DBusString*)real, buffer_len))
949 return FALSE;
950
951 memcpy (real->str + (real->len - buffer_len),
952 buffer,
953 buffer_len);
954
955 return TRUE;
956}
957
967 const char *buffer)
968{
969 unsigned long buffer_len;
970
972 _dbus_assert (buffer != NULL);
973
974 buffer_len = strlen (buffer);
975 if (buffer_len > (unsigned long) _DBUS_STRING_MAX_LENGTH)
976 return FALSE;
977
978 return append (real, buffer, buffer_len);
979}
980
982#define ASSIGN_2_OCTETS(p, octets) \
983 *((dbus_uint16_t*)(p)) = *((dbus_uint16_t*)(octets));
984
986#define ASSIGN_4_OCTETS(p, octets) \
987 *((dbus_uint32_t*)(p)) = *((dbus_uint32_t*)(octets));
988
990#define ASSIGN_8_OCTETS(p, octets) \
991 *((dbus_uint64_t*)(p)) = *((dbus_uint64_t*)(octets));
992
1004 int insert_at,
1005 const unsigned char octets[2])
1006{
1008
1009 if (!align_insert_point_then_open_gap (str, &insert_at, 2, 2))
1010 return FALSE;
1011
1012 ASSIGN_2_OCTETS (real->str + insert_at, octets);
1013
1014 return TRUE;
1015}
1016
1028 int insert_at,
1029 const unsigned char octets[4])
1030{
1032
1033 if (!align_insert_point_then_open_gap (str, &insert_at, 4, 4))
1034 return FALSE;
1035
1036 ASSIGN_4_OCTETS (real->str + insert_at, octets);
1037
1038 return TRUE;
1039}
1040
1052 int insert_at,
1053 const unsigned char octets[8])
1054{
1056
1057 if (!align_insert_point_then_open_gap (str, &insert_at, 8, 8))
1058 return FALSE;
1059
1060 _dbus_assert (_DBUS_ALIGN_VALUE (insert_at, 8) == (unsigned) insert_at);
1061
1062 ASSIGN_8_OCTETS (real->str + insert_at, octets);
1063
1064 return TRUE;
1065}
1066
1067
1080 int *insert_at,
1081 int alignment)
1082{
1084
1085 if (!align_insert_point_then_open_gap (str, insert_at, alignment, 0))
1086 return FALSE;
1087
1088 _dbus_assert (_DBUS_ALIGN_VALUE (*insert_at, alignment) == (unsigned) *insert_at);
1089
1090 return TRUE;
1091}
1092
1104 const char *format,
1105 va_list args)
1106{
1107 dbus_bool_t ret = FALSE;
1108 int len;
1109 va_list args_copy;
1110
1112
1113 DBUS_VA_COPY (args_copy, args);
1114
1115 /* Measure the message length without terminating nul */
1116 len = _dbus_printf_string_upper_bound (format, args);
1117
1118 if (len < 0)
1119 goto out;
1120
1121 if (!_dbus_string_lengthen (str, len))
1122 {
1123 goto out;
1124 }
1125
1126 vsprintf ((char*) (real->str + (real->len - len)),
1127 format, args_copy);
1128 ret = TRUE;
1129
1130out:
1131 va_end (args_copy);
1132
1133 return ret;
1134}
1135
1146 const char *format,
1147 ...)
1148{
1149 va_list args;
1150 dbus_bool_t retval;
1151
1152 va_start (args, format);
1153 retval = _dbus_string_append_printf_valist (str, format, args);
1154 va_end (args);
1155
1156 return retval;
1157}
1158
1169 const char *buffer,
1170 int len)
1171{
1173 _dbus_assert (buffer != NULL);
1174 _dbus_assert (len >= 0);
1175
1176 return append (real, buffer, len);
1177}
1178
1189 unsigned char byte)
1190{
1192
1193 if (!set_length (real, real->len + 1))
1194 return FALSE;
1195
1196 real->str[real->len-1] = byte;
1197
1198 return TRUE;
1199}
1200
1211_dbus_string_append_strings (DBusString *str, char **strings, char separator)
1212{
1213 int i;
1214
1215 if (strings == NULL)
1216 return TRUE;
1217
1218 for (i = 0; strings[i]; i++)
1219 {
1220 if (i > 0 && !_dbus_string_append_byte (str, (unsigned char) separator))
1221 return FALSE;
1222
1223 if (!_dbus_string_append (str, strings[i]))
1224 return FALSE;
1225 }
1226
1227 return TRUE;
1228}
1229
1230static void
1231delete (DBusRealString *real,
1232 int start,
1233 int len)
1234{
1235 if (len == 0)
1236 return;
1237
1238 memmove (real->str + start, real->str + start + len, real->len - (start + len));
1239 real->len -= len;
1240 real->str[real->len] = '\0';
1241}
1242
1252void
1254 int start,
1255 int len)
1256{
1258 _dbus_assert (start >= 0);
1259 _dbus_assert (len >= 0);
1260 _dbus_assert (start <= real->len);
1261 _dbus_assert (len <= real->len - start);
1262
1263 delete (real, start, len);
1264}
1265
1266static dbus_bool_t
1267copy (DBusRealString *source,
1268 int start,
1269 int len,
1270 DBusRealString *dest,
1271 int insert_at)
1272{
1273 if (len == 0)
1274 return TRUE;
1275
1276 if (!open_gap (len, dest, insert_at))
1277 return FALSE;
1278
1279 memmove (dest->str + insert_at,
1280 source->str + start,
1281 len);
1282
1283 return TRUE;
1284}
1285
1295#define DBUS_STRING_COPY_PREAMBLE(source, start, dest, insert_at) \
1296 DBusRealString *real_source = (DBusRealString*) source; \
1297 DBusRealString *real_dest = (DBusRealString*) dest; \
1298 _dbus_assert ((source) != (dest)); \
1299 DBUS_GENERIC_STRING_PREAMBLE (real_source); \
1300 DBUS_GENERIC_STRING_PREAMBLE (real_dest); \
1301 _dbus_assert (!real_dest->constant); \
1302 _dbus_assert (!real_dest->locked); \
1303 _dbus_assert ((start) >= 0); \
1304 _dbus_assert ((start) <= real_source->len); \
1305 _dbus_assert ((insert_at) >= 0); \
1306 _dbus_assert ((insert_at) <= real_dest->len)
1307
1320 int start,
1321 DBusString *dest,
1322 int insert_at)
1323{
1324 DBusRealString *real_source = (DBusRealString*) source;
1325 _dbus_assert (start <= real_source->len);
1326
1327 return _dbus_string_move_len (source, start,
1328 real_source->len - start,
1329 dest, insert_at);
1330}
1331
1344 int start,
1345 DBusString *dest,
1346 int insert_at)
1347{
1348 DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
1349
1350 return copy (real_source, start,
1351 real_source->len - start,
1352 real_dest,
1353 insert_at);
1354}
1355
1369 int start,
1370 int len,
1371 DBusString *dest,
1372 int insert_at)
1373
1374{
1375 DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
1376 _dbus_assert (len >= 0);
1377 _dbus_assert ((start + len) <= real_source->len);
1378
1379
1380 if (len == 0)
1381 {
1382 return TRUE;
1383 }
1384 else if (start == 0 &&
1385 len == real_source->len &&
1386 real_dest->len == 0)
1387 {
1388 /* Short-circuit moving an entire existing string to an empty string
1389 * by just swapping the buffers.
1390 */
1391 /* we assume ->constant doesn't matter as you can't have
1392 * a constant string involved in a move.
1393 */
1394#define ASSIGN_DATA(a, b) do { \
1395 (a)->str = (b)->str; \
1396 (a)->len = (b)->len; \
1397 (a)->allocated = (b)->allocated; \
1398 (a)->align_offset = (b)->align_offset; \
1399 } while (0)
1400
1401 DBusRealString tmp;
1402
1403 ASSIGN_DATA (&tmp, real_source);
1404 ASSIGN_DATA (real_source, real_dest);
1405 ASSIGN_DATA (real_dest, &tmp);
1406
1407 return TRUE;
1408 }
1409 else
1410 {
1411 if (!copy (real_source, start, len,
1412 real_dest,
1413 insert_at))
1414 return FALSE;
1415
1416 delete (real_source, start,
1417 len);
1418
1419 return TRUE;
1420 }
1421}
1422
1436 int start,
1437 int len,
1438 DBusString *dest,
1439 int insert_at)
1440{
1441 DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
1442 _dbus_assert (len >= 0);
1443 _dbus_assert (start <= real_source->len);
1444 _dbus_assert (len <= real_source->len - start);
1445
1446 return copy (real_source, start, len,
1447 real_dest,
1448 insert_at);
1449}
1450
1465 int start,
1466 int len,
1467 DBusString *dest,
1468 int replace_at,
1469 int replace_len)
1470{
1471 DBUS_STRING_COPY_PREAMBLE (source, start, dest, replace_at);
1472 _dbus_assert (len >= 0);
1473 _dbus_assert (start <= real_source->len);
1474 _dbus_assert (len <= real_source->len - start);
1475 _dbus_assert (replace_at >= 0);
1476 _dbus_assert (replace_at <= real_dest->len);
1477 _dbus_assert (replace_len <= real_dest->len - replace_at);
1478
1479 if (len == replace_len)
1480 {
1481 memmove (real_dest->str + replace_at,
1482 real_source->str + start, len);
1483 }
1484 else if (len < replace_len)
1485 {
1486 memmove (real_dest->str + replace_at,
1487 real_source->str + start, len);
1488 delete (real_dest, replace_at + len,
1489 replace_len - len);
1490 }
1491 else
1492 {
1493 int diff;
1494
1495 _dbus_assert (len > replace_len);
1496
1497 diff = len - replace_len;
1498
1499 /* First of all we check if destination string can be enlarged as
1500 * required, then we overwrite previous bytes
1501 */
1502
1503 if (!copy (real_source, start + replace_len, diff,
1504 real_dest, replace_at + replace_len))
1505 return FALSE;
1506
1507 memmove (real_dest->str + replace_at,
1508 real_source->str + start, replace_len);
1509 }
1510
1511 return TRUE;
1512}
1513
1528 unsigned char byte,
1529 DBusString *tail)
1530{
1531 int byte_position;
1532 char byte_string[2] = "";
1533 int head_length;
1534 int tail_length;
1535
1536 byte_string[0] = (char) byte;
1537
1538 if (!_dbus_string_find (source, 0, byte_string, &byte_position))
1539 return FALSE;
1540
1541 head_length = byte_position;
1542 tail_length = _dbus_string_get_length (source) - head_length - 1;
1543
1544 if (!_dbus_string_move_len (source, byte_position + 1, tail_length,
1545 tail, 0))
1546 return FALSE;
1547
1548 /* remove the trailing delimiter byte from the head now.
1549 */
1550 if (!_dbus_string_set_length (source, head_length))
1551 return FALSE;
1552
1553 return TRUE;
1554}
1555
1556/* Unicode macros and utf8_validate() from GLib Owen Taylor, Havoc
1557 * Pennington, and Tom Tromey are the authors and authorized relicense.
1558 */
1559
1565#define UTF8_COMPUTE(Char, Mask, Len) \
1566 if (Char < 128) \
1567 { \
1568 Len = 1; \
1569 Mask = 0x7f; \
1570 } \
1571 else if ((Char & 0xe0) == 0xc0) \
1572 { \
1573 Len = 2; \
1574 Mask = 0x1f; \
1575 } \
1576 else if ((Char & 0xf0) == 0xe0) \
1577 { \
1578 Len = 3; \
1579 Mask = 0x0f; \
1580 } \
1581 else if ((Char & 0xf8) == 0xf0) \
1582 { \
1583 Len = 4; \
1584 Mask = 0x07; \
1585 } \
1586 else if ((Char & 0xfc) == 0xf8) \
1587 { \
1588 Len = 5; \
1589 Mask = 0x03; \
1590 } \
1591 else if ((Char & 0xfe) == 0xfc) \
1592 { \
1593 Len = 6; \
1594 Mask = 0x01; \
1595 } \
1596 else \
1597 { \
1598 Len = 0; \
1599 Mask = 0; \
1600 }
1601
1606#define UTF8_LENGTH(Char) \
1607 ((Char) < 0x80 ? 1 : \
1608 ((Char) < 0x800 ? 2 : \
1609 ((Char) < 0x10000 ? 3 : \
1610 ((Char) < 0x200000 ? 4 : \
1611 ((Char) < 0x4000000 ? 5 : 6)))))
1612
1622#define UTF8_GET(Result, Chars, Count, Mask, Len) \
1623 (Result) = (Chars)[0] & (Mask); \
1624 for ((Count) = 1; (Count) < (Len); ++(Count)) \
1625 { \
1626 if (((Chars)[(Count)] & 0xc0) != 0x80) \
1627 { \
1628 (Result) = -1; \
1629 break; \
1630 } \
1631 (Result) <<= 6; \
1632 (Result) |= ((Chars)[(Count)] & 0x3f); \
1633 }
1634
1645#define UNICODE_VALID(Char) \
1646 ((Char) < 0x110000 && \
1647 (((Char) & 0xFFFFF800) != 0xD800))
1648
1665 int start,
1666 const char *substr,
1667 int *found)
1668{
1669 return _dbus_string_find_to (str, start,
1670 ((const DBusRealString*)str)->len,
1671 substr, found);
1672}
1673
1688 int start,
1689 int *found,
1690 int *found_len)
1691{
1692 int i;
1693
1695 _dbus_assert (start <= real->len);
1696 _dbus_assert (start >= 0);
1697
1698 i = start;
1699 while (i < real->len)
1700 {
1701 if (real->str[i] == '\r')
1702 {
1703 if ((i+1) < real->len && real->str[i+1] == '\n') /* "\r\n" */
1704 {
1705 if (found)
1706 *found = i;
1707 if (found_len)
1708 *found_len = 2;
1709 return TRUE;
1710 }
1711 else /* only "\r" */
1712 {
1713 if (found)
1714 *found = i;
1715 if (found_len)
1716 *found_len = 1;
1717 return TRUE;
1718 }
1719 }
1720 else if (real->str[i] == '\n') /* only "\n" */
1721 {
1722 if (found)
1723 *found = i;
1724 if (found_len)
1725 *found_len = 1;
1726 return TRUE;
1727 }
1728 ++i;
1729 }
1730
1731 if (found)
1732 *found = real->len;
1733
1734 if (found_len)
1735 *found_len = 0;
1736
1737 return FALSE;
1738}
1739
1758 int start,
1759 int end,
1760 const char *substr,
1761 int *found)
1762{
1763 int i;
1765 _dbus_assert (substr != NULL);
1766 _dbus_assert (start <= real->len);
1767 _dbus_assert (start >= 0);
1768 _dbus_assert (substr != NULL);
1769 _dbus_assert (end <= real->len);
1770 _dbus_assert (start <= end);
1771
1772 /* we always "find" an empty string */
1773 if (*substr == '\0')
1774 {
1775 if (found)
1776 *found = start;
1777 return TRUE;
1778 }
1779
1780 i = start;
1781 while (i < end)
1782 {
1783 if (real->str[i] == substr[0])
1784 {
1785 int j = i + 1;
1786
1787 while (j < end)
1788 {
1789 if (substr[j - i] == '\0')
1790 break;
1791 else if (real->str[j] != substr[j - i])
1792 break;
1793
1794 ++j;
1795 }
1796
1797 if (substr[j - i] == '\0')
1798 {
1799 if (found)
1800 *found = i;
1801 return TRUE;
1802 }
1803 }
1804
1805 ++i;
1806 }
1807
1808 if (found)
1809 *found = end;
1810
1811 return FALSE;
1812}
1813
1826 int start,
1827 int *found)
1828{
1829 int i;
1831 _dbus_assert (start <= real->len);
1832 _dbus_assert (start >= 0);
1833
1834 i = start;
1835 while (i < real->len)
1836 {
1837 if (real->str[i] == ' ' ||
1838 real->str[i] == '\t')
1839 {
1840 if (found)
1841 *found = i;
1842 return TRUE;
1843 }
1844
1845 ++i;
1846 }
1847
1848 if (found)
1849 *found = real->len;
1850
1851 return FALSE;
1852}
1853
1862void
1864 int start,
1865 int *end)
1866{
1867 int i;
1869 _dbus_assert (start <= real->len);
1870 _dbus_assert (start >= 0);
1871
1872 i = start;
1873 while (i < real->len)
1874 {
1875 if (!DBUS_IS_ASCII_BLANK (real->str[i]))
1876 break;
1877
1878 ++i;
1879 }
1880
1881 _dbus_assert (i == real->len || !DBUS_IS_ASCII_BLANK (real->str[i]));
1882
1883 if (end)
1884 *end = i;
1885}
1886
1887
1896void
1898 int start,
1899 int *end)
1900{
1901 int i;
1903 _dbus_assert (start <= real->len);
1904 _dbus_assert (start >= 0);
1905
1906 i = start;
1907 while (i < real->len)
1908 {
1909 if (!DBUS_IS_ASCII_WHITE (real->str[i]))
1910 break;
1911
1912 ++i;
1913 }
1914
1915 _dbus_assert (i == real->len || !(DBUS_IS_ASCII_WHITE (real->str[i])));
1916
1917 if (end)
1918 *end = i;
1919}
1920
1929void
1931 int end,
1932 int *start)
1933{
1934 int i;
1936 _dbus_assert (end <= real->len);
1937 _dbus_assert (end >= 0);
1938
1939 i = end;
1940 while (i > 0)
1941 {
1942 if (!DBUS_IS_ASCII_WHITE (real->str[i-1]))
1943 break;
1944 --i;
1945 }
1946
1947 _dbus_assert (i >= 0 && (i == 0 || !(DBUS_IS_ASCII_WHITE (real->str[i-1]))));
1948
1949 if (start)
1950 *start = i;
1951}
1952
1970 DBusString *dest)
1971{
1972 int eol, eol_len;
1973
1974 _dbus_string_set_length (dest, 0);
1975
1976 eol = 0;
1977 eol_len = 0;
1978 if (!_dbus_string_find_eol (source, 0, &eol, &eol_len))
1979 {
1980 _dbus_assert (eol == _dbus_string_get_length (source));
1981 if (eol == 0)
1982 {
1983 /* If there's no newline and source has zero length, we're done */
1984 return FALSE;
1985 }
1986 /* otherwise, the last line of the file has no eol characters */
1987 }
1988
1989 /* remember eol can be 0 if it's an empty line, but eol_len should not be zero also
1990 * since find_eol returned TRUE
1991 */
1992
1993 if (!_dbus_string_move_len (source, 0, eol + eol_len, dest, 0))
1994 return FALSE;
1995
1996 /* remove line ending */
1997 if (!_dbus_string_set_length (dest, eol))
1998 {
1999 _dbus_assert_not_reached ("out of memory when shortening a string");
2000 return FALSE;
2001 }
2002
2003 return TRUE;
2004}
2005
2006#ifdef DBUS_ENABLE_EMBEDDED_TESTS
2013void
2014_dbus_string_delete_first_word (DBusString *str)
2015{
2016 int i;
2017
2018 if (_dbus_string_find_blank (str, 0, &i))
2019 _dbus_string_skip_blank (str, i, &i);
2020
2021 _dbus_string_delete (str, 0, i);
2022}
2023#endif
2024
2025#ifdef DBUS_ENABLE_EMBEDDED_TESTS
2031void
2032_dbus_string_delete_leading_blanks (DBusString *str)
2033{
2034 int i;
2035
2036 _dbus_string_skip_blank (str, 0, &i);
2037
2038 if (i > 0)
2039 _dbus_string_delete (str, 0, i);
2040}
2041#endif
2042
2048void
2050{
2051 int i;
2052
2053 _dbus_string_skip_white (str, 0, &i);
2054
2055 if (i > 0)
2056 _dbus_string_delete (str, 0, i);
2057
2058 _dbus_string_skip_white_reverse (str, _dbus_string_get_length (str), &i);
2059
2060 _dbus_string_set_length (str, i);
2061}
2062
2074 const DBusString *b)
2075{
2076 const unsigned char *ap;
2077 const unsigned char *bp;
2078 const unsigned char *a_end;
2079 const DBusRealString *real_a = (const DBusRealString*) a;
2080 const DBusRealString *real_b = (const DBusRealString*) b;
2083
2084 if (real_a->len != real_b->len)
2085 return FALSE;
2086
2087 ap = real_a->str;
2088 bp = real_b->str;
2089 a_end = real_a->str + real_a->len;
2090 while (ap != a_end)
2091 {
2092 if (*ap != *bp)
2093 return FALSE;
2094
2095 ++ap;
2096 ++bp;
2097 }
2098
2099 return TRUE;
2100}
2101
2117 const DBusString *b,
2118 int len)
2119{
2120 const unsigned char *ap;
2121 const unsigned char *bp;
2122 const unsigned char *a_end;
2123 const DBusRealString *real_a = (const DBusRealString*) a;
2124 const DBusRealString *real_b = (const DBusRealString*) b;
2127
2128 if (real_a->len != real_b->len &&
2129 (real_a->len < len || real_b->len < len))
2130 return FALSE;
2131
2132 ap = real_a->str;
2133 bp = real_b->str;
2134 a_end = real_a->str + MIN (real_a->len, len);
2135 while (ap != a_end)
2136 {
2137 if (*ap != *bp)
2138 return FALSE;
2139
2140 ++ap;
2141 ++bp;
2142 }
2143
2144 return TRUE;
2145}
2146
2165 int a_start,
2166 int a_len,
2167 const DBusString *b,
2168 int b_start)
2169{
2170 const unsigned char *ap;
2171 const unsigned char *bp;
2172 const unsigned char *a_end;
2173 const DBusRealString *real_a = (const DBusRealString*) a;
2174 const DBusRealString *real_b = (const DBusRealString*) b;
2177 _dbus_assert (a_start >= 0);
2178 _dbus_assert (a_len >= 0);
2179 _dbus_assert (a_start <= real_a->len);
2180 _dbus_assert (a_len <= real_a->len - a_start);
2181 _dbus_assert (b_start >= 0);
2182 _dbus_assert (b_start <= real_b->len);
2183
2184 if (a_len > real_b->len - b_start)
2185 return FALSE;
2186
2187 ap = real_a->str + a_start;
2188 bp = real_b->str + b_start;
2189 a_end = ap + a_len;
2190 while (ap != a_end)
2191 {
2192 if (*ap != *bp)
2193 return FALSE;
2194
2195 ++ap;
2196 ++bp;
2197 }
2198
2199 _dbus_assert (bp <= (real_b->str + real_b->len));
2200
2201 return TRUE;
2202}
2203
2213 const char *c_str)
2214{
2215 const unsigned char *ap;
2216 const unsigned char *bp;
2217 const unsigned char *a_end;
2218 const DBusRealString *real_a = (const DBusRealString*) a;
2220 _dbus_assert (c_str != NULL);
2221
2222 ap = real_a->str;
2223 bp = (const unsigned char*) c_str;
2224 a_end = real_a->str + real_a->len;
2225 while (ap != a_end && *bp)
2226 {
2227 if (*ap != *bp)
2228 return FALSE;
2229
2230 ++ap;
2231 ++bp;
2232 }
2233
2234 if (ap != a_end || *bp)
2235 return FALSE;
2236
2237 return TRUE;
2238}
2239
2249 const char *c_str)
2250{
2251 const unsigned char *ap;
2252 const unsigned char *bp;
2253 const unsigned char *a_end;
2254 const DBusRealString *real_a = (const DBusRealString*) a;
2256 _dbus_assert (c_str != NULL);
2257
2258 ap = real_a->str;
2259 bp = (const unsigned char*) c_str;
2260 a_end = real_a->str + real_a->len;
2261 while (ap != a_end && *bp)
2262 {
2263 if (*ap != *bp)
2264 return FALSE;
2265
2266 ++ap;
2267 ++bp;
2268 }
2269
2270 if (*bp == '\0')
2271 return TRUE;
2272 else
2273 return FALSE;
2274}
2275
2287 const char *c_str,
2288 char word_separator)
2289{
2290 char next_char;
2291 const char *data;
2292 _dbus_assert (c_str != NULL);
2293
2294 if (!_dbus_string_starts_with_c_str (a, c_str))
2295 return FALSE;
2296
2297 data = _dbus_string_get_const_data (a);
2298 next_char = data[strlen (c_str)];
2299 return next_char == '\0' || next_char == word_separator;
2300}
2301
2312 unsigned char byte)
2313{
2314 const char hexdigits[16] = {
2315 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
2316 'a', 'b', 'c', 'd', 'e', 'f'
2317 };
2318
2319 if (!_dbus_string_append_byte (str,
2320 hexdigits[(byte >> 4)]))
2321 return FALSE;
2322
2323 if (!_dbus_string_append_byte (str,
2324 hexdigits[(byte & 0x0f)]))
2325 {
2327 _dbus_string_get_length (str) - 1);
2328 return FALSE;
2329 }
2330
2331 return TRUE;
2332}
2333
2346 int start,
2347 DBusString *dest,
2348 int insert_at)
2349{
2350 DBusString result;
2351 const unsigned char *p;
2352 const unsigned char *end;
2353 dbus_bool_t retval;
2354
2355 _dbus_assert (start <= _dbus_string_get_length (source));
2356
2357 if (!_dbus_string_init (&result))
2358 return FALSE;
2359
2360 retval = FALSE;
2361
2362 p = (const unsigned char*) _dbus_string_get_const_data (source);
2363 end = p + _dbus_string_get_length (source);
2364 p += start;
2365
2366 while (p != end)
2367 {
2368 if (!_dbus_string_append_byte_as_hex (&result, *p))
2369 goto out;
2370
2371 ++p;
2372 }
2373
2374 if (!_dbus_string_move (&result, 0, dest, insert_at))
2375 goto out;
2376
2377 retval = TRUE;
2378
2379 out:
2380 _dbus_string_free (&result);
2381 return retval;
2382}
2383
2396 int start,
2397 int *end_return,
2398 DBusString *dest,
2399 int insert_at)
2400{
2401 DBusString result;
2402 const unsigned char *p;
2403 const unsigned char *end;
2404 dbus_bool_t retval;
2405 dbus_bool_t high_bits;
2406
2407 _dbus_assert (start <= _dbus_string_get_length (source));
2408
2409 if (!_dbus_string_init (&result))
2410 return FALSE;
2411
2412 retval = FALSE;
2413
2414 high_bits = TRUE;
2415 p = (const unsigned char*) _dbus_string_get_const_data (source);
2416 end = p + _dbus_string_get_length (source);
2417 p += start;
2418
2419 while (p != end)
2420 {
2421 unsigned int val;
2422
2423 switch (*p)
2424 {
2425 case '0':
2426 val = 0;
2427 break;
2428 case '1':
2429 val = 1;
2430 break;
2431 case '2':
2432 val = 2;
2433 break;
2434 case '3':
2435 val = 3;
2436 break;
2437 case '4':
2438 val = 4;
2439 break;
2440 case '5':
2441 val = 5;
2442 break;
2443 case '6':
2444 val = 6;
2445 break;
2446 case '7':
2447 val = 7;
2448 break;
2449 case '8':
2450 val = 8;
2451 break;
2452 case '9':
2453 val = 9;
2454 break;
2455 case 'a':
2456 case 'A':
2457 val = 10;
2458 break;
2459 case 'b':
2460 case 'B':
2461 val = 11;
2462 break;
2463 case 'c':
2464 case 'C':
2465 val = 12;
2466 break;
2467 case 'd':
2468 case 'D':
2469 val = 13;
2470 break;
2471 case 'e':
2472 case 'E':
2473 val = 14;
2474 break;
2475 case 'f':
2476 case 'F':
2477 val = 15;
2478 break;
2479 default:
2480 goto done;
2481 }
2482
2483 if (high_bits)
2484 {
2485 if (!_dbus_string_append_byte (&result,
2486 val << 4))
2487 goto out;
2488 }
2489 else
2490 {
2491 int len;
2492 unsigned char b;
2493
2494 len = _dbus_string_get_length (&result);
2495
2496 b = _dbus_string_get_byte (&result, len - 1);
2497
2498 b |= val;
2499
2500 _dbus_string_set_byte (&result, len - 1, b);
2501 }
2502
2503 high_bits = !high_bits;
2504
2505 ++p;
2506 }
2507
2508 done:
2509 if (!_dbus_string_move (&result, 0, dest, insert_at))
2510 goto out;
2511
2512 if (end_return)
2513 *end_return = p - (const unsigned char*) _dbus_string_get_const_data (source);
2514
2515 retval = TRUE;
2516
2517 out:
2518 _dbus_string_free (&result);
2519 return retval;
2520}
2521
2537 int start,
2538 int len)
2539{
2540 const unsigned char *s;
2541 const unsigned char *end;
2543 _dbus_assert (start >= 0);
2544 _dbus_assert (start <= real->len);
2545 _dbus_assert (len >= 0);
2546
2547 if (len > real->len - start)
2548 return FALSE;
2549
2550 s = real->str + start;
2551 end = s + len;
2552 while (s != end)
2553 {
2554 if (_DBUS_UNLIKELY (!_DBUS_ISASCII (*s)))
2555 return FALSE;
2556
2557 ++s;
2558 }
2559
2560 return TRUE;
2561}
2562
2570void
2572 int start,
2573 int len)
2574{
2575 unsigned char *s;
2576 unsigned char *end;
2578 _dbus_assert (start >= 0);
2579 _dbus_assert (start <= real->len);
2580 _dbus_assert (len >= 0);
2581 _dbus_assert (len <= real->len - start);
2582
2583 s = real->str + start;
2584 end = s + len;
2585
2586 while (s != end)
2587 {
2588 if (*s >= 'A' && *s <= 'Z')
2589 *s += 'a' - 'A';
2590 ++s;
2591 }
2592}
2593
2601void
2603 int start,
2604 int len)
2605{
2606 unsigned char *s;
2607 unsigned char *end;
2609 _dbus_assert (start >= 0);
2610 _dbus_assert (start <= real->len);
2611 _dbus_assert (len >= 0);
2612 _dbus_assert (len <= real->len - start);
2613
2614 s = real->str + start;
2615 end = s + len;
2616
2617 while (s != end)
2618 {
2619 if (*s >= 'a' && *s <= 'z')
2620 *s += 'A' - 'a';
2621 ++s;
2622 }
2623}
2624
2642 int start,
2643 int len)
2644{
2645 const unsigned char *p;
2646 const unsigned char *end;
2648 _dbus_assert (start >= 0);
2649 _dbus_assert (start <= real->len);
2650 _dbus_assert (len >= 0);
2651
2652 /* we are doing _DBUS_UNLIKELY() here which might be
2653 * dubious in a generic library like GLib, but in D-Bus
2654 * we know we're validating messages and that it would
2655 * only be evil/broken apps that would have invalid
2656 * UTF-8. Also, this function seems to be a performance
2657 * bottleneck in profiles.
2658 */
2659
2660 if (_DBUS_UNLIKELY (len > real->len - start))
2661 return FALSE;
2662
2663 p = real->str + start;
2664 end = p + len;
2665
2666 while (p < end)
2667 {
2668 int i, mask, char_len;
2669 dbus_unichar_t result;
2670
2671 /* nul bytes considered invalid */
2672 if (*p == '\0')
2673 break;
2674
2675 /* Special-case ASCII; this makes us go a lot faster in
2676 * D-Bus profiles where we are typically validating
2677 * function names and such. We have to know that
2678 * all following checks will pass for ASCII though,
2679 * comments follow ...
2680 */
2681 if (*p < 128)
2682 {
2683 ++p;
2684 continue;
2685 }
2686
2687 UTF8_COMPUTE (*p, mask, char_len);
2688
2689 if (_DBUS_UNLIKELY (char_len == 0)) /* ASCII: char_len == 1 */
2690 break;
2691
2692 /* check that the expected number of bytes exists in the remaining length */
2693 if (_DBUS_UNLIKELY ((end - p) < char_len)) /* ASCII: p < end and char_len == 1 */
2694 break;
2695
2696 UTF8_GET (result, p, i, mask, char_len);
2697
2698 /* Check for overlong UTF-8 */
2699 if (_DBUS_UNLIKELY (UTF8_LENGTH (result) != char_len)) /* ASCII: UTF8_LENGTH == 1 */
2700 break;
2701#if 0
2702 /* The UNICODE_VALID check below will catch this */
2703 if (_DBUS_UNLIKELY (result == (dbus_unichar_t)-1)) /* ASCII: result = ascii value */
2704 break;
2705#endif
2706
2707 if (_DBUS_UNLIKELY (!UNICODE_VALID (result))) /* ASCII: always valid */
2708 break;
2709
2710 /* UNICODE_VALID should have caught it */
2711 _dbus_assert (result != (dbus_unichar_t)-1);
2712
2713 p += char_len;
2714 }
2715
2716 /* See that we covered the entire length if a length was
2717 * passed in
2718 */
2719 if (_DBUS_UNLIKELY (p != end))
2720 return FALSE;
2721 else
2722 return TRUE;
2723}
2724
2740 int start,
2741 int len)
2742{
2743 const unsigned char *s;
2744 const unsigned char *end;
2746 _dbus_assert (start >= 0);
2747 _dbus_assert (len >= 0);
2748 _dbus_assert (start <= real->len);
2749
2750 if (len > real->len - start)
2751 return FALSE;
2752
2753 s = real->str + start;
2754 end = s + len;
2755 while (s != end)
2756 {
2757 if (_DBUS_UNLIKELY (*s != '\0'))
2758 return FALSE;
2759 ++s;
2760 }
2761
2762 return TRUE;
2763}
2764
2770void
2772{
2774
2775 memset (real->str - real->align_offset, '\0', real->allocated);
2776}
2779/* tests are in dbus-string-util.c */
#define _dbus_assert_not_reached(explanation)
Aborts with an error message if called.
#define _dbus_assert(condition)
Aborts with an error message if the condition is false.
#define NULL
A null pointer, defined appropriately for C or C++.
#define TRUE
Expands to "1".
#define FALSE
Expands to "0".
void dbus_free(void *memory)
Frees a block of memory previously allocated by dbus_malloc() or dbus_malloc0().
Definition: dbus-memory.c:692
void * dbus_realloc(void *memory, size_t bytes)
Resizes a block of memory previously allocated by dbus_malloc() or dbus_malloc0().
Definition: dbus-memory.c:592
void * dbus_malloc(size_t bytes)
Allocates the given number of bytes, as with standard malloc().
Definition: dbus-memory.c:452
#define _DBUS_STRING_MAX_LENGTH
The maximum length of a DBusString.
#define DBUS_STRING_PREAMBLE(str)
Checks assertions about a string object that needs to be modifiable - may not be locked or const.
#define DBUS_CONST_STRING_PREAMBLE(str)
Checks assertions about a string that may be const or locked.
#define DBUS_GENERIC_STRING_PREAMBLE(real)
Checks a bunch of assertions about a string object.
#define DBUS_IS_ASCII_BLANK(c)
Checks for ASCII blank byte.
#define DBUS_IS_ASCII_WHITE(c)
Checks for ASCII whitespace byte.
#define DBUS_LOCKED_STRING_PREAMBLE(str)
Checks assertions about a string object that may be locked but can't be const.
dbus_bool_t _dbus_string_set_length(DBusString *str, int length)
Sets the length of a string.
Definition: dbus-string.c:833
dbus_bool_t _dbus_string_hex_decode(const DBusString *source, int start, int *end_return, DBusString *dest, int insert_at)
Decodes a string from hex encoding.
Definition: dbus-string.c:2395
dbus_bool_t _dbus_string_append(DBusString *str, const char *buffer)
Appends a nul-terminated C-style string to a DBusString.
Definition: dbus-string.c:966
dbus_bool_t _dbus_string_insert_8_aligned(DBusString *str, int insert_at, const unsigned char octets[8])
Inserts 8 bytes aligned on an 8 byte boundary with any alignment padding initialized to 0.
Definition: dbus-string.c:1051
dbus_bool_t _dbus_string_validate_nul(const DBusString *str, int start, int len)
Checks that the given range of the string is all nul bytes.
Definition: dbus-string.c:2739
dbus_bool_t _dbus_string_equal_substring(const DBusString *a, int a_start, int a_len, const DBusString *b, int b_start)
Tests two sub-parts of two DBusString for equality.
Definition: dbus-string.c:2164
#define UNICODE_VALID(Char)
Check whether a Unicode (5.2) char is in a valid range.
Definition: dbus-string.c:1645
dbus_bool_t _dbus_string_insert_alignment(DBusString *str, int *insert_at, int alignment)
Inserts padding at *insert_at such to align it to the given boundary.
Definition: dbus-string.c:1079
#define UTF8_COMPUTE(Char, Mask, Len)
computes length and mask of a unicode character
Definition: dbus-string.c:1565
dbus_bool_t _dbus_string_init(DBusString *str)
Initializes a string.
Definition: dbus-string.c:182
dbus_bool_t _dbus_string_append_strings(DBusString *str, char **strings, char separator)
Append vector with strings connected by separator.
Definition: dbus-string.c:1211
void _dbus_string_init_const(DBusString *str, const char *value)
Initializes a constant string.
Definition: dbus-string.c:197
dbus_bool_t _dbus_string_copy(const DBusString *source, int start, DBusString *dest, int insert_at)
Like _dbus_string_move(), but does not delete the section of the source string that's copied to the d...
Definition: dbus-string.c:1343
dbus_bool_t _dbus_string_find_eol(const DBusString *str, int start, int *found, int *found_len)
Finds end of line ("\r\n" or "\n") in the string, returning TRUE and filling in the byte index where ...
Definition: dbus-string.c:1687
#define ASSIGN_2_OCTETS(p, octets)
assign 2 bytes from one string to another
Definition: dbus-string.c:982
dbus_bool_t _dbus_string_starts_with_c_str(const DBusString *a, const char *c_str)
Checks whether a string starts with the given C string.
Definition: dbus-string.c:2248
dbus_bool_t _dbus_string_alloc_space(DBusString *str, int extra_bytes)
Preallocate extra_bytes such that a future lengthening of the string by extra_bytes is guaranteed to ...
Definition: dbus-string.c:930
dbus_bool_t _dbus_string_steal_data(DBusString *str, char **data_return)
Like _dbus_string_get_data(), but removes the gotten data from the original string.
Definition: dbus-string.c:672
void _dbus_string_skip_blank(const DBusString *str, int start, int *end)
Skips blanks from start, storing the first non-blank in *end (blank is space or tab).
Definition: dbus-string.c:1863
dbus_bool_t _dbus_string_init_preallocated(DBusString *str, int allocate_size)
Initializes a string that can be up to the given allocation size before it has to realloc.
Definition: dbus-string.c:139
void _dbus_string_skip_white_reverse(const DBusString *str, int end, int *start)
Skips whitespace from end, storing the start index of the trailing whitespace in *start.
Definition: dbus-string.c:1930
dbus_bool_t _dbus_string_init_from_string(DBusString *str, const DBusString *from)
Initializes a string from another string.
Definition: dbus-string.c:254
dbus_bool_t _dbus_string_split_on_byte(DBusString *source, unsigned char byte, DBusString *tail)
Looks for the first occurance of a byte, deletes that byte, and moves everything after the byte to th...
Definition: dbus-string.c:1527
dbus_bool_t _dbus_string_find(const DBusString *str, int start, const char *substr, int *found)
Finds the given substring in the string, returning TRUE and filling in the byte index where the subst...
Definition: dbus-string.c:1664
char * _dbus_string_get_data_len(DBusString *str, int start, int len)
Gets a sub-portion of the raw character buffer from the string.
Definition: dbus-string.c:521
dbus_bool_t _dbus_string_validate_utf8(const DBusString *str, int start, int len)
Checks that the given range of the string is valid UTF-8.
Definition: dbus-string.c:2641
dbus_bool_t _dbus_string_find_blank(const DBusString *str, int start, int *found)
Finds a blank (space or tab) in the string.
Definition: dbus-string.c:1825
void _dbus_string_init_const_len(DBusString *str, const char *value, int len)
Initializes a constant string with a length.
Definition: dbus-string.c:217
void _dbus_string_tolower_ascii(const DBusString *str, int start, int len)
Converts the given range of the string to lower case.
Definition: dbus-string.c:2571
dbus_bool_t _dbus_string_append_len(DBusString *str, const char *buffer, int len)
Appends block of bytes with the given length to a DBusString.
Definition: dbus-string.c:1168
void _dbus_string_free(DBusString *str)
Frees a string created by _dbus_string_init(), and fills it with the same contents as #_DBUS_STRING_I...
Definition: dbus-string.c:278
void _dbus_string_shorten(DBusString *str, int length_to_remove)
Makes a string shorter by the given number of bytes.
Definition: dbus-string.c:811
void _dbus_string_delete(DBusString *str, int start, int len)
Deletes a segment of a DBusString with length len starting at start.
Definition: dbus-string.c:1253
dbus_bool_t _dbus_string_copy_data(const DBusString *str, char **data_return)
Copies the data from the string into a char*.
Definition: dbus-string.c:703
dbus_bool_t _dbus_string_equal_c_str(const DBusString *a, const char *c_str)
Checks whether a string is equal to a C string.
Definition: dbus-string.c:2212
void _dbus_string_skip_white(const DBusString *str, int start, int *end)
Skips whitespace from start, storing the first non-whitespace in *end.
Definition: dbus-string.c:1897
dbus_bool_t _dbus_string_pop_line(DBusString *source, DBusString *dest)
Assigns a newline-terminated or \r\n-terminated line from the front of the string to the given dest s...
Definition: dbus-string.c:1969
dbus_bool_t _dbus_string_append_printf_valist(DBusString *str, const char *format, va_list args)
Appends a printf-style formatted string to the DBusString.
Definition: dbus-string.c:1103
dbus_bool_t _dbus_string_lengthen(DBusString *str, int additional_length)
Makes a string longer by the given number of bytes.
Definition: dbus-string.c:791
void _dbus_string_zero(DBusString *str)
Clears all allocated bytes in the string to zero.
Definition: dbus-string.c:2771
#define UTF8_LENGTH(Char)
computes length of a unicode character in UTF-8
Definition: dbus-string.c:1606
void _dbus_string_toupper_ascii(const DBusString *str, int start, int len)
Converts the given range of the string to upper case.
Definition: dbus-string.c:2602
dbus_bool_t _dbus_string_insert_bytes(DBusString *str, int i, int n_bytes, unsigned char byte)
Inserts a number of bytes of a given value at the given position.
Definition: dbus-string.c:615
dbus_bool_t _dbus_string_validate_ascii(const DBusString *str, int start, int len)
Checks that the given range of the string is valid ASCII with no nul bytes.
Definition: dbus-string.c:2536
dbus_bool_t _dbus_string_append_byte(DBusString *str, unsigned char byte)
Appends a single byte to the string, returning FALSE if not enough memory.
Definition: dbus-string.c:1188
void _dbus_string_chop_white(DBusString *str)
Deletes leading and trailing whitespace.
Definition: dbus-string.c:2049
dbus_bool_t _dbus_string_starts_with_words_c_str(const DBusString *a, const char *c_str, char word_separator)
Checks whether a string starts with the given C string, after which it ends or is separated from the ...
Definition: dbus-string.c:2286
dbus_bool_t _dbus_string_hex_encode(const DBusString *source, int start, DBusString *dest, int insert_at)
Encodes a string in hex, the way MD5 and SHA-1 are usually encoded.
Definition: dbus-string.c:2345
#define DBUS_STRING_COPY_PREAMBLE(source, start, dest, insert_at)
Checks assertions for two strings we're copying a segment between, and declares real_source/real_dest...
Definition: dbus-string.c:1295
dbus_bool_t _dbus_string_append_printf(DBusString *str, const char *format,...)
Appends a printf-style formatted string to the DBusString.
Definition: dbus-string.c:1145
dbus_bool_t _dbus_string_insert_byte(DBusString *str, int i, unsigned char byte)
Inserts a single byte at the given position.
Definition: dbus-string.c:645
#define UTF8_GET(Result, Chars, Count, Mask, Len)
Gets a UTF-8 value.
Definition: dbus-string.c:1622
dbus_bool_t _dbus_string_move_len(DBusString *source, int start, int len, DBusString *dest, int insert_at)
Like _dbus_string_move(), but can move a segment from the middle of the source string.
Definition: dbus-string.c:1368
void _dbus_string_copy_to_buffer_with_nul(const DBusString *str, char *buffer, int avail_len)
Copies the contents of a DBusString into a different buffer.
Definition: dbus-string.c:750
dbus_bool_t _dbus_string_compact(DBusString *str, int max_waste)
Compacts the string to avoid wasted memory.
Definition: dbus-string.c:420
dbus_bool_t _dbus_string_equal_len(const DBusString *a, const DBusString *b, int len)
Tests two DBusString for equality up to the given length.
Definition: dbus-string.c:2116
#define ASSIGN_8_OCTETS(p, octets)
assign 8 bytes from one string to another
Definition: dbus-string.c:990
dbus_bool_t _dbus_string_move(DBusString *source, int start, DBusString *dest, int insert_at)
Moves the end of one string into another string.
Definition: dbus-string.c:1319
dbus_bool_t _dbus_string_equal(const DBusString *a, const DBusString *b)
Tests two DBusString for equality.
Definition: dbus-string.c:2073
dbus_bool_t _dbus_string_insert_4_aligned(DBusString *str, int insert_at, const unsigned char octets[4])
Inserts 4 bytes aligned on a 4 byte boundary with any alignment padding initialized to 0.
Definition: dbus-string.c:1027
dbus_bool_t _dbus_string_insert_2_aligned(DBusString *str, int insert_at, const unsigned char octets[2])
Inserts 2 bytes aligned on a 2 byte boundary with any alignment padding initialized to 0.
Definition: dbus-string.c:1003
#define ASSIGN_4_OCTETS(p, octets)
assign 4 bytes from one string to another
Definition: dbus-string.c:986
dbus_bool_t _dbus_string_append_byte_as_hex(DBusString *str, unsigned char byte)
Appends a two-character hex digit to a string, where the hex digit has the value of the given byte.
Definition: dbus-string.c:2311
dbus_bool_t _dbus_string_align_length(DBusString *str, int alignment)
Align the length of a string to a specific alignment (typically 4 or 8) by appending nul bytes to the...
Definition: dbus-string.c:914
dbus_bool_t _dbus_string_find_to(const DBusString *str, int start, int end, const char *substr, int *found)
Finds the given substring in the string, up to a certain position, returning TRUE and filling in the ...
Definition: dbus-string.c:1757
dbus_bool_t _dbus_string_copy_len(const DBusString *source, int start, int len, DBusString *dest, int insert_at)
Like _dbus_string_copy(), but can copy a segment from the middle of the source string.
Definition: dbus-string.c:1435
void _dbus_string_copy_to_buffer(const DBusString *str, char *buffer, int avail_len)
Copies the contents of a DBusString into a different buffer.
Definition: dbus-string.c:728
dbus_bool_t _dbus_string_replace_len(const DBusString *source, int start, int len, DBusString *dest, int replace_at, int replace_len)
Replaces a segment of dest string with a segment of source string.
Definition: dbus-string.c:1464
int _dbus_printf_string_upper_bound(const char *format, va_list args)
Measure the length of the given format string and arguments, not including the terminating nul.
dbus_uint32_t dbus_bool_t
A boolean, valid values are TRUE and FALSE.
Definition: dbus-types.h:35
Internals of DBusString.
unsigned int align_offset
str - align_offset is the actual malloc block
unsigned int valid
DBusString is valid (initialized and not freed)
unsigned int constant
String data is not owned by DBusString.
unsigned int locked
DBusString has been locked and can't be changed.
unsigned char * str
String data, plus nul termination.
int allocated
Allocated size of data.
int len
Length without nul.