* dbus/dbus-sysdeps.h:
[platform/upstream/dbus.git] / dbus / dbus-string.c
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 string class
40  * @ingroup  DBusInternals
41  * @brief DBusString data structure
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
76 static void
77 fixup_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
106 static void
107 undo_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  */
129 dbus_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  */
173 dbus_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  */
186 static void
187 set_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  */
207 void
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  */
227 void
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  */
260 void
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  */
286 void
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
316 static dbus_bool_t
317 reallocate_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
363 static dbus_bool_t
364 set_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
383 static dbus_bool_t
384 open_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  */
416 char*
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  */
433 const 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  */
455 char*
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  */
479 const 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  */
503 void
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  */
527 unsigned 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  */
549 dbus_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  */
579 dbus_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  */
606 dbus_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  */
651 dbus_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  */
695 dbus_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  */
719 void
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  */
745 dbus_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  */
789 int
790 _dbus_string_get_length (const DBusString  *str)
791 {
792   DBUS_CONST_STRING_PREAMBLE (str);
793   
794   return real->len;
795 }
796 #endif /* !_dbus_string_get_length */
797
798 /**
799  * Makes a string longer by the given number of bytes.  Checks whether
800  * adding additional_length to the current length would overflow an
801  * integer, and checks for exceeding a string's max length.
802  * The new bytes are not initialized, other than nul-terminating
803  * the end of the string. The uninitialized bytes may contain
804  * nul bytes or other junk.
805  *
806  * @param str a string
807  * @param additional_length length to add to the string.
808  * @returns #TRUE on success.
809  */
810 dbus_bool_t
811 _dbus_string_lengthen (DBusString *str,
812                        int         additional_length)
813 {
814   DBUS_STRING_PREAMBLE (str);  
815   _dbus_assert (additional_length >= 0);
816
817   if (_DBUS_UNLIKELY (additional_length > real->max_length - real->len))
818     return FALSE; /* would overflow */
819   
820   return set_length (real,
821                      real->len + additional_length);
822 }
823
824 /**
825  * Makes a string shorter by the given number of bytes.
826  *
827  * @param str a string
828  * @param length_to_remove length to remove from the string.
829  */
830 void
831 _dbus_string_shorten (DBusString *str,
832                       int         length_to_remove)
833 {
834   DBUS_STRING_PREAMBLE (str);
835   _dbus_assert (length_to_remove >= 0);
836   _dbus_assert (length_to_remove <= real->len);
837
838   set_length (real,
839               real->len - length_to_remove);
840 }
841
842 /**
843  * Sets the length of a string. Can be used to truncate or lengthen
844  * the string. If the string is lengthened, the function may fail and
845  * return #FALSE. Newly-added bytes are not initialized, as with
846  * _dbus_string_lengthen().
847  *
848  * @param str a string
849  * @param length new length of the string.
850  * @returns #FALSE on failure.
851  */
852 dbus_bool_t
853 _dbus_string_set_length (DBusString *str,
854                          int         length)
855 {
856   DBUS_STRING_PREAMBLE (str);
857   _dbus_assert (length >= 0);
858
859   return set_length (real, length);
860 }
861
862 static dbus_bool_t
863 align_insert_point_then_open_gap (DBusString *str,
864                                   int        *insert_at_p,
865                                   int         alignment,
866                                   int         gap_size)
867 {
868   unsigned long new_len; /* ulong to avoid _DBUS_ALIGN_VALUE overflow */
869   unsigned long gap_pos;
870   int insert_at;
871   int delta;
872   DBUS_STRING_PREAMBLE (str);
873   _dbus_assert (alignment >= 1);
874   _dbus_assert (alignment <= 8); /* it has to be a bug if > 8 */
875
876   insert_at = *insert_at_p;
877
878   _dbus_assert (insert_at <= real->len);
879   
880   gap_pos = _DBUS_ALIGN_VALUE (insert_at, alignment);
881   new_len = real->len + (gap_pos - insert_at) + gap_size;
882   
883   if (_DBUS_UNLIKELY (new_len > (unsigned long) real->max_length))
884     return FALSE;
885   
886   delta = new_len - real->len;
887   _dbus_assert (delta >= 0);
888
889   if (delta == 0) /* only happens if gap_size == 0 and insert_at is aligned already */
890     {
891       _dbus_assert (((unsigned long) *insert_at_p) == gap_pos);
892       return TRUE;
893     }
894
895   if (_DBUS_UNLIKELY (!open_gap (new_len - real->len,
896                                  real, insert_at)))
897     return FALSE;
898
899   /* nul the padding if we had to add any padding */
900   if (gap_size < delta)
901     {
902       memset (&real->str[insert_at], '\0',
903               gap_pos - insert_at);
904     }
905
906   *insert_at_p = gap_pos;
907   
908   return TRUE;
909 }
910
911 static dbus_bool_t
912 align_length_then_lengthen (DBusString *str,
913                             int         alignment,
914                             int         then_lengthen_by)
915 {
916   int insert_at;
917
918   insert_at = _dbus_string_get_length (str);
919   
920   return align_insert_point_then_open_gap (str,
921                                            &insert_at,
922                                            alignment, then_lengthen_by);
923 }
924
925 /**
926  * Align the length of a string to a specific alignment (typically 4 or 8)
927  * by appending nul bytes to the string.
928  *
929  * @param str a string
930  * @param alignment the alignment
931  * @returns #FALSE if no memory
932  */
933 dbus_bool_t
934 _dbus_string_align_length (DBusString *str,
935                            int         alignment)
936 {
937   return align_length_then_lengthen (str, alignment, 0);
938 }
939
940 /**
941  * Preallocate extra_bytes such that a future lengthening of the
942  * string by extra_bytes is guaranteed to succeed without an out of
943  * memory error.
944  *
945  * @param str a string
946  * @param extra_bytes bytes to alloc
947  * @returns #FALSE if no memory
948  */
949 dbus_bool_t
950 _dbus_string_alloc_space (DBusString        *str,
951                           int                extra_bytes)
952 {
953   if (!_dbus_string_lengthen (str, extra_bytes))
954     return FALSE;
955   _dbus_string_shorten (str, extra_bytes);
956
957   return TRUE;
958 }
959
960 static dbus_bool_t
961 append (DBusRealString *real,
962         const char     *buffer,
963         int             buffer_len)
964 {
965   if (buffer_len == 0)
966     return TRUE;
967
968   if (!_dbus_string_lengthen ((DBusString*)real, buffer_len))
969     return FALSE;
970
971   memcpy (real->str + (real->len - buffer_len),
972           buffer,
973           buffer_len);
974
975   return TRUE;
976 }
977
978 /**
979  * Appends a nul-terminated C-style string to a DBusString.
980  *
981  * @param str the DBusString
982  * @param buffer the nul-terminated characters to append
983  * @returns #FALSE if not enough memory.
984  */
985 dbus_bool_t
986 _dbus_string_append (DBusString *str,
987                      const char *buffer)
988 {
989   unsigned long buffer_len;
990   
991   DBUS_STRING_PREAMBLE (str);
992   _dbus_assert (buffer != NULL);
993   
994   buffer_len = strlen (buffer);
995   if (buffer_len > (unsigned long) real->max_length)
996     return FALSE;
997   
998   return append (real, buffer, buffer_len);
999 }
1000
1001 /** assign 2 bytes from one string to another */
1002 #define ASSIGN_2_OCTETS(p, octets) \
1003   *((dbus_uint16_t*)(p)) = *((dbus_uint16_t*)(octets));
1004
1005 /** assign 4 bytes from one string to another */
1006 #define ASSIGN_4_OCTETS(p, octets) \
1007   *((dbus_uint32_t*)(p)) = *((dbus_uint32_t*)(octets));
1008
1009 #ifdef DBUS_HAVE_INT64
1010 /** assign 8 bytes from one string to another */
1011 #define ASSIGN_8_OCTETS(p, octets) \
1012   *((dbus_uint64_t*)(p)) = *((dbus_uint64_t*)(octets));
1013 #else
1014 /** assign 8 bytes from one string to another */
1015 #define ASSIGN_8_OCTETS(p, octets)              \
1016 do {                                            \
1017   unsigned char *b;                             \
1018                                                 \
1019   b = p;                                        \
1020                                                 \
1021   *b++ = octets[0];                             \
1022   *b++ = octets[1];                             \
1023   *b++ = octets[2];                             \
1024   *b++ = octets[3];                             \
1025   *b++ = octets[4];                             \
1026   *b++ = octets[5];                             \
1027   *b++ = octets[6];                             \
1028   *b++ = octets[7];                             \
1029   _dbus_assert (b == p + 8);                    \
1030 } while (0)
1031 #endif /* DBUS_HAVE_INT64 */
1032
1033 #ifdef DBUS_BUILD_TESTS
1034 /**
1035  * Appends 4 bytes aligned on a 4 byte boundary
1036  * with any alignment padding initialized to 0.
1037  *
1038  * @param str the DBusString
1039  * @param octets 4 bytes to append
1040  * @returns #FALSE if not enough memory.
1041  */
1042 dbus_bool_t
1043 _dbus_string_append_4_aligned (DBusString         *str,
1044                                const unsigned char octets[4])
1045 {
1046   DBUS_STRING_PREAMBLE (str);
1047   
1048   if (!align_length_then_lengthen (str, 4, 4))
1049     return FALSE;
1050
1051   ASSIGN_4_OCTETS (real->str + (real->len - 4), octets);
1052
1053   return TRUE;
1054 }
1055 #endif /* DBUS_BUILD_TESTS */
1056
1057 #ifdef DBUS_BUILD_TESTS
1058 /**
1059  * Appends 8 bytes aligned on an 8 byte boundary
1060  * with any alignment padding initialized to 0.
1061  *
1062  * @param str the DBusString
1063  * @param octets 8 bytes to append
1064  * @returns #FALSE if not enough memory.
1065  */
1066 dbus_bool_t
1067 _dbus_string_append_8_aligned (DBusString         *str,
1068                                const unsigned char octets[8])
1069 {
1070   DBUS_STRING_PREAMBLE (str);
1071   
1072   if (!align_length_then_lengthen (str, 8, 8))
1073     return FALSE;
1074
1075   ASSIGN_8_OCTETS (real->str + (real->len - 8), octets);
1076
1077   return TRUE;
1078 }
1079 #endif /* DBUS_BUILD_TESTS */
1080
1081 /**
1082  * Inserts 2 bytes aligned on a 2 byte boundary
1083  * with any alignment padding initialized to 0.
1084  *
1085  * @param str the DBusString
1086  * @param insert_at where to insert
1087  * @param octets 2 bytes to insert
1088  * @returns #FALSE if not enough memory.
1089  */
1090 dbus_bool_t
1091 _dbus_string_insert_2_aligned (DBusString         *str,
1092                                int                 insert_at,
1093                                const unsigned char octets[4])
1094 {
1095   DBUS_STRING_PREAMBLE (str);
1096   
1097   if (!align_insert_point_then_open_gap (str, &insert_at, 2, 2))
1098     return FALSE;
1099
1100   ASSIGN_2_OCTETS (real->str + insert_at, octets);
1101
1102   return TRUE;
1103 }
1104
1105 /**
1106  * Inserts 4 bytes aligned on a 4 byte boundary
1107  * with any alignment padding initialized to 0.
1108  *
1109  * @param str the DBusString
1110  * @param insert_at where to insert
1111  * @param octets 4 bytes to insert
1112  * @returns #FALSE if not enough memory.
1113  */
1114 dbus_bool_t
1115 _dbus_string_insert_4_aligned (DBusString         *str,
1116                                int                 insert_at,
1117                                const unsigned char octets[4])
1118 {
1119   DBUS_STRING_PREAMBLE (str);
1120   
1121   if (!align_insert_point_then_open_gap (str, &insert_at, 4, 4))
1122     return FALSE;
1123
1124   ASSIGN_4_OCTETS (real->str + insert_at, octets);
1125
1126   return TRUE;
1127 }
1128
1129 /**
1130  * Inserts 8 bytes aligned on an 8 byte boundary
1131  * with any alignment padding initialized to 0.
1132  *
1133  * @param str the DBusString
1134  * @param insert_at where to insert
1135  * @param octets 8 bytes to insert
1136  * @returns #FALSE if not enough memory.
1137  */
1138 dbus_bool_t
1139 _dbus_string_insert_8_aligned (DBusString         *str,
1140                                int                 insert_at,
1141                                const unsigned char octets[8])
1142 {
1143   DBUS_STRING_PREAMBLE (str);
1144   
1145   if (!align_insert_point_then_open_gap (str, &insert_at, 8, 8))
1146     return FALSE;
1147
1148   _dbus_assert (_DBUS_ALIGN_VALUE (insert_at, 8) == (unsigned) insert_at);
1149   
1150   ASSIGN_8_OCTETS (real->str + insert_at, octets);
1151
1152   return TRUE;
1153 }
1154
1155
1156 /**
1157  * Inserts padding at *insert_at such to align it to the given
1158  * boundary. Initializes the padding to nul bytes. Sets *insert_at
1159  * to the aligned position.
1160  *
1161  * @param str the DBusString
1162  * @param insert_at location to be aligned
1163  * @param alignment alignment boundary (1, 2, 4, or 8)
1164  * @returns #FALSE if not enough memory.
1165  */
1166 dbus_bool_t
1167 _dbus_string_insert_alignment (DBusString        *str,
1168                                int               *insert_at,
1169                                int                alignment)
1170 {
1171   DBUS_STRING_PREAMBLE (str);
1172   
1173   if (!align_insert_point_then_open_gap (str, insert_at, alignment, 0))
1174     return FALSE;
1175
1176   _dbus_assert (_DBUS_ALIGN_VALUE (*insert_at, alignment) == (unsigned) *insert_at);
1177
1178   return TRUE;
1179 }
1180
1181 /**
1182  * Appends a printf-style formatted string
1183  * to the #DBusString.
1184  *
1185  * @param str the string
1186  * @param format printf format
1187  * @param args variable argument list
1188  * @returns #FALSE if no memory
1189  */
1190 dbus_bool_t
1191 _dbus_string_append_printf_valist  (DBusString        *str,
1192                                     const char        *format,
1193                                     va_list            args)
1194 {
1195   int len;
1196   va_list args_copy;
1197
1198   DBUS_STRING_PREAMBLE (str);
1199
1200   DBUS_VA_COPY (args_copy, args);
1201
1202   /* Measure the message length without terminating nul */
1203   len = _dbus_printf_string_upper_bound (format, args);
1204
1205   if (!_dbus_string_lengthen (str, len))
1206     {
1207       /* don't leak the copy */
1208       va_end (args_copy);
1209       return FALSE;
1210     }
1211   
1212   vsprintf ((char*) (real->str + (real->len - len)),
1213             format, args_copy);
1214
1215   va_end (args_copy);
1216
1217   return TRUE;
1218 }
1219
1220 /**
1221  * Appends a printf-style formatted string
1222  * to the #DBusString.
1223  *
1224  * @param str the string
1225  * @param format printf format
1226  * @returns #FALSE if no memory
1227  */
1228 dbus_bool_t
1229 _dbus_string_append_printf (DBusString        *str,
1230                             const char        *format,
1231                             ...)
1232 {
1233   va_list args;
1234   dbus_bool_t retval;
1235   
1236   va_start (args, format);
1237   retval = _dbus_string_append_printf_valist (str, format, args);
1238   va_end (args);
1239
1240   return retval;
1241 }
1242
1243 /**
1244  * Appends block of bytes with the given length to a DBusString.
1245  *
1246  * @param str the DBusString
1247  * @param buffer the bytes to append
1248  * @param len the number of bytes to append
1249  * @returns #FALSE if not enough memory.
1250  */
1251 dbus_bool_t
1252 _dbus_string_append_len (DBusString *str,
1253                          const char *buffer,
1254                          int         len)
1255 {
1256   DBUS_STRING_PREAMBLE (str);
1257   _dbus_assert (buffer != NULL);
1258   _dbus_assert (len >= 0);
1259
1260   return append (real, buffer, len);
1261 }
1262
1263 /**
1264  * Appends a single byte to the string, returning #FALSE
1265  * if not enough memory.
1266  *
1267  * @param str the string
1268  * @param byte the byte to append
1269  * @returns #TRUE on success
1270  */
1271 dbus_bool_t
1272 _dbus_string_append_byte (DBusString    *str,
1273                           unsigned char  byte)
1274 {
1275   DBUS_STRING_PREAMBLE (str);
1276
1277   if (!set_length (real, real->len + 1))
1278     return FALSE;
1279
1280   real->str[real->len-1] = byte;
1281
1282   return TRUE;
1283 }
1284
1285 #ifdef DBUS_BUILD_TESTS
1286 /**
1287  * Appends a single Unicode character, encoding the character
1288  * in UTF-8 format.
1289  *
1290  * @param str the string
1291  * @param ch the Unicode character
1292  */
1293 dbus_bool_t
1294 _dbus_string_append_unichar (DBusString    *str,
1295                              dbus_unichar_t ch)
1296 {
1297   int len;
1298   int first;
1299   int i;
1300   unsigned char *out;
1301   
1302   DBUS_STRING_PREAMBLE (str);
1303
1304   /* this code is from GLib but is pretty standard I think */
1305   
1306   len = 0;
1307   
1308   if (ch < 0x80)
1309     {
1310       first = 0;
1311       len = 1;
1312     }
1313   else if (ch < 0x800)
1314     {
1315       first = 0xc0;
1316       len = 2;
1317     }
1318   else if (ch < 0x10000)
1319     {
1320       first = 0xe0;
1321       len = 3;
1322     }
1323    else if (ch < 0x200000)
1324     {
1325       first = 0xf0;
1326       len = 4;
1327     }
1328   else if (ch < 0x4000000)
1329     {
1330       first = 0xf8;
1331       len = 5;
1332     }
1333   else
1334     {
1335       first = 0xfc;
1336       len = 6;
1337     }
1338
1339   if (len > (real->max_length - real->len))
1340     return FALSE; /* real->len + len would overflow */
1341   
1342   if (!set_length (real, real->len + len))
1343     return FALSE;
1344
1345   out = real->str + (real->len - len);
1346   
1347   for (i = len - 1; i > 0; --i)
1348     {
1349       out[i] = (ch & 0x3f) | 0x80;
1350       ch >>= 6;
1351     }
1352   out[0] = ch | first;
1353
1354   return TRUE;
1355 }
1356 #endif /* DBUS_BUILD_TESTS */
1357
1358 static void
1359 delete (DBusRealString *real,
1360         int             start,
1361         int             len)
1362 {
1363   if (len == 0)
1364     return;
1365   
1366   memmove (real->str + start, real->str + start + len, real->len - (start + len));
1367   real->len -= len;
1368   real->str[real->len] = '\0';
1369 }
1370
1371 /**
1372  * Deletes a segment of a DBusString with length len starting at
1373  * start. (Hint: to clear an entire string, setting length to 0
1374  * with _dbus_string_set_length() is easier.)
1375  *
1376  * @param str the DBusString
1377  * @param start where to start deleting
1378  * @param len the number of bytes to delete
1379  */
1380 void
1381 _dbus_string_delete (DBusString       *str,
1382                      int               start,
1383                      int               len)
1384 {
1385   DBUS_STRING_PREAMBLE (str);
1386   _dbus_assert (start >= 0);
1387   _dbus_assert (len >= 0);
1388   _dbus_assert (start <= real->len);
1389   _dbus_assert (len <= real->len - start);
1390   
1391   delete (real, start, len);
1392 }
1393
1394 static dbus_bool_t
1395 copy (DBusRealString *source,
1396       int             start,
1397       int             len,
1398       DBusRealString *dest,
1399       int             insert_at)
1400 {
1401   if (len == 0)
1402     return TRUE;
1403
1404   if (!open_gap (len, dest, insert_at))
1405     return FALSE;
1406   
1407   memmove (dest->str + insert_at,
1408            source->str + start,
1409            len);
1410
1411   return TRUE;
1412 }
1413
1414 /**
1415  * Checks assertions for two strings we're copying a segment between,
1416  * and declares real_source/real_dest variables.
1417  *
1418  * @param source the source string
1419  * @param start the starting offset
1420  * @param dest the dest string
1421  * @param insert_at where the copied segment is inserted
1422  */
1423 #define DBUS_STRING_COPY_PREAMBLE(source, start, dest, insert_at)       \
1424   DBusRealString *real_source = (DBusRealString*) source;               \
1425   DBusRealString *real_dest = (DBusRealString*) dest;                   \
1426   _dbus_assert ((source) != (dest));                                    \
1427   DBUS_GENERIC_STRING_PREAMBLE (real_source);                           \
1428   DBUS_GENERIC_STRING_PREAMBLE (real_dest);                             \
1429   _dbus_assert (!real_dest->constant);                                  \
1430   _dbus_assert (!real_dest->locked);                                    \
1431   _dbus_assert ((start) >= 0);                                          \
1432   _dbus_assert ((start) <= real_source->len);                           \
1433   _dbus_assert ((insert_at) >= 0);                                      \
1434   _dbus_assert ((insert_at) <= real_dest->len)
1435
1436 /**
1437  * Moves the end of one string into another string. Both strings
1438  * must be initialized, valid strings.
1439  *
1440  * @param source the source string
1441  * @param start where to chop off the source string
1442  * @param dest the destination string
1443  * @param insert_at where to move the chopped-off part of source string
1444  * @returns #FALSE if not enough memory
1445  */
1446 dbus_bool_t
1447 _dbus_string_move (DBusString       *source,
1448                    int               start,
1449                    DBusString       *dest,
1450                    int               insert_at)
1451 {
1452   DBusRealString *real_source = (DBusRealString*) source;
1453   _dbus_assert (start <= real_source->len);
1454   
1455   return _dbus_string_move_len (source, start,
1456                                 real_source->len - start,
1457                                 dest, insert_at);
1458 }
1459
1460 /**
1461  * Like _dbus_string_move(), but does not delete the section
1462  * of the source string that's copied to the dest string.
1463  *
1464  * @param source the source string
1465  * @param start where to start copying the source string
1466  * @param dest the destination string
1467  * @param insert_at where to place the copied part of source string
1468  * @returns #FALSE if not enough memory
1469  */
1470 dbus_bool_t
1471 _dbus_string_copy (const DBusString *source,
1472                    int               start,
1473                    DBusString       *dest,
1474                    int               insert_at)
1475 {
1476   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
1477
1478   return copy (real_source, start,
1479                real_source->len - start,
1480                real_dest,
1481                insert_at);
1482 }
1483
1484 /**
1485  * Like _dbus_string_move(), but can move a segment from
1486  * the middle of the source string.
1487  *
1488  * @todo this doesn't do anything with max_length field.
1489  * we should probably just kill the max_length field though.
1490  * 
1491  * @param source the source string
1492  * @param start first byte of source string to move
1493  * @param len length of segment to move
1494  * @param dest the destination string
1495  * @param insert_at where to move the bytes from the source string
1496  * @returns #FALSE if not enough memory
1497  */
1498 dbus_bool_t
1499 _dbus_string_move_len (DBusString       *source,
1500                        int               start,
1501                        int               len,
1502                        DBusString       *dest,
1503                        int               insert_at)
1504
1505 {
1506   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
1507   _dbus_assert (len >= 0);
1508   _dbus_assert ((start + len) <= real_source->len);
1509
1510
1511   if (len == 0)
1512     {
1513       return TRUE;
1514     }
1515   else if (start == 0 &&
1516            len == real_source->len &&
1517            real_dest->len == 0)
1518     {
1519       /* Short-circuit moving an entire existing string to an empty string
1520        * by just swapping the buffers.
1521        */
1522       /* we assume ->constant doesn't matter as you can't have
1523        * a constant string involved in a move.
1524        */
1525 #define ASSIGN_DATA(a, b) do {                  \
1526         (a)->str = (b)->str;                    \
1527         (a)->len = (b)->len;                    \
1528         (a)->allocated = (b)->allocated;        \
1529         (a)->align_offset = (b)->align_offset;  \
1530       } while (0)
1531       
1532       DBusRealString tmp;
1533
1534       ASSIGN_DATA (&tmp, real_source);
1535       ASSIGN_DATA (real_source, real_dest);
1536       ASSIGN_DATA (real_dest, &tmp);
1537
1538       return TRUE;
1539     }
1540   else
1541     {
1542       if (!copy (real_source, start, len,
1543                  real_dest,
1544                  insert_at))
1545         return FALSE;
1546       
1547       delete (real_source, start,
1548               len);
1549       
1550       return TRUE;
1551     }
1552 }
1553
1554 /**
1555  * Like _dbus_string_copy(), but can copy a segment from the middle of
1556  * the source string.
1557  *
1558  * @param source the source string
1559  * @param start where to start copying the source string
1560  * @param len length of segment to copy
1561  * @param dest the destination string
1562  * @param insert_at where to place the copied segment of source string
1563  * @returns #FALSE if not enough memory
1564  */
1565 dbus_bool_t
1566 _dbus_string_copy_len (const DBusString *source,
1567                        int               start,
1568                        int               len,
1569                        DBusString       *dest,
1570                        int               insert_at)
1571 {
1572   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
1573   _dbus_assert (len >= 0);
1574   _dbus_assert (start <= real_source->len);
1575   _dbus_assert (len <= real_source->len - start);
1576   
1577   return copy (real_source, start, len,
1578                real_dest,
1579                insert_at);
1580 }
1581
1582 /**
1583  * Replaces a segment of dest string with a segment of source string.
1584  *
1585  * @todo optimize the case where the two lengths are the same, and
1586  * avoid memmoving the data in the trailing part of the string twice.
1587  *
1588  * @todo avoid inserting the source into dest, then deleting
1589  * the replaced chunk of dest (which creates a potentially large
1590  * intermediate string). Instead, extend the replaced chunk
1591  * of dest with padding to the same size as the source chunk,
1592  * then copy in the source bytes.
1593  * 
1594  * @param source the source string
1595  * @param start where to start copying the source string
1596  * @param len length of segment to copy
1597  * @param dest the destination string
1598  * @param replace_at start of segment of dest string to replace
1599  * @param replace_len length of segment of dest string to replace
1600  * @returns #FALSE if not enough memory
1601  *
1602  */
1603 dbus_bool_t
1604 _dbus_string_replace_len (const DBusString *source,
1605                           int               start,
1606                           int               len,
1607                           DBusString       *dest,
1608                           int               replace_at,
1609                           int               replace_len)
1610 {
1611   DBUS_STRING_COPY_PREAMBLE (source, start, dest, replace_at);
1612   _dbus_assert (len >= 0);
1613   _dbus_assert (start <= real_source->len);
1614   _dbus_assert (len <= real_source->len - start);
1615   _dbus_assert (replace_at >= 0);
1616   _dbus_assert (replace_at <= real_dest->len);
1617   _dbus_assert (replace_len <= real_dest->len - replace_at);
1618
1619   if (!copy (real_source, start, len,
1620              real_dest, replace_at))
1621     return FALSE;
1622
1623   delete (real_dest, replace_at + len, replace_len);
1624
1625   return TRUE;
1626 }
1627
1628 /* Unicode macros and utf8_validate() from GLib Owen Taylor, Havoc
1629  * Pennington, and Tom Tromey are the authors and authorized relicense.
1630  */
1631
1632 /** computes length and mask of a unicode character
1633  * @param Char the char
1634  * @param Mask the mask variable to assign to
1635  * @param Len the length variable to assign to
1636  */
1637 #define UTF8_COMPUTE(Char, Mask, Len)                                         \
1638   if (Char < 128)                                                             \
1639     {                                                                         \
1640       Len = 1;                                                                \
1641       Mask = 0x7f;                                                            \
1642     }                                                                         \
1643   else if ((Char & 0xe0) == 0xc0)                                             \
1644     {                                                                         \
1645       Len = 2;                                                                \
1646       Mask = 0x1f;                                                            \
1647     }                                                                         \
1648   else if ((Char & 0xf0) == 0xe0)                                             \
1649     {                                                                         \
1650       Len = 3;                                                                \
1651       Mask = 0x0f;                                                            \
1652     }                                                                         \
1653   else if ((Char & 0xf8) == 0xf0)                                             \
1654     {                                                                         \
1655       Len = 4;                                                                \
1656       Mask = 0x07;                                                            \
1657     }                                                                         \
1658   else if ((Char & 0xfc) == 0xf8)                                             \
1659     {                                                                         \
1660       Len = 5;                                                                \
1661       Mask = 0x03;                                                            \
1662     }                                                                         \
1663   else if ((Char & 0xfe) == 0xfc)                                             \
1664     {                                                                         \
1665       Len = 6;                                                                \
1666       Mask = 0x01;                                                            \
1667     }                                                                         \
1668   else                                                                        \
1669     {                                                                         \
1670       Len = 0;                                                               \
1671       Mask = 0;                                                               \
1672     }
1673
1674 /**
1675  * computes length of a unicode character in UTF-8
1676  * @param Char the char
1677  */
1678 #define UTF8_LENGTH(Char)              \
1679   ((Char) < 0x80 ? 1 :                 \
1680    ((Char) < 0x800 ? 2 :               \
1681     ((Char) < 0x10000 ? 3 :            \
1682      ((Char) < 0x200000 ? 4 :          \
1683       ((Char) < 0x4000000 ? 5 : 6)))))
1684    
1685 /**
1686  * Gets a UTF-8 value.
1687  *
1688  * @param Result variable for extracted unicode char.
1689  * @param Chars the bytes to decode
1690  * @param Count counter variable
1691  * @param Mask mask for this char
1692  * @param Len length for this char in bytes
1693  */
1694 #define UTF8_GET(Result, Chars, Count, Mask, Len)                             \
1695   (Result) = (Chars)[0] & (Mask);                                             \
1696   for ((Count) = 1; (Count) < (Len); ++(Count))                               \
1697     {                                                                         \
1698       if (((Chars)[(Count)] & 0xc0) != 0x80)                                  \
1699         {                                                                     \
1700           (Result) = -1;                                                      \
1701           break;                                                              \
1702         }                                                                     \
1703       (Result) <<= 6;                                                         \
1704       (Result) |= ((Chars)[(Count)] & 0x3f);                                  \
1705     }
1706
1707 /**
1708  * Check whether a unicode char is in a valid range.
1709  *
1710  * @param Char the character
1711  */
1712 #define UNICODE_VALID(Char)                   \
1713     ((Char) < 0x110000 &&                     \
1714      (((Char) & 0xFFFFF800) != 0xD800) &&     \
1715      ((Char) < 0xFDD0 || (Char) > 0xFDEF) &&  \
1716      ((Char) & 0xFFFF) != 0xFFFF)
1717
1718 #ifdef DBUS_BUILD_TESTS
1719 /**
1720  * Gets a unicode character from a UTF-8 string. Does no validation;
1721  * you must verify that the string is valid UTF-8 in advance and must
1722  * pass in the start of a character.
1723  *
1724  * @param str the string
1725  * @param start the start of the UTF-8 character.
1726  * @param ch_return location to return the character
1727  * @param end_return location to return the byte index of next character
1728  */
1729 void
1730 _dbus_string_get_unichar (const DBusString *str,
1731                           int               start,
1732                           dbus_unichar_t   *ch_return,
1733                           int              *end_return)
1734 {
1735   int i, mask, len;
1736   dbus_unichar_t result;
1737   unsigned char c;
1738   unsigned char *p;
1739   DBUS_CONST_STRING_PREAMBLE (str);
1740   _dbus_assert (start >= 0);
1741   _dbus_assert (start <= real->len);
1742   
1743   if (ch_return)
1744     *ch_return = 0;
1745   if (end_return)
1746     *end_return = real->len;
1747   
1748   mask = 0;
1749   p = real->str + start;
1750   c = *p;
1751   
1752   UTF8_COMPUTE (c, mask, len);
1753   if (len == 0)
1754     return;
1755   UTF8_GET (result, p, i, mask, len);
1756
1757   if (result == (dbus_unichar_t)-1)
1758     return;
1759
1760   if (ch_return)
1761     *ch_return = result;
1762   if (end_return)
1763     *end_return = start + len;
1764 }
1765 #endif /* DBUS_BUILD_TESTS */
1766
1767 /**
1768  * Finds the given substring in the string,
1769  * returning #TRUE and filling in the byte index
1770  * where the substring was found, if it was found.
1771  * Returns #FALSE if the substring wasn't found.
1772  * Sets *start to the length of the string if the substring
1773  * is not found.
1774  *
1775  * @param str the string
1776  * @param start where to start looking
1777  * @param substr the substring
1778  * @param found return location for where it was found, or #NULL
1779  * @returns #TRUE if found
1780  */
1781 dbus_bool_t
1782 _dbus_string_find (const DBusString *str,
1783                    int               start,
1784                    const char       *substr,
1785                    int              *found)
1786 {
1787   return _dbus_string_find_to (str, start,
1788                                ((const DBusRealString*)str)->len,
1789                                substr, found);
1790 }
1791
1792 /**
1793  * Finds the given substring in the string,
1794  * up to a certain position,
1795  * returning #TRUE and filling in the byte index
1796  * where the substring was found, if it was found.
1797  * Returns #FALSE if the substring wasn't found.
1798  * Sets *start to the length of the string if the substring
1799  * is not found.
1800  *
1801  * @param str the string
1802  * @param start where to start looking
1803  * @param end where to stop looking
1804  * @param substr the substring
1805  * @param found return location for where it was found, or #NULL
1806  * @returns #TRUE if found
1807  */
1808 dbus_bool_t
1809 _dbus_string_find_to (const DBusString *str,
1810                       int               start,
1811                       int               end,
1812                       const char       *substr,
1813                       int              *found)
1814 {
1815   int i;
1816   DBUS_CONST_STRING_PREAMBLE (str);
1817   _dbus_assert (substr != NULL);
1818   _dbus_assert (start <= real->len);
1819   _dbus_assert (start >= 0);
1820   _dbus_assert (substr != NULL);
1821   _dbus_assert (end <= real->len);
1822   _dbus_assert (start <= end);
1823
1824   /* we always "find" an empty string */
1825   if (*substr == '\0')
1826     {
1827       if (found)
1828         *found = start;
1829       return TRUE;
1830     }
1831
1832   i = start;
1833   while (i < end)
1834     {
1835       if (real->str[i] == substr[0])
1836         {
1837           int j = i + 1;
1838           
1839           while (j < end)
1840             {
1841               if (substr[j - i] == '\0')
1842                 break;
1843               else if (real->str[j] != substr[j - i])
1844                 break;
1845               
1846               ++j;
1847             }
1848
1849           if (substr[j - i] == '\0')
1850             {
1851               if (found)
1852                 *found = i;
1853               return TRUE;
1854             }
1855         }
1856       
1857       ++i;
1858     }
1859
1860   if (found)
1861     *found = end;
1862   
1863   return FALSE;  
1864 }
1865
1866 /**
1867  * Finds a blank (space or tab) in the string. Returns #TRUE
1868  * if found, #FALSE otherwise. If a blank is not found sets
1869  * *found to the length of the string.
1870  *
1871  * @param str the string
1872  * @param start byte index to start looking
1873  * @param found place to store the location of the first blank
1874  * @returns #TRUE if a blank was found
1875  */
1876 dbus_bool_t
1877 _dbus_string_find_blank (const DBusString *str,
1878                          int               start,
1879                          int              *found)
1880 {
1881   int i;
1882   DBUS_CONST_STRING_PREAMBLE (str);
1883   _dbus_assert (start <= real->len);
1884   _dbus_assert (start >= 0);
1885   
1886   i = start;
1887   while (i < real->len)
1888     {
1889       if (real->str[i] == ' ' ||
1890           real->str[i] == '\t')
1891         {
1892           if (found)
1893             *found = i;
1894           return TRUE;
1895         }
1896       
1897       ++i;
1898     }
1899
1900   if (found)
1901     *found = real->len;
1902   
1903   return FALSE;
1904 }
1905
1906 /**
1907  * Skips blanks from start, storing the first non-blank in *end
1908  * (blank is space or tab).
1909  *
1910  * @param str the string
1911  * @param start where to start
1912  * @param end where to store the first non-blank byte index
1913  */
1914 void
1915 _dbus_string_skip_blank (const DBusString *str,
1916                          int               start,
1917                          int              *end)
1918 {
1919   int i;
1920   DBUS_CONST_STRING_PREAMBLE (str);
1921   _dbus_assert (start <= real->len);
1922   _dbus_assert (start >= 0);
1923   
1924   i = start;
1925   while (i < real->len)
1926     {
1927       if (!(real->str[i] == ' ' ||
1928             real->str[i] == '\t'))
1929         break;
1930       
1931       ++i;
1932     }
1933
1934   _dbus_assert (i == real->len || !(real->str[i] == ' ' ||
1935                                     real->str[i] == '\t'));
1936   
1937   if (end)
1938     *end = i;
1939 }
1940
1941 /**
1942  * Assigns a newline-terminated or \\r\\n-terminated line from the front
1943  * of the string to the given dest string. The dest string's previous
1944  * contents are deleted. If the source string contains no newline,
1945  * moves the entire source string to the dest string.
1946  *
1947  * @todo owen correctly notes that this is a stupid function (it was
1948  * written purely for test code,
1949  * e.g. dbus-message-builder.c). Probably should be enforced as test
1950  * code only with #ifdef DBUS_BUILD_TESTS
1951  * 
1952  * @param source the source string
1953  * @param dest the destination string (contents are replaced)
1954  * @returns #FALSE if no memory, or source has length 0
1955  */
1956 dbus_bool_t
1957 _dbus_string_pop_line (DBusString *source,
1958                        DBusString *dest)
1959 {
1960   int eol;
1961   dbus_bool_t have_newline;
1962   
1963   _dbus_string_set_length (dest, 0);
1964   
1965   eol = 0;
1966   if (_dbus_string_find (source, 0, "\n", &eol))
1967     {
1968       have_newline = TRUE;
1969       eol += 1; /* include newline */
1970     }
1971   else
1972     {
1973       eol = _dbus_string_get_length (source);
1974       have_newline = FALSE;
1975     }
1976
1977   if (eol == 0)
1978     return FALSE; /* eof */
1979   
1980   if (!_dbus_string_move_len (source, 0, eol,
1981                               dest, 0))
1982     {
1983       return FALSE;
1984     }
1985
1986   /* dump the newline and the \r if we have one */
1987   if (have_newline)
1988     {
1989       dbus_bool_t have_cr;
1990       
1991       _dbus_assert (_dbus_string_get_length (dest) > 0);
1992
1993       if (_dbus_string_get_length (dest) > 1 &&
1994           _dbus_string_get_byte (dest,
1995                                  _dbus_string_get_length (dest) - 2) == '\r')
1996         have_cr = TRUE;
1997       else
1998         have_cr = FALSE;
1999         
2000       _dbus_string_set_length (dest,
2001                                _dbus_string_get_length (dest) -
2002                                (have_cr ? 2 : 1));
2003     }
2004   
2005   return TRUE;
2006 }
2007
2008 #ifdef DBUS_BUILD_TESTS
2009 /**
2010  * Deletes up to and including the first blank space
2011  * in the string.
2012  *
2013  * @param str the string
2014  */
2015 void
2016 _dbus_string_delete_first_word (DBusString *str)
2017 {
2018   int i;
2019   
2020   if (_dbus_string_find_blank (str, 0, &i))
2021     _dbus_string_skip_blank (str, i, &i);
2022
2023   _dbus_string_delete (str, 0, i);
2024 }
2025 #endif
2026
2027 #ifdef DBUS_BUILD_TESTS
2028 /**
2029  * Deletes any leading blanks in the string
2030  *
2031  * @param str the string
2032  */
2033 void
2034 _dbus_string_delete_leading_blanks (DBusString *str)
2035 {
2036   int i;
2037   
2038   _dbus_string_skip_blank (str, 0, &i);
2039
2040   if (i > 0)
2041     _dbus_string_delete (str, 0, i);
2042 }
2043 #endif
2044
2045 /**
2046  * Tests two DBusString for equality.
2047  *
2048  * @todo memcmp is probably faster
2049  *
2050  * @param a first string
2051  * @param b second string
2052  * @returns #TRUE if equal
2053  */
2054 dbus_bool_t
2055 _dbus_string_equal (const DBusString *a,
2056                     const DBusString *b)
2057 {
2058   const unsigned char *ap;
2059   const unsigned char *bp;
2060   const unsigned char *a_end;
2061   const DBusRealString *real_a = (const DBusRealString*) a;
2062   const DBusRealString *real_b = (const DBusRealString*) b;
2063   DBUS_GENERIC_STRING_PREAMBLE (real_a);
2064   DBUS_GENERIC_STRING_PREAMBLE (real_b);
2065
2066   if (real_a->len != real_b->len)
2067     return FALSE;
2068
2069   ap = real_a->str;
2070   bp = real_b->str;
2071   a_end = real_a->str + real_a->len;
2072   while (ap != a_end)
2073     {
2074       if (*ap != *bp)
2075         return FALSE;
2076       
2077       ++ap;
2078       ++bp;
2079     }
2080
2081   return TRUE;
2082 }
2083
2084 #ifdef DBUS_BUILD_TESTS
2085 /**
2086  * Tests two DBusString for equality up to the given length.
2087  * The strings may be shorter than the given length.
2088  *
2089  * @todo write a unit test
2090  *
2091  * @todo memcmp is probably faster
2092  *
2093  * @param a first string
2094  * @param b second string
2095  * @param len the maximum length to look at
2096  * @returns #TRUE if equal for the given number of bytes
2097  */
2098 dbus_bool_t
2099 _dbus_string_equal_len (const DBusString *a,
2100                         const DBusString *b,
2101                         int               len)
2102 {
2103   const unsigned char *ap;
2104   const unsigned char *bp;
2105   const unsigned char *a_end;
2106   const DBusRealString *real_a = (const DBusRealString*) a;
2107   const DBusRealString *real_b = (const DBusRealString*) b;
2108   DBUS_GENERIC_STRING_PREAMBLE (real_a);
2109   DBUS_GENERIC_STRING_PREAMBLE (real_b);
2110
2111   if (real_a->len != real_b->len &&
2112       (real_a->len < len || real_b->len < len))
2113     return FALSE;
2114
2115   ap = real_a->str;
2116   bp = real_b->str;
2117   a_end = real_a->str + MIN (real_a->len, len);
2118   while (ap != a_end)
2119     {
2120       if (*ap != *bp)
2121         return FALSE;
2122       
2123       ++ap;
2124       ++bp;
2125     }
2126
2127   return TRUE;
2128 }
2129 #endif /* DBUS_BUILD_TESTS */
2130
2131 /**
2132  * Tests two sub-parts of two DBusString for equality.  The specified
2133  * range of the first string must exist; the specified start position
2134  * of the second string must exist.
2135  *
2136  * @todo write a unit test
2137  *
2138  * @todo memcmp is probably faster
2139  *
2140  * @param a first string
2141  * @param a_start where to start substring in first string
2142  * @param a_len length of substring in first string
2143  * @param b second string
2144  * @param b_start where to start substring in second string
2145  * @returns #TRUE if the two substrings are equal
2146  */
2147 dbus_bool_t
2148 _dbus_string_equal_substring (const DBusString  *a,
2149                               int                a_start,
2150                               int                a_len,
2151                               const DBusString  *b,
2152                               int                b_start)
2153 {
2154   const unsigned char *ap;
2155   const unsigned char *bp;
2156   const unsigned char *a_end;
2157   const DBusRealString *real_a = (const DBusRealString*) a;
2158   const DBusRealString *real_b = (const DBusRealString*) b;
2159   DBUS_GENERIC_STRING_PREAMBLE (real_a);
2160   DBUS_GENERIC_STRING_PREAMBLE (real_b);
2161   _dbus_assert (a_start >= 0);
2162   _dbus_assert (a_len >= 0);
2163   _dbus_assert (a_start <= real_a->len);
2164   _dbus_assert (a_len <= real_a->len - a_start);
2165   _dbus_assert (b_start >= 0);
2166   _dbus_assert (b_start <= real_b->len);
2167   
2168   if (a_len > real_b->len - b_start)
2169     return FALSE;
2170
2171   ap = real_a->str + a_start;
2172   bp = real_b->str + b_start;
2173   a_end = ap + a_len;
2174   while (ap != a_end)
2175     {
2176       if (*ap != *bp)
2177         return FALSE;
2178       
2179       ++ap;
2180       ++bp;
2181     }
2182
2183   _dbus_assert (bp <= (real_b->str + real_b->len));
2184   
2185   return TRUE;
2186 }
2187
2188 /**
2189  * Checks whether a string is equal to a C string.
2190  *
2191  * @param a the string
2192  * @param c_str the C string
2193  * @returns #TRUE if equal
2194  */
2195 dbus_bool_t
2196 _dbus_string_equal_c_str (const DBusString *a,
2197                           const char       *c_str)
2198 {
2199   const unsigned char *ap;
2200   const unsigned char *bp;
2201   const unsigned char *a_end;
2202   const DBusRealString *real_a = (const DBusRealString*) a;
2203   DBUS_GENERIC_STRING_PREAMBLE (real_a);
2204   _dbus_assert (c_str != NULL);
2205   
2206   ap = real_a->str;
2207   bp = (const unsigned char*) c_str;
2208   a_end = real_a->str + real_a->len;
2209   while (ap != a_end && *bp)
2210     {
2211       if (*ap != *bp)
2212         return FALSE;
2213       
2214       ++ap;
2215       ++bp;
2216     }
2217
2218   if (ap != a_end || *bp)
2219     return FALSE;
2220   
2221   return TRUE;
2222 }
2223
2224 #ifdef DBUS_BUILD_TESTS
2225 /**
2226  * Checks whether a string starts with the given C string.
2227  *
2228  * @param a the string
2229  * @param c_str the C string
2230  * @returns #TRUE if string starts with it
2231  */
2232 dbus_bool_t
2233 _dbus_string_starts_with_c_str (const DBusString *a,
2234                                 const char       *c_str)
2235 {
2236   const unsigned char *ap;
2237   const unsigned char *bp;
2238   const unsigned char *a_end;
2239   const DBusRealString *real_a = (const DBusRealString*) a;
2240   DBUS_GENERIC_STRING_PREAMBLE (real_a);
2241   _dbus_assert (c_str != NULL);
2242   
2243   ap = real_a->str;
2244   bp = (const unsigned char*) c_str;
2245   a_end = real_a->str + real_a->len;
2246   while (ap != a_end && *bp)
2247     {
2248       if (*ap != *bp)
2249         return FALSE;
2250       
2251       ++ap;
2252       ++bp;
2253     }
2254
2255   if (*bp == '\0')
2256     return TRUE;
2257   else
2258     return FALSE;
2259 }
2260 #endif /* DBUS_BUILD_TESTS */
2261
2262 /**
2263  * Appends a two-character hex digit to a string, where the hex digit
2264  * has the value of the given byte.
2265  *
2266  * @param str the string
2267  * @param byte the byte
2268  * @returns #FALSE if no memory
2269  */
2270 dbus_bool_t
2271 _dbus_string_append_byte_as_hex (DBusString *str,
2272                                  int         byte)
2273 {
2274   const char hexdigits[16] = {
2275     '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
2276     'a', 'b', 'c', 'd', 'e', 'f'
2277   };
2278
2279   if (!_dbus_string_append_byte (str,
2280                                  hexdigits[(byte >> 4)]))
2281     return FALSE;
2282   
2283   if (!_dbus_string_append_byte (str,
2284                                  hexdigits[(byte & 0x0f)]))
2285     {
2286       _dbus_string_set_length (str,
2287                                _dbus_string_get_length (str) - 1);
2288       return FALSE;
2289     }
2290
2291   return TRUE;
2292 }
2293
2294 /**
2295  * Encodes a string in hex, the way MD5 and SHA-1 are usually
2296  * encoded. (Each byte is two hex digits.)
2297  *
2298  * @param source the string to encode
2299  * @param start byte index to start encoding
2300  * @param dest string where encoded data should be placed
2301  * @param insert_at where to place encoded data
2302  * @returns #TRUE if encoding was successful, #FALSE if no memory etc.
2303  */
2304 dbus_bool_t
2305 _dbus_string_hex_encode (const DBusString *source,
2306                          int               start,
2307                          DBusString       *dest,
2308                          int               insert_at)
2309 {
2310   DBusString result;
2311   const unsigned char *p;
2312   const unsigned char *end;
2313   dbus_bool_t retval;
2314   
2315   _dbus_assert (start <= _dbus_string_get_length (source));
2316
2317   if (!_dbus_string_init (&result))
2318     return FALSE;
2319
2320   retval = FALSE;
2321   
2322   p = (const unsigned char*) _dbus_string_get_const_data (source);
2323   end = p + _dbus_string_get_length (source);
2324   p += start;
2325   
2326   while (p != end)
2327     {
2328       if (!_dbus_string_append_byte_as_hex (&result, *p))
2329         goto out;
2330       
2331       ++p;
2332     }
2333
2334   if (!_dbus_string_move (&result, 0, dest, insert_at))
2335     goto out;
2336
2337   retval = TRUE;
2338
2339  out:
2340   _dbus_string_free (&result);
2341   return retval;
2342 }
2343
2344 /**
2345  * Decodes a string from hex encoding.
2346  *
2347  * @param source the string to decode
2348  * @param start byte index to start decode
2349  * @param end_return return location of the end of the hex data, or #NULL
2350  * @param dest string where decoded data should be placed
2351  * @param insert_at where to place decoded data
2352  * @returns #TRUE if decoding was successful, #FALSE if no memory.
2353  */
2354 dbus_bool_t
2355 _dbus_string_hex_decode (const DBusString *source,
2356                          int               start,
2357                          int              *end_return,
2358                          DBusString       *dest,
2359                          int               insert_at)
2360 {
2361   DBusString result;
2362   const unsigned char *p;
2363   const unsigned char *end;
2364   dbus_bool_t retval;
2365   dbus_bool_t high_bits;
2366   
2367   _dbus_assert (start <= _dbus_string_get_length (source));
2368
2369   if (!_dbus_string_init (&result))
2370     return FALSE;
2371
2372   retval = FALSE;
2373
2374   high_bits = TRUE;
2375   p = (const unsigned char*) _dbus_string_get_const_data (source);
2376   end = p + _dbus_string_get_length (source);
2377   p += start;
2378   
2379   while (p != end)
2380     {
2381       unsigned int val;
2382
2383       switch (*p)
2384         {
2385         case '0':
2386           val = 0;
2387           break;
2388         case '1':
2389           val = 1;
2390           break;
2391         case '2':
2392           val = 2;
2393           break;
2394         case '3':
2395           val = 3;
2396           break;
2397         case '4':
2398           val = 4;
2399           break;
2400         case '5':
2401           val = 5;
2402           break;
2403         case '6':
2404           val = 6;
2405           break;
2406         case '7':
2407           val = 7;
2408           break;
2409         case '8':
2410           val = 8;
2411           break;
2412         case '9':
2413           val = 9;
2414           break;
2415         case 'a':
2416         case 'A':
2417           val = 10;
2418           break;
2419         case 'b':
2420         case 'B':
2421           val = 11;
2422           break;
2423         case 'c':
2424         case 'C':
2425           val = 12;
2426           break;
2427         case 'd':
2428         case 'D':
2429           val = 13;
2430           break;
2431         case 'e':
2432         case 'E':
2433           val = 14;
2434           break;
2435         case 'f':
2436         case 'F':
2437           val = 15;
2438           break;
2439         default:
2440           goto done;
2441         }
2442
2443       if (high_bits)
2444         {
2445           if (!_dbus_string_append_byte (&result,
2446                                          val << 4))
2447             goto out;
2448         }
2449       else
2450         {
2451           int len;
2452           unsigned char b;
2453
2454           len = _dbus_string_get_length (&result);
2455           
2456           b = _dbus_string_get_byte (&result, len - 1);
2457
2458           b |= val;
2459
2460           _dbus_string_set_byte (&result, len - 1, b);
2461         }
2462
2463       high_bits = !high_bits;
2464
2465       ++p;
2466     }
2467
2468  done:
2469   if (!_dbus_string_move (&result, 0, dest, insert_at))
2470     goto out;
2471
2472   if (end_return)
2473     *end_return = p - (const unsigned char*) _dbus_string_get_const_data (source);
2474
2475   retval = TRUE;
2476   
2477  out:
2478   _dbus_string_free (&result);  
2479   return retval;
2480 }
2481
2482 /**
2483  * Checks that the given range of the string is valid ASCII with no
2484  * nul bytes. If the given range is not entirely contained in the
2485  * string, returns #FALSE.
2486  *
2487  * @todo this is inconsistent with most of DBusString in that
2488  * it allows a start,len range that extends past the string end.
2489  * 
2490  * @param str the string
2491  * @param start first byte index to check
2492  * @param len number of bytes to check
2493  * @returns #TRUE if the byte range exists and is all valid ASCII
2494  */
2495 dbus_bool_t
2496 _dbus_string_validate_ascii (const DBusString *str,
2497                              int               start,
2498                              int               len)
2499 {
2500   const unsigned char *s;
2501   const unsigned char *end;
2502   DBUS_CONST_STRING_PREAMBLE (str);
2503   _dbus_assert (start >= 0);
2504   _dbus_assert (start <= real->len);
2505   _dbus_assert (len >= 0);
2506   
2507   if (len > real->len - start)
2508     return FALSE;
2509   
2510   s = real->str + start;
2511   end = s + len;
2512   while (s != end)
2513     {
2514       if (_DBUS_UNLIKELY (!_DBUS_ISASCII (*s)))
2515         return FALSE;
2516         
2517       ++s;
2518     }
2519   
2520   return TRUE;
2521 }
2522
2523 /**
2524  * Checks that the given range of the string is valid UTF-8. If the
2525  * given range is not entirely contained in the string, returns
2526  * #FALSE. If the string contains any nul bytes in the given range,
2527  * returns #FALSE. If the start and start+len are not on character
2528  * boundaries, returns #FALSE.
2529  *
2530  * @todo this is inconsistent with most of DBusString in that
2531  * it allows a start,len range that extends past the string end.
2532  * 
2533  * @param str the string
2534  * @param start first byte index to check
2535  * @param len number of bytes to check
2536  * @returns #TRUE if the byte range exists and is all valid UTF-8
2537  */
2538 dbus_bool_t
2539 _dbus_string_validate_utf8  (const DBusString *str,
2540                              int               start,
2541                              int               len)
2542 {
2543   const unsigned char *p;
2544   const unsigned char *end;
2545   DBUS_CONST_STRING_PREAMBLE (str);
2546   _dbus_assert (start >= 0);
2547   _dbus_assert (start <= real->len);
2548   _dbus_assert (len >= 0);
2549
2550   /* we are doing _DBUS_UNLIKELY() here which might be
2551    * dubious in a generic library like GLib, but in D-Bus
2552    * we know we're validating messages and that it would
2553    * only be evil/broken apps that would have invalid
2554    * UTF-8. Also, this function seems to be a performance
2555    * bottleneck in profiles.
2556    */
2557   
2558   if (_DBUS_UNLIKELY (len > real->len - start))
2559     return FALSE;
2560   
2561   p = real->str + start;
2562   end = p + len;
2563   
2564   while (p < end)
2565     {
2566       int i, mask, char_len;
2567       dbus_unichar_t result;
2568
2569       /* nul bytes considered invalid */
2570       if (*p == '\0')
2571         break;
2572       
2573       /* Special-case ASCII; this makes us go a lot faster in
2574        * D-Bus profiles where we are typically validating
2575        * function names and such. We have to know that
2576        * all following checks will pass for ASCII though,
2577        * comments follow ...
2578        */      
2579       if (*p < 128)
2580         {
2581           ++p;
2582           continue;
2583         }
2584       
2585       UTF8_COMPUTE (*p, mask, char_len);
2586
2587       if (_DBUS_UNLIKELY (char_len == 0))  /* ASCII: char_len == 1 */
2588         break;
2589
2590       /* check that the expected number of bytes exists in the remaining length */
2591       if (_DBUS_UNLIKELY ((end - p) < char_len)) /* ASCII: p < end and char_len == 1 */
2592         break;
2593         
2594       UTF8_GET (result, p, i, mask, char_len);
2595
2596       /* Check for overlong UTF-8 */
2597       if (_DBUS_UNLIKELY (UTF8_LENGTH (result) != char_len)) /* ASCII: UTF8_LENGTH == 1 */
2598         break;
2599 #if 0
2600       /* The UNICODE_VALID check below will catch this */
2601       if (_DBUS_UNLIKELY (result == (dbus_unichar_t)-1)) /* ASCII: result = ascii value */
2602         break;
2603 #endif
2604
2605       if (_DBUS_UNLIKELY (!UNICODE_VALID (result))) /* ASCII: always valid */
2606         break;
2607
2608       /* UNICODE_VALID should have caught it */
2609       _dbus_assert (result != (dbus_unichar_t)-1);
2610       
2611       p += char_len;
2612     }
2613
2614   /* See that we covered the entire length if a length was
2615    * passed in
2616    */
2617   if (_DBUS_UNLIKELY (p != end))
2618     return FALSE;
2619   else
2620     return TRUE;
2621 }
2622
2623 /**
2624  * Checks that the given range of the string is all nul bytes. If the
2625  * given range is not entirely contained in the string, returns
2626  * #FALSE.
2627  *
2628  * @todo this is inconsistent with most of DBusString in that
2629  * it allows a start,len range that extends past the string end.
2630  * 
2631  * @param str the string
2632  * @param start first byte index to check
2633  * @param len number of bytes to check
2634  * @returns #TRUE if the byte range exists and is all nul bytes
2635  */
2636 dbus_bool_t
2637 _dbus_string_validate_nul (const DBusString *str,
2638                            int               start,
2639                            int               len)
2640 {
2641   const unsigned char *s;
2642   const unsigned char *end;
2643   DBUS_CONST_STRING_PREAMBLE (str);
2644   _dbus_assert (start >= 0);
2645   _dbus_assert (len >= 0);
2646   _dbus_assert (start <= real->len);
2647   
2648   if (len > real->len - start)
2649     return FALSE;
2650   
2651   s = real->str + start;
2652   end = s + len;
2653   while (s != end)
2654     {
2655       if (_DBUS_UNLIKELY (*s != '\0'))
2656         return FALSE;
2657       ++s;
2658     }
2659   
2660   return TRUE;
2661 }
2662
2663 /**
2664  * Clears all allocated bytes in the string to zero.
2665  *
2666  * @param str the string
2667  */
2668 void
2669 _dbus_string_zero (DBusString *str)
2670 {
2671   DBUS_STRING_PREAMBLE (str);
2672
2673   memset (real->str - real->align_offset, '\0', real->allocated);
2674 }
2675 /** @} */
2676
2677 /* tests are in dbus-string-util.c */