2003-01-08 Havoc Pennington <hp@pobox.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  Red Hat, Inc.
5  *
6  * Licensed under the Academic Free License version 1.2
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
29 /**
30  * @defgroup DBusString string class
31  * @ingroup  DBusInternals
32  * @brief DBusString data structure
33  *
34  * Types and functions related to DBusString. DBusString is intended
35  * to be a string class that makes it hard to mess up security issues
36  * (and just in general harder to write buggy code).  It should be
37  * used (or extended and then used) rather than the libc stuff in
38  * string.h.  The string class is a bit inconvenient at spots because
39  * it handles out-of-memory failures and tries to be extra-robust.
40  * 
41  * A DBusString has a maximum length set at initialization time; this
42  * can be used to ensure that a buffer doesn't get too big.  The
43  * _dbus_string_lengthen() method checks for overflow, and for max
44  * length being exceeded.
45  * 
46  * Try to avoid conversion to a plain C string, i.e. add methods on
47  * the string object instead, only convert to C string when passing
48  * things out to the public API. In particular, no sprintf, strcpy,
49  * strcat, any of that should be used. The GString feature of
50  * accepting negative numbers for "length of string" is also absent,
51  * because it could keep us from detecting bogus huge lengths. i.e. if
52  * we passed in some bogus huge length it would be taken to mean
53  * "current length of string" instead of "broken crack"
54  */
55
56 /**
57  * @defgroup DBusStringInternals DBusString implementation details
58  * @ingroup  DBusInternals
59  * @brief DBusString implementation details
60  *
61  * The guts of DBusString.
62  *
63  * @{
64  */
65
66 /**
67  * @brief Internals of DBusString.
68  * 
69  * DBusString internals. DBusString is an opaque objects, it must be
70  * used via accessor functions.
71  */
72 typedef struct
73 {
74   unsigned char *str;            /**< String data, plus nul termination */
75   int            len;            /**< Length without nul */
76   int            allocated;      /**< Allocated size of data */
77   int            max_length;     /**< Max length of this string. */
78   unsigned int   constant : 1;   /**< String data is not owned by DBusString */
79   unsigned int   locked : 1;     /**< DBusString has been locked and can't be changed */
80   unsigned int   invalid : 1;    /**< DBusString is invalid (e.g. already freed) */
81 } DBusRealString;
82
83 /**
84  * Checks a bunch of assertions about a string object
85  *
86  * @param real the DBusRealString
87  */
88 #define DBUS_GENERIC_STRING_PREAMBLE(real) _dbus_assert ((real) != NULL); _dbus_assert (!(real)->invalid); _dbus_assert ((real)->len >= 0); _dbus_assert ((real)->allocated >= 0); _dbus_assert ((real)->max_length >= 0); _dbus_assert ((real)->len <= (real)->allocated); _dbus_assert ((real)->len <= (real)->max_length)
89
90 /**
91  * Checks assertions about a string object that needs to be
92  * modifiable - may not be locked or const. Also declares
93  * the "real" variable pointing to DBusRealString. 
94  * @param str the string
95  */
96 #define DBUS_STRING_PREAMBLE(str) DBusRealString *real = (DBusRealString*) str; \
97   DBUS_GENERIC_STRING_PREAMBLE (real);                                          \
98   _dbus_assert (!(real)->constant);                                             \
99   _dbus_assert (!(real)->locked)
100
101 /**
102  * Checks assertions about a string object that may be locked but
103  * can't be const. i.e. a string object that we can free.  Also
104  * declares the "real" variable pointing to DBusRealString.
105  *
106  * @param str the string
107  */
108 #define DBUS_LOCKED_STRING_PREAMBLE(str) DBusRealString *real = (DBusRealString*) str; \
109   DBUS_GENERIC_STRING_PREAMBLE (real);                                                 \
110   _dbus_assert (!(real)->constant)
111
112 /**
113  * Checks assertions about a string that may be const or locked.  Also
114  * declares the "real" variable pointing to DBusRealString.
115  * @param str the string.
116  */
117 #define DBUS_CONST_STRING_PREAMBLE(str) const DBusRealString *real = (DBusRealString*) str; \
118   DBUS_GENERIC_STRING_PREAMBLE (real)
119
120 /** @} */
121
122 /**
123  * @addtogroup DBusString
124  * @{
125  */
126
127 /**
128  * Initializes a string. The maximum length may be _DBUS_INT_MAX for
129  * no maximum. The string starts life with zero length.
130  * The string must eventually be freed with _dbus_string_free().
131  *
132  * @param str memory to hold the string
133  * @param max_length the maximum size of the string
134  * @returns #TRUE on success
135  */
136 dbus_bool_t
137 _dbus_string_init (DBusString *str,
138                    int         max_length)
139 {
140   DBusRealString *real;
141   
142   _dbus_assert (str != NULL);
143   _dbus_assert (max_length >= 0);
144
145   _dbus_assert (sizeof (DBusString) == sizeof (DBusRealString));
146   
147   real = (DBusRealString*) str;
148
149   /* It's very important not to touch anything
150    * other than real->str if we're going to fail,
151    * since we also use this function to reset
152    * an existing string, e.g. in _dbus_string_steal_data()
153    */
154   
155 #define INITIAL_ALLOC 2
156   
157   real->str = dbus_malloc (INITIAL_ALLOC);
158   if (real->str == NULL)
159     return FALSE;
160
161   real->allocated = INITIAL_ALLOC;
162   real->len = 0;
163   real->str[real->len] = '\0';
164   
165   real->max_length = max_length;
166   real->constant = FALSE;
167   real->locked = FALSE;
168   real->invalid = FALSE;
169
170   return TRUE;
171 }
172
173 /**
174  * Initializes a constant string. The value parameter is not copied
175  * (should be static), and the string may never be modified.
176  * It is safe but not necessary to call _dbus_string_free()
177  * on a const string.
178  * 
179  * @param str memory to use for the string
180  * @param value a string to be stored in str (not copied!!!)
181  */
182 void
183 _dbus_string_init_const (DBusString *str,
184                          const char *value)
185 {
186   DBusRealString *real;
187   
188   _dbus_assert (str != NULL);
189   _dbus_assert (value != NULL);
190
191   real = (DBusRealString*) str;
192   
193   real->str = (char*) value;
194   real->len = strlen (real->str);
195   real->allocated = real->len;
196   real->max_length = real->len;
197   real->constant = TRUE;
198   real->invalid = FALSE;
199 }
200
201 /**
202  * Frees a string created by _dbus_string_init().
203  *
204  * @param str memory where the string is stored.
205  */
206 void
207 _dbus_string_free (DBusString *str)
208 {
209   DBUS_LOCKED_STRING_PREAMBLE (str);
210   
211   if (real->constant)
212     return;
213   
214   dbus_free (real->str);
215
216   real->invalid = TRUE;
217 }
218
219 /**
220  * Locks a string such that any attempts to change the string
221  * will result in aborting the program. Also, if the string
222  * is wasting a lot of memory (allocation is larger than what
223  * the string is really using), _dbus_string_lock() will realloc
224  * the string's data to "compact" it.
225  *
226  * @param str the string to lock.
227  */
228 void
229 _dbus_string_lock (DBusString *str)
230 {  
231   DBUS_LOCKED_STRING_PREAMBLE (str); /* can lock multiple times */
232
233   real->locked = TRUE;
234
235   /* Try to realloc to avoid excess memory usage, since
236    * we know we won't change the string further
237    */
238 #define MAX_WASTE 24
239   if (real->allocated > (real->len + MAX_WASTE))
240     {
241       char *new_str;
242       int new_allocated;
243
244       new_allocated = real->len + 1;
245
246       new_str = dbus_realloc (real->str, new_allocated);
247       if (new_str != NULL)
248         {
249           real->str = new_str;
250           real->allocated = new_allocated;
251         }
252     }
253 }
254
255 /**
256  * Gets the raw character buffer from the string.  The returned buffer
257  * will be nul-terminated, but note that strings may contain binary
258  * data so there may be extra nul characters prior to the termination.
259  * This function should be little-used, extend DBusString or add
260  * stuff to dbus-sysdeps.c instead. It's an error to use this
261  * function on a const string.
262  *
263  * @param str the string
264  * @param data_return place to store the returned data
265  */
266 void
267 _dbus_string_get_data (DBusString        *str,
268                        char             **data_return)
269 {
270   DBUS_STRING_PREAMBLE (str);
271   _dbus_assert (data_return != NULL);
272   
273   *data_return = real->str;
274 }
275
276 /**
277  * Gets the raw character buffer from a const string. 
278  *
279  * @param str the string
280  * @param data_return location to store returned data
281  */
282 void
283 _dbus_string_get_const_data (const DBusString  *str,
284                              const char       **data_return)
285 {
286   DBUS_CONST_STRING_PREAMBLE (str);
287   _dbus_assert (data_return != NULL);
288   
289   *data_return = real->str;
290 }
291
292 /**
293  * Gets a sub-portion of the raw character buffer from the
294  * string. The "len" field is required simply for error
295  * checking, to be sure you don't try to use more
296  * string than exists. The nul termination of the
297  * returned buffer remains at the end of the entire
298  * string, not at start + len.
299  *
300  * @param str the string
301  * @param data_return location to return the buffer
302  * @param start byte offset to return
303  * @param len length of segment to return
304  */
305 void
306 _dbus_string_get_data_len (DBusString *str,
307                            char      **data_return,
308                            int         start,
309                            int         len)
310 {
311   DBUS_STRING_PREAMBLE (str);
312   _dbus_assert (data_return != NULL);
313   _dbus_assert (start >= 0);
314   _dbus_assert (len >= 0);
315   _dbus_assert ((start + len) <= real->len);
316   
317   *data_return = real->str + start;
318 }
319
320 /**
321  * const version of _dbus_string_get_data_len().
322  *
323  * @param str the string
324  * @param data_return location to return the buffer
325  * @param start byte offset to return
326  * @param len length of segment to return
327  */
328 void
329 _dbus_string_get_const_data_len (const DBusString  *str,
330                                  const char       **data_return,
331                                  int                start,
332                                  int                len)
333 {
334   DBUS_CONST_STRING_PREAMBLE (str);
335   _dbus_assert (data_return != NULL);
336   _dbus_assert (start >= 0);
337   _dbus_assert (len >= 0);
338   _dbus_assert ((start + len) <= real->len);
339   
340   *data_return = real->str + start;
341 }
342
343 /**
344  * Like _dbus_string_get_data(), but removes the
345  * gotten data from the original string. The caller
346  * must free the data returned. This function may
347  * fail due to lack of memory, and return #FALSE.
348  *
349  * @param str the string
350  * @param data_return location to return the buffer
351  * @returns #TRUE on success
352  */
353 dbus_bool_t
354 _dbus_string_steal_data (DBusString        *str,
355                          char             **data_return)
356 {
357   DBUS_STRING_PREAMBLE (str);
358   _dbus_assert (data_return != NULL);
359   
360   *data_return = real->str;
361
362   /* reset the string */
363   if (!_dbus_string_init (str, real->max_length))
364     {
365       /* hrm, put it back then */
366       real->str = *data_return;
367       *data_return = NULL;
368       return FALSE;
369     }
370
371   return TRUE;
372 }
373
374 /**
375  * Like _dbus_string_get_data_len(), but removes the gotten data from
376  * the original string. The caller must free the data returned. This
377  * function may fail due to lack of memory, and return #FALSE.
378  * The returned string is nul-terminated and has length len.
379  *
380  * @param str the string
381  * @param data_return location to return the buffer
382  * @param start the start of segment to steal
383  * @param len the length of segment to steal
384  * @returns #TRUE on success
385  */
386 dbus_bool_t
387 _dbus_string_steal_data_len (DBusString        *str,
388                              char             **data_return,
389                              int                start,
390                              int                len)
391 {
392   DBusString dest;
393   
394   DBUS_STRING_PREAMBLE (str);
395   _dbus_assert (data_return != NULL);
396   _dbus_assert (start >= 0);
397   _dbus_assert (len >= 0);
398   _dbus_assert ((start + len) <= real->len);
399
400   if (!_dbus_string_init (&dest, real->max_length))
401     return FALSE;
402
403   if (!_dbus_string_move_len (str, start, len, &dest, 0))
404     {
405       _dbus_string_free (&dest);
406       return FALSE;
407     }
408   
409   if (!_dbus_string_steal_data (&dest, data_return))
410     {
411       _dbus_string_free (&dest);
412       return FALSE;
413     }
414
415   _dbus_string_free (&dest);
416   return TRUE;
417 }
418
419 /**
420  * Gets the length of a string (not including nul termination).
421  *
422  * @returns the length.
423  */
424 int
425 _dbus_string_get_length (const DBusString  *str)
426 {
427   DBUS_CONST_STRING_PREAMBLE (str);
428   
429   return real->len;
430 }
431
432 static dbus_bool_t
433 set_length (DBusRealString *real,
434             int             new_length)
435 {
436   /* Note, we are setting the length without nul termination */
437
438   /* exceeding max length is the same as failure to allocate memory */
439   if (new_length > real->max_length)
440     return FALSE;
441   
442   while (new_length >= real->allocated)
443     {
444       int new_allocated;
445       char *new_str;
446       
447       new_allocated = 2 + real->allocated * 2;
448       if (new_allocated < real->allocated)
449         return FALSE; /* overflow */
450         
451       new_str = dbus_realloc (real->str, new_allocated);
452       if (new_str == NULL)
453         return FALSE;
454
455       real->str = new_str;
456       real->allocated = new_allocated;
457     }
458
459   real->len = new_length;
460   real->str[real->len] = '\0';
461
462   return TRUE;
463 }
464
465 /**
466  * Makes a string longer by the given number of bytes.  Checks whether
467  * adding additional_length to the current length would overflow an
468  * integer, and checks for exceeding a string's max length.
469  * The new bytes are not initialized, other than nul-terminating
470  * the end of the string. The uninitialized bytes may contain
471  * unexpected nul bytes or other junk.
472  *
473  * @param str a string
474  * @param additional_length length to add to the string.
475  * @returns #TRUE on success.
476  */
477 dbus_bool_t
478 _dbus_string_lengthen (DBusString *str,
479                        int         additional_length)
480 {
481   DBUS_STRING_PREAMBLE (str);  
482   _dbus_assert (additional_length >= 0);
483   
484   if ((real->len + additional_length) < real->len)
485     return FALSE; /* overflow */
486   
487   return set_length (real,
488                      real->len + additional_length);
489 }
490
491 /**
492  * Makes a string shorter by the given number of bytes.
493  *
494  * @param str a string
495  * @param length_to_remove length to remove from the string.
496  */
497 void
498 _dbus_string_shorten (DBusString *str,
499                       int         length_to_remove)
500 {
501   DBUS_STRING_PREAMBLE (str);
502   _dbus_assert (length_to_remove >= 0);
503   _dbus_assert (length_to_remove <= real->len);
504
505   set_length (real,
506               real->len - length_to_remove);
507 }
508
509 /**
510  * Sets the length of a string. Can be used to truncate or lengthen
511  * the string. If the string is lengthened, the function may fail and
512  * return #FALSE. Newly-added bytes are not initialized, as with
513  * _dbus_string_lengthen().
514  *
515  * @param str a string
516  * @param length new length of the string.
517  * @returns #FALSE on failure.
518  */
519 dbus_bool_t
520 _dbus_string_set_length (DBusString *str,
521                          int         length)
522 {
523   DBUS_STRING_PREAMBLE (str);
524   _dbus_assert (length >= 0);
525
526   return set_length (real, length);
527 }
528
529 /**
530  * Align the length of a string to a specific alignment (typically 4 or 8)
531  * by appending nul bytes to the string.
532  *
533  * @param str a string
534  * @param alignment the alignment
535  * @returns #FALSE if no memory
536  */
537 dbus_bool_t
538 _dbus_string_align_length (DBusString *str,
539                            int         alignment)
540 {
541   int new_len;
542   int delta;
543   DBUS_STRING_PREAMBLE (str);
544   _dbus_assert (alignment >= 1);
545   _dbus_assert (alignment <= 16); /* arbitrary */
546
547   new_len = _DBUS_ALIGN_VALUE (real->len, alignment);
548
549   delta = new_len - real->len;
550   _dbus_assert (delta >= 0);
551
552   if (delta == 0)
553     return TRUE;
554
555   if (!set_length (real, new_len))
556     return FALSE;
557
558   memset (real->str + (new_len - delta),
559           '\0', delta);
560
561   return TRUE;
562 }
563
564 static dbus_bool_t
565 append (DBusRealString *real,
566         const char     *buffer,
567         int             buffer_len)
568 {
569   if (buffer_len == 0)
570     return TRUE;
571
572   if (!_dbus_string_lengthen ((DBusString*)real, buffer_len))
573     return FALSE;
574
575   memcpy (real->str + (real->len - buffer_len),
576           buffer,
577           buffer_len);
578
579   return TRUE;
580 }
581
582 /**
583  * Appends a nul-terminated C-style string to a DBusString.
584  *
585  * @param str the DBusString
586  * @param buffer the nul-terminated characters to append
587  * @returns #FALSE if not enough memory.
588  */
589 dbus_bool_t
590 _dbus_string_append (DBusString *str,
591                      const char *buffer)
592 {
593   int buffer_len;
594   
595   DBUS_STRING_PREAMBLE (str);
596   _dbus_assert (buffer != NULL);
597   
598   buffer_len = strlen (buffer);
599
600   return append (real, buffer, buffer_len);
601 }
602
603 /**
604  * Appends block of bytes with the given length to a DBusString.
605  *
606  * @param str the DBusString
607  * @param buffer the bytes to append
608  * @param len the number of bytes to append
609  * @returns #FALSE if not enough memory.
610  */
611 dbus_bool_t
612 _dbus_string_append_len (DBusString *str,
613                          const char *buffer,
614                          int         len)
615 {
616   DBUS_STRING_PREAMBLE (str);
617   _dbus_assert (buffer != NULL);
618   _dbus_assert (len >= 0);
619
620   return append (real, buffer, len);
621 }
622
623 /**
624  * Appends a single byte to the string, returning #FALSE
625  * if not enough memory.
626  *
627  * @param str the string
628  * @param byte the byte to append
629  * @returns #TRUE on success
630  */
631 dbus_bool_t
632 _dbus_string_append_byte (DBusString    *str,
633                           unsigned char  byte)
634 {
635   DBUS_STRING_PREAMBLE (str);
636
637   if (!set_length (real, real->len + 1))
638     return FALSE;
639
640   real->str[real->len-1] = byte;
641
642   return TRUE;
643 }
644
645 /**
646  * Appends a single Unicode character, encoding the character
647  * in UTF-8 format.
648  *
649  * @param str the string
650  * @param ch the Unicode character
651  */
652 dbus_bool_t
653 _dbus_string_append_unichar (DBusString    *str,
654                              dbus_unichar_t ch)
655 {
656   int len;
657   int first;
658   int i;
659   char *out;
660   
661   DBUS_STRING_PREAMBLE (str);
662
663   /* this code is from GLib but is pretty standard I think */
664   
665   len = 0;
666   
667   if (ch < 0x80)
668     {
669       first = 0;
670       len = 1;
671     }
672   else if (ch < 0x800)
673     {
674       first = 0xc0;
675       len = 2;
676     }
677   else if (ch < 0x10000)
678     {
679       first = 0xe0;
680       len = 3;
681     }
682    else if (ch < 0x200000)
683     {
684       first = 0xf0;
685       len = 4;
686     }
687   else if (ch < 0x4000000)
688     {
689       first = 0xf8;
690       len = 5;
691     }
692   else
693     {
694       first = 0xfc;
695       len = 6;
696     }
697
698   if (!set_length (real, real->len + len))
699     return FALSE;
700
701   out = real->str + (real->len - len);
702   
703   for (i = len - 1; i > 0; --i)
704     {
705       out[i] = (ch & 0x3f) | 0x80;
706       ch >>= 6;
707     }
708   out[0] = ch | first;
709
710   return TRUE;
711 }
712
713 static void
714 delete (DBusRealString *real,
715         int             start,
716         int             len)
717 {
718   if (len == 0)
719     return;
720   
721   memmove (real->str + start, real->str + start + len, real->len - (start + len));
722   real->len -= len;
723   real->str[real->len] = '\0';
724 }
725
726 /**
727  * Deletes a segment of a DBusString with length len starting at
728  * start. (Hint: to clear an entire string, setting length to 0
729  * with _dbus_string_set_length() is easier.)
730  *
731  * @param str the DBusString
732  * @param start where to start deleting
733  * @param len the number of bytes to delete
734  */
735 void
736 _dbus_string_delete (DBusString       *str,
737                      int               start,
738                      int               len)
739 {
740   DBUS_STRING_PREAMBLE (str);
741   _dbus_assert (start >= 0);
742   _dbus_assert (len >= 0);
743   _dbus_assert ((start + len) <= real->len);
744
745   delete (real, start, len);
746 }
747
748 static dbus_bool_t
749 open_gap (int             len,
750           DBusRealString *dest,
751           int             insert_at)
752 {
753   if (len == 0)
754     return TRUE;
755
756   if (!set_length (dest, dest->len + len))
757     return FALSE;
758
759   memmove (dest->str + insert_at + len, 
760            dest->str + insert_at,
761            dest->len - len - insert_at);
762
763   return TRUE;
764 }
765
766 static dbus_bool_t
767 copy (DBusRealString *source,
768       int             start,
769       int             len,
770       DBusRealString *dest,
771       int             insert_at)
772 {
773   if (!open_gap (len, dest, insert_at))
774     return FALSE;
775     
776   memcpy (dest->str + insert_at,
777           source->str + start,
778           len);
779
780   return TRUE;
781 }
782
783 /**
784  * Checks assertions for two strings we're copying a segment between,
785  * and declares real_source/real_dest variables.
786  *
787  * @param source the source string
788  * @param start the starting offset
789  * @param dest the dest string
790  * @param insert_at where the copied segment is inserted
791  */
792 #define DBUS_STRING_COPY_PREAMBLE(source, start, dest, insert_at)       \
793   DBusRealString *real_source = (DBusRealString*) source;               \
794   DBusRealString *real_dest = (DBusRealString*) dest;                   \
795   _dbus_assert ((source) != (dest));                                    \
796   DBUS_GENERIC_STRING_PREAMBLE (real_source);                           \
797   DBUS_GENERIC_STRING_PREAMBLE (real_dest);                             \
798   _dbus_assert (!real_source->constant);                                \
799   _dbus_assert (!real_source->locked);                                  \
800   _dbus_assert (!real_dest->constant);                                  \
801   _dbus_assert (!real_dest->locked);                                    \
802   _dbus_assert ((start) >= 0);                                          \
803   _dbus_assert ((start) <= real_source->len);                           \
804   _dbus_assert ((insert_at) >= 0);                                      \
805   _dbus_assert ((insert_at) <= real_dest->len)
806
807 /**
808  * Moves the end of one string into another string. Both strings
809  * must be initialized, valid strings.
810  *
811  * @param source the source string
812  * @param start where to chop off the source string
813  * @param dest the destination string
814  * @param insert_at where to move the chopped-off part of source string
815  * @returns #FALSE if not enough memory
816  */
817 dbus_bool_t
818 _dbus_string_move (DBusString       *source,
819                    int               start,
820                    DBusString       *dest,
821                    int               insert_at)
822 {
823   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
824   
825   if (!copy (real_source, start,
826              real_source->len - start,
827              real_dest,
828              insert_at))
829     return FALSE;
830
831   delete (real_source, start,
832           real_source->len - start);
833
834   return TRUE;
835 }
836
837 /**
838  * Like _dbus_string_move(), but does not delete the section
839  * of the source string that's copied to the dest string.
840  *
841  * @param source the source string
842  * @param start where to start copying the source string
843  * @param dest the destination string
844  * @param insert_at where to place the copied part of source string
845  * @returns #FALSE if not enough memory
846  */
847 dbus_bool_t
848 _dbus_string_copy (const DBusString *source,
849                    int               start,
850                    DBusString       *dest,
851                    int               insert_at)
852 {
853   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
854
855   return copy (real_source, start,
856                real_source->len - start,
857                real_dest,
858                insert_at);
859 }
860
861 /**
862  * Like _dbus_string_move(), but can move a segment from
863  * the middle of the source string.
864  * 
865  * @param source the source string
866  * @param start first byte of source string to move
867  * @param len length of segment to move
868  * @param dest the destination string
869  * @param insert_at where to move the bytes from the source string
870  * @returns #FALSE if not enough memory
871  */
872 dbus_bool_t
873 _dbus_string_move_len (DBusString       *source,
874                        int               start,
875                        int               len,
876                        DBusString       *dest,
877                        int               insert_at)
878
879 {
880   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
881   _dbus_assert (len >= 0);
882   _dbus_assert ((start + len) <= real_source->len);
883
884   if (!copy (real_source, start, len,
885              real_dest,
886              insert_at))
887     return FALSE;
888
889   delete (real_source, start,
890           real_source->len - start);
891
892   return TRUE;
893 }
894
895 /**
896  * Like _dbus_string_copy(), but can copy a segment from the middle of
897  * the source string.
898  *
899  * @param source the source string
900  * @param start where to start copying the source string
901  * @param len length of segment to copy
902  * @param dest the destination string
903  * @param insert_at where to place the copied segment of source string
904  * @returns #FALSE if not enough memory
905  */
906 dbus_bool_t
907 _dbus_string_copy_len (const DBusString *source,
908                        int               start,
909                        int               len,
910                        DBusString       *dest,
911                        int               insert_at)
912 {
913   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
914   _dbus_assert (len >= 0);
915   _dbus_assert ((start + len) <= real_source->len);
916   
917   return copy (real_source, start, len,
918                real_dest,
919                insert_at);
920 }
921
922 /* Unicode macros from GLib */
923
924 /** computes length and mask of a unicode character
925  * @param Char the char
926  * @param Mask the mask variable to assign to
927  * @param Len the length variable to assign to
928  */
929 #define UTF8_COMPUTE(Char, Mask, Len)                                         \
930   if (Char < 128)                                                             \
931     {                                                                         \
932       Len = 1;                                                                \
933       Mask = 0x7f;                                                            \
934     }                                                                         \
935   else if ((Char & 0xe0) == 0xc0)                                             \
936     {                                                                         \
937       Len = 2;                                                                \
938       Mask = 0x1f;                                                            \
939     }                                                                         \
940   else if ((Char & 0xf0) == 0xe0)                                             \
941     {                                                                         \
942       Len = 3;                                                                \
943       Mask = 0x0f;                                                            \
944     }                                                                         \
945   else if ((Char & 0xf8) == 0xf0)                                             \
946     {                                                                         \
947       Len = 4;                                                                \
948       Mask = 0x07;                                                            \
949     }                                                                         \
950   else if ((Char & 0xfc) == 0xf8)                                             \
951     {                                                                         \
952       Len = 5;                                                                \
953       Mask = 0x03;                                                            \
954     }                                                                         \
955   else if ((Char & 0xfe) == 0xfc)                                             \
956     {                                                                         \
957       Len = 6;                                                                \
958       Mask = 0x01;                                                            \
959     }                                                                         \
960   else                                                                        \
961     Len = -1;
962
963 /**
964  * computes length of a unicode character in UTF-8
965  * @param Char the char
966  */
967 #define UTF8_LENGTH(Char)              \
968   ((Char) < 0x80 ? 1 :                 \
969    ((Char) < 0x800 ? 2 :               \
970     ((Char) < 0x10000 ? 3 :            \
971      ((Char) < 0x200000 ? 4 :          \
972       ((Char) < 0x4000000 ? 5 : 6)))))
973    
974 /**
975  * Gets a UTF-8 value.
976  *
977  * @param Result variable for extracted unicode char.
978  * @param Chars the bytes to decode
979  * @param Count counter variable
980  * @param Mask mask for this char
981  * @param Len length for this char in bytes
982  */
983 #define UTF8_GET(Result, Chars, Count, Mask, Len)                             \
984   (Result) = (Chars)[0] & (Mask);                                             \
985   for ((Count) = 1; (Count) < (Len); ++(Count))                               \
986     {                                                                         \
987       if (((Chars)[(Count)] & 0xc0) != 0x80)                                  \
988         {                                                                     \
989           (Result) = -1;                                                      \
990           break;                                                              \
991         }                                                                     \
992       (Result) <<= 6;                                                         \
993       (Result) |= ((Chars)[(Count)] & 0x3f);                                  \
994     }
995
996 /**
997  * Check whether a unicode char is in a valid range.
998  *
999  * @param Char the character
1000  */
1001 #define UNICODE_VALID(Char)                   \
1002     ((Char) < 0x110000 &&                     \
1003      ((Char) < 0xD800 || (Char) >= 0xE000) && \
1004      (Char) != 0xFFFE && (Char) != 0xFFFF)   
1005
1006 /**
1007  * Gets a unicode character from a UTF-8 string. Does no validation;
1008  * you must verify that the string is valid UTF-8 in advance and must
1009  * pass in the start of a character.
1010  *
1011  * @param str the string
1012  * @param start the start of the UTF-8 character.
1013  * @param ch_return location to return the character
1014  * @param end_return location to return the byte index of next character
1015  * @returns #TRUE on success, #FALSE otherwise.
1016  */
1017 void
1018 _dbus_string_get_unichar (const DBusString *str,
1019                           int               start,
1020                           dbus_unichar_t   *ch_return,
1021                           int              *end_return)
1022 {
1023   int i, mask, len;
1024   dbus_unichar_t result;
1025   unsigned char c;
1026   unsigned char *p;
1027   DBUS_CONST_STRING_PREAMBLE (str);
1028
1029   if (ch_return)
1030     *ch_return = 0;
1031   if (end_return)
1032     *end_return = real->len;
1033   
1034   mask = 0;
1035   p = real->str + start;
1036   c = *p;
1037   
1038   UTF8_COMPUTE (c, mask, len);
1039   if (len == -1)
1040     return;
1041   UTF8_GET (result, p, i, mask, len);
1042
1043   if (result == (dbus_unichar_t)-1)
1044     return;
1045
1046   if (ch_return)
1047     *ch_return = result;
1048   if (end_return)
1049     *end_return = start + len;
1050 }
1051
1052 /**
1053  * Finds the given substring in the string,
1054  * returning #TRUE and filling in the byte index
1055  * where the substring was found, if it was found.
1056  * Returns #FALSE if the substring wasn't found.
1057  * Sets *start to the length of the string if the substring
1058  * is not found.
1059  *
1060  * @param str the string
1061  * @param start where to start looking
1062  * @param substr the substring
1063  * @param found return location for where it was found, or #NULL
1064  * @returns #TRUE if found
1065  */
1066 dbus_bool_t
1067 _dbus_string_find (const DBusString *str,
1068                    int               start,
1069                    const char       *substr,
1070                    int              *found)
1071 {
1072   int i;
1073   DBUS_CONST_STRING_PREAMBLE (str);
1074   _dbus_assert (substr != NULL);
1075   _dbus_assert (start <= real->len);
1076   
1077   /* we always "find" an empty string */
1078   if (*substr == '\0')
1079     {
1080       if (found)
1081         *found = 0;
1082       return TRUE;
1083     }
1084   
1085   i = start;
1086   while (i < real->len)
1087     {
1088       if (real->str[i] == substr[0])
1089         {
1090           int j = i + 1;
1091           
1092           while (j < real->len)
1093             {
1094               if (substr[j - i] == '\0')
1095                 break;
1096               else if (real->str[j] != substr[j - i])
1097                 break;
1098               
1099               ++j;
1100             }
1101
1102           if (substr[j - i] == '\0')
1103             {
1104               if (found)
1105                 *found = i;
1106               return TRUE;
1107             }
1108         }
1109       
1110       ++i;
1111     }
1112
1113   if (found)
1114     *found = real->len;
1115   
1116   return FALSE;
1117 }
1118
1119 /**
1120  * Finds a blank (space or tab) in the string. Returns #TRUE
1121  * if found, #FALSE otherwise. If a blank is not found sets
1122  * *found to the length of the string.
1123  *
1124  * @param str the string
1125  * @param start byte index to start looking
1126  * @param found place to store the location of the first blank
1127  * @returns #TRUE if a blank was found
1128  */
1129 dbus_bool_t
1130 _dbus_string_find_blank (const DBusString *str,
1131                          int               start,
1132                          int              *found)
1133 {
1134   int i;
1135   DBUS_CONST_STRING_PREAMBLE (str);
1136   _dbus_assert (start <= real->len);
1137   
1138   i = start;
1139   while (i < real->len)
1140     {
1141       if (real->str[i] == ' ' ||
1142           real->str[i] == '\t')
1143         {
1144           if (found)
1145             *found = i;
1146           return TRUE;
1147         }
1148       
1149       ++i;
1150     }
1151
1152   if (found)
1153     *found = real->len;
1154   
1155   return FALSE;
1156 }
1157
1158 /**
1159  * Skips blanks from start, storing the first non-blank in *end
1160  *
1161  * @param str the string
1162  * @param start where to start
1163  * @param end where to store the first non-blank byte index
1164  */
1165 void
1166 _dbus_string_skip_blank (const DBusString *str,
1167                          int               start,
1168                          int              *end)
1169 {
1170   int i;
1171   DBUS_CONST_STRING_PREAMBLE (str);
1172   _dbus_assert (start <= real->len);
1173   
1174   i = start;
1175   while (i < real->len)
1176     {
1177       if (!(real->str[i] == ' ' ||
1178             real->str[i] == '\t'))
1179         break;
1180       
1181       ++i;
1182     }
1183
1184   _dbus_assert (i == real->len || !(real->str[i] == ' ' ||
1185                                     real->str[i] == '\t'));
1186   
1187   if (end)
1188     *end = i;
1189 }
1190
1191 /**
1192  * Tests two DBusString for equality.
1193  *
1194  * @param a first string
1195  * @param b second string
1196  * @returns #TRUE if equal
1197  */
1198 dbus_bool_t
1199 _dbus_string_equal (const DBusString *a,
1200                     const DBusString *b)
1201 {
1202   const unsigned char *ap;
1203   const unsigned char *bp;
1204   const unsigned char *a_end;
1205   const DBusRealString *real_a = (const DBusRealString*) a;
1206   const DBusRealString *real_b = (const DBusRealString*) b;
1207   DBUS_GENERIC_STRING_PREAMBLE (real_a);
1208   DBUS_GENERIC_STRING_PREAMBLE (real_b);
1209
1210   if (real_a->len != real_b->len)
1211     return FALSE;
1212
1213   ap = real_a->str;
1214   bp = real_b->str;
1215   a_end = real_a->str + real_a->len;
1216   while (ap != a_end)
1217     {
1218       if (*ap != *bp)
1219         return FALSE;
1220       
1221       ++ap;
1222       ++bp;
1223     }
1224
1225   return TRUE;
1226 }
1227
1228 /**
1229  * Checks whether a string is equal to a C string.
1230  *
1231  * @param a the string
1232  * @param c_str the C string
1233  * @returns #TRUE if equal
1234  */
1235 dbus_bool_t
1236 _dbus_string_equal_c_str (const DBusString *a,
1237                           const char       *c_str)
1238 {
1239   const unsigned char *ap;
1240   const unsigned char *bp;
1241   const unsigned char *a_end;
1242   const DBusRealString *real_a = (const DBusRealString*) a;
1243   DBUS_GENERIC_STRING_PREAMBLE (real_a);
1244
1245   ap = real_a->str;
1246   bp = (const unsigned char*) c_str;
1247   a_end = real_a->str + real_a->len;
1248   while (ap != a_end && *bp)
1249     {
1250       if (*ap != *bp)
1251         return FALSE;
1252       
1253       ++ap;
1254       ++bp;
1255     }
1256
1257   if (*ap && *bp == '\0')
1258     return FALSE;
1259   else if (ap == a_end && *bp)
1260     return FALSE;
1261   
1262   return TRUE;
1263 }
1264
1265 static const signed char base64_table[] = {
1266   /* 0 */ 'A',
1267   /* 1 */ 'B',
1268   /* 2 */ 'C',
1269   /* 3 */ 'D',
1270   /* 4 */ 'E',
1271   /* 5 */ 'F',
1272   /* 6 */ 'G',
1273   /* 7 */ 'H',
1274   /* 8 */ 'I',
1275   /* 9 */ 'J',
1276   /* 10 */ 'K',
1277   /* 11 */ 'L',
1278   /* 12 */ 'M',
1279   /* 13 */ 'N',
1280   /* 14 */ 'O',
1281   /* 15 */ 'P',
1282   /* 16 */ 'Q',
1283   /* 17 */ 'R',
1284   /* 18 */ 'S',
1285   /* 19 */ 'T',
1286   /* 20 */ 'U',
1287   /* 21 */ 'V',
1288   /* 22 */ 'W',
1289   /* 23 */ 'X',
1290   /* 24 */ 'Y',
1291   /* 25 */ 'Z',
1292   /* 26 */ 'a',
1293   /* 27 */ 'b',
1294   /* 28 */ 'c',
1295   /* 29 */ 'd',
1296   /* 30 */ 'e',
1297   /* 31 */ 'f',
1298   /* 32 */ 'g',
1299   /* 33 */ 'h',
1300   /* 34 */ 'i',
1301   /* 35 */ 'j',
1302   /* 36 */ 'k',
1303   /* 37 */ 'l',
1304   /* 38 */ 'm',
1305   /* 39 */ 'n',
1306   /* 40 */ 'o',
1307   /* 41 */ 'p',
1308   /* 42 */ 'q',
1309   /* 43 */ 'r',
1310   /* 44 */ 's',
1311   /* 45 */ 't',
1312   /* 46 */ 'u',
1313   /* 47 */ 'v',
1314   /* 48 */ 'w',
1315   /* 49 */ 'x',
1316   /* 50 */ 'y',
1317   /* 51 */ 'z',
1318   /* 52 */ '0',
1319   /* 53 */ '1',
1320   /* 54 */ '2',
1321   /* 55 */ '3',
1322   /* 56 */ '4',
1323   /* 57 */ '5',
1324   /* 58 */ '6',
1325   /* 59 */ '7',
1326   /* 60 */ '8',
1327   /* 61 */ '9',
1328   /* 62 */ '+',
1329   /* 63 */ '/'
1330 };
1331
1332 /** The minimum char that's a valid char in Base64-encoded text */
1333 #define UNBASE64_MIN_CHAR (43)
1334 /** The maximum char that's a valid char in Base64-encoded text */
1335 #define UNBASE64_MAX_CHAR (122)
1336 /** Must subtract this from a char's integer value before offsetting
1337  * into unbase64_table
1338  */
1339 #define UNBASE64_TABLE_OFFSET UNBASE64_MIN_CHAR
1340 static const signed char unbase64_table[] = {
1341   /* 43 + */ 62,
1342   /* 44 , */ -1,
1343   /* 45 - */ -1,
1344   /* 46 . */ -1,
1345   /* 47 / */ 63,
1346   /* 48 0 */ 52,
1347   /* 49 1 */ 53,
1348   /* 50 2 */ 54,
1349   /* 51 3 */ 55,
1350   /* 52 4 */ 56,
1351   /* 53 5 */ 57,
1352   /* 54 6 */ 58,
1353   /* 55 7 */ 59,
1354   /* 56 8 */ 60,
1355   /* 57 9 */ 61,
1356   /* 58 : */ -1,
1357   /* 59 ; */ -1,
1358   /* 60 < */ -1,
1359   /* 61 = */ -1,
1360   /* 62 > */ -1,
1361   /* 63 ? */ -1,
1362   /* 64 @ */ -1,
1363   /* 65 A */ 0,
1364   /* 66 B */ 1,
1365   /* 67 C */ 2,
1366   /* 68 D */ 3,
1367   /* 69 E */ 4,
1368   /* 70 F */ 5,
1369   /* 71 G */ 6,
1370   /* 72 H */ 7,
1371   /* 73 I */ 8,
1372   /* 74 J */ 9,
1373   /* 75 K */ 10,
1374   /* 76 L */ 11,
1375   /* 77 M */ 12,
1376   /* 78 N */ 13,
1377   /* 79 O */ 14,
1378   /* 80 P */ 15,
1379   /* 81 Q */ 16,
1380   /* 82 R */ 17,
1381   /* 83 S */ 18,
1382   /* 84 T */ 19,
1383   /* 85 U */ 20,
1384   /* 86 V */ 21,
1385   /* 87 W */ 22,
1386   /* 88 X */ 23,
1387   /* 89 Y */ 24,
1388   /* 90 Z */ 25,
1389   /* 91 [ */ -1,
1390   /* 92 \ */ -1,
1391   /* 93 ] */ -1,
1392   /* 94 ^ */ -1,
1393   /* 95 _ */ -1,
1394   /* 96 ` */ -1,
1395   /* 97 a */ 26,
1396   /* 98 b */ 27,
1397   /* 99 c */ 28,
1398   /* 100 d */ 29,
1399   /* 101 e */ 30,
1400   /* 102 f */ 31,
1401   /* 103 g */ 32,
1402   /* 104 h */ 33,
1403   /* 105 i */ 34,
1404   /* 106 j */ 35,
1405   /* 107 k */ 36,
1406   /* 108 l */ 37,
1407   /* 109 m */ 38,
1408   /* 110 n */ 39,
1409   /* 111 o */ 40,
1410   /* 112 p */ 41,
1411   /* 113 q */ 42,
1412   /* 114 r */ 43,
1413   /* 115 s */ 44,
1414   /* 116 t */ 45,
1415   /* 117 u */ 46,
1416   /* 118 v */ 47,
1417   /* 119 w */ 48,
1418   /* 120 x */ 49,
1419   /* 121 y */ 50,
1420   /* 122 z */ 51
1421 };
1422
1423 /**
1424  * Encodes a string using Base64, as documented in RFC 2045.
1425  *
1426  * @param source the string to encode
1427  * @param start byte index to start encoding
1428  * @param dest string where encoded data should be placed
1429  * @param insert_at where to place encoded data
1430  * @returns #TRUE if encoding was successful, #FALSE if no memory etc.
1431  */
1432 dbus_bool_t
1433 _dbus_string_base64_encode (const DBusString *source,
1434                             int               start,
1435                             DBusString       *dest,
1436                             int               insert_at)
1437 {
1438   int source_len;
1439   int dest_len;
1440   const unsigned char *s;
1441   unsigned char *d;
1442   const unsigned char *triplet_end;
1443   const unsigned char *final_end;
1444   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);  
1445   _dbus_assert (source != dest);
1446   
1447   /* For each 24 bits (3 bytes) of input, we have 4 chars of
1448    * output.
1449    */
1450   source_len = real_source->len - start;
1451   dest_len = (source_len / 3) * 4;
1452   if (source_len % 3 != 0)
1453     dest_len += 4;
1454
1455   if (source_len == 0)
1456     return TRUE;
1457   
1458   if (!open_gap (dest_len, real_dest, insert_at))
1459     return FALSE;
1460
1461   d = real_dest->str + insert_at;
1462   s = real_source->str + start;
1463   final_end = real_source->str + (start + source_len);
1464   triplet_end = final_end - (source_len % 3);
1465   _dbus_assert (triplet_end <= final_end);
1466   _dbus_assert ((final_end - triplet_end) < 3);
1467
1468 #define ENCODE_64(v) (base64_table[ (unsigned char) (v) ])
1469 #define SIX_BITS_MASK (0x3f)
1470   _dbus_assert (SIX_BITS_MASK < _DBUS_N_ELEMENTS (base64_table));
1471   
1472   while (s != triplet_end)
1473     {
1474       unsigned int triplet;
1475
1476       triplet = s[0] | (s[1] << 8) | (s[2] << 16);
1477
1478       /* Encode each 6 bits */
1479       
1480       *d++ = ENCODE_64 (triplet >> 18);
1481       *d++ = ENCODE_64 ((triplet >> 12) & SIX_BITS_MASK);
1482       *d++ = ENCODE_64 ((triplet >> 6) & SIX_BITS_MASK);
1483       *d++ = ENCODE_64 (triplet & SIX_BITS_MASK);
1484       
1485       s += 3;
1486     }
1487
1488   switch (final_end - triplet_end)
1489     {
1490     case 2:
1491       {
1492         unsigned int doublet;
1493         
1494         doublet = s[0] | (s[1] << 8);
1495         
1496         *d++ = ENCODE_64 (doublet >> 12);
1497         *d++ = ENCODE_64 ((doublet >> 6) & SIX_BITS_MASK);
1498         *d++ = ENCODE_64 (doublet & SIX_BITS_MASK);
1499         *d++ = '=';
1500       }
1501       break;
1502     case 1:
1503       {
1504         unsigned int singlet;
1505         
1506         singlet = s[0];
1507         
1508         *d++ = ENCODE_64 ((singlet >> 6) & SIX_BITS_MASK);
1509         *d++ = ENCODE_64 (singlet & SIX_BITS_MASK);
1510         *d++ = '=';
1511         *d++ = '=';
1512       }
1513       break;
1514     case 0:
1515       break;
1516     }
1517
1518   _dbus_assert (d == (real_dest->str + (insert_at + dest_len)));
1519
1520   return TRUE;
1521 }
1522
1523
1524 /**
1525  * Decodes a string from Base64, as documented in RFC 2045.
1526  *
1527  * @param source the string to decode
1528  * @param start byte index to start decode
1529  * @param dest string where decoded data should be placed
1530  * @param insert_at where to place decoded data
1531  * @returns #TRUE if decoding was successful, #FALSE if no memory etc.
1532  */
1533 dbus_bool_t
1534 _dbus_string_base64_decode (const DBusString *source,
1535                             int               start,
1536                             DBusString       *dest,
1537                             int               insert_at)
1538 {
1539   int source_len;
1540   const char *s;
1541   const char *end;
1542   DBusString result;
1543   unsigned int triplet = 0;
1544   int sextet_count;
1545   int pad_count;
1546   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
1547   _dbus_assert (source != dest);
1548   
1549   source_len = real_source->len - start;
1550   s = real_source->str + start;
1551   end = real_source->str + source_len;
1552
1553   if (source_len == 0)
1554     return TRUE;
1555
1556   if (!_dbus_string_init (&result, _DBUS_INT_MAX))
1557     return FALSE;
1558
1559   pad_count = 0;
1560   sextet_count = 0;
1561   while (s != end)
1562     {
1563       /* The idea is to just skip anything that isn't
1564        * a base64 char - it's allowed to have whitespace,
1565        * newlines, etc. in here. We also ignore trailing
1566        * base64 chars, though that's suspicious.
1567        */
1568       
1569       if (*s >= UNBASE64_MIN_CHAR &&
1570           *s <= UNBASE64_MAX_CHAR)
1571         {
1572           if (*s == '=')
1573             {
1574               /* '=' is padding, doesn't represent additional data
1575                * but does increment our count.
1576                */
1577               pad_count += 1;
1578               sextet_count += 1;
1579             }
1580           else
1581             {
1582               int val;
1583
1584               val = unbase64_table[(*s) - UNBASE64_TABLE_OFFSET];
1585
1586               if (val >= 0)
1587                 {
1588                   triplet <<= 6;
1589                   triplet |= (unsigned int) val;
1590                   sextet_count += 1;
1591                 }
1592             }
1593
1594           if (sextet_count == 4)
1595             {
1596               /* no pad = 3 bytes, 1 pad = 2 bytes, 2 pad = 1 byte */
1597               
1598               _dbus_string_append_byte (&result,
1599                                         triplet & 0xff);
1600               
1601               if (pad_count < 2)
1602                 _dbus_string_append_byte (&result,
1603                                           (triplet >> 8) & 0xff);
1604
1605               if (pad_count < 1)
1606                 _dbus_string_append_byte (&result,
1607                                           triplet >> 16);
1608
1609               sextet_count = 0;
1610               pad_count = 0;
1611               triplet = 0;
1612             }
1613         }
1614       
1615       ++s;
1616     }
1617
1618   if (!_dbus_string_move (&result, 0, dest, insert_at))
1619     {
1620       _dbus_string_free (&result);
1621       return FALSE;
1622     }
1623
1624   _dbus_string_free (&result);
1625
1626   return TRUE;
1627 }
1628
1629 /**
1630  * Checks that the given range of the string
1631  * is valid ASCII. If the given range is not contained
1632  * in the string, returns #FALSE.
1633  *
1634  * @param str the string
1635  * @param start first byte index to check
1636  * @param len number of bytes to check
1637  * @returns #TRUE if the byte range exists and is all valid ASCII
1638  */
1639 dbus_bool_t
1640 _dbus_string_validate_ascii (const DBusString *str,
1641                              int               start,
1642                              int               len)
1643 {
1644   const unsigned char *s;
1645   const unsigned char *end;
1646   DBUS_CONST_STRING_PREAMBLE (str);
1647   _dbus_assert (start >= 0);
1648   _dbus_assert (len >= 0);
1649   
1650   if ((start + len) > real->len)
1651     return FALSE;
1652   
1653   s = real->str + start;
1654   end = s + len;
1655   while (s != end)
1656     {
1657       if (*s == '\0' ||
1658           ((*s & ~0x7f) != 0))
1659         return FALSE;
1660         
1661       ++s;
1662     }
1663   
1664   return TRUE;
1665 }
1666
1667 /** @} */
1668
1669 #ifdef DBUS_BUILD_TESTS
1670 #include "dbus-test.h"
1671 #include <stdio.h>
1672
1673 static void
1674 test_max_len (DBusString *str,
1675               int         max_len)
1676 {
1677   if (max_len > 0)
1678     {
1679       if (!_dbus_string_set_length (str, max_len - 1))
1680         _dbus_assert_not_reached ("setting len to one less than max should have worked");
1681     }
1682
1683   if (!_dbus_string_set_length (str, max_len))
1684     _dbus_assert_not_reached ("setting len to max len should have worked");
1685
1686   if (_dbus_string_set_length (str, max_len + 1))
1687     _dbus_assert_not_reached ("setting len to one more than max len should not have worked");
1688
1689   if (!_dbus_string_set_length (str, 0))
1690     _dbus_assert_not_reached ("setting len to zero should have worked");
1691 }
1692
1693 static void
1694 test_base64_roundtrip (const unsigned char *data,
1695                        int                  len)
1696 {
1697   DBusString orig;
1698   DBusString encoded;
1699   DBusString decoded;
1700
1701   if (len < 0)
1702     len = strlen (data);
1703   
1704   if (!_dbus_string_init (&orig, _DBUS_INT_MAX))
1705     _dbus_assert_not_reached ("could not init string");
1706
1707   if (!_dbus_string_init (&encoded, _DBUS_INT_MAX))
1708     _dbus_assert_not_reached ("could not init string");
1709   
1710   if (!_dbus_string_init (&decoded, _DBUS_INT_MAX))
1711     _dbus_assert_not_reached ("could not init string");
1712
1713   if (!_dbus_string_append_len (&orig, data, len))
1714     _dbus_assert_not_reached ("couldn't append orig data");
1715
1716   if (!_dbus_string_base64_encode (&orig, 0, &encoded, 0))
1717     _dbus_assert_not_reached ("could not encode");
1718
1719   if (!_dbus_string_base64_decode (&encoded, 0, &decoded, 0))
1720     _dbus_assert_not_reached ("could not decode");
1721
1722   if (!_dbus_string_equal (&orig, &decoded))
1723     {
1724       const char *s;
1725       
1726       printf ("Original string %d bytes encoded %d bytes decoded %d bytes\n",
1727               _dbus_string_get_length (&orig),
1728               _dbus_string_get_length (&encoded),
1729               _dbus_string_get_length (&decoded));
1730       printf ("Original: %s\n", data);
1731       _dbus_string_get_const_data (&decoded, &s);
1732       printf ("Decoded: %s\n", s);
1733       _dbus_assert_not_reached ("original string not the same as string decoded from base64");
1734     }
1735   
1736   _dbus_string_free (&orig);
1737   _dbus_string_free (&encoded);
1738   _dbus_string_free (&decoded);  
1739 }
1740
1741 /**
1742  * @ingroup DBusStringInternals
1743  * Unit test for DBusString.
1744  *
1745  * @todo Need to write tests for _dbus_string_copy() and
1746  * _dbus_string_move() moving to/from each of start/middle/end of a
1747  * string.
1748  * 
1749  * @returns #TRUE on success.
1750  */
1751 dbus_bool_t
1752 _dbus_string_test (void)
1753 {
1754   DBusString str;
1755   DBusString other;
1756   int i, end;
1757   long v;
1758   double d;
1759   int lens[] = { 0, 1, 2, 3, 4, 5, 10, 16, 17, 18, 25, 31, 32, 33, 34, 35, 63, 64, 65, 66, 67, 68, 69, 70, 71, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136 };
1760   char *s;
1761   dbus_unichar_t ch;
1762   
1763   i = 0;
1764   while (i < _DBUS_N_ELEMENTS (lens))
1765     {
1766       if (!_dbus_string_init (&str, lens[i]))
1767         _dbus_assert_not_reached ("failed to init string");
1768       
1769       test_max_len (&str, lens[i]);
1770       _dbus_string_free (&str);
1771
1772       ++i;
1773     }
1774
1775   /* Test shortening and setting length */
1776   i = 0;
1777   while (i < _DBUS_N_ELEMENTS (lens))
1778     {
1779       int j;
1780       
1781       if (!_dbus_string_init (&str, lens[i]))
1782         _dbus_assert_not_reached ("failed to init string");
1783       
1784       if (!_dbus_string_set_length (&str, lens[i]))
1785         _dbus_assert_not_reached ("failed to set string length");
1786
1787       j = lens[i];
1788       while (j > 0)
1789         {
1790           _dbus_assert (_dbus_string_get_length (&str) == j);
1791           if (j > 0)
1792             {
1793               _dbus_string_shorten (&str, 1);
1794               _dbus_assert (_dbus_string_get_length (&str) == (j - 1));
1795             }
1796           --j;
1797         }
1798       
1799       _dbus_string_free (&str);
1800
1801       ++i;
1802     }
1803
1804   /* Test appending data */
1805   if (!_dbus_string_init (&str, _DBUS_INT_MAX))
1806     _dbus_assert_not_reached ("failed to init string");
1807
1808   i = 0;
1809   while (i < 10)
1810     {
1811       if (!_dbus_string_append (&str, "a"))
1812         _dbus_assert_not_reached ("failed to append string to string\n");
1813
1814       _dbus_assert (_dbus_string_get_length (&str) == i * 2 + 1);
1815
1816       if (!_dbus_string_append_byte (&str, 'b'))
1817         _dbus_assert_not_reached ("failed to append byte to string\n");
1818
1819       _dbus_assert (_dbus_string_get_length (&str) == i * 2 + 2);
1820                     
1821       ++i;
1822     }
1823
1824   _dbus_string_free (&str);
1825
1826   /* Check steal_data */
1827   
1828   if (!_dbus_string_init (&str, _DBUS_INT_MAX))
1829     _dbus_assert_not_reached ("failed to init string");
1830
1831   if (!_dbus_string_append (&str, "Hello World"))
1832     _dbus_assert_not_reached ("could not append to string");
1833
1834   i = _dbus_string_get_length (&str);
1835   
1836   if (!_dbus_string_steal_data (&str, &s))
1837     _dbus_assert_not_reached ("failed to steal data");
1838
1839   _dbus_assert (_dbus_string_get_length (&str) == 0);
1840   _dbus_assert (((int)strlen (s)) == i);
1841
1842   dbus_free (s);
1843
1844   /* Check move */
1845   
1846   if (!_dbus_string_append (&str, "Hello World"))
1847     _dbus_assert_not_reached ("could not append to string");
1848
1849   i = _dbus_string_get_length (&str);
1850
1851   if (!_dbus_string_init (&other, _DBUS_INT_MAX))
1852     _dbus_assert_not_reached ("could not init string");
1853   
1854   if (!_dbus_string_move (&str, 0, &other, 0))
1855     _dbus_assert_not_reached ("could not move");
1856
1857   _dbus_assert (_dbus_string_get_length (&str) == 0);
1858   _dbus_assert (_dbus_string_get_length (&other) == i);
1859
1860   if (!_dbus_string_append (&str, "Hello World"))
1861     _dbus_assert_not_reached ("could not append to string");
1862   
1863   if (!_dbus_string_move (&str, 0, &other, _dbus_string_get_length (&other)))
1864     _dbus_assert_not_reached ("could not move");
1865
1866   _dbus_assert (_dbus_string_get_length (&str) == 0);
1867   _dbus_assert (_dbus_string_get_length (&other) == i * 2);
1868
1869     if (!_dbus_string_append (&str, "Hello World"))
1870     _dbus_assert_not_reached ("could not append to string");
1871   
1872   if (!_dbus_string_move (&str, 0, &other, _dbus_string_get_length (&other) / 2))
1873     _dbus_assert_not_reached ("could not move");
1874
1875   _dbus_assert (_dbus_string_get_length (&str) == 0);
1876   _dbus_assert (_dbus_string_get_length (&other) == i * 3);
1877   
1878   _dbus_string_free (&other);
1879
1880   /* Check copy */
1881   
1882   if (!_dbus_string_append (&str, "Hello World"))
1883     _dbus_assert_not_reached ("could not append to string");
1884
1885   i = _dbus_string_get_length (&str);
1886   
1887   if (!_dbus_string_init (&other, _DBUS_INT_MAX))
1888     _dbus_assert_not_reached ("could not init string");
1889   
1890   if (!_dbus_string_copy (&str, 0, &other, 0))
1891     _dbus_assert_not_reached ("could not copy");
1892
1893   _dbus_assert (_dbus_string_get_length (&str) == i);
1894   _dbus_assert (_dbus_string_get_length (&other) == i);
1895
1896   if (!_dbus_string_copy (&str, 0, &other, _dbus_string_get_length (&other)))
1897     _dbus_assert_not_reached ("could not copy");
1898
1899   _dbus_assert (_dbus_string_get_length (&str) == i);
1900   _dbus_assert (_dbus_string_get_length (&other) == i * 2);
1901   _dbus_assert (_dbus_string_equal_c_str (&other,
1902                                           "Hello WorldHello World"));
1903
1904   if (!_dbus_string_copy (&str, 0, &other, _dbus_string_get_length (&other) / 2))
1905     _dbus_assert_not_reached ("could not copy");
1906
1907   _dbus_assert (_dbus_string_get_length (&str) == i);
1908   _dbus_assert (_dbus_string_get_length (&other) == i * 3);
1909   _dbus_assert (_dbus_string_equal_c_str (&other,
1910                                           "Hello WorldHello WorldHello World"));
1911   
1912   _dbus_string_free (&str);
1913   _dbus_string_free (&other);
1914
1915   /* Check append/get unichar */
1916   
1917   if (!_dbus_string_init (&str, _DBUS_INT_MAX))
1918     _dbus_assert_not_reached ("failed to init string");
1919
1920   ch = 0;
1921   if (!_dbus_string_append_unichar (&str, 0xfffc))
1922     _dbus_assert_not_reached ("failed to append unichar");
1923
1924   _dbus_string_get_unichar (&str, 0, &ch, &i);
1925
1926   _dbus_assert (ch == 0xfffc);
1927   _dbus_assert (i == _dbus_string_get_length (&str));
1928
1929   _dbus_string_free (&str);
1930   
1931   /* Check append/parse int/double */
1932   
1933   if (!_dbus_string_init (&str, _DBUS_INT_MAX))
1934     _dbus_assert_not_reached ("failed to init string");
1935
1936   if (!_dbus_string_append_int (&str, 27))
1937     _dbus_assert_not_reached ("failed to append int");
1938
1939   i = _dbus_string_get_length (&str);
1940
1941   if (!_dbus_string_parse_int (&str, 0, &v, &end))
1942     _dbus_assert_not_reached ("failed to parse int");
1943
1944   _dbus_assert (v == 27);
1945   _dbus_assert (end == i);
1946
1947   _dbus_string_free (&str);
1948   
1949   if (!_dbus_string_init (&str, _DBUS_INT_MAX))
1950     _dbus_assert_not_reached ("failed to init string");
1951   
1952   if (!_dbus_string_append_double (&str, 50.3))
1953     _dbus_assert_not_reached ("failed to append float");
1954
1955   i = _dbus_string_get_length (&str);
1956
1957   if (!_dbus_string_parse_double (&str, 0, &d, &end))
1958     _dbus_assert_not_reached ("failed to parse float");
1959
1960   _dbus_assert (d > (50.3 - 1e-6) && d < (50.3 + 1e-6));
1961   _dbus_assert (end == i);
1962
1963   _dbus_string_free (&str);
1964
1965   /* Test find */
1966   if (!_dbus_string_init (&str, _DBUS_INT_MAX))
1967     _dbus_assert_not_reached ("failed to init string");
1968
1969   if (!_dbus_string_append (&str, "Hello"))
1970     _dbus_assert_not_reached ("couldn't append to string");
1971   
1972   if (!_dbus_string_find (&str, 0, "He", &i))
1973     _dbus_assert_not_reached ("didn't find 'He'");
1974   _dbus_assert (i == 0);
1975
1976   if (!_dbus_string_find (&str, 0, "ello", &i))
1977     _dbus_assert_not_reached ("didn't find 'ello'");
1978   _dbus_assert (i == 1);
1979
1980   if (!_dbus_string_find (&str, 0, "lo", &i))
1981     _dbus_assert_not_reached ("didn't find 'lo'");
1982   _dbus_assert (i == 3);
1983
1984   if (!_dbus_string_find (&str, 2, "lo", &i))
1985     _dbus_assert_not_reached ("didn't find 'lo'");
1986   _dbus_assert (i == 3);
1987
1988   if (_dbus_string_find (&str, 4, "lo", &i))
1989     _dbus_assert_not_reached ("did find 'lo'");
1990   
1991   if (!_dbus_string_find (&str, 0, "l", &i))
1992     _dbus_assert_not_reached ("didn't find 'l'");
1993   _dbus_assert (i == 2);
1994
1995   if (!_dbus_string_find (&str, 0, "H", &i))
1996     _dbus_assert_not_reached ("didn't find 'H'");
1997   _dbus_assert (i == 0);
1998
1999   if (!_dbus_string_find (&str, 0, "", &i))
2000     _dbus_assert_not_reached ("didn't find ''");
2001   _dbus_assert (i == 0);
2002   
2003   if (_dbus_string_find (&str, 0, "Hello!", NULL))
2004     _dbus_assert_not_reached ("Did find 'Hello!'");
2005
2006   if (_dbus_string_find (&str, 0, "Oh, Hello", NULL))
2007     _dbus_assert_not_reached ("Did find 'Oh, Hello'");
2008   
2009   if (_dbus_string_find (&str, 0, "ill", NULL))
2010     _dbus_assert_not_reached ("Did find 'ill'");
2011
2012   if (_dbus_string_find (&str, 0, "q", NULL))
2013     _dbus_assert_not_reached ("Did find 'q'");
2014   
2015   _dbus_string_free (&str);
2016
2017   /* Base 64 */
2018   test_base64_roundtrip ("Hello this is a string\n", -1);
2019   test_base64_roundtrip ("Hello this is a string\n1", -1);
2020   test_base64_roundtrip ("Hello this is a string\n12", -1);
2021   test_base64_roundtrip ("Hello this is a string\n123", -1);
2022   test_base64_roundtrip ("Hello this is a string\n1234", -1);
2023   test_base64_roundtrip ("Hello this is a string\n12345", -1);
2024   test_base64_roundtrip ("", 0);
2025   test_base64_roundtrip ("1", 1);
2026   test_base64_roundtrip ("12", 2);
2027   test_base64_roundtrip ("123", 3);
2028   test_base64_roundtrip ("1234", 4);
2029   test_base64_roundtrip ("12345", 5);
2030   test_base64_roundtrip ("", 1);
2031   test_base64_roundtrip ("1", 2);
2032   test_base64_roundtrip ("12", 3);
2033   test_base64_roundtrip ("123", 4);
2034   test_base64_roundtrip ("1234", 5);
2035   test_base64_roundtrip ("12345", 6);
2036   {
2037     unsigned char buf[512];
2038     i = 0;
2039     while (i < _DBUS_N_ELEMENTS (buf))
2040       {
2041         buf[i] = i;
2042         ++i;
2043       }
2044     i = 0;
2045     while (i < _DBUS_N_ELEMENTS (buf))
2046       {
2047         test_base64_roundtrip (buf, i);
2048         ++i;
2049       }
2050   }
2051   
2052   return TRUE;
2053 }
2054
2055 #endif /* DBUS_BUILD_TESTS */