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