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