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