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