2002-12-12 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 copy (DBusRealString *source,
715       int             start,
716       int             len,
717       DBusRealString *dest,
718       int             insert_at)
719 {
720   if (len == 0)
721     return TRUE;
722
723   if (!set_length (dest, dest->len + len))
724     return FALSE;
725
726   memmove (dest->str + insert_at + len, 
727            dest->str + insert_at,
728            dest->len - len);
729
730   memcpy (dest->str + insert_at,
731           source->str + start,
732           len);
733
734   return TRUE;
735 }
736
737 /**
738  * Checks assertions for two strings we're copying a segment between,
739  * and declares real_source/real_dest variables.
740  *
741  * @param source the source string
742  * @param start the starting offset
743  * @param dest the dest string
744  * @param insert_at where the copied segment is inserted
745  */
746 #define DBUS_STRING_COPY_PREAMBLE(source, start, dest, insert_at)       \
747   DBusRealString *real_source = (DBusRealString*) source;               \
748   DBusRealString *real_dest = (DBusRealString*) dest;                   \
749   _dbus_assert ((source) != (dest));                                    \
750   DBUS_GENERIC_STRING_PREAMBLE (real_source);                           \
751   DBUS_GENERIC_STRING_PREAMBLE (real_dest);                             \
752   _dbus_assert (!real_source->constant);                                \
753   _dbus_assert (!real_source->locked);                                  \
754   _dbus_assert (!real_dest->constant);                                  \
755   _dbus_assert (!real_dest->locked);                                    \
756   _dbus_assert ((start) >= 0);                                          \
757   _dbus_assert ((start) <= real_source->len);                           \
758   _dbus_assert ((insert_at) >= 0);                                      \
759   _dbus_assert ((insert_at) <= real_dest->len)
760
761 /**
762  * Moves the end of one string into another string. Both strings
763  * must be initialized, valid strings.
764  *
765  * @param source the source string
766  * @param start where to chop off the source string
767  * @param dest the destination string
768  * @param insert_at where to move the chopped-off part of source string
769  * @returns #FALSE if not enough memory
770  */
771 dbus_bool_t
772 _dbus_string_move (DBusString       *source,
773                    int               start,
774                    DBusString       *dest,
775                    int               insert_at)
776 {
777   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
778   
779   if (!copy (real_source, start,
780              real_source->len - start,
781              real_dest,
782              insert_at))
783     return FALSE;
784
785   delete (real_source, start,
786           real_source->len - start);
787
788   return TRUE;
789 }
790
791 /**
792  * Like _dbus_string_move(), but does not delete the section
793  * of the source string that's copied to the dest string.
794  *
795  * @param source the source string
796  * @param start where to start copying the source string
797  * @param dest the destination string
798  * @param insert_at where to place the copied part of source string
799  * @returns #FALSE if not enough memory
800  */
801 dbus_bool_t
802 _dbus_string_copy (const DBusString *source,
803                    int               start,
804                    DBusString       *dest,
805                    int               insert_at)
806 {
807   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
808
809   return copy (real_source, start,
810                real_source->len - start,
811                real_dest,
812                insert_at);
813 }
814
815 /**
816  * Like _dbus_string_move(), but can move a segment from
817  * the middle of the source string.
818  * 
819  * @param source the source string
820  * @param start first byte of source string to move
821  * @param len length of segment to move
822  * @param dest the destination string
823  * @param insert_at where to move the bytes from the source string
824  * @returns #FALSE if not enough memory
825  */
826 dbus_bool_t
827 _dbus_string_move_len (DBusString       *source,
828                        int               start,
829                        int               len,
830                        DBusString       *dest,
831                        int               insert_at)
832
833 {
834   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
835   _dbus_assert (len >= 0);
836   _dbus_assert ((start + len) <= real_source->len);
837
838   if (!copy (real_source, start, len,
839              real_dest,
840              insert_at))
841     return FALSE;
842
843   delete (real_source, start,
844           real_source->len - start);
845
846   return TRUE;
847 }
848
849 /**
850  * Like _dbus_string_copy(), but can copy a segment from the middle of
851  * the source string.
852  *
853  * @param source the source string
854  * @param start where to start copying the source string
855  * @param len length of segment to copy
856  * @param dest the destination string
857  * @param insert_at where to place the copied segment of source string
858  * @returns #FALSE if not enough memory
859  */
860 dbus_bool_t
861 _dbus_string_copy_len (const DBusString *source,
862                        int               start,
863                        int               len,
864                        DBusString       *dest,
865                        int               insert_at)
866 {
867   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
868   _dbus_assert (len >= 0);
869   _dbus_assert ((start + len) <= real_source->len);
870   
871   return copy (real_source, start, len,
872                real_dest,
873                insert_at);
874 }
875
876 /* Unicode macros from GLib */
877
878 /** computes length and mask of a unicode character
879  * @param Char the char
880  * @param Mask the mask variable to assign to
881  * @param Len the length variable to assign to
882  */
883 #define UTF8_COMPUTE(Char, Mask, Len)                                         \
884   if (Char < 128)                                                             \
885     {                                                                         \
886       Len = 1;                                                                \
887       Mask = 0x7f;                                                            \
888     }                                                                         \
889   else if ((Char & 0xe0) == 0xc0)                                             \
890     {                                                                         \
891       Len = 2;                                                                \
892       Mask = 0x1f;                                                            \
893     }                                                                         \
894   else if ((Char & 0xf0) == 0xe0)                                             \
895     {                                                                         \
896       Len = 3;                                                                \
897       Mask = 0x0f;                                                            \
898     }                                                                         \
899   else if ((Char & 0xf8) == 0xf0)                                             \
900     {                                                                         \
901       Len = 4;                                                                \
902       Mask = 0x07;                                                            \
903     }                                                                         \
904   else if ((Char & 0xfc) == 0xf8)                                             \
905     {                                                                         \
906       Len = 5;                                                                \
907       Mask = 0x03;                                                            \
908     }                                                                         \
909   else if ((Char & 0xfe) == 0xfc)                                             \
910     {                                                                         \
911       Len = 6;                                                                \
912       Mask = 0x01;                                                            \
913     }                                                                         \
914   else                                                                        \
915     Len = -1;
916
917 /**
918  * computes length of a unicode character in UTF-8
919  * @param Char the char
920  */
921 #define UTF8_LENGTH(Char)              \
922   ((Char) < 0x80 ? 1 :                 \
923    ((Char) < 0x800 ? 2 :               \
924     ((Char) < 0x10000 ? 3 :            \
925      ((Char) < 0x200000 ? 4 :          \
926       ((Char) < 0x4000000 ? 5 : 6)))))
927    
928 /**
929  * Gets a UTF-8 value.
930  *
931  * @param Result variable for extracted unicode char.
932  * @param Chars the bytes to decode
933  * @param Count counter variable
934  * @param Mask mask for this char
935  * @param Len length for this char in bytes
936  */
937 #define UTF8_GET(Result, Chars, Count, Mask, Len)                             \
938   (Result) = (Chars)[0] & (Mask);                                             \
939   for ((Count) = 1; (Count) < (Len); ++(Count))                               \
940     {                                                                         \
941       if (((Chars)[(Count)] & 0xc0) != 0x80)                                  \
942         {                                                                     \
943           (Result) = -1;                                                      \
944           break;                                                              \
945         }                                                                     \
946       (Result) <<= 6;                                                         \
947       (Result) |= ((Chars)[(Count)] & 0x3f);                                  \
948     }
949
950 /**
951  * Check whether a unicode char is in a valid range.
952  *
953  * @param Char the character
954  */
955 #define UNICODE_VALID(Char)                   \
956     ((Char) < 0x110000 &&                     \
957      ((Char) < 0xD800 || (Char) >= 0xE000) && \
958      (Char) != 0xFFFE && (Char) != 0xFFFF)   
959
960 /**
961  * Gets a unicode character from a UTF-8 string. Does no validation;
962  * you must verify that the string is valid UTF-8 in advance and must
963  * pass in the start of a character.
964  *
965  * @param str the string
966  * @param start the start of the UTF-8 character.
967  * @param ch_return location to return the character
968  * @param end_return location to return the byte index of next character
969  * @returns #TRUE on success, #FALSE otherwise.
970  */
971 void
972 _dbus_string_get_unichar (const DBusString *str,
973                           int               start,
974                           dbus_unichar_t   *ch_return,
975                           int              *end_return)
976 {
977   int i, mask, len;
978   dbus_unichar_t result;
979   unsigned char c;
980   unsigned char *p;
981   DBUS_CONST_STRING_PREAMBLE (str);
982
983   if (ch_return)
984     *ch_return = 0;
985   if (end_return)
986     *end_return = real->len;
987   
988   mask = 0;
989   p = real->str + start;
990   c = *p;
991   
992   UTF8_COMPUTE (c, mask, len);
993   if (len == -1)
994     return;
995   UTF8_GET (result, p, i, mask, len);
996
997   if (result == (dbus_unichar_t)-1)
998     return;
999
1000   if (ch_return)
1001     *ch_return = result;
1002   if (end_return)
1003     *end_return = start + len;
1004 }
1005
1006 /** @} */
1007
1008 #ifdef DBUS_BUILD_TESTS
1009 #include "dbus-test.h"
1010 #include <stdio.h>
1011
1012 static void
1013 test_max_len (DBusString *str,
1014               int         max_len)
1015 {
1016   if (max_len > 0)
1017     {
1018       if (!_dbus_string_set_length (str, max_len - 1))
1019         _dbus_assert_not_reached ("setting len to one less than max should have worked");
1020     }
1021
1022   if (!_dbus_string_set_length (str, max_len))
1023     _dbus_assert_not_reached ("setting len to max len should have worked");
1024
1025   if (_dbus_string_set_length (str, max_len + 1))
1026     _dbus_assert_not_reached ("setting len to one more than max len should not have worked");
1027
1028   if (!_dbus_string_set_length (str, 0))
1029     _dbus_assert_not_reached ("setting len to zero should have worked");
1030 }
1031
1032 /**
1033  * @ingroup DBusStringInternals
1034  * Unit test for DBusString.
1035  *
1036  * @todo Need to write tests for _dbus_string_copy() and
1037  * _dbus_string_move() moving to/from each of start/middle/end of a
1038  * string.
1039  * 
1040  * @returns #TRUE on success.
1041  */
1042 dbus_bool_t
1043 _dbus_string_test (void)
1044 {
1045   DBusString str;
1046   DBusString other;
1047   int i, end;
1048   long v;
1049   double d;
1050   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 };
1051   char *s;
1052   dbus_unichar_t ch;
1053   
1054   i = 0;
1055   while (i < _DBUS_N_ELEMENTS (lens))
1056     {
1057       if (!_dbus_string_init (&str, lens[i]))
1058         _dbus_assert_not_reached ("failed to init string");
1059       
1060       test_max_len (&str, lens[i]);
1061       _dbus_string_free (&str);
1062
1063       ++i;
1064     }
1065
1066   /* Test shortening and setting length */
1067   i = 0;
1068   while (i < _DBUS_N_ELEMENTS (lens))
1069     {
1070       int j;
1071       
1072       if (!_dbus_string_init (&str, lens[i]))
1073         _dbus_assert_not_reached ("failed to init string");
1074       
1075       if (!_dbus_string_set_length (&str, lens[i]))
1076         _dbus_assert_not_reached ("failed to set string length");
1077
1078       j = lens[i];
1079       while (j > 0)
1080         {
1081           _dbus_assert (_dbus_string_get_length (&str) == j);
1082           if (j > 0)
1083             {
1084               _dbus_string_shorten (&str, 1);
1085               _dbus_assert (_dbus_string_get_length (&str) == (j - 1));
1086             }
1087           --j;
1088         }
1089       
1090       _dbus_string_free (&str);
1091
1092       ++i;
1093     }
1094
1095   /* Test appending data */
1096   if (!_dbus_string_init (&str, _DBUS_INT_MAX))
1097     _dbus_assert_not_reached ("failed to init string");
1098
1099   i = 0;
1100   while (i < 10)
1101     {
1102       if (!_dbus_string_append (&str, "a"))
1103         _dbus_assert_not_reached ("failed to append string to string\n");
1104
1105       _dbus_assert (_dbus_string_get_length (&str) == i * 2 + 1);
1106
1107       if (!_dbus_string_append_byte (&str, 'b'))
1108         _dbus_assert_not_reached ("failed to append byte to string\n");
1109
1110       _dbus_assert (_dbus_string_get_length (&str) == i * 2 + 2);
1111                     
1112       ++i;
1113     }
1114
1115   _dbus_string_free (&str);
1116
1117   /* Check steal_data */
1118   
1119   if (!_dbus_string_init (&str, _DBUS_INT_MAX))
1120     _dbus_assert_not_reached ("failed to init string");
1121
1122   if (!_dbus_string_append (&str, "Hello World"))
1123     _dbus_assert_not_reached ("could not append to string");
1124
1125   i = _dbus_string_get_length (&str);
1126   
1127   if (!_dbus_string_steal_data (&str, &s))
1128     _dbus_assert_not_reached ("failed to steal data");
1129
1130   _dbus_assert (_dbus_string_get_length (&str) == 0);
1131   _dbus_assert (((int)strlen (s)) == i);
1132
1133   dbus_free (s);
1134
1135   /* Check move */
1136   
1137   if (!_dbus_string_append (&str, "Hello World"))
1138     _dbus_assert_not_reached ("could not append to string");
1139
1140   i = _dbus_string_get_length (&str);
1141
1142   if (!_dbus_string_init (&other, _DBUS_INT_MAX))
1143     _dbus_assert_not_reached ("could not init string");
1144   
1145   if (!_dbus_string_move (&str, 0, &other, 0))
1146     _dbus_assert_not_reached ("could not move");
1147
1148   _dbus_assert (_dbus_string_get_length (&str) == 0);
1149   _dbus_assert (_dbus_string_get_length (&other) == i);
1150
1151   _dbus_string_free (&other);
1152
1153   /* Check copy */
1154   
1155   if (!_dbus_string_append (&str, "Hello World"))
1156     _dbus_assert_not_reached ("could not append to string");
1157
1158   i = _dbus_string_get_length (&str);
1159   
1160   if (!_dbus_string_init (&other, _DBUS_INT_MAX))
1161     _dbus_assert_not_reached ("could not init string");
1162   
1163   if (!_dbus_string_copy (&str, 0, &other, 0))
1164     _dbus_assert_not_reached ("could not copy");
1165
1166   _dbus_assert (_dbus_string_get_length (&str) == i);
1167   _dbus_assert (_dbus_string_get_length (&other) == i);
1168   
1169   _dbus_string_free (&str);
1170   _dbus_string_free (&other);
1171
1172   /* Check append/get unichar */
1173   
1174   if (!_dbus_string_init (&str, _DBUS_INT_MAX))
1175     _dbus_assert_not_reached ("failed to init string");
1176
1177   ch = 0;
1178   if (!_dbus_string_append_unichar (&str, 0xfffc))
1179     _dbus_assert_not_reached ("failed to append unichar");
1180
1181   _dbus_string_get_unichar (&str, 0, &ch, &i);
1182
1183   _dbus_assert (ch == 0xfffc);
1184   _dbus_assert (i == _dbus_string_get_length (&str));
1185
1186   _dbus_string_free (&str);
1187   
1188   /* Check append/parse int/double */
1189   
1190   if (!_dbus_string_init (&str, _DBUS_INT_MAX))
1191     _dbus_assert_not_reached ("failed to init string");
1192
1193   if (!_dbus_string_append_int (&str, 27))
1194     _dbus_assert_not_reached ("failed to append int");
1195
1196   i = _dbus_string_get_length (&str);
1197
1198   if (!_dbus_string_parse_int (&str, 0, &v, &end))
1199     _dbus_assert_not_reached ("failed to parse int");
1200
1201   _dbus_assert (v == 27);
1202   _dbus_assert (end == i);
1203     
1204   _dbus_string_set_length (&str, 0);
1205
1206   if (!_dbus_string_init (&str, _DBUS_INT_MAX))
1207     _dbus_assert_not_reached ("failed to init string");
1208   
1209   if (!_dbus_string_append_double (&str, 50.3))
1210     _dbus_assert_not_reached ("failed to append float");
1211
1212   i = _dbus_string_get_length (&str);
1213
1214   if (!_dbus_string_parse_double (&str, 0, &d, &end))
1215     _dbus_assert_not_reached ("failed to parse float");
1216
1217   _dbus_assert (d > (50.3 - 1e-6) && d < (50.3 + 1e-6));
1218   _dbus_assert (end == i);
1219
1220   _dbus_string_free (&str);
1221
1222   return TRUE;
1223 }
1224
1225 #endif /* DBUS_BUILD_TESTS */