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