1/* -*- mode: C; c-file-style: "gnu" -*- */
2/* dbus-string.c String utility class (internal to D-Bus implementation)
3 *
4 * Copyright (C) 2002, 2003, 2004, 2005 Red Hat, Inc.
5 *
6 * Licensed under the Academic Free License version 2.1
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21 *
22 */
23
24#include "dbus-internals.h"
25#include "dbus-string.h"
26/* we allow a system header here, for speed/convenience */
27#include <string.h>
28/* for vsnprintf */
29#include <stdio.h>
30#define DBUS_CAN_USE_DBUS_STRING_PRIVATE 1
31#include "dbus-string-private.h"
32#include "dbus-marshal-basic.h" /* probably should be removed by moving the usage of DBUS_TYPE
33                                 * into the marshaling-related files
34                                 */
35/* for DBUS_VA_COPY */
36#include "dbus-sysdeps.h"
37
38/**
39 * @defgroup DBusString DBusString class
40 * @ingroup  DBusInternals
41 * @brief DBusString data structure for safer string handling
42 *
43 * Types and functions related to DBusString. DBusString is intended
44 * to be a string class that makes it hard to mess up security issues
45 * (and just in general harder to write buggy code).  It should be
46 * used (or extended and then used) rather than the libc stuff in
47 * string.h.  The string class is a bit inconvenient at spots because
48 * it handles out-of-memory failures and tries to be extra-robust.
49 *
50 * A DBusString has a maximum length set at initialization time; this
51 * can be used to ensure that a buffer doesn't get too big.  The
52 * _dbus_string_lengthen() method checks for overflow, and for max
53 * length being exceeded.
54 *
55 * Try to avoid conversion to a plain C string, i.e. add methods on
56 * the string object instead, only convert to C string when passing
57 * things out to the public API. In particular, no sprintf, strcpy,
58 * strcat, any of that should be used. The GString feature of
59 * accepting negative numbers for "length of string" is also absent,
60 * because it could keep us from detecting bogus huge lengths. i.e. if
61 * we passed in some bogus huge length it would be taken to mean
62 * "current length of string" instead of "broken crack"
63 *
64 * @todo #DBusString needs a lot of cleaning up; some of the
65 * API is no longer used, and the API is pretty inconsistent.
66 * In particular all the "append" APIs, especially those involving
67 * alignment but probably lots of them, are no longer used by the
68 * marshaling code which always does "inserts" now.
69 */
70
71/**
72 * @addtogroup DBusString
73 * @{
74 */
75
76static void
77fixup_alignment (DBusRealString *real)
78{
79  unsigned char *aligned;
80  unsigned char *real_block;
81  unsigned int old_align_offset;
82
83  /* we have to have extra space in real->allocated for the align offset and nul byte */
84  _dbus_assert (real->len <= real->allocated - _DBUS_STRING_ALLOCATION_PADDING);
85
86  old_align_offset = real->align_offset;
87  real_block = real->str - old_align_offset;
88
89  aligned = _DBUS_ALIGN_ADDRESS (real_block, 8);
90
91  real->align_offset = aligned - real_block;
92  real->str = aligned;
93
94  if (old_align_offset != real->align_offset)
95    {
96      /* Here comes the suck */
97      memmove (real_block + real->align_offset,
98               real_block + old_align_offset,
99               real->len + 1);
100    }
101
102  _dbus_assert (real->align_offset < 8);
103  _dbus_assert (_DBUS_ALIGN_ADDRESS (real->str, 8) == real->str);
104}
105
106static void
107undo_alignment (DBusRealString *real)
108{
109  if (real->align_offset != 0)
110    {
111      memmove (real->str - real->align_offset,
112               real->str,
113               real->len + 1);
114
115      real->str = real->str - real->align_offset;
116      real->align_offset = 0;
117    }
118}
119
120/**
121 * Initializes a string that can be up to the given allocation size
122 * before it has to realloc. The string starts life with zero length.
123 * The string must eventually be freed with _dbus_string_free().
124 *
125 * @param str memory to hold the string
126 * @param allocate_size amount to preallocate
127 * @returns #TRUE on success, #FALSE if no memory
128 */
129dbus_bool_t
130_dbus_string_init_preallocated (DBusString *str,
131                                int         allocate_size)
132{
133  DBusRealString *real;
134
135  _dbus_assert (str != NULL);
136
137  _dbus_assert (sizeof (DBusString) == sizeof (DBusRealString));
138
139  real = (DBusRealString*) str;
140
141  /* It's very important not to touch anything
142   * other than real->str if we're going to fail,
143   * since we also use this function to reset
144   * an existing string, e.g. in _dbus_string_steal_data()
145   */
146
147  real->str = dbus_malloc (_DBUS_STRING_ALLOCATION_PADDING + allocate_size);
148  if (real->str == NULL)
149    return FALSE;
150
151  real->allocated = _DBUS_STRING_ALLOCATION_PADDING + allocate_size;
152  real->len = 0;
153  real->str[real->len] = '\0';
154
155  real->max_length = _DBUS_STRING_MAX_MAX_LENGTH;
156  real->constant = FALSE;
157  real->locked = FALSE;
158  real->invalid = FALSE;
159  real->align_offset = 0;
160
161  fixup_alignment (real);
162
163  return TRUE;
164}
165
166/**
167 * Initializes a string. The string starts life with zero length.  The
168 * string must eventually be freed with _dbus_string_free().
169 *
170 * @param str memory to hold the string
171 * @returns #TRUE on success, #FALSE if no memory
172 */
173dbus_bool_t
174_dbus_string_init (DBusString *str)
175{
176  return _dbus_string_init_preallocated (str, 0);
177}
178
179#ifdef DBUS_BUILD_TESTS
180/* The max length thing is sort of a historical artifact
181 * from a feature that turned out to be dumb; perhaps
182 * we should purge it entirely. The problem with
183 * the feature is that it looks like memory allocation
184 * failure, but is not a transient or resolvable failure.
185 */
186static void
187set_max_length (DBusString *str,
188                int         max_length)
189{
190  DBusRealString *real;
191
192  real = (DBusRealString*) str;
193
194  real->max_length = max_length;
195}
196#endif /* DBUS_BUILD_TESTS */
197
198/**
199 * Initializes a constant string. The value parameter is not copied
200 * (should be static), and the string may never be modified.
201 * It is safe but not necessary to call _dbus_string_free()
202 * on a const string. The string has a length limit of MAXINT - 8.
203 *
204 * @param str memory to use for the string
205 * @param value a string to be stored in str (not copied!!!)
206 */
207void
208_dbus_string_init_const (DBusString *str,
209                         const char *value)
210{
211  _dbus_assert (value != NULL);
212
213  _dbus_string_init_const_len (str, value,
214                               strlen (value));
215}
216
217/**
218 * Initializes a constant string with a length. The value parameter is
219 * not copied (should be static), and the string may never be
220 * modified.  It is safe but not necessary to call _dbus_string_free()
221 * on a const string.
222 *
223 * @param str memory to use for the string
224 * @param value a string to be stored in str (not copied!!!)
225 * @param len the length to use
226 */
227void
228_dbus_string_init_const_len (DBusString *str,
229                             const char *value,
230                             int         len)
231{
232  DBusRealString *real;
233
234  _dbus_assert (str != NULL);
235  _dbus_assert (len == 0 || value != NULL);
236  _dbus_assert (len <= _DBUS_STRING_MAX_MAX_LENGTH);
237  _dbus_assert (len >= 0);
238
239  real = (DBusRealString*) str;
240
241  real->str = (unsigned char*) value;
242  real->len = len;
243  real->allocated = real->len + _DBUS_STRING_ALLOCATION_PADDING; /* a lie, just to avoid special-case assertions... */
244  real->max_length = real->len + 1;
245  real->constant = TRUE;
246  real->locked = TRUE;
247  real->invalid = FALSE;
248  real->align_offset = 0;
249
250  /* We don't require const strings to be 8-byte aligned as the
251   * memory is coming from elsewhere.
252   */
253}
254
255/**
256 * Frees a string created by _dbus_string_init().
257 *
258 * @param str memory where the string is stored.
259 */
260void
261_dbus_string_free (DBusString *str)
262{
263  DBusRealString *real = (DBusRealString*) str;
264  DBUS_GENERIC_STRING_PREAMBLE (real);
265
266  if (real->constant)
267    return;
268  dbus_free (real->str - real->align_offset);
269
270  real->invalid = TRUE;
271}
272
273#ifdef DBUS_BUILD_TESTS
274/* Not using this feature at the moment,
275 * so marked DBUS_BUILD_TESTS-only
276 */
277/**
278 * Locks a string such that any attempts to change the string will
279 * result in aborting the program. Also, if the string is wasting a
280 * lot of memory (allocation is sufficiently larger than what the
281 * string is really using), _dbus_string_lock() will realloc the
282 * string's data to "compact" it.
283 *
284 * @param str the string to lock.
285 */
286void
287_dbus_string_lock (DBusString *str)
288{
289  DBUS_LOCKED_STRING_PREAMBLE (str); /* can lock multiple times */
290
291  real->locked = TRUE;
292
293  /* Try to realloc to avoid excess memory usage, since
294   * we know we won't change the string further
295   */
296#define MAX_WASTE 48
297  if (real->allocated - MAX_WASTE > real->len)
298    {
299      unsigned char *new_str;
300      int new_allocated;
301
302      new_allocated = real->len + _DBUS_STRING_ALLOCATION_PADDING;
303
304      new_str = dbus_realloc (real->str - real->align_offset,
305                              new_allocated);
306      if (new_str != NULL)
307        {
308          real->str = new_str + real->align_offset;
309          real->allocated = new_allocated;
310          fixup_alignment (real);
311        }
312    }
313}
314#endif /* DBUS_BUILD_TESTS */
315
316static dbus_bool_t
317reallocate_for_length (DBusRealString *real,
318                       int             new_length)
319{
320  int new_allocated;
321  unsigned char *new_str;
322
323  /* at least double our old allocation to avoid O(n), avoiding
324   * overflow
325   */
326  if (real->allocated > (_DBUS_STRING_MAX_MAX_LENGTH + _DBUS_STRING_ALLOCATION_PADDING) / 2)
327    new_allocated = _DBUS_STRING_MAX_MAX_LENGTH + _DBUS_STRING_ALLOCATION_PADDING;
328  else
329    new_allocated = real->allocated * 2;
330
331  /* if you change the code just above here, run the tests without
332   * the following assert-only hack before you commit
333   */
334  /* This is keyed off asserts in addition to tests so when you
335   * disable asserts to profile, you don't get this destroyer
336   * of profiles.
337   */
338#ifdef DBUS_DISABLE_ASSERT
339#else
340#ifdef DBUS_BUILD_TESTS
341  new_allocated = 0; /* ensure a realloc every time so that we go
342                      * through all malloc failure codepaths
343                      */
344#endif /* DBUS_BUILD_TESTS */
345#endif /* !DBUS_DISABLE_ASSERT */
346
347  /* But be sure we always alloc at least space for the new length */
348  new_allocated = MAX (new_allocated,
349                       new_length + _DBUS_STRING_ALLOCATION_PADDING);
350
351  _dbus_assert (new_allocated >= real->allocated); /* code relies on this */
352  new_str = dbus_realloc (real->str - real->align_offset, new_allocated);
353  if (_DBUS_UNLIKELY (new_str == NULL))
354    return FALSE;
355
356  real->str = new_str + real->align_offset;
357  real->allocated = new_allocated;
358  fixup_alignment (real);
359
360  return TRUE;
361}
362
363static dbus_bool_t
364set_length (DBusRealString *real,
365            int             new_length)
366{
367  /* Note, we are setting the length not including nul termination */
368
369  /* exceeding max length is the same as failure to allocate memory */
370  if (_DBUS_UNLIKELY (new_length > real->max_length))
371    return FALSE;
372  else if (new_length > (real->allocated - _DBUS_STRING_ALLOCATION_PADDING) &&
373           _DBUS_UNLIKELY (!reallocate_for_length (real, new_length)))
374    return FALSE;
375  else
376    {
377      real->len = new_length;
378      real->str[new_length] = '\0';
379      return TRUE;
380    }
381}
382
383static dbus_bool_t
384open_gap (int             len,
385          DBusRealString *dest,
386          int             insert_at)
387{
388  if (len == 0)
389    return TRUE;
390
391  if (len > dest->max_length - dest->len)
392    return FALSE; /* detected overflow of dest->len + len below */
393
394  if (!set_length (dest, dest->len + len))
395    return FALSE;
396
397  memmove (dest->str + insert_at + len,
398           dest->str + insert_at,
399           dest->len - len - insert_at);
400
401  return TRUE;
402}
403
404#ifndef _dbus_string_get_data
405/**
406 * Gets the raw character buffer from the string.  The returned buffer
407 * will be nul-terminated, but note that strings may contain binary
408 * data so there may be extra nul characters prior to the termination.
409 * This function should be little-used, extend DBusString or add
410 * stuff to dbus-sysdeps.c instead. It's an error to use this
411 * function on a const string.
412 *
413 * @param str the string
414 * @returns the data
415 */
416char*
417_dbus_string_get_data (DBusString *str)
418{
419  DBUS_STRING_PREAMBLE (str);
420
421  return (char*) real->str;
422}
423#endif /* _dbus_string_get_data */
424
425/* only do the function if we don't have the macro */
426#ifndef _dbus_string_get_const_data
427/**
428 * Gets the raw character buffer from a const string.
429 *
430 * @param str the string
431 * @returns the string data
432 */
433const char*
434_dbus_string_get_const_data (const DBusString  *str)
435{
436  DBUS_CONST_STRING_PREAMBLE (str);
437
438  return (const char*) real->str;
439}
440#endif /* _dbus_string_get_const_data */
441
442/**
443 * Gets a sub-portion of the raw character buffer from the
444 * string. The "len" field is required simply for error
445 * checking, to be sure you don't try to use more
446 * string than exists. The nul termination of the
447 * returned buffer remains at the end of the entire
448 * string, not at start + len.
449 *
450 * @param str the string
451 * @param start byte offset to return
452 * @param len length of segment to return
453 * @returns the string data
454 */
455char*
456_dbus_string_get_data_len (DBusString *str,
457                           int         start,
458                           int         len)
459{
460  DBUS_STRING_PREAMBLE (str);
461  _dbus_assert (start >= 0);
462  _dbus_assert (len >= 0);
463  _dbus_assert (start <= real->len);
464  _dbus_assert (len <= real->len - start);
465
466  return (char*) real->str + start;
467}
468
469/* only do the function if we don't have the macro */
470#ifndef _dbus_string_get_const_data_len
471/**
472 * const version of _dbus_string_get_data_len().
473 *
474 * @param str the string
475 * @param start byte offset to return
476 * @param len length of segment to return
477 * @returns the string data
478 */
479const char*
480_dbus_string_get_const_data_len (const DBusString  *str,
481                                 int                start,
482                                 int                len)
483{
484  DBUS_CONST_STRING_PREAMBLE (str);
485  _dbus_assert (start >= 0);
486  _dbus_assert (len >= 0);
487  _dbus_assert (start <= real->len);
488  _dbus_assert (len <= real->len - start);
489
490  return (const char*) real->str + start;
491}
492#endif /* _dbus_string_get_const_data_len */
493
494/* only do the function if we don't have the macro */
495#ifndef _dbus_string_set_byte
496/**
497 * Sets the value of the byte at the given position.
498 *
499 * @param str the string
500 * @param i the position
501 * @param byte the new value
502 */
503void
504_dbus_string_set_byte (DBusString    *str,
505                       int            i,
506                       unsigned char  byte)
507{
508  DBUS_STRING_PREAMBLE (str);
509  _dbus_assert (i < real->len);
510  _dbus_assert (i >= 0);
511
512  real->str[i] = byte;
513}
514#endif /* _dbus_string_set_byte */
515
516/* only have the function if we didn't create a macro */
517#ifndef _dbus_string_get_byte
518/**
519 * Gets the byte at the given position. It is
520 * allowed to ask for the nul byte at the end of
521 * the string.
522 *
523 * @param str the string
524 * @param start the position
525 * @returns the byte at that position
526 */
527unsigned char
528_dbus_string_get_byte (const DBusString  *str,
529                       int                start)
530{
531  DBUS_CONST_STRING_PREAMBLE (str);
532  _dbus_assert (start <= real->len);
533  _dbus_assert (start >= 0);
534
535  return real->str[start];
536}
537#endif /* _dbus_string_get_byte */
538
539/**
540 * Inserts a number of bytes of a given value at the
541 * given position.
542 *
543 * @param str the string
544 * @param i the position
545 * @param n_bytes number of bytes
546 * @param byte the value to insert
547 * @returns #TRUE on success
548 */
549dbus_bool_t
550_dbus_string_insert_bytes (DBusString   *str,
551			   int           i,
552			   int           n_bytes,
553			   unsigned char byte)
554{
555  DBUS_STRING_PREAMBLE (str);
556  _dbus_assert (i <= real->len);
557  _dbus_assert (i >= 0);
558  _dbus_assert (n_bytes >= 0);
559
560  if (n_bytes == 0)
561    return TRUE;
562
563  if (!open_gap (n_bytes, real, i))
564    return FALSE;
565
566  memset (real->str + i, byte, n_bytes);
567
568  return TRUE;
569}
570
571/**
572 * Inserts a single byte at the given position.
573 *
574 * @param str the string
575 * @param i the position
576 * @param byte the value to insert
577 * @returns #TRUE on success
578 */
579dbus_bool_t
580_dbus_string_insert_byte (DBusString   *str,
581			   int           i,
582			   unsigned char byte)
583{
584  DBUS_STRING_PREAMBLE (str);
585  _dbus_assert (i <= real->len);
586  _dbus_assert (i >= 0);
587
588  if (!open_gap (1, real, i))
589    return FALSE;
590
591  real->str[i] = byte;
592
593  return TRUE;
594}
595
596/**
597 * Like _dbus_string_get_data(), but removes the
598 * gotten data from the original string. The caller
599 * must free the data returned. This function may
600 * fail due to lack of memory, and return #FALSE.
601 *
602 * @param str the string
603 * @param data_return location to return the buffer
604 * @returns #TRUE on success
605 */
606dbus_bool_t
607_dbus_string_steal_data (DBusString        *str,
608                         char             **data_return)
609{
610  int old_max_length;
611  DBUS_STRING_PREAMBLE (str);
612  _dbus_assert (data_return != NULL);
613
614  undo_alignment (real);
615
616  *data_return = (char*) real->str;
617
618  old_max_length = real->max_length;
619
620  /* reset the string */
621  if (!_dbus_string_init (str))
622    {
623      /* hrm, put it back then */
624      real->str = (unsigned char*) *data_return;
625      *data_return = NULL;
626      fixup_alignment (real);
627      return FALSE;
628    }
629
630  real->max_length = old_max_length;
631
632  return TRUE;
633}
634
635#ifdef DBUS_BUILD_TESTS
636/**
637 * Like _dbus_string_get_data_len(), but removes the gotten data from
638 * the original string. The caller must free the data returned. This
639 * function may fail due to lack of memory, and return #FALSE.
640 * The returned string is nul-terminated and has length len.
641 *
642 * @todo this function is broken because on failure it
643 * may corrupt the source string.
644 *
645 * @param str the string
646 * @param data_return location to return the buffer
647 * @param start the start of segment to steal
648 * @param len the length of segment to steal
649 * @returns #TRUE on success
650 */
651dbus_bool_t
652_dbus_string_steal_data_len (DBusString        *str,
653                             char             **data_return,
654                             int                start,
655                             int                len)
656{
657  DBusString dest;
658  DBUS_STRING_PREAMBLE (str);
659  _dbus_assert (data_return != NULL);
660  _dbus_assert (start >= 0);
661  _dbus_assert (len >= 0);
662  _dbus_assert (start <= real->len);
663  _dbus_assert (len <= real->len - start);
664
665  if (!_dbus_string_init (&dest))
666    return FALSE;
667
668  set_max_length (&dest, real->max_length);
669
670  if (!_dbus_string_move_len (str, start, len, &dest, 0))
671    {
672      _dbus_string_free (&dest);
673      return FALSE;
674    }
675
676  _dbus_warn ("Broken code in _dbus_string_steal_data_len(), see @todo, FIXME\n");
677  if (!_dbus_string_steal_data (&dest, data_return))
678    {
679      _dbus_string_free (&dest);
680      return FALSE;
681    }
682
683  _dbus_string_free (&dest);
684  return TRUE;
685}
686#endif /* DBUS_BUILD_TESTS */
687
688/**
689 * Copies the data from the string into a char*
690 *
691 * @param str the string
692 * @param data_return place to return the data
693 * @returns #TRUE on success, #FALSE on no memory
694 */
695dbus_bool_t
696_dbus_string_copy_data (const DBusString  *str,
697                        char             **data_return)
698{
699  DBUS_CONST_STRING_PREAMBLE (str);
700  _dbus_assert (data_return != NULL);
701
702  *data_return = dbus_malloc (real->len + 1);
703  if (*data_return == NULL)
704    return FALSE;
705
706  memcpy (*data_return, real->str, real->len + 1);
707
708  return TRUE;
709}
710
711/**
712 * Copies the contents of a DBusString into a different
713 * buffer. The resulting buffer will be nul-terminated.
714 *
715 * @param str a string
716 * @param buffer a C buffer to copy data to
717 * @param avail_len maximum length of C buffer
718 */
719void
720_dbus_string_copy_to_buffer (const DBusString  *str,
721			     char              *buffer,
722			     int                avail_len)
723{
724  int copy_len;
725  DBUS_CONST_STRING_PREAMBLE (str);
726
727  _dbus_assert (avail_len >= 0);
728
729  copy_len = MIN (avail_len, real->len+1);
730  memcpy (buffer, real->str, copy_len);
731  if (avail_len > 0 && avail_len == copy_len)
732    buffer[avail_len-1] = '\0';
733}
734
735#ifdef DBUS_BUILD_TESTS
736/**
737 * Copies a segment of the string into a char*
738 *
739 * @param str the string
740 * @param data_return place to return the data
741 * @param start start index
742 * @param len length to copy
743 * @returns #FALSE if no memory
744 */
745dbus_bool_t
746_dbus_string_copy_data_len (const DBusString  *str,
747                            char             **data_return,
748                            int                start,
749                            int                len)
750{
751  DBusString dest;
752
753  DBUS_CONST_STRING_PREAMBLE (str);
754  _dbus_assert (data_return != NULL);
755  _dbus_assert (start >= 0);
756  _dbus_assert (len >= 0);
757  _dbus_assert (start <= real->len);
758  _dbus_assert (len <= real->len - start);
759
760  if (!_dbus_string_init (&dest))
761    return FALSE;
762
763  set_max_length (&dest, real->max_length);
764
765  if (!_dbus_string_copy_len (str, start, len, &dest, 0))
766    {
767      _dbus_string_free (&dest);
768      return FALSE;
769    }
770
771  if (!_dbus_string_steal_data (&dest, data_return))
772    {
773      _dbus_string_free (&dest);
774      return FALSE;
775    }
776
777  _dbus_string_free (&dest);
778  return TRUE;
779}
780#endif /* DBUS_BUILD_TESTS */
781
782/* Only have the function if we don't have the macro */
783#ifndef _dbus_string_get_length
784/**
785 * Gets the length of a string (not including nul termination).
786 *
787 * @returns the length.
788 */
789int
790_dbus_string_get_length (const DBusString  *str)
791{
792  /* The assertion should not fail for empty strings. */
793  DBusRealString *real = (DBusRealString *)str;
794  if (((DBusRealString *)str)->len || ((DBusRealString *)str)->allocated) {
795      DBUS_CONST_STRING_PREAMBLE (str);
796  }
797
798  return real->len;
799}
800#endif /* !_dbus_string_get_length */
801
802/**
803 * Makes a string longer by the given number of bytes.  Checks whether
804 * adding additional_length to the current length would overflow an
805 * integer, and checks for exceeding a string's max length.
806 * The new bytes are not initialized, other than nul-terminating
807 * the end of the string. The uninitialized bytes may contain
808 * nul bytes or other junk.
809 *
810 * @param str a string
811 * @param additional_length length to add to the string.
812 * @returns #TRUE on success.
813 */
814dbus_bool_t
815_dbus_string_lengthen (DBusString *str,
816                       int         additional_length)
817{
818  DBUS_STRING_PREAMBLE (str);
819  _dbus_assert (additional_length >= 0);
820
821  if (_DBUS_UNLIKELY (additional_length > real->max_length - real->len))
822    return FALSE; /* would overflow */
823
824  return set_length (real,
825                     real->len + additional_length);
826}
827
828/**
829 * Makes a string shorter by the given number of bytes.
830 *
831 * @param str a string
832 * @param length_to_remove length to remove from the string.
833 */
834void
835_dbus_string_shorten (DBusString *str,
836                      int         length_to_remove)
837{
838  DBUS_STRING_PREAMBLE (str);
839  _dbus_assert (length_to_remove >= 0);
840  _dbus_assert (length_to_remove <= real->len);
841
842  set_length (real,
843              real->len - length_to_remove);
844}
845
846/**
847 * Sets the length of a string. Can be used to truncate or lengthen
848 * the string. If the string is lengthened, the function may fail and
849 * return #FALSE. Newly-added bytes are not initialized, as with
850 * _dbus_string_lengthen().
851 *
852 * @param str a string
853 * @param length new length of the string.
854 * @returns #FALSE on failure.
855 */
856dbus_bool_t
857_dbus_string_set_length (DBusString *str,
858                         int         length)
859{
860  DBUS_STRING_PREAMBLE (str);
861  _dbus_assert (length >= 0);
862
863  return set_length (real, length);
864}
865
866static dbus_bool_t
867align_insert_point_then_open_gap (DBusString *str,
868                                  int        *insert_at_p,
869                                  int         alignment,
870                                  int         gap_size)
871{
872  unsigned long new_len; /* ulong to avoid _DBUS_ALIGN_VALUE overflow */
873  unsigned long gap_pos;
874  int insert_at;
875  int delta;
876  DBUS_STRING_PREAMBLE (str);
877  _dbus_assert (alignment >= 1);
878  _dbus_assert (alignment <= 8); /* it has to be a bug if > 8 */
879
880  insert_at = *insert_at_p;
881
882  _dbus_assert (insert_at <= real->len);
883
884  gap_pos = _DBUS_ALIGN_VALUE (insert_at, alignment);
885  new_len = real->len + (gap_pos - insert_at) + gap_size;
886
887  if (_DBUS_UNLIKELY (new_len > (unsigned long) real->max_length))
888    return FALSE;
889
890  delta = new_len - real->len;
891  _dbus_assert (delta >= 0);
892
893  if (delta == 0) /* only happens if gap_size == 0 and insert_at is aligned already */
894    {
895      _dbus_assert (((unsigned long) *insert_at_p) == gap_pos);
896      return TRUE;
897    }
898
899  if (_DBUS_UNLIKELY (!open_gap (new_len - real->len,
900                                 real, insert_at)))
901    return FALSE;
902
903  /* nul the padding if we had to add any padding */
904  if (gap_size < delta)
905    {
906      memset (&real->str[insert_at], '\0',
907              gap_pos - insert_at);
908    }
909
910  *insert_at_p = gap_pos;
911
912  return TRUE;
913}
914
915static dbus_bool_t
916align_length_then_lengthen (DBusString *str,
917                            int         alignment,
918                            int         then_lengthen_by)
919{
920  int insert_at;
921
922  insert_at = _dbus_string_get_length (str);
923
924  return align_insert_point_then_open_gap (str,
925                                           &insert_at,
926                                           alignment, then_lengthen_by);
927}
928
929/**
930 * Align the length of a string to a specific alignment (typically 4 or 8)
931 * by appending nul bytes to the string.
932 *
933 * @param str a string
934 * @param alignment the alignment
935 * @returns #FALSE if no memory
936 */
937dbus_bool_t
938_dbus_string_align_length (DBusString *str,
939                           int         alignment)
940{
941  return align_length_then_lengthen (str, alignment, 0);
942}
943
944/**
945 * Preallocate extra_bytes such that a future lengthening of the
946 * string by extra_bytes is guaranteed to succeed without an out of
947 * memory error.
948 *
949 * @param str a string
950 * @param extra_bytes bytes to alloc
951 * @returns #FALSE if no memory
952 */
953dbus_bool_t
954_dbus_string_alloc_space (DBusString        *str,
955                          int                extra_bytes)
956{
957  if (!_dbus_string_lengthen (str, extra_bytes))
958    return FALSE;
959  _dbus_string_shorten (str, extra_bytes);
960
961  return TRUE;
962}
963
964static dbus_bool_t
965append (DBusRealString *real,
966        const char     *buffer,
967        int             buffer_len)
968{
969  if (buffer_len == 0)
970    return TRUE;
971
972  if (!_dbus_string_lengthen ((DBusString*)real, buffer_len))
973    return FALSE;
974
975  memcpy (real->str + (real->len - buffer_len),
976          buffer,
977          buffer_len);
978
979  return TRUE;
980}
981
982/**
983 * Appends a nul-terminated C-style string to a DBusString.
984 *
985 * @param str the DBusString
986 * @param buffer the nul-terminated characters to append
987 * @returns #FALSE if not enough memory.
988 */
989dbus_bool_t
990_dbus_string_append (DBusString *str,
991                     const char *buffer)
992{
993  unsigned long buffer_len;
994
995  DBUS_STRING_PREAMBLE (str);
996  _dbus_assert (buffer != NULL);
997
998  buffer_len = strlen (buffer);
999  if (buffer_len > (unsigned long) real->max_length)
1000    return FALSE;
1001
1002  return append (real, buffer, buffer_len);
1003}
1004
1005/** assign 2 bytes from one string to another */
1006#define ASSIGN_2_OCTETS(p, octets) \
1007  *((dbus_uint16_t*)(p)) = *((dbus_uint16_t*)(octets));
1008
1009/** assign 4 bytes from one string to another */
1010#define ASSIGN_4_OCTETS(p, octets) \
1011  *((dbus_uint32_t*)(p)) = *((dbus_uint32_t*)(octets));
1012
1013#ifdef DBUS_HAVE_INT64
1014/** assign 8 bytes from one string to another */
1015#define ASSIGN_8_OCTETS(p, octets) \
1016  *((dbus_uint64_t*)(p)) = *((dbus_uint64_t*)(octets));
1017#else
1018/** assign 8 bytes from one string to another */
1019#define ASSIGN_8_OCTETS(p, octets)              \
1020do {                                            \
1021  unsigned char *b;                             \
1022                                                \
1023  b = p;                                        \
1024                                                \
1025  *b++ = octets[0];                             \
1026  *b++ = octets[1];                             \
1027  *b++ = octets[2];                             \
1028  *b++ = octets[3];                             \
1029  *b++ = octets[4];                             \
1030  *b++ = octets[5];                             \
1031  *b++ = octets[6];                             \
1032  *b++ = octets[7];                             \
1033  _dbus_assert (b == p + 8);                    \
1034} while (0)
1035#endif /* DBUS_HAVE_INT64 */
1036
1037#ifdef DBUS_BUILD_TESTS
1038/**
1039 * Appends 4 bytes aligned on a 4 byte boundary
1040 * with any alignment padding initialized to 0.
1041 *
1042 * @param str the DBusString
1043 * @param octets 4 bytes to append
1044 * @returns #FALSE if not enough memory.
1045 */
1046dbus_bool_t
1047_dbus_string_append_4_aligned (DBusString         *str,
1048                               const unsigned char octets[4])
1049{
1050  DBUS_STRING_PREAMBLE (str);
1051
1052  if (!align_length_then_lengthen (str, 4, 4))
1053    return FALSE;
1054
1055  ASSIGN_4_OCTETS (real->str + (real->len - 4), octets);
1056
1057  return TRUE;
1058}
1059#endif /* DBUS_BUILD_TESTS */
1060
1061#ifdef DBUS_BUILD_TESTS
1062/**
1063 * Appends 8 bytes aligned on an 8 byte boundary
1064 * with any alignment padding initialized to 0.
1065 *
1066 * @param str the DBusString
1067 * @param octets 8 bytes to append
1068 * @returns #FALSE if not enough memory.
1069 */
1070dbus_bool_t
1071_dbus_string_append_8_aligned (DBusString         *str,
1072                               const unsigned char octets[8])
1073{
1074  DBUS_STRING_PREAMBLE (str);
1075
1076  if (!align_length_then_lengthen (str, 8, 8))
1077    return FALSE;
1078
1079  ASSIGN_8_OCTETS (real->str + (real->len - 8), octets);
1080
1081  return TRUE;
1082}
1083#endif /* DBUS_BUILD_TESTS */
1084
1085/**
1086 * Inserts 2 bytes aligned on a 2 byte boundary
1087 * with any alignment padding initialized to 0.
1088 *
1089 * @param str the DBusString
1090 * @param insert_at where to insert
1091 * @param octets 2 bytes to insert
1092 * @returns #FALSE if not enough memory.
1093 */
1094dbus_bool_t
1095_dbus_string_insert_2_aligned (DBusString         *str,
1096                               int                 insert_at,
1097                               const unsigned char octets[4])
1098{
1099  DBUS_STRING_PREAMBLE (str);
1100
1101  if (!align_insert_point_then_open_gap (str, &insert_at, 2, 2))
1102    return FALSE;
1103
1104  ASSIGN_2_OCTETS (real->str + insert_at, octets);
1105
1106  return TRUE;
1107}
1108
1109/**
1110 * Inserts 4 bytes aligned on a 4 byte boundary
1111 * with any alignment padding initialized to 0.
1112 *
1113 * @param str the DBusString
1114 * @param insert_at where to insert
1115 * @param octets 4 bytes to insert
1116 * @returns #FALSE if not enough memory.
1117 */
1118dbus_bool_t
1119_dbus_string_insert_4_aligned (DBusString         *str,
1120                               int                 insert_at,
1121                               const unsigned char octets[4])
1122{
1123  DBUS_STRING_PREAMBLE (str);
1124
1125  if (!align_insert_point_then_open_gap (str, &insert_at, 4, 4))
1126    return FALSE;
1127
1128  ASSIGN_4_OCTETS (real->str + insert_at, octets);
1129
1130  return TRUE;
1131}
1132
1133/**
1134 * Inserts 8 bytes aligned on an 8 byte boundary
1135 * with any alignment padding initialized to 0.
1136 *
1137 * @param str the DBusString
1138 * @param insert_at where to insert
1139 * @param octets 8 bytes to insert
1140 * @returns #FALSE if not enough memory.
1141 */
1142dbus_bool_t
1143_dbus_string_insert_8_aligned (DBusString         *str,
1144                               int                 insert_at,
1145                               const unsigned char octets[8])
1146{
1147  DBUS_STRING_PREAMBLE (str);
1148
1149  if (!align_insert_point_then_open_gap (str, &insert_at, 8, 8))
1150    return FALSE;
1151
1152  _dbus_assert (_DBUS_ALIGN_VALUE (insert_at, 8) == (unsigned) insert_at);
1153
1154  ASSIGN_8_OCTETS (real->str + insert_at, octets);
1155
1156  return TRUE;
1157}
1158
1159
1160/**
1161 * Inserts padding at *insert_at such to align it to the given
1162 * boundary. Initializes the padding to nul bytes. Sets *insert_at
1163 * to the aligned position.
1164 *
1165 * @param str the DBusString
1166 * @param insert_at location to be aligned
1167 * @param alignment alignment boundary (1, 2, 4, or 8)
1168 * @returns #FALSE if not enough memory.
1169 */
1170dbus_bool_t
1171_dbus_string_insert_alignment (DBusString        *str,
1172                               int               *insert_at,
1173                               int                alignment)
1174{
1175  DBUS_STRING_PREAMBLE (str);
1176
1177  if (!align_insert_point_then_open_gap (str, insert_at, alignment, 0))
1178    return FALSE;
1179
1180  _dbus_assert (_DBUS_ALIGN_VALUE (*insert_at, alignment) == (unsigned) *insert_at);
1181
1182  return TRUE;
1183}
1184
1185/**
1186 * Appends a printf-style formatted string
1187 * to the #DBusString.
1188 *
1189 * @param str the string
1190 * @param format printf format
1191 * @param args variable argument list
1192 * @returns #FALSE if no memory
1193 */
1194dbus_bool_t
1195_dbus_string_append_printf_valist  (DBusString        *str,
1196                                    const char        *format,
1197                                    va_list            args)
1198{
1199  int len;
1200  va_list args_copy;
1201
1202  DBUS_STRING_PREAMBLE (str);
1203
1204  DBUS_VA_COPY (args_copy, args);
1205
1206  /* Measure the message length without terminating nul */
1207  len = _dbus_printf_string_upper_bound (format, args);
1208
1209  if (!_dbus_string_lengthen (str, len))
1210    {
1211      /* don't leak the copy */
1212      va_end (args_copy);
1213      return FALSE;
1214    }
1215
1216  vsprintf ((char*) (real->str + (real->len - len)),
1217            format, args_copy);
1218
1219  va_end (args_copy);
1220
1221  return TRUE;
1222}
1223
1224/**
1225 * Appends a printf-style formatted string
1226 * to the #DBusString.
1227 *
1228 * @param str the string
1229 * @param format printf format
1230 * @returns #FALSE if no memory
1231 */
1232dbus_bool_t
1233_dbus_string_append_printf (DBusString        *str,
1234                            const char        *format,
1235                            ...)
1236{
1237  va_list args;
1238  dbus_bool_t retval;
1239
1240  va_start (args, format);
1241  retval = _dbus_string_append_printf_valist (str, format, args);
1242  va_end (args);
1243
1244  return retval;
1245}
1246
1247/**
1248 * Appends block of bytes with the given length to a DBusString.
1249 *
1250 * @param str the DBusString
1251 * @param buffer the bytes to append
1252 * @param len the number of bytes to append
1253 * @returns #FALSE if not enough memory.
1254 */
1255dbus_bool_t
1256_dbus_string_append_len (DBusString *str,
1257                         const char *buffer,
1258                         int         len)
1259{
1260  DBUS_STRING_PREAMBLE (str);
1261  _dbus_assert (buffer != NULL);
1262  _dbus_assert (len >= 0);
1263
1264  return append (real, buffer, len);
1265}
1266
1267/**
1268 * Appends a single byte to the string, returning #FALSE
1269 * if not enough memory.
1270 *
1271 * @param str the string
1272 * @param byte the byte to append
1273 * @returns #TRUE on success
1274 */
1275dbus_bool_t
1276_dbus_string_append_byte (DBusString    *str,
1277                          unsigned char  byte)
1278{
1279  DBUS_STRING_PREAMBLE (str);
1280
1281  if (!set_length (real, real->len + 1))
1282    return FALSE;
1283
1284  real->str[real->len-1] = byte;
1285
1286  return TRUE;
1287}
1288
1289#ifdef DBUS_BUILD_TESTS
1290/**
1291 * Appends a single Unicode character, encoding the character
1292 * in UTF-8 format.
1293 *
1294 * @param str the string
1295 * @param ch the Unicode character
1296 */
1297dbus_bool_t
1298_dbus_string_append_unichar (DBusString    *str,
1299                             dbus_unichar_t ch)
1300{
1301  int len;
1302  int first;
1303  int i;
1304  unsigned char *out;
1305
1306  DBUS_STRING_PREAMBLE (str);
1307
1308  /* this code is from GLib but is pretty standard I think */
1309
1310  len = 0;
1311
1312  if (ch < 0x80)
1313    {
1314      first = 0;
1315      len = 1;
1316    }
1317  else if (ch < 0x800)
1318    {
1319      first = 0xc0;
1320      len = 2;
1321    }
1322  else if (ch < 0x10000)
1323    {
1324      first = 0xe0;
1325      len = 3;
1326    }
1327   else if (ch < 0x200000)
1328    {
1329      first = 0xf0;
1330      len = 4;
1331    }
1332  else if (ch < 0x4000000)
1333    {
1334      first = 0xf8;
1335      len = 5;
1336    }
1337  else
1338    {
1339      first = 0xfc;
1340      len = 6;
1341    }
1342
1343  if (len > (real->max_length - real->len))
1344    return FALSE; /* real->len + len would overflow */
1345
1346  if (!set_length (real, real->len + len))
1347    return FALSE;
1348
1349  out = real->str + (real->len - len);
1350
1351  for (i = len - 1; i > 0; --i)
1352    {
1353      out[i] = (ch & 0x3f) | 0x80;
1354      ch >>= 6;
1355    }
1356  out[0] = ch | first;
1357
1358  return TRUE;
1359}
1360#endif /* DBUS_BUILD_TESTS */
1361
1362static void
1363delete (DBusRealString *real,
1364        int             start,
1365        int             len)
1366{
1367  if (len == 0)
1368    return;
1369
1370  memmove (real->str + start, real->str + start + len, real->len - (start + len));
1371  real->len -= len;
1372  real->str[real->len] = '\0';
1373}
1374
1375/**
1376 * Deletes a segment of a DBusString with length len starting at
1377 * start. (Hint: to clear an entire string, setting length to 0
1378 * with _dbus_string_set_length() is easier.)
1379 *
1380 * @param str the DBusString
1381 * @param start where to start deleting
1382 * @param len the number of bytes to delete
1383 */
1384void
1385_dbus_string_delete (DBusString       *str,
1386                     int               start,
1387                     int               len)
1388{
1389  DBUS_STRING_PREAMBLE (str);
1390  _dbus_assert (start >= 0);
1391  _dbus_assert (len >= 0);
1392  _dbus_assert (start <= real->len);
1393  _dbus_assert (len <= real->len - start);
1394
1395  delete (real, start, len);
1396}
1397
1398static dbus_bool_t
1399copy (DBusRealString *source,
1400      int             start,
1401      int             len,
1402      DBusRealString *dest,
1403      int             insert_at)
1404{
1405  if (len == 0)
1406    return TRUE;
1407
1408  if (!open_gap (len, dest, insert_at))
1409    return FALSE;
1410
1411  memmove (dest->str + insert_at,
1412           source->str + start,
1413           len);
1414
1415  return TRUE;
1416}
1417
1418/**
1419 * Checks assertions for two strings we're copying a segment between,
1420 * and declares real_source/real_dest variables.
1421 *
1422 * @param source the source string
1423 * @param start the starting offset
1424 * @param dest the dest string
1425 * @param insert_at where the copied segment is inserted
1426 */
1427#define DBUS_STRING_COPY_PREAMBLE(source, start, dest, insert_at)       \
1428  DBusRealString *real_source = (DBusRealString*) source;               \
1429  DBusRealString *real_dest = (DBusRealString*) dest;                   \
1430  _dbus_assert ((source) != (dest));                                    \
1431  DBUS_GENERIC_STRING_PREAMBLE (real_source);                           \
1432  DBUS_GENERIC_STRING_PREAMBLE (real_dest);                             \
1433  _dbus_assert (!real_dest->constant);                                  \
1434  _dbus_assert (!real_dest->locked);                                    \
1435  _dbus_assert ((start) >= 0);                                          \
1436  _dbus_assert ((start) <= real_source->len);                           \
1437  _dbus_assert ((insert_at) >= 0);                                      \
1438  _dbus_assert ((insert_at) <= real_dest->len)
1439
1440/**
1441 * Moves the end of one string into another string. Both strings
1442 * must be initialized, valid strings.
1443 *
1444 * @param source the source string
1445 * @param start where to chop off the source string
1446 * @param dest the destination string
1447 * @param insert_at where to move the chopped-off part of source string
1448 * @returns #FALSE if not enough memory
1449 */
1450dbus_bool_t
1451_dbus_string_move (DBusString       *source,
1452                   int               start,
1453                   DBusString       *dest,
1454                   int               insert_at)
1455{
1456  DBusRealString *real_source = (DBusRealString*) source;
1457  _dbus_assert (start <= real_source->len);
1458
1459  return _dbus_string_move_len (source, start,
1460                                real_source->len - start,
1461                                dest, insert_at);
1462}
1463
1464/**
1465 * Like _dbus_string_move(), but does not delete the section
1466 * of the source string that's copied to the dest string.
1467 *
1468 * @param source the source string
1469 * @param start where to start copying the source string
1470 * @param dest the destination string
1471 * @param insert_at where to place the copied part of source string
1472 * @returns #FALSE if not enough memory
1473 */
1474dbus_bool_t
1475_dbus_string_copy (const DBusString *source,
1476                   int               start,
1477                   DBusString       *dest,
1478                   int               insert_at)
1479{
1480  DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
1481
1482  return copy (real_source, start,
1483               real_source->len - start,
1484               real_dest,
1485               insert_at);
1486}
1487
1488/**
1489 * Like _dbus_string_move(), but can move a segment from
1490 * the middle of the source string.
1491 *
1492 * @todo this doesn't do anything with max_length field.
1493 * we should probably just kill the max_length field though.
1494 *
1495 * @param source the source string
1496 * @param start first byte of source string to move
1497 * @param len length of segment to move
1498 * @param dest the destination string
1499 * @param insert_at where to move the bytes from the source string
1500 * @returns #FALSE if not enough memory
1501 */
1502dbus_bool_t
1503_dbus_string_move_len (DBusString       *source,
1504                       int               start,
1505                       int               len,
1506                       DBusString       *dest,
1507                       int               insert_at)
1508
1509{
1510  DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
1511  _dbus_assert (len >= 0);
1512  _dbus_assert ((start + len) <= real_source->len);
1513
1514
1515  if (len == 0)
1516    {
1517      return TRUE;
1518    }
1519  else if (start == 0 &&
1520           len == real_source->len &&
1521           real_dest->len == 0)
1522    {
1523      /* Short-circuit moving an entire existing string to an empty string
1524       * by just swapping the buffers.
1525       */
1526      /* we assume ->constant doesn't matter as you can't have
1527       * a constant string involved in a move.
1528       */
1529#define ASSIGN_DATA(a, b) do {                  \
1530        (a)->str = (b)->str;                    \
1531        (a)->len = (b)->len;                    \
1532        (a)->allocated = (b)->allocated;        \
1533        (a)->align_offset = (b)->align_offset;  \
1534      } while (0)
1535
1536      DBusRealString tmp;
1537
1538      ASSIGN_DATA (&tmp, real_source);
1539      ASSIGN_DATA (real_source, real_dest);
1540      ASSIGN_DATA (real_dest, &tmp);
1541
1542      return TRUE;
1543    }
1544  else
1545    {
1546      if (!copy (real_source, start, len,
1547                 real_dest,
1548                 insert_at))
1549        return FALSE;
1550
1551      delete (real_source, start,
1552              len);
1553
1554      return TRUE;
1555    }
1556}
1557
1558/**
1559 * Like _dbus_string_copy(), but can copy a segment from the middle of
1560 * the source string.
1561 *
1562 * @param source the source string
1563 * @param start where to start copying the source string
1564 * @param len length of segment to copy
1565 * @param dest the destination string
1566 * @param insert_at where to place the copied segment of source string
1567 * @returns #FALSE if not enough memory
1568 */
1569dbus_bool_t
1570_dbus_string_copy_len (const DBusString *source,
1571                       int               start,
1572                       int               len,
1573                       DBusString       *dest,
1574                       int               insert_at)
1575{
1576  DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
1577  _dbus_assert (len >= 0);
1578  _dbus_assert (start <= real_source->len);
1579  _dbus_assert (len <= real_source->len - start);
1580
1581  return copy (real_source, start, len,
1582               real_dest,
1583               insert_at);
1584}
1585
1586/**
1587 * Replaces a segment of dest string with a segment of source string.
1588 *
1589 * @todo optimize the case where the two lengths are the same, and
1590 * avoid memmoving the data in the trailing part of the string twice.
1591 *
1592 * @todo avoid inserting the source into dest, then deleting
1593 * the replaced chunk of dest (which creates a potentially large
1594 * intermediate string). Instead, extend the replaced chunk
1595 * of dest with padding to the same size as the source chunk,
1596 * then copy in the source bytes.
1597 *
1598 * @param source the source string
1599 * @param start where to start copying the source string
1600 * @param len length of segment to copy
1601 * @param dest the destination string
1602 * @param replace_at start of segment of dest string to replace
1603 * @param replace_len length of segment of dest string to replace
1604 * @returns #FALSE if not enough memory
1605 *
1606 */
1607dbus_bool_t
1608_dbus_string_replace_len (const DBusString *source,
1609                          int               start,
1610                          int               len,
1611                          DBusString       *dest,
1612                          int               replace_at,
1613                          int               replace_len)
1614{
1615  DBUS_STRING_COPY_PREAMBLE (source, start, dest, replace_at);
1616  _dbus_assert (len >= 0);
1617  _dbus_assert (start <= real_source->len);
1618  _dbus_assert (len <= real_source->len - start);
1619  _dbus_assert (replace_at >= 0);
1620  _dbus_assert (replace_at <= real_dest->len);
1621  _dbus_assert (replace_len <= real_dest->len - replace_at);
1622
1623  if (!copy (real_source, start, len,
1624             real_dest, replace_at))
1625    return FALSE;
1626
1627  delete (real_dest, replace_at + len, replace_len);
1628
1629  return TRUE;
1630}
1631
1632/* Unicode macros and utf8_validate() from GLib Owen Taylor, Havoc
1633 * Pennington, and Tom Tromey are the authors and authorized relicense.
1634 */
1635
1636/** computes length and mask of a unicode character
1637 * @param Char the char
1638 * @param Mask the mask variable to assign to
1639 * @param Len the length variable to assign to
1640 */
1641#define UTF8_COMPUTE(Char, Mask, Len)					      \
1642  if (Char < 128)							      \
1643    {									      \
1644      Len = 1;								      \
1645      Mask = 0x7f;							      \
1646    }									      \
1647  else if ((Char & 0xe0) == 0xc0)					      \
1648    {									      \
1649      Len = 2;								      \
1650      Mask = 0x1f;							      \
1651    }									      \
1652  else if ((Char & 0xf0) == 0xe0)					      \
1653    {									      \
1654      Len = 3;								      \
1655      Mask = 0x0f;							      \
1656    }									      \
1657  else if ((Char & 0xf8) == 0xf0)					      \
1658    {									      \
1659      Len = 4;								      \
1660      Mask = 0x07;							      \
1661    }									      \
1662  else if ((Char & 0xfc) == 0xf8)					      \
1663    {									      \
1664      Len = 5;								      \
1665      Mask = 0x03;							      \
1666    }									      \
1667  else if ((Char & 0xfe) == 0xfc)					      \
1668    {									      \
1669      Len = 6;								      \
1670      Mask = 0x01;							      \
1671    }									      \
1672  else                                                                        \
1673    {                                                                         \
1674      Len = 0;                                                               \
1675      Mask = 0;                                                               \
1676    }
1677
1678/**
1679 * computes length of a unicode character in UTF-8
1680 * @param Char the char
1681 */
1682#define UTF8_LENGTH(Char)              \
1683  ((Char) < 0x80 ? 1 :                 \
1684   ((Char) < 0x800 ? 2 :               \
1685    ((Char) < 0x10000 ? 3 :            \
1686     ((Char) < 0x200000 ? 4 :          \
1687      ((Char) < 0x4000000 ? 5 : 6)))))
1688
1689/**
1690 * Gets a UTF-8 value.
1691 *
1692 * @param Result variable for extracted unicode char.
1693 * @param Chars the bytes to decode
1694 * @param Count counter variable
1695 * @param Mask mask for this char
1696 * @param Len length for this char in bytes
1697 */
1698#define UTF8_GET(Result, Chars, Count, Mask, Len)			      \
1699  (Result) = (Chars)[0] & (Mask);					      \
1700  for ((Count) = 1; (Count) < (Len); ++(Count))				      \
1701    {									      \
1702      if (((Chars)[(Count)] & 0xc0) != 0x80)				      \
1703	{								      \
1704	  (Result) = -1;						      \
1705	  break;							      \
1706	}								      \
1707      (Result) <<= 6;							      \
1708      (Result) |= ((Chars)[(Count)] & 0x3f);				      \
1709    }
1710
1711/**
1712 * Check whether a unicode char is in a valid range.
1713 *
1714 * @param Char the character
1715 */
1716#define UNICODE_VALID(Char)                   \
1717    ((Char) < 0x110000 &&                     \
1718     (((Char) & 0xFFFFF800) != 0xD800) &&     \
1719     ((Char) < 0xFDD0 || (Char) > 0xFDEF) &&  \
1720     ((Char) & 0xFFFF) != 0xFFFF)
1721
1722#ifdef DBUS_BUILD_TESTS
1723/**
1724 * Gets a unicode character from a UTF-8 string. Does no validation;
1725 * you must verify that the string is valid UTF-8 in advance and must
1726 * pass in the start of a character.
1727 *
1728 * @param str the string
1729 * @param start the start of the UTF-8 character.
1730 * @param ch_return location to return the character
1731 * @param end_return location to return the byte index of next character
1732 */
1733void
1734_dbus_string_get_unichar (const DBusString *str,
1735                          int               start,
1736                          dbus_unichar_t   *ch_return,
1737                          int              *end_return)
1738{
1739  int i, mask, len;
1740  dbus_unichar_t result;
1741  unsigned char c;
1742  unsigned char *p;
1743  DBUS_CONST_STRING_PREAMBLE (str);
1744  _dbus_assert (start >= 0);
1745  _dbus_assert (start <= real->len);
1746
1747  if (ch_return)
1748    *ch_return = 0;
1749  if (end_return)
1750    *end_return = real->len;
1751
1752  mask = 0;
1753  p = real->str + start;
1754  c = *p;
1755
1756  UTF8_COMPUTE (c, mask, len);
1757  if (len == 0)
1758    return;
1759  UTF8_GET (result, p, i, mask, len);
1760
1761  if (result == (dbus_unichar_t)-1)
1762    return;
1763
1764  if (ch_return)
1765    *ch_return = result;
1766  if (end_return)
1767    *end_return = start + len;
1768}
1769#endif /* DBUS_BUILD_TESTS */
1770
1771/**
1772 * Finds the given substring in the string,
1773 * returning #TRUE and filling in the byte index
1774 * where the substring was found, if it was found.
1775 * Returns #FALSE if the substring wasn't found.
1776 * Sets *start to the length of the string if the substring
1777 * is not found.
1778 *
1779 * @param str the string
1780 * @param start where to start looking
1781 * @param substr the substring
1782 * @param found return location for where it was found, or #NULL
1783 * @returns #TRUE if found
1784 */
1785dbus_bool_t
1786_dbus_string_find (const DBusString *str,
1787                   int               start,
1788                   const char       *substr,
1789                   int              *found)
1790{
1791  return _dbus_string_find_to (str, start,
1792                               ((const DBusRealString*)str)->len,
1793                               substr, found);
1794}
1795
1796/**
1797 * Finds the given substring in the string,
1798 * up to a certain position,
1799 * returning #TRUE and filling in the byte index
1800 * where the substring was found, if it was found.
1801 * Returns #FALSE if the substring wasn't found.
1802 * Sets *start to the length of the string if the substring
1803 * is not found.
1804 *
1805 * @param str the string
1806 * @param start where to start looking
1807 * @param end where to stop looking
1808 * @param substr the substring
1809 * @param found return location for where it was found, or #NULL
1810 * @returns #TRUE if found
1811 */
1812dbus_bool_t
1813_dbus_string_find_to (const DBusString *str,
1814		      int               start,
1815		      int               end,
1816		      const char       *substr,
1817		      int              *found)
1818{
1819  int i;
1820  DBUS_CONST_STRING_PREAMBLE (str);
1821  _dbus_assert (substr != NULL);
1822  _dbus_assert (start <= real->len);
1823  _dbus_assert (start >= 0);
1824  _dbus_assert (substr != NULL);
1825  _dbus_assert (end <= real->len);
1826  _dbus_assert (start <= end);
1827
1828  /* we always "find" an empty string */
1829  if (*substr == '\0')
1830    {
1831      if (found)
1832        *found = start;
1833      return TRUE;
1834    }
1835
1836  i = start;
1837  while (i < end)
1838    {
1839      if (real->str[i] == substr[0])
1840        {
1841          int j = i + 1;
1842
1843          while (j < end)
1844            {
1845              if (substr[j - i] == '\0')
1846                break;
1847              else if (real->str[j] != substr[j - i])
1848                break;
1849
1850              ++j;
1851            }
1852
1853          if (substr[j - i] == '\0')
1854            {
1855              if (found)
1856                *found = i;
1857              return TRUE;
1858            }
1859        }
1860
1861      ++i;
1862    }
1863
1864  if (found)
1865    *found = end;
1866
1867  return FALSE;
1868}
1869
1870/**
1871 * Finds a blank (space or tab) in the string. Returns #TRUE
1872 * if found, #FALSE otherwise. If a blank is not found sets
1873 * *found to the length of the string.
1874 *
1875 * @param str the string
1876 * @param start byte index to start looking
1877 * @param found place to store the location of the first blank
1878 * @returns #TRUE if a blank was found
1879 */
1880dbus_bool_t
1881_dbus_string_find_blank (const DBusString *str,
1882                         int               start,
1883                         int              *found)
1884{
1885  int i;
1886  DBUS_CONST_STRING_PREAMBLE (str);
1887  _dbus_assert (start <= real->len);
1888  _dbus_assert (start >= 0);
1889
1890  i = start;
1891  while (i < real->len)
1892    {
1893      if (real->str[i] == ' ' ||
1894          real->str[i] == '\t')
1895        {
1896          if (found)
1897            *found = i;
1898          return TRUE;
1899        }
1900
1901      ++i;
1902    }
1903
1904  if (found)
1905    *found = real->len;
1906
1907  return FALSE;
1908}
1909
1910/**
1911 * Skips blanks from start, storing the first non-blank in *end
1912 * (blank is space or tab).
1913 *
1914 * @param str the string
1915 * @param start where to start
1916 * @param end where to store the first non-blank byte index
1917 */
1918void
1919_dbus_string_skip_blank (const DBusString *str,
1920                         int               start,
1921                         int              *end)
1922{
1923  int i;
1924  DBUS_CONST_STRING_PREAMBLE (str);
1925  _dbus_assert (start <= real->len);
1926  _dbus_assert (start >= 0);
1927
1928  i = start;
1929  while (i < real->len)
1930    {
1931      if (!DBUS_IS_ASCII_BLANK (real->str[i]))
1932        break;
1933
1934      ++i;
1935    }
1936
1937  _dbus_assert (i == real->len || !DBUS_IS_ASCII_WHITE (real->str[i]));
1938
1939  if (end)
1940    *end = i;
1941}
1942
1943
1944/**
1945 * Skips whitespace from start, storing the first non-whitespace in *end.
1946 * (whitespace is space, tab, newline, CR).
1947 *
1948 * @param str the string
1949 * @param start where to start
1950 * @param end where to store the first non-whitespace byte index
1951 */
1952void
1953_dbus_string_skip_white (const DBusString *str,
1954                         int               start,
1955                         int              *end)
1956{
1957  int i;
1958  DBUS_CONST_STRING_PREAMBLE (str);
1959  _dbus_assert (start <= real->len);
1960  _dbus_assert (start >= 0);
1961
1962  i = start;
1963  while (i < real->len)
1964    {
1965      if (!DBUS_IS_ASCII_WHITE (real->str[i]))
1966        break;
1967
1968      ++i;
1969    }
1970
1971  _dbus_assert (i == real->len || !(DBUS_IS_ASCII_WHITE (real->str[i])));
1972
1973  if (end)
1974    *end = i;
1975}
1976
1977/**
1978 * Skips whitespace from end, storing the start index of the trailing
1979 * whitespace in *start. (whitespace is space, tab, newline, CR).
1980 *
1981 * @param str the string
1982 * @param end where to start scanning backward
1983 * @param start where to store the start of whitespace chars
1984 */
1985void
1986_dbus_string_skip_white_reverse (const DBusString *str,
1987                                 int               end,
1988                                 int              *start)
1989{
1990  int i;
1991  DBUS_CONST_STRING_PREAMBLE (str);
1992  _dbus_assert (end <= real->len);
1993  _dbus_assert (end >= 0);
1994
1995  i = end;
1996  while (i > 0)
1997    {
1998      if (!DBUS_IS_ASCII_WHITE (real->str[i-1]))
1999        break;
2000      --i;
2001    }
2002
2003  _dbus_assert (i >= 0 && (i == 0 || !(DBUS_IS_ASCII_WHITE (real->str[i-1]))));
2004
2005  if (start)
2006    *start = i;
2007}
2008
2009/**
2010 * Assigns a newline-terminated or \\r\\n-terminated line from the front
2011 * of the string to the given dest string. The dest string's previous
2012 * contents are deleted. If the source string contains no newline,
2013 * moves the entire source string to the dest string.
2014 *
2015 * @todo owen correctly notes that this is a stupid function (it was
2016 * written purely for test code,
2017 * e.g. dbus-message-builder.c). Probably should be enforced as test
2018 * code only with ifdef DBUS_BUILD_TESTS
2019 *
2020 * @param source the source string
2021 * @param dest the destination string (contents are replaced)
2022 * @returns #FALSE if no memory, or source has length 0
2023 */
2024dbus_bool_t
2025_dbus_string_pop_line (DBusString *source,
2026                       DBusString *dest)
2027{
2028  int eol;
2029  dbus_bool_t have_newline;
2030
2031  _dbus_string_set_length (dest, 0);
2032
2033  eol = 0;
2034  if (_dbus_string_find (source, 0, "\n", &eol))
2035    {
2036      have_newline = TRUE;
2037      eol += 1; /* include newline */
2038    }
2039  else
2040    {
2041      eol = _dbus_string_get_length (source);
2042      have_newline = FALSE;
2043    }
2044
2045  if (eol == 0)
2046    return FALSE; /* eof */
2047
2048  if (!_dbus_string_move_len (source, 0, eol,
2049                              dest, 0))
2050    {
2051      return FALSE;
2052    }
2053
2054  /* dump the newline and the \r if we have one */
2055  if (have_newline)
2056    {
2057      dbus_bool_t have_cr;
2058
2059      _dbus_assert (_dbus_string_get_length (dest) > 0);
2060
2061      if (_dbus_string_get_length (dest) > 1 &&
2062          _dbus_string_get_byte (dest,
2063                                 _dbus_string_get_length (dest) - 2) == '\r')
2064        have_cr = TRUE;
2065      else
2066        have_cr = FALSE;
2067
2068      _dbus_string_set_length (dest,
2069                               _dbus_string_get_length (dest) -
2070                               (have_cr ? 2 : 1));
2071    }
2072
2073  return TRUE;
2074}
2075
2076#ifdef DBUS_BUILD_TESTS
2077/**
2078 * Deletes up to and including the first blank space
2079 * in the string.
2080 *
2081 * @param str the string
2082 */
2083void
2084_dbus_string_delete_first_word (DBusString *str)
2085{
2086  int i;
2087
2088  if (_dbus_string_find_blank (str, 0, &i))
2089    _dbus_string_skip_blank (str, i, &i);
2090
2091  _dbus_string_delete (str, 0, i);
2092}
2093#endif
2094
2095#ifdef DBUS_BUILD_TESTS
2096/**
2097 * Deletes any leading blanks in the string
2098 *
2099 * @param str the string
2100 */
2101void
2102_dbus_string_delete_leading_blanks (DBusString *str)
2103{
2104  int i;
2105
2106  _dbus_string_skip_blank (str, 0, &i);
2107
2108  if (i > 0)
2109    _dbus_string_delete (str, 0, i);
2110}
2111#endif
2112
2113/**
2114 * Deletes leading and trailing whitespace
2115 *
2116 * @param str the string
2117 */
2118void
2119_dbus_string_chop_white(DBusString *str)
2120{
2121  int i;
2122
2123  _dbus_string_skip_white (str, 0, &i);
2124
2125  if (i > 0)
2126    _dbus_string_delete (str, 0, i);
2127
2128  _dbus_string_skip_white_reverse (str, _dbus_string_get_length (str), &i);
2129
2130  _dbus_string_set_length (str, i);
2131}
2132
2133/**
2134 * Tests two DBusString for equality.
2135 *
2136 * @todo memcmp is probably faster
2137 *
2138 * @param a first string
2139 * @param b second string
2140 * @returns #TRUE if equal
2141 */
2142dbus_bool_t
2143_dbus_string_equal (const DBusString *a,
2144                    const DBusString *b)
2145{
2146  const unsigned char *ap;
2147  const unsigned char *bp;
2148  const unsigned char *a_end;
2149  const DBusRealString *real_a = (const DBusRealString*) a;
2150  const DBusRealString *real_b = (const DBusRealString*) b;
2151  DBUS_GENERIC_STRING_PREAMBLE (real_a);
2152  DBUS_GENERIC_STRING_PREAMBLE (real_b);
2153
2154  if (real_a->len != real_b->len)
2155    return FALSE;
2156
2157  ap = real_a->str;
2158  bp = real_b->str;
2159  a_end = real_a->str + real_a->len;
2160  while (ap != a_end)
2161    {
2162      if (*ap != *bp)
2163        return FALSE;
2164
2165      ++ap;
2166      ++bp;
2167    }
2168
2169  return TRUE;
2170}
2171
2172#ifdef DBUS_BUILD_TESTS
2173/**
2174 * Tests two DBusString for equality up to the given length.
2175 * The strings may be shorter than the given length.
2176 *
2177 * @todo write a unit test
2178 *
2179 * @todo memcmp is probably faster
2180 *
2181 * @param a first string
2182 * @param b second string
2183 * @param len the maximum length to look at
2184 * @returns #TRUE if equal for the given number of bytes
2185 */
2186dbus_bool_t
2187_dbus_string_equal_len (const DBusString *a,
2188                        const DBusString *b,
2189                        int               len)
2190{
2191  const unsigned char *ap;
2192  const unsigned char *bp;
2193  const unsigned char *a_end;
2194  const DBusRealString *real_a = (const DBusRealString*) a;
2195  const DBusRealString *real_b = (const DBusRealString*) b;
2196  DBUS_GENERIC_STRING_PREAMBLE (real_a);
2197  DBUS_GENERIC_STRING_PREAMBLE (real_b);
2198
2199  if (real_a->len != real_b->len &&
2200      (real_a->len < len || real_b->len < len))
2201    return FALSE;
2202
2203  ap = real_a->str;
2204  bp = real_b->str;
2205  a_end = real_a->str + MIN (real_a->len, len);
2206  while (ap != a_end)
2207    {
2208      if (*ap != *bp)
2209        return FALSE;
2210
2211      ++ap;
2212      ++bp;
2213    }
2214
2215  return TRUE;
2216}
2217#endif /* DBUS_BUILD_TESTS */
2218
2219/**
2220 * Tests two sub-parts of two DBusString for equality.  The specified
2221 * range of the first string must exist; the specified start position
2222 * of the second string must exist.
2223 *
2224 * @todo write a unit test
2225 *
2226 * @todo memcmp is probably faster
2227 *
2228 * @param a first string
2229 * @param a_start where to start substring in first string
2230 * @param a_len length of substring in first string
2231 * @param b second string
2232 * @param b_start where to start substring in second string
2233 * @returns #TRUE if the two substrings are equal
2234 */
2235dbus_bool_t
2236_dbus_string_equal_substring (const DBusString  *a,
2237                              int                a_start,
2238                              int                a_len,
2239                              const DBusString  *b,
2240                              int                b_start)
2241{
2242  const unsigned char *ap;
2243  const unsigned char *bp;
2244  const unsigned char *a_end;
2245  const DBusRealString *real_a = (const DBusRealString*) a;
2246  const DBusRealString *real_b = (const DBusRealString*) b;
2247  DBUS_GENERIC_STRING_PREAMBLE (real_a);
2248  DBUS_GENERIC_STRING_PREAMBLE (real_b);
2249  _dbus_assert (a_start >= 0);
2250  _dbus_assert (a_len >= 0);
2251  _dbus_assert (a_start <= real_a->len);
2252  _dbus_assert (a_len <= real_a->len - a_start);
2253  _dbus_assert (b_start >= 0);
2254  _dbus_assert (b_start <= real_b->len);
2255
2256  if (a_len > real_b->len - b_start)
2257    return FALSE;
2258
2259  ap = real_a->str + a_start;
2260  bp = real_b->str + b_start;
2261  a_end = ap + a_len;
2262  while (ap != a_end)
2263    {
2264      if (*ap != *bp)
2265        return FALSE;
2266
2267      ++ap;
2268      ++bp;
2269    }
2270
2271  _dbus_assert (bp <= (real_b->str + real_b->len));
2272
2273  return TRUE;
2274}
2275
2276/**
2277 * Checks whether a string is equal to a C string.
2278 *
2279 * @param a the string
2280 * @param c_str the C string
2281 * @returns #TRUE if equal
2282 */
2283dbus_bool_t
2284_dbus_string_equal_c_str (const DBusString *a,
2285                          const char       *c_str)
2286{
2287  const unsigned char *ap;
2288  const unsigned char *bp;
2289  const unsigned char *a_end;
2290  const DBusRealString *real_a = (const DBusRealString*) a;
2291  DBUS_GENERIC_STRING_PREAMBLE (real_a);
2292  _dbus_assert (c_str != NULL);
2293
2294  ap = real_a->str;
2295  bp = (const unsigned char*) c_str;
2296  a_end = real_a->str + real_a->len;
2297  while (ap != a_end && *bp)
2298    {
2299      if (*ap != *bp)
2300        return FALSE;
2301
2302      ++ap;
2303      ++bp;
2304    }
2305
2306  if (ap != a_end || *bp)
2307    return FALSE;
2308
2309  return TRUE;
2310}
2311
2312#ifdef DBUS_BUILD_TESTS
2313/**
2314 * Checks whether a string starts with the given C string.
2315 *
2316 * @param a the string
2317 * @param c_str the C string
2318 * @returns #TRUE if string starts with it
2319 */
2320dbus_bool_t
2321_dbus_string_starts_with_c_str (const DBusString *a,
2322                                const char       *c_str)
2323{
2324  const unsigned char *ap;
2325  const unsigned char *bp;
2326  const unsigned char *a_end;
2327  const DBusRealString *real_a = (const DBusRealString*) a;
2328  DBUS_GENERIC_STRING_PREAMBLE (real_a);
2329  _dbus_assert (c_str != NULL);
2330
2331  ap = real_a->str;
2332  bp = (const unsigned char*) c_str;
2333  a_end = real_a->str + real_a->len;
2334  while (ap != a_end && *bp)
2335    {
2336      if (*ap != *bp)
2337        return FALSE;
2338
2339      ++ap;
2340      ++bp;
2341    }
2342
2343  if (*bp == '\0')
2344    return TRUE;
2345  else
2346    return FALSE;
2347}
2348#endif /* DBUS_BUILD_TESTS */
2349
2350/**
2351 * Appends a two-character hex digit to a string, where the hex digit
2352 * has the value of the given byte.
2353 *
2354 * @param str the string
2355 * @param byte the byte
2356 * @returns #FALSE if no memory
2357 */
2358dbus_bool_t
2359_dbus_string_append_byte_as_hex (DBusString *str,
2360                                 int         byte)
2361{
2362  const char hexdigits[16] = {
2363    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
2364    'a', 'b', 'c', 'd', 'e', 'f'
2365  };
2366
2367  if (!_dbus_string_append_byte (str,
2368                                 hexdigits[(byte >> 4)]))
2369    return FALSE;
2370
2371  if (!_dbus_string_append_byte (str,
2372                                 hexdigits[(byte & 0x0f)]))
2373    {
2374      _dbus_string_set_length (str,
2375                               _dbus_string_get_length (str) - 1);
2376      return FALSE;
2377    }
2378
2379  return TRUE;
2380}
2381
2382/**
2383 * Encodes a string in hex, the way MD5 and SHA-1 are usually
2384 * encoded. (Each byte is two hex digits.)
2385 *
2386 * @param source the string to encode
2387 * @param start byte index to start encoding
2388 * @param dest string where encoded data should be placed
2389 * @param insert_at where to place encoded data
2390 * @returns #TRUE if encoding was successful, #FALSE if no memory etc.
2391 */
2392dbus_bool_t
2393_dbus_string_hex_encode (const DBusString *source,
2394                         int               start,
2395                         DBusString       *dest,
2396                         int               insert_at)
2397{
2398  DBusString result;
2399  const unsigned char *p;
2400  const unsigned char *end;
2401  dbus_bool_t retval;
2402
2403  _dbus_assert (start <= _dbus_string_get_length (source));
2404
2405  if (!_dbus_string_init (&result))
2406    return FALSE;
2407
2408  retval = FALSE;
2409
2410  p = (const unsigned char*) _dbus_string_get_const_data (source);
2411  end = p + _dbus_string_get_length (source);
2412  p += start;
2413
2414  while (p != end)
2415    {
2416      if (!_dbus_string_append_byte_as_hex (&result, *p))
2417        goto out;
2418
2419      ++p;
2420    }
2421
2422  if (!_dbus_string_move (&result, 0, dest, insert_at))
2423    goto out;
2424
2425  retval = TRUE;
2426
2427 out:
2428  _dbus_string_free (&result);
2429  return retval;
2430}
2431
2432/**
2433 * Decodes a string from hex encoding.
2434 *
2435 * @param source the string to decode
2436 * @param start byte index to start decode
2437 * @param end_return return location of the end of the hex data, or #NULL
2438 * @param dest string where decoded data should be placed
2439 * @param insert_at where to place decoded data
2440 * @returns #TRUE if decoding was successful, #FALSE if no memory.
2441 */
2442dbus_bool_t
2443_dbus_string_hex_decode (const DBusString *source,
2444                         int               start,
2445			 int              *end_return,
2446                         DBusString       *dest,
2447                         int               insert_at)
2448{
2449  DBusString result;
2450  const unsigned char *p;
2451  const unsigned char *end;
2452  dbus_bool_t retval;
2453  dbus_bool_t high_bits;
2454
2455  _dbus_assert (start <= _dbus_string_get_length (source));
2456
2457  if (!_dbus_string_init (&result))
2458    return FALSE;
2459
2460  retval = FALSE;
2461
2462  high_bits = TRUE;
2463  p = (const unsigned char*) _dbus_string_get_const_data (source);
2464  end = p + _dbus_string_get_length (source);
2465  p += start;
2466
2467  while (p != end)
2468    {
2469      unsigned int val;
2470
2471      switch (*p)
2472        {
2473        case '0':
2474          val = 0;
2475          break;
2476        case '1':
2477          val = 1;
2478          break;
2479        case '2':
2480          val = 2;
2481          break;
2482        case '3':
2483          val = 3;
2484          break;
2485        case '4':
2486          val = 4;
2487          break;
2488        case '5':
2489          val = 5;
2490          break;
2491        case '6':
2492          val = 6;
2493          break;
2494        case '7':
2495          val = 7;
2496          break;
2497        case '8':
2498          val = 8;
2499          break;
2500        case '9':
2501          val = 9;
2502          break;
2503        case 'a':
2504        case 'A':
2505          val = 10;
2506          break;
2507        case 'b':
2508        case 'B':
2509          val = 11;
2510          break;
2511        case 'c':
2512        case 'C':
2513          val = 12;
2514          break;
2515        case 'd':
2516        case 'D':
2517          val = 13;
2518          break;
2519        case 'e':
2520        case 'E':
2521          val = 14;
2522          break;
2523        case 'f':
2524        case 'F':
2525          val = 15;
2526          break;
2527        default:
2528          goto done;
2529        }
2530
2531      if (high_bits)
2532        {
2533          if (!_dbus_string_append_byte (&result,
2534                                         val << 4))
2535	    goto out;
2536        }
2537      else
2538        {
2539          int len;
2540          unsigned char b;
2541
2542          len = _dbus_string_get_length (&result);
2543
2544          b = _dbus_string_get_byte (&result, len - 1);
2545
2546          b |= val;
2547
2548          _dbus_string_set_byte (&result, len - 1, b);
2549        }
2550
2551      high_bits = !high_bits;
2552
2553      ++p;
2554    }
2555
2556 done:
2557  if (!_dbus_string_move (&result, 0, dest, insert_at))
2558    goto out;
2559
2560  if (end_return)
2561    *end_return = p - (const unsigned char*) _dbus_string_get_const_data (source);
2562
2563  retval = TRUE;
2564
2565 out:
2566  _dbus_string_free (&result);
2567  return retval;
2568}
2569
2570/**
2571 * Checks that the given range of the string is valid ASCII with no
2572 * nul bytes. If the given range is not entirely contained in the
2573 * string, returns #FALSE.
2574 *
2575 * @todo this is inconsistent with most of DBusString in that
2576 * it allows a start,len range that extends past the string end.
2577 *
2578 * @param str the string
2579 * @param start first byte index to check
2580 * @param len number of bytes to check
2581 * @returns #TRUE if the byte range exists and is all valid ASCII
2582 */
2583dbus_bool_t
2584_dbus_string_validate_ascii (const DBusString *str,
2585                             int               start,
2586                             int               len)
2587{
2588  const unsigned char *s;
2589  const unsigned char *end;
2590  DBUS_CONST_STRING_PREAMBLE (str);
2591  _dbus_assert (start >= 0);
2592  _dbus_assert (start <= real->len);
2593  _dbus_assert (len >= 0);
2594
2595  if (len > real->len - start)
2596    return FALSE;
2597
2598  s = real->str + start;
2599  end = s + len;
2600  while (s != end)
2601    {
2602      if (_DBUS_UNLIKELY (!_DBUS_ISASCII (*s)))
2603        return FALSE;
2604
2605      ++s;
2606    }
2607
2608  return TRUE;
2609}
2610
2611/**
2612 * Checks that the given range of the string is valid UTF-8. If the
2613 * given range is not entirely contained in the string, returns
2614 * #FALSE. If the string contains any nul bytes in the given range,
2615 * returns #FALSE. If the start and start+len are not on character
2616 * boundaries, returns #FALSE.
2617 *
2618 * @todo this is inconsistent with most of DBusString in that
2619 * it allows a start,len range that extends past the string end.
2620 *
2621 * @param str the string
2622 * @param start first byte index to check
2623 * @param len number of bytes to check
2624 * @returns #TRUE if the byte range exists and is all valid UTF-8
2625 */
2626dbus_bool_t
2627_dbus_string_validate_utf8  (const DBusString *str,
2628                             int               start,
2629                             int               len)
2630{
2631  const unsigned char *p;
2632  const unsigned char *end;
2633  DBUS_CONST_STRING_PREAMBLE (str);
2634  _dbus_assert (start >= 0);
2635  _dbus_assert (start <= real->len);
2636  _dbus_assert (len >= 0);
2637
2638  /* we are doing _DBUS_UNLIKELY() here which might be
2639   * dubious in a generic library like GLib, but in D-Bus
2640   * we know we're validating messages and that it would
2641   * only be evil/broken apps that would have invalid
2642   * UTF-8. Also, this function seems to be a performance
2643   * bottleneck in profiles.
2644   */
2645
2646  if (_DBUS_UNLIKELY (len > real->len - start))
2647    return FALSE;
2648
2649  p = real->str + start;
2650  end = p + len;
2651
2652  while (p < end)
2653    {
2654      int i, mask, char_len;
2655      dbus_unichar_t result;
2656
2657      /* nul bytes considered invalid */
2658      if (*p == '\0')
2659        break;
2660
2661      /* Special-case ASCII; this makes us go a lot faster in
2662       * D-Bus profiles where we are typically validating
2663       * function names and such. We have to know that
2664       * all following checks will pass for ASCII though,
2665       * comments follow ...
2666       */
2667      if (*p < 128)
2668        {
2669          ++p;
2670          continue;
2671        }
2672
2673      UTF8_COMPUTE (*p, mask, char_len);
2674
2675      if (_DBUS_UNLIKELY (char_len == 0))  /* ASCII: char_len == 1 */
2676        break;
2677
2678      /* check that the expected number of bytes exists in the remaining length */
2679      if (_DBUS_UNLIKELY ((end - p) < char_len)) /* ASCII: p < end and char_len == 1 */
2680        break;
2681
2682      UTF8_GET (result, p, i, mask, char_len);
2683
2684      /* Check for overlong UTF-8 */
2685      if (_DBUS_UNLIKELY (UTF8_LENGTH (result) != char_len)) /* ASCII: UTF8_LENGTH == 1 */
2686        break;
2687#if 0
2688      /* The UNICODE_VALID check below will catch this */
2689      if (_DBUS_UNLIKELY (result == (dbus_unichar_t)-1)) /* ASCII: result = ascii value */
2690        break;
2691#endif
2692
2693      if (_DBUS_UNLIKELY (!UNICODE_VALID (result))) /* ASCII: always valid */
2694        break;
2695
2696      /* UNICODE_VALID should have caught it */
2697      _dbus_assert (result != (dbus_unichar_t)-1);
2698
2699      p += char_len;
2700    }
2701
2702  /* See that we covered the entire length if a length was
2703   * passed in
2704   */
2705  if (_DBUS_UNLIKELY (p != end))
2706    return FALSE;
2707  else
2708    return TRUE;
2709}
2710
2711/**
2712 * Checks that the given range of the string is all nul bytes. If the
2713 * given range is not entirely contained in the string, returns
2714 * #FALSE.
2715 *
2716 * @todo this is inconsistent with most of DBusString in that
2717 * it allows a start,len range that extends past the string end.
2718 *
2719 * @param str the string
2720 * @param start first byte index to check
2721 * @param len number of bytes to check
2722 * @returns #TRUE if the byte range exists and is all nul bytes
2723 */
2724dbus_bool_t
2725_dbus_string_validate_nul (const DBusString *str,
2726                           int               start,
2727                           int               len)
2728{
2729  const unsigned char *s;
2730  const unsigned char *end;
2731  DBUS_CONST_STRING_PREAMBLE (str);
2732  _dbus_assert (start >= 0);
2733  _dbus_assert (len >= 0);
2734  _dbus_assert (start <= real->len);
2735
2736  if (len > real->len - start)
2737    return FALSE;
2738
2739  s = real->str + start;
2740  end = s + len;
2741  while (s != end)
2742    {
2743      if (_DBUS_UNLIKELY (*s != '\0'))
2744        return FALSE;
2745      ++s;
2746    }
2747
2748  return TRUE;
2749}
2750
2751/**
2752 * Clears all allocated bytes in the string to zero.
2753 *
2754 * @param str the string
2755 */
2756void
2757_dbus_string_zero (DBusString *str)
2758{
2759  DBUS_STRING_PREAMBLE (str);
2760
2761  memset (real->str - real->align_offset, '\0', real->allocated);
2762}
2763/** @} */
2764
2765/* tests are in dbus-string-util.c */
2766