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