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