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