2006-10-21 Havoc Pennington <hp@redhat.com>
[platform/upstream/dbus.git] / dbus / dbus-string.c
1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-string.c String utility class (internal to D-Bus implementation)
3  * 
4  * Copyright (C) 2002, 2003, 2004, 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   va_list args_copy;
1197
1198   DBUS_STRING_PREAMBLE (str);
1199
1200   DBUS_VA_COPY (args_copy, args);
1201
1202   /* Measure the message length without terminating nul */
1203   len = _dbus_printf_string_upper_bound (format, args);
1204
1205   if (!_dbus_string_lengthen (str, len))
1206     {
1207       /* don't leak the copy */
1208       va_end (args_copy);
1209       return FALSE;
1210     }
1211   
1212   vsprintf ((char*) (real->str + (real->len - len)),
1213             format, args_copy);
1214
1215   va_end (args_copy);
1216
1217   return TRUE;
1218 }
1219
1220 /**
1221  * Appends a printf-style formatted string
1222  * to the #DBusString.
1223  *
1224  * @param str the string
1225  * @param format printf format
1226  * @returns #FALSE if no memory
1227  */
1228 dbus_bool_t
1229 _dbus_string_append_printf (DBusString        *str,
1230                             const char        *format,
1231                             ...)
1232 {
1233   va_list args;
1234   dbus_bool_t retval;
1235   
1236   va_start (args, format);
1237   retval = _dbus_string_append_printf_valist (str, format, args);
1238   va_end (args);
1239
1240   return retval;
1241 }
1242
1243 /**
1244  * Appends block of bytes with the given length to a DBusString.
1245  *
1246  * @param str the DBusString
1247  * @param buffer the bytes to append
1248  * @param len the number of bytes to append
1249  * @returns #FALSE if not enough memory.
1250  */
1251 dbus_bool_t
1252 _dbus_string_append_len (DBusString *str,
1253                          const char *buffer,
1254                          int         len)
1255 {
1256   DBUS_STRING_PREAMBLE (str);
1257   _dbus_assert (buffer != NULL);
1258   _dbus_assert (len >= 0);
1259
1260   return append (real, buffer, len);
1261 }
1262
1263 /**
1264  * Appends a single byte to the string, returning #FALSE
1265  * if not enough memory.
1266  *
1267  * @param str the string
1268  * @param byte the byte to append
1269  * @returns #TRUE on success
1270  */
1271 dbus_bool_t
1272 _dbus_string_append_byte (DBusString    *str,
1273                           unsigned char  byte)
1274 {
1275   DBUS_STRING_PREAMBLE (str);
1276
1277   if (!set_length (real, real->len + 1))
1278     return FALSE;
1279
1280   real->str[real->len-1] = byte;
1281
1282   return TRUE;
1283 }
1284
1285 #ifdef DBUS_BUILD_TESTS
1286 /**
1287  * Appends a single Unicode character, encoding the character
1288  * in UTF-8 format.
1289  *
1290  * @param str the string
1291  * @param ch the Unicode character
1292  */
1293 dbus_bool_t
1294 _dbus_string_append_unichar (DBusString    *str,
1295                              dbus_unichar_t ch)
1296 {
1297   int len;
1298   int first;
1299   int i;
1300   unsigned char *out;
1301   
1302   DBUS_STRING_PREAMBLE (str);
1303
1304   /* this code is from GLib but is pretty standard I think */
1305   
1306   len = 0;
1307   
1308   if (ch < 0x80)
1309     {
1310       first = 0;
1311       len = 1;
1312     }
1313   else if (ch < 0x800)
1314     {
1315       first = 0xc0;
1316       len = 2;
1317     }
1318   else if (ch < 0x10000)
1319     {
1320       first = 0xe0;
1321       len = 3;
1322     }
1323    else if (ch < 0x200000)
1324     {
1325       first = 0xf0;
1326       len = 4;
1327     }
1328   else if (ch < 0x4000000)
1329     {
1330       first = 0xf8;
1331       len = 5;
1332     }
1333   else
1334     {
1335       first = 0xfc;
1336       len = 6;
1337     }
1338
1339   if (len > (real->max_length - real->len))
1340     return FALSE; /* real->len + len would overflow */
1341   
1342   if (!set_length (real, real->len + len))
1343     return FALSE;
1344
1345   out = real->str + (real->len - len);
1346   
1347   for (i = len - 1; i > 0; --i)
1348     {
1349       out[i] = (ch & 0x3f) | 0x80;
1350       ch >>= 6;
1351     }
1352   out[0] = ch | first;
1353
1354   return TRUE;
1355 }
1356 #endif /* DBUS_BUILD_TESTS */
1357
1358 static void
1359 delete (DBusRealString *real,
1360         int             start,
1361         int             len)
1362 {
1363   if (len == 0)
1364     return;
1365   
1366   memmove (real->str + start, real->str + start + len, real->len - (start + len));
1367   real->len -= len;
1368   real->str[real->len] = '\0';
1369 }
1370
1371 /**
1372  * Deletes a segment of a DBusString with length len starting at
1373  * start. (Hint: to clear an entire string, setting length to 0
1374  * with _dbus_string_set_length() is easier.)
1375  *
1376  * @param str the DBusString
1377  * @param start where to start deleting
1378  * @param len the number of bytes to delete
1379  */
1380 void
1381 _dbus_string_delete (DBusString       *str,
1382                      int               start,
1383                      int               len)
1384 {
1385   DBUS_STRING_PREAMBLE (str);
1386   _dbus_assert (start >= 0);
1387   _dbus_assert (len >= 0);
1388   _dbus_assert (start <= real->len);
1389   _dbus_assert (len <= real->len - start);
1390   
1391   delete (real, start, len);
1392 }
1393
1394 static dbus_bool_t
1395 copy (DBusRealString *source,
1396       int             start,
1397       int             len,
1398       DBusRealString *dest,
1399       int             insert_at)
1400 {
1401   if (len == 0)
1402     return TRUE;
1403
1404   if (!open_gap (len, dest, insert_at))
1405     return FALSE;
1406   
1407   memmove (dest->str + insert_at,
1408            source->str + start,
1409            len);
1410
1411   return TRUE;
1412 }
1413
1414 /**
1415  * Checks assertions for two strings we're copying a segment between,
1416  * and declares real_source/real_dest variables.
1417  *
1418  * @param source the source string
1419  * @param start the starting offset
1420  * @param dest the dest string
1421  * @param insert_at where the copied segment is inserted
1422  */
1423 #define DBUS_STRING_COPY_PREAMBLE(source, start, dest, insert_at)       \
1424   DBusRealString *real_source = (DBusRealString*) source;               \
1425   DBusRealString *real_dest = (DBusRealString*) dest;                   \
1426   _dbus_assert ((source) != (dest));                                    \
1427   DBUS_GENERIC_STRING_PREAMBLE (real_source);                           \
1428   DBUS_GENERIC_STRING_PREAMBLE (real_dest);                             \
1429   _dbus_assert (!real_dest->constant);                                  \
1430   _dbus_assert (!real_dest->locked);                                    \
1431   _dbus_assert ((start) >= 0);                                          \
1432   _dbus_assert ((start) <= real_source->len);                           \
1433   _dbus_assert ((insert_at) >= 0);                                      \
1434   _dbus_assert ((insert_at) <= real_dest->len)
1435
1436 /**
1437  * Moves the end of one string into another string. Both strings
1438  * must be initialized, valid strings.
1439  *
1440  * @param source the source string
1441  * @param start where to chop off the source string
1442  * @param dest the destination string
1443  * @param insert_at where to move the chopped-off part of source string
1444  * @returns #FALSE if not enough memory
1445  */
1446 dbus_bool_t
1447 _dbus_string_move (DBusString       *source,
1448                    int               start,
1449                    DBusString       *dest,
1450                    int               insert_at)
1451 {
1452   DBusRealString *real_source = (DBusRealString*) source;
1453   _dbus_assert (start <= real_source->len);
1454   
1455   return _dbus_string_move_len (source, start,
1456                                 real_source->len - start,
1457                                 dest, insert_at);
1458 }
1459
1460 /**
1461  * Like _dbus_string_move(), but does not delete the section
1462  * of the source string that's copied to the dest string.
1463  *
1464  * @param source the source string
1465  * @param start where to start copying the source string
1466  * @param dest the destination string
1467  * @param insert_at where to place the copied part of source string
1468  * @returns #FALSE if not enough memory
1469  */
1470 dbus_bool_t
1471 _dbus_string_copy (const DBusString *source,
1472                    int               start,
1473                    DBusString       *dest,
1474                    int               insert_at)
1475 {
1476   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
1477
1478   return copy (real_source, start,
1479                real_source->len - start,
1480                real_dest,
1481                insert_at);
1482 }
1483
1484 /**
1485  * Like _dbus_string_move(), but can move a segment from
1486  * the middle of the source string.
1487  *
1488  * @todo this doesn't do anything with max_length field.
1489  * we should probably just kill the max_length field though.
1490  * 
1491  * @param source the source string
1492  * @param start first byte of source string to move
1493  * @param len length of segment to move
1494  * @param dest the destination string
1495  * @param insert_at where to move the bytes from the source string
1496  * @returns #FALSE if not enough memory
1497  */
1498 dbus_bool_t
1499 _dbus_string_move_len (DBusString       *source,
1500                        int               start,
1501                        int               len,
1502                        DBusString       *dest,
1503                        int               insert_at)
1504
1505 {
1506   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
1507   _dbus_assert (len >= 0);
1508   _dbus_assert ((start + len) <= real_source->len);
1509
1510
1511   if (len == 0)
1512     {
1513       return TRUE;
1514     }
1515   else if (start == 0 &&
1516            len == real_source->len &&
1517            real_dest->len == 0)
1518     {
1519       /* Short-circuit moving an entire existing string to an empty string
1520        * by just swapping the buffers.
1521        */
1522       /* we assume ->constant doesn't matter as you can't have
1523        * a constant string involved in a move.
1524        */
1525 #define ASSIGN_DATA(a, b) do {                  \
1526         (a)->str = (b)->str;                    \
1527         (a)->len = (b)->len;                    \
1528         (a)->allocated = (b)->allocated;        \
1529         (a)->align_offset = (b)->align_offset;  \
1530       } while (0)
1531       
1532       DBusRealString tmp;
1533
1534       ASSIGN_DATA (&tmp, real_source);
1535       ASSIGN_DATA (real_source, real_dest);
1536       ASSIGN_DATA (real_dest, &tmp);
1537
1538       return TRUE;
1539     }
1540   else
1541     {
1542       if (!copy (real_source, start, len,
1543                  real_dest,
1544                  insert_at))
1545         return FALSE;
1546       
1547       delete (real_source, start,
1548               len);
1549       
1550       return TRUE;
1551     }
1552 }
1553
1554 /**
1555  * Like _dbus_string_copy(), but can copy a segment from the middle of
1556  * the source string.
1557  *
1558  * @param source the source string
1559  * @param start where to start copying the source string
1560  * @param len length of segment to copy
1561  * @param dest the destination string
1562  * @param insert_at where to place the copied segment of source string
1563  * @returns #FALSE if not enough memory
1564  */
1565 dbus_bool_t
1566 _dbus_string_copy_len (const DBusString *source,
1567                        int               start,
1568                        int               len,
1569                        DBusString       *dest,
1570                        int               insert_at)
1571 {
1572   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
1573   _dbus_assert (len >= 0);
1574   _dbus_assert (start <= real_source->len);
1575   _dbus_assert (len <= real_source->len - start);
1576   
1577   return copy (real_source, start, len,
1578                real_dest,
1579                insert_at);
1580 }
1581
1582 /**
1583  * Replaces a segment of dest string with a segment of source string.
1584  *
1585  * @todo optimize the case where the two lengths are the same, and
1586  * avoid memmoving the data in the trailing part of the string twice.
1587  *
1588  * @todo avoid inserting the source into dest, then deleting
1589  * the replaced chunk of dest (which creates a potentially large
1590  * intermediate string). Instead, extend the replaced chunk
1591  * of dest with padding to the same size as the source chunk,
1592  * then copy in the source bytes.
1593  * 
1594  * @param source the source string
1595  * @param start where to start copying the source string
1596  * @param len length of segment to copy
1597  * @param dest the destination string
1598  * @param replace_at start of segment of dest string to replace
1599  * @param replace_len length of segment of dest string to replace
1600  * @returns #FALSE if not enough memory
1601  *
1602  */
1603 dbus_bool_t
1604 _dbus_string_replace_len (const DBusString *source,
1605                           int               start,
1606                           int               len,
1607                           DBusString       *dest,
1608                           int               replace_at,
1609                           int               replace_len)
1610 {
1611   DBUS_STRING_COPY_PREAMBLE (source, start, dest, replace_at);
1612   _dbus_assert (len >= 0);
1613   _dbus_assert (start <= real_source->len);
1614   _dbus_assert (len <= real_source->len - start);
1615   _dbus_assert (replace_at >= 0);
1616   _dbus_assert (replace_at <= real_dest->len);
1617   _dbus_assert (replace_len <= real_dest->len - replace_at);
1618
1619   if (!copy (real_source, start, len,
1620              real_dest, replace_at))
1621     return FALSE;
1622
1623   delete (real_dest, replace_at + len, replace_len);
1624
1625   return TRUE;
1626 }
1627
1628 /* Unicode macros and utf8_validate() from GLib Owen Taylor, Havoc
1629  * Pennington, and Tom Tromey are the authors and authorized relicense.
1630  */
1631
1632 /** computes length and mask of a unicode character
1633  * @param Char the char
1634  * @param Mask the mask variable to assign to
1635  * @param Len the length variable to assign to
1636  */
1637 #define UTF8_COMPUTE(Char, Mask, Len)                                         \
1638   if (Char < 128)                                                             \
1639     {                                                                         \
1640       Len = 1;                                                                \
1641       Mask = 0x7f;                                                            \
1642     }                                                                         \
1643   else if ((Char & 0xe0) == 0xc0)                                             \
1644     {                                                                         \
1645       Len = 2;                                                                \
1646       Mask = 0x1f;                                                            \
1647     }                                                                         \
1648   else if ((Char & 0xf0) == 0xe0)                                             \
1649     {                                                                         \
1650       Len = 3;                                                                \
1651       Mask = 0x0f;                                                            \
1652     }                                                                         \
1653   else if ((Char & 0xf8) == 0xf0)                                             \
1654     {                                                                         \
1655       Len = 4;                                                                \
1656       Mask = 0x07;                                                            \
1657     }                                                                         \
1658   else if ((Char & 0xfc) == 0xf8)                                             \
1659     {                                                                         \
1660       Len = 5;                                                                \
1661       Mask = 0x03;                                                            \
1662     }                                                                         \
1663   else if ((Char & 0xfe) == 0xfc)                                             \
1664     {                                                                         \
1665       Len = 6;                                                                \
1666       Mask = 0x01;                                                            \
1667     }                                                                         \
1668   else                                                                        \
1669     {                                                                         \
1670       Len = 0;                                                               \
1671       Mask = 0;                                                               \
1672     }
1673
1674 /**
1675  * computes length of a unicode character in UTF-8
1676  * @param Char the char
1677  */
1678 #define UTF8_LENGTH(Char)              \
1679   ((Char) < 0x80 ? 1 :                 \
1680    ((Char) < 0x800 ? 2 :               \
1681     ((Char) < 0x10000 ? 3 :            \
1682      ((Char) < 0x200000 ? 4 :          \
1683       ((Char) < 0x4000000 ? 5 : 6)))))
1684    
1685 /**
1686  * Gets a UTF-8 value.
1687  *
1688  * @param Result variable for extracted unicode char.
1689  * @param Chars the bytes to decode
1690  * @param Count counter variable
1691  * @param Mask mask for this char
1692  * @param Len length for this char in bytes
1693  */
1694 #define UTF8_GET(Result, Chars, Count, Mask, Len)                             \
1695   (Result) = (Chars)[0] & (Mask);                                             \
1696   for ((Count) = 1; (Count) < (Len); ++(Count))                               \
1697     {                                                                         \
1698       if (((Chars)[(Count)] & 0xc0) != 0x80)                                  \
1699         {                                                                     \
1700           (Result) = -1;                                                      \
1701           break;                                                              \
1702         }                                                                     \
1703       (Result) <<= 6;                                                         \
1704       (Result) |= ((Chars)[(Count)] & 0x3f);                                  \
1705     }
1706
1707 /**
1708  * Check whether a unicode char is in a valid range.
1709  *
1710  * @param Char the character
1711  */
1712 #define UNICODE_VALID(Char)                   \
1713     ((Char) < 0x110000 &&                     \
1714      (((Char) & 0xFFFFF800) != 0xD800) &&     \
1715      ((Char) < 0xFDD0 || (Char) > 0xFDEF) &&  \
1716      ((Char) & 0xFFFF) != 0xFFFF)
1717
1718 #ifdef DBUS_BUILD_TESTS
1719 /**
1720  * Gets a unicode character from a UTF-8 string. Does no validation;
1721  * you must verify that the string is valid UTF-8 in advance and must
1722  * pass in the start of a character.
1723  *
1724  * @param str the string
1725  * @param start the start of the UTF-8 character.
1726  * @param ch_return location to return the character
1727  * @param end_return location to return the byte index of next character
1728  */
1729 void
1730 _dbus_string_get_unichar (const DBusString *str,
1731                           int               start,
1732                           dbus_unichar_t   *ch_return,
1733                           int              *end_return)
1734 {
1735   int i, mask, len;
1736   dbus_unichar_t result;
1737   unsigned char c;
1738   unsigned char *p;
1739   DBUS_CONST_STRING_PREAMBLE (str);
1740   _dbus_assert (start >= 0);
1741   _dbus_assert (start <= real->len);
1742   
1743   if (ch_return)
1744     *ch_return = 0;
1745   if (end_return)
1746     *end_return = real->len;
1747   
1748   mask = 0;
1749   p = real->str + start;
1750   c = *p;
1751   
1752   UTF8_COMPUTE (c, mask, len);
1753   if (len == 0)
1754     return;
1755   UTF8_GET (result, p, i, mask, len);
1756
1757   if (result == (dbus_unichar_t)-1)
1758     return;
1759
1760   if (ch_return)
1761     *ch_return = result;
1762   if (end_return)
1763     *end_return = start + len;
1764 }
1765 #endif /* DBUS_BUILD_TESTS */
1766
1767 /**
1768  * Finds the given substring in the string,
1769  * returning #TRUE and filling in the byte index
1770  * where the substring was found, if it was found.
1771  * Returns #FALSE if the substring wasn't found.
1772  * Sets *start to the length of the string if the substring
1773  * is not found.
1774  *
1775  * @param str the string
1776  * @param start where to start looking
1777  * @param substr the substring
1778  * @param found return location for where it was found, or #NULL
1779  * @returns #TRUE if found
1780  */
1781 dbus_bool_t
1782 _dbus_string_find (const DBusString *str,
1783                    int               start,
1784                    const char       *substr,
1785                    int              *found)
1786 {
1787   return _dbus_string_find_to (str, start,
1788                                ((const DBusRealString*)str)->len,
1789                                substr, found);
1790 }
1791
1792 /**
1793  * Finds the given substring in the string,
1794  * up to a certain position,
1795  * returning #TRUE and filling in the byte index
1796  * where the substring was found, if it was found.
1797  * Returns #FALSE if the substring wasn't found.
1798  * Sets *start to the length of the string if the substring
1799  * is not found.
1800  *
1801  * @param str the string
1802  * @param start where to start looking
1803  * @param end where to stop looking
1804  * @param substr the substring
1805  * @param found return location for where it was found, or #NULL
1806  * @returns #TRUE if found
1807  */
1808 dbus_bool_t
1809 _dbus_string_find_to (const DBusString *str,
1810                       int               start,
1811                       int               end,
1812                       const char       *substr,
1813                       int              *found)
1814 {
1815   int i;
1816   DBUS_CONST_STRING_PREAMBLE (str);
1817   _dbus_assert (substr != NULL);
1818   _dbus_assert (start <= real->len);
1819   _dbus_assert (start >= 0);
1820   _dbus_assert (substr != NULL);
1821   _dbus_assert (end <= real->len);
1822   _dbus_assert (start <= end);
1823
1824   /* we always "find" an empty string */
1825   if (*substr == '\0')
1826     {
1827       if (found)
1828         *found = start;
1829       return TRUE;
1830     }
1831
1832   i = start;
1833   while (i < end)
1834     {
1835       if (real->str[i] == substr[0])
1836         {
1837           int j = i + 1;
1838           
1839           while (j < end)
1840             {
1841               if (substr[j - i] == '\0')
1842                 break;
1843               else if (real->str[j] != substr[j - i])
1844                 break;
1845               
1846               ++j;
1847             }
1848
1849           if (substr[j - i] == '\0')
1850             {
1851               if (found)
1852                 *found = i;
1853               return TRUE;
1854             }
1855         }
1856       
1857       ++i;
1858     }
1859
1860   if (found)
1861     *found = end;
1862   
1863   return FALSE;  
1864 }
1865
1866 /**
1867  * Finds a blank (space or tab) in the string. Returns #TRUE
1868  * if found, #FALSE otherwise. If a blank is not found sets
1869  * *found to the length of the string.
1870  *
1871  * @param str the string
1872  * @param start byte index to start looking
1873  * @param found place to store the location of the first blank
1874  * @returns #TRUE if a blank was found
1875  */
1876 dbus_bool_t
1877 _dbus_string_find_blank (const DBusString *str,
1878                          int               start,
1879                          int              *found)
1880 {
1881   int i;
1882   DBUS_CONST_STRING_PREAMBLE (str);
1883   _dbus_assert (start <= real->len);
1884   _dbus_assert (start >= 0);
1885   
1886   i = start;
1887   while (i < real->len)
1888     {
1889       if (real->str[i] == ' ' ||
1890           real->str[i] == '\t')
1891         {
1892           if (found)
1893             *found = i;
1894           return TRUE;
1895         }
1896       
1897       ++i;
1898     }
1899
1900   if (found)
1901     *found = real->len;
1902   
1903   return FALSE;
1904 }
1905
1906 /**
1907  * Skips blanks from start, storing the first non-blank in *end
1908  * (blank is space or tab).
1909  *
1910  * @param str the string
1911  * @param start where to start
1912  * @param end where to store the first non-blank byte index
1913  */
1914 void
1915 _dbus_string_skip_blank (const DBusString *str,
1916                          int               start,
1917                          int              *end)
1918 {
1919   int i;
1920   DBUS_CONST_STRING_PREAMBLE (str);
1921   _dbus_assert (start <= real->len);
1922   _dbus_assert (start >= 0);
1923   
1924   i = start;
1925   while (i < real->len)
1926     {
1927       if (!DBUS_IS_ASCII_BLANK (real->str[i]))
1928         break;
1929       
1930       ++i;
1931     }
1932
1933   _dbus_assert (i == real->len || !DBUS_IS_ASCII_WHITE (real->str[i]));
1934   
1935   if (end)
1936     *end = i;
1937 }
1938
1939
1940 /**
1941  * Skips whitespace from start, storing the first non-whitespace in *end.
1942  * (whitespace is space, tab, newline, CR).
1943  *
1944  * @param str the string
1945  * @param start where to start
1946  * @param end where to store the first non-whitespace byte index
1947  */
1948 void
1949 _dbus_string_skip_white (const DBusString *str,
1950                          int               start,
1951                          int              *end)
1952 {
1953   int i;
1954   DBUS_CONST_STRING_PREAMBLE (str);
1955   _dbus_assert (start <= real->len);
1956   _dbus_assert (start >= 0);
1957   
1958   i = start;
1959   while (i < real->len)
1960     {
1961       if (!DBUS_IS_ASCII_WHITE (real->str[i]))
1962         break;
1963       
1964       ++i;
1965     }
1966
1967   _dbus_assert (i == real->len || !(DBUS_IS_ASCII_WHITE (real->str[i])));
1968   
1969   if (end)
1970     *end = i;
1971 }
1972
1973 /**
1974  * Skips whitespace from end, storing the start index of the trailing
1975  * whitespace in *start. (whitespace is space, tab, newline, CR).
1976  *
1977  * @param str the string
1978  * @param end where to start scanning backward
1979  * @param start where to store the start of whitespace chars
1980  */
1981 void
1982 _dbus_string_skip_white_reverse (const DBusString *str,
1983                                  int               end,
1984                                  int              *start)
1985 {
1986   int i;
1987   DBUS_CONST_STRING_PREAMBLE (str);
1988   _dbus_assert (end <= real->len);
1989   _dbus_assert (end >= 0);
1990   
1991   i = end;
1992   while (i > 0)
1993     {
1994       if (!DBUS_IS_ASCII_WHITE (real->str[i-1]))
1995         break;
1996       --i;
1997     }
1998
1999   _dbus_assert (i >= 0 && (i == 0 || !(DBUS_IS_ASCII_WHITE (real->str[i-1]))));
2000   
2001   if (start)
2002     *start = i;
2003 }
2004
2005 /**
2006  * Assigns a newline-terminated or \\r\\n-terminated line from the front
2007  * of the string to the given dest string. The dest string's previous
2008  * contents are deleted. If the source string contains no newline,
2009  * moves the entire source string to the dest string.
2010  *
2011  * @todo owen correctly notes that this is a stupid function (it was
2012  * written purely for test code,
2013  * e.g. dbus-message-builder.c). Probably should be enforced as test
2014  * code only with ifdef DBUS_BUILD_TESTS
2015  * 
2016  * @param source the source string
2017  * @param dest the destination string (contents are replaced)
2018  * @returns #FALSE if no memory, or source has length 0
2019  */
2020 dbus_bool_t
2021 _dbus_string_pop_line (DBusString *source,
2022                        DBusString *dest)
2023 {
2024   int eol;
2025   dbus_bool_t have_newline;
2026   
2027   _dbus_string_set_length (dest, 0);
2028   
2029   eol = 0;
2030   if (_dbus_string_find (source, 0, "\n", &eol))
2031     {
2032       have_newline = TRUE;
2033       eol += 1; /* include newline */
2034     }
2035   else
2036     {
2037       eol = _dbus_string_get_length (source);
2038       have_newline = FALSE;
2039     }
2040
2041   if (eol == 0)
2042     return FALSE; /* eof */
2043   
2044   if (!_dbus_string_move_len (source, 0, eol,
2045                               dest, 0))
2046     {
2047       return FALSE;
2048     }
2049
2050   /* dump the newline and the \r if we have one */
2051   if (have_newline)
2052     {
2053       dbus_bool_t have_cr;
2054       
2055       _dbus_assert (_dbus_string_get_length (dest) > 0);
2056
2057       if (_dbus_string_get_length (dest) > 1 &&
2058           _dbus_string_get_byte (dest,
2059                                  _dbus_string_get_length (dest) - 2) == '\r')
2060         have_cr = TRUE;
2061       else
2062         have_cr = FALSE;
2063         
2064       _dbus_string_set_length (dest,
2065                                _dbus_string_get_length (dest) -
2066                                (have_cr ? 2 : 1));
2067     }
2068   
2069   return TRUE;
2070 }
2071
2072 #ifdef DBUS_BUILD_TESTS
2073 /**
2074  * Deletes up to and including the first blank space
2075  * in the string.
2076  *
2077  * @param str the string
2078  */
2079 void
2080 _dbus_string_delete_first_word (DBusString *str)
2081 {
2082   int i;
2083   
2084   if (_dbus_string_find_blank (str, 0, &i))
2085     _dbus_string_skip_blank (str, i, &i);
2086
2087   _dbus_string_delete (str, 0, i);
2088 }
2089 #endif
2090
2091 #ifdef DBUS_BUILD_TESTS
2092 /**
2093  * Deletes any leading blanks in the string
2094  *
2095  * @param str the string
2096  */
2097 void
2098 _dbus_string_delete_leading_blanks (DBusString *str)
2099 {
2100   int i;
2101   
2102   _dbus_string_skip_blank (str, 0, &i);
2103
2104   if (i > 0)
2105     _dbus_string_delete (str, 0, i);
2106 }
2107 #endif
2108
2109 /**
2110  * Deletes leading and trailing whitespace
2111  * 
2112  * @param str the string
2113  */
2114 void
2115 _dbus_string_chop_white(DBusString *str)
2116 {
2117   int i;
2118   
2119   _dbus_string_skip_white (str, 0, &i);
2120
2121   if (i > 0)
2122     _dbus_string_delete (str, 0, i);
2123   
2124   _dbus_string_skip_white_reverse (str, _dbus_string_get_length (str), &i);
2125
2126   _dbus_string_set_length (str, i);
2127 }
2128
2129 /**
2130  * Tests two DBusString for equality.
2131  *
2132  * @todo memcmp is probably faster
2133  *
2134  * @param a first string
2135  * @param b second string
2136  * @returns #TRUE if equal
2137  */
2138 dbus_bool_t
2139 _dbus_string_equal (const DBusString *a,
2140                     const DBusString *b)
2141 {
2142   const unsigned char *ap;
2143   const unsigned char *bp;
2144   const unsigned char *a_end;
2145   const DBusRealString *real_a = (const DBusRealString*) a;
2146   const DBusRealString *real_b = (const DBusRealString*) b;
2147   DBUS_GENERIC_STRING_PREAMBLE (real_a);
2148   DBUS_GENERIC_STRING_PREAMBLE (real_b);
2149
2150   if (real_a->len != real_b->len)
2151     return FALSE;
2152
2153   ap = real_a->str;
2154   bp = real_b->str;
2155   a_end = real_a->str + real_a->len;
2156   while (ap != a_end)
2157     {
2158       if (*ap != *bp)
2159         return FALSE;
2160       
2161       ++ap;
2162       ++bp;
2163     }
2164
2165   return TRUE;
2166 }
2167
2168 #ifdef DBUS_BUILD_TESTS
2169 /**
2170  * Tests two DBusString for equality up to the given length.
2171  * The strings may be shorter than the given length.
2172  *
2173  * @todo write a unit test
2174  *
2175  * @todo memcmp is probably faster
2176  *
2177  * @param a first string
2178  * @param b second string
2179  * @param len the maximum length to look at
2180  * @returns #TRUE if equal for the given number of bytes
2181  */
2182 dbus_bool_t
2183 _dbus_string_equal_len (const DBusString *a,
2184                         const DBusString *b,
2185                         int               len)
2186 {
2187   const unsigned char *ap;
2188   const unsigned char *bp;
2189   const unsigned char *a_end;
2190   const DBusRealString *real_a = (const DBusRealString*) a;
2191   const DBusRealString *real_b = (const DBusRealString*) b;
2192   DBUS_GENERIC_STRING_PREAMBLE (real_a);
2193   DBUS_GENERIC_STRING_PREAMBLE (real_b);
2194
2195   if (real_a->len != real_b->len &&
2196       (real_a->len < len || real_b->len < len))
2197     return FALSE;
2198
2199   ap = real_a->str;
2200   bp = real_b->str;
2201   a_end = real_a->str + MIN (real_a->len, len);
2202   while (ap != a_end)
2203     {
2204       if (*ap != *bp)
2205         return FALSE;
2206       
2207       ++ap;
2208       ++bp;
2209     }
2210
2211   return TRUE;
2212 }
2213 #endif /* DBUS_BUILD_TESTS */
2214
2215 /**
2216  * Tests two sub-parts of two DBusString for equality.  The specified
2217  * range of the first string must exist; the specified start position
2218  * of the second string must exist.
2219  *
2220  * @todo write a unit test
2221  *
2222  * @todo memcmp is probably faster
2223  *
2224  * @param a first string
2225  * @param a_start where to start substring in first string
2226  * @param a_len length of substring in first string
2227  * @param b second string
2228  * @param b_start where to start substring in second string
2229  * @returns #TRUE if the two substrings are equal
2230  */
2231 dbus_bool_t
2232 _dbus_string_equal_substring (const DBusString  *a,
2233                               int                a_start,
2234                               int                a_len,
2235                               const DBusString  *b,
2236                               int                b_start)
2237 {
2238   const unsigned char *ap;
2239   const unsigned char *bp;
2240   const unsigned char *a_end;
2241   const DBusRealString *real_a = (const DBusRealString*) a;
2242   const DBusRealString *real_b = (const DBusRealString*) b;
2243   DBUS_GENERIC_STRING_PREAMBLE (real_a);
2244   DBUS_GENERIC_STRING_PREAMBLE (real_b);
2245   _dbus_assert (a_start >= 0);
2246   _dbus_assert (a_len >= 0);
2247   _dbus_assert (a_start <= real_a->len);
2248   _dbus_assert (a_len <= real_a->len - a_start);
2249   _dbus_assert (b_start >= 0);
2250   _dbus_assert (b_start <= real_b->len);
2251   
2252   if (a_len > real_b->len - b_start)
2253     return FALSE;
2254
2255   ap = real_a->str + a_start;
2256   bp = real_b->str + b_start;
2257   a_end = ap + a_len;
2258   while (ap != a_end)
2259     {
2260       if (*ap != *bp)
2261         return FALSE;
2262       
2263       ++ap;
2264       ++bp;
2265     }
2266
2267   _dbus_assert (bp <= (real_b->str + real_b->len));
2268   
2269   return TRUE;
2270 }
2271
2272 /**
2273  * Checks whether a string is equal to a C string.
2274  *
2275  * @param a the string
2276  * @param c_str the C string
2277  * @returns #TRUE if equal
2278  */
2279 dbus_bool_t
2280 _dbus_string_equal_c_str (const DBusString *a,
2281                           const char       *c_str)
2282 {
2283   const unsigned char *ap;
2284   const unsigned char *bp;
2285   const unsigned char *a_end;
2286   const DBusRealString *real_a = (const DBusRealString*) a;
2287   DBUS_GENERIC_STRING_PREAMBLE (real_a);
2288   _dbus_assert (c_str != NULL);
2289   
2290   ap = real_a->str;
2291   bp = (const unsigned char*) c_str;
2292   a_end = real_a->str + real_a->len;
2293   while (ap != a_end && *bp)
2294     {
2295       if (*ap != *bp)
2296         return FALSE;
2297       
2298       ++ap;
2299       ++bp;
2300     }
2301
2302   if (ap != a_end || *bp)
2303     return FALSE;
2304   
2305   return TRUE;
2306 }
2307
2308 #ifdef DBUS_BUILD_TESTS
2309 /**
2310  * Checks whether a string starts with the given C string.
2311  *
2312  * @param a the string
2313  * @param c_str the C string
2314  * @returns #TRUE if string starts with it
2315  */
2316 dbus_bool_t
2317 _dbus_string_starts_with_c_str (const DBusString *a,
2318                                 const char       *c_str)
2319 {
2320   const unsigned char *ap;
2321   const unsigned char *bp;
2322   const unsigned char *a_end;
2323   const DBusRealString *real_a = (const DBusRealString*) a;
2324   DBUS_GENERIC_STRING_PREAMBLE (real_a);
2325   _dbus_assert (c_str != NULL);
2326   
2327   ap = real_a->str;
2328   bp = (const unsigned char*) c_str;
2329   a_end = real_a->str + real_a->len;
2330   while (ap != a_end && *bp)
2331     {
2332       if (*ap != *bp)
2333         return FALSE;
2334       
2335       ++ap;
2336       ++bp;
2337     }
2338
2339   if (*bp == '\0')
2340     return TRUE;
2341   else
2342     return FALSE;
2343 }
2344 #endif /* DBUS_BUILD_TESTS */
2345
2346 /**
2347  * Appends a two-character hex digit to a string, where the hex digit
2348  * has the value of the given byte.
2349  *
2350  * @param str the string
2351  * @param byte the byte
2352  * @returns #FALSE if no memory
2353  */
2354 dbus_bool_t
2355 _dbus_string_append_byte_as_hex (DBusString *str,
2356                                  int         byte)
2357 {
2358   const char hexdigits[16] = {
2359     '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
2360     'a', 'b', 'c', 'd', 'e', 'f'
2361   };
2362
2363   if (!_dbus_string_append_byte (str,
2364                                  hexdigits[(byte >> 4)]))
2365     return FALSE;
2366   
2367   if (!_dbus_string_append_byte (str,
2368                                  hexdigits[(byte & 0x0f)]))
2369     {
2370       _dbus_string_set_length (str,
2371                                _dbus_string_get_length (str) - 1);
2372       return FALSE;
2373     }
2374
2375   return TRUE;
2376 }
2377
2378 /**
2379  * Encodes a string in hex, the way MD5 and SHA-1 are usually
2380  * encoded. (Each byte is two hex digits.)
2381  *
2382  * @param source the string to encode
2383  * @param start byte index to start encoding
2384  * @param dest string where encoded data should be placed
2385  * @param insert_at where to place encoded data
2386  * @returns #TRUE if encoding was successful, #FALSE if no memory etc.
2387  */
2388 dbus_bool_t
2389 _dbus_string_hex_encode (const DBusString *source,
2390                          int               start,
2391                          DBusString       *dest,
2392                          int               insert_at)
2393 {
2394   DBusString result;
2395   const unsigned char *p;
2396   const unsigned char *end;
2397   dbus_bool_t retval;
2398   
2399   _dbus_assert (start <= _dbus_string_get_length (source));
2400
2401   if (!_dbus_string_init (&result))
2402     return FALSE;
2403
2404   retval = FALSE;
2405   
2406   p = (const unsigned char*) _dbus_string_get_const_data (source);
2407   end = p + _dbus_string_get_length (source);
2408   p += start;
2409   
2410   while (p != end)
2411     {
2412       if (!_dbus_string_append_byte_as_hex (&result, *p))
2413         goto out;
2414       
2415       ++p;
2416     }
2417
2418   if (!_dbus_string_move (&result, 0, dest, insert_at))
2419     goto out;
2420
2421   retval = TRUE;
2422
2423  out:
2424   _dbus_string_free (&result);
2425   return retval;
2426 }
2427
2428 /**
2429  * Decodes a string from hex encoding.
2430  *
2431  * @param source the string to decode
2432  * @param start byte index to start decode
2433  * @param end_return return location of the end of the hex data, or #NULL
2434  * @param dest string where decoded data should be placed
2435  * @param insert_at where to place decoded data
2436  * @returns #TRUE if decoding was successful, #FALSE if no memory.
2437  */
2438 dbus_bool_t
2439 _dbus_string_hex_decode (const DBusString *source,
2440                          int               start,
2441                          int              *end_return,
2442                          DBusString       *dest,
2443                          int               insert_at)
2444 {
2445   DBusString result;
2446   const unsigned char *p;
2447   const unsigned char *end;
2448   dbus_bool_t retval;
2449   dbus_bool_t high_bits;
2450   
2451   _dbus_assert (start <= _dbus_string_get_length (source));
2452
2453   if (!_dbus_string_init (&result))
2454     return FALSE;
2455
2456   retval = FALSE;
2457
2458   high_bits = TRUE;
2459   p = (const unsigned char*) _dbus_string_get_const_data (source);
2460   end = p + _dbus_string_get_length (source);
2461   p += start;
2462   
2463   while (p != end)
2464     {
2465       unsigned int val;
2466
2467       switch (*p)
2468         {
2469         case '0':
2470           val = 0;
2471           break;
2472         case '1':
2473           val = 1;
2474           break;
2475         case '2':
2476           val = 2;
2477           break;
2478         case '3':
2479           val = 3;
2480           break;
2481         case '4':
2482           val = 4;
2483           break;
2484         case '5':
2485           val = 5;
2486           break;
2487         case '6':
2488           val = 6;
2489           break;
2490         case '7':
2491           val = 7;
2492           break;
2493         case '8':
2494           val = 8;
2495           break;
2496         case '9':
2497           val = 9;
2498           break;
2499         case 'a':
2500         case 'A':
2501           val = 10;
2502           break;
2503         case 'b':
2504         case 'B':
2505           val = 11;
2506           break;
2507         case 'c':
2508         case 'C':
2509           val = 12;
2510           break;
2511         case 'd':
2512         case 'D':
2513           val = 13;
2514           break;
2515         case 'e':
2516         case 'E':
2517           val = 14;
2518           break;
2519         case 'f':
2520         case 'F':
2521           val = 15;
2522           break;
2523         default:
2524           goto done;
2525         }
2526
2527       if (high_bits)
2528         {
2529           if (!_dbus_string_append_byte (&result,
2530                                          val << 4))
2531             goto out;
2532         }
2533       else
2534         {
2535           int len;
2536           unsigned char b;
2537
2538           len = _dbus_string_get_length (&result);
2539           
2540           b = _dbus_string_get_byte (&result, len - 1);
2541
2542           b |= val;
2543
2544           _dbus_string_set_byte (&result, len - 1, b);
2545         }
2546
2547       high_bits = !high_bits;
2548
2549       ++p;
2550     }
2551
2552  done:
2553   if (!_dbus_string_move (&result, 0, dest, insert_at))
2554     goto out;
2555
2556   if (end_return)
2557     *end_return = p - (const unsigned char*) _dbus_string_get_const_data (source);
2558
2559   retval = TRUE;
2560   
2561  out:
2562   _dbus_string_free (&result);  
2563   return retval;
2564 }
2565
2566 /**
2567  * Checks that the given range of the string is valid ASCII with no
2568  * nul bytes. If the given range is not entirely contained in the
2569  * string, returns #FALSE.
2570  *
2571  * @todo this is inconsistent with most of DBusString in that
2572  * it allows a start,len range that extends past the string end.
2573  * 
2574  * @param str the string
2575  * @param start first byte index to check
2576  * @param len number of bytes to check
2577  * @returns #TRUE if the byte range exists and is all valid ASCII
2578  */
2579 dbus_bool_t
2580 _dbus_string_validate_ascii (const DBusString *str,
2581                              int               start,
2582                              int               len)
2583 {
2584   const unsigned char *s;
2585   const unsigned char *end;
2586   DBUS_CONST_STRING_PREAMBLE (str);
2587   _dbus_assert (start >= 0);
2588   _dbus_assert (start <= real->len);
2589   _dbus_assert (len >= 0);
2590   
2591   if (len > real->len - start)
2592     return FALSE;
2593   
2594   s = real->str + start;
2595   end = s + len;
2596   while (s != end)
2597     {
2598       if (_DBUS_UNLIKELY (!_DBUS_ISASCII (*s)))
2599         return FALSE;
2600         
2601       ++s;
2602     }
2603   
2604   return TRUE;
2605 }
2606
2607 /**
2608  * Checks that the given range of the string is valid UTF-8. If the
2609  * given range is not entirely contained in the string, returns
2610  * #FALSE. If the string contains any nul bytes in the given range,
2611  * returns #FALSE. If the start and start+len are not on character
2612  * boundaries, returns #FALSE.
2613  *
2614  * @todo this is inconsistent with most of DBusString in that
2615  * it allows a start,len range that extends past the string end.
2616  * 
2617  * @param str the string
2618  * @param start first byte index to check
2619  * @param len number of bytes to check
2620  * @returns #TRUE if the byte range exists and is all valid UTF-8
2621  */
2622 dbus_bool_t
2623 _dbus_string_validate_utf8  (const DBusString *str,
2624                              int               start,
2625                              int               len)
2626 {
2627   const unsigned char *p;
2628   const unsigned char *end;
2629   DBUS_CONST_STRING_PREAMBLE (str);
2630   _dbus_assert (start >= 0);
2631   _dbus_assert (start <= real->len);
2632   _dbus_assert (len >= 0);
2633
2634   /* we are doing _DBUS_UNLIKELY() here which might be
2635    * dubious in a generic library like GLib, but in D-Bus
2636    * we know we're validating messages and that it would
2637    * only be evil/broken apps that would have invalid
2638    * UTF-8. Also, this function seems to be a performance
2639    * bottleneck in profiles.
2640    */
2641   
2642   if (_DBUS_UNLIKELY (len > real->len - start))
2643     return FALSE;
2644   
2645   p = real->str + start;
2646   end = p + len;
2647   
2648   while (p < end)
2649     {
2650       int i, mask, char_len;
2651       dbus_unichar_t result;
2652
2653       /* nul bytes considered invalid */
2654       if (*p == '\0')
2655         break;
2656       
2657       /* Special-case ASCII; this makes us go a lot faster in
2658        * D-Bus profiles where we are typically validating
2659        * function names and such. We have to know that
2660        * all following checks will pass for ASCII though,
2661        * comments follow ...
2662        */      
2663       if (*p < 128)
2664         {
2665           ++p;
2666           continue;
2667         }
2668       
2669       UTF8_COMPUTE (*p, mask, char_len);
2670
2671       if (_DBUS_UNLIKELY (char_len == 0))  /* ASCII: char_len == 1 */
2672         break;
2673
2674       /* check that the expected number of bytes exists in the remaining length */
2675       if (_DBUS_UNLIKELY ((end - p) < char_len)) /* ASCII: p < end and char_len == 1 */
2676         break;
2677         
2678       UTF8_GET (result, p, i, mask, char_len);
2679
2680       /* Check for overlong UTF-8 */
2681       if (_DBUS_UNLIKELY (UTF8_LENGTH (result) != char_len)) /* ASCII: UTF8_LENGTH == 1 */
2682         break;
2683 #if 0
2684       /* The UNICODE_VALID check below will catch this */
2685       if (_DBUS_UNLIKELY (result == (dbus_unichar_t)-1)) /* ASCII: result = ascii value */
2686         break;
2687 #endif
2688
2689       if (_DBUS_UNLIKELY (!UNICODE_VALID (result))) /* ASCII: always valid */
2690         break;
2691
2692       /* UNICODE_VALID should have caught it */
2693       _dbus_assert (result != (dbus_unichar_t)-1);
2694       
2695       p += char_len;
2696     }
2697
2698   /* See that we covered the entire length if a length was
2699    * passed in
2700    */
2701   if (_DBUS_UNLIKELY (p != end))
2702     return FALSE;
2703   else
2704     return TRUE;
2705 }
2706
2707 /**
2708  * Checks that the given range of the string is all nul bytes. If the
2709  * given range is not entirely contained in the string, returns
2710  * #FALSE.
2711  *
2712  * @todo this is inconsistent with most of DBusString in that
2713  * it allows a start,len range that extends past the string end.
2714  * 
2715  * @param str the string
2716  * @param start first byte index to check
2717  * @param len number of bytes to check
2718  * @returns #TRUE if the byte range exists and is all nul bytes
2719  */
2720 dbus_bool_t
2721 _dbus_string_validate_nul (const DBusString *str,
2722                            int               start,
2723                            int               len)
2724 {
2725   const unsigned char *s;
2726   const unsigned char *end;
2727   DBUS_CONST_STRING_PREAMBLE (str);
2728   _dbus_assert (start >= 0);
2729   _dbus_assert (len >= 0);
2730   _dbus_assert (start <= real->len);
2731   
2732   if (len > real->len - start)
2733     return FALSE;
2734   
2735   s = real->str + start;
2736   end = s + len;
2737   while (s != end)
2738     {
2739       if (_DBUS_UNLIKELY (*s != '\0'))
2740         return FALSE;
2741       ++s;
2742     }
2743   
2744   return TRUE;
2745 }
2746
2747 /**
2748  * Clears all allocated bytes in the string to zero.
2749  *
2750  * @param str the string
2751  */
2752 void
2753 _dbus_string_zero (DBusString *str)
2754 {
2755   DBUS_STRING_PREAMBLE (str);
2756
2757   memset (real->str - real->align_offset, '\0', real->allocated);
2758 }
2759 /** @} */
2760
2761 /* tests are in dbus-string-util.c */