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