add int64 to test suites, fix minor bug where marshaling assumed that DBusOctets8...
[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   _dbus_assert (_DBUS_ALIGN_VALUE (insert_at, 8) == (unsigned) insert_at);
1152   
1153   ASSIGN_8_OCTETS (real->str + insert_at, octets);
1154
1155   return TRUE;
1156 }
1157
1158 /**
1159  * Appends a printf-style formatted string
1160  * to the #DBusString.
1161  *
1162  * @param str the string
1163  * @param format printf format
1164  * @param args variable argument list
1165  * @returns #FALSE if no memory
1166  */
1167 dbus_bool_t
1168 _dbus_string_append_printf_valist  (DBusString        *str,
1169                                     const char        *format,
1170                                     va_list            args)
1171 {
1172   int len;
1173   char c;
1174   va_list args_copy;
1175
1176   DBUS_STRING_PREAMBLE (str);
1177
1178   DBUS_VA_COPY (args_copy, args);
1179
1180   /* Measure the message length without terminating nul */
1181   len = vsnprintf (&c, 1, format, args);
1182
1183   if (!_dbus_string_lengthen (str, len))
1184     {
1185       /* don't leak the copy */
1186       va_end (args_copy);
1187       return FALSE;
1188     }
1189   
1190   vsprintf (real->str + (real->len - len),
1191             format, args_copy);
1192
1193   va_end (args_copy);
1194
1195   return TRUE;
1196 }
1197
1198 /**
1199  * Appends a printf-style formatted string
1200  * to the #DBusString.
1201  *
1202  * @param str the string
1203  * @param format printf format
1204  * @returns #FALSE if no memory
1205  */
1206 dbus_bool_t
1207 _dbus_string_append_printf (DBusString        *str,
1208                             const char        *format,
1209                             ...)
1210 {
1211   va_list args;
1212   dbus_bool_t retval;
1213   
1214   va_start (args, format);
1215   retval = _dbus_string_append_printf_valist (str, format, args);
1216   va_end (args);
1217
1218   return retval;
1219 }
1220
1221 /**
1222  * Appends block of bytes with the given length to a DBusString.
1223  *
1224  * @param str the DBusString
1225  * @param buffer the bytes to append
1226  * @param len the number of bytes to append
1227  * @returns #FALSE if not enough memory.
1228  */
1229 dbus_bool_t
1230 _dbus_string_append_len (DBusString *str,
1231                          const char *buffer,
1232                          int         len)
1233 {
1234   DBUS_STRING_PREAMBLE (str);
1235   _dbus_assert (buffer != NULL);
1236   _dbus_assert (len >= 0);
1237
1238   return append (real, buffer, len);
1239 }
1240
1241 /**
1242  * Appends a single byte to the string, returning #FALSE
1243  * if not enough memory.
1244  *
1245  * @param str the string
1246  * @param byte the byte to append
1247  * @returns #TRUE on success
1248  */
1249 dbus_bool_t
1250 _dbus_string_append_byte (DBusString    *str,
1251                           unsigned char  byte)
1252 {
1253   DBUS_STRING_PREAMBLE (str);
1254
1255   if (!set_length (real, real->len + 1))
1256     return FALSE;
1257
1258   real->str[real->len-1] = byte;
1259
1260   return TRUE;
1261 }
1262
1263 /**
1264  * Appends a single Unicode character, encoding the character
1265  * in UTF-8 format.
1266  *
1267  * @param str the string
1268  * @param ch the Unicode character
1269  */
1270 dbus_bool_t
1271 _dbus_string_append_unichar (DBusString    *str,
1272                              dbus_unichar_t ch)
1273 {
1274   int len;
1275   int first;
1276   int i;
1277   char *out;
1278   
1279   DBUS_STRING_PREAMBLE (str);
1280
1281   /* this code is from GLib but is pretty standard I think */
1282   
1283   len = 0;
1284   
1285   if (ch < 0x80)
1286     {
1287       first = 0;
1288       len = 1;
1289     }
1290   else if (ch < 0x800)
1291     {
1292       first = 0xc0;
1293       len = 2;
1294     }
1295   else if (ch < 0x10000)
1296     {
1297       first = 0xe0;
1298       len = 3;
1299     }
1300    else if (ch < 0x200000)
1301     {
1302       first = 0xf0;
1303       len = 4;
1304     }
1305   else if (ch < 0x4000000)
1306     {
1307       first = 0xf8;
1308       len = 5;
1309     }
1310   else
1311     {
1312       first = 0xfc;
1313       len = 6;
1314     }
1315
1316   if (len > (real->max_length - real->len))
1317     return FALSE; /* real->len + len would overflow */
1318   
1319   if (!set_length (real, real->len + len))
1320     return FALSE;
1321
1322   out = real->str + (real->len - len);
1323   
1324   for (i = len - 1; i > 0; --i)
1325     {
1326       out[i] = (ch & 0x3f) | 0x80;
1327       ch >>= 6;
1328     }
1329   out[0] = ch | first;
1330
1331   return TRUE;
1332 }
1333
1334 static void
1335 delete (DBusRealString *real,
1336         int             start,
1337         int             len)
1338 {
1339   if (len == 0)
1340     return;
1341   
1342   memmove (real->str + start, real->str + start + len, real->len - (start + len));
1343   real->len -= len;
1344   real->str[real->len] = '\0';
1345 }
1346
1347 /**
1348  * Deletes a segment of a DBusString with length len starting at
1349  * start. (Hint: to clear an entire string, setting length to 0
1350  * with _dbus_string_set_length() is easier.)
1351  *
1352  * @param str the DBusString
1353  * @param start where to start deleting
1354  * @param len the number of bytes to delete
1355  */
1356 void
1357 _dbus_string_delete (DBusString       *str,
1358                      int               start,
1359                      int               len)
1360 {
1361   DBUS_STRING_PREAMBLE (str);
1362   _dbus_assert (start >= 0);
1363   _dbus_assert (len >= 0);
1364   _dbus_assert (start <= real->len);
1365   _dbus_assert (len <= real->len - start);
1366   
1367   delete (real, start, len);
1368 }
1369
1370 static dbus_bool_t
1371 copy (DBusRealString *source,
1372       int             start,
1373       int             len,
1374       DBusRealString *dest,
1375       int             insert_at)
1376 {
1377   if (len == 0)
1378     return TRUE;
1379
1380   if (!open_gap (len, dest, insert_at))
1381     return FALSE;
1382   
1383   memcpy (dest->str + insert_at,
1384           source->str + start,
1385           len);
1386
1387   return TRUE;
1388 }
1389
1390 /**
1391  * Checks assertions for two strings we're copying a segment between,
1392  * and declares real_source/real_dest variables.
1393  *
1394  * @param source the source string
1395  * @param start the starting offset
1396  * @param dest the dest string
1397  * @param insert_at where the copied segment is inserted
1398  */
1399 #define DBUS_STRING_COPY_PREAMBLE(source, start, dest, insert_at)       \
1400   DBusRealString *real_source = (DBusRealString*) source;               \
1401   DBusRealString *real_dest = (DBusRealString*) dest;                   \
1402   _dbus_assert ((source) != (dest));                                    \
1403   DBUS_GENERIC_STRING_PREAMBLE (real_source);                           \
1404   DBUS_GENERIC_STRING_PREAMBLE (real_dest);                             \
1405   _dbus_assert (!real_dest->constant);                                  \
1406   _dbus_assert (!real_dest->locked);                                    \
1407   _dbus_assert ((start) >= 0);                                          \
1408   _dbus_assert ((start) <= real_source->len);                           \
1409   _dbus_assert ((insert_at) >= 0);                                      \
1410   _dbus_assert ((insert_at) <= real_dest->len)
1411
1412 /**
1413  * Moves the end of one string into another string. Both strings
1414  * must be initialized, valid strings.
1415  *
1416  * @param source the source string
1417  * @param start where to chop off the source string
1418  * @param dest the destination string
1419  * @param insert_at where to move the chopped-off part of source string
1420  * @returns #FALSE if not enough memory
1421  */
1422 dbus_bool_t
1423 _dbus_string_move (DBusString       *source,
1424                    int               start,
1425                    DBusString       *dest,
1426                    int               insert_at)
1427 {
1428   DBusRealString *real_source = (DBusRealString*) source;
1429   _dbus_assert (start <= real_source->len);
1430   
1431   return _dbus_string_move_len (source, start,
1432                                 real_source->len - start,
1433                                 dest, insert_at);
1434 }
1435
1436 /**
1437  * Like _dbus_string_move(), but does not delete the section
1438  * of the source string that's copied to the dest string.
1439  *
1440  * @param source the source string
1441  * @param start where to start copying the source string
1442  * @param dest the destination string
1443  * @param insert_at where to place the copied part of source string
1444  * @returns #FALSE if not enough memory
1445  */
1446 dbus_bool_t
1447 _dbus_string_copy (const DBusString *source,
1448                    int               start,
1449                    DBusString       *dest,
1450                    int               insert_at)
1451 {
1452   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
1453
1454   return copy (real_source, start,
1455                real_source->len - start,
1456                real_dest,
1457                insert_at);
1458 }
1459
1460 /**
1461  * Like _dbus_string_move(), but can move a segment from
1462  * the middle of the source string.
1463  *
1464  * @todo this doesn't do anything with max_length field.
1465  * we should probably just kill the max_length field though.
1466  * 
1467  * @param source the source string
1468  * @param start first byte of source string to move
1469  * @param len length of segment to move
1470  * @param dest the destination string
1471  * @param insert_at where to move the bytes from the source string
1472  * @returns #FALSE if not enough memory
1473  */
1474 dbus_bool_t
1475 _dbus_string_move_len (DBusString       *source,
1476                        int               start,
1477                        int               len,
1478                        DBusString       *dest,
1479                        int               insert_at)
1480
1481 {
1482   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
1483   _dbus_assert (len >= 0);
1484   _dbus_assert ((start + len) <= real_source->len);
1485
1486
1487   if (len == 0)
1488     {
1489       return TRUE;
1490     }
1491   else if (start == 0 &&
1492            len == real_source->len &&
1493            real_dest->len == 0)
1494     {
1495       /* Short-circuit moving an entire existing string to an empty string
1496        * by just swapping the buffers.
1497        */
1498       /* we assume ->constant doesn't matter as you can't have
1499        * a constant string involved in a move.
1500        */
1501 #define ASSIGN_DATA(a, b) do {                  \
1502         (a)->str = (b)->str;                    \
1503         (a)->len = (b)->len;                    \
1504         (a)->allocated = (b)->allocated;        \
1505         (a)->align_offset = (b)->align_offset;  \
1506       } while (0)
1507       
1508       DBusRealString tmp;
1509
1510       ASSIGN_DATA (&tmp, real_source);
1511       ASSIGN_DATA (real_source, real_dest);
1512       ASSIGN_DATA (real_dest, &tmp);
1513
1514       return TRUE;
1515     }
1516   else
1517     {
1518       if (!copy (real_source, start, len,
1519                  real_dest,
1520                  insert_at))
1521         return FALSE;
1522       
1523       delete (real_source, start,
1524               len);
1525       
1526       return TRUE;
1527     }
1528 }
1529
1530 /**
1531  * Like _dbus_string_copy(), but can copy a segment from the middle of
1532  * the source string.
1533  *
1534  * @param source the source string
1535  * @param start where to start copying the source string
1536  * @param len length of segment to copy
1537  * @param dest the destination string
1538  * @param insert_at where to place the copied segment of source string
1539  * @returns #FALSE if not enough memory
1540  */
1541 dbus_bool_t
1542 _dbus_string_copy_len (const DBusString *source,
1543                        int               start,
1544                        int               len,
1545                        DBusString       *dest,
1546                        int               insert_at)
1547 {
1548   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
1549   _dbus_assert (len >= 0);
1550   _dbus_assert (start <= real_source->len);
1551   _dbus_assert (len <= real_source->len - start);
1552   
1553   return copy (real_source, start, len,
1554                real_dest,
1555                insert_at);
1556 }
1557
1558 /**
1559  * Replaces a segment of dest string with a segment of source string.
1560  *
1561  * @todo optimize the case where the two lengths are the same, and
1562  * avoid memmoving the data in the trailing part of the string twice.
1563  *
1564  * @todo avoid inserting the source into dest, then deleting
1565  * the replaced chunk of dest (which creates a potentially large
1566  * intermediate string). Instead, extend the replaced chunk
1567  * of dest with padding to the same size as the source chunk,
1568  * then copy in the source bytes.
1569  * 
1570  * @param source the source string
1571  * @param start where to start copying the source string
1572  * @param len length of segment to copy
1573  * @param dest the destination string
1574  * @param replace_at start of segment of dest string to replace
1575  * @param replace_len length of segment of dest string to replace
1576  * @returns #FALSE if not enough memory
1577  *
1578  */
1579 dbus_bool_t
1580 _dbus_string_replace_len (const DBusString *source,
1581                           int               start,
1582                           int               len,
1583                           DBusString       *dest,
1584                           int               replace_at,
1585                           int               replace_len)
1586 {
1587   DBUS_STRING_COPY_PREAMBLE (source, start, dest, replace_at);
1588   _dbus_assert (len >= 0);
1589   _dbus_assert (start <= real_source->len);
1590   _dbus_assert (len <= real_source->len - start);
1591   _dbus_assert (replace_at >= 0);
1592   _dbus_assert (replace_at <= real_dest->len);
1593   _dbus_assert (replace_len <= real_dest->len - replace_at);
1594
1595   if (!copy (real_source, start, len,
1596              real_dest, replace_at))
1597     return FALSE;
1598
1599   delete (real_dest, replace_at + len, replace_len);
1600
1601   return TRUE;
1602 }
1603
1604 /* Unicode macros and utf8_validate() from GLib Owen Taylor, Havoc
1605  * Pennington, and Tom Tromey are the authors and authorized relicense.
1606  */
1607
1608 /** computes length and mask of a unicode character
1609  * @param Char the char
1610  * @param Mask the mask variable to assign to
1611  * @param Len the length variable to assign to
1612  */
1613 #define UTF8_COMPUTE(Char, Mask, Len)                                         \
1614   if (Char < 128)                                                             \
1615     {                                                                         \
1616       Len = 1;                                                                \
1617       Mask = 0x7f;                                                            \
1618     }                                                                         \
1619   else if ((Char & 0xe0) == 0xc0)                                             \
1620     {                                                                         \
1621       Len = 2;                                                                \
1622       Mask = 0x1f;                                                            \
1623     }                                                                         \
1624   else if ((Char & 0xf0) == 0xe0)                                             \
1625     {                                                                         \
1626       Len = 3;                                                                \
1627       Mask = 0x0f;                                                            \
1628     }                                                                         \
1629   else if ((Char & 0xf8) == 0xf0)                                             \
1630     {                                                                         \
1631       Len = 4;                                                                \
1632       Mask = 0x07;                                                            \
1633     }                                                                         \
1634   else if ((Char & 0xfc) == 0xf8)                                             \
1635     {                                                                         \
1636       Len = 5;                                                                \
1637       Mask = 0x03;                                                            \
1638     }                                                                         \
1639   else if ((Char & 0xfe) == 0xfc)                                             \
1640     {                                                                         \
1641       Len = 6;                                                                \
1642       Mask = 0x01;                                                            \
1643     }                                                                         \
1644   else                                                                        \
1645     {                                                                         \
1646       Len = 0;                                                               \
1647       Mask = 0;                                                               \
1648     }
1649
1650 /**
1651  * computes length of a unicode character in UTF-8
1652  * @param Char the char
1653  */
1654 #define UTF8_LENGTH(Char)              \
1655   ((Char) < 0x80 ? 1 :                 \
1656    ((Char) < 0x800 ? 2 :               \
1657     ((Char) < 0x10000 ? 3 :            \
1658      ((Char) < 0x200000 ? 4 :          \
1659       ((Char) < 0x4000000 ? 5 : 6)))))
1660    
1661 /**
1662  * Gets a UTF-8 value.
1663  *
1664  * @param Result variable for extracted unicode char.
1665  * @param Chars the bytes to decode
1666  * @param Count counter variable
1667  * @param Mask mask for this char
1668  * @param Len length for this char in bytes
1669  */
1670 #define UTF8_GET(Result, Chars, Count, Mask, Len)                             \
1671   (Result) = (Chars)[0] & (Mask);                                             \
1672   for ((Count) = 1; (Count) < (Len); ++(Count))                               \
1673     {                                                                         \
1674       if (((Chars)[(Count)] & 0xc0) != 0x80)                                  \
1675         {                                                                     \
1676           (Result) = -1;                                                      \
1677           break;                                                              \
1678         }                                                                     \
1679       (Result) <<= 6;                                                         \
1680       (Result) |= ((Chars)[(Count)] & 0x3f);                                  \
1681     }
1682
1683 /**
1684  * Check whether a unicode char is in a valid range.
1685  *
1686  * @param Char the character
1687  */
1688 #define UNICODE_VALID(Char)                   \
1689     ((Char) < 0x110000 &&                     \
1690      (((Char) & 0xFFFFF800) != 0xD800) &&     \
1691      ((Char) < 0xFDD0 || (Char) > 0xFDEF) &&  \
1692      ((Char) & 0xFFFF) != 0xFFFF)
1693
1694 /**
1695  * Gets a unicode character from a UTF-8 string. Does no validation;
1696  * you must verify that the string is valid UTF-8 in advance and must
1697  * pass in the start of a character.
1698  *
1699  * @param str the string
1700  * @param start the start of the UTF-8 character.
1701  * @param ch_return location to return the character
1702  * @param end_return location to return the byte index of next character
1703  */
1704 void
1705 _dbus_string_get_unichar (const DBusString *str,
1706                           int               start,
1707                           dbus_unichar_t   *ch_return,
1708                           int              *end_return)
1709 {
1710   int i, mask, len;
1711   dbus_unichar_t result;
1712   unsigned char c;
1713   unsigned char *p;
1714   DBUS_CONST_STRING_PREAMBLE (str);
1715   _dbus_assert (start >= 0);
1716   _dbus_assert (start <= real->len);
1717   
1718   if (ch_return)
1719     *ch_return = 0;
1720   if (end_return)
1721     *end_return = real->len;
1722   
1723   mask = 0;
1724   p = real->str + start;
1725   c = *p;
1726   
1727   UTF8_COMPUTE (c, mask, len);
1728   if (len == 0)
1729     return;
1730   UTF8_GET (result, p, i, mask, len);
1731
1732   if (result == (dbus_unichar_t)-1)
1733     return;
1734
1735   if (ch_return)
1736     *ch_return = result;
1737   if (end_return)
1738     *end_return = start + len;
1739 }
1740
1741 /**
1742  * Finds the given substring in the string,
1743  * returning #TRUE and filling in the byte index
1744  * where the substring was found, if it was found.
1745  * Returns #FALSE if the substring wasn't found.
1746  * Sets *start to the length of the string if the substring
1747  * is not found.
1748  *
1749  * @param str the string
1750  * @param start where to start looking
1751  * @param substr the substring
1752  * @param found return location for where it was found, or #NULL
1753  * @returns #TRUE if found
1754  */
1755 dbus_bool_t
1756 _dbus_string_find (const DBusString *str,
1757                    int               start,
1758                    const char       *substr,
1759                    int              *found)
1760 {
1761   return _dbus_string_find_to (str, start,
1762                                ((const DBusRealString*)str)->len,
1763                                substr, found);
1764 }
1765
1766 /**
1767  * Finds the given substring in the string,
1768  * up to a certain position,
1769  * returning #TRUE and filling in the byte index
1770  * where the substring was found, if it was found.
1771  * Returns #FALSE if the substring wasn't found.
1772  * Sets *start to the length of the string if the substring
1773  * is not found.
1774  *
1775  * @param str the string
1776  * @param start where to start looking
1777  * @param end where to stop looking
1778  * @param substr the substring
1779  * @param found return location for where it was found, or #NULL
1780  * @returns #TRUE if found
1781  */
1782 dbus_bool_t
1783 _dbus_string_find_to (const DBusString *str,
1784                       int               start,
1785                       int               end,
1786                       const char       *substr,
1787                       int              *found)
1788 {
1789   int i;
1790   DBUS_CONST_STRING_PREAMBLE (str);
1791   _dbus_assert (substr != NULL);
1792   _dbus_assert (start <= real->len);
1793   _dbus_assert (start >= 0);
1794   _dbus_assert (substr != NULL);
1795   _dbus_assert (end <= real->len);
1796   _dbus_assert (start <= end);
1797
1798   /* we always "find" an empty string */
1799   if (*substr == '\0')
1800     {
1801       if (found)
1802         *found = start;
1803       return TRUE;
1804     }
1805
1806   i = start;
1807   while (i < end)
1808     {
1809       if (real->str[i] == substr[0])
1810         {
1811           int j = i + 1;
1812           
1813           while (j < end)
1814             {
1815               if (substr[j - i] == '\0')
1816                 break;
1817               else if (real->str[j] != substr[j - i])
1818                 break;
1819               
1820               ++j;
1821             }
1822
1823           if (substr[j - i] == '\0')
1824             {
1825               if (found)
1826                 *found = i;
1827               return TRUE;
1828             }
1829         }
1830       
1831       ++i;
1832     }
1833
1834   if (found)
1835     *found = end;
1836   
1837   return FALSE;  
1838 }
1839
1840 /**
1841  * Find the given byte scanning backward from the given start.
1842  * Sets *found to -1 if the byte is not found.
1843  *
1844  * @param str the string
1845  * @param start the place to start scanning (will not find the byte at this point)
1846  * @param byte the byte to find
1847  * @param found return location for where it was found
1848  * @returns #TRUE if found
1849  */
1850 dbus_bool_t
1851 _dbus_string_find_byte_backward (const DBusString  *str,
1852                                  int                start,
1853                                  unsigned char      byte,
1854                                  int               *found)
1855 {
1856   int i;
1857   DBUS_CONST_STRING_PREAMBLE (str);
1858   _dbus_assert (start <= real->len);
1859   _dbus_assert (start >= 0);
1860   _dbus_assert (found != NULL);
1861
1862   i = start - 1;
1863   while (i >= 0)
1864     {
1865       if (real->str[i] == byte)
1866         break;
1867       
1868       --i;
1869     }
1870
1871   if (found)
1872     *found = i;
1873
1874   return i >= 0;
1875 }
1876
1877 /**
1878  * Finds a blank (space or tab) in the string. Returns #TRUE
1879  * if found, #FALSE otherwise. If a blank is not found sets
1880  * *found to the length of the string.
1881  *
1882  * @param str the string
1883  * @param start byte index to start looking
1884  * @param found place to store the location of the first blank
1885  * @returns #TRUE if a blank was found
1886  */
1887 dbus_bool_t
1888 _dbus_string_find_blank (const DBusString *str,
1889                          int               start,
1890                          int              *found)
1891 {
1892   int i;
1893   DBUS_CONST_STRING_PREAMBLE (str);
1894   _dbus_assert (start <= real->len);
1895   _dbus_assert (start >= 0);
1896   
1897   i = start;
1898   while (i < real->len)
1899     {
1900       if (real->str[i] == ' ' ||
1901           real->str[i] == '\t')
1902         {
1903           if (found)
1904             *found = i;
1905           return TRUE;
1906         }
1907       
1908       ++i;
1909     }
1910
1911   if (found)
1912     *found = real->len;
1913   
1914   return FALSE;
1915 }
1916
1917 /**
1918  * Skips blanks from start, storing the first non-blank in *end
1919  * (blank is space or tab).
1920  *
1921  * @param str the string
1922  * @param start where to start
1923  * @param end where to store the first non-blank byte index
1924  */
1925 void
1926 _dbus_string_skip_blank (const DBusString *str,
1927                          int               start,
1928                          int              *end)
1929 {
1930   int i;
1931   DBUS_CONST_STRING_PREAMBLE (str);
1932   _dbus_assert (start <= real->len);
1933   _dbus_assert (start >= 0);
1934   
1935   i = start;
1936   while (i < real->len)
1937     {
1938       if (!(real->str[i] == ' ' ||
1939             real->str[i] == '\t'))
1940         break;
1941       
1942       ++i;
1943     }
1944
1945   _dbus_assert (i == real->len || !(real->str[i] == ' ' ||
1946                                     real->str[i] == '\t'));
1947   
1948   if (end)
1949     *end = i;
1950 }
1951
1952 /**
1953  * Skips whitespace from start, storing the first non-whitespace in *end.
1954  * (whitespace is space, tab, newline, CR).
1955  *
1956  * @param str the string
1957  * @param start where to start
1958  * @param end where to store the first non-whitespace byte index
1959  */
1960 void
1961 _dbus_string_skip_white (const DBusString *str,
1962                          int               start,
1963                          int              *end)
1964 {
1965   int i;
1966   DBUS_CONST_STRING_PREAMBLE (str);
1967   _dbus_assert (start <= real->len);
1968   _dbus_assert (start >= 0);
1969   
1970   i = start;
1971   while (i < real->len)
1972     {
1973       if (!(real->str[i] == ' ' ||
1974             real->str[i] == '\n' ||
1975             real->str[i] == '\r' ||
1976             real->str[i] == '\t'))
1977         break;
1978       
1979       ++i;
1980     }
1981
1982   _dbus_assert (i == real->len || !(real->str[i] == ' ' ||
1983                                     real->str[i] == '\t'));
1984   
1985   if (end)
1986     *end = i;
1987 }
1988
1989 /**
1990  * Assigns a newline-terminated or \\r\\n-terminated line from the front
1991  * of the string to the given dest string. The dest string's previous
1992  * contents are deleted. If the source string contains no newline,
1993  * moves the entire source string to the dest string.
1994  *
1995  * @todo owen correctly notes that this is a stupid function (it was
1996  * written purely for test code,
1997  * e.g. dbus-message-builder.c). Probably should be enforced as test
1998  * code only with #ifdef DBUS_BUILD_TESTS
1999  * 
2000  * @param source the source string
2001  * @param dest the destination string (contents are replaced)
2002  * @returns #FALSE if no memory, or source has length 0
2003  */
2004 dbus_bool_t
2005 _dbus_string_pop_line (DBusString *source,
2006                        DBusString *dest)
2007 {
2008   int eol;
2009   dbus_bool_t have_newline;
2010   
2011   _dbus_string_set_length (dest, 0);
2012   
2013   eol = 0;
2014   if (_dbus_string_find (source, 0, "\n", &eol))
2015     {
2016       have_newline = TRUE;
2017       eol += 1; /* include newline */
2018     }
2019   else
2020     {
2021       eol = _dbus_string_get_length (source);
2022       have_newline = FALSE;
2023     }
2024
2025   if (eol == 0)
2026     return FALSE; /* eof */
2027   
2028   if (!_dbus_string_move_len (source, 0, eol,
2029                               dest, 0))
2030     {
2031       return FALSE;
2032     }
2033
2034   /* dump the newline and the \r if we have one */
2035   if (have_newline)
2036     {
2037       dbus_bool_t have_cr;
2038       
2039       _dbus_assert (_dbus_string_get_length (dest) > 0);
2040
2041       if (_dbus_string_get_length (dest) > 1 &&
2042           _dbus_string_get_byte (dest,
2043                                  _dbus_string_get_length (dest) - 2) == '\r')
2044         have_cr = TRUE;
2045       else
2046         have_cr = FALSE;
2047         
2048       _dbus_string_set_length (dest,
2049                                _dbus_string_get_length (dest) -
2050                                (have_cr ? 2 : 1));
2051     }
2052   
2053   return TRUE;
2054 }
2055
2056 /**
2057  * Deletes up to and including the first blank space
2058  * in the string.
2059  *
2060  * @param str the string
2061  */
2062 void
2063 _dbus_string_delete_first_word (DBusString *str)
2064 {
2065   int i;
2066   
2067   if (_dbus_string_find_blank (str, 0, &i))
2068     _dbus_string_skip_blank (str, i, &i);
2069
2070   _dbus_string_delete (str, 0, i);
2071 }
2072
2073 /**
2074  * Deletes any leading blanks in the string
2075  *
2076  * @param str the string
2077  */
2078 void
2079 _dbus_string_delete_leading_blanks (DBusString *str)
2080 {
2081   int i;
2082   
2083   _dbus_string_skip_blank (str, 0, &i);
2084
2085   if (i > 0)
2086     _dbus_string_delete (str, 0, i);
2087 }
2088
2089 /**
2090  * Tests two DBusString for equality.
2091  *
2092  * @todo memcmp is probably faster
2093  *
2094  * @param a first string
2095  * @param b second string
2096  * @returns #TRUE if equal
2097  */
2098 dbus_bool_t
2099 _dbus_string_equal (const DBusString *a,
2100                     const DBusString *b)
2101 {
2102   const unsigned char *ap;
2103   const unsigned char *bp;
2104   const unsigned char *a_end;
2105   const DBusRealString *real_a = (const DBusRealString*) a;
2106   const DBusRealString *real_b = (const DBusRealString*) b;
2107   DBUS_GENERIC_STRING_PREAMBLE (real_a);
2108   DBUS_GENERIC_STRING_PREAMBLE (real_b);
2109
2110   if (real_a->len != real_b->len)
2111     return FALSE;
2112
2113   ap = real_a->str;
2114   bp = real_b->str;
2115   a_end = real_a->str + real_a->len;
2116   while (ap != a_end)
2117     {
2118       if (*ap != *bp)
2119         return FALSE;
2120       
2121       ++ap;
2122       ++bp;
2123     }
2124
2125   return TRUE;
2126 }
2127
2128 /**
2129  * Tests two DBusString for equality up to the given length.
2130  * The strings may be shorter than the given length.
2131  *
2132  * @todo write a unit test
2133  *
2134  * @todo memcmp is probably faster
2135  *
2136  * @param a first string
2137  * @param b second string
2138  * @param len the maximum length to look at
2139  * @returns #TRUE if equal for the given number of bytes
2140  */
2141 dbus_bool_t
2142 _dbus_string_equal_len (const DBusString *a,
2143                         const DBusString *b,
2144                         int               len)
2145 {
2146   const unsigned char *ap;
2147   const unsigned char *bp;
2148   const unsigned char *a_end;
2149   const DBusRealString *real_a = (const DBusRealString*) a;
2150   const DBusRealString *real_b = (const DBusRealString*) b;
2151   DBUS_GENERIC_STRING_PREAMBLE (real_a);
2152   DBUS_GENERIC_STRING_PREAMBLE (real_b);
2153
2154   if (real_a->len != real_b->len &&
2155       (real_a->len < len || real_b->len < len))
2156     return FALSE;
2157
2158   ap = real_a->str;
2159   bp = real_b->str;
2160   a_end = real_a->str + MIN (real_a->len, len);
2161   while (ap != a_end)
2162     {
2163       if (*ap != *bp)
2164         return FALSE;
2165       
2166       ++ap;
2167       ++bp;
2168     }
2169
2170   return TRUE;
2171 }
2172
2173 /**
2174  * Tests two sub-parts of two DBusString for equality.  The specified
2175  * range of the first string must exist; the specified start position
2176  * of the second string must exist.
2177  *
2178  * @todo write a unit test
2179  *
2180  * @todo memcmp is probably faster
2181  *
2182  * @param a first string
2183  * @param a_start where to start substring in first string
2184  * @param a_len length of substring in first string
2185  * @param b second string
2186  * @param b_start where to start substring in second string
2187  * @returns #TRUE if the two substrings are equal
2188  */
2189 dbus_bool_t
2190 _dbus_string_equal_substring (const DBusString  *a,
2191                               int                a_start,
2192                               int                a_len,
2193                               const DBusString  *b,
2194                               int                b_start)
2195 {
2196   const unsigned char *ap;
2197   const unsigned char *bp;
2198   const unsigned char *a_end;
2199   const DBusRealString *real_a = (const DBusRealString*) a;
2200   const DBusRealString *real_b = (const DBusRealString*) b;
2201   DBUS_GENERIC_STRING_PREAMBLE (real_a);
2202   DBUS_GENERIC_STRING_PREAMBLE (real_b);
2203   _dbus_assert (a_start >= 0);
2204   _dbus_assert (a_len >= 0);
2205   _dbus_assert (a_start <= real_a->len);
2206   _dbus_assert (a_len <= real_a->len - a_start);
2207   _dbus_assert (b_start >= 0);
2208   _dbus_assert (b_start <= real_b->len);
2209   
2210   if (a_len > real_b->len - b_start)
2211     return FALSE;
2212
2213   ap = real_a->str + a_start;
2214   bp = real_b->str + b_start;
2215   a_end = ap + a_len;
2216   while (ap != a_end)
2217     {
2218       if (*ap != *bp)
2219         return FALSE;
2220       
2221       ++ap;
2222       ++bp;
2223     }
2224
2225   _dbus_assert (bp <= (real_b->str + real_b->len));
2226   
2227   return TRUE;
2228 }
2229
2230 /**
2231  * Checks whether a string is equal to a C string.
2232  *
2233  * @param a the string
2234  * @param c_str the C string
2235  * @returns #TRUE if equal
2236  */
2237 dbus_bool_t
2238 _dbus_string_equal_c_str (const DBusString *a,
2239                           const char       *c_str)
2240 {
2241   const unsigned char *ap;
2242   const unsigned char *bp;
2243   const unsigned char *a_end;
2244   const DBusRealString *real_a = (const DBusRealString*) a;
2245   DBUS_GENERIC_STRING_PREAMBLE (real_a);
2246   _dbus_assert (c_str != NULL);
2247   
2248   ap = real_a->str;
2249   bp = (const unsigned char*) c_str;
2250   a_end = real_a->str + real_a->len;
2251   while (ap != a_end && *bp)
2252     {
2253       if (*ap != *bp)
2254         return FALSE;
2255       
2256       ++ap;
2257       ++bp;
2258     }
2259
2260   if (ap != a_end || *bp)
2261     return FALSE;
2262   
2263   return TRUE;
2264 }
2265
2266 /**
2267  * Checks whether a string starts with the given C string.
2268  *
2269  * @param a the string
2270  * @param c_str the C string
2271  * @returns #TRUE if string starts with it
2272  */
2273 dbus_bool_t
2274 _dbus_string_starts_with_c_str (const DBusString *a,
2275                                 const char       *c_str)
2276 {
2277   const unsigned char *ap;
2278   const unsigned char *bp;
2279   const unsigned char *a_end;
2280   const DBusRealString *real_a = (const DBusRealString*) a;
2281   DBUS_GENERIC_STRING_PREAMBLE (real_a);
2282   _dbus_assert (c_str != NULL);
2283   
2284   ap = real_a->str;
2285   bp = (const unsigned char*) c_str;
2286   a_end = real_a->str + real_a->len;
2287   while (ap != a_end && *bp)
2288     {
2289       if (*ap != *bp)
2290         return FALSE;
2291       
2292       ++ap;
2293       ++bp;
2294     }
2295
2296   if (*bp == '\0')
2297     return TRUE;
2298   else
2299     return FALSE;
2300 }
2301
2302 /**
2303  * Returns whether a string ends with the given suffix
2304  *
2305  * @todo memcmp might make this faster.
2306  * 
2307  * @param a the string
2308  * @param c_str the C-style string
2309  * @returns #TRUE if the string ends with the suffix
2310  */
2311 dbus_bool_t
2312 _dbus_string_ends_with_c_str (const DBusString *a,
2313                               const char       *c_str)
2314 {
2315   const unsigned char *ap;
2316   const unsigned char *bp;
2317   const unsigned char *a_end;
2318   unsigned long c_str_len;
2319   const DBusRealString *real_a = (const DBusRealString*) a;
2320   DBUS_GENERIC_STRING_PREAMBLE (real_a);
2321   _dbus_assert (c_str != NULL);
2322   
2323   c_str_len = strlen (c_str);
2324   if (((unsigned long)real_a->len) < c_str_len)
2325     return FALSE;
2326   
2327   ap = real_a->str + (real_a->len - c_str_len);
2328   bp = (const unsigned char*) c_str;
2329   a_end = real_a->str + real_a->len;
2330   while (ap != a_end)
2331     {
2332       if (*ap != *bp)
2333         return FALSE;
2334       
2335       ++ap;
2336       ++bp;
2337     }
2338
2339   _dbus_assert (*ap == '\0');
2340   _dbus_assert (*bp == '\0');
2341   
2342   return TRUE;
2343 }
2344
2345 /**
2346  * Encodes a string in hex, the way MD5 and SHA-1 are usually
2347  * encoded. (Each byte is two hex digits.)
2348  *
2349  * @param source the string to encode
2350  * @param start byte index to start encoding
2351  * @param dest string where encoded data should be placed
2352  * @param insert_at where to place encoded data
2353  * @returns #TRUE if encoding was successful, #FALSE if no memory etc.
2354  */
2355 dbus_bool_t
2356 _dbus_string_hex_encode (const DBusString *source,
2357                          int               start,
2358                          DBusString       *dest,
2359                          int               insert_at)
2360 {
2361   DBusString result;
2362   const char hexdigits[16] = {
2363     '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
2364     'a', 'b', 'c', 'd', 'e', 'f'
2365   };
2366   const unsigned char *p;
2367   const unsigned char *end;
2368   dbus_bool_t retval;
2369   
2370   _dbus_assert (start <= _dbus_string_get_length (source));
2371
2372   if (!_dbus_string_init (&result))
2373     return FALSE;
2374
2375   retval = FALSE;
2376   
2377   p = (const unsigned char*) _dbus_string_get_const_data (source);
2378   end = p + _dbus_string_get_length (source);
2379   p += start;
2380   
2381   while (p != end)
2382     {
2383       if (!_dbus_string_append_byte (&result,
2384                                      hexdigits[(*p >> 4)]))
2385         goto out;
2386       
2387       if (!_dbus_string_append_byte (&result,
2388                                      hexdigits[(*p & 0x0f)]))
2389         goto out;
2390
2391       ++p;
2392     }
2393
2394   if (!_dbus_string_move (&result, 0, dest, insert_at))
2395     goto out;
2396
2397   retval = TRUE;
2398
2399  out:
2400   _dbus_string_free (&result);
2401   return retval;
2402 }
2403
2404 /**
2405  * Decodes a string from hex encoding.
2406  *
2407  * @param source the string to decode
2408  * @param start byte index to start decode
2409  * @param end_return return location of the end of the hex data, or #NULL
2410  * @param dest string where decoded data should be placed
2411  * @param insert_at where to place decoded data
2412  * @returns #TRUE if decoding was successful, #FALSE if no memory.
2413  */
2414 dbus_bool_t
2415 _dbus_string_hex_decode (const DBusString *source,
2416                          int               start,
2417                          int              *end_return,
2418                          DBusString       *dest,
2419                          int               insert_at)
2420 {
2421   DBusString result;
2422   const unsigned char *p;
2423   const unsigned char *end;
2424   dbus_bool_t retval;
2425   dbus_bool_t high_bits;
2426   
2427   _dbus_assert (start <= _dbus_string_get_length (source));
2428
2429   if (!_dbus_string_init (&result))
2430     return FALSE;
2431
2432   retval = FALSE;
2433
2434   high_bits = TRUE;
2435   p = (const unsigned char*) _dbus_string_get_const_data (source);
2436   end = p + _dbus_string_get_length (source);
2437   p += start;
2438   
2439   while (p != end)
2440     {
2441       unsigned int val;
2442
2443       switch (*p)
2444         {
2445         case '0':
2446           val = 0;
2447           break;
2448         case '1':
2449           val = 1;
2450           break;
2451         case '2':
2452           val = 2;
2453           break;
2454         case '3':
2455           val = 3;
2456           break;
2457         case '4':
2458           val = 4;
2459           break;
2460         case '5':
2461           val = 5;
2462           break;
2463         case '6':
2464           val = 6;
2465           break;
2466         case '7':
2467           val = 7;
2468           break;
2469         case '8':
2470           val = 8;
2471           break;
2472         case '9':
2473           val = 9;
2474           break;
2475         case 'a':
2476         case 'A':
2477           val = 10;
2478           break;
2479         case 'b':
2480         case 'B':
2481           val = 11;
2482           break;
2483         case 'c':
2484         case 'C':
2485           val = 12;
2486           break;
2487         case 'd':
2488         case 'D':
2489           val = 13;
2490           break;
2491         case 'e':
2492         case 'E':
2493           val = 14;
2494           break;
2495         case 'f':
2496         case 'F':
2497           val = 15;
2498           break;
2499         default:
2500           goto done;
2501         }
2502
2503       if (high_bits)
2504         {
2505           if (!_dbus_string_append_byte (&result,
2506                                          val << 4))
2507             goto out;
2508         }
2509       else
2510         {
2511           int len;
2512           unsigned char b;
2513
2514           len = _dbus_string_get_length (&result);
2515           
2516           b = _dbus_string_get_byte (&result, len - 1);
2517
2518           b |= val;
2519
2520           _dbus_string_set_byte (&result, len - 1, b);
2521         }
2522
2523       high_bits = !high_bits;
2524
2525       ++p;
2526     }
2527
2528  done:
2529   if (!_dbus_string_move (&result, 0, dest, insert_at))
2530     goto out;
2531
2532   if (end_return)
2533     *end_return = p - (const unsigned char*) _dbus_string_get_const_data (source);
2534
2535   retval = TRUE;
2536   
2537  out:
2538   _dbus_string_free (&result);  
2539   return retval;
2540 }
2541
2542 /**
2543  * Checks that the given range of the string is valid ASCII with no
2544  * nul bytes. If the given range is not entirely contained in the
2545  * string, returns #FALSE.
2546  *
2547  * @todo this is inconsistent with most of DBusString in that
2548  * it allows a start,len range that extends past the string end.
2549  * 
2550  * @param str the string
2551  * @param start first byte index to check
2552  * @param len number of bytes to check
2553  * @returns #TRUE if the byte range exists and is all valid ASCII
2554  */
2555 dbus_bool_t
2556 _dbus_string_validate_ascii (const DBusString *str,
2557                              int               start,
2558                              int               len)
2559 {
2560   const unsigned char *s;
2561   const unsigned char *end;
2562   DBUS_CONST_STRING_PREAMBLE (str);
2563   _dbus_assert (start >= 0);
2564   _dbus_assert (start <= real->len);
2565   _dbus_assert (len >= 0);
2566   
2567   if (len > real->len - start)
2568     return FALSE;
2569   
2570   s = real->str + start;
2571   end = s + len;
2572   while (s != end)
2573     {
2574       if (_DBUS_UNLIKELY (!_DBUS_ISASCII (*s)))
2575         return FALSE;
2576         
2577       ++s;
2578     }
2579   
2580   return TRUE;
2581 }
2582
2583 /**
2584  * Checks that the given range of the string is valid UTF-8. If the
2585  * given range is not entirely contained in the string, returns
2586  * #FALSE. If the string contains any nul bytes in the given range,
2587  * returns #FALSE. If the start and start+len are not on character
2588  * boundaries, returns #FALSE.
2589  *
2590  * @todo this is inconsistent with most of DBusString in that
2591  * it allows a start,len range that extends past the string end.
2592  * 
2593  * @param str the string
2594  * @param start first byte index to check
2595  * @param len number of bytes to check
2596  * @returns #TRUE if the byte range exists and is all valid UTF-8
2597  */
2598 dbus_bool_t
2599 _dbus_string_validate_utf8  (const DBusString *str,
2600                              int               start,
2601                              int               len)
2602 {
2603   const unsigned char *p;
2604   const unsigned char *end;
2605   DBUS_CONST_STRING_PREAMBLE (str);
2606   _dbus_assert (start >= 0);
2607   _dbus_assert (start <= real->len);
2608   _dbus_assert (len >= 0);
2609
2610   /* we are doing _DBUS_UNLIKELY() here which might be
2611    * dubious in a generic library like GLib, but in D-BUS
2612    * we know we're validating messages and that it would
2613    * only be evil/broken apps that would have invalid
2614    * UTF-8. Also, this function seems to be a performance
2615    * bottleneck in profiles.
2616    */
2617   
2618   if (_DBUS_UNLIKELY (len > real->len - start))
2619     return FALSE;
2620   
2621   p = real->str + start;
2622   end = p + len;
2623   
2624   while (p < end)
2625     {
2626       int i, mask, char_len;
2627       dbus_unichar_t result;
2628
2629       /* nul bytes considered invalid */
2630       if (*p == '\0')
2631         break;
2632       
2633       /* Special-case ASCII; this makes us go a lot faster in
2634        * D-BUS profiles where we are typically validating
2635        * function names and such. We have to know that
2636        * all following checks will pass for ASCII though,
2637        * comments follow ...
2638        */      
2639       if (*p < 128)
2640         {
2641           ++p;
2642           continue;
2643         }
2644       
2645       UTF8_COMPUTE (*p, mask, char_len);
2646
2647       if (_DBUS_UNLIKELY (char_len == 0))  /* ASCII: char_len == 1 */
2648         break;
2649
2650       /* check that the expected number of bytes exists in the remaining length */
2651       if (_DBUS_UNLIKELY ((end - p) < char_len)) /* ASCII: p < end and char_len == 1 */
2652         break;
2653         
2654       UTF8_GET (result, p, i, mask, char_len);
2655
2656       /* Check for overlong UTF-8 */
2657       if (_DBUS_UNLIKELY (UTF8_LENGTH (result) != char_len)) /* ASCII: UTF8_LENGTH == 1 */
2658         break;
2659 #if 0
2660       /* The UNICODE_VALID check below will catch this */
2661       if (_DBUS_UNLIKELY (result == (dbus_unichar_t)-1)) /* ASCII: result = ascii value */
2662         break;
2663 #endif
2664
2665       if (_DBUS_UNLIKELY (!UNICODE_VALID (result))) /* ASCII: always valid */
2666         break;
2667
2668       /* UNICODE_VALID should have caught it */
2669       _dbus_assert (result != (dbus_unichar_t)-1);
2670       
2671       p += char_len;
2672     }
2673
2674   /* See that we covered the entire length if a length was
2675    * passed in
2676    */
2677   if (_DBUS_UNLIKELY (p != end))
2678     return FALSE;
2679   else
2680     return TRUE;
2681 }
2682
2683 /**
2684  * Checks that the given range of the string is all nul bytes. If the
2685  * given range is not entirely contained in the string, returns
2686  * #FALSE.
2687  *
2688  * @todo this is inconsistent with most of DBusString in that
2689  * it allows a start,len range that extends past the string end.
2690  * 
2691  * @param str the string
2692  * @param start first byte index to check
2693  * @param len number of bytes to check
2694  * @returns #TRUE if the byte range exists and is all nul bytes
2695  */
2696 dbus_bool_t
2697 _dbus_string_validate_nul (const DBusString *str,
2698                            int               start,
2699                            int               len)
2700 {
2701   const unsigned char *s;
2702   const unsigned char *end;
2703   DBUS_CONST_STRING_PREAMBLE (str);
2704   _dbus_assert (start >= 0);
2705   _dbus_assert (len >= 0);
2706   _dbus_assert (start <= real->len);
2707   
2708   if (len > real->len - start)
2709     return FALSE;
2710   
2711   s = real->str + start;
2712   end = s + len;
2713   while (s != end)
2714     {
2715       if (_DBUS_UNLIKELY (*s != '\0'))
2716         return FALSE;
2717       ++s;
2718     }
2719   
2720   return TRUE;
2721 }
2722
2723 /**
2724  * Checks that the given range of the string is a valid object path
2725  * name in the D-BUS protocol. This includes a length restriction,
2726  * etc., see the specification. It does not validate UTF-8, that has
2727  * to be done separately for now.
2728  *
2729  * @todo this is inconsistent with most of DBusString in that
2730  * it allows a start,len range that extends past the string end.
2731  *
2732  * @todo change spec to disallow more things, such as spaces in the
2733  * path name
2734  * 
2735  * @param str the string
2736  * @param start first byte index to check
2737  * @param len number of bytes to check
2738  * @returns #TRUE if the byte range exists and is a valid name
2739  */
2740 dbus_bool_t
2741 _dbus_string_validate_path (const DBusString  *str,
2742                             int                start,
2743                             int                len)
2744 {
2745   const unsigned char *s;
2746   const unsigned char *end;
2747   const unsigned char *last_slash;
2748   
2749   DBUS_CONST_STRING_PREAMBLE (str);
2750   _dbus_assert (start >= 0);
2751   _dbus_assert (len >= 0);
2752   _dbus_assert (start <= real->len);
2753   
2754   if (len > real->len - start)
2755     return FALSE;
2756
2757   if (len > DBUS_MAXIMUM_NAME_LENGTH)
2758     return FALSE;
2759
2760   if (len == 0)
2761     return FALSE;
2762
2763   s = real->str + start;
2764   end = s + len;
2765
2766   if (*s != '/')
2767     return FALSE;
2768   last_slash = s;
2769   ++s;
2770   
2771   while (s != end)
2772     {
2773       if (*s == '/')
2774         {
2775           if ((s - last_slash) < 2)
2776             return FALSE; /* no empty path components allowed */
2777
2778           last_slash = s;
2779         }
2780       
2781       ++s;
2782     }
2783
2784   if ((end - last_slash) < 2 &&
2785       len > 1)
2786     return FALSE; /* trailing slash not allowed unless the string is "/" */
2787   
2788   return TRUE;
2789 }
2790
2791 /**
2792  * Determine wether the given charater is valid as the first charater
2793  * in a name.
2794  */
2795 #define VALID_INITIAL_NAME_CHARACTER(c)         \
2796   ( ((c) >= 'A' && (c) <= 'Z') ||               \
2797     ((c) >= 'a' && (c) <= 'z') ||               \
2798     ((c) == '_') )
2799
2800 /**
2801  * Determine wether the given charater is valid as a second or later
2802  * character in a nam
2803  */
2804 #define VALID_NAME_CHARACTER(c)                 \
2805   ( ((c) >= '0' && (c) <= '9') ||               \
2806     ((c) >= 'A' && (c) <= 'Z') ||               \
2807     ((c) >= 'a' && (c) <= 'z') ||               \
2808     ((c) == '_') )
2809
2810 /**
2811  * Checks that the given range of the string is a valid interface name
2812  * in the D-BUS protocol. This includes a length restriction and an
2813  * ASCII subset, see the specification.
2814  *
2815  * @todo this is inconsistent with most of DBusString in that
2816  * it allows a start,len range that extends past the string end.
2817  * 
2818  * @param str the string
2819  * @param start first byte index to check
2820  * @param len number of bytes to check
2821  * @returns #TRUE if the byte range exists and is a valid name
2822  */
2823 dbus_bool_t
2824 _dbus_string_validate_interface (const DBusString  *str,
2825                                  int                start,
2826                                  int                len)
2827 {  
2828   const unsigned char *s;
2829   const unsigned char *end;
2830   const unsigned char *iface;
2831   const unsigned char *last_dot;
2832   
2833   DBUS_CONST_STRING_PREAMBLE (str);
2834   _dbus_assert (start >= 0);
2835   _dbus_assert (len >= 0);
2836   _dbus_assert (start <= real->len);
2837   
2838   if (len > real->len - start)
2839     return FALSE;
2840
2841   if (len > DBUS_MAXIMUM_NAME_LENGTH)
2842     return FALSE;
2843
2844   if (len == 0)
2845     return FALSE;
2846
2847   last_dot = NULL;
2848   iface = real->str + start;
2849   end = iface + len;
2850   s = iface;
2851
2852   /* check special cases of first char so it doesn't have to be done
2853    * in the loop. Note we know len > 0
2854    */
2855   if (_DBUS_UNLIKELY (*s == '.')) /* disallow starting with a . */
2856     return FALSE;
2857   else if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*s)))
2858     return FALSE;
2859   else
2860     ++s;
2861   
2862   while (s != end)
2863     {
2864       if (*s == '.')
2865         {
2866           if (_DBUS_UNLIKELY ((s + 1) == end))
2867             return FALSE;
2868           else if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*(s + 1))))
2869             return FALSE;
2870           last_dot = s;
2871           ++s; /* we just validated the next char, so skip two */
2872         }
2873       else if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s)))
2874         {
2875           return FALSE;
2876         }
2877       
2878       ++s;
2879     }
2880
2881   if (_DBUS_UNLIKELY (last_dot == NULL))
2882     return FALSE;
2883   
2884   return TRUE;
2885 }
2886
2887 /**
2888  * Checks that the given range of the string is a valid member name
2889  * in the D-BUS protocol. This includes a length restriction, etc.,
2890  * see the specification.
2891  *
2892  * @todo this is inconsistent with most of DBusString in that
2893  * it allows a start,len range that extends past the string end.
2894  * 
2895  * @param str the string
2896  * @param start first byte index to check
2897  * @param len number of bytes to check
2898  * @returns #TRUE if the byte range exists and is a valid name
2899  */
2900 dbus_bool_t
2901 _dbus_string_validate_member (const DBusString  *str,
2902                               int                start,
2903                               int                len)
2904 {
2905   const unsigned char *s;
2906   const unsigned char *end;
2907   const unsigned char *member;
2908   
2909   DBUS_CONST_STRING_PREAMBLE (str);
2910   _dbus_assert (start >= 0);
2911   _dbus_assert (len >= 0);
2912   _dbus_assert (start <= real->len);
2913   
2914   if (len > real->len - start)
2915     return FALSE;
2916
2917   if (len > DBUS_MAXIMUM_NAME_LENGTH)
2918     return FALSE;
2919
2920   if (len == 0)
2921     return FALSE;
2922
2923   member = real->str + start;
2924   end = member + len;
2925   s = member;
2926
2927   /* check special cases of first char so it doesn't have to be done
2928    * in the loop. Note we know len > 0
2929    */
2930
2931   if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*s)))
2932     return FALSE;
2933   else
2934     ++s;
2935   
2936   while (s != end)
2937     {
2938       if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s)))
2939         {
2940           return FALSE;
2941         }
2942       
2943       ++s;
2944     }
2945   
2946   return TRUE;
2947 }
2948
2949 /**
2950  * Checks that the given range of the string is a valid error name
2951  * in the D-BUS protocol. This includes a length restriction, etc.,
2952  * see the specification.
2953  *
2954  * @todo this is inconsistent with most of DBusString in that
2955  * it allows a start,len range that extends past the string end.
2956  * 
2957  * @param str the string
2958  * @param start first byte index to check
2959  * @param len number of bytes to check
2960  * @returns #TRUE if the byte range exists and is a valid name
2961  */
2962 dbus_bool_t
2963 _dbus_string_validate_error_name (const DBusString  *str,
2964                                   int                start,
2965                                   int                len)
2966 {
2967   /* Same restrictions as interface name at the moment */
2968   return _dbus_string_validate_interface (str, start, len);
2969 }
2970
2971 /* This assumes the first char exists and is ':' */
2972 static dbus_bool_t
2973 _dbus_string_validate_base_service (const DBusString  *str,
2974                                     int                start,
2975                                     int                len)
2976 {
2977   const unsigned char *s;
2978   const unsigned char *end;
2979   const unsigned char *service;
2980   
2981   DBUS_CONST_STRING_PREAMBLE (str);
2982   _dbus_assert (start >= 0);
2983   _dbus_assert (len >= 0);
2984   _dbus_assert (start <= real->len);
2985   
2986   if (len > real->len - start)
2987     return FALSE;
2988
2989   if (len > DBUS_MAXIMUM_NAME_LENGTH)
2990     return FALSE;
2991
2992   _dbus_assert (len > 0);
2993
2994   service = real->str + start;
2995   end = service + len;
2996   _dbus_assert (*service == ':');
2997   s = service + 1;
2998   
2999   while (s != end)
3000     {
3001       if (*s == '.')
3002         {
3003           if (_DBUS_UNLIKELY ((s + 1) == end))
3004             return FALSE;
3005           if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*(s + 1))))
3006             return FALSE;
3007           ++s; /* we just validated the next char, so skip two */
3008         }
3009       else if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s)))
3010         {
3011           return FALSE;
3012         }
3013       
3014       ++s;
3015     }
3016   
3017   return TRUE;
3018 }
3019
3020 /**
3021  * Checks that the given range of the string is a valid service name
3022  * in the D-BUS protocol. This includes a length restriction, etc.,
3023  * see the specification.
3024  *
3025  * @todo this is inconsistent with most of DBusString in that
3026  * it allows a start,len range that extends past the string end.
3027  * 
3028  * @param str the string
3029  * @param start first byte index to check
3030  * @param len number of bytes to check
3031  * @returns #TRUE if the byte range exists and is a valid name
3032  */
3033 dbus_bool_t
3034 _dbus_string_validate_service (const DBusString  *str,
3035                                int                start,
3036                                int                len)
3037 {
3038   if (_DBUS_UNLIKELY (len == 0))
3039     return FALSE;
3040   if (_dbus_string_get_byte (str, start) == ':')
3041     return _dbus_string_validate_base_service (str, start, len);
3042   else
3043     return _dbus_string_validate_interface (str, start, len);
3044 }
3045
3046 /**
3047  * Checks that the given range of the string is a valid message type
3048  * signature in the D-BUS protocol.
3049  *
3050  * @todo this is inconsistent with most of DBusString in that
3051  * it allows a start,len range that extends past the string end.
3052  * 
3053  * @param str the string
3054  * @param start first byte index to check
3055  * @param len number of bytes to check
3056  * @returns #TRUE if the byte range exists and is a valid signature
3057  */
3058 dbus_bool_t
3059 _dbus_string_validate_signature (const DBusString  *str,
3060                                  int                start,
3061                                  int                len)
3062 {
3063   const unsigned char *s;
3064   const unsigned char *end;
3065   DBUS_CONST_STRING_PREAMBLE (str);
3066   _dbus_assert (start >= 0);
3067   _dbus_assert (start <= real->len);
3068   _dbus_assert (len >= 0);
3069   
3070   if (len > real->len - start)
3071     return FALSE;
3072   
3073   s = real->str + start;
3074   end = s + len;
3075   while (s != end)
3076     {
3077       switch (*s)
3078         {
3079         case DBUS_TYPE_NIL:
3080         case DBUS_TYPE_BYTE:
3081         case DBUS_TYPE_BOOLEAN:
3082         case DBUS_TYPE_INT32:
3083         case DBUS_TYPE_UINT32:
3084         case DBUS_TYPE_INT64:
3085         case DBUS_TYPE_UINT64:
3086         case DBUS_TYPE_DOUBLE:
3087         case DBUS_TYPE_STRING:
3088         case DBUS_TYPE_CUSTOM:
3089         case DBUS_TYPE_ARRAY:
3090         case DBUS_TYPE_DICT:
3091         case DBUS_TYPE_OBJECT_PATH:
3092           break;
3093           
3094         default:
3095           return FALSE;
3096         }
3097       
3098       ++s;
3099     }
3100   
3101   return TRUE;
3102 }
3103
3104 /**
3105  * Clears all allocated bytes in the string to zero.
3106  *
3107  * @param str the string
3108  */
3109 void
3110 _dbus_string_zero (DBusString *str)
3111 {
3112   DBUS_STRING_PREAMBLE (str);
3113
3114   memset (real->str - real->align_offset, '\0', real->allocated);
3115 }
3116 /** @} */
3117
3118 #ifdef DBUS_BUILD_TESTS
3119 #include "dbus-test.h"
3120 #include <stdio.h>
3121
3122 /**
3123  * Parses a basic type defined by type contained in a DBusString. The
3124  * end_return parameter may be #NULL if you aren't interested in it. The
3125  * type is parsed and stored in value_return. Return parameters are not
3126  * initialized if the function returns #FALSE.
3127  *
3128  * @param str the string
3129  * @param type the type of the basic type
3130  * @param start the byte index of the start of the type
3131  * @param value_return return location of the value or #NULL
3132  * @param end_return return location of the end of the type, or #NULL
3133  * @returns #TRUE on success
3134  */
3135 dbus_bool_t
3136 _dbus_string_parse_basic_type (const DBusString  *str,
3137                                char               type,
3138                                int                start,
3139                                void              *value,
3140                                int               *end_return)
3141 {
3142   int end = start;
3143
3144   switch (type)
3145     {
3146     case DBUS_TYPE_BOOLEAN:
3147       {
3148         int len = _dbus_string_get_length (str) - start;
3149         if (len >= 5 && _dbus_string_find_to (str, start, start + 5, "false", NULL))
3150           {
3151             end += 5;
3152             *(unsigned char *) value = TRUE;
3153           }
3154         else if (len >= 4 && _dbus_string_find_to (str, start, start + 4, "true", NULL))
3155           {
3156             end += 4;
3157             *(unsigned char *) value = FALSE;
3158           }
3159         else
3160           _dbus_warn ("could not parse BOOLEAN\n");
3161         break;
3162       }
3163     case DBUS_TYPE_BYTE:
3164       {
3165         long val = 0;
3166
3167         if (_dbus_string_get_byte (str, start) == '\'' &&
3168             _dbus_string_get_length (str) >= start + 4 &&
3169             _dbus_string_get_byte (str, start + 1) == '\\' &&
3170             _dbus_string_get_byte (str, start + 2) == '\'' &&
3171             _dbus_string_get_byte (str, start + 3) == '\'')
3172           {
3173             val = '\'';
3174             end += 4;
3175           }
3176         else if (_dbus_string_get_byte (str, start) == '\'' &&
3177                  _dbus_string_get_length (str) >= start + 3 &&
3178                  _dbus_string_get_byte (str, start + 2) == '\'')
3179           {
3180             val = _dbus_string_get_byte (str, start + 1);
3181             end += 3;
3182           }
3183         else
3184           {
3185             if (!_dbus_string_parse_int (str, start, &val, &end)) 
3186               _dbus_warn ("Failed to parse integer for BYTE\n");
3187           }
3188
3189         if (val > 255)
3190           _dbus_warn ("A byte must be in range 0-255 not %ld\n", val);
3191
3192         *(unsigned char *) value = val;
3193         break;
3194       }
3195     case DBUS_TYPE_INT32:
3196       {
3197         long val;
3198         if (_dbus_string_parse_int (str, start, &val, &end))
3199           *(dbus_int32_t *)value = val;
3200         break;
3201       }
3202     case DBUS_TYPE_UINT32:
3203       {
3204         unsigned long val;
3205         if (_dbus_string_parse_uint (str, start, &val, &end))
3206           *(dbus_uint32_t *)value = val;
3207         break;
3208       }
3209 #ifdef DBUS_HAVE_INT64
3210     case DBUS_TYPE_INT64:
3211     case DBUS_TYPE_UINT64: 
3212       /* use stroll oull */
3213       _dbus_assert_not_reached ("string -> [u]int64 not supported yet");
3214       break;
3215 #endif /* DBUS_HAVE_INT64 */
3216     case DBUS_TYPE_DOUBLE:
3217       _dbus_string_parse_double (str, start, value, &end);
3218       break;
3219     default:
3220       _dbus_assert_not_reached ("not a basic type");
3221       break;
3222     }
3223   if (end_return)
3224     *end_return = end;
3225
3226   return end != start;
3227 }
3228
3229 static void
3230 test_max_len (DBusString *str,
3231               int         max_len)
3232 {
3233   if (max_len > 0)
3234     {
3235       if (!_dbus_string_set_length (str, max_len - 1))
3236         _dbus_assert_not_reached ("setting len to one less than max should have worked");
3237     }
3238
3239   if (!_dbus_string_set_length (str, max_len))
3240     _dbus_assert_not_reached ("setting len to max len should have worked");
3241
3242   if (_dbus_string_set_length (str, max_len + 1))
3243     _dbus_assert_not_reached ("setting len to one more than max len should not have worked");
3244
3245   if (!_dbus_string_set_length (str, 0))
3246     _dbus_assert_not_reached ("setting len to zero should have worked");
3247 }
3248
3249 static void
3250 test_hex_roundtrip (const unsigned char *data,
3251                     int                  len)
3252 {
3253   DBusString orig;
3254   DBusString encoded;
3255   DBusString decoded;
3256   int end;
3257
3258   if (len < 0)
3259     len = strlen (data);
3260   
3261   if (!_dbus_string_init (&orig))
3262     _dbus_assert_not_reached ("could not init string");
3263
3264   if (!_dbus_string_init (&encoded))
3265     _dbus_assert_not_reached ("could not init string");
3266   
3267   if (!_dbus_string_init (&decoded))
3268     _dbus_assert_not_reached ("could not init string");
3269
3270   if (!_dbus_string_append_len (&orig, data, len))
3271     _dbus_assert_not_reached ("couldn't append orig data");
3272
3273   if (!_dbus_string_hex_encode (&orig, 0, &encoded, 0))
3274     _dbus_assert_not_reached ("could not encode");
3275
3276   if (!_dbus_string_hex_decode (&encoded, 0, &end, &decoded, 0))
3277     _dbus_assert_not_reached ("could not decode");
3278     
3279   _dbus_assert (_dbus_string_get_length (&encoded) == end);
3280
3281   if (!_dbus_string_equal (&orig, &decoded))
3282     {
3283       const char *s;
3284       
3285       printf ("Original string %d bytes encoded %d bytes decoded %d bytes\n",
3286               _dbus_string_get_length (&orig),
3287               _dbus_string_get_length (&encoded),
3288               _dbus_string_get_length (&decoded));
3289       printf ("Original: %s\n", data);
3290       s = _dbus_string_get_const_data (&decoded);
3291       printf ("Decoded: %s\n", s);
3292       _dbus_assert_not_reached ("original string not the same as string decoded from hex");
3293     }
3294   
3295   _dbus_string_free (&orig);
3296   _dbus_string_free (&encoded);
3297   _dbus_string_free (&decoded);  
3298 }
3299
3300 typedef void (* TestRoundtripFunc) (const unsigned char *data,
3301                                     int                  len);
3302 static void
3303 test_roundtrips (TestRoundtripFunc func)
3304 {
3305   (* func) ("Hello this is a string\n", -1);
3306   (* func) ("Hello this is a string\n1", -1);
3307   (* func) ("Hello this is a string\n12", -1);
3308   (* func) ("Hello this is a string\n123", -1);
3309   (* func) ("Hello this is a string\n1234", -1);
3310   (* func) ("Hello this is a string\n12345", -1);
3311   (* func) ("", 0);
3312   (* func) ("1", 1);
3313   (* func) ("12", 2);
3314   (* func) ("123", 3);
3315   (* func) ("1234", 4);
3316   (* func) ("12345", 5);
3317   (* func) ("", 1);
3318   (* func) ("1", 2);
3319   (* func) ("12", 3);
3320   (* func) ("123", 4);
3321   (* func) ("1234", 5);
3322   (* func) ("12345", 6);
3323   {
3324     unsigned char buf[512];
3325     int i;
3326     
3327     i = 0;
3328     while (i < _DBUS_N_ELEMENTS (buf))
3329       {
3330         buf[i] = i;
3331         ++i;
3332       }
3333     i = 0;
3334     while (i < _DBUS_N_ELEMENTS (buf))
3335       {
3336         (* func) (buf, i);
3337         ++i;
3338       }
3339   }
3340 }
3341
3342
3343 /**
3344  * @ingroup DBusStringInternals
3345  * Unit test for DBusString.
3346  *
3347  * @todo Need to write tests for _dbus_string_copy() and
3348  * _dbus_string_move() moving to/from each of start/middle/end of a
3349  * string. Also need tests for _dbus_string_move_len ()
3350  * 
3351  * @returns #TRUE on success.
3352  */
3353 dbus_bool_t
3354 _dbus_string_test (void)
3355 {
3356   DBusString str;
3357   DBusString other;
3358   int i, end;
3359   long v;
3360   double d;
3361   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 };
3362   char *s;
3363   dbus_unichar_t ch;
3364   const char *valid_paths[] = {
3365     "/",
3366     "/foo/bar",
3367     "/foo",
3368     "/foo/bar/baz"
3369   };
3370   const char *invalid_paths[] = {
3371     "bar",
3372     "bar/baz",
3373     "/foo/bar/",
3374     "/foo/"
3375     "foo/",
3376     "boo//blah",
3377     "//",
3378     "///",
3379     "foo///blah/",
3380     "Hello World",
3381     "",
3382     "   ",
3383     "foo bar"
3384   };
3385
3386   const char *valid_interfaces[] = {
3387     "org.freedesktop.Foo",
3388     "Bar.Baz",
3389     "Blah.Blah.Blah.Blah.Blah",
3390     "a.b",
3391     "a.b.c.d.e.f.g",
3392     "a0.b1.c2.d3.e4.f5.g6",
3393     "abc123.foo27"
3394   };
3395   const char *invalid_interfaces[] = {
3396     ".",
3397     "",
3398     "..",
3399     ".Foo.Bar",
3400     "..Foo.Bar",
3401     "Foo.Bar.",
3402     "Foo.Bar..",
3403     "Foo",
3404     "9foo.bar.baz",
3405     "foo.bar..baz",
3406     "foo.bar...baz",
3407     "foo.bar.b..blah",
3408     ":",
3409     ":0-1",
3410     "10",
3411     ":11.34324",
3412     "0.0.0",
3413     "0..0",
3414     "foo.Bar.%",
3415     "foo.Bar!!",
3416     "!Foo.bar.bz",
3417     "foo.$.blah",
3418     "",
3419     "   ",
3420     "foo bar"
3421   };
3422
3423   const char *valid_base_services[] = {
3424     ":0",
3425     ":a",
3426     ":",
3427     ":.a",
3428     ":.1",
3429     ":0.1",
3430     ":000.2222",
3431     ":.blah",
3432     ":abce.freedesktop.blah"
3433   };
3434   const char *invalid_base_services[] = {
3435     ":-",
3436     ":!",
3437     ":0-10",
3438     ":blah.",
3439     ":blah.",
3440     ":blah..org",
3441     ":blah.org..",
3442     ":..blah.org",
3443     "",
3444     "   ",
3445     "foo bar"
3446   };
3447
3448   const char *valid_members[] = {
3449     "Hello",
3450     "Bar",
3451     "foobar",
3452     "_foobar",
3453     "foo89"
3454   };
3455
3456   const char *invalid_members[] = {
3457     "9Hello",
3458     "10",
3459     "1",
3460     "foo-bar",
3461     "blah.org",
3462     ".blah",
3463     "blah.",
3464     "Hello.",
3465     "!foo",
3466     "",
3467     "   ",
3468     "foo bar"
3469   };
3470
3471   const char *valid_signatures[] = {
3472     "",
3473     "sss",
3474     "i",
3475     "b"
3476   };
3477
3478   const char *invalid_signatures[] = {
3479     " ",
3480     "not a valid signature",
3481     "123",
3482     ".",
3483     "("
3484   };
3485   
3486   i = 0;
3487   while (i < _DBUS_N_ELEMENTS (lens))
3488     {
3489       if (!_dbus_string_init (&str))
3490         _dbus_assert_not_reached ("failed to init string");
3491
3492       set_max_length (&str, lens[i]);
3493       
3494       test_max_len (&str, lens[i]);
3495       _dbus_string_free (&str);
3496
3497       ++i;
3498     }
3499
3500   /* Test shortening and setting length */
3501   i = 0;
3502   while (i < _DBUS_N_ELEMENTS (lens))
3503     {
3504       int j;
3505       
3506       if (!_dbus_string_init (&str))
3507         _dbus_assert_not_reached ("failed to init string");
3508
3509       set_max_length (&str, lens[i]);
3510       
3511       if (!_dbus_string_set_length (&str, lens[i]))
3512         _dbus_assert_not_reached ("failed to set string length");
3513
3514       j = lens[i];
3515       while (j > 0)
3516         {
3517           _dbus_assert (_dbus_string_get_length (&str) == j);
3518           if (j > 0)
3519             {
3520               _dbus_string_shorten (&str, 1);
3521               _dbus_assert (_dbus_string_get_length (&str) == (j - 1));
3522             }
3523           --j;
3524         }
3525       
3526       _dbus_string_free (&str);
3527
3528       ++i;
3529     }
3530
3531   /* Test appending data */
3532   if (!_dbus_string_init (&str))
3533     _dbus_assert_not_reached ("failed to init string");
3534
3535   i = 0;
3536   while (i < 10)
3537     {
3538       if (!_dbus_string_append (&str, "a"))
3539         _dbus_assert_not_reached ("failed to append string to string\n");
3540
3541       _dbus_assert (_dbus_string_get_length (&str) == i * 2 + 1);
3542
3543       if (!_dbus_string_append_byte (&str, 'b'))
3544         _dbus_assert_not_reached ("failed to append byte to string\n");
3545
3546       _dbus_assert (_dbus_string_get_length (&str) == i * 2 + 2);
3547                     
3548       ++i;
3549     }
3550
3551   _dbus_string_free (&str);
3552
3553   /* Check steal_data */
3554   
3555   if (!_dbus_string_init (&str))
3556     _dbus_assert_not_reached ("failed to init string");
3557
3558   if (!_dbus_string_append (&str, "Hello World"))
3559     _dbus_assert_not_reached ("could not append to string");
3560
3561   i = _dbus_string_get_length (&str);
3562   
3563   if (!_dbus_string_steal_data (&str, &s))
3564     _dbus_assert_not_reached ("failed to steal data");
3565
3566   _dbus_assert (_dbus_string_get_length (&str) == 0);
3567   _dbus_assert (((int)strlen (s)) == i);
3568
3569   dbus_free (s);
3570
3571   /* Check move */
3572   
3573   if (!_dbus_string_append (&str, "Hello World"))
3574     _dbus_assert_not_reached ("could not append to string");
3575
3576   i = _dbus_string_get_length (&str);
3577
3578   if (!_dbus_string_init (&other))
3579     _dbus_assert_not_reached ("could not init string");
3580   
3581   if (!_dbus_string_move (&str, 0, &other, 0))
3582     _dbus_assert_not_reached ("could not move");
3583
3584   _dbus_assert (_dbus_string_get_length (&str) == 0);
3585   _dbus_assert (_dbus_string_get_length (&other) == i);
3586
3587   if (!_dbus_string_append (&str, "Hello World"))
3588     _dbus_assert_not_reached ("could not append to string");
3589   
3590   if (!_dbus_string_move (&str, 0, &other, _dbus_string_get_length (&other)))
3591     _dbus_assert_not_reached ("could not move");
3592
3593   _dbus_assert (_dbus_string_get_length (&str) == 0);
3594   _dbus_assert (_dbus_string_get_length (&other) == i * 2);
3595
3596     if (!_dbus_string_append (&str, "Hello World"))
3597     _dbus_assert_not_reached ("could not append to string");
3598   
3599   if (!_dbus_string_move (&str, 0, &other, _dbus_string_get_length (&other) / 2))
3600     _dbus_assert_not_reached ("could not move");
3601
3602   _dbus_assert (_dbus_string_get_length (&str) == 0);
3603   _dbus_assert (_dbus_string_get_length (&other) == i * 3);
3604   
3605   _dbus_string_free (&other);
3606
3607   /* Check copy */
3608   
3609   if (!_dbus_string_append (&str, "Hello World"))
3610     _dbus_assert_not_reached ("could not append to string");
3611
3612   i = _dbus_string_get_length (&str);
3613   
3614   if (!_dbus_string_init (&other))
3615     _dbus_assert_not_reached ("could not init string");
3616   
3617   if (!_dbus_string_copy (&str, 0, &other, 0))
3618     _dbus_assert_not_reached ("could not copy");
3619
3620   _dbus_assert (_dbus_string_get_length (&str) == i);
3621   _dbus_assert (_dbus_string_get_length (&other) == i);
3622
3623   if (!_dbus_string_copy (&str, 0, &other, _dbus_string_get_length (&other)))
3624     _dbus_assert_not_reached ("could not copy");
3625
3626   _dbus_assert (_dbus_string_get_length (&str) == i);
3627   _dbus_assert (_dbus_string_get_length (&other) == i * 2);
3628   _dbus_assert (_dbus_string_equal_c_str (&other,
3629                                           "Hello WorldHello World"));
3630
3631   if (!_dbus_string_copy (&str, 0, &other, _dbus_string_get_length (&other) / 2))
3632     _dbus_assert_not_reached ("could not copy");
3633
3634   _dbus_assert (_dbus_string_get_length (&str) == i);
3635   _dbus_assert (_dbus_string_get_length (&other) == i * 3);
3636   _dbus_assert (_dbus_string_equal_c_str (&other,
3637                                           "Hello WorldHello WorldHello World"));
3638   
3639   _dbus_string_free (&str);
3640   _dbus_string_free (&other);
3641
3642   /* Check replace */
3643
3644   if (!_dbus_string_init (&str))
3645     _dbus_assert_not_reached ("failed to init string");
3646   
3647   if (!_dbus_string_append (&str, "Hello World"))
3648     _dbus_assert_not_reached ("could not append to string");
3649
3650   i = _dbus_string_get_length (&str);
3651   
3652   if (!_dbus_string_init (&other))
3653     _dbus_assert_not_reached ("could not init string");
3654   
3655   if (!_dbus_string_replace_len (&str, 0, _dbus_string_get_length (&str),
3656                                  &other, 0, _dbus_string_get_length (&other)))
3657     _dbus_assert_not_reached ("could not replace");
3658
3659   _dbus_assert (_dbus_string_get_length (&str) == i);
3660   _dbus_assert (_dbus_string_get_length (&other) == i);
3661   _dbus_assert (_dbus_string_equal_c_str (&other, "Hello World"));
3662   
3663   if (!_dbus_string_replace_len (&str, 0, _dbus_string_get_length (&str),
3664                                  &other, 5, 1))
3665     _dbus_assert_not_reached ("could not replace center space");
3666
3667   _dbus_assert (_dbus_string_get_length (&str) == i);
3668   _dbus_assert (_dbus_string_get_length (&other) == i * 2 - 1);
3669   _dbus_assert (_dbus_string_equal_c_str (&other,
3670                                           "HelloHello WorldWorld"));
3671
3672   
3673   if (!_dbus_string_replace_len (&str, 1, 1,
3674                                  &other,
3675                                  _dbus_string_get_length (&other) - 1,
3676                                  1))
3677     _dbus_assert_not_reached ("could not replace end character");
3678   
3679   _dbus_assert (_dbus_string_get_length (&str) == i);
3680   _dbus_assert (_dbus_string_get_length (&other) == i * 2 - 1);
3681   _dbus_assert (_dbus_string_equal_c_str (&other,
3682                                           "HelloHello WorldWorle"));
3683   
3684   _dbus_string_free (&str);
3685   _dbus_string_free (&other);
3686   
3687   /* Check append/get unichar */
3688   
3689   if (!_dbus_string_init (&str))
3690     _dbus_assert_not_reached ("failed to init string");
3691
3692   ch = 0;
3693   if (!_dbus_string_append_unichar (&str, 0xfffc))
3694     _dbus_assert_not_reached ("failed to append unichar");
3695
3696   _dbus_string_get_unichar (&str, 0, &ch, &i);
3697
3698   _dbus_assert (ch == 0xfffc);
3699   _dbus_assert (i == _dbus_string_get_length (&str));
3700
3701   _dbus_string_free (&str);
3702
3703   /* Check insert/set/get byte */
3704   
3705   if (!_dbus_string_init (&str))
3706     _dbus_assert_not_reached ("failed to init string");
3707
3708   if (!_dbus_string_append (&str, "Hello"))
3709     _dbus_assert_not_reached ("failed to append Hello");
3710
3711   _dbus_assert (_dbus_string_get_byte (&str, 0) == 'H');
3712   _dbus_assert (_dbus_string_get_byte (&str, 1) == 'e');
3713   _dbus_assert (_dbus_string_get_byte (&str, 2) == 'l');
3714   _dbus_assert (_dbus_string_get_byte (&str, 3) == 'l');
3715   _dbus_assert (_dbus_string_get_byte (&str, 4) == 'o');
3716
3717   _dbus_string_set_byte (&str, 1, 'q');
3718   _dbus_assert (_dbus_string_get_byte (&str, 1) == 'q');
3719
3720   if (!_dbus_string_insert_bytes (&str, 0, 1, 255))
3721     _dbus_assert_not_reached ("can't insert byte");
3722
3723   if (!_dbus_string_insert_bytes (&str, 2, 4, 'Z'))
3724     _dbus_assert_not_reached ("can't insert byte");
3725
3726   if (!_dbus_string_insert_bytes (&str, _dbus_string_get_length (&str), 1, 'W'))
3727     _dbus_assert_not_reached ("can't insert byte");
3728   
3729   _dbus_assert (_dbus_string_get_byte (&str, 0) == 255);
3730   _dbus_assert (_dbus_string_get_byte (&str, 1) == 'H');
3731   _dbus_assert (_dbus_string_get_byte (&str, 2) == 'Z');
3732   _dbus_assert (_dbus_string_get_byte (&str, 3) == 'Z');
3733   _dbus_assert (_dbus_string_get_byte (&str, 4) == 'Z');
3734   _dbus_assert (_dbus_string_get_byte (&str, 5) == 'Z');
3735   _dbus_assert (_dbus_string_get_byte (&str, 6) == 'q');
3736   _dbus_assert (_dbus_string_get_byte (&str, 7) == 'l');
3737   _dbus_assert (_dbus_string_get_byte (&str, 8) == 'l');
3738   _dbus_assert (_dbus_string_get_byte (&str, 9) == 'o');
3739   _dbus_assert (_dbus_string_get_byte (&str, 10) == 'W');
3740
3741   _dbus_string_free (&str);
3742   
3743   /* Check append/parse int/double */
3744   
3745   if (!_dbus_string_init (&str))
3746     _dbus_assert_not_reached ("failed to init string");
3747
3748   if (!_dbus_string_append_int (&str, 27))
3749     _dbus_assert_not_reached ("failed to append int");
3750
3751   i = _dbus_string_get_length (&str);
3752
3753   if (!_dbus_string_parse_int (&str, 0, &v, &end))
3754     _dbus_assert_not_reached ("failed to parse int");
3755
3756   _dbus_assert (v == 27);
3757   _dbus_assert (end == i);
3758
3759   _dbus_string_free (&str);
3760   
3761   if (!_dbus_string_init (&str))
3762     _dbus_assert_not_reached ("failed to init string");
3763   
3764   if (!_dbus_string_append_double (&str, 50.3))
3765     _dbus_assert_not_reached ("failed to append float");
3766
3767   i = _dbus_string_get_length (&str);
3768
3769   if (!_dbus_string_parse_double (&str, 0, &d, &end))
3770     _dbus_assert_not_reached ("failed to parse float");
3771
3772   _dbus_assert (d > (50.3 - 1e-6) && d < (50.3 + 1e-6));
3773   _dbus_assert (end == i);
3774
3775   _dbus_string_free (&str);
3776
3777   /* Test find */
3778   if (!_dbus_string_init (&str))
3779     _dbus_assert_not_reached ("failed to init string");
3780
3781   if (!_dbus_string_append (&str, "Hello"))
3782     _dbus_assert_not_reached ("couldn't append to string");
3783   
3784   if (!_dbus_string_find (&str, 0, "He", &i))
3785     _dbus_assert_not_reached ("didn't find 'He'");
3786   _dbus_assert (i == 0);
3787
3788   if (!_dbus_string_find (&str, 0, "Hello", &i))
3789     _dbus_assert_not_reached ("didn't find 'Hello'");
3790   _dbus_assert (i == 0);
3791   
3792   if (!_dbus_string_find (&str, 0, "ello", &i))
3793     _dbus_assert_not_reached ("didn't find 'ello'");
3794   _dbus_assert (i == 1);
3795
3796   if (!_dbus_string_find (&str, 0, "lo", &i))
3797     _dbus_assert_not_reached ("didn't find 'lo'");
3798   _dbus_assert (i == 3);
3799
3800   if (!_dbus_string_find (&str, 2, "lo", &i))
3801     _dbus_assert_not_reached ("didn't find 'lo'");
3802   _dbus_assert (i == 3);
3803
3804   if (_dbus_string_find (&str, 4, "lo", &i))
3805     _dbus_assert_not_reached ("did find 'lo'");
3806   
3807   if (!_dbus_string_find (&str, 0, "l", &i))
3808     _dbus_assert_not_reached ("didn't find 'l'");
3809   _dbus_assert (i == 2);
3810
3811   if (!_dbus_string_find (&str, 0, "H", &i))
3812     _dbus_assert_not_reached ("didn't find 'H'");
3813   _dbus_assert (i == 0);
3814
3815   if (!_dbus_string_find (&str, 0, "", &i))
3816     _dbus_assert_not_reached ("didn't find ''");
3817   _dbus_assert (i == 0);
3818   
3819   if (_dbus_string_find (&str, 0, "Hello!", NULL))
3820     _dbus_assert_not_reached ("Did find 'Hello!'");
3821
3822   if (_dbus_string_find (&str, 0, "Oh, Hello", NULL))
3823     _dbus_assert_not_reached ("Did find 'Oh, Hello'");
3824   
3825   if (_dbus_string_find (&str, 0, "ill", NULL))
3826     _dbus_assert_not_reached ("Did find 'ill'");
3827
3828   if (_dbus_string_find (&str, 0, "q", NULL))
3829     _dbus_assert_not_reached ("Did find 'q'");
3830
3831   if (!_dbus_string_find_to (&str, 0, 2, "He", NULL))
3832     _dbus_assert_not_reached ("Didn't find 'He'");
3833
3834   if (_dbus_string_find_to (&str, 0, 2, "Hello", NULL))
3835     _dbus_assert_not_reached ("Did find 'Hello'");
3836
3837   if (!_dbus_string_find_byte_backward (&str, _dbus_string_get_length (&str), 'H', &i))
3838     _dbus_assert_not_reached ("Did not find 'H'");
3839   _dbus_assert (i == 0);
3840
3841   if (!_dbus_string_find_byte_backward (&str, _dbus_string_get_length (&str), 'o', &i))
3842     _dbus_assert_not_reached ("Did not find 'o'");
3843   _dbus_assert (i == _dbus_string_get_length (&str) - 1);
3844
3845   if (_dbus_string_find_byte_backward (&str, _dbus_string_get_length (&str) - 1, 'o', &i))
3846     _dbus_assert_not_reached ("Did find 'o'");
3847   _dbus_assert (i == -1);
3848
3849   if (_dbus_string_find_byte_backward (&str, 1, 'e', &i))
3850     _dbus_assert_not_reached ("Did find 'e'");
3851   _dbus_assert (i == -1);
3852
3853   if (!_dbus_string_find_byte_backward (&str, 2, 'e', &i))
3854     _dbus_assert_not_reached ("Didn't find 'e'");
3855   _dbus_assert (i == 1);
3856   
3857   _dbus_string_free (&str);
3858
3859   /* Hex encoding */
3860   _dbus_string_init_const (&str, "cafebabe, this is a bogus hex string");
3861   if (!_dbus_string_init (&other))
3862     _dbus_assert_not_reached ("could not init string");
3863
3864   if (!_dbus_string_hex_decode (&str, 0, &end, &other, 0))
3865     _dbus_assert_not_reached ("deccoded bogus hex string with no error");
3866
3867   _dbus_assert (end == 8);
3868
3869   _dbus_string_free (&other);
3870
3871   test_roundtrips (test_hex_roundtrip);
3872
3873   /* Path validation */
3874   i = 0;
3875   while (i < (int) _DBUS_N_ELEMENTS (valid_paths))
3876     {
3877       _dbus_string_init_const (&str, valid_paths[i]);
3878
3879       if (!_dbus_string_validate_path (&str, 0,
3880                                        _dbus_string_get_length (&str)))
3881         {
3882           _dbus_warn ("Path \"%s\" should have been valid\n", valid_paths[i]);
3883           _dbus_assert_not_reached ("invalid path");
3884         }
3885       
3886       ++i;
3887     }
3888
3889   i = 0;
3890   while (i < (int) _DBUS_N_ELEMENTS (invalid_paths))
3891     {
3892       _dbus_string_init_const (&str, invalid_paths[i]);
3893       
3894       if (_dbus_string_validate_path (&str, 0,
3895                                       _dbus_string_get_length (&str)))
3896         {
3897           _dbus_warn ("Path \"%s\" should have been invalid\n", invalid_paths[i]);
3898           _dbus_assert_not_reached ("valid path");
3899         }
3900       
3901       ++i;
3902     }
3903
3904   /* Interface validation */
3905   i = 0;
3906   while (i < (int) _DBUS_N_ELEMENTS (valid_interfaces))
3907     {
3908       _dbus_string_init_const (&str, valid_interfaces[i]);
3909
3910       if (!_dbus_string_validate_interface (&str, 0,
3911                                             _dbus_string_get_length (&str)))
3912         {
3913           _dbus_warn ("Interface \"%s\" should have been valid\n", valid_interfaces[i]);
3914           _dbus_assert_not_reached ("invalid interface");
3915         }
3916       
3917       ++i;
3918     }
3919
3920   i = 0;
3921   while (i < (int) _DBUS_N_ELEMENTS (invalid_interfaces))
3922     {
3923       _dbus_string_init_const (&str, invalid_interfaces[i]);
3924       
3925       if (_dbus_string_validate_interface (&str, 0,
3926                                            _dbus_string_get_length (&str)))
3927         {
3928           _dbus_warn ("Interface \"%s\" should have been invalid\n", invalid_interfaces[i]);
3929           _dbus_assert_not_reached ("valid interface");
3930         }
3931       
3932       ++i;
3933     }
3934
3935   /* Service validation (check that valid interfaces are valid services,
3936    * and invalid interfaces are invalid services except if they start with ':')
3937    */
3938   i = 0;
3939   while (i < (int) _DBUS_N_ELEMENTS (valid_interfaces))
3940     {
3941       _dbus_string_init_const (&str, valid_interfaces[i]);
3942
3943       if (!_dbus_string_validate_service (&str, 0,
3944                                           _dbus_string_get_length (&str)))
3945         {
3946           _dbus_warn ("Service \"%s\" should have been valid\n", valid_interfaces[i]);
3947           _dbus_assert_not_reached ("invalid service");
3948         }
3949       
3950       ++i;
3951     }
3952
3953   i = 0;
3954   while (i < (int) _DBUS_N_ELEMENTS (invalid_interfaces))
3955     {
3956       if (invalid_interfaces[i][0] != ':')
3957         {
3958           _dbus_string_init_const (&str, invalid_interfaces[i]);
3959           
3960           if (_dbus_string_validate_service (&str, 0,
3961                                              _dbus_string_get_length (&str)))
3962             {
3963               _dbus_warn ("Service \"%s\" should have been invalid\n", invalid_interfaces[i]);
3964               _dbus_assert_not_reached ("valid service");
3965             }
3966         }
3967       
3968       ++i;
3969     }
3970
3971   /* Base service validation */
3972   i = 0;
3973   while (i < (int) _DBUS_N_ELEMENTS (valid_base_services))
3974     {
3975       _dbus_string_init_const (&str, valid_base_services[i]);
3976
3977       if (!_dbus_string_validate_service (&str, 0,
3978                                           _dbus_string_get_length (&str)))
3979         {
3980           _dbus_warn ("Service \"%s\" should have been valid\n", valid_base_services[i]);
3981           _dbus_assert_not_reached ("invalid base service");
3982         }
3983       
3984       ++i;
3985     }
3986
3987   i = 0;
3988   while (i < (int) _DBUS_N_ELEMENTS (invalid_base_services))
3989     {
3990       _dbus_string_init_const (&str, invalid_base_services[i]);
3991       
3992       if (_dbus_string_validate_service (&str, 0,
3993                                          _dbus_string_get_length (&str)))
3994         {
3995           _dbus_warn ("Service \"%s\" should have been invalid\n", invalid_base_services[i]);
3996           _dbus_assert_not_reached ("valid base service");
3997         }
3998       
3999       ++i;
4000     }
4001
4002
4003   /* Error name validation (currently identical to interfaces)
4004    */
4005   i = 0;
4006   while (i < (int) _DBUS_N_ELEMENTS (valid_interfaces))
4007     {
4008       _dbus_string_init_const (&str, valid_interfaces[i]);
4009
4010       if (!_dbus_string_validate_error_name (&str, 0,
4011                                              _dbus_string_get_length (&str)))
4012         {
4013           _dbus_warn ("Error name \"%s\" should have been valid\n", valid_interfaces[i]);
4014           _dbus_assert_not_reached ("invalid error name");
4015         }
4016       
4017       ++i;
4018     }
4019
4020   i = 0;
4021   while (i < (int) _DBUS_N_ELEMENTS (invalid_interfaces))
4022     {
4023       if (invalid_interfaces[i][0] != ':')
4024         {
4025           _dbus_string_init_const (&str, invalid_interfaces[i]);
4026           
4027           if (_dbus_string_validate_error_name (&str, 0,
4028                                                 _dbus_string_get_length (&str)))
4029             {
4030               _dbus_warn ("Error name \"%s\" should have been invalid\n", invalid_interfaces[i]);
4031               _dbus_assert_not_reached ("valid error name");
4032             }
4033         }
4034       
4035       ++i;
4036     }
4037   
4038   /* Member validation */
4039   i = 0;
4040   while (i < (int) _DBUS_N_ELEMENTS (valid_members))
4041     {
4042       _dbus_string_init_const (&str, valid_members[i]);
4043
4044       if (!_dbus_string_validate_member (&str, 0,
4045                                          _dbus_string_get_length (&str)))
4046         {
4047           _dbus_warn ("Member \"%s\" should have been valid\n", valid_members[i]);
4048           _dbus_assert_not_reached ("invalid member");
4049         }
4050       
4051       ++i;
4052     }
4053
4054   i = 0;
4055   while (i < (int) _DBUS_N_ELEMENTS (invalid_members))
4056     {
4057       _dbus_string_init_const (&str, invalid_members[i]);
4058       
4059       if (_dbus_string_validate_member (&str, 0,
4060                                         _dbus_string_get_length (&str)))
4061         {
4062           _dbus_warn ("Member \"%s\" should have been invalid\n", invalid_members[i]);
4063           _dbus_assert_not_reached ("valid member");
4064         }
4065       
4066       ++i;
4067     }
4068
4069   /* Signature validation */
4070   i = 0;
4071   while (i < (int) _DBUS_N_ELEMENTS (valid_signatures))
4072     {
4073       _dbus_string_init_const (&str, valid_signatures[i]);
4074
4075       if (!_dbus_string_validate_signature (&str, 0,
4076                                             _dbus_string_get_length (&str)))
4077         {
4078           _dbus_warn ("Signature \"%s\" should have been valid\n", valid_signatures[i]);
4079           _dbus_assert_not_reached ("invalid signature");
4080         }
4081       
4082       ++i;
4083     }
4084
4085   i = 0;
4086   while (i < (int) _DBUS_N_ELEMENTS (invalid_signatures))
4087     {
4088       _dbus_string_init_const (&str, invalid_signatures[i]);
4089       
4090       if (_dbus_string_validate_signature (&str, 0,
4091                                            _dbus_string_get_length (&str)))
4092         {
4093           _dbus_warn ("Signature \"%s\" should have been invalid\n", invalid_signatures[i]);
4094           _dbus_assert_not_reached ("valid signature");
4095         }
4096       
4097       ++i;
4098     }
4099   
4100   /* Validate claimed length longer than real length */
4101   _dbus_string_init_const (&str, "abc.efg");
4102   if (_dbus_string_validate_service (&str, 0, 8))
4103     _dbus_assert_not_reached ("validated too-long string");
4104   if (_dbus_string_validate_interface (&str, 0, 8))
4105     _dbus_assert_not_reached ("validated too-long string");
4106   if (_dbus_string_validate_error_name (&str, 0, 8))
4107     _dbus_assert_not_reached ("validated too-long string");
4108
4109   _dbus_string_init_const (&str, "abc");
4110   if (_dbus_string_validate_member (&str, 0, 4))
4111     _dbus_assert_not_reached ("validated too-long string");
4112
4113   _dbus_string_init_const (&str, "sss");
4114   if (_dbus_string_validate_signature (&str, 0, 4))
4115     _dbus_assert_not_reached ("validated too-long signature");
4116   
4117   /* Validate string exceeding max name length */
4118   if (!_dbus_string_init (&str))
4119     _dbus_assert_not_reached ("no memory");
4120
4121   while (_dbus_string_get_length (&str) <= DBUS_MAXIMUM_NAME_LENGTH)
4122     if (!_dbus_string_append (&str, "abc.def"))
4123       _dbus_assert_not_reached ("no memory");
4124
4125   if (_dbus_string_validate_service (&str, 0, _dbus_string_get_length (&str)))
4126     _dbus_assert_not_reached ("validated overmax string");
4127   if (_dbus_string_validate_interface (&str, 0, _dbus_string_get_length (&str)))
4128     _dbus_assert_not_reached ("validated overmax string");
4129   if (_dbus_string_validate_error_name (&str, 0, _dbus_string_get_length (&str)))
4130     _dbus_assert_not_reached ("validated overmax string");
4131
4132   /* overlong member */
4133   _dbus_string_set_length (&str, 0);
4134   while (_dbus_string_get_length (&str) <= DBUS_MAXIMUM_NAME_LENGTH)
4135     if (!_dbus_string_append (&str, "abc"))
4136       _dbus_assert_not_reached ("no memory");  
4137
4138   if (_dbus_string_validate_member (&str, 0, _dbus_string_get_length (&str)))
4139     _dbus_assert_not_reached ("validated overmax string");
4140
4141   /* overlong base service */
4142   _dbus_string_set_length (&str, 0);
4143   _dbus_string_append (&str, ":");
4144   while (_dbus_string_get_length (&str) <= DBUS_MAXIMUM_NAME_LENGTH)
4145     if (!_dbus_string_append (&str, "abc"))
4146       _dbus_assert_not_reached ("no memory");  
4147
4148   if (_dbus_string_validate_service (&str, 0, _dbus_string_get_length (&str)))
4149     _dbus_assert_not_reached ("validated overmax string");
4150   
4151   _dbus_string_free (&str);
4152   
4153   return TRUE;
4154 }
4155
4156 #endif /* DBUS_BUILD_TESTS */