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