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