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