2002-12-26 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 static dbus_bool_t
530 append (DBusRealString *real,
531         const char     *buffer,
532         int             buffer_len)
533 {
534   if (buffer_len == 0)
535     return TRUE;
536
537   if (!_dbus_string_lengthen ((DBusString*)real, buffer_len))
538     return FALSE;
539
540   memcpy (real->str + (real->len - buffer_len),
541           buffer,
542           buffer_len);
543
544   return TRUE;
545 }
546
547 /**
548  * Appends a nul-terminated C-style string to a DBusString.
549  *
550  * @param str the DBusString
551  * @param buffer the nul-terminated characters to append
552  * @returns #FALSE if not enough memory.
553  */
554 dbus_bool_t
555 _dbus_string_append (DBusString *str,
556                      const char *buffer)
557 {
558   int buffer_len;
559   
560   DBUS_STRING_PREAMBLE (str);
561   _dbus_assert (buffer != NULL);
562   
563   buffer_len = strlen (buffer);
564
565   return append (real, buffer, buffer_len);
566 }
567
568 /**
569  * Appends block of bytes with the given length to a DBusString.
570  *
571  * @param str the DBusString
572  * @param buffer the bytes to append
573  * @param len the number of bytes to append
574  * @returns #FALSE if not enough memory.
575  */
576 dbus_bool_t
577 _dbus_string_append_len (DBusString *str,
578                          const char *buffer,
579                          int         len)
580 {
581   DBUS_STRING_PREAMBLE (str);
582   _dbus_assert (buffer != NULL);
583   _dbus_assert (len >= 0);
584
585   return append (real, buffer, len);
586 }
587
588 /**
589  * Appends a single byte to the string, returning #FALSE
590  * if not enough memory.
591  *
592  * @param str the string
593  * @param byte the byte to append
594  * @returns #TRUE on success
595  */
596 dbus_bool_t
597 _dbus_string_append_byte (DBusString    *str,
598                           unsigned char  byte)
599 {
600   DBUS_STRING_PREAMBLE (str);
601
602   if (!set_length (real, real->len + 1))
603     return FALSE;
604
605   real->str[real->len-1] = byte;
606
607   return TRUE;
608 }
609
610 /**
611  * Appends a single Unicode character, encoding the character
612  * in UTF-8 format.
613  *
614  * @param str the string
615  * @param ch the Unicode character
616  */
617 dbus_bool_t
618 _dbus_string_append_unichar (DBusString    *str,
619                              dbus_unichar_t ch)
620 {
621   int len;
622   int first;
623   int i;
624   char *out;
625   
626   DBUS_STRING_PREAMBLE (str);
627
628   /* this code is from GLib but is pretty standard I think */
629   
630   len = 0;
631   
632   if (ch < 0x80)
633     {
634       first = 0;
635       len = 1;
636     }
637   else if (ch < 0x800)
638     {
639       first = 0xc0;
640       len = 2;
641     }
642   else if (ch < 0x10000)
643     {
644       first = 0xe0;
645       len = 3;
646     }
647    else if (ch < 0x200000)
648     {
649       first = 0xf0;
650       len = 4;
651     }
652   else if (ch < 0x4000000)
653     {
654       first = 0xf8;
655       len = 5;
656     }
657   else
658     {
659       first = 0xfc;
660       len = 6;
661     }
662
663   if (!set_length (real, real->len + len))
664     return FALSE;
665
666   out = real->str + (real->len - len);
667   
668   for (i = len - 1; i > 0; --i)
669     {
670       out[i] = (ch & 0x3f) | 0x80;
671       ch >>= 6;
672     }
673   out[0] = ch | first;
674
675   return TRUE;
676 }
677
678 static void
679 delete (DBusRealString *real,
680         int             start,
681         int             len)
682 {
683   if (len == 0)
684     return;
685   
686   memmove (real->str + start, real->str + start + len, real->len - (start + len));
687   real->len -= len;
688   real->str[real->len] = '\0';
689 }
690
691 /**
692  * Deletes a segment of a DBusString with length len starting at
693  * start. (Hint: to clear an entire string, setting length to 0
694  * with _dbus_string_set_length() is easier.)
695  *
696  * @param str the DBusString
697  * @param start where to start deleting
698  * @param len the number of bytes to delete
699  */
700 void
701 _dbus_string_delete (DBusString       *str,
702                      int               start,
703                      int               len)
704 {
705   DBUS_STRING_PREAMBLE (str);
706   _dbus_assert (start >= 0);
707   _dbus_assert (len >= 0);
708   _dbus_assert ((start + len) <= real->len);
709
710   delete (real, start, len);
711 }
712
713 static dbus_bool_t
714 open_gap (int             len,
715           DBusRealString *dest,
716           int             insert_at)
717 {
718   if (len == 0)
719     return TRUE;
720
721   if (!set_length (dest, dest->len + len))
722     return FALSE;
723
724   memmove (dest->str + insert_at + len, 
725            dest->str + insert_at,
726            dest->len - len - insert_at);
727
728   return TRUE;
729 }
730
731 static dbus_bool_t
732 copy (DBusRealString *source,
733       int             start,
734       int             len,
735       DBusRealString *dest,
736       int             insert_at)
737 {
738   if (!open_gap (len, dest, insert_at))
739     return FALSE;
740     
741   memcpy (dest->str + insert_at,
742           source->str + start,
743           len);
744
745   return TRUE;
746 }
747
748 /**
749  * Checks assertions for two strings we're copying a segment between,
750  * and declares real_source/real_dest variables.
751  *
752  * @param source the source string
753  * @param start the starting offset
754  * @param dest the dest string
755  * @param insert_at where the copied segment is inserted
756  */
757 #define DBUS_STRING_COPY_PREAMBLE(source, start, dest, insert_at)       \
758   DBusRealString *real_source = (DBusRealString*) source;               \
759   DBusRealString *real_dest = (DBusRealString*) dest;                   \
760   _dbus_assert ((source) != (dest));                                    \
761   DBUS_GENERIC_STRING_PREAMBLE (real_source);                           \
762   DBUS_GENERIC_STRING_PREAMBLE (real_dest);                             \
763   _dbus_assert (!real_source->constant);                                \
764   _dbus_assert (!real_source->locked);                                  \
765   _dbus_assert (!real_dest->constant);                                  \
766   _dbus_assert (!real_dest->locked);                                    \
767   _dbus_assert ((start) >= 0);                                          \
768   _dbus_assert ((start) <= real_source->len);                           \
769   _dbus_assert ((insert_at) >= 0);                                      \
770   _dbus_assert ((insert_at) <= real_dest->len)
771
772 /**
773  * Moves the end of one string into another string. Both strings
774  * must be initialized, valid strings.
775  *
776  * @param source the source string
777  * @param start where to chop off the source string
778  * @param dest the destination string
779  * @param insert_at where to move the chopped-off part of source string
780  * @returns #FALSE if not enough memory
781  */
782 dbus_bool_t
783 _dbus_string_move (DBusString       *source,
784                    int               start,
785                    DBusString       *dest,
786                    int               insert_at)
787 {
788   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
789   
790   if (!copy (real_source, start,
791              real_source->len - start,
792              real_dest,
793              insert_at))
794     return FALSE;
795
796   delete (real_source, start,
797           real_source->len - start);
798
799   return TRUE;
800 }
801
802 /**
803  * Like _dbus_string_move(), but does not delete the section
804  * of the source string that's copied to the dest string.
805  *
806  * @param source the source string
807  * @param start where to start copying the source string
808  * @param dest the destination string
809  * @param insert_at where to place the copied part of source string
810  * @returns #FALSE if not enough memory
811  */
812 dbus_bool_t
813 _dbus_string_copy (const DBusString *source,
814                    int               start,
815                    DBusString       *dest,
816                    int               insert_at)
817 {
818   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
819
820   return copy (real_source, start,
821                real_source->len - start,
822                real_dest,
823                insert_at);
824 }
825
826 /**
827  * Like _dbus_string_move(), but can move a segment from
828  * the middle of the source string.
829  * 
830  * @param source the source string
831  * @param start first byte of source string to move
832  * @param len length of segment to move
833  * @param dest the destination string
834  * @param insert_at where to move the bytes from the source string
835  * @returns #FALSE if not enough memory
836  */
837 dbus_bool_t
838 _dbus_string_move_len (DBusString       *source,
839                        int               start,
840                        int               len,
841                        DBusString       *dest,
842                        int               insert_at)
843
844 {
845   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
846   _dbus_assert (len >= 0);
847   _dbus_assert ((start + len) <= real_source->len);
848
849   if (!copy (real_source, start, len,
850              real_dest,
851              insert_at))
852     return FALSE;
853
854   delete (real_source, start,
855           real_source->len - start);
856
857   return TRUE;
858 }
859
860 /**
861  * Like _dbus_string_copy(), but can copy a segment from the middle of
862  * the source string.
863  *
864  * @param source the source string
865  * @param start where to start copying the source string
866  * @param len length of segment to copy
867  * @param dest the destination string
868  * @param insert_at where to place the copied segment of source string
869  * @returns #FALSE if not enough memory
870  */
871 dbus_bool_t
872 _dbus_string_copy_len (const DBusString *source,
873                        int               start,
874                        int               len,
875                        DBusString       *dest,
876                        int               insert_at)
877 {
878   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
879   _dbus_assert (len >= 0);
880   _dbus_assert ((start + len) <= real_source->len);
881   
882   return copy (real_source, start, len,
883                real_dest,
884                insert_at);
885 }
886
887 /* Unicode macros from GLib */
888
889 /** computes length and mask of a unicode character
890  * @param Char the char
891  * @param Mask the mask variable to assign to
892  * @param Len the length variable to assign to
893  */
894 #define UTF8_COMPUTE(Char, Mask, Len)                                         \
895   if (Char < 128)                                                             \
896     {                                                                         \
897       Len = 1;                                                                \
898       Mask = 0x7f;                                                            \
899     }                                                                         \
900   else if ((Char & 0xe0) == 0xc0)                                             \
901     {                                                                         \
902       Len = 2;                                                                \
903       Mask = 0x1f;                                                            \
904     }                                                                         \
905   else if ((Char & 0xf0) == 0xe0)                                             \
906     {                                                                         \
907       Len = 3;                                                                \
908       Mask = 0x0f;                                                            \
909     }                                                                         \
910   else if ((Char & 0xf8) == 0xf0)                                             \
911     {                                                                         \
912       Len = 4;                                                                \
913       Mask = 0x07;                                                            \
914     }                                                                         \
915   else if ((Char & 0xfc) == 0xf8)                                             \
916     {                                                                         \
917       Len = 5;                                                                \
918       Mask = 0x03;                                                            \
919     }                                                                         \
920   else if ((Char & 0xfe) == 0xfc)                                             \
921     {                                                                         \
922       Len = 6;                                                                \
923       Mask = 0x01;                                                            \
924     }                                                                         \
925   else                                                                        \
926     Len = -1;
927
928 /**
929  * computes length of a unicode character in UTF-8
930  * @param Char the char
931  */
932 #define UTF8_LENGTH(Char)              \
933   ((Char) < 0x80 ? 1 :                 \
934    ((Char) < 0x800 ? 2 :               \
935     ((Char) < 0x10000 ? 3 :            \
936      ((Char) < 0x200000 ? 4 :          \
937       ((Char) < 0x4000000 ? 5 : 6)))))
938    
939 /**
940  * Gets a UTF-8 value.
941  *
942  * @param Result variable for extracted unicode char.
943  * @param Chars the bytes to decode
944  * @param Count counter variable
945  * @param Mask mask for this char
946  * @param Len length for this char in bytes
947  */
948 #define UTF8_GET(Result, Chars, Count, Mask, Len)                             \
949   (Result) = (Chars)[0] & (Mask);                                             \
950   for ((Count) = 1; (Count) < (Len); ++(Count))                               \
951     {                                                                         \
952       if (((Chars)[(Count)] & 0xc0) != 0x80)                                  \
953         {                                                                     \
954           (Result) = -1;                                                      \
955           break;                                                              \
956         }                                                                     \
957       (Result) <<= 6;                                                         \
958       (Result) |= ((Chars)[(Count)] & 0x3f);                                  \
959     }
960
961 /**
962  * Check whether a unicode char is in a valid range.
963  *
964  * @param Char the character
965  */
966 #define UNICODE_VALID(Char)                   \
967     ((Char) < 0x110000 &&                     \
968      ((Char) < 0xD800 || (Char) >= 0xE000) && \
969      (Char) != 0xFFFE && (Char) != 0xFFFF)   
970
971 /**
972  * Gets a unicode character from a UTF-8 string. Does no validation;
973  * you must verify that the string is valid UTF-8 in advance and must
974  * pass in the start of a character.
975  *
976  * @param str the string
977  * @param start the start of the UTF-8 character.
978  * @param ch_return location to return the character
979  * @param end_return location to return the byte index of next character
980  * @returns #TRUE on success, #FALSE otherwise.
981  */
982 void
983 _dbus_string_get_unichar (const DBusString *str,
984                           int               start,
985                           dbus_unichar_t   *ch_return,
986                           int              *end_return)
987 {
988   int i, mask, len;
989   dbus_unichar_t result;
990   unsigned char c;
991   unsigned char *p;
992   DBUS_CONST_STRING_PREAMBLE (str);
993
994   if (ch_return)
995     *ch_return = 0;
996   if (end_return)
997     *end_return = real->len;
998   
999   mask = 0;
1000   p = real->str + start;
1001   c = *p;
1002   
1003   UTF8_COMPUTE (c, mask, len);
1004   if (len == -1)
1005     return;
1006   UTF8_GET (result, p, i, mask, len);
1007
1008   if (result == (dbus_unichar_t)-1)
1009     return;
1010
1011   if (ch_return)
1012     *ch_return = result;
1013   if (end_return)
1014     *end_return = start + len;
1015 }
1016
1017 /**
1018  * Finds the given substring in the string,
1019  * returning #TRUE and filling in the byte index
1020  * where the substring was found, if it was found.
1021  * Returns #FALSE if the substring wasn't found.
1022  * Sets *start to the length of the string if the substring
1023  * is not found.
1024  *
1025  * @param str the string
1026  * @param start where to start looking
1027  * @param substr the substring
1028  * @param found return location for where it was found, or #NULL
1029  * @returns #TRUE if found
1030  */
1031 dbus_bool_t
1032 _dbus_string_find (const DBusString *str,
1033                    int               start,
1034                    const char       *substr,
1035                    int              *found)
1036 {
1037   int i;
1038   DBUS_CONST_STRING_PREAMBLE (str);
1039   _dbus_assert (substr != NULL);
1040   _dbus_assert (start <= real->len);
1041   
1042   /* we always "find" an empty string */
1043   if (*substr == '\0')
1044     {
1045       if (found)
1046         *found = 0;
1047       return TRUE;
1048     }
1049   
1050   i = start;
1051   while (i < real->len)
1052     {
1053       if (real->str[i] == substr[0])
1054         {
1055           int j = i + 1;
1056           
1057           while (j < real->len)
1058             {
1059               if (substr[j - i] == '\0')
1060                 break;
1061               else if (real->str[j] != substr[j - i])
1062                 break;
1063               
1064               ++j;
1065             }
1066
1067           if (substr[j - i] == '\0')
1068             {
1069               if (found)
1070                 *found = i;
1071               return TRUE;
1072             }
1073         }
1074       
1075       ++i;
1076     }
1077
1078   if (found)
1079     *found = real->len;
1080   
1081   return FALSE;
1082 }
1083
1084 /**
1085  * Finds a blank (space or tab) in the string. Returns #TRUE
1086  * if found, #FALSE otherwise. If a blank is not found sets
1087  * *found to the length of the string.
1088  *
1089  * @param str the string
1090  * @param start byte index to start looking
1091  * @param found place to store the location of the first blank
1092  * @returns #TRUE if a blank was found
1093  */
1094 dbus_bool_t
1095 _dbus_string_find_blank (const DBusString *str,
1096                          int               start,
1097                          int              *found)
1098 {
1099   int i;
1100   DBUS_CONST_STRING_PREAMBLE (str);
1101   _dbus_assert (start <= real->len);
1102   
1103   i = start;
1104   while (i < real->len)
1105     {
1106       if (real->str[i] == ' ' ||
1107           real->str[i] == '\t')
1108         {
1109           if (found)
1110             *found = i;
1111           return TRUE;
1112         }
1113       
1114       ++i;
1115     }
1116
1117   if (found)
1118     *found = real->len;
1119   
1120   return FALSE;
1121 }
1122
1123 /**
1124  * Skips blanks from start, storing the first non-blank in *end
1125  *
1126  * @param str the string
1127  * @param start where to start
1128  * @param end where to store the first non-blank byte index
1129  */
1130 void
1131 _dbus_string_skip_blank (const DBusString *str,
1132                          int               start,
1133                          int              *end)
1134 {
1135   int i;
1136   DBUS_CONST_STRING_PREAMBLE (str);
1137   _dbus_assert (start <= real->len);
1138   
1139   i = start;
1140   while (i < real->len)
1141     {
1142       if (!(real->str[i] == ' ' ||
1143             real->str[i] == '\t'))
1144         break;
1145       
1146       ++i;
1147     }
1148
1149   _dbus_assert (i == real->len || !(real->str[i] == ' ' ||
1150                                     real->str[i] == '\t'));
1151   
1152   if (end)
1153     *end = i;
1154 }
1155
1156 /**
1157  * Tests two DBusString for equality.
1158  *
1159  * @param a first string
1160  * @param b second string
1161  * @returns #TRUE if equal
1162  */
1163 dbus_bool_t
1164 _dbus_string_equal (const DBusString *a,
1165                     const DBusString *b)
1166 {
1167   const unsigned char *ap;
1168   const unsigned char *bp;
1169   const unsigned char *a_end;
1170   const DBusRealString *real_a = (const DBusRealString*) a;
1171   const DBusRealString *real_b = (const DBusRealString*) b;
1172   DBUS_GENERIC_STRING_PREAMBLE (real_a);
1173   DBUS_GENERIC_STRING_PREAMBLE (real_b);
1174
1175   if (real_a->len != real_b->len)
1176     return FALSE;
1177
1178   ap = real_a->str;
1179   bp = real_b->str;
1180   a_end = real_a->str + real_a->len;
1181   while (ap != a_end)
1182     {
1183       if (*ap != *bp)
1184         return FALSE;
1185       
1186       ++ap;
1187       ++bp;
1188     }
1189
1190   return TRUE;
1191 }
1192
1193 /**
1194  * Checks whether a string is equal to a C string.
1195  *
1196  * @param a the string
1197  * @param c_str the C string
1198  * @returns #TRUE if equal
1199  */
1200 dbus_bool_t
1201 _dbus_string_equal_c_str (const DBusString *a,
1202                           const char       *c_str)
1203 {
1204   const unsigned char *ap;
1205   const unsigned char *bp;
1206   const unsigned char *a_end;
1207   const DBusRealString *real_a = (const DBusRealString*) a;
1208   DBUS_GENERIC_STRING_PREAMBLE (real_a);
1209
1210   ap = real_a->str;
1211   bp = (const unsigned char*) c_str;
1212   a_end = real_a->str + real_a->len;
1213   while (ap != a_end && *bp)
1214     {
1215       if (*ap != *bp)
1216         return FALSE;
1217       
1218       ++ap;
1219       ++bp;
1220     }
1221
1222   if (*ap && *bp == '\0')
1223     return FALSE;
1224   else if (ap == a_end && *bp)
1225     return FALSE;
1226   
1227   return TRUE;
1228 }
1229
1230 static const signed char base64_table[] = {
1231   /* 0 */ 'A',
1232   /* 1 */ 'B',
1233   /* 2 */ 'C',
1234   /* 3 */ 'D',
1235   /* 4 */ 'E',
1236   /* 5 */ 'F',
1237   /* 6 */ 'G',
1238   /* 7 */ 'H',
1239   /* 8 */ 'I',
1240   /* 9 */ 'J',
1241   /* 10 */ 'K',
1242   /* 11 */ 'L',
1243   /* 12 */ 'M',
1244   /* 13 */ 'N',
1245   /* 14 */ 'O',
1246   /* 15 */ 'P',
1247   /* 16 */ 'Q',
1248   /* 17 */ 'R',
1249   /* 18 */ 'S',
1250   /* 19 */ 'T',
1251   /* 20 */ 'U',
1252   /* 21 */ 'V',
1253   /* 22 */ 'W',
1254   /* 23 */ 'X',
1255   /* 24 */ 'Y',
1256   /* 25 */ 'Z',
1257   /* 26 */ 'a',
1258   /* 27 */ 'b',
1259   /* 28 */ 'c',
1260   /* 29 */ 'd',
1261   /* 30 */ 'e',
1262   /* 31 */ 'f',
1263   /* 32 */ 'g',
1264   /* 33 */ 'h',
1265   /* 34 */ 'i',
1266   /* 35 */ 'j',
1267   /* 36 */ 'k',
1268   /* 37 */ 'l',
1269   /* 38 */ 'm',
1270   /* 39 */ 'n',
1271   /* 40 */ 'o',
1272   /* 41 */ 'p',
1273   /* 42 */ 'q',
1274   /* 43 */ 'r',
1275   /* 44 */ 's',
1276   /* 45 */ 't',
1277   /* 46 */ 'u',
1278   /* 47 */ 'v',
1279   /* 48 */ 'w',
1280   /* 49 */ 'x',
1281   /* 50 */ 'y',
1282   /* 51 */ 'z',
1283   /* 52 */ '0',
1284   /* 53 */ '1',
1285   /* 54 */ '2',
1286   /* 55 */ '3',
1287   /* 56 */ '4',
1288   /* 57 */ '5',
1289   /* 58 */ '6',
1290   /* 59 */ '7',
1291   /* 60 */ '8',
1292   /* 61 */ '9',
1293   /* 62 */ '+',
1294   /* 63 */ '/'
1295 };
1296
1297 /** The minimum char that's a valid char in Base64-encoded text */
1298 #define UNBASE64_MIN_CHAR (43)
1299 /** The maximum char that's a valid char in Base64-encoded text */
1300 #define UNBASE64_MAX_CHAR (122)
1301 /** Must subtract this from a char's integer value before offsetting
1302  * into unbase64_table
1303  */
1304 #define UNBASE64_TABLE_OFFSET UNBASE64_MIN_CHAR
1305 static const signed char unbase64_table[] = {
1306   /* 43 + */ 62,
1307   /* 44 , */ -1,
1308   /* 45 - */ -1,
1309   /* 46 . */ -1,
1310   /* 47 / */ 63,
1311   /* 48 0 */ 52,
1312   /* 49 1 */ 53,
1313   /* 50 2 */ 54,
1314   /* 51 3 */ 55,
1315   /* 52 4 */ 56,
1316   /* 53 5 */ 57,
1317   /* 54 6 */ 58,
1318   /* 55 7 */ 59,
1319   /* 56 8 */ 60,
1320   /* 57 9 */ 61,
1321   /* 58 : */ -1,
1322   /* 59 ; */ -1,
1323   /* 60 < */ -1,
1324   /* 61 = */ -1,
1325   /* 62 > */ -1,
1326   /* 63 ? */ -1,
1327   /* 64 @ */ -1,
1328   /* 65 A */ 0,
1329   /* 66 B */ 1,
1330   /* 67 C */ 2,
1331   /* 68 D */ 3,
1332   /* 69 E */ 4,
1333   /* 70 F */ 5,
1334   /* 71 G */ 6,
1335   /* 72 H */ 7,
1336   /* 73 I */ 8,
1337   /* 74 J */ 9,
1338   /* 75 K */ 10,
1339   /* 76 L */ 11,
1340   /* 77 M */ 12,
1341   /* 78 N */ 13,
1342   /* 79 O */ 14,
1343   /* 80 P */ 15,
1344   /* 81 Q */ 16,
1345   /* 82 R */ 17,
1346   /* 83 S */ 18,
1347   /* 84 T */ 19,
1348   /* 85 U */ 20,
1349   /* 86 V */ 21,
1350   /* 87 W */ 22,
1351   /* 88 X */ 23,
1352   /* 89 Y */ 24,
1353   /* 90 Z */ 25,
1354   /* 91 [ */ -1,
1355   /* 92 \ */ -1,
1356   /* 93 ] */ -1,
1357   /* 94 ^ */ -1,
1358   /* 95 _ */ -1,
1359   /* 96 ` */ -1,
1360   /* 97 a */ 26,
1361   /* 98 b */ 27,
1362   /* 99 c */ 28,
1363   /* 100 d */ 29,
1364   /* 101 e */ 30,
1365   /* 102 f */ 31,
1366   /* 103 g */ 32,
1367   /* 104 h */ 33,
1368   /* 105 i */ 34,
1369   /* 106 j */ 35,
1370   /* 107 k */ 36,
1371   /* 108 l */ 37,
1372   /* 109 m */ 38,
1373   /* 110 n */ 39,
1374   /* 111 o */ 40,
1375   /* 112 p */ 41,
1376   /* 113 q */ 42,
1377   /* 114 r */ 43,
1378   /* 115 s */ 44,
1379   /* 116 t */ 45,
1380   /* 117 u */ 46,
1381   /* 118 v */ 47,
1382   /* 119 w */ 48,
1383   /* 120 x */ 49,
1384   /* 121 y */ 50,
1385   /* 122 z */ 51
1386 };
1387
1388 /**
1389  * Encodes a string using Base64, as documented in RFC 2045.
1390  *
1391  * @param source the string to encode
1392  * @param start byte index to start encoding
1393  * @param dest string where encoded data should be placed
1394  * @param insert_at where to place encoded data
1395  * @returns #TRUE if encoding was successful, #FALSE if no memory etc.
1396  */
1397 dbus_bool_t
1398 _dbus_string_base64_encode (const DBusString *source,
1399                             int               start,
1400                             DBusString       *dest,
1401                             int               insert_at)
1402 {
1403   int source_len;
1404   int dest_len;
1405   const unsigned char *s;
1406   unsigned char *d;
1407   const unsigned char *triplet_end;
1408   const unsigned char *final_end;
1409   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);  
1410   
1411   /* For each 24 bits (3 bytes) of input, we have 4 chars of
1412    * output.
1413    */
1414   source_len = real_source->len - start;
1415   dest_len = (source_len / 3) * 4;
1416   if (source_len % 3 != 0)
1417     dest_len += 4;
1418
1419   if (source_len == 0)
1420     return TRUE;
1421   
1422   if (!open_gap (dest_len, real_dest, insert_at))
1423     return FALSE;
1424
1425   d = real_dest->str + insert_at;
1426   s = real_source->str + start;
1427   final_end = real_source->str + (start + source_len);
1428   triplet_end = final_end - (source_len % 3);
1429   _dbus_assert (triplet_end <= final_end);
1430   _dbus_assert ((final_end - triplet_end) < 3);
1431
1432 #define ENCODE_64(v) (base64_table[ (unsigned char) (v) ])
1433 #define SIX_BITS_MASK (0x3f)
1434   _dbus_assert (SIX_BITS_MASK < _DBUS_N_ELEMENTS (base64_table));
1435   
1436   while (s != triplet_end)
1437     {
1438       unsigned int triplet;
1439
1440       triplet = s[0] | (s[1] << 8) | (s[2] << 16);
1441
1442       /* Encode each 6 bits */
1443       
1444       *d++ = ENCODE_64 (triplet >> 18);
1445       *d++ = ENCODE_64 ((triplet >> 12) & SIX_BITS_MASK);
1446       *d++ = ENCODE_64 ((triplet >> 6) & SIX_BITS_MASK);
1447       *d++ = ENCODE_64 (triplet & SIX_BITS_MASK);
1448       
1449       s += 3;
1450     }
1451
1452   switch (final_end - triplet_end)
1453     {
1454     case 2:
1455       {
1456         unsigned int doublet;
1457         
1458         doublet = s[0] | (s[1] << 8);
1459         
1460         *d++ = ENCODE_64 (doublet >> 12);
1461         *d++ = ENCODE_64 ((doublet >> 6) & SIX_BITS_MASK);
1462         *d++ = ENCODE_64 (doublet & SIX_BITS_MASK);
1463         *d++ = '=';
1464       }
1465       break;
1466     case 1:
1467       {
1468         unsigned int singlet;
1469         
1470         singlet = s[0];
1471         
1472         *d++ = ENCODE_64 ((singlet >> 6) & SIX_BITS_MASK);
1473         *d++ = ENCODE_64 (singlet & SIX_BITS_MASK);
1474         *d++ = '=';
1475         *d++ = '=';
1476       }
1477       break;
1478     case 0:
1479       break;
1480     }
1481
1482   _dbus_assert (d == (real_dest->str + (insert_at + dest_len)));
1483
1484   return TRUE;
1485 }
1486
1487
1488 /**
1489  * Decodes a string from Base64, as documented in RFC 2045.
1490  *
1491  * @param source the string to decode
1492  * @param start byte index to start decode
1493  * @param dest string where decoded data should be placed
1494  * @param insert_at where to place decoded data
1495  * @returns #TRUE if decoding was successful, #FALSE if no memory etc.
1496  */
1497 dbus_bool_t
1498 _dbus_string_base64_decode (const DBusString *source,
1499                             int               start,
1500                             DBusString       *dest,
1501                             int               insert_at)
1502 {
1503   int source_len;
1504   const char *s;
1505   const char *end;
1506   DBusString result;
1507   unsigned int triplet = 0;
1508   int sextet_count;
1509   int pad_count;
1510   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
1511   
1512   source_len = real_source->len - start;
1513   s = real_source->str + start;
1514   end = real_source->str + source_len;
1515
1516   if (source_len == 0)
1517     return TRUE;
1518
1519   if (!_dbus_string_init (&result, _DBUS_INT_MAX))
1520     return FALSE;
1521
1522   pad_count = 0;
1523   sextet_count = 0;
1524   while (s != end)
1525     {
1526       /* The idea is to just skip anything that isn't
1527        * a base64 char - it's allowed to have whitespace,
1528        * newlines, etc. in here. We also ignore trailing
1529        * base64 chars, though that's suspicious.
1530        */
1531       
1532       if (*s >= UNBASE64_MIN_CHAR &&
1533           *s <= UNBASE64_MAX_CHAR)
1534         {
1535           if (*s == '=')
1536             {
1537               /* '=' is padding, doesn't represent additional data
1538                * but does increment our count.
1539                */
1540               pad_count += 1;
1541               sextet_count += 1;
1542             }
1543           else
1544             {
1545               int val;
1546
1547               val = unbase64_table[(*s) - UNBASE64_TABLE_OFFSET];
1548
1549               if (val >= 0)
1550                 {
1551                   triplet <<= 6;
1552                   triplet |= (unsigned int) val;
1553                   sextet_count += 1;
1554                 }
1555             }
1556
1557           if (sextet_count == 4)
1558             {
1559               /* no pad = 3 bytes, 1 pad = 2 bytes, 2 pad = 1 byte */
1560               
1561               _dbus_string_append_byte (&result,
1562                                         triplet & 0xff);
1563               
1564               if (pad_count < 2)
1565                 _dbus_string_append_byte (&result,
1566                                           (triplet >> 8) & 0xff);
1567
1568               if (pad_count < 1)
1569                 _dbus_string_append_byte (&result,
1570                                           triplet >> 16);
1571
1572               sextet_count = 0;
1573               pad_count = 0;
1574               triplet = 0;
1575             }
1576         }
1577       
1578       ++s;
1579     }
1580
1581   if (!_dbus_string_move (&result, 0, dest, insert_at))
1582     {
1583       _dbus_string_free (&result);
1584       return FALSE;
1585     }
1586
1587   _dbus_string_free (&result);
1588
1589   return TRUE;
1590 }
1591
1592 /**
1593  * Checks that the given range of the string
1594  * is valid ASCII. If the given range is not contained
1595  * in the string, returns #FALSE.
1596  *
1597  * @param str the string
1598  * @param start first byte index to check
1599  * @param len number of bytes to check
1600  * @returns #TRUE if the byte range exists and is all valid ASCII
1601  */
1602 dbus_bool_t
1603 _dbus_string_validate_ascii (const DBusString *str,
1604                              int               start,
1605                              int               len)
1606 {
1607   const unsigned char *s;
1608   const unsigned char *end;
1609   DBUS_CONST_STRING_PREAMBLE (str);
1610   _dbus_assert (start >= 0);
1611   _dbus_assert (len >= 0);
1612   
1613   if ((start + len) > real->len)
1614     return FALSE;
1615   
1616   s = real->str + start;
1617   end = s + len;
1618   while (s != end)
1619     {
1620       if (*s == '\0' ||
1621           ((*s & ~0x7f) != 0))
1622         return FALSE;
1623         
1624       ++s;
1625     }
1626   
1627   return TRUE;
1628 }
1629
1630 /** @} */
1631
1632 #ifdef DBUS_BUILD_TESTS
1633 #include "dbus-test.h"
1634 #include <stdio.h>
1635
1636 static void
1637 test_max_len (DBusString *str,
1638               int         max_len)
1639 {
1640   if (max_len > 0)
1641     {
1642       if (!_dbus_string_set_length (str, max_len - 1))
1643         _dbus_assert_not_reached ("setting len to one less than max should have worked");
1644     }
1645
1646   if (!_dbus_string_set_length (str, max_len))
1647     _dbus_assert_not_reached ("setting len to max len should have worked");
1648
1649   if (_dbus_string_set_length (str, max_len + 1))
1650     _dbus_assert_not_reached ("setting len to one more than max len should not have worked");
1651
1652   if (!_dbus_string_set_length (str, 0))
1653     _dbus_assert_not_reached ("setting len to zero should have worked");
1654 }
1655
1656 static void
1657 test_base64_roundtrip (const unsigned char *data,
1658                        int                  len)
1659 {
1660   DBusString orig;
1661   DBusString encoded;
1662   DBusString decoded;
1663
1664   if (len < 0)
1665     len = strlen (data);
1666   
1667   if (!_dbus_string_init (&orig, _DBUS_INT_MAX))
1668     _dbus_assert_not_reached ("could not init string");
1669
1670   if (!_dbus_string_init (&encoded, _DBUS_INT_MAX))
1671     _dbus_assert_not_reached ("could not init string");
1672   
1673   if (!_dbus_string_init (&decoded, _DBUS_INT_MAX))
1674     _dbus_assert_not_reached ("could not init string");
1675
1676   if (!_dbus_string_append_len (&orig, data, len))
1677     _dbus_assert_not_reached ("couldn't append orig data");
1678
1679   if (!_dbus_string_base64_encode (&orig, 0, &encoded, 0))
1680     _dbus_assert_not_reached ("could not encode");
1681
1682   if (!_dbus_string_base64_decode (&encoded, 0, &decoded, 0))
1683     _dbus_assert_not_reached ("could not decode");
1684
1685   if (!_dbus_string_equal (&orig, &decoded))
1686     {
1687       const char *s;
1688       
1689       printf ("Original string %d bytes encoded %d bytes decoded %d bytes\n",
1690               _dbus_string_get_length (&orig),
1691               _dbus_string_get_length (&encoded),
1692               _dbus_string_get_length (&decoded));
1693       printf ("Original: %s\n", data);
1694       _dbus_string_get_const_data (&decoded, &s);
1695       printf ("Decoded: %s\n", s);
1696       _dbus_assert_not_reached ("original string not the same as string decoded from base64");
1697     }
1698   
1699   _dbus_string_free (&orig);
1700   _dbus_string_free (&encoded);
1701   _dbus_string_free (&decoded);  
1702 }
1703
1704 /**
1705  * @ingroup DBusStringInternals
1706  * Unit test for DBusString.
1707  *
1708  * @todo Need to write tests for _dbus_string_copy() and
1709  * _dbus_string_move() moving to/from each of start/middle/end of a
1710  * string.
1711  * 
1712  * @returns #TRUE on success.
1713  */
1714 dbus_bool_t
1715 _dbus_string_test (void)
1716 {
1717   DBusString str;
1718   DBusString other;
1719   int i, end;
1720   long v;
1721   double d;
1722   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 };
1723   char *s;
1724   dbus_unichar_t ch;
1725   
1726   i = 0;
1727   while (i < _DBUS_N_ELEMENTS (lens))
1728     {
1729       if (!_dbus_string_init (&str, lens[i]))
1730         _dbus_assert_not_reached ("failed to init string");
1731       
1732       test_max_len (&str, lens[i]);
1733       _dbus_string_free (&str);
1734
1735       ++i;
1736     }
1737
1738   /* Test shortening and setting length */
1739   i = 0;
1740   while (i < _DBUS_N_ELEMENTS (lens))
1741     {
1742       int j;
1743       
1744       if (!_dbus_string_init (&str, lens[i]))
1745         _dbus_assert_not_reached ("failed to init string");
1746       
1747       if (!_dbus_string_set_length (&str, lens[i]))
1748         _dbus_assert_not_reached ("failed to set string length");
1749
1750       j = lens[i];
1751       while (j > 0)
1752         {
1753           _dbus_assert (_dbus_string_get_length (&str) == j);
1754           if (j > 0)
1755             {
1756               _dbus_string_shorten (&str, 1);
1757               _dbus_assert (_dbus_string_get_length (&str) == (j - 1));
1758             }
1759           --j;
1760         }
1761       
1762       _dbus_string_free (&str);
1763
1764       ++i;
1765     }
1766
1767   /* Test appending data */
1768   if (!_dbus_string_init (&str, _DBUS_INT_MAX))
1769     _dbus_assert_not_reached ("failed to init string");
1770
1771   i = 0;
1772   while (i < 10)
1773     {
1774       if (!_dbus_string_append (&str, "a"))
1775         _dbus_assert_not_reached ("failed to append string to string\n");
1776
1777       _dbus_assert (_dbus_string_get_length (&str) == i * 2 + 1);
1778
1779       if (!_dbus_string_append_byte (&str, 'b'))
1780         _dbus_assert_not_reached ("failed to append byte to string\n");
1781
1782       _dbus_assert (_dbus_string_get_length (&str) == i * 2 + 2);
1783                     
1784       ++i;
1785     }
1786
1787   _dbus_string_free (&str);
1788
1789   /* Check steal_data */
1790   
1791   if (!_dbus_string_init (&str, _DBUS_INT_MAX))
1792     _dbus_assert_not_reached ("failed to init string");
1793
1794   if (!_dbus_string_append (&str, "Hello World"))
1795     _dbus_assert_not_reached ("could not append to string");
1796
1797   i = _dbus_string_get_length (&str);
1798   
1799   if (!_dbus_string_steal_data (&str, &s))
1800     _dbus_assert_not_reached ("failed to steal data");
1801
1802   _dbus_assert (_dbus_string_get_length (&str) == 0);
1803   _dbus_assert (((int)strlen (s)) == i);
1804
1805   dbus_free (s);
1806
1807   /* Check move */
1808   
1809   if (!_dbus_string_append (&str, "Hello World"))
1810     _dbus_assert_not_reached ("could not append to string");
1811
1812   i = _dbus_string_get_length (&str);
1813
1814   if (!_dbus_string_init (&other, _DBUS_INT_MAX))
1815     _dbus_assert_not_reached ("could not init string");
1816   
1817   if (!_dbus_string_move (&str, 0, &other, 0))
1818     _dbus_assert_not_reached ("could not move");
1819
1820   _dbus_assert (_dbus_string_get_length (&str) == 0);
1821   _dbus_assert (_dbus_string_get_length (&other) == i);
1822
1823   if (!_dbus_string_append (&str, "Hello World"))
1824     _dbus_assert_not_reached ("could not append to string");
1825   
1826   if (!_dbus_string_move (&str, 0, &other, _dbus_string_get_length (&other)))
1827     _dbus_assert_not_reached ("could not move");
1828
1829   _dbus_assert (_dbus_string_get_length (&str) == 0);
1830   _dbus_assert (_dbus_string_get_length (&other) == i * 2);
1831
1832     if (!_dbus_string_append (&str, "Hello World"))
1833     _dbus_assert_not_reached ("could not append to string");
1834   
1835   if (!_dbus_string_move (&str, 0, &other, _dbus_string_get_length (&other) / 2))
1836     _dbus_assert_not_reached ("could not move");
1837
1838   _dbus_assert (_dbus_string_get_length (&str) == 0);
1839   _dbus_assert (_dbus_string_get_length (&other) == i * 3);
1840   
1841   _dbus_string_free (&other);
1842
1843   /* Check copy */
1844   
1845   if (!_dbus_string_append (&str, "Hello World"))
1846     _dbus_assert_not_reached ("could not append to string");
1847
1848   i = _dbus_string_get_length (&str);
1849   
1850   if (!_dbus_string_init (&other, _DBUS_INT_MAX))
1851     _dbus_assert_not_reached ("could not init string");
1852   
1853   if (!_dbus_string_copy (&str, 0, &other, 0))
1854     _dbus_assert_not_reached ("could not copy");
1855
1856   _dbus_assert (_dbus_string_get_length (&str) == i);
1857   _dbus_assert (_dbus_string_get_length (&other) == i);
1858
1859   if (!_dbus_string_copy (&str, 0, &other, _dbus_string_get_length (&other)))
1860     _dbus_assert_not_reached ("could not copy");
1861
1862   _dbus_assert (_dbus_string_get_length (&str) == i);
1863   _dbus_assert (_dbus_string_get_length (&other) == i * 2);
1864   _dbus_assert (_dbus_string_equal_c_str (&other,
1865                                           "Hello WorldHello World"));
1866
1867   if (!_dbus_string_copy (&str, 0, &other, _dbus_string_get_length (&other) / 2))
1868     _dbus_assert_not_reached ("could not copy");
1869
1870   _dbus_assert (_dbus_string_get_length (&str) == i);
1871   _dbus_assert (_dbus_string_get_length (&other) == i * 3);
1872   _dbus_assert (_dbus_string_equal_c_str (&other,
1873                                           "Hello WorldHello WorldHello World"));
1874   
1875   _dbus_string_free (&str);
1876   _dbus_string_free (&other);
1877
1878   /* Check append/get unichar */
1879   
1880   if (!_dbus_string_init (&str, _DBUS_INT_MAX))
1881     _dbus_assert_not_reached ("failed to init string");
1882
1883   ch = 0;
1884   if (!_dbus_string_append_unichar (&str, 0xfffc))
1885     _dbus_assert_not_reached ("failed to append unichar");
1886
1887   _dbus_string_get_unichar (&str, 0, &ch, &i);
1888
1889   _dbus_assert (ch == 0xfffc);
1890   _dbus_assert (i == _dbus_string_get_length (&str));
1891
1892   _dbus_string_free (&str);
1893   
1894   /* Check append/parse int/double */
1895   
1896   if (!_dbus_string_init (&str, _DBUS_INT_MAX))
1897     _dbus_assert_not_reached ("failed to init string");
1898
1899   if (!_dbus_string_append_int (&str, 27))
1900     _dbus_assert_not_reached ("failed to append int");
1901
1902   i = _dbus_string_get_length (&str);
1903
1904   if (!_dbus_string_parse_int (&str, 0, &v, &end))
1905     _dbus_assert_not_reached ("failed to parse int");
1906
1907   _dbus_assert (v == 27);
1908   _dbus_assert (end == i);
1909
1910   _dbus_string_free (&str);
1911   
1912   if (!_dbus_string_init (&str, _DBUS_INT_MAX))
1913     _dbus_assert_not_reached ("failed to init string");
1914   
1915   if (!_dbus_string_append_double (&str, 50.3))
1916     _dbus_assert_not_reached ("failed to append float");
1917
1918   i = _dbus_string_get_length (&str);
1919
1920   if (!_dbus_string_parse_double (&str, 0, &d, &end))
1921     _dbus_assert_not_reached ("failed to parse float");
1922
1923   _dbus_assert (d > (50.3 - 1e-6) && d < (50.3 + 1e-6));
1924   _dbus_assert (end == i);
1925
1926   _dbus_string_free (&str);
1927
1928   /* Test find */
1929   if (!_dbus_string_init (&str, _DBUS_INT_MAX))
1930     _dbus_assert_not_reached ("failed to init string");
1931
1932   if (!_dbus_string_append (&str, "Hello"))
1933     _dbus_assert_not_reached ("couldn't append to string");
1934   
1935   if (!_dbus_string_find (&str, 0, "He", &i))
1936     _dbus_assert_not_reached ("didn't find 'He'");
1937   _dbus_assert (i == 0);
1938
1939   if (!_dbus_string_find (&str, 0, "ello", &i))
1940     _dbus_assert_not_reached ("didn't find 'ello'");
1941   _dbus_assert (i == 1);
1942
1943   if (!_dbus_string_find (&str, 0, "lo", &i))
1944     _dbus_assert_not_reached ("didn't find 'lo'");
1945   _dbus_assert (i == 3);
1946
1947   if (!_dbus_string_find (&str, 2, "lo", &i))
1948     _dbus_assert_not_reached ("didn't find 'lo'");
1949   _dbus_assert (i == 3);
1950
1951   if (_dbus_string_find (&str, 4, "lo", &i))
1952     _dbus_assert_not_reached ("did find 'lo'");
1953   
1954   if (!_dbus_string_find (&str, 0, "l", &i))
1955     _dbus_assert_not_reached ("didn't find 'l'");
1956   _dbus_assert (i == 2);
1957
1958   if (!_dbus_string_find (&str, 0, "H", &i))
1959     _dbus_assert_not_reached ("didn't find 'H'");
1960   _dbus_assert (i == 0);
1961
1962   if (!_dbus_string_find (&str, 0, "", &i))
1963     _dbus_assert_not_reached ("didn't find ''");
1964   _dbus_assert (i == 0);
1965   
1966   if (_dbus_string_find (&str, 0, "Hello!", NULL))
1967     _dbus_assert_not_reached ("Did find 'Hello!'");
1968
1969   if (_dbus_string_find (&str, 0, "Oh, Hello", NULL))
1970     _dbus_assert_not_reached ("Did find 'Oh, Hello'");
1971   
1972   if (_dbus_string_find (&str, 0, "ill", NULL))
1973     _dbus_assert_not_reached ("Did find 'ill'");
1974
1975   if (_dbus_string_find (&str, 0, "q", NULL))
1976     _dbus_assert_not_reached ("Did find 'q'");
1977   
1978   _dbus_string_free (&str);
1979
1980   /* Base 64 */
1981   test_base64_roundtrip ("Hello this is a string\n", -1);
1982   test_base64_roundtrip ("Hello this is a string\n1", -1);
1983   test_base64_roundtrip ("Hello this is a string\n12", -1);
1984   test_base64_roundtrip ("Hello this is a string\n123", -1);
1985   test_base64_roundtrip ("Hello this is a string\n1234", -1);
1986   test_base64_roundtrip ("Hello this is a string\n12345", -1);
1987   test_base64_roundtrip ("", 0);
1988   test_base64_roundtrip ("1", 1);
1989   test_base64_roundtrip ("12", 2);
1990   test_base64_roundtrip ("123", 3);
1991   test_base64_roundtrip ("1234", 4);
1992   test_base64_roundtrip ("12345", 5);
1993   test_base64_roundtrip ("", 1);
1994   test_base64_roundtrip ("1", 2);
1995   test_base64_roundtrip ("12", 3);
1996   test_base64_roundtrip ("123", 4);
1997   test_base64_roundtrip ("1234", 5);
1998   test_base64_roundtrip ("12345", 6);
1999   {
2000     unsigned char buf[512];
2001     i = 0;
2002     while (i < _DBUS_N_ELEMENTS (buf))
2003       {
2004         buf[i] = i;
2005         ++i;
2006       }
2007     i = 0;
2008     while (i < _DBUS_N_ELEMENTS (buf))
2009       {
2010         test_base64_roundtrip (buf, i);
2011         ++i;
2012       }
2013   }
2014   
2015   return TRUE;
2016 }
2017
2018 #endif /* DBUS_BUILD_TESTS */