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