2003-02-02 Havoc Pennington <hp@pobox.com>
[platform/upstream/dbus.git] / dbus / dbus-string.c
1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-string.c String utility class (internal to D-BUS implementation)
3  * 
4  * Copyright (C) 2002  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
29 /**
30  * @defgroup DBusString string class
31  * @ingroup  DBusInternals
32  * @brief DBusString data structure
33  *
34  * Types and functions related to DBusString. DBusString is intended
35  * to be a string class that makes it hard to mess up security issues
36  * (and just in general harder to write buggy code).  It should be
37  * used (or extended and then used) rather than the libc stuff in
38  * string.h.  The string class is a bit inconvenient at spots because
39  * it handles out-of-memory failures and tries to be extra-robust.
40  * 
41  * A DBusString has a maximum length set at initialization time; this
42  * can be used to ensure that a buffer doesn't get too big.  The
43  * _dbus_string_lengthen() method checks for overflow, and for max
44  * length being exceeded.
45  * 
46  * Try to avoid conversion to a plain C string, i.e. add methods on
47  * the string object instead, only convert to C string when passing
48  * things out to the public API. In particular, no sprintf, strcpy,
49  * strcat, any of that should be used. The GString feature of
50  * accepting negative numbers for "length of string" is also absent,
51  * because it could keep us from detecting bogus huge lengths. i.e. if
52  * we passed in some bogus huge length it would be taken to mean
53  * "current length of string" instead of "broken crack"
54  */
55
56 /**
57  * @defgroup DBusStringInternals DBusString implementation details
58  * @ingroup  DBusInternals
59  * @brief DBusString implementation details
60  *
61  * The guts of DBusString.
62  *
63  * @{
64  */
65
66 /**
67  * @brief Internals of DBusString.
68  * 
69  * DBusString internals. DBusString is an opaque objects, it must be
70  * used via accessor functions.
71  */
72 typedef struct
73 {
74   unsigned char *str;            /**< String data, plus nul termination */
75   int            len;            /**< Length without nul */
76   int            allocated;      /**< Allocated size of data */
77   int            max_length;     /**< Max length of this string. */
78   unsigned int   constant : 1;   /**< String data is not owned by DBusString */
79   unsigned int   locked : 1;     /**< DBusString has been locked and can't be changed */
80   unsigned int   invalid : 1;    /**< DBusString is invalid (e.g. already freed) */
81 } DBusRealString;
82
83 /**
84  * Checks a bunch of assertions about a string object
85  *
86  * @param real the DBusRealString
87  */
88 #define DBUS_GENERIC_STRING_PREAMBLE(real) _dbus_assert ((real) != NULL); _dbus_assert (!(real)->invalid); _dbus_assert ((real)->len >= 0); _dbus_assert ((real)->allocated >= 0); _dbus_assert ((real)->max_length >= 0); _dbus_assert ((real)->len <= (real)->allocated); _dbus_assert ((real)->len <= (real)->max_length)
89
90 /**
91  * Checks assertions about a string object that needs to be
92  * modifiable - may not be locked or const. Also declares
93  * the "real" variable pointing to DBusRealString. 
94  * @param str the string
95  */
96 #define DBUS_STRING_PREAMBLE(str) DBusRealString *real = (DBusRealString*) str; \
97   DBUS_GENERIC_STRING_PREAMBLE (real);                                          \
98   _dbus_assert (!(real)->constant);                                             \
99   _dbus_assert (!(real)->locked)
100
101 /**
102  * Checks assertions about a string object that may be locked but
103  * can't be const. i.e. a string object that we can free.  Also
104  * declares the "real" variable pointing to DBusRealString.
105  *
106  * @param str the string
107  */
108 #define DBUS_LOCKED_STRING_PREAMBLE(str) DBusRealString *real = (DBusRealString*) str; \
109   DBUS_GENERIC_STRING_PREAMBLE (real);                                                 \
110   _dbus_assert (!(real)->constant)
111
112 /**
113  * Checks assertions about a string that may be const or locked.  Also
114  * declares the "real" variable pointing to DBusRealString.
115  * @param str the string.
116  */
117 #define DBUS_CONST_STRING_PREAMBLE(str) const DBusRealString *real = (DBusRealString*) str; \
118   DBUS_GENERIC_STRING_PREAMBLE (real)
119
120 /** @} */
121
122 /**
123  * @addtogroup DBusString
124  * @{
125  */
126
127 /** Assert that the string's memory is 8-byte aligned.
128  *
129  *  @todo Currently we just hope libc returns 8-byte aligned memory
130  *  (which is true for GNU libc), but really we need to ensure it by
131  *  allocating 8 extra bytes and keeping an "align_offset : 3" field
132  *  in DBusString, or something along those lines.
133  */
134 #define ASSERT_8_BYTE_ALIGNED(s) \
135   _dbus_assert (_DBUS_ALIGN_ADDRESS (((const DBusRealString*)s)->str, 8) == ((const DBusRealString*)s)->str)
136
137 /**
138  * Initializes a string. The maximum length may be _DBUS_INT_MAX for
139  * no maximum. The string starts life with zero length.
140  * The string must eventually be freed with _dbus_string_free().
141  *
142  * @todo the max length feature is useless, because it looks
143  * to the app like out of memory, and the app might try
144  * to "recover" - but recovery in this case is impossible,
145  * as we can't ever "get more memory" - so should delete the
146  * max length feature I think.
147  *
148  * @todo we could make this init routine not alloc any memory and
149  * return void, would simplify a lot of code, however it might
150  * complexify things elsewhere because _dbus_string_get_data()
151  * etc. could suddenly fail as they'd need to alloc new memory.
152  * 
153  * @param str memory to hold the string
154  * @param max_length the maximum size of the string
155  * @returns #TRUE on success
156  */
157 dbus_bool_t
158 _dbus_string_init (DBusString *str,
159                    int         max_length)
160 {
161   DBusRealString *real;
162   
163   _dbus_assert (str != NULL);
164   _dbus_assert (max_length >= 0);
165
166   _dbus_assert (sizeof (DBusString) == sizeof (DBusRealString));
167   
168   real = (DBusRealString*) str;
169
170   /* It's very important not to touch anything
171    * other than real->str if we're going to fail,
172    * since we also use this function to reset
173    * an existing string, e.g. in _dbus_string_steal_data()
174    */
175   
176 #define INITIAL_ALLOC 2
177   
178   real->str = dbus_malloc (INITIAL_ALLOC);
179   if (real->str == NULL)
180     return FALSE;  
181   
182   real->allocated = INITIAL_ALLOC;
183   real->len = 0;
184   real->str[real->len] = '\0';
185   
186   real->max_length = max_length;
187   real->constant = FALSE;
188   real->locked = FALSE;
189   real->invalid = FALSE;
190
191   ASSERT_8_BYTE_ALIGNED (str);
192   
193   return TRUE;
194 }
195
196 /**
197  * Initializes a constant string. The value parameter is not copied
198  * (should be static), and the string may never be modified.
199  * It is safe but not necessary to call _dbus_string_free()
200  * on a const string.
201  * 
202  * @param str memory to use for the string
203  * @param value a string to be stored in str (not copied!!!)
204  */
205 void
206 _dbus_string_init_const (DBusString *str,
207                          const char *value)
208 {
209   _dbus_string_init_const_len (str, value,
210                                strlen (value));
211 }
212
213 /**
214  * Initializes a constant string with a length. The value parameter is
215  * not copied (should be static), and the string may never be
216  * modified.  It is safe but not necessary to call _dbus_string_free()
217  * on a const string.
218  * 
219  * @param str memory to use for the string
220  * @param value a string to be stored in str (not copied!!!)
221  * @param len the length to use
222  */
223 void
224 _dbus_string_init_const_len (DBusString *str,
225                              const char *value,
226                              int         len)
227 {
228   DBusRealString *real;
229   
230   _dbus_assert (str != NULL);
231   _dbus_assert (value != NULL);
232
233   real = (DBusRealString*) str;
234   
235   real->str = (char*) value;
236   real->len = len;
237   real->allocated = real->len;
238   real->max_length = real->len;
239   real->constant = TRUE;
240   real->invalid = FALSE;
241
242   /* We don't require const strings to be 8-byte aligned as the
243    * memory is coming from elsewhere.
244    */
245 }
246
247 /**
248  * Frees a string created by _dbus_string_init().
249  *
250  * @param str memory where the string is stored.
251  */
252 void
253 _dbus_string_free (DBusString *str)
254 {
255   DBusRealString *real = (DBusRealString*) str;
256   DBUS_GENERIC_STRING_PREAMBLE (real);
257   
258   if (real->constant)
259     return;
260   dbus_free (real->str);
261
262   real->invalid = TRUE;
263 }
264
265 /**
266  * Locks a string such that any attempts to change the string
267  * will result in aborting the program. Also, if the string
268  * is wasting a lot of memory (allocation is larger than what
269  * the string is really using), _dbus_string_lock() will realloc
270  * the string's data to "compact" it.
271  *
272  * @param str the string to lock.
273  */
274 void
275 _dbus_string_lock (DBusString *str)
276 {  
277   DBUS_LOCKED_STRING_PREAMBLE (str); /* can lock multiple times */
278
279   real->locked = TRUE;
280
281   /* Try to realloc to avoid excess memory usage, since
282    * we know we won't change the string further
283    */
284 #define MAX_WASTE 24
285   if (real->allocated > (real->len + MAX_WASTE))
286     {
287       char *new_str;
288       int new_allocated;
289
290       new_allocated = real->len + 1;
291
292       new_str = dbus_realloc (real->str, new_allocated);
293       if (new_str != NULL)
294         {
295           real->str = new_str;
296           real->allocated = new_allocated;
297           ASSERT_8_BYTE_ALIGNED (str);
298         }
299     }
300 }
301
302 static dbus_bool_t
303 set_length (DBusRealString *real,
304             int             new_length)
305 {
306   /* Note, we are setting the length without nul termination */
307
308   /* exceeding max length is the same as failure to allocate memory */
309   if (new_length > real->max_length)
310     return FALSE;
311   
312   while (new_length >= real->allocated)
313     {
314       int new_allocated;
315       char *new_str;
316       
317       new_allocated = 2 + real->allocated * 2;
318       if (new_allocated < real->allocated)
319         return FALSE; /* overflow */
320         
321       new_str = dbus_realloc (real->str, new_allocated);
322       if (new_str == NULL)
323         return FALSE;
324
325       real->str = new_str;
326       real->allocated = new_allocated;
327
328       ASSERT_8_BYTE_ALIGNED (real);
329     }
330
331   real->len = new_length;
332   real->str[real->len] = '\0';
333
334   return TRUE;
335 }
336
337 static dbus_bool_t
338 open_gap (int             len,
339           DBusRealString *dest,
340           int             insert_at)
341 {
342   if (len == 0)
343     return TRUE;
344
345   if (!set_length (dest, dest->len + len))
346     return FALSE;
347
348   memmove (dest->str + insert_at + len, 
349            dest->str + insert_at,
350            dest->len - len - insert_at);
351
352   return TRUE;
353 }
354
355 /**
356  * Gets the raw character buffer from the string.  The returned buffer
357  * will be nul-terminated, but note that strings may contain binary
358  * data so there may be extra nul characters prior to the termination.
359  * This function should be little-used, extend DBusString or add
360  * stuff to dbus-sysdeps.c instead. It's an error to use this
361  * function on a const string.
362  *
363  * @param str the string
364  * @param data_return place to store the returned data
365  */
366 void
367 _dbus_string_get_data (DBusString        *str,
368                        char             **data_return)
369 {
370   DBUS_STRING_PREAMBLE (str);
371   _dbus_assert (data_return != NULL);
372   
373   *data_return = real->str;
374 }
375
376 /**
377  * Gets the raw character buffer from a const string.
378  *
379  * @todo should return the const char* instead of using an out param;
380  * the temporary variable encourages a bug where you use const data
381  * after modifying the string and possibly causing a realloc.
382  *
383  * @param str the string
384  * @param data_return location to store returned data
385  */
386 void
387 _dbus_string_get_const_data (const DBusString  *str,
388                              const char       **data_return)
389 {
390   DBUS_CONST_STRING_PREAMBLE (str);
391   _dbus_assert (data_return != NULL);
392   
393   *data_return = real->str;
394 }
395
396 /**
397  * Gets a sub-portion of the raw character buffer from the
398  * string. The "len" field is required simply for error
399  * checking, to be sure you don't try to use more
400  * string than exists. The nul termination of the
401  * returned buffer remains at the end of the entire
402  * string, not at start + len.
403  *
404  * @param str the string
405  * @param data_return location to return the buffer
406  * @param start byte offset to return
407  * @param len length of segment to return
408  */
409 void
410 _dbus_string_get_data_len (DBusString *str,
411                            char      **data_return,
412                            int         start,
413                            int         len)
414 {
415   DBUS_STRING_PREAMBLE (str);
416   _dbus_assert (data_return != NULL);
417   _dbus_assert (start >= 0);
418   _dbus_assert (len >= 0);
419   _dbus_assert ((start + len) <= real->len);
420   
421   *data_return = real->str + start;
422 }
423
424 /**
425  * const version of _dbus_string_get_data_len().
426  *
427  * @todo should return the const char* instead of using an out param;
428  * the temporary variable encourages a bug where you use const data
429  * after modifying the string and possibly causing a realloc.
430  * 
431  * @param str the string
432  * @param data_return location to return the buffer
433  * @param start byte offset to return
434  * @param len length of segment to return
435  */
436 void
437 _dbus_string_get_const_data_len (const DBusString  *str,
438                                  const char       **data_return,
439                                  int                start,
440                                  int                len)
441 {
442   DBUS_CONST_STRING_PREAMBLE (str);
443   _dbus_assert (data_return != NULL);
444   _dbus_assert (start >= 0);
445   _dbus_assert (len >= 0);
446   _dbus_assert ((start + len) <= real->len);
447   
448   *data_return = real->str + start;
449 }
450
451 /**
452  * Sets the value of the byte at the given position.
453  *
454  * @param str the string
455  * @param i the position
456  * @param byte the new value
457  */
458 void
459 _dbus_string_set_byte (DBusString    *str,
460                        int            i,
461                        unsigned char  byte)
462 {
463   DBUS_STRING_PREAMBLE (str);
464   _dbus_assert (i < real->len);
465
466   real->str[i] = byte;
467 }
468
469 /**
470  * Gets the byte at the given position.
471  *
472  * @param str the string
473  * @param start the position
474  * @returns the byte at that position
475  */
476 unsigned char
477 _dbus_string_get_byte (const DBusString  *str,
478                        int                start)
479 {
480   DBUS_CONST_STRING_PREAMBLE (str);
481   _dbus_assert (start < real->len);
482
483   return real->str[start];
484 }
485
486 /**
487  * Inserts the given byte at the given position.
488  *
489  * @param str the string
490  * @param i the position
491  * @param byte the value to insert
492  * @returns #TRUE on success
493  */
494 dbus_bool_t
495 _dbus_string_insert_byte (DBusString   *str,
496                           int           i,
497                           unsigned char byte)
498 {
499   DBUS_STRING_PREAMBLE (str);
500   _dbus_assert (i <= real->len);
501
502   if (!open_gap (1, real, i))
503     return FALSE;
504   
505   real->str[i] = byte;
506
507   return TRUE;
508 }
509
510 /**
511  * Like _dbus_string_get_data(), but removes the
512  * gotten data from the original string. The caller
513  * must free the data returned. This function may
514  * fail due to lack of memory, and return #FALSE.
515  *
516  * @param str the string
517  * @param data_return location to return the buffer
518  * @returns #TRUE on success
519  */
520 dbus_bool_t
521 _dbus_string_steal_data (DBusString        *str,
522                          char             **data_return)
523 {
524   DBUS_STRING_PREAMBLE (str);
525   _dbus_assert (data_return != NULL);
526   
527   *data_return = real->str;
528
529   /* reset the string */
530   if (!_dbus_string_init (str, real->max_length))
531     {
532       /* hrm, put it back then */
533       real->str = *data_return;
534       *data_return = NULL;
535       return FALSE;
536     }
537
538   return TRUE;
539 }
540
541 /**
542  * Like _dbus_string_get_data_len(), but removes the gotten data from
543  * the original string. The caller must free the data returned. This
544  * function may fail due to lack of memory, and return #FALSE.
545  * The returned string is nul-terminated and has length len.
546  *
547  * @param str the string
548  * @param data_return location to return the buffer
549  * @param start the start of segment to steal
550  * @param len the length of segment to steal
551  * @returns #TRUE on success
552  */
553 dbus_bool_t
554 _dbus_string_steal_data_len (DBusString        *str,
555                              char             **data_return,
556                              int                start,
557                              int                len)
558 {
559   DBusString dest;
560   
561   DBUS_STRING_PREAMBLE (str);
562   _dbus_assert (data_return != NULL);
563   _dbus_assert (start >= 0);
564   _dbus_assert (len >= 0);
565   _dbus_assert ((start + len) <= real->len);
566
567   if (!_dbus_string_init (&dest, real->max_length))
568     return FALSE;
569
570   if (!_dbus_string_move_len (str, start, len, &dest, 0))
571     {
572       _dbus_string_free (&dest);
573       return FALSE;
574     }
575   
576   if (!_dbus_string_steal_data (&dest, data_return))
577     {
578       _dbus_string_free (&dest);
579       return FALSE;
580     }
581
582   _dbus_string_free (&dest);
583   return TRUE;
584 }
585
586 /**
587  * Gets the length of a string (not including nul termination).
588  *
589  * @returns the length.
590  */
591 int
592 _dbus_string_get_length (const DBusString  *str)
593 {
594   DBUS_CONST_STRING_PREAMBLE (str);
595   
596   return real->len;
597 }
598
599 /**
600  * Makes a string longer by the given number of bytes.  Checks whether
601  * adding additional_length to the current length would overflow an
602  * integer, and checks for exceeding a string's max length.
603  * The new bytes are not initialized, other than nul-terminating
604  * the end of the string. The uninitialized bytes may contain
605  * unexpected nul bytes or other junk.
606  *
607  * @param str a string
608  * @param additional_length length to add to the string.
609  * @returns #TRUE on success.
610  */
611 dbus_bool_t
612 _dbus_string_lengthen (DBusString *str,
613                        int         additional_length)
614 {
615   DBUS_STRING_PREAMBLE (str);  
616   _dbus_assert (additional_length >= 0);
617   
618   if ((real->len + additional_length) < real->len)
619     return FALSE; /* overflow */
620   
621   return set_length (real,
622                      real->len + additional_length);
623 }
624
625 /**
626  * Makes a string shorter by the given number of bytes.
627  *
628  * @param str a string
629  * @param length_to_remove length to remove from the string.
630  */
631 void
632 _dbus_string_shorten (DBusString *str,
633                       int         length_to_remove)
634 {
635   DBUS_STRING_PREAMBLE (str);
636   _dbus_assert (length_to_remove >= 0);
637   _dbus_assert (length_to_remove <= real->len);
638
639   set_length (real,
640               real->len - length_to_remove);
641 }
642
643 /**
644  * Sets the length of a string. Can be used to truncate or lengthen
645  * the string. If the string is lengthened, the function may fail and
646  * return #FALSE. Newly-added bytes are not initialized, as with
647  * _dbus_string_lengthen().
648  *
649  * @param str a string
650  * @param length new length of the string.
651  * @returns #FALSE on failure.
652  */
653 dbus_bool_t
654 _dbus_string_set_length (DBusString *str,
655                          int         length)
656 {
657   DBUS_STRING_PREAMBLE (str);
658   _dbus_assert (length >= 0);
659
660   return set_length (real, length);
661 }
662
663 /**
664  * Align the length of a string to a specific alignment (typically 4 or 8)
665  * by appending nul bytes to the string.
666  *
667  * @param str a string
668  * @param alignment the alignment
669  * @returns #FALSE if no memory
670  */
671 dbus_bool_t
672 _dbus_string_align_length (DBusString *str,
673                            int         alignment)
674 {
675   int new_len;
676   int delta;
677   DBUS_STRING_PREAMBLE (str);
678   _dbus_assert (alignment >= 1);
679   _dbus_assert (alignment <= 8); /* it has to be a bug if > 8 */
680
681   new_len = _DBUS_ALIGN_VALUE (real->len, alignment);
682
683   delta = new_len - real->len;
684   _dbus_assert (delta >= 0);
685
686   if (delta == 0)
687     return TRUE;
688
689   if (!set_length (real, new_len))
690     return FALSE;
691
692   memset (real->str + (new_len - delta),
693           '\0', delta);
694
695   return TRUE;
696 }
697
698 static dbus_bool_t
699 append (DBusRealString *real,
700         const char     *buffer,
701         int             buffer_len)
702 {
703   if (buffer_len == 0)
704     return TRUE;
705
706   if (!_dbus_string_lengthen ((DBusString*)real, buffer_len))
707     return FALSE;
708
709   memcpy (real->str + (real->len - buffer_len),
710           buffer,
711           buffer_len);
712
713   return TRUE;
714 }
715
716 /**
717  * Appends a nul-terminated C-style string to a DBusString.
718  *
719  * @param str the DBusString
720  * @param buffer the nul-terminated characters to append
721  * @returns #FALSE if not enough memory.
722  */
723 dbus_bool_t
724 _dbus_string_append (DBusString *str,
725                      const char *buffer)
726 {
727   int buffer_len;
728   
729   DBUS_STRING_PREAMBLE (str);
730   _dbus_assert (buffer != NULL);
731   
732   buffer_len = strlen (buffer);
733
734   return append (real, buffer, buffer_len);
735 }
736
737 /**
738  * Appends block of bytes with the given length to a DBusString.
739  *
740  * @param str the DBusString
741  * @param buffer the bytes to append
742  * @param len the number of bytes to append
743  * @returns #FALSE if not enough memory.
744  */
745 dbus_bool_t
746 _dbus_string_append_len (DBusString *str,
747                          const char *buffer,
748                          int         len)
749 {
750   DBUS_STRING_PREAMBLE (str);
751   _dbus_assert (buffer != NULL);
752   _dbus_assert (len >= 0);
753
754   return append (real, buffer, len);
755 }
756
757 /**
758  * Appends a single byte to the string, returning #FALSE
759  * if not enough memory.
760  *
761  * @param str the string
762  * @param byte the byte to append
763  * @returns #TRUE on success
764  */
765 dbus_bool_t
766 _dbus_string_append_byte (DBusString    *str,
767                           unsigned char  byte)
768 {
769   DBUS_STRING_PREAMBLE (str);
770
771   if (!set_length (real, real->len + 1))
772     return FALSE;
773
774   real->str[real->len-1] = byte;
775
776   return TRUE;
777 }
778
779 /**
780  * Appends a single Unicode character, encoding the character
781  * in UTF-8 format.
782  *
783  * @param str the string
784  * @param ch the Unicode character
785  */
786 dbus_bool_t
787 _dbus_string_append_unichar (DBusString    *str,
788                              dbus_unichar_t ch)
789 {
790   int len;
791   int first;
792   int i;
793   char *out;
794   
795   DBUS_STRING_PREAMBLE (str);
796
797   /* this code is from GLib but is pretty standard I think */
798   
799   len = 0;
800   
801   if (ch < 0x80)
802     {
803       first = 0;
804       len = 1;
805     }
806   else if (ch < 0x800)
807     {
808       first = 0xc0;
809       len = 2;
810     }
811   else if (ch < 0x10000)
812     {
813       first = 0xe0;
814       len = 3;
815     }
816    else if (ch < 0x200000)
817     {
818       first = 0xf0;
819       len = 4;
820     }
821   else if (ch < 0x4000000)
822     {
823       first = 0xf8;
824       len = 5;
825     }
826   else
827     {
828       first = 0xfc;
829       len = 6;
830     }
831
832   if (!set_length (real, real->len + len))
833     return FALSE;
834
835   out = real->str + (real->len - len);
836   
837   for (i = len - 1; i > 0; --i)
838     {
839       out[i] = (ch & 0x3f) | 0x80;
840       ch >>= 6;
841     }
842   out[0] = ch | first;
843
844   return TRUE;
845 }
846
847 static void
848 delete (DBusRealString *real,
849         int             start,
850         int             len)
851 {
852   if (len == 0)
853     return;
854   
855   memmove (real->str + start, real->str + start + len, real->len - (start + len));
856   real->len -= len;
857   real->str[real->len] = '\0';
858 }
859
860 /**
861  * Deletes a segment of a DBusString with length len starting at
862  * start. (Hint: to clear an entire string, setting length to 0
863  * with _dbus_string_set_length() is easier.)
864  *
865  * @param str the DBusString
866  * @param start where to start deleting
867  * @param len the number of bytes to delete
868  */
869 void
870 _dbus_string_delete (DBusString       *str,
871                      int               start,
872                      int               len)
873 {
874   DBUS_STRING_PREAMBLE (str);
875   _dbus_assert (start >= 0);
876   _dbus_assert (len >= 0);
877   _dbus_assert ((start + len) <= real->len);
878   
879   delete (real, start, len);
880 }
881
882 static dbus_bool_t
883 copy (DBusRealString *source,
884       int             start,
885       int             len,
886       DBusRealString *dest,
887       int             insert_at)
888 {
889   if (len == 0)
890     return TRUE;
891
892   if (!open_gap (len, dest, insert_at))
893     return FALSE;
894   
895   memcpy (dest->str + insert_at,
896           source->str + start,
897           len);
898
899   return TRUE;
900 }
901
902 /**
903  * Checks assertions for two strings we're copying a segment between,
904  * and declares real_source/real_dest variables.
905  *
906  * @param source the source string
907  * @param start the starting offset
908  * @param dest the dest string
909  * @param insert_at where the copied segment is inserted
910  */
911 #define DBUS_STRING_COPY_PREAMBLE(source, start, dest, insert_at)       \
912   DBusRealString *real_source = (DBusRealString*) source;               \
913   DBusRealString *real_dest = (DBusRealString*) dest;                   \
914   _dbus_assert ((source) != (dest));                                    \
915   DBUS_GENERIC_STRING_PREAMBLE (real_source);                           \
916   DBUS_GENERIC_STRING_PREAMBLE (real_dest);                             \
917   _dbus_assert (!real_dest->constant);                                  \
918   _dbus_assert (!real_dest->locked);                                    \
919   _dbus_assert ((start) >= 0);                                          \
920   _dbus_assert ((start) <= real_source->len);                           \
921   _dbus_assert ((insert_at) >= 0);                                      \
922   _dbus_assert ((insert_at) <= real_dest->len)
923
924 /**
925  * Moves the end of one string into another string. Both strings
926  * must be initialized, valid strings.
927  *
928  * @param source the source string
929  * @param start where to chop off the source string
930  * @param dest the destination string
931  * @param insert_at where to move the chopped-off part of source string
932  * @returns #FALSE if not enough memory
933  */
934 dbus_bool_t
935 _dbus_string_move (DBusString       *source,
936                    int               start,
937                    DBusString       *dest,
938                    int               insert_at)
939 {
940   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
941   
942   if (!copy (real_source, start,
943              real_source->len - start,
944              real_dest,
945              insert_at))
946     return FALSE;
947
948   delete (real_source, start,
949           real_source->len - start);
950
951   return TRUE;
952 }
953
954 /**
955  * Like _dbus_string_move(), but does not delete the section
956  * of the source string that's copied to the dest string.
957  *
958  * @param source the source string
959  * @param start where to start copying the source string
960  * @param dest the destination string
961  * @param insert_at where to place the copied part of source string
962  * @returns #FALSE if not enough memory
963  */
964 dbus_bool_t
965 _dbus_string_copy (const DBusString *source,
966                    int               start,
967                    DBusString       *dest,
968                    int               insert_at)
969 {
970   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
971
972   return copy (real_source, start,
973                real_source->len - start,
974                real_dest,
975                insert_at);
976 }
977
978 /**
979  * Like _dbus_string_move(), but can move a segment from
980  * the middle of the source string.
981  * 
982  * @param source the source string
983  * @param start first byte of source string to move
984  * @param len length of segment to move
985  * @param dest the destination string
986  * @param insert_at where to move the bytes from the source string
987  * @returns #FALSE if not enough memory
988  */
989 dbus_bool_t
990 _dbus_string_move_len (DBusString       *source,
991                        int               start,
992                        int               len,
993                        DBusString       *dest,
994                        int               insert_at)
995
996 {
997   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
998   _dbus_assert (len >= 0);
999   _dbus_assert ((start + len) <= real_source->len);
1000
1001   if (!copy (real_source, start, len,
1002              real_dest,
1003              insert_at))
1004     return FALSE;
1005
1006   delete (real_source, start,
1007           len);
1008
1009   return TRUE;
1010 }
1011
1012 /**
1013  * Like _dbus_string_copy(), but can copy a segment from the middle of
1014  * the source string.
1015  *
1016  * @param source the source string
1017  * @param start where to start copying the source string
1018  * @param len length of segment to copy
1019  * @param dest the destination string
1020  * @param insert_at where to place the copied segment of source string
1021  * @returns #FALSE if not enough memory
1022  */
1023 dbus_bool_t
1024 _dbus_string_copy_len (const DBusString *source,
1025                        int               start,
1026                        int               len,
1027                        DBusString       *dest,
1028                        int               insert_at)
1029 {
1030   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
1031   _dbus_assert (len >= 0);
1032   _dbus_assert ((start + len) <= real_source->len);
1033   
1034   return copy (real_source, start, len,
1035                real_dest,
1036                insert_at);
1037 }
1038
1039 /**
1040  * Replaces a segment of dest string with a segment of source string.
1041  *
1042  * @todo optimize the case where the two lengths are the same, and
1043  * avoid memmoving the data in the trailing part of the string twice.
1044  * 
1045  * @param source the source string
1046  * @param start where to start copying the source string
1047  * @param len length of segment to copy
1048  * @param dest the destination string
1049  * @param replace_at start of segment of dest string to replace
1050  * @param replace_len length of segment of dest string to replace
1051  * @returns #FALSE if not enough memory
1052  *
1053  */
1054 dbus_bool_t
1055 _dbus_string_replace_len (const DBusString *source,
1056                           int               start,
1057                           int               len,
1058                           DBusString       *dest,
1059                           int               replace_at,
1060                           int               replace_len)
1061 {
1062   DBUS_STRING_COPY_PREAMBLE (source, start, dest, replace_at);
1063   _dbus_assert (len >= 0);
1064   _dbus_assert ((start + len) <= real_source->len);
1065   _dbus_assert (replace_at >= 0);
1066   _dbus_assert ((replace_at + replace_len) <= real_dest->len);
1067
1068   if (!copy (real_source, start, len,
1069              real_dest, replace_at))
1070     return FALSE;
1071
1072   delete (real_dest, replace_at + len, replace_len);
1073
1074   return TRUE;
1075 }
1076
1077 /* Unicode macros from GLib */
1078
1079 /** computes length and mask of a unicode character
1080  * @param Char the char
1081  * @param Mask the mask variable to assign to
1082  * @param Len the length variable to assign to
1083  */
1084 #define UTF8_COMPUTE(Char, Mask, Len)                                         \
1085   if (Char < 128)                                                             \
1086     {                                                                         \
1087       Len = 1;                                                                \
1088       Mask = 0x7f;                                                            \
1089     }                                                                         \
1090   else if ((Char & 0xe0) == 0xc0)                                             \
1091     {                                                                         \
1092       Len = 2;                                                                \
1093       Mask = 0x1f;                                                            \
1094     }                                                                         \
1095   else if ((Char & 0xf0) == 0xe0)                                             \
1096     {                                                                         \
1097       Len = 3;                                                                \
1098       Mask = 0x0f;                                                            \
1099     }                                                                         \
1100   else if ((Char & 0xf8) == 0xf0)                                             \
1101     {                                                                         \
1102       Len = 4;                                                                \
1103       Mask = 0x07;                                                            \
1104     }                                                                         \
1105   else if ((Char & 0xfc) == 0xf8)                                             \
1106     {                                                                         \
1107       Len = 5;                                                                \
1108       Mask = 0x03;                                                            \
1109     }                                                                         \
1110   else if ((Char & 0xfe) == 0xfc)                                             \
1111     {                                                                         \
1112       Len = 6;                                                                \
1113       Mask = 0x01;                                                            \
1114     }                                                                         \
1115   else                                                                        \
1116     Len = -1;
1117
1118 /**
1119  * computes length of a unicode character in UTF-8
1120  * @param Char the char
1121  */
1122 #define UTF8_LENGTH(Char)              \
1123   ((Char) < 0x80 ? 1 :                 \
1124    ((Char) < 0x800 ? 2 :               \
1125     ((Char) < 0x10000 ? 3 :            \
1126      ((Char) < 0x200000 ? 4 :          \
1127       ((Char) < 0x4000000 ? 5 : 6)))))
1128    
1129 /**
1130  * Gets a UTF-8 value.
1131  *
1132  * @param Result variable for extracted unicode char.
1133  * @param Chars the bytes to decode
1134  * @param Count counter variable
1135  * @param Mask mask for this char
1136  * @param Len length for this char in bytes
1137  */
1138 #define UTF8_GET(Result, Chars, Count, Mask, Len)                             \
1139   (Result) = (Chars)[0] & (Mask);                                             \
1140   for ((Count) = 1; (Count) < (Len); ++(Count))                               \
1141     {                                                                         \
1142       if (((Chars)[(Count)] & 0xc0) != 0x80)                                  \
1143         {                                                                     \
1144           (Result) = -1;                                                      \
1145           break;                                                              \
1146         }                                                                     \
1147       (Result) <<= 6;                                                         \
1148       (Result) |= ((Chars)[(Count)] & 0x3f);                                  \
1149     }
1150
1151 /**
1152  * Check whether a unicode char is in a valid range.
1153  *
1154  * @param Char the character
1155  */
1156 #define UNICODE_VALID(Char)                   \
1157     ((Char) < 0x110000 &&                     \
1158      ((Char) < 0xD800 || (Char) >= 0xE000) && \
1159      (Char) != 0xFFFE && (Char) != 0xFFFF)   
1160
1161 /**
1162  * Gets a unicode character from a UTF-8 string. Does no validation;
1163  * you must verify that the string is valid UTF-8 in advance and must
1164  * pass in the start of a character.
1165  *
1166  * @param str the string
1167  * @param start the start of the UTF-8 character.
1168  * @param ch_return location to return the character
1169  * @param end_return location to return the byte index of next character
1170  * @returns #TRUE on success, #FALSE otherwise.
1171  */
1172 void
1173 _dbus_string_get_unichar (const DBusString *str,
1174                           int               start,
1175                           dbus_unichar_t   *ch_return,
1176                           int              *end_return)
1177 {
1178   int i, mask, len;
1179   dbus_unichar_t result;
1180   unsigned char c;
1181   unsigned char *p;
1182   DBUS_CONST_STRING_PREAMBLE (str);
1183
1184   if (ch_return)
1185     *ch_return = 0;
1186   if (end_return)
1187     *end_return = real->len;
1188   
1189   mask = 0;
1190   p = real->str + start;
1191   c = *p;
1192   
1193   UTF8_COMPUTE (c, mask, len);
1194   if (len == -1)
1195     return;
1196   UTF8_GET (result, p, i, mask, len);
1197
1198   if (result == (dbus_unichar_t)-1)
1199     return;
1200
1201   if (ch_return)
1202     *ch_return = result;
1203   if (end_return)
1204     *end_return = start + len;
1205 }
1206
1207 /**
1208  * Finds the given substring in the string,
1209  * returning #TRUE and filling in the byte index
1210  * where the substring was found, if it was found.
1211  * Returns #FALSE if the substring wasn't found.
1212  * Sets *start to the length of the string if the substring
1213  * is not found.
1214  *
1215  * @param str the string
1216  * @param start where to start looking
1217  * @param substr the substring
1218  * @param found return location for where it was found, or #NULL
1219  * @returns #TRUE if found
1220  */
1221 dbus_bool_t
1222 _dbus_string_find (const DBusString *str,
1223                    int               start,
1224                    const char       *substr,
1225                    int              *found)
1226 {
1227   int i;
1228   DBUS_CONST_STRING_PREAMBLE (str);
1229   _dbus_assert (substr != NULL);
1230   _dbus_assert (start <= real->len);
1231   
1232   /* we always "find" an empty string */
1233   if (*substr == '\0')
1234     {
1235       if (found)
1236         *found = 0;
1237       return TRUE;
1238     }
1239   
1240   i = start;
1241   while (i < real->len)
1242     {
1243       if (real->str[i] == substr[0])
1244         {
1245           int j = i + 1;
1246           
1247           while (j < real->len)
1248             {
1249               if (substr[j - i] == '\0')
1250                 break;
1251               else if (real->str[j] != substr[j - i])
1252                 break;
1253               
1254               ++j;
1255             }
1256
1257           if (substr[j - i] == '\0')
1258             {
1259               if (found)
1260                 *found = i;
1261               return TRUE;
1262             }
1263         }
1264       
1265       ++i;
1266     }
1267
1268   if (found)
1269     *found = real->len;
1270   
1271   return FALSE;
1272 }
1273
1274 /**
1275  * Finds the given substring in the string,
1276  * up to a certain position,
1277  * returning #TRUE and filling in the byte index
1278  * where the substring was found, if it was found.
1279  * Returns #FALSE if the substring wasn't found.
1280  * Sets *start to the length of the string if the substring
1281  * is not found.
1282  *
1283  * @param str the string
1284  * @param start where to start looking
1285  * @param end where to stop looking
1286  * @param substr the substring
1287  * @param found return location for where it was found, or #NULL
1288  * @returns #TRUE if found
1289  */
1290 dbus_bool_t
1291 _dbus_string_find_to (const DBusString *str,
1292                       int               start,
1293                       int               end,
1294                       const char       *substr,
1295                       int              *found)
1296 {
1297   int i;
1298   DBUS_CONST_STRING_PREAMBLE (str);
1299   _dbus_assert (substr != NULL);
1300   _dbus_assert (start <= real->len);
1301   _dbus_assert (end <= real->len);
1302   _dbus_assert (start < end);
1303
1304   /* we always "find" an empty string */
1305   if (*substr == '\0')
1306     {
1307       if (found)
1308         *found = 0;
1309       return TRUE;
1310     }
1311
1312   i = start;
1313   while (i < real->len && i < end)
1314     {
1315       if (real->str[i] == substr[0])
1316         {
1317           int j = i + 1;
1318           
1319           while (j < real->len && j < end)
1320             {
1321               if (substr[j - i] == '\0')
1322                 break;
1323               else if (real->str[j] != substr[j - i])
1324                 break;
1325               
1326               ++j;
1327             }
1328
1329           if (substr[j - i] == '\0')
1330             {
1331               if (found)
1332                 *found = i;
1333               return TRUE;
1334             }
1335         }
1336       
1337       ++i;
1338     }
1339
1340   if (found)
1341     *found = end;
1342   
1343   return FALSE;  
1344 }
1345
1346 /**
1347  * Finds a blank (space or tab) in the string. Returns #TRUE
1348  * if found, #FALSE otherwise. If a blank is not found sets
1349  * *found to the length of the string.
1350  *
1351  * @param str the string
1352  * @param start byte index to start looking
1353  * @param found place to store the location of the first blank
1354  * @returns #TRUE if a blank was found
1355  */
1356 dbus_bool_t
1357 _dbus_string_find_blank (const DBusString *str,
1358                          int               start,
1359                          int              *found)
1360 {
1361   int i;
1362   DBUS_CONST_STRING_PREAMBLE (str);
1363   _dbus_assert (start <= real->len);
1364   
1365   i = start;
1366   while (i < real->len)
1367     {
1368       if (real->str[i] == ' ' ||
1369           real->str[i] == '\t')
1370         {
1371           if (found)
1372             *found = i;
1373           return TRUE;
1374         }
1375       
1376       ++i;
1377     }
1378
1379   if (found)
1380     *found = real->len;
1381   
1382   return FALSE;
1383 }
1384
1385 /**
1386  * Skips blanks from start, storing the first non-blank in *end
1387  *
1388  * @param str the string
1389  * @param start where to start
1390  * @param end where to store the first non-blank byte index
1391  */
1392 void
1393 _dbus_string_skip_blank (const DBusString *str,
1394                          int               start,
1395                          int              *end)
1396 {
1397   int i;
1398   DBUS_CONST_STRING_PREAMBLE (str);
1399   _dbus_assert (start <= real->len);
1400   
1401   i = start;
1402   while (i < real->len)
1403     {
1404       if (!(real->str[i] == ' ' ||
1405             real->str[i] == '\t'))
1406         break;
1407       
1408       ++i;
1409     }
1410
1411   _dbus_assert (i == real->len || !(real->str[i] == ' ' ||
1412                                     real->str[i] == '\t'));
1413   
1414   if (end)
1415     *end = i;
1416 }
1417
1418 /**
1419  * Tests two DBusString for equality.
1420  *
1421  * @param a first string
1422  * @param b second string
1423  * @returns #TRUE if equal
1424  */
1425 dbus_bool_t
1426 _dbus_string_equal (const DBusString *a,
1427                     const DBusString *b)
1428 {
1429   const unsigned char *ap;
1430   const unsigned char *bp;
1431   const unsigned char *a_end;
1432   const DBusRealString *real_a = (const DBusRealString*) a;
1433   const DBusRealString *real_b = (const DBusRealString*) b;
1434   DBUS_GENERIC_STRING_PREAMBLE (real_a);
1435   DBUS_GENERIC_STRING_PREAMBLE (real_b);
1436
1437   if (real_a->len != real_b->len)
1438     return FALSE;
1439
1440   ap = real_a->str;
1441   bp = real_b->str;
1442   a_end = real_a->str + real_a->len;
1443   while (ap != a_end)
1444     {
1445       if (*ap != *bp)
1446         return FALSE;
1447       
1448       ++ap;
1449       ++bp;
1450     }
1451
1452   return TRUE;
1453 }
1454
1455 /**
1456  * Checks whether a string is equal to a C string.
1457  *
1458  * @param a the string
1459  * @param c_str the C string
1460  * @returns #TRUE if equal
1461  */
1462 dbus_bool_t
1463 _dbus_string_equal_c_str (const DBusString *a,
1464                           const char       *c_str)
1465 {
1466   const unsigned char *ap;
1467   const unsigned char *bp;
1468   const unsigned char *a_end;
1469   const DBusRealString *real_a = (const DBusRealString*) a;
1470   DBUS_GENERIC_STRING_PREAMBLE (real_a);
1471
1472   ap = real_a->str;
1473   bp = (const unsigned char*) c_str;
1474   a_end = real_a->str + real_a->len;
1475   while (ap != a_end && *bp)
1476     {
1477       if (*ap != *bp)
1478         return FALSE;
1479       
1480       ++ap;
1481       ++bp;
1482     }
1483
1484   if (*ap && *bp == '\0')
1485     return FALSE;
1486   else if (ap == a_end && *bp)
1487     return FALSE;
1488   
1489   return TRUE;
1490 }
1491
1492 /**
1493  * Checks whether a string starts with the given C string.
1494  *
1495  * @param a the string
1496  * @param c_str the C string
1497  * @returns #TRUE if string starts with it
1498  */
1499 dbus_bool_t
1500 _dbus_string_starts_with_c_str (const DBusString *a,
1501                                 const char       *c_str)
1502 {
1503   const unsigned char *ap;
1504   const unsigned char *bp;
1505   const unsigned char *a_end;
1506   const DBusRealString *real_a = (const DBusRealString*) a;
1507   DBUS_GENERIC_STRING_PREAMBLE (real_a);
1508
1509   ap = real_a->str;
1510   bp = (const unsigned char*) c_str;
1511   a_end = real_a->str + real_a->len;
1512   while (ap != a_end && *bp)
1513     {
1514       if (*ap != *bp)
1515         return FALSE;
1516       
1517       ++ap;
1518       ++bp;
1519     }
1520
1521   if (*bp == '\0')
1522     return TRUE;
1523   else
1524     return FALSE;
1525 }
1526
1527 /**
1528  * Returns whether a string ends with the given suffix
1529  *
1530  * @param a the string
1531  * @param c_str the C-style string
1532  * @returns #TRUE if the string ends with the suffix
1533  */
1534 dbus_bool_t
1535 _dbus_string_ends_with_c_str (const DBusString *a,
1536                               const char       *c_str)
1537 {
1538   const unsigned char *ap;
1539   const unsigned char *bp;
1540   const unsigned char *a_end;
1541   int c_str_len;
1542   const DBusRealString *real_a = (const DBusRealString*) a;
1543   DBUS_GENERIC_STRING_PREAMBLE (real_a);
1544
1545   c_str_len = strlen (c_str);
1546   if (real_a->len < c_str_len)
1547     return FALSE;
1548   
1549   ap = real_a->str + (real_a->len - c_str_len);
1550   bp = (const unsigned char*) c_str;
1551   a_end = real_a->str + real_a->len;
1552   while (ap != a_end)
1553     {
1554       if (*ap != *bp)
1555         return FALSE;
1556       
1557       ++ap;
1558       ++bp;
1559     }
1560
1561   _dbus_assert (*ap == '\0');
1562   _dbus_assert (*bp == '\0');
1563   
1564   return TRUE;
1565 }
1566
1567 static const signed char base64_table[] = {
1568   /* 0 */ 'A',
1569   /* 1 */ 'B',
1570   /* 2 */ 'C',
1571   /* 3 */ 'D',
1572   /* 4 */ 'E',
1573   /* 5 */ 'F',
1574   /* 6 */ 'G',
1575   /* 7 */ 'H',
1576   /* 8 */ 'I',
1577   /* 9 */ 'J',
1578   /* 10 */ 'K',
1579   /* 11 */ 'L',
1580   /* 12 */ 'M',
1581   /* 13 */ 'N',
1582   /* 14 */ 'O',
1583   /* 15 */ 'P',
1584   /* 16 */ 'Q',
1585   /* 17 */ 'R',
1586   /* 18 */ 'S',
1587   /* 19 */ 'T',
1588   /* 20 */ 'U',
1589   /* 21 */ 'V',
1590   /* 22 */ 'W',
1591   /* 23 */ 'X',
1592   /* 24 */ 'Y',
1593   /* 25 */ 'Z',
1594   /* 26 */ 'a',
1595   /* 27 */ 'b',
1596   /* 28 */ 'c',
1597   /* 29 */ 'd',
1598   /* 30 */ 'e',
1599   /* 31 */ 'f',
1600   /* 32 */ 'g',
1601   /* 33 */ 'h',
1602   /* 34 */ 'i',
1603   /* 35 */ 'j',
1604   /* 36 */ 'k',
1605   /* 37 */ 'l',
1606   /* 38 */ 'm',
1607   /* 39 */ 'n',
1608   /* 40 */ 'o',
1609   /* 41 */ 'p',
1610   /* 42 */ 'q',
1611   /* 43 */ 'r',
1612   /* 44 */ 's',
1613   /* 45 */ 't',
1614   /* 46 */ 'u',
1615   /* 47 */ 'v',
1616   /* 48 */ 'w',
1617   /* 49 */ 'x',
1618   /* 50 */ 'y',
1619   /* 51 */ 'z',
1620   /* 52 */ '0',
1621   /* 53 */ '1',
1622   /* 54 */ '2',
1623   /* 55 */ '3',
1624   /* 56 */ '4',
1625   /* 57 */ '5',
1626   /* 58 */ '6',
1627   /* 59 */ '7',
1628   /* 60 */ '8',
1629   /* 61 */ '9',
1630   /* 62 */ '+',
1631   /* 63 */ '/'
1632 };
1633
1634 /** The minimum char that's a valid char in Base64-encoded text */
1635 #define UNBASE64_MIN_CHAR (43)
1636 /** The maximum char that's a valid char in Base64-encoded text */
1637 #define UNBASE64_MAX_CHAR (122)
1638 /** Must subtract this from a char's integer value before offsetting
1639  * into unbase64_table
1640  */
1641 #define UNBASE64_TABLE_OFFSET UNBASE64_MIN_CHAR
1642 static const signed char unbase64_table[] = {
1643   /* 43 + */ 62,
1644   /* 44 , */ -1,
1645   /* 45 - */ -1,
1646   /* 46 . */ -1,
1647   /* 47 / */ 63,
1648   /* 48 0 */ 52,
1649   /* 49 1 */ 53,
1650   /* 50 2 */ 54,
1651   /* 51 3 */ 55,
1652   /* 52 4 */ 56,
1653   /* 53 5 */ 57,
1654   /* 54 6 */ 58,
1655   /* 55 7 */ 59,
1656   /* 56 8 */ 60,
1657   /* 57 9 */ 61,
1658   /* 58 : */ -1,
1659   /* 59 ; */ -1,
1660   /* 60 < */ -1,
1661   /* 61 = */ -1,
1662   /* 62 > */ -1,
1663   /* 63 ? */ -1,
1664   /* 64 @ */ -1,
1665   /* 65 A */ 0,
1666   /* 66 B */ 1,
1667   /* 67 C */ 2,
1668   /* 68 D */ 3,
1669   /* 69 E */ 4,
1670   /* 70 F */ 5,
1671   /* 71 G */ 6,
1672   /* 72 H */ 7,
1673   /* 73 I */ 8,
1674   /* 74 J */ 9,
1675   /* 75 K */ 10,
1676   /* 76 L */ 11,
1677   /* 77 M */ 12,
1678   /* 78 N */ 13,
1679   /* 79 O */ 14,
1680   /* 80 P */ 15,
1681   /* 81 Q */ 16,
1682   /* 82 R */ 17,
1683   /* 83 S */ 18,
1684   /* 84 T */ 19,
1685   /* 85 U */ 20,
1686   /* 86 V */ 21,
1687   /* 87 W */ 22,
1688   /* 88 X */ 23,
1689   /* 89 Y */ 24,
1690   /* 90 Z */ 25,
1691   /* 91 [ */ -1,
1692   /* 92 \ */ -1,
1693   /* 93 ] */ -1,
1694   /* 94 ^ */ -1,
1695   /* 95 _ */ -1,
1696   /* 96 ` */ -1,
1697   /* 97 a */ 26,
1698   /* 98 b */ 27,
1699   /* 99 c */ 28,
1700   /* 100 d */ 29,
1701   /* 101 e */ 30,
1702   /* 102 f */ 31,
1703   /* 103 g */ 32,
1704   /* 104 h */ 33,
1705   /* 105 i */ 34,
1706   /* 106 j */ 35,
1707   /* 107 k */ 36,
1708   /* 108 l */ 37,
1709   /* 109 m */ 38,
1710   /* 110 n */ 39,
1711   /* 111 o */ 40,
1712   /* 112 p */ 41,
1713   /* 113 q */ 42,
1714   /* 114 r */ 43,
1715   /* 115 s */ 44,
1716   /* 116 t */ 45,
1717   /* 117 u */ 46,
1718   /* 118 v */ 47,
1719   /* 119 w */ 48,
1720   /* 120 x */ 49,
1721   /* 121 y */ 50,
1722   /* 122 z */ 51
1723 };
1724
1725 /**
1726  * Encodes a string using Base64, as documented in RFC 2045.
1727  *
1728  * @param source the string to encode
1729  * @param start byte index to start encoding
1730  * @param dest string where encoded data should be placed
1731  * @param insert_at where to place encoded data
1732  * @returns #TRUE if encoding was successful, #FALSE if no memory etc.
1733  */
1734 dbus_bool_t
1735 _dbus_string_base64_encode (const DBusString *source,
1736                             int               start,
1737                             DBusString       *dest,
1738                             int               insert_at)
1739 {
1740   int source_len;
1741   int dest_len;
1742   const unsigned char *s;
1743   unsigned char *d;
1744   const unsigned char *triplet_end;
1745   const unsigned char *final_end;
1746   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);  
1747   _dbus_assert (source != dest);
1748   
1749   /* For each 24 bits (3 bytes) of input, we have 4 chars of
1750    * output.
1751    */
1752   source_len = real_source->len - start;
1753   dest_len = (source_len / 3) * 4;
1754   if (source_len % 3 != 0)
1755     dest_len += 4;
1756
1757   if (source_len == 0)
1758     return TRUE;
1759   
1760   if (!open_gap (dest_len, real_dest, insert_at))
1761     return FALSE;
1762
1763   d = real_dest->str + insert_at;
1764   s = real_source->str + start;
1765   final_end = real_source->str + (start + source_len);
1766   triplet_end = final_end - (source_len % 3);
1767   _dbus_assert (triplet_end <= final_end);
1768   _dbus_assert ((final_end - triplet_end) < 3);
1769
1770 #define ENCODE_64(v) (base64_table[ (unsigned char) (v) ])
1771 #define SIX_BITS_MASK (0x3f)
1772   _dbus_assert (SIX_BITS_MASK < _DBUS_N_ELEMENTS (base64_table));
1773   
1774   while (s != triplet_end)
1775     {
1776       unsigned int triplet;
1777
1778       triplet = s[2] | (s[1] << 8) | (s[0] << 16);
1779
1780       /* Encode each 6 bits. */
1781
1782       *d++ = ENCODE_64 (triplet >> 18);
1783       *d++ = ENCODE_64 ((triplet >> 12) & SIX_BITS_MASK);
1784       *d++ = ENCODE_64 ((triplet >> 6) & SIX_BITS_MASK);
1785       *d++ = ENCODE_64 (triplet & SIX_BITS_MASK);
1786       
1787       s += 3;
1788     }
1789
1790   switch (final_end - triplet_end)
1791     {
1792     case 2:
1793       {
1794         unsigned int doublet;
1795         
1796         doublet = s[1] | (s[0] << 8);        
1797
1798         *d++ = ENCODE_64 (doublet >> 12);
1799         *d++ = ENCODE_64 ((doublet >> 6) & SIX_BITS_MASK);
1800         *d++ = ENCODE_64 (doublet & SIX_BITS_MASK);
1801         *d++ = '=';
1802       }
1803       break;
1804     case 1:
1805       {
1806         unsigned int singlet;
1807         
1808         singlet = s[0];
1809
1810         *d++ = ENCODE_64 ((singlet >> 6) & SIX_BITS_MASK);
1811         *d++ = ENCODE_64 (singlet & SIX_BITS_MASK);
1812         *d++ = '=';
1813         *d++ = '=';
1814       }
1815       break;
1816     case 0:
1817       break;
1818     }
1819
1820   _dbus_assert (d == (real_dest->str + (insert_at + dest_len)));
1821
1822   return TRUE;
1823 }
1824
1825
1826 /**
1827  * Decodes a string from Base64, as documented in RFC 2045.
1828  *
1829  * @param source the string to decode
1830  * @param start byte index to start decode
1831  * @param dest string where decoded data should be placed
1832  * @param insert_at where to place decoded data
1833  * @returns #TRUE if decoding was successful, #FALSE if no memory etc.
1834  */
1835 dbus_bool_t
1836 _dbus_string_base64_decode (const DBusString *source,
1837                             int               start,
1838                             DBusString       *dest,
1839                             int               insert_at)
1840 {
1841   int source_len;
1842   const char *s;
1843   const char *end;
1844   DBusString result;
1845   unsigned int triplet = 0;
1846   int sextet_count;
1847   int pad_count;
1848   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
1849   _dbus_assert (source != dest);
1850   
1851   source_len = real_source->len - start;
1852   s = real_source->str + start;
1853   end = real_source->str + source_len;
1854
1855   if (source_len == 0)
1856     return TRUE;
1857
1858   if (!_dbus_string_init (&result, _DBUS_INT_MAX))
1859     return FALSE;
1860
1861   pad_count = 0;
1862   sextet_count = 0;
1863   while (s != end)
1864     {
1865       /* The idea is to just skip anything that isn't
1866        * a base64 char - it's allowed to have whitespace,
1867        * newlines, etc. in here. We also ignore trailing
1868        * base64 chars, though that's suspicious.
1869        */
1870       
1871       if (*s >= UNBASE64_MIN_CHAR &&
1872           *s <= UNBASE64_MAX_CHAR)
1873         {
1874           if (*s == '=')
1875             {
1876               /* '=' is padding, doesn't represent additional data
1877                * but does increment our count.
1878                */
1879               pad_count += 1;
1880               sextet_count += 1;
1881             }
1882           else
1883             {
1884               int val;
1885
1886               val = unbase64_table[(*s) - UNBASE64_TABLE_OFFSET];
1887
1888               if (val >= 0)
1889                 {
1890                   triplet <<= 6;
1891                   triplet |= (unsigned int) val;
1892                   sextet_count += 1;
1893                 }
1894             }
1895
1896           if (sextet_count == 4)
1897             {
1898               /* no pad = 3 bytes, 1 pad = 2 bytes, 2 pad = 1 byte */
1899               if (pad_count < 1)
1900                 _dbus_string_append_byte (&result,
1901                                           triplet >> 16);
1902               
1903               if (pad_count < 2)
1904                 _dbus_string_append_byte (&result,
1905                                           (triplet >> 8) & 0xff);              
1906               
1907               _dbus_string_append_byte (&result,
1908                                         triplet & 0xff);
1909               
1910               sextet_count = 0;
1911               pad_count = 0;
1912               triplet = 0;
1913             }
1914         }
1915       
1916       ++s;
1917     }
1918
1919   if (!_dbus_string_move (&result, 0, dest, insert_at))
1920     {
1921       _dbus_string_free (&result);
1922       return FALSE;
1923     }
1924
1925   _dbus_string_free (&result);
1926
1927   return TRUE;
1928 }
1929
1930 /**
1931  * Checks that the given range of the string
1932  * is valid ASCII. If the given range is not contained
1933  * in the string, returns #FALSE.
1934  *
1935  * @param str the string
1936  * @param start first byte index to check
1937  * @param len number of bytes to check
1938  * @returns #TRUE if the byte range exists and is all valid ASCII
1939  */
1940 dbus_bool_t
1941 _dbus_string_validate_ascii (const DBusString *str,
1942                              int               start,
1943                              int               len)
1944 {
1945   const unsigned char *s;
1946   const unsigned char *end;
1947   DBUS_CONST_STRING_PREAMBLE (str);
1948   _dbus_assert (start >= 0);
1949   _dbus_assert (len >= 0);
1950   
1951   if ((start + len) > real->len)
1952     return FALSE;
1953   
1954   s = real->str + start;
1955   end = s + len;
1956   while (s != end)
1957     {
1958       if (*s == '\0' ||
1959           ((*s & ~0x7f) != 0))
1960         return FALSE;
1961         
1962       ++s;
1963     }
1964   
1965   return TRUE;
1966 }
1967
1968 /**
1969  * Checks that the given range of the string
1970  * is valid UTF-8. If the given range is not contained
1971  * in the string, returns #FALSE. If the string
1972  * contains any nul bytes in the given range, returns
1973  * #FALSE.
1974  *
1975  * @todo right now just calls _dbus_string_validate_ascii()
1976  * 
1977  * @param str the string
1978  * @param start first byte index to check
1979  * @param len number of bytes to check
1980  * @returns #TRUE if the byte range exists and is all valid UTF-8
1981  */
1982 dbus_bool_t
1983 _dbus_string_validate_utf8  (const DBusString *str,
1984                              int               start,
1985                              int               len)
1986 {
1987   /* FIXME actually validate UTF-8 */
1988   return _dbus_string_validate_ascii (str, start, len);
1989 }
1990
1991 /**
1992  * Checks that the given range of the string
1993  * is all nul bytes. If the given range is
1994  * not contained in the string, returns #FALSE.
1995  * 
1996  * @param str the string
1997  * @param start first byte index to check
1998  * @param len number of bytes to check
1999  * @returns #TRUE if the byte range exists and is all nul bytes
2000  */
2001 dbus_bool_t
2002 _dbus_string_validate_nul (const DBusString *str,
2003                            int               start,
2004                            int               len)
2005 {
2006   const unsigned char *s;
2007   const unsigned char *end;
2008   DBUS_CONST_STRING_PREAMBLE (str);
2009   _dbus_assert (start >= 0);
2010   _dbus_assert (len >= 0);
2011   
2012   if ((start + len) > real->len)
2013     return FALSE;
2014   
2015   s = real->str + start;
2016   end = s + len;
2017   while (s != end)
2018     {
2019       if (*s != '\0')
2020         return FALSE;
2021       ++s;
2022     }
2023   
2024   return TRUE;
2025 }
2026
2027 /** @} */
2028
2029 #ifdef DBUS_BUILD_TESTS
2030 #include "dbus-test.h"
2031 #include <stdio.h>
2032
2033 static void
2034 test_max_len (DBusString *str,
2035               int         max_len)
2036 {
2037   if (max_len > 0)
2038     {
2039       if (!_dbus_string_set_length (str, max_len - 1))
2040         _dbus_assert_not_reached ("setting len to one less than max should have worked");
2041     }
2042
2043   if (!_dbus_string_set_length (str, max_len))
2044     _dbus_assert_not_reached ("setting len to max len should have worked");
2045
2046   if (_dbus_string_set_length (str, max_len + 1))
2047     _dbus_assert_not_reached ("setting len to one more than max len should not have worked");
2048
2049   if (!_dbus_string_set_length (str, 0))
2050     _dbus_assert_not_reached ("setting len to zero should have worked");
2051 }
2052
2053 static void
2054 test_base64_roundtrip (const unsigned char *data,
2055                        int                  len)
2056 {
2057   DBusString orig;
2058   DBusString encoded;
2059   DBusString decoded;
2060
2061   if (len < 0)
2062     len = strlen (data);
2063   
2064   if (!_dbus_string_init (&orig, _DBUS_INT_MAX))
2065     _dbus_assert_not_reached ("could not init string");
2066
2067   if (!_dbus_string_init (&encoded, _DBUS_INT_MAX))
2068     _dbus_assert_not_reached ("could not init string");
2069   
2070   if (!_dbus_string_init (&decoded, _DBUS_INT_MAX))
2071     _dbus_assert_not_reached ("could not init string");
2072
2073   if (!_dbus_string_append_len (&orig, data, len))
2074     _dbus_assert_not_reached ("couldn't append orig data");
2075
2076   if (!_dbus_string_base64_encode (&orig, 0, &encoded, 0))
2077     _dbus_assert_not_reached ("could not encode");
2078
2079   if (!_dbus_string_base64_decode (&encoded, 0, &decoded, 0))
2080     _dbus_assert_not_reached ("could not decode");
2081
2082   if (!_dbus_string_equal (&orig, &decoded))
2083     {
2084       const char *s;
2085       
2086       printf ("Original string %d bytes encoded %d bytes decoded %d bytes\n",
2087               _dbus_string_get_length (&orig),
2088               _dbus_string_get_length (&encoded),
2089               _dbus_string_get_length (&decoded));
2090       printf ("Original: %s\n", data);
2091       _dbus_string_get_const_data (&decoded, &s);
2092       printf ("Decoded: %s\n", s);
2093       _dbus_assert_not_reached ("original string not the same as string decoded from base64");
2094     }
2095   
2096   _dbus_string_free (&orig);
2097   _dbus_string_free (&encoded);
2098   _dbus_string_free (&decoded);  
2099 }
2100
2101 /**
2102  * @ingroup DBusStringInternals
2103  * Unit test for DBusString.
2104  *
2105  * @todo Need to write tests for _dbus_string_copy() and
2106  * _dbus_string_move() moving to/from each of start/middle/end of a
2107  * string. Also need tests for _dbus_string_move_len ()
2108  * 
2109  * @returns #TRUE on success.
2110  */
2111 dbus_bool_t
2112 _dbus_string_test (void)
2113 {
2114   DBusString str;
2115   DBusString other;
2116   int i, end;
2117   long v;
2118   double d;
2119   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 };
2120   char *s;
2121   dbus_unichar_t ch;
2122   
2123   i = 0;
2124   while (i < _DBUS_N_ELEMENTS (lens))
2125     {
2126       if (!_dbus_string_init (&str, lens[i]))
2127         _dbus_assert_not_reached ("failed to init string");
2128       
2129       test_max_len (&str, lens[i]);
2130       _dbus_string_free (&str);
2131
2132       ++i;
2133     }
2134
2135   /* Test shortening and setting length */
2136   i = 0;
2137   while (i < _DBUS_N_ELEMENTS (lens))
2138     {
2139       int j;
2140       
2141       if (!_dbus_string_init (&str, lens[i]))
2142         _dbus_assert_not_reached ("failed to init string");
2143       
2144       if (!_dbus_string_set_length (&str, lens[i]))
2145         _dbus_assert_not_reached ("failed to set string length");
2146
2147       j = lens[i];
2148       while (j > 0)
2149         {
2150           _dbus_assert (_dbus_string_get_length (&str) == j);
2151           if (j > 0)
2152             {
2153               _dbus_string_shorten (&str, 1);
2154               _dbus_assert (_dbus_string_get_length (&str) == (j - 1));
2155             }
2156           --j;
2157         }
2158       
2159       _dbus_string_free (&str);
2160
2161       ++i;
2162     }
2163
2164   /* Test appending data */
2165   if (!_dbus_string_init (&str, _DBUS_INT_MAX))
2166     _dbus_assert_not_reached ("failed to init string");
2167
2168   i = 0;
2169   while (i < 10)
2170     {
2171       if (!_dbus_string_append (&str, "a"))
2172         _dbus_assert_not_reached ("failed to append string to string\n");
2173
2174       _dbus_assert (_dbus_string_get_length (&str) == i * 2 + 1);
2175
2176       if (!_dbus_string_append_byte (&str, 'b'))
2177         _dbus_assert_not_reached ("failed to append byte to string\n");
2178
2179       _dbus_assert (_dbus_string_get_length (&str) == i * 2 + 2);
2180                     
2181       ++i;
2182     }
2183
2184   _dbus_string_free (&str);
2185
2186   /* Check steal_data */
2187   
2188   if (!_dbus_string_init (&str, _DBUS_INT_MAX))
2189     _dbus_assert_not_reached ("failed to init string");
2190
2191   if (!_dbus_string_append (&str, "Hello World"))
2192     _dbus_assert_not_reached ("could not append to string");
2193
2194   i = _dbus_string_get_length (&str);
2195   
2196   if (!_dbus_string_steal_data (&str, &s))
2197     _dbus_assert_not_reached ("failed to steal data");
2198
2199   _dbus_assert (_dbus_string_get_length (&str) == 0);
2200   _dbus_assert (((int)strlen (s)) == i);
2201
2202   dbus_free (s);
2203
2204   /* Check move */
2205   
2206   if (!_dbus_string_append (&str, "Hello World"))
2207     _dbus_assert_not_reached ("could not append to string");
2208
2209   i = _dbus_string_get_length (&str);
2210
2211   if (!_dbus_string_init (&other, _DBUS_INT_MAX))
2212     _dbus_assert_not_reached ("could not init string");
2213   
2214   if (!_dbus_string_move (&str, 0, &other, 0))
2215     _dbus_assert_not_reached ("could not move");
2216
2217   _dbus_assert (_dbus_string_get_length (&str) == 0);
2218   _dbus_assert (_dbus_string_get_length (&other) == i);
2219
2220   if (!_dbus_string_append (&str, "Hello World"))
2221     _dbus_assert_not_reached ("could not append to string");
2222   
2223   if (!_dbus_string_move (&str, 0, &other, _dbus_string_get_length (&other)))
2224     _dbus_assert_not_reached ("could not move");
2225
2226   _dbus_assert (_dbus_string_get_length (&str) == 0);
2227   _dbus_assert (_dbus_string_get_length (&other) == i * 2);
2228
2229     if (!_dbus_string_append (&str, "Hello World"))
2230     _dbus_assert_not_reached ("could not append to string");
2231   
2232   if (!_dbus_string_move (&str, 0, &other, _dbus_string_get_length (&other) / 2))
2233     _dbus_assert_not_reached ("could not move");
2234
2235   _dbus_assert (_dbus_string_get_length (&str) == 0);
2236   _dbus_assert (_dbus_string_get_length (&other) == i * 3);
2237   
2238   _dbus_string_free (&other);
2239
2240   /* Check copy */
2241   
2242   if (!_dbus_string_append (&str, "Hello World"))
2243     _dbus_assert_not_reached ("could not append to string");
2244
2245   i = _dbus_string_get_length (&str);
2246   
2247   if (!_dbus_string_init (&other, _DBUS_INT_MAX))
2248     _dbus_assert_not_reached ("could not init string");
2249   
2250   if (!_dbus_string_copy (&str, 0, &other, 0))
2251     _dbus_assert_not_reached ("could not copy");
2252
2253   _dbus_assert (_dbus_string_get_length (&str) == i);
2254   _dbus_assert (_dbus_string_get_length (&other) == i);
2255
2256   if (!_dbus_string_copy (&str, 0, &other, _dbus_string_get_length (&other)))
2257     _dbus_assert_not_reached ("could not copy");
2258
2259   _dbus_assert (_dbus_string_get_length (&str) == i);
2260   _dbus_assert (_dbus_string_get_length (&other) == i * 2);
2261   _dbus_assert (_dbus_string_equal_c_str (&other,
2262                                           "Hello WorldHello World"));
2263
2264   if (!_dbus_string_copy (&str, 0, &other, _dbus_string_get_length (&other) / 2))
2265     _dbus_assert_not_reached ("could not copy");
2266
2267   _dbus_assert (_dbus_string_get_length (&str) == i);
2268   _dbus_assert (_dbus_string_get_length (&other) == i * 3);
2269   _dbus_assert (_dbus_string_equal_c_str (&other,
2270                                           "Hello WorldHello WorldHello World"));
2271   
2272   _dbus_string_free (&str);
2273   _dbus_string_free (&other);
2274
2275   /* Check replace */
2276
2277   if (!_dbus_string_init (&str, _DBUS_INT_MAX))
2278     _dbus_assert_not_reached ("failed to init string");
2279   
2280   if (!_dbus_string_append (&str, "Hello World"))
2281     _dbus_assert_not_reached ("could not append to string");
2282
2283   i = _dbus_string_get_length (&str);
2284   
2285   if (!_dbus_string_init (&other, _DBUS_INT_MAX))
2286     _dbus_assert_not_reached ("could not init string");
2287   
2288   if (!_dbus_string_replace_len (&str, 0, _dbus_string_get_length (&str),
2289                                  &other, 0, _dbus_string_get_length (&other)))
2290     _dbus_assert_not_reached ("could not replace");
2291
2292   _dbus_assert (_dbus_string_get_length (&str) == i);
2293   _dbus_assert (_dbus_string_get_length (&other) == i);
2294   _dbus_assert (_dbus_string_equal_c_str (&other, "Hello World"));
2295   
2296   if (!_dbus_string_replace_len (&str, 0, _dbus_string_get_length (&str),
2297                                  &other, 5, 1))
2298     _dbus_assert_not_reached ("could not replace center space");
2299
2300   _dbus_assert (_dbus_string_get_length (&str) == i);
2301   _dbus_assert (_dbus_string_get_length (&other) == i * 2 - 1);
2302   _dbus_assert (_dbus_string_equal_c_str (&other,
2303                                           "HelloHello WorldWorld"));
2304
2305   
2306   if (!_dbus_string_replace_len (&str, 1, 1,
2307                                  &other,
2308                                  _dbus_string_get_length (&other) - 1,
2309                                  1))
2310     _dbus_assert_not_reached ("could not replace end character");
2311   
2312   _dbus_assert (_dbus_string_get_length (&str) == i);
2313   _dbus_assert (_dbus_string_get_length (&other) == i * 2 - 1);
2314   _dbus_assert (_dbus_string_equal_c_str (&other,
2315                                           "HelloHello WorldWorle"));
2316   
2317   _dbus_string_free (&str);
2318   _dbus_string_free (&other);
2319   
2320   /* Check append/get unichar */
2321   
2322   if (!_dbus_string_init (&str, _DBUS_INT_MAX))
2323     _dbus_assert_not_reached ("failed to init string");
2324
2325   ch = 0;
2326   if (!_dbus_string_append_unichar (&str, 0xfffc))
2327     _dbus_assert_not_reached ("failed to append unichar");
2328
2329   _dbus_string_get_unichar (&str, 0, &ch, &i);
2330
2331   _dbus_assert (ch == 0xfffc);
2332   _dbus_assert (i == _dbus_string_get_length (&str));
2333
2334   _dbus_string_free (&str);
2335
2336   /* Check insert/set/get byte */
2337   
2338   if (!_dbus_string_init (&str, _DBUS_INT_MAX))
2339     _dbus_assert_not_reached ("failed to init string");
2340
2341   if (!_dbus_string_append (&str, "Hello"))
2342     _dbus_assert_not_reached ("failed to append Hello");
2343
2344   _dbus_assert (_dbus_string_get_byte (&str, 0) == 'H');
2345   _dbus_assert (_dbus_string_get_byte (&str, 1) == 'e');
2346   _dbus_assert (_dbus_string_get_byte (&str, 2) == 'l');
2347   _dbus_assert (_dbus_string_get_byte (&str, 3) == 'l');
2348   _dbus_assert (_dbus_string_get_byte (&str, 4) == 'o');
2349
2350   _dbus_string_set_byte (&str, 1, 'q');
2351   _dbus_assert (_dbus_string_get_byte (&str, 1) == 'q');
2352
2353   if (!_dbus_string_insert_byte (&str, 0, 255))
2354     _dbus_assert_not_reached ("can't insert byte");
2355
2356   if (!_dbus_string_insert_byte (&str, 2, 'Z'))
2357     _dbus_assert_not_reached ("can't insert byte");
2358
2359   if (!_dbus_string_insert_byte (&str, _dbus_string_get_length (&str), 'W'))
2360     _dbus_assert_not_reached ("can't insert byte");
2361   
2362   _dbus_assert (_dbus_string_get_byte (&str, 0) == 255);
2363   _dbus_assert (_dbus_string_get_byte (&str, 1) == 'H');
2364   _dbus_assert (_dbus_string_get_byte (&str, 2) == 'Z');
2365   _dbus_assert (_dbus_string_get_byte (&str, 3) == 'q');
2366   _dbus_assert (_dbus_string_get_byte (&str, 4) == 'l');
2367   _dbus_assert (_dbus_string_get_byte (&str, 5) == 'l');
2368   _dbus_assert (_dbus_string_get_byte (&str, 6) == 'o');
2369   _dbus_assert (_dbus_string_get_byte (&str, 7) == 'W');
2370
2371   _dbus_string_free (&str);
2372   
2373   /* Check append/parse int/double */
2374   
2375   if (!_dbus_string_init (&str, _DBUS_INT_MAX))
2376     _dbus_assert_not_reached ("failed to init string");
2377
2378   if (!_dbus_string_append_int (&str, 27))
2379     _dbus_assert_not_reached ("failed to append int");
2380
2381   i = _dbus_string_get_length (&str);
2382
2383   if (!_dbus_string_parse_int (&str, 0, &v, &end))
2384     _dbus_assert_not_reached ("failed to parse int");
2385
2386   _dbus_assert (v == 27);
2387   _dbus_assert (end == i);
2388
2389   _dbus_string_free (&str);
2390   
2391   if (!_dbus_string_init (&str, _DBUS_INT_MAX))
2392     _dbus_assert_not_reached ("failed to init string");
2393   
2394   if (!_dbus_string_append_double (&str, 50.3))
2395     _dbus_assert_not_reached ("failed to append float");
2396
2397   i = _dbus_string_get_length (&str);
2398
2399   if (!_dbus_string_parse_double (&str, 0, &d, &end))
2400     _dbus_assert_not_reached ("failed to parse float");
2401
2402   _dbus_assert (d > (50.3 - 1e-6) && d < (50.3 + 1e-6));
2403   _dbus_assert (end == i);
2404
2405   _dbus_string_free (&str);
2406
2407   /* Test find */
2408   if (!_dbus_string_init (&str, _DBUS_INT_MAX))
2409     _dbus_assert_not_reached ("failed to init string");
2410
2411   if (!_dbus_string_append (&str, "Hello"))
2412     _dbus_assert_not_reached ("couldn't append to string");
2413   
2414   if (!_dbus_string_find (&str, 0, "He", &i))
2415     _dbus_assert_not_reached ("didn't find 'He'");
2416   _dbus_assert (i == 0);
2417
2418   if (!_dbus_string_find (&str, 0, "ello", &i))
2419     _dbus_assert_not_reached ("didn't find 'ello'");
2420   _dbus_assert (i == 1);
2421
2422   if (!_dbus_string_find (&str, 0, "lo", &i))
2423     _dbus_assert_not_reached ("didn't find 'lo'");
2424   _dbus_assert (i == 3);
2425
2426   if (!_dbus_string_find (&str, 2, "lo", &i))
2427     _dbus_assert_not_reached ("didn't find 'lo'");
2428   _dbus_assert (i == 3);
2429
2430   if (_dbus_string_find (&str, 4, "lo", &i))
2431     _dbus_assert_not_reached ("did find 'lo'");
2432   
2433   if (!_dbus_string_find (&str, 0, "l", &i))
2434     _dbus_assert_not_reached ("didn't find 'l'");
2435   _dbus_assert (i == 2);
2436
2437   if (!_dbus_string_find (&str, 0, "H", &i))
2438     _dbus_assert_not_reached ("didn't find 'H'");
2439   _dbus_assert (i == 0);
2440
2441   if (!_dbus_string_find (&str, 0, "", &i))
2442     _dbus_assert_not_reached ("didn't find ''");
2443   _dbus_assert (i == 0);
2444   
2445   if (_dbus_string_find (&str, 0, "Hello!", NULL))
2446     _dbus_assert_not_reached ("Did find 'Hello!'");
2447
2448   if (_dbus_string_find (&str, 0, "Oh, Hello", NULL))
2449     _dbus_assert_not_reached ("Did find 'Oh, Hello'");
2450   
2451   if (_dbus_string_find (&str, 0, "ill", NULL))
2452     _dbus_assert_not_reached ("Did find 'ill'");
2453
2454   if (_dbus_string_find (&str, 0, "q", NULL))
2455     _dbus_assert_not_reached ("Did find 'q'");
2456
2457   if (!_dbus_string_find_to (&str, 0, 2, "He", NULL))
2458     _dbus_assert_not_reached ("Didn't find 'He'");
2459
2460   if (_dbus_string_find_to (&str, 0, 2, "Hello", NULL))
2461     _dbus_assert_not_reached ("Did find 'Hello'");
2462   
2463   _dbus_string_free (&str);
2464
2465   /* Base 64 */
2466   test_base64_roundtrip ("Hello this is a string\n", -1);
2467   test_base64_roundtrip ("Hello this is a string\n1", -1);
2468   test_base64_roundtrip ("Hello this is a string\n12", -1);
2469   test_base64_roundtrip ("Hello this is a string\n123", -1);
2470   test_base64_roundtrip ("Hello this is a string\n1234", -1);
2471   test_base64_roundtrip ("Hello this is a string\n12345", -1);
2472   test_base64_roundtrip ("", 0);
2473   test_base64_roundtrip ("1", 1);
2474   test_base64_roundtrip ("12", 2);
2475   test_base64_roundtrip ("123", 3);
2476   test_base64_roundtrip ("1234", 4);
2477   test_base64_roundtrip ("12345", 5);
2478   test_base64_roundtrip ("", 1);
2479   test_base64_roundtrip ("1", 2);
2480   test_base64_roundtrip ("12", 3);
2481   test_base64_roundtrip ("123", 4);
2482   test_base64_roundtrip ("1234", 5);
2483   test_base64_roundtrip ("12345", 6);
2484   {
2485     unsigned char buf[512];
2486     i = 0;
2487     while (i < _DBUS_N_ELEMENTS (buf))
2488       {
2489         buf[i] = i;
2490         ++i;
2491       }
2492     i = 0;
2493     while (i < _DBUS_N_ELEMENTS (buf))
2494       {
2495         test_base64_roundtrip (buf, i);
2496         ++i;
2497       }
2498   }
2499   
2500   return TRUE;
2501 }
2502
2503 #endif /* DBUS_BUILD_TESTS */