2006-02-16 Robert McQueen <robot101@debian.org>
[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, 2005 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 #define DBUS_CAN_USE_DBUS_STRING_PRIVATE 1
31 #include "dbus-string-private.h"
32 #include "dbus-marshal-basic.h" /* probably should be removed by moving the usage of DBUS_TYPE
33                                  * into the marshaling-related files
34                                  */
35 /* for DBUS_VA_COPY */
36 #include "dbus-sysdeps.h"
37
38 /**
39  * @defgroup DBusString string class
40  * @ingroup  DBusInternals
41  * @brief DBusString data structure
42  *
43  * Types and functions related to DBusString. DBusString is intended
44  * to be a string class that makes it hard to mess up security issues
45  * (and just in general harder to write buggy code).  It should be
46  * used (or extended and then used) rather than the libc stuff in
47  * string.h.  The string class is a bit inconvenient at spots because
48  * it handles out-of-memory failures and tries to be extra-robust.
49  * 
50  * A DBusString has a maximum length set at initialization time; this
51  * can be used to ensure that a buffer doesn't get too big.  The
52  * _dbus_string_lengthen() method checks for overflow, and for max
53  * length being exceeded.
54  * 
55  * Try to avoid conversion to a plain C string, i.e. add methods on
56  * the string object instead, only convert to C string when passing
57  * things out to the public API. In particular, no sprintf, strcpy,
58  * strcat, any of that should be used. The GString feature of
59  * accepting negative numbers for "length of string" is also absent,
60  * because it could keep us from detecting bogus huge lengths. i.e. if
61  * we passed in some bogus huge length it would be taken to mean
62  * "current length of string" instead of "broken crack"
63  *
64  * @todo #DBusString needs a lot of cleaning up; some of the
65  * API is no longer used, and the API is pretty inconsistent.
66  * In particular all the "append" APIs, especially those involving
67  * alignment but probably lots of them, are no longer used by the
68  * marshaling code which always does "inserts" now.
69  */
70
71 /**
72  * @addtogroup DBusString
73  * @{
74  */
75
76 static void
77 fixup_alignment (DBusRealString *real)
78 {
79   unsigned char *aligned;
80   unsigned char *real_block;
81   unsigned int old_align_offset;
82
83   /* we have to have extra space in real->allocated for the align offset and nul byte */
84   _dbus_assert (real->len <= real->allocated - _DBUS_STRING_ALLOCATION_PADDING);
85   
86   old_align_offset = real->align_offset;
87   real_block = real->str - old_align_offset;
88   
89   aligned = _DBUS_ALIGN_ADDRESS (real_block, 8);
90
91   real->align_offset = aligned - real_block;
92   real->str = aligned;
93   
94   if (old_align_offset != real->align_offset)
95     {
96       /* Here comes the suck */
97       memmove (real_block + real->align_offset,
98                real_block + old_align_offset,
99                real->len + 1);
100     }
101
102   _dbus_assert (real->align_offset < 8);
103   _dbus_assert (_DBUS_ALIGN_ADDRESS (real->str, 8) == real->str);
104 }
105
106 static void
107 undo_alignment (DBusRealString *real)
108 {
109   if (real->align_offset != 0)
110     {
111       memmove (real->str - real->align_offset,
112                real->str,
113                real->len + 1);
114
115       real->str = real->str - real->align_offset;
116       real->align_offset = 0;
117     }
118 }
119
120 /**
121  * Initializes a string that can be up to the given allocation size
122  * before it has to realloc. The string starts life with zero length.
123  * The string must eventually be freed with _dbus_string_free().
124  * 
125  * @param str memory to hold the string
126  * @param allocate_size amount to preallocate
127  * @returns #TRUE on success, #FALSE if no memory
128  */
129 dbus_bool_t
130 _dbus_string_init_preallocated (DBusString *str,
131                                 int         allocate_size)
132 {
133   DBusRealString *real;
134   
135   _dbus_assert (str != NULL);
136
137   _dbus_assert (sizeof (DBusString) == sizeof (DBusRealString));
138   
139   real = (DBusRealString*) str;
140
141   /* It's very important not to touch anything
142    * other than real->str if we're going to fail,
143    * since we also use this function to reset
144    * an existing string, e.g. in _dbus_string_steal_data()
145    */
146   
147   real->str = dbus_malloc (_DBUS_STRING_ALLOCATION_PADDING + allocate_size);
148   if (real->str == NULL)
149     return FALSE;  
150   
151   real->allocated = _DBUS_STRING_ALLOCATION_PADDING + allocate_size;
152   real->len = 0;
153   real->str[real->len] = '\0';
154   
155   real->max_length = _DBUS_STRING_MAX_MAX_LENGTH;
156   real->constant = FALSE;
157   real->locked = FALSE;
158   real->invalid = FALSE;
159   real->align_offset = 0;
160   
161   fixup_alignment (real);
162   
163   return TRUE;
164 }
165
166 /**
167  * Initializes a string. The string starts life with zero length.  The
168  * string must eventually be freed with _dbus_string_free().
169  * 
170  * @param str memory to hold the string
171  * @returns #TRUE on success, #FALSE if no memory
172  */
173 dbus_bool_t
174 _dbus_string_init (DBusString *str)
175 {
176   return _dbus_string_init_preallocated (str, 0);
177 }
178
179 #ifdef DBUS_BUILD_TESTS
180 /* The max length thing is sort of a historical artifact
181  * from a feature that turned out to be dumb; perhaps
182  * we should purge it entirely. The problem with
183  * the feature is that it looks like memory allocation
184  * failure, but is not a transient or resolvable failure.
185  */
186 static void
187 set_max_length (DBusString *str,
188                 int         max_length)
189 {
190   DBusRealString *real;
191   
192   real = (DBusRealString*) str;
193
194   real->max_length = max_length;
195 }
196 #endif /* DBUS_BUILD_TESTS */
197
198 /**
199  * Initializes a constant string. The value parameter is not copied
200  * (should be static), and the string may never be modified.
201  * It is safe but not necessary to call _dbus_string_free()
202  * on a const string. The string has a length limit of MAXINT - 8.
203  * 
204  * @param str memory to use for the string
205  * @param value a string to be stored in str (not copied!!!)
206  */
207 void
208 _dbus_string_init_const (DBusString *str,
209                          const char *value)
210 {
211   _dbus_assert (value != NULL);
212   
213   _dbus_string_init_const_len (str, value,
214                                strlen (value));
215 }
216
217 /**
218  * Initializes a constant string with a length. The value parameter is
219  * not copied (should be static), and the string may never be
220  * modified.  It is safe but not necessary to call _dbus_string_free()
221  * on a const string.
222  * 
223  * @param str memory to use for the string
224  * @param value a string to be stored in str (not copied!!!)
225  * @param len the length to use
226  */
227 void
228 _dbus_string_init_const_len (DBusString *str,
229                              const char *value,
230                              int         len)
231 {
232   DBusRealString *real;
233   
234   _dbus_assert (str != NULL);
235   _dbus_assert (len == 0 || value != NULL);
236   _dbus_assert (len <= _DBUS_STRING_MAX_MAX_LENGTH);
237   _dbus_assert (len >= 0);
238   
239   real = (DBusRealString*) str;
240   
241   real->str = (unsigned char*) value;
242   real->len = len;
243   real->allocated = real->len + _DBUS_STRING_ALLOCATION_PADDING; /* a lie, just to avoid special-case assertions... */
244   real->max_length = real->len + 1;
245   real->constant = TRUE;
246   real->locked = TRUE;
247   real->invalid = FALSE;
248   real->align_offset = 0;
249
250   /* We don't require const strings to be 8-byte aligned as the
251    * memory is coming from elsewhere.
252    */
253 }
254
255 /**
256  * Frees a string created by _dbus_string_init().
257  *
258  * @param str memory where the string is stored.
259  */
260 void
261 _dbus_string_free (DBusString *str)
262 {
263   DBusRealString *real = (DBusRealString*) str;
264   DBUS_GENERIC_STRING_PREAMBLE (real);
265   
266   if (real->constant)
267     return;
268   dbus_free (real->str - real->align_offset);
269
270   real->invalid = TRUE;
271 }
272
273 #ifdef DBUS_BUILD_TESTS
274 /* Not using this feature at the moment,
275  * so marked DBUS_BUILD_TESTS-only
276  */
277 /**
278  * Locks a string such that any attempts to change the string will
279  * result in aborting the program. Also, if the string is wasting a
280  * lot of memory (allocation is sufficiently larger than what the
281  * string is really using), _dbus_string_lock() will realloc the
282  * string's data to "compact" it.
283  *
284  * @param str the string to lock.
285  */
286 void
287 _dbus_string_lock (DBusString *str)
288 {  
289   DBUS_LOCKED_STRING_PREAMBLE (str); /* can lock multiple times */
290
291   real->locked = TRUE;
292
293   /* Try to realloc to avoid excess memory usage, since
294    * we know we won't change the string further
295    */
296 #define MAX_WASTE 48
297   if (real->allocated - MAX_WASTE > real->len)
298     {
299       unsigned char *new_str;
300       int new_allocated;
301
302       new_allocated = real->len + _DBUS_STRING_ALLOCATION_PADDING;
303
304       new_str = dbus_realloc (real->str - real->align_offset,
305                               new_allocated);
306       if (new_str != NULL)
307         {
308           real->str = new_str + real->align_offset;
309           real->allocated = new_allocated;
310           fixup_alignment (real);
311         }
312     }
313 }
314 #endif /* DBUS_BUILD_TESTS */
315
316 static dbus_bool_t
317 reallocate_for_length (DBusRealString *real,
318                        int             new_length)
319 {
320   int new_allocated;
321   unsigned char *new_str;
322
323   /* at least double our old allocation to avoid O(n), avoiding
324    * overflow
325    */
326   if (real->allocated > (_DBUS_STRING_MAX_MAX_LENGTH + _DBUS_STRING_ALLOCATION_PADDING) / 2)
327     new_allocated = _DBUS_STRING_MAX_MAX_LENGTH + _DBUS_STRING_ALLOCATION_PADDING;
328   else
329     new_allocated = real->allocated * 2;
330
331   /* if you change the code just above here, run the tests without
332    * the following assert-only hack before you commit
333    */
334   /* This is keyed off asserts in addition to tests so when you
335    * disable asserts to profile, you don't get this destroyer
336    * of profiles.
337    */
338 #ifdef DBUS_DISABLE_ASSERT
339 #else
340 #ifdef DBUS_BUILD_TESTS
341   new_allocated = 0; /* ensure a realloc every time so that we go
342                       * through all malloc failure codepaths
343                       */
344 #endif /* DBUS_BUILD_TESTS */
345 #endif /* !DBUS_DISABLE_ASSERT */
346
347   /* But be sure we always alloc at least space for the new length */
348   new_allocated = MAX (new_allocated,
349                        new_length + _DBUS_STRING_ALLOCATION_PADDING);
350
351   _dbus_assert (new_allocated >= real->allocated); /* code relies on this */
352   new_str = dbus_realloc (real->str - real->align_offset, new_allocated);
353   if (_DBUS_UNLIKELY (new_str == NULL))
354     return FALSE;
355
356   real->str = new_str + real->align_offset;
357   real->allocated = new_allocated;
358   fixup_alignment (real);
359
360   return TRUE;
361 }
362
363 static dbus_bool_t
364 set_length (DBusRealString *real,
365             int             new_length)
366 {
367   /* Note, we are setting the length not including nul termination */
368
369   /* exceeding max length is the same as failure to allocate memory */
370   if (_DBUS_UNLIKELY (new_length > real->max_length))
371     return FALSE;
372   else if (new_length > (real->allocated - _DBUS_STRING_ALLOCATION_PADDING) &&
373            _DBUS_UNLIKELY (!reallocate_for_length (real, new_length)))
374     return FALSE;
375   else
376     {
377       real->len = new_length;
378       real->str[new_length] = '\0';
379       return TRUE;
380     }
381 }
382
383 static dbus_bool_t
384 open_gap (int             len,
385           DBusRealString *dest,
386           int             insert_at)
387 {
388   if (len == 0)
389     return TRUE;
390
391   if (len > dest->max_length - dest->len)
392     return FALSE; /* detected overflow of dest->len + len below */
393   
394   if (!set_length (dest, dest->len + len))
395     return FALSE;
396
397   memmove (dest->str + insert_at + len, 
398            dest->str + insert_at,
399            dest->len - len - insert_at);
400
401   return TRUE;
402 }
403
404 #ifndef _dbus_string_get_data
405 /**
406  * Gets the raw character buffer from the string.  The returned buffer
407  * will be nul-terminated, but note that strings may contain binary
408  * data so there may be extra nul characters prior to the termination.
409  * This function should be little-used, extend DBusString or add
410  * stuff to dbus-sysdeps.c instead. It's an error to use this
411  * function on a const string.
412  *
413  * @param str the string
414  * @returns the data
415  */
416 char*
417 _dbus_string_get_data (DBusString *str)
418 {
419   DBUS_STRING_PREAMBLE (str);
420   
421   return (char*) real->str;
422 }
423 #endif /* _dbus_string_get_data */
424
425 /* only do the function if we don't have the macro */
426 #ifndef _dbus_string_get_const_data
427 /**
428  * Gets the raw character buffer from a const string.
429  *
430  * @param str the string
431  * @returns the string data
432  */
433 const char*
434 _dbus_string_get_const_data (const DBusString  *str)
435 {
436   DBUS_CONST_STRING_PREAMBLE (str);
437   
438   return (const char*) real->str;
439 }
440 #endif /* _dbus_string_get_const_data */
441
442 /**
443  * Gets a sub-portion of the raw character buffer from the
444  * string. The "len" field is required simply for error
445  * checking, to be sure you don't try to use more
446  * string than exists. The nul termination of the
447  * returned buffer remains at the end of the entire
448  * string, not at start + len.
449  *
450  * @param str the string
451  * @param start byte offset to return
452  * @param len length of segment to return
453  * @returns the string data
454  */
455 char*
456 _dbus_string_get_data_len (DBusString *str,
457                            int         start,
458                            int         len)
459 {
460   DBUS_STRING_PREAMBLE (str);
461   _dbus_assert (start >= 0);
462   _dbus_assert (len >= 0);
463   _dbus_assert (start <= real->len);
464   _dbus_assert (len <= real->len - start);
465   
466   return (char*) real->str + start;
467 }
468
469 /* only do the function if we don't have the macro */
470 #ifndef _dbus_string_get_const_data_len
471 /**
472  * const version of _dbus_string_get_data_len().
473  *
474  * @param str the string
475  * @param start byte offset to return
476  * @param len length of segment to return
477  * @returns the string data
478  */
479 const char*
480 _dbus_string_get_const_data_len (const DBusString  *str,
481                                  int                start,
482                                  int                len)
483 {
484   DBUS_CONST_STRING_PREAMBLE (str);
485   _dbus_assert (start >= 0);
486   _dbus_assert (len >= 0);
487   _dbus_assert (start <= real->len);
488   _dbus_assert (len <= real->len - start);
489   
490   return (const char*) real->str + start;
491 }
492 #endif /* _dbus_string_get_const_data_len */
493
494 /* only do the function if we don't have the macro */
495 #ifndef _dbus_string_set_byte
496 /**
497  * Sets the value of the byte at the given position.
498  *
499  * @param str the string
500  * @param i the position
501  * @param byte the new value
502  */
503 void
504 _dbus_string_set_byte (DBusString    *str,
505                        int            i,
506                        unsigned char  byte)
507 {
508   DBUS_STRING_PREAMBLE (str);
509   _dbus_assert (i < real->len);
510   _dbus_assert (i >= 0);
511   
512   real->str[i] = byte;
513 }
514 #endif /* _dbus_string_set_byte */
515
516 /* only have the function if we didn't create a macro */
517 #ifndef _dbus_string_get_byte
518 /**
519  * Gets the byte at the given position. It is
520  * allowed to ask for the nul byte at the end of
521  * the string.
522  *
523  * @param str the string
524  * @param start the position
525  * @returns the byte at that position
526  */
527 unsigned char
528 _dbus_string_get_byte (const DBusString  *str,
529                        int                start)
530 {
531   DBUS_CONST_STRING_PREAMBLE (str);
532   _dbus_assert (start <= real->len);
533   _dbus_assert (start >= 0);
534   
535   return real->str[start];
536 }
537 #endif /* _dbus_string_get_byte */
538
539 /**
540  * Inserts a number of bytes of a given value at the
541  * given position.
542  *
543  * @param str the string
544  * @param i the position
545  * @param n_bytes number of bytes
546  * @param byte the value to insert
547  * @returns #TRUE on success
548  */
549 dbus_bool_t
550 _dbus_string_insert_bytes (DBusString   *str,
551                            int           i,
552                            int           n_bytes,
553                            unsigned char byte)
554 {
555   DBUS_STRING_PREAMBLE (str);
556   _dbus_assert (i <= real->len);
557   _dbus_assert (i >= 0);
558   _dbus_assert (n_bytes >= 0);
559
560   if (n_bytes == 0)
561     return TRUE;
562   
563   if (!open_gap (n_bytes, real, i))
564     return FALSE;
565   
566   memset (real->str + i, byte, n_bytes);
567
568   return TRUE;
569 }
570
571 /**
572  * Inserts a single byte at the given position.
573  *
574  * @param str the string
575  * @param i the position
576  * @param byte the value to insert
577  * @returns #TRUE on success
578  */
579 dbus_bool_t
580 _dbus_string_insert_byte (DBusString   *str,
581                            int           i,
582                            unsigned char byte)
583 {
584   DBUS_STRING_PREAMBLE (str);
585   _dbus_assert (i <= real->len);
586   _dbus_assert (i >= 0);
587   
588   if (!open_gap (1, real, i))
589     return FALSE;
590
591   real->str[i] = byte;
592
593   return TRUE;
594 }
595
596 /**
597  * Like _dbus_string_get_data(), but removes the
598  * gotten data from the original string. The caller
599  * must free the data returned. This function may
600  * fail due to lack of memory, and return #FALSE.
601  *
602  * @param str the string
603  * @param data_return location to return the buffer
604  * @returns #TRUE on success
605  */
606 dbus_bool_t
607 _dbus_string_steal_data (DBusString        *str,
608                          char             **data_return)
609 {
610   int old_max_length;
611   DBUS_STRING_PREAMBLE (str);
612   _dbus_assert (data_return != NULL);
613
614   undo_alignment (real);
615   
616   *data_return = (char*) real->str;
617
618   old_max_length = real->max_length;
619   
620   /* reset the string */
621   if (!_dbus_string_init (str))
622     {
623       /* hrm, put it back then */
624       real->str = (unsigned char*) *data_return;
625       *data_return = NULL;
626       fixup_alignment (real);
627       return FALSE;
628     }
629
630   real->max_length = old_max_length;
631
632   return TRUE;
633 }
634
635 #ifdef DBUS_BUILD_TESTS
636 /**
637  * Like _dbus_string_get_data_len(), but removes the gotten data from
638  * the original string. The caller must free the data returned. This
639  * function may fail due to lack of memory, and return #FALSE.
640  * The returned string is nul-terminated and has length len.
641  *
642  * @todo this function is broken because on failure it
643  * may corrupt the source string.
644  * 
645  * @param str the string
646  * @param data_return location to return the buffer
647  * @param start the start of segment to steal
648  * @param len the length of segment to steal
649  * @returns #TRUE on success
650  */
651 dbus_bool_t
652 _dbus_string_steal_data_len (DBusString        *str,
653                              char             **data_return,
654                              int                start,
655                              int                len)
656 {
657   DBusString dest;
658   DBUS_STRING_PREAMBLE (str);
659   _dbus_assert (data_return != NULL);
660   _dbus_assert (start >= 0);
661   _dbus_assert (len >= 0);
662   _dbus_assert (start <= real->len);
663   _dbus_assert (len <= real->len - start);
664
665   if (!_dbus_string_init (&dest))
666     return FALSE;
667
668   set_max_length (&dest, real->max_length);
669   
670   if (!_dbus_string_move_len (str, start, len, &dest, 0))
671     {
672       _dbus_string_free (&dest);
673       return FALSE;
674     }
675
676   _dbus_warn ("Broken code in _dbus_string_steal_data_len(), see @todo, FIXME\n");
677   if (!_dbus_string_steal_data (&dest, data_return))
678     {
679       _dbus_string_free (&dest);
680       return FALSE;
681     }
682
683   _dbus_string_free (&dest);
684   return TRUE;
685 }
686 #endif /* DBUS_BUILD_TESTS */
687
688 /**
689  * Copies the data from the string into a char*
690  *
691  * @param str the string
692  * @param data_return place to return the data
693  * @returns #TRUE on success, #FALSE on no memory
694  */
695 dbus_bool_t
696 _dbus_string_copy_data (const DBusString  *str,
697                         char             **data_return)
698 {
699   DBUS_CONST_STRING_PREAMBLE (str);
700   _dbus_assert (data_return != NULL);
701   
702   *data_return = dbus_malloc (real->len + 1);
703   if (*data_return == NULL)
704     return FALSE;
705
706   memcpy (*data_return, real->str, real->len + 1);
707
708   return TRUE;
709 }
710
711 /**
712  * Copies the contents of a DBusString into a different
713  * buffer. The resulting buffer will be nul-terminated.
714  * 
715  * @param str a string
716  * @param buffer a C buffer to copy data to
717  * @param avail_len maximum length of C buffer
718  */
719 void
720 _dbus_string_copy_to_buffer (const DBusString  *str,
721                              char              *buffer,
722                              int                avail_len)
723 {
724   int copy_len;
725   DBUS_CONST_STRING_PREAMBLE (str);
726
727   _dbus_assert (avail_len >= 0);
728
729   copy_len = MIN (avail_len, real->len+1);
730   memcpy (buffer, real->str, copy_len);
731   if (avail_len > 0 && avail_len == copy_len)
732     buffer[avail_len-1] = '\0';
733 }
734
735 #ifdef DBUS_BUILD_TESTS
736 /**
737  * Copies a segment of the string into a char*
738  *
739  * @param str the string
740  * @param data_return place to return the data
741  * @param start start index
742  * @param len length to copy
743  * @returns #FALSE if no memory
744  */
745 dbus_bool_t
746 _dbus_string_copy_data_len (const DBusString  *str,
747                             char             **data_return,
748                             int                start,
749                             int                len)
750 {
751   DBusString dest;
752
753   DBUS_CONST_STRING_PREAMBLE (str);
754   _dbus_assert (data_return != NULL);
755   _dbus_assert (start >= 0);
756   _dbus_assert (len >= 0);
757   _dbus_assert (start <= real->len);
758   _dbus_assert (len <= real->len - start);
759
760   if (!_dbus_string_init (&dest))
761     return FALSE;
762
763   set_max_length (&dest, real->max_length);
764
765   if (!_dbus_string_copy_len (str, start, len, &dest, 0))
766     {
767       _dbus_string_free (&dest);
768       return FALSE;
769     }
770
771   if (!_dbus_string_steal_data (&dest, data_return))
772     {
773       _dbus_string_free (&dest);
774       return FALSE;
775     }
776
777   _dbus_string_free (&dest);
778   return TRUE;
779 }
780 #endif /* DBUS_BUILD_TESTS */
781
782 /* Only have the function if we don't have the macro */
783 #ifndef _dbus_string_get_length
784 /**
785  * Gets the length of a string (not including nul termination).
786  *
787  * @returns the length.
788  */
789 int
790 _dbus_string_get_length (const DBusString  *str)
791 {
792   DBUS_CONST_STRING_PREAMBLE (str);
793   
794   return real->len;
795 }
796 #endif /* !_dbus_string_get_length */
797
798 /**
799  * Makes a string longer by the given number of bytes.  Checks whether
800  * adding additional_length to the current length would overflow an
801  * integer, and checks for exceeding a string's max length.
802  * The new bytes are not initialized, other than nul-terminating
803  * the end of the string. The uninitialized bytes may contain
804  * nul bytes or other junk.
805  *
806  * @param str a string
807  * @param additional_length length to add to the string.
808  * @returns #TRUE on success.
809  */
810 dbus_bool_t
811 _dbus_string_lengthen (DBusString *str,
812                        int         additional_length)
813 {
814   DBUS_STRING_PREAMBLE (str);  
815   _dbus_assert (additional_length >= 0);
816
817   if (_DBUS_UNLIKELY (additional_length > real->max_length - real->len))
818     return FALSE; /* would overflow */
819   
820   return set_length (real,
821                      real->len + additional_length);
822 }
823
824 /**
825  * Makes a string shorter by the given number of bytes.
826  *
827  * @param str a string
828  * @param length_to_remove length to remove from the string.
829  */
830 void
831 _dbus_string_shorten (DBusString *str,
832                       int         length_to_remove)
833 {
834   DBUS_STRING_PREAMBLE (str);
835   _dbus_assert (length_to_remove >= 0);
836   _dbus_assert (length_to_remove <= real->len);
837
838   set_length (real,
839               real->len - length_to_remove);
840 }
841
842 /**
843  * Sets the length of a string. Can be used to truncate or lengthen
844  * the string. If the string is lengthened, the function may fail and
845  * return #FALSE. Newly-added bytes are not initialized, as with
846  * _dbus_string_lengthen().
847  *
848  * @param str a string
849  * @param length new length of the string.
850  * @returns #FALSE on failure.
851  */
852 dbus_bool_t
853 _dbus_string_set_length (DBusString *str,
854                          int         length)
855 {
856   DBUS_STRING_PREAMBLE (str);
857   _dbus_assert (length >= 0);
858
859   return set_length (real, length);
860 }
861
862 static dbus_bool_t
863 align_insert_point_then_open_gap (DBusString *str,
864                                   int        *insert_at_p,
865                                   int         alignment,
866                                   int         gap_size)
867 {
868   unsigned long new_len; /* ulong to avoid _DBUS_ALIGN_VALUE overflow */
869   unsigned long gap_pos;
870   int insert_at;
871   int delta;
872   DBUS_STRING_PREAMBLE (str);
873   _dbus_assert (alignment >= 1);
874   _dbus_assert (alignment <= 8); /* it has to be a bug if > 8 */
875
876   insert_at = *insert_at_p;
877
878   _dbus_assert (insert_at <= real->len);
879   
880   gap_pos = _DBUS_ALIGN_VALUE (insert_at, alignment);
881   new_len = real->len + (gap_pos - insert_at) + gap_size;
882   
883   if (_DBUS_UNLIKELY (new_len > (unsigned long) real->max_length))
884     return FALSE;
885   
886   delta = new_len - real->len;
887   _dbus_assert (delta >= 0);
888
889   if (delta == 0) /* only happens if gap_size == 0 and insert_at is aligned already */
890     {
891       _dbus_assert (((unsigned long) *insert_at_p) == gap_pos);
892       return TRUE;
893     }
894
895   if (_DBUS_UNLIKELY (!open_gap (new_len - real->len,
896                                  real, insert_at)))
897     return FALSE;
898
899   /* nul the padding if we had to add any padding */
900   if (gap_size < delta)
901     {
902       memset (&real->str[insert_at], '\0',
903               gap_pos - insert_at);
904     }
905
906   *insert_at_p = gap_pos;
907   
908   return TRUE;
909 }
910
911 static dbus_bool_t
912 align_length_then_lengthen (DBusString *str,
913                             int         alignment,
914                             int         then_lengthen_by)
915 {
916   int insert_at;
917
918   insert_at = _dbus_string_get_length (str);
919   
920   return align_insert_point_then_open_gap (str,
921                                            &insert_at,
922                                            alignment, then_lengthen_by);
923 }
924
925 /**
926  * Align the length of a string to a specific alignment (typically 4 or 8)
927  * by appending nul bytes to the string.
928  *
929  * @param str a string
930  * @param alignment the alignment
931  * @returns #FALSE if no memory
932  */
933 dbus_bool_t
934 _dbus_string_align_length (DBusString *str,
935                            int         alignment)
936 {
937   return align_length_then_lengthen (str, alignment, 0);
938 }
939
940 /**
941  * Preallocate extra_bytes such that a future lengthening of the
942  * string by extra_bytes is guaranteed to succeed without an out of
943  * memory error.
944  *
945  * @param str a string
946  * @param extra_bytes bytes to alloc
947  * @returns #FALSE if no memory
948  */
949 dbus_bool_t
950 _dbus_string_alloc_space (DBusString        *str,
951                           int                extra_bytes)
952 {
953   if (!_dbus_string_lengthen (str, extra_bytes))
954     return FALSE;
955   _dbus_string_shorten (str, extra_bytes);
956
957   return TRUE;
958 }
959
960 static dbus_bool_t
961 append (DBusRealString *real,
962         const char     *buffer,
963         int             buffer_len)
964 {
965   if (buffer_len == 0)
966     return TRUE;
967
968   if (!_dbus_string_lengthen ((DBusString*)real, buffer_len))
969     return FALSE;
970
971   memcpy (real->str + (real->len - buffer_len),
972           buffer,
973           buffer_len);
974
975   return TRUE;
976 }
977
978 /**
979  * Appends a nul-terminated C-style string to a DBusString.
980  *
981  * @param str the DBusString
982  * @param buffer the nul-terminated characters to append
983  * @returns #FALSE if not enough memory.
984  */
985 dbus_bool_t
986 _dbus_string_append (DBusString *str,
987                      const char *buffer)
988 {
989   unsigned long buffer_len;
990   
991   DBUS_STRING_PREAMBLE (str);
992   _dbus_assert (buffer != NULL);
993   
994   buffer_len = strlen (buffer);
995   if (buffer_len > (unsigned long) real->max_length)
996     return FALSE;
997   
998   return append (real, buffer, buffer_len);
999 }
1000
1001 /** assign 2 bytes from one string to another */
1002 #define ASSIGN_2_OCTETS(p, octets) \
1003   *((dbus_uint16_t*)(p)) = *((dbus_uint16_t*)(octets));
1004
1005 /** assign 4 bytes from one string to another */
1006 #define ASSIGN_4_OCTETS(p, octets) \
1007   *((dbus_uint32_t*)(p)) = *((dbus_uint32_t*)(octets));
1008
1009 #ifdef DBUS_HAVE_INT64
1010 /** assign 8 bytes from one string to another */
1011 #define ASSIGN_8_OCTETS(p, octets) \
1012   *((dbus_uint64_t*)(p)) = *((dbus_uint64_t*)(octets));
1013 #else
1014 /** assign 8 bytes from one string to another */
1015 #define ASSIGN_8_OCTETS(p, octets)              \
1016 do {                                            \
1017   unsigned char *b;                             \
1018                                                 \
1019   b = p;                                        \
1020                                                 \
1021   *b++ = octets[0];                             \
1022   *b++ = octets[1];                             \
1023   *b++ = octets[2];                             \
1024   *b++ = octets[3];                             \
1025   *b++ = octets[4];                             \
1026   *b++ = octets[5];                             \
1027   *b++ = octets[6];                             \
1028   *b++ = octets[7];                             \
1029   _dbus_assert (b == p + 8);                    \
1030 } while (0)
1031 #endif /* DBUS_HAVE_INT64 */
1032
1033 #ifdef DBUS_BUILD_TESTS
1034 /**
1035  * Appends 4 bytes aligned on a 4 byte boundary
1036  * with any alignment padding initialized to 0.
1037  *
1038  * @param str the DBusString
1039  * @param octets 4 bytes to append
1040  * @returns #FALSE if not enough memory.
1041  */
1042 dbus_bool_t
1043 _dbus_string_append_4_aligned (DBusString         *str,
1044                                const unsigned char octets[4])
1045 {
1046   DBUS_STRING_PREAMBLE (str);
1047   
1048   if (!align_length_then_lengthen (str, 4, 4))
1049     return FALSE;
1050
1051   ASSIGN_4_OCTETS (real->str + (real->len - 4), octets);
1052
1053   return TRUE;
1054 }
1055 #endif /* DBUS_BUILD_TESTS */
1056
1057 #ifdef DBUS_BUILD_TESTS
1058 /**
1059  * Appends 8 bytes aligned on an 8 byte boundary
1060  * with any alignment padding initialized to 0.
1061  *
1062  * @param str the DBusString
1063  * @param octets 8 bytes to append
1064  * @returns #FALSE if not enough memory.
1065  */
1066 dbus_bool_t
1067 _dbus_string_append_8_aligned (DBusString         *str,
1068                                const unsigned char octets[8])
1069 {
1070   DBUS_STRING_PREAMBLE (str);
1071   
1072   if (!align_length_then_lengthen (str, 8, 8))
1073     return FALSE;
1074
1075   ASSIGN_8_OCTETS (real->str + (real->len - 8), octets);
1076
1077   return TRUE;
1078 }
1079 #endif /* DBUS_BUILD_TESTS */
1080
1081 /**
1082  * Inserts 2 bytes aligned on a 2 byte boundary
1083  * with any alignment padding initialized to 0.
1084  *
1085  * @param str the DBusString
1086  * @param insert_at where to insert
1087  * @param octets 2 bytes to insert
1088  * @returns #FALSE if not enough memory.
1089  */
1090 dbus_bool_t
1091 _dbus_string_insert_2_aligned (DBusString         *str,
1092                                int                 insert_at,
1093                                const unsigned char octets[4])
1094 {
1095   DBUS_STRING_PREAMBLE (str);
1096   
1097   if (!align_insert_point_then_open_gap (str, &insert_at, 2, 2))
1098     return FALSE;
1099
1100   ASSIGN_2_OCTETS (real->str + insert_at, octets);
1101
1102   return TRUE;
1103 }
1104
1105 /**
1106  * Inserts 4 bytes aligned on a 4 byte boundary
1107  * with any alignment padding initialized to 0.
1108  *
1109  * @param str the DBusString
1110  * @param insert_at where to insert
1111  * @param octets 4 bytes to insert
1112  * @returns #FALSE if not enough memory.
1113  */
1114 dbus_bool_t
1115 _dbus_string_insert_4_aligned (DBusString         *str,
1116                                int                 insert_at,
1117                                const unsigned char octets[4])
1118 {
1119   DBUS_STRING_PREAMBLE (str);
1120   
1121   if (!align_insert_point_then_open_gap (str, &insert_at, 4, 4))
1122     return FALSE;
1123
1124   ASSIGN_4_OCTETS (real->str + insert_at, octets);
1125
1126   return TRUE;
1127 }
1128
1129 /**
1130  * Inserts 8 bytes aligned on an 8 byte boundary
1131  * with any alignment padding initialized to 0.
1132  *
1133  * @param str the DBusString
1134  * @param insert_at where to insert
1135  * @param octets 8 bytes to insert
1136  * @returns #FALSE if not enough memory.
1137  */
1138 dbus_bool_t
1139 _dbus_string_insert_8_aligned (DBusString         *str,
1140                                int                 insert_at,
1141                                const unsigned char octets[8])
1142 {
1143   DBUS_STRING_PREAMBLE (str);
1144   
1145   if (!align_insert_point_then_open_gap (str, &insert_at, 8, 8))
1146     return FALSE;
1147
1148   _dbus_assert (_DBUS_ALIGN_VALUE (insert_at, 8) == (unsigned) insert_at);
1149   
1150   ASSIGN_8_OCTETS (real->str + insert_at, octets);
1151
1152   return TRUE;
1153 }
1154
1155
1156 /**
1157  * Inserts padding at *insert_at such to align it to the given
1158  * boundary. Initializes the padding to nul bytes. Sets *insert_at
1159  * to the aligned position.
1160  *
1161  * @param str the DBusString
1162  * @param insert_at location to be aligned
1163  * @param alignment alignment boundary (1, 2, 4, or 8)
1164  * @returns #FALSE if not enough memory.
1165  */
1166 dbus_bool_t
1167 _dbus_string_insert_alignment (DBusString        *str,
1168                                int               *insert_at,
1169                                int                alignment)
1170 {
1171   DBUS_STRING_PREAMBLE (str);
1172   
1173   if (!align_insert_point_then_open_gap (str, insert_at, alignment, 0))
1174     return FALSE;
1175
1176   _dbus_assert (_DBUS_ALIGN_VALUE (*insert_at, alignment) == (unsigned) *insert_at);
1177
1178   return TRUE;
1179 }
1180
1181 /**
1182  * Appends a printf-style formatted string
1183  * to the #DBusString.
1184  *
1185  * @param str the string
1186  * @param format printf format
1187  * @param args variable argument list
1188  * @returns #FALSE if no memory
1189  */
1190 dbus_bool_t
1191 _dbus_string_append_printf_valist  (DBusString        *str,
1192                                     const char        *format,
1193                                     va_list            args)
1194 {
1195   int len;
1196   char c;
1197   va_list args_copy;
1198
1199   DBUS_STRING_PREAMBLE (str);
1200
1201   DBUS_VA_COPY (args_copy, args);
1202
1203   /* Measure the message length without terminating nul */
1204   len = vsnprintf (&c, 1, format, args);
1205
1206   if (!_dbus_string_lengthen (str, len))
1207     {
1208       /* don't leak the copy */
1209       va_end (args_copy);
1210       return FALSE;
1211     }
1212   
1213   vsprintf ((char*) (real->str + (real->len - len)),
1214             format, args_copy);
1215
1216   va_end (args_copy);
1217
1218   return TRUE;
1219 }
1220
1221 /**
1222  * Appends a printf-style formatted string
1223  * to the #DBusString.
1224  *
1225  * @param str the string
1226  * @param format printf format
1227  * @returns #FALSE if no memory
1228  */
1229 dbus_bool_t
1230 _dbus_string_append_printf (DBusString        *str,
1231                             const char        *format,
1232                             ...)
1233 {
1234   va_list args;
1235   dbus_bool_t retval;
1236   
1237   va_start (args, format);
1238   retval = _dbus_string_append_printf_valist (str, format, args);
1239   va_end (args);
1240
1241   return retval;
1242 }
1243
1244 /**
1245  * Appends block of bytes with the given length to a DBusString.
1246  *
1247  * @param str the DBusString
1248  * @param buffer the bytes to append
1249  * @param len the number of bytes to append
1250  * @returns #FALSE if not enough memory.
1251  */
1252 dbus_bool_t
1253 _dbus_string_append_len (DBusString *str,
1254                          const char *buffer,
1255                          int         len)
1256 {
1257   DBUS_STRING_PREAMBLE (str);
1258   _dbus_assert (buffer != NULL);
1259   _dbus_assert (len >= 0);
1260
1261   return append (real, buffer, len);
1262 }
1263
1264 /**
1265  * Appends a single byte to the string, returning #FALSE
1266  * if not enough memory.
1267  *
1268  * @param str the string
1269  * @param byte the byte to append
1270  * @returns #TRUE on success
1271  */
1272 dbus_bool_t
1273 _dbus_string_append_byte (DBusString    *str,
1274                           unsigned char  byte)
1275 {
1276   DBUS_STRING_PREAMBLE (str);
1277
1278   if (!set_length (real, real->len + 1))
1279     return FALSE;
1280
1281   real->str[real->len-1] = byte;
1282
1283   return TRUE;
1284 }
1285
1286 #ifdef DBUS_BUILD_TESTS
1287 /**
1288  * Appends a single Unicode character, encoding the character
1289  * in UTF-8 format.
1290  *
1291  * @param str the string
1292  * @param ch the Unicode character
1293  */
1294 dbus_bool_t
1295 _dbus_string_append_unichar (DBusString    *str,
1296                              dbus_unichar_t ch)
1297 {
1298   int len;
1299   int first;
1300   int i;
1301   unsigned char *out;
1302   
1303   DBUS_STRING_PREAMBLE (str);
1304
1305   /* this code is from GLib but is pretty standard I think */
1306   
1307   len = 0;
1308   
1309   if (ch < 0x80)
1310     {
1311       first = 0;
1312       len = 1;
1313     }
1314   else if (ch < 0x800)
1315     {
1316       first = 0xc0;
1317       len = 2;
1318     }
1319   else if (ch < 0x10000)
1320     {
1321       first = 0xe0;
1322       len = 3;
1323     }
1324    else if (ch < 0x200000)
1325     {
1326       first = 0xf0;
1327       len = 4;
1328     }
1329   else if (ch < 0x4000000)
1330     {
1331       first = 0xf8;
1332       len = 5;
1333     }
1334   else
1335     {
1336       first = 0xfc;
1337       len = 6;
1338     }
1339
1340   if (len > (real->max_length - real->len))
1341     return FALSE; /* real->len + len would overflow */
1342   
1343   if (!set_length (real, real->len + len))
1344     return FALSE;
1345
1346   out = real->str + (real->len - len);
1347   
1348   for (i = len - 1; i > 0; --i)
1349     {
1350       out[i] = (ch & 0x3f) | 0x80;
1351       ch >>= 6;
1352     }
1353   out[0] = ch | first;
1354
1355   return TRUE;
1356 }
1357 #endif /* DBUS_BUILD_TESTS */
1358
1359 static void
1360 delete (DBusRealString *real,
1361         int             start,
1362         int             len)
1363 {
1364   if (len == 0)
1365     return;
1366   
1367   memmove (real->str + start, real->str + start + len, real->len - (start + len));
1368   real->len -= len;
1369   real->str[real->len] = '\0';
1370 }
1371
1372 /**
1373  * Deletes a segment of a DBusString with length len starting at
1374  * start. (Hint: to clear an entire string, setting length to 0
1375  * with _dbus_string_set_length() is easier.)
1376  *
1377  * @param str the DBusString
1378  * @param start where to start deleting
1379  * @param len the number of bytes to delete
1380  */
1381 void
1382 _dbus_string_delete (DBusString       *str,
1383                      int               start,
1384                      int               len)
1385 {
1386   DBUS_STRING_PREAMBLE (str);
1387   _dbus_assert (start >= 0);
1388   _dbus_assert (len >= 0);
1389   _dbus_assert (start <= real->len);
1390   _dbus_assert (len <= real->len - start);
1391   
1392   delete (real, start, len);
1393 }
1394
1395 static dbus_bool_t
1396 copy (DBusRealString *source,
1397       int             start,
1398       int             len,
1399       DBusRealString *dest,
1400       int             insert_at)
1401 {
1402   if (len == 0)
1403     return TRUE;
1404
1405   if (!open_gap (len, dest, insert_at))
1406     return FALSE;
1407   
1408   memmove (dest->str + insert_at,
1409            source->str + start,
1410            len);
1411
1412   return TRUE;
1413 }
1414
1415 /**
1416  * Checks assertions for two strings we're copying a segment between,
1417  * and declares real_source/real_dest variables.
1418  *
1419  * @param source the source string
1420  * @param start the starting offset
1421  * @param dest the dest string
1422  * @param insert_at where the copied segment is inserted
1423  */
1424 #define DBUS_STRING_COPY_PREAMBLE(source, start, dest, insert_at)       \
1425   DBusRealString *real_source = (DBusRealString*) source;               \
1426   DBusRealString *real_dest = (DBusRealString*) dest;                   \
1427   _dbus_assert ((source) != (dest));                                    \
1428   DBUS_GENERIC_STRING_PREAMBLE (real_source);                           \
1429   DBUS_GENERIC_STRING_PREAMBLE (real_dest);                             \
1430   _dbus_assert (!real_dest->constant);                                  \
1431   _dbus_assert (!real_dest->locked);                                    \
1432   _dbus_assert ((start) >= 0);                                          \
1433   _dbus_assert ((start) <= real_source->len);                           \
1434   _dbus_assert ((insert_at) >= 0);                                      \
1435   _dbus_assert ((insert_at) <= real_dest->len)
1436
1437 /**
1438  * Moves the end of one string into another string. Both strings
1439  * must be initialized, valid strings.
1440  *
1441  * @param source the source string
1442  * @param start where to chop off the source string
1443  * @param dest the destination string
1444  * @param insert_at where to move the chopped-off part of source string
1445  * @returns #FALSE if not enough memory
1446  */
1447 dbus_bool_t
1448 _dbus_string_move (DBusString       *source,
1449                    int               start,
1450                    DBusString       *dest,
1451                    int               insert_at)
1452 {
1453   DBusRealString *real_source = (DBusRealString*) source;
1454   _dbus_assert (start <= real_source->len);
1455   
1456   return _dbus_string_move_len (source, start,
1457                                 real_source->len - start,
1458                                 dest, insert_at);
1459 }
1460
1461 /**
1462  * Like _dbus_string_move(), but does not delete the section
1463  * of the source string that's copied to the dest string.
1464  *
1465  * @param source the source string
1466  * @param start where to start copying the source string
1467  * @param dest the destination string
1468  * @param insert_at where to place the copied part of source string
1469  * @returns #FALSE if not enough memory
1470  */
1471 dbus_bool_t
1472 _dbus_string_copy (const DBusString *source,
1473                    int               start,
1474                    DBusString       *dest,
1475                    int               insert_at)
1476 {
1477   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
1478
1479   return copy (real_source, start,
1480                real_source->len - start,
1481                real_dest,
1482                insert_at);
1483 }
1484
1485 /**
1486  * Like _dbus_string_move(), but can move a segment from
1487  * the middle of the source string.
1488  *
1489  * @todo this doesn't do anything with max_length field.
1490  * we should probably just kill the max_length field though.
1491  * 
1492  * @param source the source string
1493  * @param start first byte of source string to move
1494  * @param len length of segment to move
1495  * @param dest the destination string
1496  * @param insert_at where to move the bytes from the source string
1497  * @returns #FALSE if not enough memory
1498  */
1499 dbus_bool_t
1500 _dbus_string_move_len (DBusString       *source,
1501                        int               start,
1502                        int               len,
1503                        DBusString       *dest,
1504                        int               insert_at)
1505
1506 {
1507   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
1508   _dbus_assert (len >= 0);
1509   _dbus_assert ((start + len) <= real_source->len);
1510
1511
1512   if (len == 0)
1513     {
1514       return TRUE;
1515     }
1516   else if (start == 0 &&
1517            len == real_source->len &&
1518            real_dest->len == 0)
1519     {
1520       /* Short-circuit moving an entire existing string to an empty string
1521        * by just swapping the buffers.
1522        */
1523       /* we assume ->constant doesn't matter as you can't have
1524        * a constant string involved in a move.
1525        */
1526 #define ASSIGN_DATA(a, b) do {                  \
1527         (a)->str = (b)->str;                    \
1528         (a)->len = (b)->len;                    \
1529         (a)->allocated = (b)->allocated;        \
1530         (a)->align_offset = (b)->align_offset;  \
1531       } while (0)
1532       
1533       DBusRealString tmp;
1534
1535       ASSIGN_DATA (&tmp, real_source);
1536       ASSIGN_DATA (real_source, real_dest);
1537       ASSIGN_DATA (real_dest, &tmp);
1538
1539       return TRUE;
1540     }
1541   else
1542     {
1543       if (!copy (real_source, start, len,
1544                  real_dest,
1545                  insert_at))
1546         return FALSE;
1547       
1548       delete (real_source, start,
1549               len);
1550       
1551       return TRUE;
1552     }
1553 }
1554
1555 /**
1556  * Like _dbus_string_copy(), but can copy a segment from the middle of
1557  * the source string.
1558  *
1559  * @param source the source string
1560  * @param start where to start copying the source string
1561  * @param len length of segment to copy
1562  * @param dest the destination string
1563  * @param insert_at where to place the copied segment of source string
1564  * @returns #FALSE if not enough memory
1565  */
1566 dbus_bool_t
1567 _dbus_string_copy_len (const DBusString *source,
1568                        int               start,
1569                        int               len,
1570                        DBusString       *dest,
1571                        int               insert_at)
1572 {
1573   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
1574   _dbus_assert (len >= 0);
1575   _dbus_assert (start <= real_source->len);
1576   _dbus_assert (len <= real_source->len - start);
1577   
1578   return copy (real_source, start, len,
1579                real_dest,
1580                insert_at);
1581 }
1582
1583 /**
1584  * Replaces a segment of dest string with a segment of source string.
1585  *
1586  * @todo optimize the case where the two lengths are the same, and
1587  * avoid memmoving the data in the trailing part of the string twice.
1588  *
1589  * @todo avoid inserting the source into dest, then deleting
1590  * the replaced chunk of dest (which creates a potentially large
1591  * intermediate string). Instead, extend the replaced chunk
1592  * of dest with padding to the same size as the source chunk,
1593  * then copy in the source bytes.
1594  * 
1595  * @param source the source string
1596  * @param start where to start copying the source string
1597  * @param len length of segment to copy
1598  * @param dest the destination string
1599  * @param replace_at start of segment of dest string to replace
1600  * @param replace_len length of segment of dest string to replace
1601  * @returns #FALSE if not enough memory
1602  *
1603  */
1604 dbus_bool_t
1605 _dbus_string_replace_len (const DBusString *source,
1606                           int               start,
1607                           int               len,
1608                           DBusString       *dest,
1609                           int               replace_at,
1610                           int               replace_len)
1611 {
1612   DBUS_STRING_COPY_PREAMBLE (source, start, dest, replace_at);
1613   _dbus_assert (len >= 0);
1614   _dbus_assert (start <= real_source->len);
1615   _dbus_assert (len <= real_source->len - start);
1616   _dbus_assert (replace_at >= 0);
1617   _dbus_assert (replace_at <= real_dest->len);
1618   _dbus_assert (replace_len <= real_dest->len - replace_at);
1619
1620   if (!copy (real_source, start, len,
1621              real_dest, replace_at))
1622     return FALSE;
1623
1624   delete (real_dest, replace_at + len, replace_len);
1625
1626   return TRUE;
1627 }
1628
1629 /* Unicode macros and utf8_validate() from GLib Owen Taylor, Havoc
1630  * Pennington, and Tom Tromey are the authors and authorized relicense.
1631  */
1632
1633 /** computes length and mask of a unicode character
1634  * @param Char the char
1635  * @param Mask the mask variable to assign to
1636  * @param Len the length variable to assign to
1637  */
1638 #define UTF8_COMPUTE(Char, Mask, Len)                                         \
1639   if (Char < 128)                                                             \
1640     {                                                                         \
1641       Len = 1;                                                                \
1642       Mask = 0x7f;                                                            \
1643     }                                                                         \
1644   else if ((Char & 0xe0) == 0xc0)                                             \
1645     {                                                                         \
1646       Len = 2;                                                                \
1647       Mask = 0x1f;                                                            \
1648     }                                                                         \
1649   else if ((Char & 0xf0) == 0xe0)                                             \
1650     {                                                                         \
1651       Len = 3;                                                                \
1652       Mask = 0x0f;                                                            \
1653     }                                                                         \
1654   else if ((Char & 0xf8) == 0xf0)                                             \
1655     {                                                                         \
1656       Len = 4;                                                                \
1657       Mask = 0x07;                                                            \
1658     }                                                                         \
1659   else if ((Char & 0xfc) == 0xf8)                                             \
1660     {                                                                         \
1661       Len = 5;                                                                \
1662       Mask = 0x03;                                                            \
1663     }                                                                         \
1664   else if ((Char & 0xfe) == 0xfc)                                             \
1665     {                                                                         \
1666       Len = 6;                                                                \
1667       Mask = 0x01;                                                            \
1668     }                                                                         \
1669   else                                                                        \
1670     {                                                                         \
1671       Len = 0;                                                               \
1672       Mask = 0;                                                               \
1673     }
1674
1675 /**
1676  * computes length of a unicode character in UTF-8
1677  * @param Char the char
1678  */
1679 #define UTF8_LENGTH(Char)              \
1680   ((Char) < 0x80 ? 1 :                 \
1681    ((Char) < 0x800 ? 2 :               \
1682     ((Char) < 0x10000 ? 3 :            \
1683      ((Char) < 0x200000 ? 4 :          \
1684       ((Char) < 0x4000000 ? 5 : 6)))))
1685    
1686 /**
1687  * Gets a UTF-8 value.
1688  *
1689  * @param Result variable for extracted unicode char.
1690  * @param Chars the bytes to decode
1691  * @param Count counter variable
1692  * @param Mask mask for this char
1693  * @param Len length for this char in bytes
1694  */
1695 #define UTF8_GET(Result, Chars, Count, Mask, Len)                             \
1696   (Result) = (Chars)[0] & (Mask);                                             \
1697   for ((Count) = 1; (Count) < (Len); ++(Count))                               \
1698     {                                                                         \
1699       if (((Chars)[(Count)] & 0xc0) != 0x80)                                  \
1700         {                                                                     \
1701           (Result) = -1;                                                      \
1702           break;                                                              \
1703         }                                                                     \
1704       (Result) <<= 6;                                                         \
1705       (Result) |= ((Chars)[(Count)] & 0x3f);                                  \
1706     }
1707
1708 /**
1709  * Check whether a unicode char is in a valid range.
1710  *
1711  * @param Char the character
1712  */
1713 #define UNICODE_VALID(Char)                   \
1714     ((Char) < 0x110000 &&                     \
1715      (((Char) & 0xFFFFF800) != 0xD800) &&     \
1716      ((Char) < 0xFDD0 || (Char) > 0xFDEF) &&  \
1717      ((Char) & 0xFFFF) != 0xFFFF)
1718
1719 #ifdef DBUS_BUILD_TESTS
1720 /**
1721  * Gets a unicode character from a UTF-8 string. Does no validation;
1722  * you must verify that the string is valid UTF-8 in advance and must
1723  * pass in the start of a character.
1724  *
1725  * @param str the string
1726  * @param start the start of the UTF-8 character.
1727  * @param ch_return location to return the character
1728  * @param end_return location to return the byte index of next character
1729  */
1730 void
1731 _dbus_string_get_unichar (const DBusString *str,
1732                           int               start,
1733                           dbus_unichar_t   *ch_return,
1734                           int              *end_return)
1735 {
1736   int i, mask, len;
1737   dbus_unichar_t result;
1738   unsigned char c;
1739   unsigned char *p;
1740   DBUS_CONST_STRING_PREAMBLE (str);
1741   _dbus_assert (start >= 0);
1742   _dbus_assert (start <= real->len);
1743   
1744   if (ch_return)
1745     *ch_return = 0;
1746   if (end_return)
1747     *end_return = real->len;
1748   
1749   mask = 0;
1750   p = real->str + start;
1751   c = *p;
1752   
1753   UTF8_COMPUTE (c, mask, len);
1754   if (len == 0)
1755     return;
1756   UTF8_GET (result, p, i, mask, len);
1757
1758   if (result == (dbus_unichar_t)-1)
1759     return;
1760
1761   if (ch_return)
1762     *ch_return = result;
1763   if (end_return)
1764     *end_return = start + len;
1765 }
1766 #endif /* DBUS_BUILD_TESTS */
1767
1768 /**
1769  * Finds the given substring in the string,
1770  * returning #TRUE and filling in the byte index
1771  * where the substring was found, if it was found.
1772  * Returns #FALSE if the substring wasn't found.
1773  * Sets *start to the length of the string if the substring
1774  * is not found.
1775  *
1776  * @param str the string
1777  * @param start where to start looking
1778  * @param substr the substring
1779  * @param found return location for where it was found, or #NULL
1780  * @returns #TRUE if found
1781  */
1782 dbus_bool_t
1783 _dbus_string_find (const DBusString *str,
1784                    int               start,
1785                    const char       *substr,
1786                    int              *found)
1787 {
1788   return _dbus_string_find_to (str, start,
1789                                ((const DBusRealString*)str)->len,
1790                                substr, found);
1791 }
1792
1793 /**
1794  * Finds the given substring in the string,
1795  * up to a certain position,
1796  * returning #TRUE and filling in the byte index
1797  * where the substring was found, if it was found.
1798  * Returns #FALSE if the substring wasn't found.
1799  * Sets *start to the length of the string if the substring
1800  * is not found.
1801  *
1802  * @param str the string
1803  * @param start where to start looking
1804  * @param end where to stop looking
1805  * @param substr the substring
1806  * @param found return location for where it was found, or #NULL
1807  * @returns #TRUE if found
1808  */
1809 dbus_bool_t
1810 _dbus_string_find_to (const DBusString *str,
1811                       int               start,
1812                       int               end,
1813                       const char       *substr,
1814                       int              *found)
1815 {
1816   int i;
1817   DBUS_CONST_STRING_PREAMBLE (str);
1818   _dbus_assert (substr != NULL);
1819   _dbus_assert (start <= real->len);
1820   _dbus_assert (start >= 0);
1821   _dbus_assert (substr != NULL);
1822   _dbus_assert (end <= real->len);
1823   _dbus_assert (start <= end);
1824
1825   /* we always "find" an empty string */
1826   if (*substr == '\0')
1827     {
1828       if (found)
1829         *found = start;
1830       return TRUE;
1831     }
1832
1833   i = start;
1834   while (i < end)
1835     {
1836       if (real->str[i] == substr[0])
1837         {
1838           int j = i + 1;
1839           
1840           while (j < end)
1841             {
1842               if (substr[j - i] == '\0')
1843                 break;
1844               else if (real->str[j] != substr[j - i])
1845                 break;
1846               
1847               ++j;
1848             }
1849
1850           if (substr[j - i] == '\0')
1851             {
1852               if (found)
1853                 *found = i;
1854               return TRUE;
1855             }
1856         }
1857       
1858       ++i;
1859     }
1860
1861   if (found)
1862     *found = end;
1863   
1864   return FALSE;  
1865 }
1866
1867 /**
1868  * Finds a blank (space or tab) in the string. Returns #TRUE
1869  * if found, #FALSE otherwise. If a blank is not found sets
1870  * *found to the length of the string.
1871  *
1872  * @param str the string
1873  * @param start byte index to start looking
1874  * @param found place to store the location of the first blank
1875  * @returns #TRUE if a blank was found
1876  */
1877 dbus_bool_t
1878 _dbus_string_find_blank (const DBusString *str,
1879                          int               start,
1880                          int              *found)
1881 {
1882   int i;
1883   DBUS_CONST_STRING_PREAMBLE (str);
1884   _dbus_assert (start <= real->len);
1885   _dbus_assert (start >= 0);
1886   
1887   i = start;
1888   while (i < real->len)
1889     {
1890       if (real->str[i] == ' ' ||
1891           real->str[i] == '\t')
1892         {
1893           if (found)
1894             *found = i;
1895           return TRUE;
1896         }
1897       
1898       ++i;
1899     }
1900
1901   if (found)
1902     *found = real->len;
1903   
1904   return FALSE;
1905 }
1906
1907 /**
1908  * Skips blanks from start, storing the first non-blank in *end
1909  * (blank is space or tab).
1910  *
1911  * @param str the string
1912  * @param start where to start
1913  * @param end where to store the first non-blank byte index
1914  */
1915 void
1916 _dbus_string_skip_blank (const DBusString *str,
1917                          int               start,
1918                          int              *end)
1919 {
1920   int i;
1921   DBUS_CONST_STRING_PREAMBLE (str);
1922   _dbus_assert (start <= real->len);
1923   _dbus_assert (start >= 0);
1924   
1925   i = start;
1926   while (i < real->len)
1927     {
1928       if (!(real->str[i] == ' ' ||
1929             real->str[i] == '\t'))
1930         break;
1931       
1932       ++i;
1933     }
1934
1935   _dbus_assert (i == real->len || !(real->str[i] == ' ' ||
1936                                     real->str[i] == '\t'));
1937   
1938   if (end)
1939     *end = i;
1940 }
1941
1942 /**
1943  * Assigns a newline-terminated or \\r\\n-terminated line from the front
1944  * of the string to the given dest string. The dest string's previous
1945  * contents are deleted. If the source string contains no newline,
1946  * moves the entire source string to the dest string.
1947  *
1948  * @todo owen correctly notes that this is a stupid function (it was
1949  * written purely for test code,
1950  * e.g. dbus-message-builder.c). Probably should be enforced as test
1951  * code only with #ifdef DBUS_BUILD_TESTS
1952  * 
1953  * @param source the source string
1954  * @param dest the destination string (contents are replaced)
1955  * @returns #FALSE if no memory, or source has length 0
1956  */
1957 dbus_bool_t
1958 _dbus_string_pop_line (DBusString *source,
1959                        DBusString *dest)
1960 {
1961   int eol;
1962   dbus_bool_t have_newline;
1963   
1964   _dbus_string_set_length (dest, 0);
1965   
1966   eol = 0;
1967   if (_dbus_string_find (source, 0, "\n", &eol))
1968     {
1969       have_newline = TRUE;
1970       eol += 1; /* include newline */
1971     }
1972   else
1973     {
1974       eol = _dbus_string_get_length (source);
1975       have_newline = FALSE;
1976     }
1977
1978   if (eol == 0)
1979     return FALSE; /* eof */
1980   
1981   if (!_dbus_string_move_len (source, 0, eol,
1982                               dest, 0))
1983     {
1984       return FALSE;
1985     }
1986
1987   /* dump the newline and the \r if we have one */
1988   if (have_newline)
1989     {
1990       dbus_bool_t have_cr;
1991       
1992       _dbus_assert (_dbus_string_get_length (dest) > 0);
1993
1994       if (_dbus_string_get_length (dest) > 1 &&
1995           _dbus_string_get_byte (dest,
1996                                  _dbus_string_get_length (dest) - 2) == '\r')
1997         have_cr = TRUE;
1998       else
1999         have_cr = FALSE;
2000         
2001       _dbus_string_set_length (dest,
2002                                _dbus_string_get_length (dest) -
2003                                (have_cr ? 2 : 1));
2004     }
2005   
2006   return TRUE;
2007 }
2008
2009 #ifdef DBUS_BUILD_TESTS
2010 /**
2011  * Deletes up to and including the first blank space
2012  * in the string.
2013  *
2014  * @param str the string
2015  */
2016 void
2017 _dbus_string_delete_first_word (DBusString *str)
2018 {
2019   int i;
2020   
2021   if (_dbus_string_find_blank (str, 0, &i))
2022     _dbus_string_skip_blank (str, i, &i);
2023
2024   _dbus_string_delete (str, 0, i);
2025 }
2026 #endif
2027
2028 #ifdef DBUS_BUILD_TESTS
2029 /**
2030  * Deletes any leading blanks in the string
2031  *
2032  * @param str the string
2033  */
2034 void
2035 _dbus_string_delete_leading_blanks (DBusString *str)
2036 {
2037   int i;
2038   
2039   _dbus_string_skip_blank (str, 0, &i);
2040
2041   if (i > 0)
2042     _dbus_string_delete (str, 0, i);
2043 }
2044 #endif
2045
2046 /**
2047  * Tests two DBusString for equality.
2048  *
2049  * @todo memcmp is probably faster
2050  *
2051  * @param a first string
2052  * @param b second string
2053  * @returns #TRUE if equal
2054  */
2055 dbus_bool_t
2056 _dbus_string_equal (const DBusString *a,
2057                     const DBusString *b)
2058 {
2059   const unsigned char *ap;
2060   const unsigned char *bp;
2061   const unsigned char *a_end;
2062   const DBusRealString *real_a = (const DBusRealString*) a;
2063   const DBusRealString *real_b = (const DBusRealString*) b;
2064   DBUS_GENERIC_STRING_PREAMBLE (real_a);
2065   DBUS_GENERIC_STRING_PREAMBLE (real_b);
2066
2067   if (real_a->len != real_b->len)
2068     return FALSE;
2069
2070   ap = real_a->str;
2071   bp = real_b->str;
2072   a_end = real_a->str + real_a->len;
2073   while (ap != a_end)
2074     {
2075       if (*ap != *bp)
2076         return FALSE;
2077       
2078       ++ap;
2079       ++bp;
2080     }
2081
2082   return TRUE;
2083 }
2084
2085 #ifdef DBUS_BUILD_TESTS
2086 /**
2087  * Tests two DBusString for equality up to the given length.
2088  * The strings may be shorter than the given length.
2089  *
2090  * @todo write a unit test
2091  *
2092  * @todo memcmp is probably faster
2093  *
2094  * @param a first string
2095  * @param b second string
2096  * @param len the maximum length to look at
2097  * @returns #TRUE if equal for the given number of bytes
2098  */
2099 dbus_bool_t
2100 _dbus_string_equal_len (const DBusString *a,
2101                         const DBusString *b,
2102                         int               len)
2103 {
2104   const unsigned char *ap;
2105   const unsigned char *bp;
2106   const unsigned char *a_end;
2107   const DBusRealString *real_a = (const DBusRealString*) a;
2108   const DBusRealString *real_b = (const DBusRealString*) b;
2109   DBUS_GENERIC_STRING_PREAMBLE (real_a);
2110   DBUS_GENERIC_STRING_PREAMBLE (real_b);
2111
2112   if (real_a->len != real_b->len &&
2113       (real_a->len < len || real_b->len < len))
2114     return FALSE;
2115
2116   ap = real_a->str;
2117   bp = real_b->str;
2118   a_end = real_a->str + MIN (real_a->len, len);
2119   while (ap != a_end)
2120     {
2121       if (*ap != *bp)
2122         return FALSE;
2123       
2124       ++ap;
2125       ++bp;
2126     }
2127
2128   return TRUE;
2129 }
2130 #endif /* DBUS_BUILD_TESTS */
2131
2132 /**
2133  * Tests two sub-parts of two DBusString for equality.  The specified
2134  * range of the first string must exist; the specified start position
2135  * of the second string must exist.
2136  *
2137  * @todo write a unit test
2138  *
2139  * @todo memcmp is probably faster
2140  *
2141  * @param a first string
2142  * @param a_start where to start substring in first string
2143  * @param a_len length of substring in first string
2144  * @param b second string
2145  * @param b_start where to start substring in second string
2146  * @returns #TRUE if the two substrings are equal
2147  */
2148 dbus_bool_t
2149 _dbus_string_equal_substring (const DBusString  *a,
2150                               int                a_start,
2151                               int                a_len,
2152                               const DBusString  *b,
2153                               int                b_start)
2154 {
2155   const unsigned char *ap;
2156   const unsigned char *bp;
2157   const unsigned char *a_end;
2158   const DBusRealString *real_a = (const DBusRealString*) a;
2159   const DBusRealString *real_b = (const DBusRealString*) b;
2160   DBUS_GENERIC_STRING_PREAMBLE (real_a);
2161   DBUS_GENERIC_STRING_PREAMBLE (real_b);
2162   _dbus_assert (a_start >= 0);
2163   _dbus_assert (a_len >= 0);
2164   _dbus_assert (a_start <= real_a->len);
2165   _dbus_assert (a_len <= real_a->len - a_start);
2166   _dbus_assert (b_start >= 0);
2167   _dbus_assert (b_start <= real_b->len);
2168   
2169   if (a_len > real_b->len - b_start)
2170     return FALSE;
2171
2172   ap = real_a->str + a_start;
2173   bp = real_b->str + b_start;
2174   a_end = ap + a_len;
2175   while (ap != a_end)
2176     {
2177       if (*ap != *bp)
2178         return FALSE;
2179       
2180       ++ap;
2181       ++bp;
2182     }
2183
2184   _dbus_assert (bp <= (real_b->str + real_b->len));
2185   
2186   return TRUE;
2187 }
2188
2189 /**
2190  * Checks whether a string is equal to a C string.
2191  *
2192  * @param a the string
2193  * @param c_str the C string
2194  * @returns #TRUE if equal
2195  */
2196 dbus_bool_t
2197 _dbus_string_equal_c_str (const DBusString *a,
2198                           const char       *c_str)
2199 {
2200   const unsigned char *ap;
2201   const unsigned char *bp;
2202   const unsigned char *a_end;
2203   const DBusRealString *real_a = (const DBusRealString*) a;
2204   DBUS_GENERIC_STRING_PREAMBLE (real_a);
2205   _dbus_assert (c_str != NULL);
2206   
2207   ap = real_a->str;
2208   bp = (const unsigned char*) c_str;
2209   a_end = real_a->str + real_a->len;
2210   while (ap != a_end && *bp)
2211     {
2212       if (*ap != *bp)
2213         return FALSE;
2214       
2215       ++ap;
2216       ++bp;
2217     }
2218
2219   if (ap != a_end || *bp)
2220     return FALSE;
2221   
2222   return TRUE;
2223 }
2224
2225 #ifdef DBUS_BUILD_TESTS
2226 /**
2227  * Checks whether a string starts with the given C string.
2228  *
2229  * @param a the string
2230  * @param c_str the C string
2231  * @returns #TRUE if string starts with it
2232  */
2233 dbus_bool_t
2234 _dbus_string_starts_with_c_str (const DBusString *a,
2235                                 const char       *c_str)
2236 {
2237   const unsigned char *ap;
2238   const unsigned char *bp;
2239   const unsigned char *a_end;
2240   const DBusRealString *real_a = (const DBusRealString*) a;
2241   DBUS_GENERIC_STRING_PREAMBLE (real_a);
2242   _dbus_assert (c_str != NULL);
2243   
2244   ap = real_a->str;
2245   bp = (const unsigned char*) c_str;
2246   a_end = real_a->str + real_a->len;
2247   while (ap != a_end && *bp)
2248     {
2249       if (*ap != *bp)
2250         return FALSE;
2251       
2252       ++ap;
2253       ++bp;
2254     }
2255
2256   if (*bp == '\0')
2257     return TRUE;
2258   else
2259     return FALSE;
2260 }
2261 #endif /* DBUS_BUILD_TESTS */
2262
2263 /**
2264  * Appends a two-character hex digit to a string, where the hex digit
2265  * has the value of the given byte.
2266  *
2267  * @param str the string
2268  * @param byte the byte
2269  * @returns #FALSE if no memory
2270  */
2271 dbus_bool_t
2272 _dbus_string_append_byte_as_hex (DBusString *str,
2273                                  int         byte)
2274 {
2275   const char hexdigits[16] = {
2276     '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
2277     'a', 'b', 'c', 'd', 'e', 'f'
2278   };
2279
2280   if (!_dbus_string_append_byte (str,
2281                                  hexdigits[(byte >> 4)]))
2282     return FALSE;
2283   
2284   if (!_dbus_string_append_byte (str,
2285                                  hexdigits[(byte & 0x0f)]))
2286     {
2287       _dbus_string_set_length (str,
2288                                _dbus_string_get_length (str) - 1);
2289       return FALSE;
2290     }
2291
2292   return TRUE;
2293 }
2294
2295 /**
2296  * Encodes a string in hex, the way MD5 and SHA-1 are usually
2297  * encoded. (Each byte is two hex digits.)
2298  *
2299  * @param source the string to encode
2300  * @param start byte index to start encoding
2301  * @param dest string where encoded data should be placed
2302  * @param insert_at where to place encoded data
2303  * @returns #TRUE if encoding was successful, #FALSE if no memory etc.
2304  */
2305 dbus_bool_t
2306 _dbus_string_hex_encode (const DBusString *source,
2307                          int               start,
2308                          DBusString       *dest,
2309                          int               insert_at)
2310 {
2311   DBusString result;
2312   const unsigned char *p;
2313   const unsigned char *end;
2314   dbus_bool_t retval;
2315   
2316   _dbus_assert (start <= _dbus_string_get_length (source));
2317
2318   if (!_dbus_string_init (&result))
2319     return FALSE;
2320
2321   retval = FALSE;
2322   
2323   p = (const unsigned char*) _dbus_string_get_const_data (source);
2324   end = p + _dbus_string_get_length (source);
2325   p += start;
2326   
2327   while (p != end)
2328     {
2329       if (!_dbus_string_append_byte_as_hex (&result, *p))
2330         goto out;
2331       
2332       ++p;
2333     }
2334
2335   if (!_dbus_string_move (&result, 0, dest, insert_at))
2336     goto out;
2337
2338   retval = TRUE;
2339
2340  out:
2341   _dbus_string_free (&result);
2342   return retval;
2343 }
2344
2345 /**
2346  * Decodes a string from hex encoding.
2347  *
2348  * @param source the string to decode
2349  * @param start byte index to start decode
2350  * @param end_return return location of the end of the hex data, or #NULL
2351  * @param dest string where decoded data should be placed
2352  * @param insert_at where to place decoded data
2353  * @returns #TRUE if decoding was successful, #FALSE if no memory.
2354  */
2355 dbus_bool_t
2356 _dbus_string_hex_decode (const DBusString *source,
2357                          int               start,
2358                          int              *end_return,
2359                          DBusString       *dest,
2360                          int               insert_at)
2361 {
2362   DBusString result;
2363   const unsigned char *p;
2364   const unsigned char *end;
2365   dbus_bool_t retval;
2366   dbus_bool_t high_bits;
2367   
2368   _dbus_assert (start <= _dbus_string_get_length (source));
2369
2370   if (!_dbus_string_init (&result))
2371     return FALSE;
2372
2373   retval = FALSE;
2374
2375   high_bits = TRUE;
2376   p = (const unsigned char*) _dbus_string_get_const_data (source);
2377   end = p + _dbus_string_get_length (source);
2378   p += start;
2379   
2380   while (p != end)
2381     {
2382       unsigned int val;
2383
2384       switch (*p)
2385         {
2386         case '0':
2387           val = 0;
2388           break;
2389         case '1':
2390           val = 1;
2391           break;
2392         case '2':
2393           val = 2;
2394           break;
2395         case '3':
2396           val = 3;
2397           break;
2398         case '4':
2399           val = 4;
2400           break;
2401         case '5':
2402           val = 5;
2403           break;
2404         case '6':
2405           val = 6;
2406           break;
2407         case '7':
2408           val = 7;
2409           break;
2410         case '8':
2411           val = 8;
2412           break;
2413         case '9':
2414           val = 9;
2415           break;
2416         case 'a':
2417         case 'A':
2418           val = 10;
2419           break;
2420         case 'b':
2421         case 'B':
2422           val = 11;
2423           break;
2424         case 'c':
2425         case 'C':
2426           val = 12;
2427           break;
2428         case 'd':
2429         case 'D':
2430           val = 13;
2431           break;
2432         case 'e':
2433         case 'E':
2434           val = 14;
2435           break;
2436         case 'f':
2437         case 'F':
2438           val = 15;
2439           break;
2440         default:
2441           goto done;
2442         }
2443
2444       if (high_bits)
2445         {
2446           if (!_dbus_string_append_byte (&result,
2447                                          val << 4))
2448             goto out;
2449         }
2450       else
2451         {
2452           int len;
2453           unsigned char b;
2454
2455           len = _dbus_string_get_length (&result);
2456           
2457           b = _dbus_string_get_byte (&result, len - 1);
2458
2459           b |= val;
2460
2461           _dbus_string_set_byte (&result, len - 1, b);
2462         }
2463
2464       high_bits = !high_bits;
2465
2466       ++p;
2467     }
2468
2469  done:
2470   if (!_dbus_string_move (&result, 0, dest, insert_at))
2471     goto out;
2472
2473   if (end_return)
2474     *end_return = p - (const unsigned char*) _dbus_string_get_const_data (source);
2475
2476   retval = TRUE;
2477   
2478  out:
2479   _dbus_string_free (&result);  
2480   return retval;
2481 }
2482
2483 /**
2484  * Checks that the given range of the string is valid ASCII with no
2485  * nul bytes. If the given range is not entirely contained in the
2486  * string, returns #FALSE.
2487  *
2488  * @todo this is inconsistent with most of DBusString in that
2489  * it allows a start,len range that extends past the string end.
2490  * 
2491  * @param str the string
2492  * @param start first byte index to check
2493  * @param len number of bytes to check
2494  * @returns #TRUE if the byte range exists and is all valid ASCII
2495  */
2496 dbus_bool_t
2497 _dbus_string_validate_ascii (const DBusString *str,
2498                              int               start,
2499                              int               len)
2500 {
2501   const unsigned char *s;
2502   const unsigned char *end;
2503   DBUS_CONST_STRING_PREAMBLE (str);
2504   _dbus_assert (start >= 0);
2505   _dbus_assert (start <= real->len);
2506   _dbus_assert (len >= 0);
2507   
2508   if (len > real->len - start)
2509     return FALSE;
2510   
2511   s = real->str + start;
2512   end = s + len;
2513   while (s != end)
2514     {
2515       if (_DBUS_UNLIKELY (!_DBUS_ISASCII (*s)))
2516         return FALSE;
2517         
2518       ++s;
2519     }
2520   
2521   return TRUE;
2522 }
2523
2524 /**
2525  * Checks that the given range of the string is valid UTF-8. If the
2526  * given range is not entirely contained in the string, returns
2527  * #FALSE. If the string contains any nul bytes in the given range,
2528  * returns #FALSE. If the start and start+len are not on character
2529  * boundaries, returns #FALSE.
2530  *
2531  * @todo this is inconsistent with most of DBusString in that
2532  * it allows a start,len range that extends past the string end.
2533  * 
2534  * @param str the string
2535  * @param start first byte index to check
2536  * @param len number of bytes to check
2537  * @returns #TRUE if the byte range exists and is all valid UTF-8
2538  */
2539 dbus_bool_t
2540 _dbus_string_validate_utf8  (const DBusString *str,
2541                              int               start,
2542                              int               len)
2543 {
2544   const unsigned char *p;
2545   const unsigned char *end;
2546   DBUS_CONST_STRING_PREAMBLE (str);
2547   _dbus_assert (start >= 0);
2548   _dbus_assert (start <= real->len);
2549   _dbus_assert (len >= 0);
2550
2551   /* we are doing _DBUS_UNLIKELY() here which might be
2552    * dubious in a generic library like GLib, but in D-BUS
2553    * we know we're validating messages and that it would
2554    * only be evil/broken apps that would have invalid
2555    * UTF-8. Also, this function seems to be a performance
2556    * bottleneck in profiles.
2557    */
2558   
2559   if (_DBUS_UNLIKELY (len > real->len - start))
2560     return FALSE;
2561   
2562   p = real->str + start;
2563   end = p + len;
2564   
2565   while (p < end)
2566     {
2567       int i, mask, char_len;
2568       dbus_unichar_t result;
2569
2570       /* nul bytes considered invalid */
2571       if (*p == '\0')
2572         break;
2573       
2574       /* Special-case ASCII; this makes us go a lot faster in
2575        * D-BUS profiles where we are typically validating
2576        * function names and such. We have to know that
2577        * all following checks will pass for ASCII though,
2578        * comments follow ...
2579        */      
2580       if (*p < 128)
2581         {
2582           ++p;
2583           continue;
2584         }
2585       
2586       UTF8_COMPUTE (*p, mask, char_len);
2587
2588       if (_DBUS_UNLIKELY (char_len == 0))  /* ASCII: char_len == 1 */
2589         break;
2590
2591       /* check that the expected number of bytes exists in the remaining length */
2592       if (_DBUS_UNLIKELY ((end - p) < char_len)) /* ASCII: p < end and char_len == 1 */
2593         break;
2594         
2595       UTF8_GET (result, p, i, mask, char_len);
2596
2597       /* Check for overlong UTF-8 */
2598       if (_DBUS_UNLIKELY (UTF8_LENGTH (result) != char_len)) /* ASCII: UTF8_LENGTH == 1 */
2599         break;
2600 #if 0
2601       /* The UNICODE_VALID check below will catch this */
2602       if (_DBUS_UNLIKELY (result == (dbus_unichar_t)-1)) /* ASCII: result = ascii value */
2603         break;
2604 #endif
2605
2606       if (_DBUS_UNLIKELY (!UNICODE_VALID (result))) /* ASCII: always valid */
2607         break;
2608
2609       /* UNICODE_VALID should have caught it */
2610       _dbus_assert (result != (dbus_unichar_t)-1);
2611       
2612       p += char_len;
2613     }
2614
2615   /* See that we covered the entire length if a length was
2616    * passed in
2617    */
2618   if (_DBUS_UNLIKELY (p != end))
2619     return FALSE;
2620   else
2621     return TRUE;
2622 }
2623
2624 /**
2625  * Checks that the given range of the string is all nul bytes. If the
2626  * given range is not entirely contained in the string, returns
2627  * #FALSE.
2628  *
2629  * @todo this is inconsistent with most of DBusString in that
2630  * it allows a start,len range that extends past the string end.
2631  * 
2632  * @param str the string
2633  * @param start first byte index to check
2634  * @param len number of bytes to check
2635  * @returns #TRUE if the byte range exists and is all nul bytes
2636  */
2637 dbus_bool_t
2638 _dbus_string_validate_nul (const DBusString *str,
2639                            int               start,
2640                            int               len)
2641 {
2642   const unsigned char *s;
2643   const unsigned char *end;
2644   DBUS_CONST_STRING_PREAMBLE (str);
2645   _dbus_assert (start >= 0);
2646   _dbus_assert (len >= 0);
2647   _dbus_assert (start <= real->len);
2648   
2649   if (len > real->len - start)
2650     return FALSE;
2651   
2652   s = real->str + start;
2653   end = s + len;
2654   while (s != end)
2655     {
2656       if (_DBUS_UNLIKELY (*s != '\0'))
2657         return FALSE;
2658       ++s;
2659     }
2660   
2661   return TRUE;
2662 }
2663
2664 /**
2665  * Clears all allocated bytes in the string to zero.
2666  *
2667  * @param str the string
2668  */
2669 void
2670 _dbus_string_zero (DBusString *str)
2671 {
2672   DBUS_STRING_PREAMBLE (str);
2673
2674   memset (real->str - real->align_offset, '\0', real->allocated);
2675 }
2676 /** @} */
2677
2678 /* tests are in dbus-string-util.c */