Main Page | Modules | Data Structures | Directories | File List | Data Fields | Related Pages

dbus-string.c

00001 /* -*- mode: C; c-file-style: "gnu" -*- */
00002 /* dbus-string.c String utility class (internal to D-BUS implementation)
00003  * 
00004  * Copyright (C) 2002, 2003, 2004 Red Hat, Inc.
00005  *
00006  * Licensed under the Academic Free License version 2.1
00007  * 
00008  * This program is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * This program is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  * 
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program; if not, write to the Free Software
00020  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021  *
00022  */
00023 
00024 #include "dbus-internals.h"
00025 #include "dbus-string.h"
00026 /* we allow a system header here, for speed/convenience */
00027 #include <string.h>
00028 /* for vsnprintf */
00029 #include <stdio.h>
00030 #include "dbus-marshal.h"
00031 #define DBUS_CAN_USE_DBUS_STRING_PRIVATE 1
00032 #include "dbus-string-private.h"
00033 #include "dbus-protocol.h"
00034 /* for DBUS_VA_COPY */
00035 #include "dbus-sysdeps.h"
00036 
00085 #define ALLOCATION_PADDING 8
00086 
00091 #define MAX_MAX_LENGTH (_DBUS_INT_MAX - ALLOCATION_PADDING)
00092 
00098 #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 - ALLOCATION_PADDING)); _dbus_assert ((real)->len <= (real)->max_length)
00099 
00106 #define DBUS_STRING_PREAMBLE(str) DBusRealString *real = (DBusRealString*) str; \
00107   DBUS_GENERIC_STRING_PREAMBLE (real);                                          \
00108   _dbus_assert (!(real)->constant);                                             \
00109   _dbus_assert (!(real)->locked)
00110 
00118 #define DBUS_LOCKED_STRING_PREAMBLE(str) DBusRealString *real = (DBusRealString*) str; \
00119   DBUS_GENERIC_STRING_PREAMBLE (real);                                                 \
00120   _dbus_assert (!(real)->constant)
00121 
00127 #define DBUS_CONST_STRING_PREAMBLE(str) const DBusRealString *real = (DBusRealString*) str; \
00128   DBUS_GENERIC_STRING_PREAMBLE (real)
00129 
00137 static void
00138 fixup_alignment (DBusRealString *real)
00139 {
00140   char *aligned;
00141   char *real_block;
00142   unsigned int old_align_offset;
00143 
00144   /* we have to have extra space in real->allocated for the align offset and nul byte */
00145   _dbus_assert (real->len <= real->allocated - ALLOCATION_PADDING);
00146   
00147   old_align_offset = real->align_offset;
00148   real_block = real->str - old_align_offset;
00149   
00150   aligned = _DBUS_ALIGN_ADDRESS (real_block, 8);
00151 
00152   real->align_offset = aligned - real_block;
00153   real->str = aligned;
00154   
00155   if (old_align_offset != real->align_offset)
00156     {
00157       /* Here comes the suck */
00158       memmove (real_block + real->align_offset,
00159                real_block + old_align_offset,
00160                real->len + 1);
00161     }
00162 
00163   _dbus_assert (real->align_offset < 8);
00164   _dbus_assert (_DBUS_ALIGN_ADDRESS (real->str, 8) == real->str);
00165 }
00166 
00167 static void
00168 undo_alignment (DBusRealString *real)
00169 {
00170   if (real->align_offset != 0)
00171     {
00172       memmove (real->str - real->align_offset,
00173                real->str,
00174                real->len + 1);
00175 
00176       real->str = real->str - real->align_offset;
00177       real->align_offset = 0;
00178     }
00179 }
00180 
00190 dbus_bool_t
00191 _dbus_string_init_preallocated (DBusString *str,
00192                                 int         allocate_size)
00193 {
00194   DBusRealString *real;
00195   
00196   _dbus_assert (str != NULL);
00197 
00198   _dbus_assert (sizeof (DBusString) == sizeof (DBusRealString));
00199   
00200   real = (DBusRealString*) str;
00201 
00202   /* It's very important not to touch anything
00203    * other than real->str if we're going to fail,
00204    * since we also use this function to reset
00205    * an existing string, e.g. in _dbus_string_steal_data()
00206    */
00207   
00208   real->str = dbus_malloc (ALLOCATION_PADDING + allocate_size);
00209   if (real->str == NULL)
00210     return FALSE;  
00211   
00212   real->allocated = ALLOCATION_PADDING + allocate_size;
00213   real->len = 0;
00214   real->str[real->len] = '\0';
00215   
00216   real->max_length = MAX_MAX_LENGTH;
00217   real->constant = FALSE;
00218   real->locked = FALSE;
00219   real->invalid = FALSE;
00220   real->align_offset = 0;
00221   
00222   fixup_alignment (real);
00223   
00224   return TRUE;
00225 }
00226 
00234 dbus_bool_t
00235 _dbus_string_init (DBusString *str)
00236 {
00237   return _dbus_string_init_preallocated (str, 0);
00238 }
00239 
00240 /* The max length thing is sort of a historical artifact
00241  * from a feature that turned out to be dumb; perhaps
00242  * we should purge it entirely. The problem with
00243  * the feature is that it looks like memory allocation
00244  * failure, but is not a transient or resolvable failure.
00245  */
00246 static void
00247 set_max_length (DBusString *str,
00248                 int         max_length)
00249 {
00250   DBusRealString *real;
00251   
00252   real = (DBusRealString*) str;
00253 
00254   real->max_length = max_length;
00255 }
00256 
00266 void
00267 _dbus_string_init_const (DBusString *str,
00268                          const char *value)
00269 {
00270   _dbus_assert (value != NULL);
00271   
00272   _dbus_string_init_const_len (str, value,
00273                                strlen (value));
00274 }
00275 
00286 void
00287 _dbus_string_init_const_len (DBusString *str,
00288                              const char *value,
00289                              int         len)
00290 {
00291   DBusRealString *real;
00292   
00293   _dbus_assert (str != NULL);
00294   _dbus_assert (value != NULL);
00295   _dbus_assert (len <= MAX_MAX_LENGTH);
00296   _dbus_assert (len >= 0);
00297   
00298   real = (DBusRealString*) str;
00299   
00300   real->str = (char*) value;
00301   real->len = len;
00302   real->allocated = real->len + ALLOCATION_PADDING; /* a lie, just to avoid special-case assertions... */
00303   real->max_length = real->len + 1;
00304   real->constant = TRUE;
00305   real->invalid = FALSE;
00306 
00307   /* We don't require const strings to be 8-byte aligned as the
00308    * memory is coming from elsewhere.
00309    */
00310 }
00311 
00317 void
00318 _dbus_string_free (DBusString *str)
00319 {
00320   DBusRealString *real = (DBusRealString*) str;
00321   DBUS_GENERIC_STRING_PREAMBLE (real);
00322   
00323   if (real->constant)
00324     return;
00325   dbus_free (real->str - real->align_offset);
00326 
00327   real->invalid = TRUE;
00328 }
00329 
00330 #ifdef DBUS_BUILD_TESTS
00331 /* Not using this feature at the moment,
00332  * so marked DBUS_BUILD_TESTS-only
00333  */
00343 void
00344 _dbus_string_lock (DBusString *str)
00345 {  
00346   DBUS_LOCKED_STRING_PREAMBLE (str); /* can lock multiple times */
00347 
00348   real->locked = TRUE;
00349 
00350   /* Try to realloc to avoid excess memory usage, since
00351    * we know we won't change the string further
00352    */
00353 #define MAX_WASTE 48
00354   if (real->allocated - MAX_WASTE > real->len)
00355     {
00356       char *new_str;
00357       int new_allocated;
00358 
00359       new_allocated = real->len + ALLOCATION_PADDING;
00360 
00361       new_str = dbus_realloc (real->str - real->align_offset,
00362                               new_allocated);
00363       if (new_str != NULL)
00364         {
00365           real->str = new_str + real->align_offset;
00366           real->allocated = new_allocated;
00367           fixup_alignment (real);
00368         }
00369     }
00370 }
00371 #endif /* DBUS_BUILD_TESTS */
00372 
00373 static dbus_bool_t
00374 reallocate_for_length (DBusRealString *real,
00375                        int             new_length)
00376 {
00377   int new_allocated;
00378   char *new_str;
00379 
00380   /* at least double our old allocation to avoid O(n), avoiding
00381    * overflow
00382    */
00383   if (real->allocated > (MAX_MAX_LENGTH + ALLOCATION_PADDING) / 2)
00384     new_allocated = MAX_MAX_LENGTH + ALLOCATION_PADDING;
00385   else
00386     new_allocated = real->allocated * 2;
00387 
00388   /* if you change the code just above here, run the tests without
00389    * the following assert-only hack before you commit
00390    */
00391   /* This is keyed off asserts in addition to tests so when you
00392    * disable asserts to profile, you don't get this destroyer
00393    * of profiles.
00394    */
00395 #ifdef DBUS_DISABLE_ASSERT
00396 #else
00397 #ifdef DBUS_BUILD_TESTS
00398   new_allocated = 0; /* ensure a realloc every time so that we go
00399                       * through all malloc failure codepaths
00400                       */
00401 #endif /* DBUS_BUILD_TESTS */
00402 #endif /* !DBUS_DISABLE_ASSERT */
00403 
00404   /* But be sure we always alloc at least space for the new length */
00405   new_allocated = MAX (new_allocated,
00406                        new_length + ALLOCATION_PADDING);
00407 
00408   _dbus_assert (new_allocated >= real->allocated); /* code relies on this */
00409   new_str = dbus_realloc (real->str - real->align_offset, new_allocated);
00410   if (_DBUS_UNLIKELY (new_str == NULL))
00411     return FALSE;
00412 
00413   real->str = new_str + real->align_offset;
00414   real->allocated = new_allocated;
00415   fixup_alignment (real);
00416 
00417   return TRUE;
00418 }
00419 
00420 static dbus_bool_t
00421 set_length (DBusRealString *real,
00422             int             new_length)
00423 {
00424   /* Note, we are setting the length not including nul termination */
00425 
00426   /* exceeding max length is the same as failure to allocate memory */
00427   if (_DBUS_UNLIKELY (new_length > real->max_length))
00428     return FALSE;
00429   else if (new_length > (real->allocated - ALLOCATION_PADDING) &&
00430            _DBUS_UNLIKELY (!reallocate_for_length (real, new_length)))
00431     return FALSE;
00432   else
00433     {
00434       real->len = new_length;
00435       real->str[new_length] = '\0';
00436       return TRUE;
00437     }
00438 }
00439 
00440 static dbus_bool_t
00441 open_gap (int             len,
00442           DBusRealString *dest,
00443           int             insert_at)
00444 {
00445   if (len == 0)
00446     return TRUE;
00447 
00448   if (len > dest->max_length - dest->len)
00449     return FALSE; /* detected overflow of dest->len + len below */
00450   
00451   if (!set_length (dest, dest->len + len))
00452     return FALSE;
00453 
00454   memmove (dest->str + insert_at + len, 
00455            dest->str + insert_at,
00456            dest->len - len - insert_at);
00457 
00458   return TRUE;
00459 }
00460 
00472 char*
00473 _dbus_string_get_data (DBusString *str)
00474 {
00475   DBUS_STRING_PREAMBLE (str);
00476   
00477   return real->str;
00478 }
00479 
00480 /* only do the function if we don't have the macro */
00481 #ifndef _dbus_string_get_const_data
00482 
00488 const char*
00489 _dbus_string_get_const_data (const DBusString  *str)
00490 {
00491   DBUS_CONST_STRING_PREAMBLE (str);
00492   
00493   return real->str;
00494 }
00495 #endif /* _dbus_string_get_const_data */
00496 
00510 char*
00511 _dbus_string_get_data_len (DBusString *str,
00512                            int         start,
00513                            int         len)
00514 {
00515   DBUS_STRING_PREAMBLE (str);
00516   _dbus_assert (start >= 0);
00517   _dbus_assert (len >= 0);
00518   _dbus_assert (start <= real->len);
00519   _dbus_assert (len <= real->len - start);
00520   
00521   return real->str + start;
00522 }
00523 
00532 const char*
00533 _dbus_string_get_const_data_len (const DBusString  *str,
00534                                  int                start,
00535                                  int                len)
00536 {
00537   DBUS_CONST_STRING_PREAMBLE (str);
00538   _dbus_assert (start >= 0);
00539   _dbus_assert (len >= 0);
00540   _dbus_assert (start <= real->len);
00541   _dbus_assert (len <= real->len - start);
00542   
00543   return real->str + start;
00544 }
00545 
00553 void
00554 _dbus_string_set_byte (DBusString    *str,
00555                        int            i,
00556                        unsigned char  byte)
00557 {
00558   DBUS_STRING_PREAMBLE (str);
00559   _dbus_assert (i < real->len);
00560   _dbus_assert (i >= 0);
00561   
00562   real->str[i] = byte;
00563 }
00564 
00565 /* only have the function if we didn't create a macro */
00566 #ifndef _dbus_string_get_byte
00567 
00576 unsigned char
00577 _dbus_string_get_byte (const DBusString  *str,
00578                        int                start)
00579 {
00580   DBUS_CONST_STRING_PREAMBLE (str);
00581   _dbus_assert (start <= real->len);
00582   _dbus_assert (start >= 0);
00583   
00584   return real->str[start];
00585 }
00586 #endif /* _dbus_string_get_byte */
00587 
00598 dbus_bool_t
00599 _dbus_string_insert_bytes (DBusString   *str,
00600                            int           i,
00601                            int           n_bytes,
00602                            unsigned char byte)
00603 {
00604   DBUS_STRING_PREAMBLE (str);
00605   _dbus_assert (i <= real->len);
00606   _dbus_assert (i >= 0);
00607   _dbus_assert (n_bytes >= 0);
00608 
00609   if (n_bytes == 0)
00610     return TRUE;
00611   
00612   if (!open_gap (n_bytes, real, i))
00613     return FALSE;
00614   
00615   memset (real->str + i, byte, n_bytes);
00616 
00617   return TRUE;
00618 }
00619 
00628 dbus_bool_t
00629 _dbus_string_insert_byte (DBusString   *str,
00630                            int           i,
00631                            unsigned char byte)
00632 {
00633   DBUS_STRING_PREAMBLE (str);
00634   _dbus_assert (i <= real->len);
00635   _dbus_assert (i >= 0);
00636   
00637   if (!open_gap (1, real, i))
00638     return FALSE;
00639 
00640   real->str[i] = byte;
00641 
00642   return TRUE;
00643 }
00644 
00655 dbus_bool_t
00656 _dbus_string_steal_data (DBusString        *str,
00657                          char             **data_return)
00658 {
00659   int old_max_length;
00660   DBUS_STRING_PREAMBLE (str);
00661   _dbus_assert (data_return != NULL);
00662 
00663   undo_alignment (real);
00664   
00665   *data_return = real->str;
00666 
00667   old_max_length = real->max_length;
00668   
00669   /* reset the string */
00670   if (!_dbus_string_init (str))
00671     {
00672       /* hrm, put it back then */
00673       real->str = *data_return;
00674       *data_return = NULL;
00675       fixup_alignment (real);
00676       return FALSE;
00677     }
00678 
00679   real->max_length = old_max_length;
00680 
00681   return TRUE;
00682 }
00683 
00699 dbus_bool_t
00700 _dbus_string_steal_data_len (DBusString        *str,
00701                              char             **data_return,
00702                              int                start,
00703                              int                len)
00704 {
00705   DBusString dest;
00706   DBUS_STRING_PREAMBLE (str);
00707   _dbus_assert (data_return != NULL);
00708   _dbus_assert (start >= 0);
00709   _dbus_assert (len >= 0);
00710   _dbus_assert (start <= real->len);
00711   _dbus_assert (len <= real->len - start);
00712 
00713   if (!_dbus_string_init (&dest))
00714     return FALSE;
00715 
00716   set_max_length (&dest, real->max_length);
00717   
00718   if (!_dbus_string_move_len (str, start, len, &dest, 0))
00719     {
00720       _dbus_string_free (&dest);
00721       return FALSE;
00722     }
00723 
00724   _dbus_warn ("Broken code in _dbus_string_steal_data_len(), see @todo, FIXME\n");
00725   if (!_dbus_string_steal_data (&dest, data_return))
00726     {
00727       _dbus_string_free (&dest);
00728       return FALSE;
00729     }
00730 
00731   _dbus_string_free (&dest);
00732   return TRUE;
00733 }
00734 
00735 
00743 dbus_bool_t
00744 _dbus_string_copy_data (const DBusString  *str,
00745                         char             **data_return)
00746 {
00747   DBUS_CONST_STRING_PREAMBLE (str);
00748   _dbus_assert (data_return != NULL);
00749   
00750   *data_return = dbus_malloc (real->len + 1);
00751   if (*data_return == NULL)
00752     return FALSE;
00753 
00754   memcpy (*data_return, real->str, real->len + 1);
00755 
00756   return TRUE;
00757 }
00758 
00768 dbus_bool_t
00769 _dbus_string_copy_data_len (const DBusString  *str,
00770                             char             **data_return,
00771                             int                start,
00772                             int                len)
00773 {
00774   DBusString dest;
00775 
00776   DBUS_CONST_STRING_PREAMBLE (str);
00777   _dbus_assert (data_return != NULL);
00778   _dbus_assert (start >= 0);
00779   _dbus_assert (len >= 0);
00780   _dbus_assert (start <= real->len);
00781   _dbus_assert (len <= real->len - start);
00782 
00783   if (!_dbus_string_init (&dest))
00784     return FALSE;
00785 
00786   set_max_length (&dest, real->max_length);
00787 
00788   if (!_dbus_string_copy_len (str, start, len, &dest, 0))
00789     {
00790       _dbus_string_free (&dest);
00791       return FALSE;
00792     }
00793 
00794   if (!_dbus_string_steal_data (&dest, data_return))
00795     {
00796       _dbus_string_free (&dest);
00797       return FALSE;
00798     }
00799 
00800   _dbus_string_free (&dest);
00801   return TRUE;
00802 }
00803 
00812 void
00813 _dbus_string_copy_to_buffer (const DBusString  *str,
00814                              char              *buffer,
00815                              int                avail_len)
00816 {
00817   int copy_len;
00818   DBUS_CONST_STRING_PREAMBLE (str);
00819 
00820   _dbus_assert (avail_len >= 0);
00821 
00822   copy_len = MIN (avail_len, real->len+1);
00823   memcpy (buffer, real->str, copy_len);
00824   if (avail_len > 0 && avail_len == copy_len)
00825     buffer[avail_len-1] = '\0';
00826 }
00827 
00828 /* Only have the function if we don't have the macro */
00829 #ifndef _dbus_string_get_length
00830 
00835 int
00836 _dbus_string_get_length (const DBusString  *str)
00837 {
00838   DBUS_CONST_STRING_PREAMBLE (str);
00839   
00840   return real->len;
00841 }
00842 #endif /* !_dbus_string_get_length */
00843 
00856 dbus_bool_t
00857 _dbus_string_lengthen (DBusString *str,
00858                        int         additional_length)
00859 {
00860   DBUS_STRING_PREAMBLE (str);  
00861   _dbus_assert (additional_length >= 0);
00862 
00863   if (_DBUS_UNLIKELY (additional_length > real->max_length - real->len))
00864     return FALSE; /* would overflow */
00865   
00866   return set_length (real,
00867                      real->len + additional_length);
00868 }
00869 
00876 void
00877 _dbus_string_shorten (DBusString *str,
00878                       int         length_to_remove)
00879 {
00880   DBUS_STRING_PREAMBLE (str);
00881   _dbus_assert (length_to_remove >= 0);
00882   _dbus_assert (length_to_remove <= real->len);
00883 
00884   set_length (real,
00885               real->len - length_to_remove);
00886 }
00887 
00898 dbus_bool_t
00899 _dbus_string_set_length (DBusString *str,
00900                          int         length)
00901 {
00902   DBUS_STRING_PREAMBLE (str);
00903   _dbus_assert (length >= 0);
00904 
00905   return set_length (real, length);
00906 }
00907 
00908 static dbus_bool_t
00909 align_insert_point_then_open_gap (DBusString *str,
00910                                   int        *insert_at_p,
00911                                   int         alignment,
00912                                   int         gap_size)
00913 {
00914   unsigned long new_len; /* ulong to avoid _DBUS_ALIGN_VALUE overflow */
00915   unsigned long gap_pos;
00916   int insert_at;
00917   int delta;
00918   DBUS_STRING_PREAMBLE (str);
00919   _dbus_assert (alignment >= 1);
00920   _dbus_assert (alignment <= 8); /* it has to be a bug if > 8 */
00921 
00922   insert_at = *insert_at_p;
00923 
00924   _dbus_assert (insert_at <= real->len);
00925   
00926   gap_pos = _DBUS_ALIGN_VALUE (insert_at, alignment);
00927   new_len = real->len + (gap_pos - insert_at) + gap_size;
00928   
00929   if (_DBUS_UNLIKELY (new_len > (unsigned long) real->max_length))
00930     return FALSE;
00931   
00932   delta = new_len - real->len;
00933   _dbus_assert (delta >= 0);
00934 
00935   if (delta == 0) /* only happens if gap_size == 0 and insert_at is aligned already */
00936     {
00937       _dbus_assert (((unsigned long) *insert_at_p) == gap_pos);
00938       return TRUE;
00939     }
00940 
00941   if (_DBUS_UNLIKELY (!open_gap (new_len - real->len,
00942                                  real, insert_at)))
00943     return FALSE;
00944 
00945   /* nul the padding if we had to add any padding */
00946   if (gap_size < delta)
00947     {
00948       memset (&real->str[insert_at], '\0',
00949               gap_pos - insert_at);
00950     }
00951 
00952   *insert_at_p = gap_pos;
00953   
00954   return TRUE;
00955 }
00956 
00957 static dbus_bool_t
00958 align_length_then_lengthen (DBusString *str,
00959                             int         alignment,
00960                             int         then_lengthen_by)
00961 {
00962   int insert_at;
00963 
00964   insert_at = _dbus_string_get_length (str);
00965   
00966   return align_insert_point_then_open_gap (str,
00967                                            &insert_at,
00968                                            alignment, then_lengthen_by);
00969 }
00970 
00979 dbus_bool_t
00980 _dbus_string_align_length (DBusString *str,
00981                            int         alignment)
00982 {
00983   return align_length_then_lengthen (str, alignment, 0);
00984 }
00985 
00995 dbus_bool_t
00996 _dbus_string_alloc_space (DBusString        *str,
00997                           int                extra_bytes)
00998 {
00999   if (!_dbus_string_lengthen (str, extra_bytes))
01000     return FALSE;
01001   _dbus_string_shorten (str, extra_bytes);
01002 
01003   return TRUE;
01004 }
01005 
01006 static dbus_bool_t
01007 append (DBusRealString *real,
01008         const char     *buffer,
01009         int             buffer_len)
01010 {
01011   if (buffer_len == 0)
01012     return TRUE;
01013 
01014   if (!_dbus_string_lengthen ((DBusString*)real, buffer_len))
01015     return FALSE;
01016 
01017   memcpy (real->str + (real->len - buffer_len),
01018           buffer,
01019           buffer_len);
01020 
01021   return TRUE;
01022 }
01023 
01031 dbus_bool_t
01032 _dbus_string_append (DBusString *str,
01033                      const char *buffer)
01034 {
01035   unsigned long buffer_len;
01036   
01037   DBUS_STRING_PREAMBLE (str);
01038   _dbus_assert (buffer != NULL);
01039   
01040   buffer_len = strlen (buffer);
01041   if (buffer_len > (unsigned long) real->max_length)
01042     return FALSE;
01043   
01044   return append (real, buffer, buffer_len);
01045 }
01046 
01047 #define ASSIGN_4_OCTETS(p, octets) \
01048   *((dbus_uint32_t*)(p)) = *((dbus_uint32_t*)(octets));
01049 
01050 #ifdef DBUS_HAVE_INT64
01051 #define ASSIGN_8_OCTETS(p, octets) \
01052   *((dbus_uint64_t*)(p)) = *((dbus_uint64_t*)(octets));
01053 #else
01054 #define ASSIGN_8_OCTETS(p, octets)              \
01055 do {                                            \
01056   unsigned char *b;                             \
01057                                                 \
01058   b = p;                                        \
01059                                                 \
01060   *b++ = octets[0];                             \
01061   *b++ = octets[1];                             \
01062   *b++ = octets[2];                             \
01063   *b++ = octets[3];                             \
01064   *b++ = octets[4];                             \
01065   *b++ = octets[5];                             \
01066   *b++ = octets[6];                             \
01067   *b++ = octets[7];                             \
01068   _dbus_assert (b == p + 8);                    \
01069 } while (0)
01070 #endif /* DBUS_HAVE_INT64 */
01071 
01080 dbus_bool_t
01081 _dbus_string_append_4_aligned (DBusString         *str,
01082                                const unsigned char octets[4])
01083 {
01084   DBUS_STRING_PREAMBLE (str);
01085   
01086   if (!align_length_then_lengthen (str, 4, 4))
01087     return FALSE;
01088 
01089   ASSIGN_4_OCTETS (real->str + (real->len - 4), octets);
01090 
01091   return TRUE;
01092 }
01093 
01102 dbus_bool_t
01103 _dbus_string_append_8_aligned (DBusString         *str,
01104                                const unsigned char octets[8])
01105 {
01106   DBUS_STRING_PREAMBLE (str);
01107   
01108   if (!align_length_then_lengthen (str, 8, 8))
01109     return FALSE;
01110 
01111   ASSIGN_8_OCTETS (real->str + (real->len - 8), octets);
01112 
01113   return TRUE;
01114 }
01115 
01124 dbus_bool_t
01125 _dbus_string_insert_4_aligned (DBusString         *str,
01126                                int                 insert_at,
01127                                const unsigned char octets[4])
01128 {
01129   DBUS_STRING_PREAMBLE (str);
01130   
01131   if (!align_insert_point_then_open_gap (str, &insert_at, 4, 4))
01132     return FALSE;
01133 
01134   ASSIGN_4_OCTETS (real->str + insert_at, octets);
01135 
01136   return TRUE;
01137 }
01138 
01147 dbus_bool_t
01148 _dbus_string_insert_8_aligned (DBusString         *str,
01149                                int                 insert_at,
01150                                const unsigned char octets[8])
01151 {
01152   DBUS_STRING_PREAMBLE (str);
01153   
01154   if (!align_insert_point_then_open_gap (str, &insert_at, 8, 8))
01155     return FALSE;
01156 
01157   _dbus_assert (_DBUS_ALIGN_VALUE (insert_at, 8) == (unsigned) insert_at);
01158   
01159   ASSIGN_8_OCTETS (real->str + insert_at, octets);
01160 
01161   return TRUE;
01162 }
01163 
01164 
01175 dbus_bool_t
01176 _dbus_string_insert_alignment (DBusString        *str,
01177                                int               *insert_at,
01178                                int                alignment)
01179 {
01180   DBUS_STRING_PREAMBLE (str);
01181   
01182   if (!align_insert_point_then_open_gap (str, insert_at, 8, 0))
01183     return FALSE;
01184 
01185   _dbus_assert (_DBUS_ALIGN_VALUE (*insert_at, 8) == (unsigned) *insert_at);
01186 
01187   return TRUE;
01188 }
01189 
01199 dbus_bool_t
01200 _dbus_string_append_printf_valist  (DBusString        *str,
01201                                     const char        *format,
01202                                     va_list            args)
01203 {
01204   int len;
01205   char c;
01206   va_list args_copy;
01207 
01208   DBUS_STRING_PREAMBLE (str);
01209 
01210   DBUS_VA_COPY (args_copy, args);
01211 
01212   /* Measure the message length without terminating nul */
01213   len = vsnprintf (&c, 1, format, args);
01214 
01215   if (!_dbus_string_lengthen (str, len))
01216     {
01217       /* don't leak the copy */
01218       va_end (args_copy);
01219       return FALSE;
01220     }
01221   
01222   vsprintf (real->str + (real->len - len),
01223             format, args_copy);
01224 
01225   va_end (args_copy);
01226 
01227   return TRUE;
01228 }
01229 
01238 dbus_bool_t
01239 _dbus_string_append_printf (DBusString        *str,
01240                             const char        *format,
01241                             ...)
01242 {
01243   va_list args;
01244   dbus_bool_t retval;
01245   
01246   va_start (args, format);
01247   retval = _dbus_string_append_printf_valist (str, format, args);
01248   va_end (args);
01249 
01250   return retval;
01251 }
01252 
01261 dbus_bool_t
01262 _dbus_string_append_len (DBusString *str,
01263                          const char *buffer,
01264                          int         len)
01265 {
01266   DBUS_STRING_PREAMBLE (str);
01267   _dbus_assert (buffer != NULL);
01268   _dbus_assert (len >= 0);
01269 
01270   return append (real, buffer, len);
01271 }
01272 
01281 dbus_bool_t
01282 _dbus_string_append_byte (DBusString    *str,
01283                           unsigned char  byte)
01284 {
01285   DBUS_STRING_PREAMBLE (str);
01286 
01287   if (!set_length (real, real->len + 1))
01288     return FALSE;
01289 
01290   real->str[real->len-1] = byte;
01291 
01292   return TRUE;
01293 }
01294 
01302 dbus_bool_t
01303 _dbus_string_append_unichar (DBusString    *str,
01304                              dbus_unichar_t ch)
01305 {
01306   int len;
01307   int first;
01308   int i;
01309   char *out;
01310   
01311   DBUS_STRING_PREAMBLE (str);
01312 
01313   /* this code is from GLib but is pretty standard I think */
01314   
01315   len = 0;
01316   
01317   if (ch < 0x80)
01318     {
01319       first = 0;
01320       len = 1;
01321     }
01322   else if (ch < 0x800)
01323     {
01324       first = 0xc0;
01325       len = 2;
01326     }
01327   else if (ch < 0x10000)
01328     {
01329       first = 0xe0;
01330       len = 3;
01331     }
01332    else if (ch < 0x200000)
01333     {
01334       first = 0xf0;
01335       len = 4;
01336     }
01337   else if (ch < 0x4000000)
01338     {
01339       first = 0xf8;
01340       len = 5;
01341     }
01342   else
01343     {
01344       first = 0xfc;
01345       len = 6;
01346     }
01347 
01348   if (len > (real->max_length - real->len))
01349     return FALSE; /* real->len + len would overflow */
01350   
01351   if (!set_length (real, real->len + len))
01352     return FALSE;
01353 
01354   out = real->str + (real->len - len);
01355   
01356   for (i = len - 1; i > 0; --i)
01357     {
01358       out[i] = (ch & 0x3f) | 0x80;
01359       ch >>= 6;
01360     }
01361   out[0] = ch | first;
01362 
01363   return TRUE;
01364 }
01365 
01366 static void
01367 delete (DBusRealString *real,
01368         int             start,
01369         int             len)
01370 {
01371   if (len == 0)
01372     return;
01373   
01374   memmove (real->str + start, real->str + start + len, real->len - (start + len));
01375   real->len -= len;
01376   real->str[real->len] = '\0';
01377 }
01378 
01388 void
01389 _dbus_string_delete (DBusString       *str,
01390                      int               start,
01391                      int               len)
01392 {
01393   DBUS_STRING_PREAMBLE (str);
01394   _dbus_assert (start >= 0);
01395   _dbus_assert (len >= 0);
01396   _dbus_assert (start <= real->len);
01397   _dbus_assert (len <= real->len - start);
01398   
01399   delete (real, start, len);
01400 }
01401 
01402 static dbus_bool_t
01403 copy (DBusRealString *source,
01404       int             start,
01405       int             len,
01406       DBusRealString *dest,
01407       int             insert_at)
01408 {
01409   if (len == 0)
01410     return TRUE;
01411 
01412   if (!open_gap (len, dest, insert_at))
01413     return FALSE;
01414   
01415   memcpy (dest->str + insert_at,
01416           source->str + start,
01417           len);
01418 
01419   return TRUE;
01420 }
01421 
01431 #define DBUS_STRING_COPY_PREAMBLE(source, start, dest, insert_at)       \
01432   DBusRealString *real_source = (DBusRealString*) source;               \
01433   DBusRealString *real_dest = (DBusRealString*) dest;                   \
01434   _dbus_assert ((source) != (dest));                                    \
01435   DBUS_GENERIC_STRING_PREAMBLE (real_source);                           \
01436   DBUS_GENERIC_STRING_PREAMBLE (real_dest);                             \
01437   _dbus_assert (!real_dest->constant);                                  \
01438   _dbus_assert (!real_dest->locked);                                    \
01439   _dbus_assert ((start) >= 0);                                          \
01440   _dbus_assert ((start) <= real_source->len);                           \
01441   _dbus_assert ((insert_at) >= 0);                                      \
01442   _dbus_assert ((insert_at) <= real_dest->len)
01443 
01454 dbus_bool_t
01455 _dbus_string_move (DBusString       *source,
01456                    int               start,
01457                    DBusString       *dest,
01458                    int               insert_at)
01459 {
01460   DBusRealString *real_source = (DBusRealString*) source;
01461   _dbus_assert (start <= real_source->len);
01462   
01463   return _dbus_string_move_len (source, start,
01464                                 real_source->len - start,
01465                                 dest, insert_at);
01466 }
01467 
01478 dbus_bool_t
01479 _dbus_string_copy (const DBusString *source,
01480                    int               start,
01481                    DBusString       *dest,
01482                    int               insert_at)
01483 {
01484   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
01485 
01486   return copy (real_source, start,
01487                real_source->len - start,
01488                real_dest,
01489                insert_at);
01490 }
01491 
01506 dbus_bool_t
01507 _dbus_string_move_len (DBusString       *source,
01508                        int               start,
01509                        int               len,
01510                        DBusString       *dest,
01511                        int               insert_at)
01512 
01513 {
01514   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
01515   _dbus_assert (len >= 0);
01516   _dbus_assert ((start + len) <= real_source->len);
01517 
01518 
01519   if (len == 0)
01520     {
01521       return TRUE;
01522     }
01523   else if (start == 0 &&
01524            len == real_source->len &&
01525            real_dest->len == 0)
01526     {
01527       /* Short-circuit moving an entire existing string to an empty string
01528        * by just swapping the buffers.
01529        */
01530       /* we assume ->constant doesn't matter as you can't have
01531        * a constant string involved in a move.
01532        */
01533 #define ASSIGN_DATA(a, b) do {                  \
01534         (a)->str = (b)->str;                    \
01535         (a)->len = (b)->len;                    \
01536         (a)->allocated = (b)->allocated;        \
01537         (a)->align_offset = (b)->align_offset;  \
01538       } while (0)
01539       
01540       DBusRealString tmp;
01541 
01542       ASSIGN_DATA (&tmp, real_source);
01543       ASSIGN_DATA (real_source, real_dest);
01544       ASSIGN_DATA (real_dest, &tmp);
01545 
01546       return TRUE;
01547     }
01548   else
01549     {
01550       if (!copy (real_source, start, len,
01551                  real_dest,
01552                  insert_at))
01553         return FALSE;
01554       
01555       delete (real_source, start,
01556               len);
01557       
01558       return TRUE;
01559     }
01560 }
01561 
01573 dbus_bool_t
01574 _dbus_string_copy_len (const DBusString *source,
01575                        int               start,
01576                        int               len,
01577                        DBusString       *dest,
01578                        int               insert_at)
01579 {
01580   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
01581   _dbus_assert (len >= 0);
01582   _dbus_assert (start <= real_source->len);
01583   _dbus_assert (len <= real_source->len - start);
01584   
01585   return copy (real_source, start, len,
01586                real_dest,
01587                insert_at);
01588 }
01589 
01611 dbus_bool_t
01612 _dbus_string_replace_len (const DBusString *source,
01613                           int               start,
01614                           int               len,
01615                           DBusString       *dest,
01616                           int               replace_at,
01617                           int               replace_len)
01618 {
01619   DBUS_STRING_COPY_PREAMBLE (source, start, dest, replace_at);
01620   _dbus_assert (len >= 0);
01621   _dbus_assert (start <= real_source->len);
01622   _dbus_assert (len <= real_source->len - start);
01623   _dbus_assert (replace_at >= 0);
01624   _dbus_assert (replace_at <= real_dest->len);
01625   _dbus_assert (replace_len <= real_dest->len - replace_at);
01626 
01627   if (!copy (real_source, start, len,
01628              real_dest, replace_at))
01629     return FALSE;
01630 
01631   delete (real_dest, replace_at + len, replace_len);
01632 
01633   return TRUE;
01634 }
01635 
01636 /* Unicode macros and utf8_validate() from GLib Owen Taylor, Havoc
01637  * Pennington, and Tom Tromey are the authors and authorized relicense.
01638  */
01639 
01645 #define UTF8_COMPUTE(Char, Mask, Len)                                         \
01646   if (Char < 128)                                                             \
01647     {                                                                         \
01648       Len = 1;                                                                \
01649       Mask = 0x7f;                                                            \
01650     }                                                                         \
01651   else if ((Char & 0xe0) == 0xc0)                                             \
01652     {                                                                         \
01653       Len = 2;                                                                \
01654       Mask = 0x1f;                                                            \
01655     }                                                                         \
01656   else if ((Char & 0xf0) == 0xe0)                                             \
01657     {                                                                         \
01658       Len = 3;                                                                \
01659       Mask = 0x0f;                                                            \
01660     }                                                                         \
01661   else if ((Char & 0xf8) == 0xf0)                                             \
01662     {                                                                         \
01663       Len = 4;                                                                \
01664       Mask = 0x07;                                                            \
01665     }                                                                         \
01666   else if ((Char & 0xfc) == 0xf8)                                             \
01667     {                                                                         \
01668       Len = 5;                                                                \
01669       Mask = 0x03;                                                            \
01670     }                                                                         \
01671   else if ((Char & 0xfe) == 0xfc)                                             \
01672     {                                                                         \
01673       Len = 6;                                                                \
01674       Mask = 0x01;                                                            \
01675     }                                                                         \
01676   else                                                                        \
01677     {                                                                         \
01678       Len = 0;                                                               \
01679       Mask = 0;                                                               \
01680     }
01681 
01686 #define UTF8_LENGTH(Char)              \
01687   ((Char) < 0x80 ? 1 :                 \
01688    ((Char) < 0x800 ? 2 :               \
01689     ((Char) < 0x10000 ? 3 :            \
01690      ((Char) < 0x200000 ? 4 :          \
01691       ((Char) < 0x4000000 ? 5 : 6)))))
01692    
01702 #define UTF8_GET(Result, Chars, Count, Mask, Len)                             \
01703   (Result) = (Chars)[0] & (Mask);                                             \
01704   for ((Count) = 1; (Count) < (Len); ++(Count))                               \
01705     {                                                                         \
01706       if (((Chars)[(Count)] & 0xc0) != 0x80)                                  \
01707         {                                                                     \
01708           (Result) = -1;                                                      \
01709           break;                                                              \
01710         }                                                                     \
01711       (Result) <<= 6;                                                         \
01712       (Result) |= ((Chars)[(Count)] & 0x3f);                                  \
01713     }
01714 
01720 #define UNICODE_VALID(Char)                   \
01721     ((Char) < 0x110000 &&                     \
01722      (((Char) & 0xFFFFF800) != 0xD800) &&     \
01723      ((Char) < 0xFDD0 || (Char) > 0xFDEF) &&  \
01724      ((Char) & 0xFFFF) != 0xFFFF)
01725 
01736 void
01737 _dbus_string_get_unichar (const DBusString *str,
01738                           int               start,
01739                           dbus_unichar_t   *ch_return,
01740                           int              *end_return)
01741 {
01742   int i, mask, len;
01743   dbus_unichar_t result;
01744   unsigned char c;
01745   unsigned char *p;
01746   DBUS_CONST_STRING_PREAMBLE (str);
01747   _dbus_assert (start >= 0);
01748   _dbus_assert (start <= real->len);
01749   
01750   if (ch_return)
01751     *ch_return = 0;
01752   if (end_return)
01753     *end_return = real->len;
01754   
01755   mask = 0;
01756   p = real->str + start;
01757   c = *p;
01758   
01759   UTF8_COMPUTE (c, mask, len);
01760   if (len == 0)
01761     return;
01762   UTF8_GET (result, p, i, mask, len);
01763 
01764   if (result == (dbus_unichar_t)-1)
01765     return;
01766 
01767   if (ch_return)
01768     *ch_return = result;
01769   if (end_return)
01770     *end_return = start + len;
01771 }
01772 
01787 dbus_bool_t
01788 _dbus_string_find (const DBusString *str,
01789                    int               start,
01790                    const char       *substr,
01791                    int              *found)
01792 {
01793   return _dbus_string_find_to (str, start,
01794                                ((const DBusRealString*)str)->len,
01795                                substr, found);
01796 }
01797 
01814 dbus_bool_t
01815 _dbus_string_find_to (const DBusString *str,
01816                       int               start,
01817                       int               end,
01818                       const char       *substr,
01819                       int              *found)
01820 {
01821   int i;
01822   DBUS_CONST_STRING_PREAMBLE (str);
01823   _dbus_assert (substr != NULL);
01824   _dbus_assert (start <= real->len);
01825   _dbus_assert (start >= 0);
01826   _dbus_assert (substr != NULL);
01827   _dbus_assert (end <= real->len);
01828   _dbus_assert (start <= end);
01829 
01830   /* we always "find" an empty string */
01831   if (*substr == '\0')
01832     {
01833       if (found)
01834         *found = start;
01835       return TRUE;
01836     }
01837 
01838   i = start;
01839   while (i < end)
01840     {
01841       if (real->str[i] == substr[0])
01842         {
01843           int j = i + 1;
01844           
01845           while (j < end)
01846             {
01847               if (substr[j - i] == '\0')
01848                 break;
01849               else if (real->str[j] != substr[j - i])
01850                 break;
01851               
01852               ++j;
01853             }
01854 
01855           if (substr[j - i] == '\0')
01856             {
01857               if (found)
01858                 *found = i;
01859               return TRUE;
01860             }
01861         }
01862       
01863       ++i;
01864     }
01865 
01866   if (found)
01867     *found = end;
01868   
01869   return FALSE;  
01870 }
01871 
01882 dbus_bool_t
01883 _dbus_string_find_byte_backward (const DBusString  *str,
01884                                  int                start,
01885                                  unsigned char      byte,
01886                                  int               *found)
01887 {
01888   int i;
01889   DBUS_CONST_STRING_PREAMBLE (str);
01890   _dbus_assert (start <= real->len);
01891   _dbus_assert (start >= 0);
01892   _dbus_assert (found != NULL);
01893 
01894   i = start - 1;
01895   while (i >= 0)
01896     {
01897       if (real->str[i] == byte)
01898         break;
01899       
01900       --i;
01901     }
01902 
01903   if (found)
01904     *found = i;
01905 
01906   return i >= 0;
01907 }
01908 
01919 dbus_bool_t
01920 _dbus_string_find_blank (const DBusString *str,
01921                          int               start,
01922                          int              *found)
01923 {
01924   int i;
01925   DBUS_CONST_STRING_PREAMBLE (str);
01926   _dbus_assert (start <= real->len);
01927   _dbus_assert (start >= 0);
01928   
01929   i = start;
01930   while (i < real->len)
01931     {
01932       if (real->str[i] == ' ' ||
01933           real->str[i] == '\t')
01934         {
01935           if (found)
01936             *found = i;
01937           return TRUE;
01938         }
01939       
01940       ++i;
01941     }
01942 
01943   if (found)
01944     *found = real->len;
01945   
01946   return FALSE;
01947 }
01948 
01957 void
01958 _dbus_string_skip_blank (const DBusString *str,
01959                          int               start,
01960                          int              *end)
01961 {
01962   int i;
01963   DBUS_CONST_STRING_PREAMBLE (str);
01964   _dbus_assert (start <= real->len);
01965   _dbus_assert (start >= 0);
01966   
01967   i = start;
01968   while (i < real->len)
01969     {
01970       if (!(real->str[i] == ' ' ||
01971             real->str[i] == '\t'))
01972         break;
01973       
01974       ++i;
01975     }
01976 
01977   _dbus_assert (i == real->len || !(real->str[i] == ' ' ||
01978                                     real->str[i] == '\t'));
01979   
01980   if (end)
01981     *end = i;
01982 }
01983 
01992 void
01993 _dbus_string_skip_white (const DBusString *str,
01994                          int               start,
01995                          int              *end)
01996 {
01997   int i;
01998   DBUS_CONST_STRING_PREAMBLE (str);
01999   _dbus_assert (start <= real->len);
02000   _dbus_assert (start >= 0);
02001   
02002   i = start;
02003   while (i < real->len)
02004     {
02005       if (!(real->str[i] == ' ' ||
02006             real->str[i] == '\n' ||
02007             real->str[i] == '\r' ||
02008             real->str[i] == '\t'))
02009         break;
02010       
02011       ++i;
02012     }
02013 
02014   _dbus_assert (i == real->len || !(real->str[i] == ' ' ||
02015                                     real->str[i] == '\t'));
02016   
02017   if (end)
02018     *end = i;
02019 }
02020 
02036 dbus_bool_t
02037 _dbus_string_pop_line (DBusString *source,
02038                        DBusString *dest)
02039 {
02040   int eol;
02041   dbus_bool_t have_newline;
02042   
02043   _dbus_string_set_length (dest, 0);
02044   
02045   eol = 0;
02046   if (_dbus_string_find (source, 0, "\n", &eol))
02047     {
02048       have_newline = TRUE;
02049       eol += 1; /* include newline */
02050     }
02051   else
02052     {
02053       eol = _dbus_string_get_length (source);
02054       have_newline = FALSE;
02055     }
02056 
02057   if (eol == 0)
02058     return FALSE; /* eof */
02059   
02060   if (!_dbus_string_move_len (source, 0, eol,
02061                               dest, 0))
02062     {
02063       return FALSE;
02064     }
02065 
02066   /* dump the newline and the \r if we have one */
02067   if (have_newline)
02068     {
02069       dbus_bool_t have_cr;
02070       
02071       _dbus_assert (_dbus_string_get_length (dest) > 0);
02072 
02073       if (_dbus_string_get_length (dest) > 1 &&
02074           _dbus_string_get_byte (dest,
02075                                  _dbus_string_get_length (dest) - 2) == '\r')
02076         have_cr = TRUE;
02077       else
02078         have_cr = FALSE;
02079         
02080       _dbus_string_set_length (dest,
02081                                _dbus_string_get_length (dest) -
02082                                (have_cr ? 2 : 1));
02083     }
02084   
02085   return TRUE;
02086 }
02087 
02094 void
02095 _dbus_string_delete_first_word (DBusString *str)
02096 {
02097   int i;
02098   
02099   if (_dbus_string_find_blank (str, 0, &i))
02100     _dbus_string_skip_blank (str, i, &i);
02101 
02102   _dbus_string_delete (str, 0, i);
02103 }
02104 
02110 void
02111 _dbus_string_delete_leading_blanks (DBusString *str)
02112 {
02113   int i;
02114   
02115   _dbus_string_skip_blank (str, 0, &i);
02116 
02117   if (i > 0)
02118     _dbus_string_delete (str, 0, i);
02119 }
02120 
02130 dbus_bool_t
02131 _dbus_string_equal (const DBusString *a,
02132                     const DBusString *b)
02133 {
02134   const unsigned char *ap;
02135   const unsigned char *bp;
02136   const unsigned char *a_end;
02137   const DBusRealString *real_a = (const DBusRealString*) a;
02138   const DBusRealString *real_b = (const DBusRealString*) b;
02139   DBUS_GENERIC_STRING_PREAMBLE (real_a);
02140   DBUS_GENERIC_STRING_PREAMBLE (real_b);
02141 
02142   if (real_a->len != real_b->len)
02143     return FALSE;
02144 
02145   ap = real_a->str;
02146   bp = real_b->str;
02147   a_end = real_a->str + real_a->len;
02148   while (ap != a_end)
02149     {
02150       if (*ap != *bp)
02151         return FALSE;
02152       
02153       ++ap;
02154       ++bp;
02155     }
02156 
02157   return TRUE;
02158 }
02159 
02173 dbus_bool_t
02174 _dbus_string_equal_len (const DBusString *a,
02175                         const DBusString *b,
02176                         int               len)
02177 {
02178   const unsigned char *ap;
02179   const unsigned char *bp;
02180   const unsigned char *a_end;
02181   const DBusRealString *real_a = (const DBusRealString*) a;
02182   const DBusRealString *real_b = (const DBusRealString*) b;
02183   DBUS_GENERIC_STRING_PREAMBLE (real_a);
02184   DBUS_GENERIC_STRING_PREAMBLE (real_b);
02185 
02186   if (real_a->len != real_b->len &&
02187       (real_a->len < len || real_b->len < len))
02188     return FALSE;
02189 
02190   ap = real_a->str;
02191   bp = real_b->str;
02192   a_end = real_a->str + MIN (real_a->len, len);
02193   while (ap != a_end)
02194     {
02195       if (*ap != *bp)
02196         return FALSE;
02197       
02198       ++ap;
02199       ++bp;
02200     }
02201 
02202   return TRUE;
02203 }
02204 
02221 dbus_bool_t
02222 _dbus_string_equal_substring (const DBusString  *a,
02223                               int                a_start,
02224                               int                a_len,
02225                               const DBusString  *b,
02226                               int                b_start)
02227 {
02228   const unsigned char *ap;
02229   const unsigned char *bp;
02230   const unsigned char *a_end;
02231   const DBusRealString *real_a = (const DBusRealString*) a;
02232   const DBusRealString *real_b = (const DBusRealString*) b;
02233   DBUS_GENERIC_STRING_PREAMBLE (real_a);
02234   DBUS_GENERIC_STRING_PREAMBLE (real_b);
02235   _dbus_assert (a_start >= 0);
02236   _dbus_assert (a_len >= 0);
02237   _dbus_assert (a_start <= real_a->len);
02238   _dbus_assert (a_len <= real_a->len - a_start);
02239   _dbus_assert (b_start >= 0);
02240   _dbus_assert (b_start <= real_b->len);
02241   
02242   if (a_len > real_b->len - b_start)
02243     return FALSE;
02244 
02245   ap = real_a->str + a_start;
02246   bp = real_b->str + b_start;
02247   a_end = ap + a_len;
02248   while (ap != a_end)
02249     {
02250       if (*ap != *bp)
02251         return FALSE;
02252       
02253       ++ap;
02254       ++bp;
02255     }
02256 
02257   _dbus_assert (bp <= (real_b->str + real_b->len));
02258   
02259   return TRUE;
02260 }
02261 
02269 dbus_bool_t
02270 _dbus_string_equal_c_str (const DBusString *a,
02271                           const char       *c_str)
02272 {
02273   const unsigned char *ap;
02274   const unsigned char *bp;
02275   const unsigned char *a_end;
02276   const DBusRealString *real_a = (const DBusRealString*) a;
02277   DBUS_GENERIC_STRING_PREAMBLE (real_a);
02278   _dbus_assert (c_str != NULL);
02279   
02280   ap = real_a->str;
02281   bp = (const unsigned char*) c_str;
02282   a_end = real_a->str + real_a->len;
02283   while (ap != a_end && *bp)
02284     {
02285       if (*ap != *bp)
02286         return FALSE;
02287       
02288       ++ap;
02289       ++bp;
02290     }
02291 
02292   if (ap != a_end || *bp)
02293     return FALSE;
02294   
02295   return TRUE;
02296 }
02297 
02305 dbus_bool_t
02306 _dbus_string_starts_with_c_str (const DBusString *a,
02307                                 const char       *c_str)
02308 {
02309   const unsigned char *ap;
02310   const unsigned char *bp;
02311   const unsigned char *a_end;
02312   const DBusRealString *real_a = (const DBusRealString*) a;
02313   DBUS_GENERIC_STRING_PREAMBLE (real_a);
02314   _dbus_assert (c_str != NULL);
02315   
02316   ap = real_a->str;
02317   bp = (const unsigned char*) c_str;
02318   a_end = real_a->str + real_a->len;
02319   while (ap != a_end && *bp)
02320     {
02321       if (*ap != *bp)
02322         return FALSE;
02323       
02324       ++ap;
02325       ++bp;
02326     }
02327 
02328   if (*bp == '\0')
02329     return TRUE;
02330   else
02331     return FALSE;
02332 }
02333 
02343 dbus_bool_t
02344 _dbus_string_ends_with_c_str (const DBusString *a,
02345                               const char       *c_str)
02346 {
02347   const unsigned char *ap;
02348   const unsigned char *bp;
02349   const unsigned char *a_end;
02350   unsigned long c_str_len;
02351   const DBusRealString *real_a = (const DBusRealString*) a;
02352   DBUS_GENERIC_STRING_PREAMBLE (real_a);
02353   _dbus_assert (c_str != NULL);
02354   
02355   c_str_len = strlen (c_str);
02356   if (((unsigned long)real_a->len) < c_str_len)
02357     return FALSE;
02358   
02359   ap = real_a->str + (real_a->len - c_str_len);
02360   bp = (const unsigned char*) c_str;
02361   a_end = real_a->str + real_a->len;
02362   while (ap != a_end)
02363     {
02364       if (*ap != *bp)
02365         return FALSE;
02366       
02367       ++ap;
02368       ++bp;
02369     }
02370 
02371   _dbus_assert (*ap == '\0');
02372   _dbus_assert (*bp == '\0');
02373   
02374   return TRUE;
02375 }
02376 
02387 dbus_bool_t
02388 _dbus_string_hex_encode (const DBusString *source,
02389                          int               start,
02390                          DBusString       *dest,
02391                          int               insert_at)
02392 {
02393   DBusString result;
02394   const char hexdigits[16] = {
02395     '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
02396     'a', 'b', 'c', 'd', 'e', 'f'
02397   };
02398   const unsigned char *p;
02399   const unsigned char *end;
02400   dbus_bool_t retval;
02401   
02402   _dbus_assert (start <= _dbus_string_get_length (source));
02403 
02404   if (!_dbus_string_init (&result))
02405     return FALSE;
02406 
02407   retval = FALSE;
02408   
02409   p = (const unsigned char*) _dbus_string_get_const_data (source);
02410   end = p + _dbus_string_get_length (source);
02411   p += start;
02412   
02413   while (p != end)
02414     {
02415       if (!_dbus_string_append_byte (&result,
02416                                      hexdigits[(*p >> 4)]))
02417         goto out;
02418       
02419       if (!_dbus_string_append_byte (&result,
02420                                      hexdigits[(*p & 0x0f)]))
02421         goto out;
02422 
02423       ++p;
02424     }
02425 
02426   if (!_dbus_string_move (&result, 0, dest, insert_at))
02427     goto out;
02428 
02429   retval = TRUE;
02430 
02431  out:
02432   _dbus_string_free (&result);
02433   return retval;
02434 }
02435 
02446 dbus_bool_t
02447 _dbus_string_hex_decode (const DBusString *source,
02448                          int               start,
02449                          int              *end_return,
02450                          DBusString       *dest,
02451                          int               insert_at)
02452 {
02453   DBusString result;
02454   const unsigned char *p;
02455   const unsigned char *end;
02456   dbus_bool_t retval;
02457   dbus_bool_t high_bits;
02458   
02459   _dbus_assert (start <= _dbus_string_get_length (source));
02460 
02461   if (!_dbus_string_init (&result))
02462     return FALSE;
02463 
02464   retval = FALSE;
02465 
02466   high_bits = TRUE;
02467   p = (const unsigned char*) _dbus_string_get_const_data (source);
02468   end = p + _dbus_string_get_length (source);
02469   p += start;
02470   
02471   while (p != end)
02472     {
02473       unsigned int val;
02474 
02475       switch (*p)
02476         {
02477         case '0':
02478           val = 0;
02479           break;
02480         case '1':
02481           val = 1;
02482           break;
02483         case '2':
02484           val = 2;
02485           break;
02486         case '3':
02487           val = 3;
02488           break;
02489         case '4':
02490           val = 4;
02491           break;
02492         case '5':
02493           val = 5;
02494           break;
02495         case '6':
02496           val = 6;
02497           break;
02498         case '7':
02499           val = 7;
02500           break;
02501         case '8':
02502           val = 8;
02503           break;
02504         case '9':
02505           val = 9;
02506           break;
02507         case 'a':
02508         case 'A':
02509           val = 10;
02510           break;
02511         case 'b':
02512         case 'B':
02513           val = 11;
02514           break;
02515         case 'c':
02516         case 'C':
02517           val = 12;
02518           break;
02519         case 'd':
02520         case 'D':
02521           val = 13;
02522           break;
02523         case 'e':
02524         case 'E':
02525           val = 14;
02526           break;
02527         case 'f':
02528         case 'F':
02529           val = 15;
02530           break;
02531         default:
02532           goto done;
02533         }
02534 
02535       if (high_bits)
02536         {
02537           if (!_dbus_string_append_byte (&result,
02538                                          val << 4))
02539             goto out;
02540         }
02541       else
02542         {
02543           int len;
02544           unsigned char b;
02545 
02546           len = _dbus_string_get_length (&result);
02547           
02548           b = _dbus_string_get_byte (&result, len - 1);
02549 
02550           b |= val;
02551 
02552           _dbus_string_set_byte (&result, len - 1, b);
02553         }
02554 
02555       high_bits = !high_bits;
02556 
02557       ++p;
02558     }
02559 
02560  done:
02561   if (!_dbus_string_move (&result, 0, dest, insert_at))
02562     goto out;
02563 
02564   if (end_return)
02565     *end_return = p - (const unsigned char*) _dbus_string_get_const_data (source);
02566 
02567   retval = TRUE;
02568   
02569  out:
02570   _dbus_string_free (&result);  
02571   return retval;
02572 }
02573 
02587 dbus_bool_t
02588 _dbus_string_validate_ascii (const DBusString *str,
02589                              int               start,
02590                              int               len)
02591 {
02592   const unsigned char *s;
02593   const unsigned char *end;
02594   DBUS_CONST_STRING_PREAMBLE (str);
02595   _dbus_assert (start >= 0);
02596   _dbus_assert (start <= real->len);
02597   _dbus_assert (len >= 0);
02598   
02599   if (len > real->len - start)
02600     return FALSE;
02601   
02602   s = real->str + start;
02603   end = s + len;
02604   while (s != end)
02605     {
02606       if (_DBUS_UNLIKELY (!_DBUS_ISASCII (*s)))
02607         return FALSE;
02608         
02609       ++s;
02610     }
02611   
02612   return TRUE;
02613 }
02614 
02630 dbus_bool_t
02631 _dbus_string_validate_utf8  (const DBusString *str,
02632                              int               start,
02633                              int               len)
02634 {
02635   const unsigned char *p;
02636   const unsigned char *end;
02637   DBUS_CONST_STRING_PREAMBLE (str);
02638   _dbus_assert (start >= 0);
02639   _dbus_assert (start <= real->len);
02640   _dbus_assert (len >= 0);
02641 
02642   /* we are doing _DBUS_UNLIKELY() here which might be
02643    * dubious in a generic library like GLib, but in D-BUS
02644    * we know we're validating messages and that it would
02645    * only be evil/broken apps that would have invalid
02646    * UTF-8. Also, this function seems to be a performance
02647    * bottleneck in profiles.
02648    */
02649   
02650   if (_DBUS_UNLIKELY (len > real->len - start))
02651     return FALSE;
02652   
02653   p = real->str + start;
02654   end = p + len;
02655   
02656   while (p < end)
02657     {
02658       int i, mask, char_len;
02659       dbus_unichar_t result;
02660 
02661       /* nul bytes considered invalid */
02662       if (*p == '\0')
02663         break;
02664       
02665       /* Special-case ASCII; this makes us go a lot faster in
02666        * D-BUS profiles where we are typically validating
02667        * function names and such. We have to know that
02668        * all following checks will pass for ASCII though,
02669        * comments follow ...
02670        */      
02671       if (*p < 128)
02672         {
02673           ++p;
02674           continue;
02675         }
02676       
02677       UTF8_COMPUTE (*p, mask, char_len);
02678 
02679       if (_DBUS_UNLIKELY (char_len == 0))  /* ASCII: char_len == 1 */
02680         break;
02681 
02682       /* check that the expected number of bytes exists in the remaining length */
02683       if (_DBUS_UNLIKELY ((end - p) < char_len)) /* ASCII: p < end and char_len == 1 */
02684         break;
02685         
02686       UTF8_GET (result, p, i, mask, char_len);
02687 
02688       /* Check for overlong UTF-8 */
02689       if (_DBUS_UNLIKELY (UTF8_LENGTH (result) != char_len)) /* ASCII: UTF8_LENGTH == 1 */
02690         break;
02691 #if 0
02692       /* The UNICODE_VALID check below will catch this */
02693       if (_DBUS_UNLIKELY (result == (dbus_unichar_t)-1)) /* ASCII: result = ascii value */
02694         break;
02695 #endif
02696 
02697       if (_DBUS_UNLIKELY (!UNICODE_VALID (result))) /* ASCII: always valid */
02698         break;
02699 
02700       /* UNICODE_VALID should have caught it */
02701       _dbus_assert (result != (dbus_unichar_t)-1);
02702       
02703       p += char_len;
02704     }
02705 
02706   /* See that we covered the entire length if a length was
02707    * passed in
02708    */
02709   if (_DBUS_UNLIKELY (p != end))
02710     return FALSE;
02711   else
02712     return TRUE;
02713 }
02714 
02728 dbus_bool_t
02729 _dbus_string_validate_nul (const DBusString *str,
02730                            int               start,
02731                            int               len)
02732 {
02733   const unsigned char *s;
02734   const unsigned char *end;
02735   DBUS_CONST_STRING_PREAMBLE (str);
02736   _dbus_assert (start >= 0);
02737   _dbus_assert (len >= 0);
02738   _dbus_assert (start <= real->len);
02739   
02740   if (len > real->len - start)
02741     return FALSE;
02742   
02743   s = real->str + start;
02744   end = s + len;
02745   while (s != end)
02746     {
02747       if (_DBUS_UNLIKELY (*s != '\0'))
02748         return FALSE;
02749       ++s;
02750     }
02751   
02752   return TRUE;
02753 }
02754 
02772 dbus_bool_t
02773 _dbus_string_validate_path (const DBusString  *str,
02774                             int                start,
02775                             int                len)
02776 {
02777   const unsigned char *s;
02778   const unsigned char *end;
02779   const unsigned char *last_slash;
02780   
02781   DBUS_CONST_STRING_PREAMBLE (str);
02782   _dbus_assert (start >= 0);
02783   _dbus_assert (len >= 0);
02784   _dbus_assert (start <= real->len);
02785   
02786   if (len > real->len - start)
02787     return FALSE;
02788 
02789   if (len > DBUS_MAXIMUM_NAME_LENGTH)
02790     return FALSE;
02791 
02792   if (len == 0)
02793     return FALSE;
02794 
02795   s = real->str + start;
02796   end = s + len;
02797 
02798   if (*s != '/')
02799     return FALSE;
02800   last_slash = s;
02801   ++s;
02802   
02803   while (s != end)
02804     {
02805       if (*s == '/')
02806         {
02807           if ((s - last_slash) < 2)
02808             return FALSE; /* no empty path components allowed */
02809 
02810           last_slash = s;
02811         }
02812       
02813       ++s;
02814     }
02815 
02816   if ((end - last_slash) < 2 &&
02817       len > 1)
02818     return FALSE; /* trailing slash not allowed unless the string is "/" */
02819   
02820   return TRUE;
02821 }
02822 
02827 #define VALID_INITIAL_NAME_CHARACTER(c)         \
02828   ( ((c) >= 'A' && (c) <= 'Z') ||               \
02829     ((c) >= 'a' && (c) <= 'z') ||               \
02830     ((c) == '_') )
02831 
02836 #define VALID_NAME_CHARACTER(c)                 \
02837   ( ((c) >= '0' && (c) <= '9') ||               \
02838     ((c) >= 'A' && (c) <= 'Z') ||               \
02839     ((c) >= 'a' && (c) <= 'z') ||               \
02840     ((c) == '_') )
02841 
02855 dbus_bool_t
02856 _dbus_string_validate_interface (const DBusString  *str,
02857                                  int                start,
02858                                  int                len)
02859 {  
02860   const unsigned char *s;
02861   const unsigned char *end;
02862   const unsigned char *iface;
02863   const unsigned char *last_dot;
02864   
02865   DBUS_CONST_STRING_PREAMBLE (str);
02866   _dbus_assert (start >= 0);
02867   _dbus_assert (len >= 0);
02868   _dbus_assert (start <= real->len);
02869   
02870   if (len > real->len - start)
02871     return FALSE;
02872 
02873   if (len > DBUS_MAXIMUM_NAME_LENGTH)
02874     return FALSE;
02875 
02876   if (len == 0)
02877     return FALSE;
02878 
02879   last_dot = NULL;
02880   iface = real->str + start;
02881   end = iface + len;
02882   s = iface;
02883 
02884   /* check special cases of first char so it doesn't have to be done
02885    * in the loop. Note we know len > 0
02886    */
02887   if (_DBUS_UNLIKELY (*s == '.')) /* disallow starting with a . */
02888     return FALSE;
02889   else if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*s)))
02890     return FALSE;
02891   else
02892     ++s;
02893   
02894   while (s != end)
02895     {
02896       if (*s == '.')
02897         {
02898           if (_DBUS_UNLIKELY ((s + 1) == end))
02899             return FALSE;
02900           else if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*(s + 1))))
02901             return FALSE;
02902           last_dot = s;
02903           ++s; /* we just validated the next char, so skip two */
02904         }
02905       else if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s)))
02906         {
02907           return FALSE;
02908         }
02909       
02910       ++s;
02911     }
02912 
02913   if (_DBUS_UNLIKELY (last_dot == NULL))
02914     return FALSE;
02915   
02916   return TRUE;
02917 }
02918 
02932 dbus_bool_t
02933 _dbus_string_validate_member (const DBusString  *str,
02934                               int                start,
02935                               int                len)
02936 {
02937   const unsigned char *s;
02938   const unsigned char *end;
02939   const unsigned char *member;
02940   
02941   DBUS_CONST_STRING_PREAMBLE (str);
02942   _dbus_assert (start >= 0);
02943   _dbus_assert (len >= 0);
02944   _dbus_assert (start <= real->len);
02945   
02946   if (len > real->len - start)
02947     return FALSE;
02948 
02949   if (len > DBUS_MAXIMUM_NAME_LENGTH)
02950     return FALSE;
02951 
02952   if (len == 0)
02953     return FALSE;
02954 
02955   member = real->str + start;
02956   end = member + len;
02957   s = member;
02958 
02959   /* check special cases of first char so it doesn't have to be done
02960    * in the loop. Note we know len > 0
02961    */
02962 
02963   if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*s)))
02964     return FALSE;
02965   else
02966     ++s;
02967   
02968   while (s != end)
02969     {
02970       if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s)))
02971         {
02972           return FALSE;
02973         }
02974       
02975       ++s;
02976     }
02977   
02978   return TRUE;
02979 }
02980 
02994 dbus_bool_t
02995 _dbus_string_validate_error_name (const DBusString  *str,
02996                                   int                start,
02997                                   int                len)
02998 {
02999   /* Same restrictions as interface name at the moment */
03000   return _dbus_string_validate_interface (str, start, len);
03001 }
03002 
03003 /* This assumes the first char exists and is ':' */
03004 static dbus_bool_t
03005 _dbus_string_validate_base_service (const DBusString  *str,
03006                                     int                start,
03007                                     int                len)
03008 {
03009   const unsigned char *s;
03010   const unsigned char *end;
03011   const unsigned char *service;
03012   
03013   DBUS_CONST_STRING_PREAMBLE (str);
03014   _dbus_assert (start >= 0);
03015   _dbus_assert (len >= 0);
03016   _dbus_assert (start <= real->len);
03017   
03018   if (len > real->len - start)
03019     return FALSE;
03020 
03021   if (len > DBUS_MAXIMUM_NAME_LENGTH)
03022     return FALSE;
03023 
03024   _dbus_assert (len > 0);
03025 
03026   service = real->str + start;
03027   end = service + len;
03028   _dbus_assert (*service == ':');
03029   s = service + 1;
03030   
03031   while (s != end)
03032     {
03033       if (*s == '.')
03034         {
03035           if (_DBUS_UNLIKELY ((s + 1) == end))
03036             return FALSE;
03037           if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*(s + 1))))
03038             return FALSE;
03039           ++s; /* we just validated the next char, so skip two */
03040         }
03041       else if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s)))
03042         {
03043           return FALSE;
03044         }
03045       
03046       ++s;
03047     }
03048   
03049   return TRUE;
03050 }
03051 
03065 dbus_bool_t
03066 _dbus_string_validate_service (const DBusString  *str,
03067                                int                start,
03068                                int                len)
03069 {
03070   if (_DBUS_UNLIKELY (len == 0))
03071     return FALSE;
03072   if (_dbus_string_get_byte (str, start) == ':')
03073     return _dbus_string_validate_base_service (str, start, len);
03074   else
03075     return _dbus_string_validate_interface (str, start, len);
03076 }
03077 
03090 dbus_bool_t
03091 _dbus_string_validate_signature (const DBusString  *str,
03092                                  int                start,
03093                                  int                len)
03094 {
03095   const unsigned char *s;
03096   const unsigned char *end;
03097   DBUS_CONST_STRING_PREAMBLE (str);
03098   _dbus_assert (start >= 0);
03099   _dbus_assert (start <= real->len);
03100   _dbus_assert (len >= 0);
03101   
03102   if (len > real->len - start)
03103     return FALSE;
03104   
03105   s = real->str + start;
03106   end = s + len;
03107   while (s != end)
03108     {
03109       switch (*s)
03110         {
03111         case DBUS_TYPE_NIL:
03112         case DBUS_TYPE_BYTE:
03113         case DBUS_TYPE_BOOLEAN:
03114         case DBUS_TYPE_INT32:
03115         case DBUS_TYPE_UINT32:
03116         case DBUS_TYPE_INT64:
03117         case DBUS_TYPE_UINT64:
03118         case DBUS_TYPE_DOUBLE:
03119         case DBUS_TYPE_STRING:
03120         case DBUS_TYPE_CUSTOM:
03121         case DBUS_TYPE_ARRAY:
03122         case DBUS_TYPE_DICT:
03123         case DBUS_TYPE_OBJECT_PATH:
03124           break;
03125           
03126         default:
03127           return FALSE;
03128         }
03129       
03130       ++s;
03131     }
03132   
03133   return TRUE;
03134 }
03135 
03141 void
03142 _dbus_string_zero (DBusString *str)
03143 {
03144   DBUS_STRING_PREAMBLE (str);
03145 
03146   memset (real->str - real->align_offset, '\0', real->allocated);
03147 }
03150 #ifdef DBUS_BUILD_TESTS
03151 #include "dbus-test.h"
03152 #include <stdio.h>
03153 
03167 dbus_bool_t
03168 _dbus_string_parse_basic_type (const DBusString  *str,
03169                                char               type,
03170                                int                start,
03171                                void              *value,
03172                                int               *end_return)
03173 {
03174   int end = start;
03175 
03176   switch (type)
03177     {
03178     case DBUS_TYPE_BOOLEAN:
03179       {
03180         int len = _dbus_string_get_length (str) - start;
03181         if (len >= 5 && _dbus_string_find_to (str, start, start + 5, "false", NULL))
03182           {
03183             end += 5;
03184             *(unsigned char *) value = TRUE;
03185           }
03186         else if (len >= 4 && _dbus_string_find_to (str, start, start + 4, "true", NULL))
03187           {
03188             end += 4;
03189             *(unsigned char *) value = FALSE;
03190           }
03191         else
03192           _dbus_warn ("could not parse BOOLEAN\n");
03193         break;
03194       }
03195     case DBUS_TYPE_BYTE:
03196       {
03197         long val = 0;
03198 
03199         if (_dbus_string_get_byte (str, start) == '\'' &&
03200             _dbus_string_get_length (str) >= start + 4 &&
03201             _dbus_string_get_byte (str, start + 1) == '\\' &&
03202             _dbus_string_get_byte (str, start + 2) == '\'' &&
03203             _dbus_string_get_byte (str, start + 3) == '\'')
03204           {
03205             val = '\'';
03206             end += 4;
03207           }
03208         else if (_dbus_string_get_byte (str, start) == '\'' &&
03209                  _dbus_string_get_length (str) >= start + 3 &&
03210                  _dbus_string_get_byte (str, start + 2) == '\'')
03211           {
03212             val = _dbus_string_get_byte (str, start + 1);
03213             end += 3;
03214           }
03215         else
03216           {
03217             if (!_dbus_string_parse_int (str, start, &val, &end)) 
03218               _dbus_warn ("Failed to parse integer for BYTE\n");
03219           }
03220 
03221         if (val > 255)
03222           _dbus_warn ("A byte must be in range 0-255 not %ld\n", val);
03223 
03224         *(unsigned char *) value = val;
03225         break;
03226       }
03227     case DBUS_TYPE_INT32:
03228       {
03229         long val;
03230         if (_dbus_string_parse_int (str, start, &val, &end))
03231           *(dbus_int32_t *)value = val;
03232         break;
03233       }
03234     case DBUS_TYPE_UINT32:
03235       {
03236         unsigned long val;
03237         if (_dbus_string_parse_uint (str, start, &val, &end))
03238           *(dbus_uint32_t *)value = val;
03239         break;
03240       }
03241 #ifdef DBUS_HAVE_INT64
03242     case DBUS_TYPE_INT64:
03243     case DBUS_TYPE_UINT64: 
03244       /* use stroll oull */
03245       _dbus_assert_not_reached ("string -> [u]int64 not supported yet");
03246       break;
03247 #endif /* DBUS_HAVE_INT64 */
03248     case DBUS_TYPE_DOUBLE:
03249       _dbus_string_parse_double (str, start, value, &end);
03250       break;
03251     default:
03252       _dbus_assert_not_reached ("not a basic type");
03253       break;
03254     }
03255   if (end_return)
03256     *end_return = end;
03257 
03258   return end != start;
03259 }
03260 
03261 static void
03262 test_max_len (DBusString *str,
03263               int         max_len)
03264 {
03265   if (max_len > 0)
03266     {
03267       if (!_dbus_string_set_length (str, max_len - 1))
03268         _dbus_assert_not_reached ("setting len to one less than max should have worked");
03269     }
03270 
03271   if (!_dbus_string_set_length (str, max_len))
03272     _dbus_assert_not_reached ("setting len to max len should have worked");
03273 
03274   if (_dbus_string_set_length (str, max_len + 1))
03275     _dbus_assert_not_reached ("setting len to one more than max len should not have worked");
03276 
03277   if (!_dbus_string_set_length (str, 0))
03278     _dbus_assert_not_reached ("setting len to zero should have worked");
03279 }
03280 
03281 static void
03282 test_hex_roundtrip (const unsigned char *data,
03283                     int                  len)
03284 {
03285   DBusString orig;
03286   DBusString encoded;
03287   DBusString decoded;
03288   int end;
03289 
03290   if (len < 0)
03291     len = strlen (data);
03292   
03293   if (!_dbus_string_init (&orig))
03294     _dbus_assert_not_reached ("could not init string");
03295 
03296   if (!_dbus_string_init (&encoded))
03297     _dbus_assert_not_reached ("could not init string");
03298   
03299   if (!_dbus_string_init (&decoded))
03300     _dbus_assert_not_reached ("could not init string");
03301 
03302   if (!_dbus_string_append_len (&orig, data, len))
03303     _dbus_assert_not_reached ("couldn't append orig data");
03304 
03305   if (!_dbus_string_hex_encode (&orig, 0, &encoded, 0))
03306     _dbus_assert_not_reached ("could not encode");
03307 
03308   if (!_dbus_string_hex_decode (&encoded, 0, &end, &decoded, 0))
03309     _dbus_assert_not_reached ("could not decode");
03310     
03311   _dbus_assert (_dbus_string_get_length (&encoded) == end);
03312 
03313   if (!_dbus_string_equal (&orig, &decoded))
03314     {
03315       const char *s;
03316       
03317       printf ("Original string %d bytes encoded %d bytes decoded %d bytes\n",
03318               _dbus_string_get_length (&orig),
03319               _dbus_string_get_length (&encoded),
03320               _dbus_string_get_length (&decoded));
03321       printf ("Original: %s\n", data);
03322       s = _dbus_string_get_const_data (&decoded);
03323       printf ("Decoded: %s\n", s);
03324       _dbus_assert_not_reached ("original string not the same as string decoded from hex");
03325     }
03326   
03327   _dbus_string_free (&orig);
03328   _dbus_string_free (&encoded);
03329   _dbus_string_free (&decoded);  
03330 }
03331 
03332 typedef void (* TestRoundtripFunc) (const unsigned char *data,
03333                                     int                  len);
03334 static void
03335 test_roundtrips (TestRoundtripFunc func)
03336 {
03337   (* func) ("Hello this is a string\n", -1);
03338   (* func) ("Hello this is a string\n1", -1);
03339   (* func) ("Hello this is a string\n12", -1);
03340   (* func) ("Hello this is a string\n123", -1);
03341   (* func) ("Hello this is a string\n1234", -1);
03342   (* func) ("Hello this is a string\n12345", -1);
03343   (* func) ("", 0);
03344   (* func) ("1", 1);
03345   (* func) ("12", 2);
03346   (* func) ("123", 3);
03347   (* func) ("1234", 4);
03348   (* func) ("12345", 5);
03349   (* func) ("", 1);
03350   (* func) ("1", 2);
03351   (* func) ("12", 3);
03352   (* func) ("123", 4);
03353   (* func) ("1234", 5);
03354   (* func) ("12345", 6);
03355   {
03356     unsigned char buf[512];
03357     int i;
03358     
03359     i = 0;
03360     while (i < _DBUS_N_ELEMENTS (buf))
03361       {
03362         buf[i] = i;
03363         ++i;
03364       }
03365     i = 0;
03366     while (i < _DBUS_N_ELEMENTS (buf))
03367       {
03368         (* func) (buf, i);
03369         ++i;
03370       }
03371   }
03372 }
03373 
03374 
03385 dbus_bool_t
03386 _dbus_string_test (void)
03387 {
03388   DBusString str;
03389   DBusString other;
03390   int i, end;
03391   long v;
03392   double d;
03393   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 };
03394   char *s;
03395   dbus_unichar_t ch;
03396   const char *valid_paths[] = {
03397     "/",
03398     "/foo/bar",
03399     "/foo",
03400     "/foo/bar/baz"
03401   };
03402   const char *invalid_paths[] = {
03403     "bar",
03404     "bar/baz",
03405     "/foo/bar/",
03406     "/foo/"
03407     "foo/",
03408     "boo//blah",
03409     "//",
03410     "
03411     "foo
03412     "Hello World",
03413     "",
03414     "   ",
03415     "foo bar"
03416   };
03417 
03418   const char *valid_interfaces[] = {
03419     "org.freedesktop.Foo",
03420     "Bar.Baz",
03421     "Blah.Blah.Blah.Blah.Blah",
03422     "a.b",
03423     "a.b.c.d.e.f.g",
03424     "a0.b1.c2.d3.e4.f5.g6",
03425     "abc123.foo27"
03426   };
03427   const char *invalid_interfaces[] = {
03428     ".",
03429     "",
03430     "..",
03431     ".Foo.Bar",
03432     "..Foo.Bar",
03433     "Foo.Bar.",
03434     "Foo.Bar..",
03435     "Foo",
03436     "9foo.bar.baz",
03437     "foo.bar..baz",
03438     "foo.bar...baz",
03439     "foo.bar.b..blah",
03440     ":",
03441     ":0-1",
03442     "10",
03443     ":11.34324",
03444     "0.0.0",
03445     "0..0",
03446     "foo.Bar.%",
03447     "foo.Bar!!",
03448     "!Foo.bar.bz",
03449     "foo.$.blah",
03450     "",
03451     "   ",
03452     "foo bar"
03453   };
03454 
03455   const char *valid_base_services[] = {
03456     ":0",
03457     ":a",
03458     ":",
03459     ":.a",
03460     ":.1",
03461     ":0.1",
03462     ":000.2222",
03463     ":.blah",
03464     ":abce.freedesktop.blah"
03465   };
03466   const char *invalid_base_services[] = {
03467     ":-",
03468     ":!",
03469     ":0-10",
03470     ":blah.",
03471     ":blah.",
03472     ":blah..org",
03473     ":blah.org..",
03474     ":..blah.org",
03475     "",
03476     "   ",
03477     "foo bar"
03478   };
03479 
03480   const char *valid_members[] = {
03481     "Hello",
03482     "Bar",
03483     "foobar",
03484     "_foobar",
03485     "foo89"
03486   };
03487 
03488   const char *invalid_members[] = {
03489     "9Hello",
03490     "10",
03491     "1",
03492     "foo-bar",
03493     "blah.org",
03494     ".blah",
03495     "blah.",
03496     "Hello.",
03497     "!foo",
03498     "",
03499     "   ",
03500     "foo bar"
03501   };
03502 
03503   const char *valid_signatures[] = {
03504     "",
03505     "sss",
03506     "i",
03507     "b"
03508   };
03509 
03510   const char *invalid_signatures[] = {
03511     " ",
03512     "not a valid signature",
03513     "123",
03514     ".",
03515     "("
03516   };
03517   
03518   i = 0;
03519   while (i < _DBUS_N_ELEMENTS (lens))
03520     {
03521       if (!_dbus_string_init (&str))
03522         _dbus_assert_not_reached ("failed to init string");
03523 
03524       set_max_length (&str, lens[i]);
03525       
03526       test_max_len (&str, lens[i]);
03527       _dbus_string_free (&str);
03528 
03529       ++i;
03530     }
03531 
03532   /* Test shortening and setting length */
03533   i = 0;
03534   while (i < _DBUS_N_ELEMENTS (lens))
03535     {
03536       int j;
03537       
03538       if (!_dbus_string_init (&str))
03539         _dbus_assert_not_reached ("failed to init string");
03540 
03541       set_max_length (&str, lens[i]);
03542       
03543       if (!_dbus_string_set_length (&str, lens[i]))
03544         _dbus_assert_not_reached ("failed to set string length");
03545 
03546       j = lens[i];
03547       while (j > 0)
03548         {
03549           _dbus_assert (_dbus_string_get_length (&str) == j);
03550           if (j > 0)
03551             {
03552               _dbus_string_shorten (&str, 1);
03553               _dbus_assert (_dbus_string_get_length (&str) == (j - 1));
03554             }
03555           --j;
03556         }
03557       
03558       _dbus_string_free (&str);
03559 
03560       ++i;
03561     }
03562 
03563   /* Test appending data */
03564   if (!_dbus_string_init (&str))
03565     _dbus_assert_not_reached ("failed to init string");
03566 
03567   i = 0;
03568   while (i < 10)
03569     {
03570       if (!_dbus_string_append (&str, "a"))
03571         _dbus_assert_not_reached ("failed to append string to string\n");
03572 
03573       _dbus_assert (_dbus_string_get_length (&str) == i * 2 + 1);
03574 
03575       if (!_dbus_string_append_byte (&str, 'b'))
03576         _dbus_assert_not_reached ("failed to append byte to string\n");
03577 
03578       _dbus_assert (_dbus_string_get_length (&str) == i * 2 + 2);
03579                     
03580       ++i;
03581     }
03582 
03583   _dbus_string_free (&str);
03584 
03585   /* Check steal_data */
03586   
03587   if (!_dbus_string_init (&str))
03588     _dbus_assert_not_reached ("failed to init string");
03589 
03590   if (!_dbus_string_append (&str, "Hello World"))
03591     _dbus_assert_not_reached ("could not append to string");
03592 
03593   i = _dbus_string_get_length (&str);
03594   
03595   if (!_dbus_string_steal_data (&str, &s))
03596     _dbus_assert_not_reached ("failed to steal data");
03597 
03598   _dbus_assert (_dbus_string_get_length (&str) == 0);
03599   _dbus_assert (((int)strlen (s)) == i);
03600 
03601   dbus_free (s);
03602 
03603   /* Check move */
03604   
03605   if (!_dbus_string_append (&str, "Hello World"))
03606     _dbus_assert_not_reached ("could not append to string");
03607 
03608   i = _dbus_string_get_length (&str);
03609 
03610   if (!_dbus_string_init (&other))
03611     _dbus_assert_not_reached ("could not init string");
03612   
03613   if (!_dbus_string_move (&str, 0, &other, 0))
03614     _dbus_assert_not_reached ("could not move");
03615 
03616   _dbus_assert (_dbus_string_get_length (&str) == 0);
03617   _dbus_assert (_dbus_string_get_length (&other) == i);
03618 
03619   if (!_dbus_string_append (&str, "Hello World"))
03620     _dbus_assert_not_reached ("could not append to string");
03621   
03622   if (!_dbus_string_move (&str, 0, &other, _dbus_string_get_length (&other)))
03623     _dbus_assert_not_reached ("could not move");
03624 
03625   _dbus_assert (_dbus_string_get_length (&str) == 0);
03626   _dbus_assert (_dbus_string_get_length (&other) == i * 2);
03627 
03628     if (!_dbus_string_append (&str, "Hello World"))
03629     _dbus_assert_not_reached ("could not append to string");
03630   
03631   if (!_dbus_string_move (&str, 0, &other, _dbus_string_get_length (&other) / 2))
03632     _dbus_assert_not_reached ("could not move");
03633 
03634   _dbus_assert (_dbus_string_get_length (&str) == 0);
03635   _dbus_assert (_dbus_string_get_length (&other) == i * 3);
03636   
03637   _dbus_string_free (&other);
03638 
03639   /* Check copy */
03640   
03641   if (!_dbus_string_append (&str, "Hello World"))
03642     _dbus_assert_not_reached ("could not append to string");
03643 
03644   i = _dbus_string_get_length (&str);
03645   
03646   if (!_dbus_string_init (&other))
03647     _dbus_assert_not_reached ("could not init string");
03648   
03649   if (!_dbus_string_copy (&str, 0, &other, 0))
03650     _dbus_assert_not_reached ("could not copy");
03651 
03652   _dbus_assert (_dbus_string_get_length (&str) == i);
03653   _dbus_assert (_dbus_string_get_length (&other) == i);
03654 
03655   if (!_dbus_string_copy (&str, 0, &other, _dbus_string_get_length (&other)))
03656     _dbus_assert_not_reached ("could not copy");
03657 
03658   _dbus_assert (_dbus_string_get_length (&str) == i);
03659   _dbus_assert (_dbus_string_get_length (&other) == i * 2);
03660   _dbus_assert (_dbus_string_equal_c_str (&other,
03661                                           "Hello WorldHello World"));
03662 
03663   if (!_dbus_string_copy (&str, 0, &other, _dbus_string_get_length (&other) / 2))
03664     _dbus_assert_not_reached ("could not copy");
03665 
03666   _dbus_assert (_dbus_string_get_length (&str) == i);
03667   _dbus_assert (_dbus_string_get_length (&other) == i * 3);
03668   _dbus_assert (_dbus_string_equal_c_str (&other,
03669                                           "Hello WorldHello WorldHello World"));
03670   
03671   _dbus_string_free (&str);
03672   _dbus_string_free (&other);
03673 
03674   /* Check replace */
03675 
03676   if (!_dbus_string_init (&str))
03677     _dbus_assert_not_reached ("failed to init string");
03678   
03679   if (!_dbus_string_append (&str, "Hello World"))
03680     _dbus_assert_not_reached ("could not append to string");
03681 
03682   i = _dbus_string_get_length (&str);
03683   
03684   if (!_dbus_string_init (&other))
03685     _dbus_assert_not_reached ("could not init string");
03686   
03687   if (!_dbus_string_replace_len (&str, 0, _dbus_string_get_length (&str),
03688                                  &other, 0, _dbus_string_get_length (&other)))
03689     _dbus_assert_not_reached ("could not replace");
03690 
03691   _dbus_assert (_dbus_string_get_length (&str) == i);
03692   _dbus_assert (_dbus_string_get_length (&other) == i);
03693   _dbus_assert (_dbus_string_equal_c_str (&other, "Hello World"));
03694   
03695   if (!_dbus_string_replace_len (&str, 0, _dbus_string_get_length (&str),
03696                                  &other, 5, 1))
03697     _dbus_assert_not_reached ("could not replace center space");
03698 
03699   _dbus_assert (_dbus_string_get_length (&str) == i);
03700   _dbus_assert (_dbus_string_get_length (&other) == i * 2 - 1);
03701   _dbus_assert (_dbus_string_equal_c_str (&other,
03702                                           "HelloHello WorldWorld"));
03703 
03704   
03705   if (!_dbus_string_replace_len (&str, 1, 1,
03706                                  &other,
03707                                  _dbus_string_get_length (&other) - 1,
03708                                  1))
03709     _dbus_assert_not_reached ("could not replace end character");
03710   
03711   _dbus_assert (_dbus_string_get_length (&str) == i);
03712   _dbus_assert (_dbus_string_get_length (&other) == i * 2 - 1);
03713   _dbus_assert (_dbus_string_equal_c_str (&other,
03714                                           "HelloHello WorldWorle"));
03715   
03716   _dbus_string_free (&str);
03717   _dbus_string_free (&other);
03718   
03719   /* Check append/get unichar */
03720   
03721   if (!_dbus_string_init (&str))
03722     _dbus_assert_not_reached ("failed to init string");
03723 
03724   ch = 0;
03725   if (!_dbus_string_append_unichar (&str, 0xfffc))
03726     _dbus_assert_not_reached ("failed to append unichar");
03727 
03728   _dbus_string_get_unichar (&str, 0, &ch, &i);
03729 
03730   _dbus_assert (ch == 0xfffc);
03731   _dbus_assert (i == _dbus_string_get_length (&str));
03732 
03733   _dbus_string_free (&str);
03734 
03735   /* Check insert/set/get byte */
03736   
03737   if (!_dbus_string_init (&str))
03738     _dbus_assert_not_reached ("failed to init string");
03739 
03740   if (!_dbus_string_append (&str, "Hello"))
03741     _dbus_assert_not_reached ("failed to append Hello");
03742 
03743   _dbus_assert (_dbus_string_get_byte (&str, 0) == 'H');
03744   _dbus_assert (_dbus_string_get_byte (&str, 1) == 'e');
03745   _dbus_assert (_dbus_string_get_byte (&str, 2) == 'l');
03746   _dbus_assert (_dbus_string_get_byte (&str, 3) == 'l');
03747   _dbus_assert (_dbus_string_get_byte (&str, 4) == 'o');
03748 
03749   _dbus_string_set_byte (&str, 1, 'q');
03750   _dbus_assert (_dbus_string_get_byte (&str, 1) == 'q');
03751 
03752   if (!_dbus_string_insert_bytes (&str, 0, 1, 255))
03753     _dbus_assert_not_reached ("can't insert byte");
03754 
03755   if (!_dbus_string_insert_bytes (&str, 2, 4, 'Z'))
03756     _dbus_assert_not_reached ("can't insert byte");
03757 
03758   if (!_dbus_string_insert_bytes (&str, _dbus_string_get_length (&str), 1, 'W'))
03759     _dbus_assert_not_reached ("can't insert byte");
03760   
03761   _dbus_assert (_dbus_string_get_byte (&str, 0) == 255);
03762   _dbus_assert (_dbus_string_get_byte (&str, 1) == 'H');
03763   _dbus_assert (_dbus_string_get_byte (&str, 2) == 'Z');
03764   _dbus_assert (_dbus_string_get_byte (&str, 3) == 'Z');
03765   _dbus_assert (_dbus_string_get_byte (&str, 4) == 'Z');
03766   _dbus_assert (_dbus_string_get_byte (&str, 5) == 'Z');
03767   _dbus_assert (_dbus_string_get_byte (&str, 6) == 'q');
03768   _dbus_assert (_dbus_string_get_byte (&str, 7) == 'l');
03769   _dbus_assert (_dbus_string_get_byte (&str, 8) == 'l');
03770   _dbus_assert (_dbus_string_get_byte (&str, 9) == 'o');
03771   _dbus_assert (_dbus_string_get_byte (&str, 10) == 'W');
03772 
03773   _dbus_string_free (&str);
03774   
03775   /* Check append/parse int/double */
03776   
03777   if (!_dbus_string_init (&str))
03778     _dbus_assert_not_reached ("failed to init string");
03779 
03780   if (!_dbus_string_append_int (&str, 27))
03781     _dbus_assert_not_reached ("failed to append int");
03782 
03783   i = _dbus_string_get_length (&str);
03784 
03785   if (!_dbus_string_parse_int (&str, 0, &v, &end))
03786     _dbus_assert_not_reached ("failed to parse int");
03787 
03788   _dbus_assert (v == 27);
03789   _dbus_assert (end == i);
03790 
03791   _dbus_string_free (&str);
03792   
03793   if (!_dbus_string_init (&str))
03794     _dbus_assert_not_reached ("failed to init string");
03795   
03796   if (!_dbus_string_append_double (&str, 50.3))
03797     _dbus_assert_not_reached ("failed to append float");
03798 
03799   i = _dbus_string_get_length (&str);
03800 
03801   if (!_dbus_string_parse_double (&str, 0, &d, &end))
03802     _dbus_assert_not_reached ("failed to parse float");
03803 
03804   _dbus_assert (d > (50.3 - 1e-6) && d < (50.3 + 1e-6));
03805   _dbus_assert (end == i);
03806 
03807   _dbus_string_free (&str);
03808 
03809   /* Test find */
03810   if (!_dbus_string_init (&str))
03811     _dbus_assert_not_reached ("failed to init string");
03812 
03813   if (!_dbus_string_append (&str, "Hello"))
03814     _dbus_assert_not_reached ("couldn't append to string");
03815   
03816   if (!_dbus_string_find (&str, 0, "He", &i))
03817     _dbus_assert_not_reached ("didn't find 'He'");
03818   _dbus_assert (i == 0);
03819 
03820   if (!_dbus_string_find (&str, 0, "Hello", &i))
03821     _dbus_assert_not_reached ("didn't find 'Hello'");
03822   _dbus_assert (i == 0);
03823   
03824   if (!_dbus_string_find (&str, 0, "ello", &i))
03825     _dbus_assert_not_reached ("didn't find 'ello'");
03826   _dbus_assert (i == 1);
03827 
03828   if (!_dbus_string_find (&str, 0, "lo", &i))
03829     _dbus_assert_not_reached ("didn't find 'lo'");
03830   _dbus_assert (i == 3);
03831 
03832   if (!_dbus_string_find (&str, 2, "lo", &i))
03833     _dbus_assert_not_reached ("didn't find 'lo'");
03834   _dbus_assert (i == 3);
03835 
03836   if (_dbus_string_find (&str, 4, "lo", &i))
03837     _dbus_assert_not_reached ("did find 'lo'");
03838   
03839   if (!_dbus_string_find (&str, 0, "l", &i))
03840     _dbus_assert_not_reached ("didn't find 'l'");
03841   _dbus_assert (i == 2);
03842 
03843   if (!_dbus_string_find (&str, 0, "H", &i))
03844     _dbus_assert_not_reached ("didn't find 'H'");
03845   _dbus_assert (i == 0);
03846 
03847   if (!_dbus_string_find (&str, 0, "", &i))
03848     _dbus_assert_not_reached ("didn't find ''");
03849   _dbus_assert (i == 0);
03850   
03851   if (_dbus_string_find (&str, 0, "Hello!", NULL))
03852     _dbus_assert_not_reached ("Did find 'Hello!'");
03853 
03854   if (_dbus_string_find (&str, 0, "Oh, Hello", NULL))
03855     _dbus_assert_not_reached ("Did find 'Oh, Hello'");
03856   
03857   if (_dbus_string_find (&str, 0, "ill", NULL))
03858     _dbus_assert_not_reached ("Did find 'ill'");
03859 
03860   if (_dbus_string_find (&str, 0, "q", NULL))
03861     _dbus_assert_not_reached ("Did find 'q'");
03862 
03863   if (!_dbus_string_find_to (&str, 0, 2, "He", NULL))
03864     _dbus_assert_not_reached ("Didn't find 'He'");
03865 
03866   if (_dbus_string_find_to (&str, 0, 2, "Hello", NULL))
03867     _dbus_assert_not_reached ("Did find 'Hello'");
03868 
03869   if (!_dbus_string_find_byte_backward (&str, _dbus_string_get_length (&str), 'H', &i))
03870     _dbus_assert_not_reached ("Did not find 'H'");
03871   _dbus_assert (i == 0);
03872 
03873   if (!_dbus_string_find_byte_backward (&str, _dbus_string_get_length (&str), 'o', &i))
03874     _dbus_assert_not_reached ("Did not find 'o'");
03875   _dbus_assert (i == _dbus_string_get_length (&str) - 1);
03876 
03877   if (_dbus_string_find_byte_backward (&str, _dbus_string_get_length (&str) - 1, 'o', &i))
03878     _dbus_assert_not_reached ("Did find 'o'");
03879   _dbus_assert (i == -1);
03880 
03881   if (_dbus_string_find_byte_backward (&str, 1, 'e', &i))
03882     _dbus_assert_not_reached ("Did find 'e'");
03883   _dbus_assert (i == -1);
03884 
03885   if (!_dbus_string_find_byte_backward (&str, 2, 'e', &i))
03886     _dbus_assert_not_reached ("Didn't find 'e'");
03887   _dbus_assert (i == 1);
03888   
03889   _dbus_string_free (&str);
03890 
03891   /* Hex encoding */
03892   _dbus_string_init_const (&str, "cafebabe, this is a bogus hex string");
03893   if (!_dbus_string_init (&other))
03894     _dbus_assert_not_reached ("could not init string");
03895 
03896   if (!_dbus_string_hex_decode (&str, 0, &end, &other, 0))
03897     _dbus_assert_not_reached ("deccoded bogus hex string with no error");
03898 
03899   _dbus_assert (end == 8);
03900 
03901   _dbus_string_free (&other);
03902 
03903   test_roundtrips (test_hex_roundtrip);
03904 
03905   /* Path validation */
03906   i = 0;
03907   while (i < (int) _DBUS_N_ELEMENTS (valid_paths))
03908     {
03909       _dbus_string_init_const (&str, valid_paths[i]);
03910 
03911       if (!_dbus_string_validate_path (&str, 0,
03912                                        _dbus_string_get_length (&str)))
03913         {
03914           _dbus_warn ("Path \"%s\" should have been valid\n", valid_paths[i]);
03915           _dbus_assert_not_reached ("invalid path");
03916         }
03917       
03918       ++i;
03919     }
03920 
03921   i = 0;
03922   while (i < (int) _DBUS_N_ELEMENTS (invalid_paths))
03923     {
03924       _dbus_string_init_const (&str, invalid_paths[i]);
03925       
03926       if (_dbus_string_validate_path (&str, 0,
03927                                       _dbus_string_get_length (&str)))
03928         {
03929           _dbus_warn ("Path \"%s\" should have been invalid\n", invalid_paths[i]);
03930           _dbus_assert_not_reached ("valid path");
03931         }
03932       
03933       ++i;
03934     }
03935 
03936   /* Interface validation */
03937   i = 0;
03938   while (i < (int) _DBUS_N_ELEMENTS (valid_interfaces))
03939     {
03940       _dbus_string_init_const (&str, valid_interfaces[i]);
03941 
03942       if (!_dbus_string_validate_interface (&str, 0,
03943                                             _dbus_string_get_length (&str)))
03944         {
03945           _dbus_warn ("Interface \"%s\" should have been valid\n", valid_interfaces[i]);
03946           _dbus_assert_not_reached ("invalid interface");
03947         }
03948       
03949       ++i;
03950     }
03951 
03952   i = 0;
03953   while (i < (int) _DBUS_N_ELEMENTS (invalid_interfaces))
03954     {
03955       _dbus_string_init_const (&str, invalid_interfaces[i]);
03956       
03957       if (_dbus_string_validate_interface (&str, 0,
03958                                            _dbus_string_get_length (&str)))
03959         {
03960           _dbus_warn ("Interface \"%s\" should have been invalid\n", invalid_interfaces[i]);
03961           _dbus_assert_not_reached ("valid interface");
03962         }
03963       
03964       ++i;
03965     }
03966 
03967   /* Service validation (check that valid interfaces are valid services,
03968    * and invalid interfaces are invalid services except if they start with ':')
03969    */
03970   i = 0;
03971   while (i < (int) _DBUS_N_ELEMENTS (valid_interfaces))
03972     {
03973       _dbus_string_init_const (&str, valid_interfaces[i]);
03974 
03975       if (!_dbus_string_validate_service (&str, 0,
03976                                           _dbus_string_get_length (&str)))
03977         {
03978           _dbus_warn ("Service \"%s\" should have been valid\n", valid_interfaces[i]);
03979           _dbus_assert_not_reached ("invalid service");
03980         }
03981       
03982       ++i;
03983     }
03984 
03985   i = 0;
03986   while (i < (int) _DBUS_N_ELEMENTS (invalid_interfaces))
03987     {
03988       if (invalid_interfaces[i][0] != ':')
03989         {
03990           _dbus_string_init_const (&str, invalid_interfaces[i]);
03991           
03992           if (_dbus_string_validate_service (&str, 0,
03993                                              _dbus_string_get_length (&str)))
03994             {
03995               _dbus_warn ("Service \"%s\" should have been invalid\n", invalid_interfaces[i]);
03996               _dbus_assert_not_reached ("valid service");
03997             }
03998         }
03999       
04000       ++i;
04001     }
04002 
04003   /* Base service validation */
04004   i = 0;
04005   while (i < (int) _DBUS_N_ELEMENTS (valid_base_services))
04006     {
04007       _dbus_string_init_const (&str, valid_base_services[i]);
04008 
04009       if (!_dbus_string_validate_service (&str, 0,
04010                                           _dbus_string_get_length (&str)))
04011         {
04012           _dbus_warn ("Service \"%s\" should have been valid\n", valid_base_services[i]);
04013           _dbus_assert_not_reached ("invalid base service");
04014         }
04015       
04016       ++i;
04017     }
04018 
04019   i = 0;
04020   while (i < (int) _DBUS_N_ELEMENTS (invalid_base_services))
04021     {
04022       _dbus_string_init_const (&str, invalid_base_services[i]);
04023       
04024       if (_dbus_string_validate_service (&str, 0,
04025                                          _dbus_string_get_length (&str)))
04026         {
04027           _dbus_warn ("Service \"%s\" should have been invalid\n", invalid_base_services[i]);
04028           _dbus_assert_not_reached ("valid base service");
04029         }
04030       
04031       ++i;
04032     }
04033 
04034 
04035   /* Error name validation (currently identical to interfaces)
04036    */
04037   i = 0;
04038   while (i < (int) _DBUS_N_ELEMENTS (valid_interfaces))
04039     {
04040       _dbus_string_init_const (&str, valid_interfaces[i]);
04041 
04042       if (!_dbus_string_validate_error_name (&str, 0,
04043                                              _dbus_string_get_length (&str)))
04044         {
04045           _dbus_warn ("Error name \"%s\" should have been valid\n", valid_interfaces[i]);
04046           _dbus_assert_not_reached ("invalid error name");
04047         }
04048       
04049       ++i;
04050     }
04051 
04052   i = 0;
04053   while (i < (int) _DBUS_N_ELEMENTS (invalid_interfaces))
04054     {
04055       if (invalid_interfaces[i][0] != ':')
04056         {
04057           _dbus_string_init_const (&str, invalid_interfaces[i]);
04058           
04059           if (_dbus_string_validate_error_name (&str, 0,
04060                                                 _dbus_string_get_length (&str)))
04061             {
04062               _dbus_warn ("Error name \"%s\" should have been invalid\n", invalid_interfaces[i]);
04063               _dbus_assert_not_reached ("valid error name");
04064             }
04065         }
04066       
04067       ++i;
04068     }
04069   
04070   /* Member validation */
04071   i = 0;
04072   while (i < (int) _DBUS_N_ELEMENTS (valid_members))
04073     {
04074       _dbus_string_init_const (&str, valid_members[i]);
04075 
04076       if (!_dbus_string_validate_member (&str, 0,
04077                                          _dbus_string_get_length (&str)))
04078         {
04079           _dbus_warn ("Member \"%s\" should have been valid\n", valid_members[i]);
04080           _dbus_assert_not_reached ("invalid member");
04081         }
04082       
04083       ++i;
04084     }
04085 
04086   i = 0;
04087   while (i < (int) _DBUS_N_ELEMENTS (invalid_members))
04088     {
04089       _dbus_string_init_const (&str, invalid_members[i]);
04090       
04091       if (_dbus_string_validate_member (&str, 0,
04092                                         _dbus_string_get_length (&str)))
04093         {
04094           _dbus_warn ("Member \"%s\" should have been invalid\n", invalid_members[i]);
04095           _dbus_assert_not_reached ("valid member");
04096         }
04097       
04098       ++i;
04099     }
04100 
04101   /* Signature validation */
04102   i = 0;
04103   while (i < (int) _DBUS_N_ELEMENTS (valid_signatures))
04104     {
04105       _dbus_string_init_const (&str, valid_signatures[i]);
04106 
04107       if (!_dbus_string_validate_signature (&str, 0,
04108                                             _dbus_string_get_length (&str)))
04109         {
04110           _dbus_warn ("Signature \"%s\" should have been valid\n", valid_signatures[i]);
04111           _dbus_assert_not_reached ("invalid signature");
04112         }
04113       
04114       ++i;
04115     }
04116 
04117   i = 0;
04118   while (i < (int) _DBUS_N_ELEMENTS (invalid_signatures))
04119     {
04120       _dbus_string_init_const (&str, invalid_signatures[i]);
04121       
04122       if (_dbus_string_validate_signature (&str, 0,
04123                                            _dbus_string_get_length (&str)))
04124         {
04125           _dbus_warn ("Signature \"%s\" should have been invalid\n", invalid_signatures[i]);
04126           _dbus_assert_not_reached ("valid signature");
04127         }
04128       
04129       ++i;
04130     }
04131   
04132   /* Validate claimed length longer than real length */
04133   _dbus_string_init_const (&str, "abc.efg");
04134   if (_dbus_string_validate_service (&str, 0, 8))
04135     _dbus_assert_not_reached ("validated too-long string");
04136   if (_dbus_string_validate_interface (&str, 0, 8))
04137     _dbus_assert_not_reached ("validated too-long string");
04138   if (_dbus_string_validate_error_name (&str, 0, 8))
04139     _dbus_assert_not_reached ("validated too-long string");
04140 
04141   _dbus_string_init_const (&str, "abc");
04142   if (_dbus_string_validate_member (&str, 0, 4))
04143     _dbus_assert_not_reached ("validated too-long string");
04144 
04145   _dbus_string_init_const (&str, "sss");
04146   if (_dbus_string_validate_signature (&str, 0, 4))
04147     _dbus_assert_not_reached ("validated too-long signature");
04148   
04149   /* Validate string exceeding max name length */
04150   if (!_dbus_string_init (&str))
04151     _dbus_assert_not_reached ("no memory");
04152 
04153   while (_dbus_string_get_length (&str) <= DBUS_MAXIMUM_NAME_LENGTH)
04154     if (!_dbus_string_append (&str, "abc.def"))
04155       _dbus_assert_not_reached ("no memory");
04156 
04157   if (_dbus_string_validate_service (&str, 0, _dbus_string_get_length (&str)))
04158     _dbus_assert_not_reached ("validated overmax string");
04159   if (_dbus_string_validate_interface (&str, 0, _dbus_string_get_length (&str)))
04160     _dbus_assert_not_reached ("validated overmax string");
04161   if (_dbus_string_validate_error_name (&str, 0, _dbus_string_get_length (&str)))
04162     _dbus_assert_not_reached ("validated overmax string");
04163 
04164   /* overlong member */
04165   _dbus_string_set_length (&str, 0);
04166   while (_dbus_string_get_length (&str) <= DBUS_MAXIMUM_NAME_LENGTH)
04167     if (!_dbus_string_append (&str, "abc"))
04168       _dbus_assert_not_reached ("no memory");  
04169 
04170   if (_dbus_string_validate_member (&str, 0, _dbus_string_get_length (&str)))
04171     _dbus_assert_not_reached ("validated overmax string");
04172 
04173   /* overlong base service */
04174   _dbus_string_set_length (&str, 0);
04175   _dbus_string_append (&str, ":");
04176   while (_dbus_string_get_length (&str) <= DBUS_MAXIMUM_NAME_LENGTH)
04177     if (!_dbus_string_append (&str, "abc"))
04178       _dbus_assert_not_reached ("no memory");  
04179 
04180   if (_dbus_string_validate_service (&str, 0, _dbus_string_get_length (&str)))
04181     _dbus_assert_not_reached ("validated overmax string");
04182   
04183   _dbus_string_free (&str);
04184   
04185   return TRUE;
04186 }
04187 
04188 #endif /* DBUS_BUILD_TESTS */

Generated on Thu Aug 11 21:11:14 2005 for D-BUS by  doxygen 1.4.0