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