Main Page | Modules | Data Structures | 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 Red Hat, Inc.
00005  *
00006  * Licensed under the Academic Free License version 2.0
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 
00079 #define ALLOCATION_PADDING 8
00080 
00085 #define MAX_MAX_LENGTH (_DBUS_INT_MAX - ALLOCATION_PADDING)
00086 
00092 #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)
00093 
00100 #define DBUS_STRING_PREAMBLE(str) DBusRealString *real = (DBusRealString*) str; \
00101   DBUS_GENERIC_STRING_PREAMBLE (real);                                          \
00102   _dbus_assert (!(real)->constant);                                             \
00103   _dbus_assert (!(real)->locked)
00104 
00112 #define DBUS_LOCKED_STRING_PREAMBLE(str) DBusRealString *real = (DBusRealString*) str; \
00113   DBUS_GENERIC_STRING_PREAMBLE (real);                                                 \
00114   _dbus_assert (!(real)->constant)
00115 
00121 #define DBUS_CONST_STRING_PREAMBLE(str) const DBusRealString *real = (DBusRealString*) str; \
00122   DBUS_GENERIC_STRING_PREAMBLE (real)
00123 
00131 static void
00132 fixup_alignment (DBusRealString *real)
00133 {
00134   char *aligned;
00135   char *real_block;
00136   unsigned int old_align_offset;
00137 
00138   /* we have to have extra space in real->allocated for the align offset and nul byte */
00139   _dbus_assert (real->len <= real->allocated - ALLOCATION_PADDING);
00140   
00141   old_align_offset = real->align_offset;
00142   real_block = real->str - old_align_offset;
00143   
00144   aligned = _DBUS_ALIGN_ADDRESS (real_block, 8);
00145 
00146   real->align_offset = aligned - real_block;
00147   real->str = aligned;
00148   
00149   if (old_align_offset != real->align_offset)
00150     {
00151       /* Here comes the suck */
00152       memmove (real_block + real->align_offset,
00153                real_block + old_align_offset,
00154                real->len + 1);
00155     }
00156 
00157   _dbus_assert (real->align_offset < 8);
00158   _dbus_assert (_DBUS_ALIGN_ADDRESS (real->str, 8) == real->str);
00159 }
00160 
00161 static void
00162 undo_alignment (DBusRealString *real)
00163 {
00164   if (real->align_offset != 0)
00165     {
00166       memmove (real->str - real->align_offset,
00167                real->str,
00168                real->len + 1);
00169 
00170       real->str = real->str - real->align_offset;
00171       real->align_offset = 0;
00172     }
00173 }
00174 
00184 dbus_bool_t
00185 _dbus_string_init_preallocated (DBusString *str,
00186                                 int         allocate_size)
00187 {
00188   DBusRealString *real;
00189   
00190   _dbus_assert (str != NULL);
00191 
00192   _dbus_assert (sizeof (DBusString) == sizeof (DBusRealString));
00193   
00194   real = (DBusRealString*) str;
00195 
00196   /* It's very important not to touch anything
00197    * other than real->str if we're going to fail,
00198    * since we also use this function to reset
00199    * an existing string, e.g. in _dbus_string_steal_data()
00200    */
00201   
00202   real->str = dbus_malloc (ALLOCATION_PADDING + allocate_size);
00203   if (real->str == NULL)
00204     return FALSE;  
00205   
00206   real->allocated = ALLOCATION_PADDING + allocate_size;
00207   real->len = 0;
00208   real->str[real->len] = '\0';
00209   
00210   real->max_length = MAX_MAX_LENGTH;
00211   real->constant = FALSE;
00212   real->locked = FALSE;
00213   real->invalid = FALSE;
00214   real->align_offset = 0;
00215   
00216   fixup_alignment (real);
00217   
00218   return TRUE;
00219 }
00220 
00228 dbus_bool_t
00229 _dbus_string_init (DBusString *str)
00230 {
00231   return _dbus_string_init_preallocated (str, 0);
00232 }
00233 
00234 /* The max length thing is sort of a historical artifact
00235  * from a feature that turned out to be dumb; perhaps
00236  * we should purge it entirely. The problem with
00237  * the feature is that it looks like memory allocation
00238  * failure, but is not a transient or resolvable failure.
00239  */
00240 static void
00241 set_max_length (DBusString *str,
00242                 int         max_length)
00243 {
00244   DBusRealString *real;
00245   
00246   real = (DBusRealString*) str;
00247 
00248   real->max_length = max_length;
00249 }
00250 
00260 void
00261 _dbus_string_init_const (DBusString *str,
00262                          const char *value)
00263 {
00264   _dbus_assert (value != NULL);
00265   
00266   _dbus_string_init_const_len (str, value,
00267                                strlen (value));
00268 }
00269 
00280 void
00281 _dbus_string_init_const_len (DBusString *str,
00282                              const char *value,
00283                              int         len)
00284 {
00285   DBusRealString *real;
00286   
00287   _dbus_assert (str != NULL);
00288   _dbus_assert (value != NULL);
00289   _dbus_assert (len <= MAX_MAX_LENGTH);
00290   _dbus_assert (len >= 0);
00291   
00292   real = (DBusRealString*) str;
00293   
00294   real->str = (char*) value;
00295   real->len = len;
00296   real->allocated = real->len + ALLOCATION_PADDING; /* a lie, just to avoid special-case assertions... */
00297   real->max_length = real->len + 1;
00298   real->constant = TRUE;
00299   real->invalid = FALSE;
00300 
00301   /* We don't require const strings to be 8-byte aligned as the
00302    * memory is coming from elsewhere.
00303    */
00304 }
00305 
00311 void
00312 _dbus_string_free (DBusString *str)
00313 {
00314   DBusRealString *real = (DBusRealString*) str;
00315   DBUS_GENERIC_STRING_PREAMBLE (real);
00316   
00317   if (real->constant)
00318     return;
00319   dbus_free (real->str - real->align_offset);
00320 
00321   real->invalid = TRUE;
00322 }
00323 
00324 #ifdef DBUS_BUILD_TESTS
00325 /* Not using this feature at the moment,
00326  * so marked DBUS_BUILD_TESTS-only
00327  */
00337 void
00338 _dbus_string_lock (DBusString *str)
00339 {  
00340   DBUS_LOCKED_STRING_PREAMBLE (str); /* can lock multiple times */
00341 
00342   real->locked = TRUE;
00343 
00344   /* Try to realloc to avoid excess memory usage, since
00345    * we know we won't change the string further
00346    */
00347 #define MAX_WASTE 48
00348   if (real->allocated - MAX_WASTE > real->len)
00349     {
00350       char *new_str;
00351       int new_allocated;
00352 
00353       new_allocated = real->len + ALLOCATION_PADDING;
00354 
00355       new_str = dbus_realloc (real->str - real->align_offset,
00356                               new_allocated);
00357       if (new_str != NULL)
00358         {
00359           real->str = new_str + real->align_offset;
00360           real->allocated = new_allocated;
00361           fixup_alignment (real);
00362         }
00363     }
00364 }
00365 #endif /* DBUS_BUILD_TESTS */
00366 
00367 static dbus_bool_t
00368 reallocate_for_length (DBusRealString *real,
00369                        int             new_length)
00370 {
00371   int new_allocated;
00372   char *new_str;
00373 
00374   /* at least double our old allocation to avoid O(n), avoiding
00375    * overflow
00376    */
00377   if (real->allocated > (MAX_MAX_LENGTH + ALLOCATION_PADDING) / 2)
00378     new_allocated = MAX_MAX_LENGTH + ALLOCATION_PADDING;
00379   else
00380     new_allocated = real->allocated * 2;
00381 
00382   /* if you change the code just above here, run the tests without
00383    * the following before you commit
00384    */
00385 #ifdef DBUS_BUILD_TESTS
00386   new_allocated = 0; /* ensure a realloc every time so that we go
00387                       * through all malloc failure codepaths
00388                       */
00389 #endif
00390       
00391   /* But be sure we always alloc at least space for the new length */
00392   new_allocated = MAX (new_allocated, new_length + ALLOCATION_PADDING);
00393 
00394   _dbus_assert (new_allocated >= real->allocated); /* code relies on this */
00395   new_str = dbus_realloc (real->str - real->align_offset, new_allocated);
00396   if (new_str == NULL)
00397     return FALSE;
00398 
00399   real->str = new_str + real->align_offset;
00400   real->allocated = new_allocated;
00401   fixup_alignment (real);
00402 
00403   return TRUE;
00404 }
00405 
00406 static dbus_bool_t
00407 set_length (DBusRealString *real,
00408             int             new_length)
00409 {
00410   /* Note, we are setting the length not including nul termination */
00411 
00412   /* exceeding max length is the same as failure to allocate memory */
00413   if (new_length > real->max_length)
00414     return FALSE;
00415   else if (new_length > (real->allocated - ALLOCATION_PADDING) &&
00416            !reallocate_for_length (real, new_length))
00417     return FALSE;
00418   else
00419     {
00420       real->len = new_length;
00421       real->str[real->len] = '\0';
00422       return TRUE;
00423     }
00424 }
00425 
00426 static dbus_bool_t
00427 open_gap (int             len,
00428           DBusRealString *dest,
00429           int             insert_at)
00430 {
00431   if (len == 0)
00432     return TRUE;
00433 
00434   if (len > dest->max_length - dest->len)
00435     return FALSE; /* detected overflow of dest->len + len below */
00436   
00437   if (!set_length (dest, dest->len + len))
00438     return FALSE;
00439 
00440   memmove (dest->str + insert_at + len, 
00441            dest->str + insert_at,
00442            dest->len - len - insert_at);
00443 
00444   return TRUE;
00445 }
00446 
00458 char*
00459 _dbus_string_get_data (DBusString *str)
00460 {
00461   DBUS_STRING_PREAMBLE (str);
00462   
00463   return real->str;
00464 }
00465 
00472 const char*
00473 _dbus_string_get_const_data (const DBusString  *str)
00474 {
00475   DBUS_CONST_STRING_PREAMBLE (str);
00476   
00477   return real->str;
00478 }
00479 
00493 char*
00494 _dbus_string_get_data_len (DBusString *str,
00495                            int         start,
00496                            int         len)
00497 {
00498   DBUS_STRING_PREAMBLE (str);
00499   _dbus_assert (start >= 0);
00500   _dbus_assert (len >= 0);
00501   _dbus_assert (start <= real->len);
00502   _dbus_assert (len <= real->len - start);
00503   
00504   return real->str + start;
00505 }
00506 
00515 const char*
00516 _dbus_string_get_const_data_len (const DBusString  *str,
00517                                  int                start,
00518                                  int                len)
00519 {
00520   DBUS_CONST_STRING_PREAMBLE (str);
00521   _dbus_assert (start >= 0);
00522   _dbus_assert (len >= 0);
00523   _dbus_assert (start <= real->len);
00524   _dbus_assert (len <= real->len - start);
00525   
00526   return real->str + start;
00527 }
00528 
00536 void
00537 _dbus_string_set_byte (DBusString    *str,
00538                        int            i,
00539                        unsigned char  byte)
00540 {
00541   DBUS_STRING_PREAMBLE (str);
00542   _dbus_assert (i < real->len);
00543   _dbus_assert (i >= 0);
00544   
00545   real->str[i] = byte;
00546 }
00547 
00557 unsigned char
00558 _dbus_string_get_byte (const DBusString  *str,
00559                        int                start)
00560 {
00561   DBUS_CONST_STRING_PREAMBLE (str);
00562   _dbus_assert (start <= real->len);
00563   _dbus_assert (start >= 0);
00564   
00565   return real->str[start];
00566 }
00567 
00578 dbus_bool_t
00579 _dbus_string_insert_bytes (DBusString   *str,
00580                            int           i,
00581                            int           n_bytes,
00582                            unsigned char byte)
00583 {
00584   DBUS_STRING_PREAMBLE (str);
00585   _dbus_assert (i <= real->len);
00586   _dbus_assert (i >= 0);
00587   _dbus_assert (n_bytes >= 0);
00588 
00589   if (n_bytes == 0)
00590     return TRUE;
00591   
00592   if (!open_gap (n_bytes, real, i))
00593     return FALSE;
00594   
00595   memset (real->str + i, byte, n_bytes);
00596 
00597   return TRUE;
00598 }
00599 
00610 dbus_bool_t
00611 _dbus_string_steal_data (DBusString        *str,
00612                          char             **data_return)
00613 {
00614   int old_max_length;
00615   DBUS_STRING_PREAMBLE (str);
00616   _dbus_assert (data_return != NULL);
00617 
00618   undo_alignment (real);
00619   
00620   *data_return = real->str;
00621 
00622   old_max_length = real->max_length;
00623   
00624   /* reset the string */
00625   if (!_dbus_string_init (str))
00626     {
00627       /* hrm, put it back then */
00628       real->str = *data_return;
00629       *data_return = NULL;
00630       fixup_alignment (real);
00631       return FALSE;
00632     }
00633 
00634   real->max_length = old_max_length;
00635 
00636   return TRUE;
00637 }
00638 
00654 dbus_bool_t
00655 _dbus_string_steal_data_len (DBusString        *str,
00656                              char             **data_return,
00657                              int                start,
00658                              int                len)
00659 {
00660   DBusString dest;
00661   DBUS_STRING_PREAMBLE (str);
00662   _dbus_assert (data_return != NULL);
00663   _dbus_assert (start >= 0);
00664   _dbus_assert (len >= 0);
00665   _dbus_assert (start <= real->len);
00666   _dbus_assert (len <= real->len - start);
00667 
00668   if (!_dbus_string_init (&dest))
00669     return FALSE;
00670 
00671   set_max_length (&dest, real->max_length);
00672   
00673   if (!_dbus_string_move_len (str, start, len, &dest, 0))
00674     {
00675       _dbus_string_free (&dest);
00676       return FALSE;
00677     }
00678 
00679   _dbus_warn ("Broken code in _dbus_string_steal_data_len(), see @todo, FIXME\n");
00680   if (!_dbus_string_steal_data (&dest, data_return))
00681     {
00682       _dbus_string_free (&dest);
00683       return FALSE;
00684     }
00685 
00686   _dbus_string_free (&dest);
00687   return TRUE;
00688 }
00689 
00690 
00698 dbus_bool_t
00699 _dbus_string_copy_data (const DBusString  *str,
00700                         char             **data_return)
00701 {
00702   DBUS_CONST_STRING_PREAMBLE (str);
00703   _dbus_assert (data_return != NULL);
00704   
00705   *data_return = dbus_malloc (real->len + 1);
00706   if (*data_return == NULL)
00707     return FALSE;
00708 
00709   memcpy (*data_return, real->str, real->len + 1);
00710 
00711   return TRUE;
00712 }
00713 
00723 dbus_bool_t
00724 _dbus_string_copy_data_len (const DBusString  *str,
00725                             char             **data_return,
00726                             int                start,
00727                             int                len)
00728 {
00729   DBusString dest;
00730 
00731   DBUS_CONST_STRING_PREAMBLE (str);
00732   _dbus_assert (data_return != NULL);
00733   _dbus_assert (start >= 0);
00734   _dbus_assert (len >= 0);
00735   _dbus_assert (start <= real->len);
00736   _dbus_assert (len <= real->len - start);
00737 
00738   if (!_dbus_string_init (&dest))
00739     return FALSE;
00740 
00741   set_max_length (&dest, real->max_length);
00742 
00743   if (!_dbus_string_copy_len (str, start, len, &dest, 0))
00744     {
00745       _dbus_string_free (&dest);
00746       return FALSE;
00747     }
00748 
00749   if (!_dbus_string_steal_data (&dest, data_return))
00750     {
00751       _dbus_string_free (&dest);
00752       return FALSE;
00753     }
00754 
00755   _dbus_string_free (&dest);
00756   return TRUE;
00757 }
00758 
00764 int
00765 _dbus_string_get_length (const DBusString  *str)
00766 {
00767   DBUS_CONST_STRING_PREAMBLE (str);
00768   
00769   return real->len;
00770 }
00771 
00784 dbus_bool_t
00785 _dbus_string_lengthen (DBusString *str,
00786                        int         additional_length)
00787 {
00788   DBUS_STRING_PREAMBLE (str);  
00789   _dbus_assert (additional_length >= 0);
00790 
00791   if (additional_length > real->max_length - real->len)
00792     return FALSE; /* would overflow */
00793   
00794   return set_length (real,
00795                      real->len + additional_length);
00796 }
00797 
00804 void
00805 _dbus_string_shorten (DBusString *str,
00806                       int         length_to_remove)
00807 {
00808   DBUS_STRING_PREAMBLE (str);
00809   _dbus_assert (length_to_remove >= 0);
00810   _dbus_assert (length_to_remove <= real->len);
00811 
00812   set_length (real,
00813               real->len - length_to_remove);
00814 }
00815 
00826 dbus_bool_t
00827 _dbus_string_set_length (DBusString *str,
00828                          int         length)
00829 {
00830   DBUS_STRING_PREAMBLE (str);
00831   _dbus_assert (length >= 0);
00832 
00833   return set_length (real, length);
00834 }
00835 
00836 static dbus_bool_t
00837 align_length_then_lengthen (DBusString *str,
00838                             int         alignment,
00839                             int         then_lengthen_by)
00840 {
00841   unsigned long new_len; /* ulong to avoid _DBUS_ALIGN_VALUE overflow */
00842   int delta;
00843   DBUS_STRING_PREAMBLE (str);
00844   _dbus_assert (alignment >= 1);
00845   _dbus_assert (alignment <= 8); /* it has to be a bug if > 8 */
00846 
00847   new_len = _DBUS_ALIGN_VALUE (real->len, alignment);
00848   if (new_len > (unsigned long) real->max_length - then_lengthen_by)
00849     return FALSE;
00850   new_len += then_lengthen_by;
00851   
00852   delta = new_len - real->len;
00853   _dbus_assert (delta >= 0);
00854 
00855   if (delta == 0)
00856     return TRUE;
00857 
00858   if (!set_length (real, new_len))
00859     return FALSE;
00860 
00861   /* delta == padding + then_lengthen_by
00862    * new_len == old_len + padding + then_lengthen_by
00863    */
00864   if (then_lengthen_by < delta)
00865     {
00866       unsigned int i;
00867       i = new_len - delta;
00868       while (i < (new_len - then_lengthen_by))
00869         {
00870           real->str[i] = '\0';
00871           ++i;
00872         }
00873     }
00874       
00875   return TRUE;
00876 }
00877 
00886 dbus_bool_t
00887 _dbus_string_align_length (DBusString *str,
00888                            int         alignment)
00889 {
00890   return align_length_then_lengthen (str, alignment, 0);
00891 }
00892 
00893 static dbus_bool_t
00894 append (DBusRealString *real,
00895         const char     *buffer,
00896         int             buffer_len)
00897 {
00898   if (buffer_len == 0)
00899     return TRUE;
00900 
00901   if (!_dbus_string_lengthen ((DBusString*)real, buffer_len))
00902     return FALSE;
00903 
00904   memcpy (real->str + (real->len - buffer_len),
00905           buffer,
00906           buffer_len);
00907 
00908   return TRUE;
00909 }
00910 
00918 dbus_bool_t
00919 _dbus_string_append (DBusString *str,
00920                      const char *buffer)
00921 {
00922   unsigned long buffer_len;
00923   
00924   DBUS_STRING_PREAMBLE (str);
00925   _dbus_assert (buffer != NULL);
00926   
00927   buffer_len = strlen (buffer);
00928   if (buffer_len > (unsigned long) real->max_length)
00929     return FALSE;
00930   
00931   return append (real, buffer, buffer_len);
00932 }
00933 
00942 dbus_bool_t
00943 _dbus_string_append_4_aligned (DBusString         *str,
00944                                const unsigned char octets[4])
00945 {
00946   dbus_uint32_t *p;
00947   DBUS_STRING_PREAMBLE (str);
00948   
00949   if (!align_length_then_lengthen (str, 4, 4))
00950     return FALSE;
00951 
00952   p = (dbus_uint32_t*) (real->str + (real->len - 4));
00953   *p = *((dbus_uint32_t*)octets);
00954 
00955   return TRUE;
00956 }
00957 
00966 dbus_bool_t
00967 _dbus_string_append_8_aligned (DBusString         *str,
00968                                const unsigned char octets[8])
00969 {
00970 #ifdef DBUS_HAVE_INT64
00971   dbus_uint64_t *p;
00972   DBUS_STRING_PREAMBLE (str);
00973   
00974   if (!align_length_then_lengthen (str, 8, 8))
00975     return FALSE;
00976 
00977   p = (dbus_uint64_t*) (real->str + (real->len - 8));
00978   *p = *((dbus_uint64_t*)octets);
00979 #else
00980   unsigned char *p;
00981   DBUS_STRING_PREAMBLE (str);
00982   
00983   if (!align_length_then_lengthen (str, 8, 8))
00984     return FALSE;
00985 
00986   p = real->str + (real->len - 8);
00987   
00988   *p++ = octets[0];
00989   *p++ = octets[1];
00990   *p++ = octets[2];
00991   *p++ = octets[3];
00992   *p++ = octets[4];
00993   *p++ = octets[5];
00994   *p++ = octets[6];
00995   *p++ = octets[7];
00996   _dbus_assert (p == (real->str + real->len));
00997 #endif
00998 
00999   return TRUE;
01000 }
01001 
01011 dbus_bool_t
01012 _dbus_string_append_printf_valist  (DBusString        *str,
01013                                     const char        *format,
01014                                     va_list            args)
01015 {
01016   int len;
01017   char c;
01018   va_list args_copy;
01019 
01020   DBUS_STRING_PREAMBLE (str);
01021 
01022   DBUS_VA_COPY (args_copy, args);
01023 
01024   /* Measure the message length without terminating nul */
01025   len = vsnprintf (&c, 1, format, args);
01026 
01027   if (!_dbus_string_lengthen (str, len))
01028     {
01029       /* don't leak the copy */
01030       va_end (args_copy);
01031       return FALSE;
01032     }
01033   
01034   vsprintf (real->str + (real->len - len),
01035             format, args_copy);
01036 
01037   va_end (args_copy);
01038 
01039   return TRUE;
01040 }
01041 
01050 dbus_bool_t
01051 _dbus_string_append_printf (DBusString        *str,
01052                             const char        *format,
01053                             ...)
01054 {
01055   va_list args;
01056   dbus_bool_t retval;
01057   
01058   va_start (args, format);
01059   retval = _dbus_string_append_printf_valist (str, format, args);
01060   va_end (args);
01061 
01062   return retval;
01063 }
01064 
01073 dbus_bool_t
01074 _dbus_string_append_len (DBusString *str,
01075                          const char *buffer,
01076                          int         len)
01077 {
01078   DBUS_STRING_PREAMBLE (str);
01079   _dbus_assert (buffer != NULL);
01080   _dbus_assert (len >= 0);
01081 
01082   return append (real, buffer, len);
01083 }
01084 
01093 dbus_bool_t
01094 _dbus_string_append_byte (DBusString    *str,
01095                           unsigned char  byte)
01096 {
01097   DBUS_STRING_PREAMBLE (str);
01098 
01099   if (!set_length (real, real->len + 1))
01100     return FALSE;
01101 
01102   real->str[real->len-1] = byte;
01103 
01104   return TRUE;
01105 }
01106 
01114 dbus_bool_t
01115 _dbus_string_append_unichar (DBusString    *str,
01116                              dbus_unichar_t ch)
01117 {
01118   int len;
01119   int first;
01120   int i;
01121   char *out;
01122   
01123   DBUS_STRING_PREAMBLE (str);
01124 
01125   /* this code is from GLib but is pretty standard I think */
01126   
01127   len = 0;
01128   
01129   if (ch < 0x80)
01130     {
01131       first = 0;
01132       len = 1;
01133     }
01134   else if (ch < 0x800)
01135     {
01136       first = 0xc0;
01137       len = 2;
01138     }
01139   else if (ch < 0x10000)
01140     {
01141       first = 0xe0;
01142       len = 3;
01143     }
01144    else if (ch < 0x200000)
01145     {
01146       first = 0xf0;
01147       len = 4;
01148     }
01149   else if (ch < 0x4000000)
01150     {
01151       first = 0xf8;
01152       len = 5;
01153     }
01154   else
01155     {
01156       first = 0xfc;
01157       len = 6;
01158     }
01159 
01160   if (len > (real->max_length - real->len))
01161     return FALSE; /* real->len + len would overflow */
01162   
01163   if (!set_length (real, real->len + len))
01164     return FALSE;
01165 
01166   out = real->str + (real->len - len);
01167   
01168   for (i = len - 1; i > 0; --i)
01169     {
01170       out[i] = (ch & 0x3f) | 0x80;
01171       ch >>= 6;
01172     }
01173   out[0] = ch | first;
01174 
01175   return TRUE;
01176 }
01177 
01178 static void
01179 delete (DBusRealString *real,
01180         int             start,
01181         int             len)
01182 {
01183   if (len == 0)
01184     return;
01185   
01186   memmove (real->str + start, real->str + start + len, real->len - (start + len));
01187   real->len -= len;
01188   real->str[real->len] = '\0';
01189 }
01190 
01200 void
01201 _dbus_string_delete (DBusString       *str,
01202                      int               start,
01203                      int               len)
01204 {
01205   DBUS_STRING_PREAMBLE (str);
01206   _dbus_assert (start >= 0);
01207   _dbus_assert (len >= 0);
01208   _dbus_assert (start <= real->len);
01209   _dbus_assert (len <= real->len - start);
01210   
01211   delete (real, start, len);
01212 }
01213 
01214 static dbus_bool_t
01215 copy (DBusRealString *source,
01216       int             start,
01217       int             len,
01218       DBusRealString *dest,
01219       int             insert_at)
01220 {
01221   if (len == 0)
01222     return TRUE;
01223 
01224   if (!open_gap (len, dest, insert_at))
01225     return FALSE;
01226   
01227   memcpy (dest->str + insert_at,
01228           source->str + start,
01229           len);
01230 
01231   return TRUE;
01232 }
01233 
01243 #define DBUS_STRING_COPY_PREAMBLE(source, start, dest, insert_at)       \
01244   DBusRealString *real_source = (DBusRealString*) source;               \
01245   DBusRealString *real_dest = (DBusRealString*) dest;                   \
01246   _dbus_assert ((source) != (dest));                                    \
01247   DBUS_GENERIC_STRING_PREAMBLE (real_source);                           \
01248   DBUS_GENERIC_STRING_PREAMBLE (real_dest);                             \
01249   _dbus_assert (!real_dest->constant);                                  \
01250   _dbus_assert (!real_dest->locked);                                    \
01251   _dbus_assert ((start) >= 0);                                          \
01252   _dbus_assert ((start) <= real_source->len);                           \
01253   _dbus_assert ((insert_at) >= 0);                                      \
01254   _dbus_assert ((insert_at) <= real_dest->len)
01255 
01266 dbus_bool_t
01267 _dbus_string_move (DBusString       *source,
01268                    int               start,
01269                    DBusString       *dest,
01270                    int               insert_at)
01271 {
01272   DBusRealString *real_source = (DBusRealString*) source;
01273   _dbus_assert (start <= real_source->len);
01274   
01275   return _dbus_string_move_len (source, start,
01276                                 real_source->len - start,
01277                                 dest, insert_at);
01278 }
01279 
01290 dbus_bool_t
01291 _dbus_string_copy (const DBusString *source,
01292                    int               start,
01293                    DBusString       *dest,
01294                    int               insert_at)
01295 {
01296   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
01297 
01298   return copy (real_source, start,
01299                real_source->len - start,
01300                real_dest,
01301                insert_at);
01302 }
01303 
01318 dbus_bool_t
01319 _dbus_string_move_len (DBusString       *source,
01320                        int               start,
01321                        int               len,
01322                        DBusString       *dest,
01323                        int               insert_at)
01324 
01325 {
01326   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
01327   _dbus_assert (len >= 0);
01328   _dbus_assert ((start + len) <= real_source->len);
01329 
01330 
01331   if (len == 0)
01332     {
01333       return TRUE;
01334     }
01335   else if (start == 0 &&
01336            len == real_source->len &&
01337            real_dest->len == 0)
01338     {
01339       /* Short-circuit moving an entire existing string to an empty string
01340        * by just swapping the buffers.
01341        */
01342       /* we assume ->constant doesn't matter as you can't have
01343        * a constant string involved in a move.
01344        */
01345 #define ASSIGN_DATA(a, b) do {                  \
01346         (a)->str = (b)->str;                    \
01347         (a)->len = (b)->len;                    \
01348         (a)->allocated = (b)->allocated;        \
01349         (a)->align_offset = (b)->align_offset;  \
01350       } while (0)
01351       
01352       DBusRealString tmp;
01353 
01354       ASSIGN_DATA (&tmp, real_source);
01355       ASSIGN_DATA (real_source, real_dest);
01356       ASSIGN_DATA (real_dest, &tmp);
01357 
01358       return TRUE;
01359     }
01360   else
01361     {
01362       if (!copy (real_source, start, len,
01363                  real_dest,
01364                  insert_at))
01365         return FALSE;
01366       
01367       delete (real_source, start,
01368               len);
01369       
01370       return TRUE;
01371     }
01372 }
01373 
01385 dbus_bool_t
01386 _dbus_string_copy_len (const DBusString *source,
01387                        int               start,
01388                        int               len,
01389                        DBusString       *dest,
01390                        int               insert_at)
01391 {
01392   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
01393   _dbus_assert (len >= 0);
01394   _dbus_assert (start <= real_source->len);
01395   _dbus_assert (len <= real_source->len - start);
01396   
01397   return copy (real_source, start, len,
01398                real_dest,
01399                insert_at);
01400 }
01401 
01423 dbus_bool_t
01424 _dbus_string_replace_len (const DBusString *source,
01425                           int               start,
01426                           int               len,
01427                           DBusString       *dest,
01428                           int               replace_at,
01429                           int               replace_len)
01430 {
01431   DBUS_STRING_COPY_PREAMBLE (source, start, dest, replace_at);
01432   _dbus_assert (len >= 0);
01433   _dbus_assert (start <= real_source->len);
01434   _dbus_assert (len <= real_source->len - start);
01435   _dbus_assert (replace_at >= 0);
01436   _dbus_assert (replace_at <= real_dest->len);
01437   _dbus_assert (replace_len <= real_dest->len - replace_at);
01438 
01439   if (!copy (real_source, start, len,
01440              real_dest, replace_at))
01441     return FALSE;
01442 
01443   delete (real_dest, replace_at + len, replace_len);
01444 
01445   return TRUE;
01446 }
01447 
01448 /* Unicode macros and utf8_validate() from GLib Owen Taylor, Havoc
01449  * Pennington, and Tom Tromey are the authors and authorized relicense.
01450  */
01451 
01457 #define UTF8_COMPUTE(Char, Mask, Len)                                         \
01458   if (Char < 128)                                                             \
01459     {                                                                         \
01460       Len = 1;                                                                \
01461       Mask = 0x7f;                                                            \
01462     }                                                                         \
01463   else if ((Char & 0xe0) == 0xc0)                                             \
01464     {                                                                         \
01465       Len = 2;                                                                \
01466       Mask = 0x1f;                                                            \
01467     }                                                                         \
01468   else if ((Char & 0xf0) == 0xe0)                                             \
01469     {                                                                         \
01470       Len = 3;                                                                \
01471       Mask = 0x0f;                                                            \
01472     }                                                                         \
01473   else if ((Char & 0xf8) == 0xf0)                                             \
01474     {                                                                         \
01475       Len = 4;                                                                \
01476       Mask = 0x07;                                                            \
01477     }                                                                         \
01478   else if ((Char & 0xfc) == 0xf8)                                             \
01479     {                                                                         \
01480       Len = 5;                                                                \
01481       Mask = 0x03;                                                            \
01482     }                                                                         \
01483   else if ((Char & 0xfe) == 0xfc)                                             \
01484     {                                                                         \
01485       Len = 6;                                                                \
01486       Mask = 0x01;                                                            \
01487     }                                                                         \
01488   else                                                                        \
01489     Len = -1;
01490 
01495 #define UTF8_LENGTH(Char)              \
01496   ((Char) < 0x80 ? 1 :                 \
01497    ((Char) < 0x800 ? 2 :               \
01498     ((Char) < 0x10000 ? 3 :            \
01499      ((Char) < 0x200000 ? 4 :          \
01500       ((Char) < 0x4000000 ? 5 : 6)))))
01501    
01511 #define UTF8_GET(Result, Chars, Count, Mask, Len)                             \
01512   (Result) = (Chars)[0] & (Mask);                                             \
01513   for ((Count) = 1; (Count) < (Len); ++(Count))                               \
01514     {                                                                         \
01515       if (((Chars)[(Count)] & 0xc0) != 0x80)                                  \
01516         {                                                                     \
01517           (Result) = -1;                                                      \
01518           break;                                                              \
01519         }                                                                     \
01520       (Result) <<= 6;                                                         \
01521       (Result) |= ((Chars)[(Count)] & 0x3f);                                  \
01522     }
01523 
01529 #define UNICODE_VALID(Char)                   \
01530     ((Char) < 0x110000 &&                     \
01531      (((Char) & 0xFFFFF800) != 0xD800) &&     \
01532      ((Char) < 0xFDD0 || (Char) > 0xFDEF) &&  \
01533      ((Char) & 0xFFFF) != 0xFFFF)
01534 
01545 void
01546 _dbus_string_get_unichar (const DBusString *str,
01547                           int               start,
01548                           dbus_unichar_t   *ch_return,
01549                           int              *end_return)
01550 {
01551   int i, mask, len;
01552   dbus_unichar_t result;
01553   unsigned char c;
01554   unsigned char *p;
01555   DBUS_CONST_STRING_PREAMBLE (str);
01556   _dbus_assert (start >= 0);
01557   _dbus_assert (start <= real->len);
01558   
01559   if (ch_return)
01560     *ch_return = 0;
01561   if (end_return)
01562     *end_return = real->len;
01563   
01564   mask = 0;
01565   p = real->str + start;
01566   c = *p;
01567   
01568   UTF8_COMPUTE (c, mask, len);
01569   if (len == -1)
01570     return;
01571   UTF8_GET (result, p, i, mask, len);
01572 
01573   if (result == (dbus_unichar_t)-1)
01574     return;
01575 
01576   if (ch_return)
01577     *ch_return = result;
01578   if (end_return)
01579     *end_return = start + len;
01580 }
01581 
01596 dbus_bool_t
01597 _dbus_string_find (const DBusString *str,
01598                    int               start,
01599                    const char       *substr,
01600                    int              *found)
01601 {
01602   return _dbus_string_find_to (str, start,
01603                                ((const DBusRealString*)str)->len,
01604                                substr, found);
01605 }
01606 
01623 dbus_bool_t
01624 _dbus_string_find_to (const DBusString *str,
01625                       int               start,
01626                       int               end,
01627                       const char       *substr,
01628                       int              *found)
01629 {
01630   int i;
01631   DBUS_CONST_STRING_PREAMBLE (str);
01632   _dbus_assert (substr != NULL);
01633   _dbus_assert (start <= real->len);
01634   _dbus_assert (start >= 0);
01635   _dbus_assert (substr != NULL);
01636   _dbus_assert (end <= real->len);
01637   _dbus_assert (start <= end);
01638 
01639   /* we always "find" an empty string */
01640   if (*substr == '\0')
01641     {
01642       if (found)
01643         *found = start;
01644       return TRUE;
01645     }
01646 
01647   i = start;
01648   while (i < end)
01649     {
01650       if (real->str[i] == substr[0])
01651         {
01652           int j = i + 1;
01653           
01654           while (j < end)
01655             {
01656               if (substr[j - i] == '\0')
01657                 break;
01658               else if (real->str[j] != substr[j - i])
01659                 break;
01660               
01661               ++j;
01662             }
01663 
01664           if (substr[j - i] == '\0')
01665             {
01666               if (found)
01667                 *found = i;
01668               return TRUE;
01669             }
01670         }
01671       
01672       ++i;
01673     }
01674 
01675   if (found)
01676     *found = end;
01677   
01678   return FALSE;  
01679 }
01680 
01691 dbus_bool_t
01692 _dbus_string_find_byte_backward (const DBusString  *str,
01693                                  int                start,
01694                                  unsigned char      byte,
01695                                  int               *found)
01696 {
01697   int i;
01698   DBUS_CONST_STRING_PREAMBLE (str);
01699   _dbus_assert (start <= real->len);
01700   _dbus_assert (start >= 0);
01701   _dbus_assert (found != NULL);
01702 
01703   i = start - 1;
01704   while (i >= 0)
01705     {
01706       if (real->str[i] == byte)
01707         break;
01708       
01709       --i;
01710     }
01711 
01712   if (found)
01713     *found = i;
01714 
01715   return i >= 0;
01716 }
01717 
01728 dbus_bool_t
01729 _dbus_string_find_blank (const DBusString *str,
01730                          int               start,
01731                          int              *found)
01732 {
01733   int i;
01734   DBUS_CONST_STRING_PREAMBLE (str);
01735   _dbus_assert (start <= real->len);
01736   _dbus_assert (start >= 0);
01737   
01738   i = start;
01739   while (i < real->len)
01740     {
01741       if (real->str[i] == ' ' ||
01742           real->str[i] == '\t')
01743         {
01744           if (found)
01745             *found = i;
01746           return TRUE;
01747         }
01748       
01749       ++i;
01750     }
01751 
01752   if (found)
01753     *found = real->len;
01754   
01755   return FALSE;
01756 }
01757 
01766 void
01767 _dbus_string_skip_blank (const DBusString *str,
01768                          int               start,
01769                          int              *end)
01770 {
01771   int i;
01772   DBUS_CONST_STRING_PREAMBLE (str);
01773   _dbus_assert (start <= real->len);
01774   _dbus_assert (start >= 0);
01775   
01776   i = start;
01777   while (i < real->len)
01778     {
01779       if (!(real->str[i] == ' ' ||
01780             real->str[i] == '\t'))
01781         break;
01782       
01783       ++i;
01784     }
01785 
01786   _dbus_assert (i == real->len || !(real->str[i] == ' ' ||
01787                                     real->str[i] == '\t'));
01788   
01789   if (end)
01790     *end = i;
01791 }
01792 
01801 void
01802 _dbus_string_skip_white (const DBusString *str,
01803                          int               start,
01804                          int              *end)
01805 {
01806   int i;
01807   DBUS_CONST_STRING_PREAMBLE (str);
01808   _dbus_assert (start <= real->len);
01809   _dbus_assert (start >= 0);
01810   
01811   i = start;
01812   while (i < real->len)
01813     {
01814       if (!(real->str[i] == ' ' ||
01815             real->str[i] == '\n' ||
01816             real->str[i] == '\r' ||
01817             real->str[i] == '\t'))
01818         break;
01819       
01820       ++i;
01821     }
01822 
01823   _dbus_assert (i == real->len || !(real->str[i] == ' ' ||
01824                                     real->str[i] == '\t'));
01825   
01826   if (end)
01827     *end = i;
01828 }
01829 
01845 dbus_bool_t
01846 _dbus_string_pop_line (DBusString *source,
01847                        DBusString *dest)
01848 {
01849   int eol;
01850   dbus_bool_t have_newline;
01851   
01852   _dbus_string_set_length (dest, 0);
01853   
01854   eol = 0;
01855   if (_dbus_string_find (source, 0, "\n", &eol))
01856     {
01857       have_newline = TRUE;
01858       eol += 1; /* include newline */
01859     }
01860   else
01861     {
01862       eol = _dbus_string_get_length (source);
01863       have_newline = FALSE;
01864     }
01865 
01866   if (eol == 0)
01867     return FALSE; /* eof */
01868   
01869   if (!_dbus_string_move_len (source, 0, eol,
01870                               dest, 0))
01871     {
01872       return FALSE;
01873     }
01874 
01875   /* dump the newline and the \r if we have one */
01876   if (have_newline)
01877     {
01878       dbus_bool_t have_cr;
01879       
01880       _dbus_assert (_dbus_string_get_length (dest) > 0);
01881 
01882       if (_dbus_string_get_length (dest) > 1 &&
01883           _dbus_string_get_byte (dest,
01884                                  _dbus_string_get_length (dest) - 2) == '\r')
01885         have_cr = TRUE;
01886       else
01887         have_cr = FALSE;
01888         
01889       _dbus_string_set_length (dest,
01890                                _dbus_string_get_length (dest) -
01891                                (have_cr ? 2 : 1));
01892     }
01893   
01894   return TRUE;
01895 }
01896 
01903 void
01904 _dbus_string_delete_first_word (DBusString *str)
01905 {
01906   int i;
01907   
01908   if (_dbus_string_find_blank (str, 0, &i))
01909     _dbus_string_skip_blank (str, i, &i);
01910 
01911   _dbus_string_delete (str, 0, i);
01912 }
01913 
01919 void
01920 _dbus_string_delete_leading_blanks (DBusString *str)
01921 {
01922   int i;
01923   
01924   _dbus_string_skip_blank (str, 0, &i);
01925 
01926   if (i > 0)
01927     _dbus_string_delete (str, 0, i);
01928 }
01929 
01939 dbus_bool_t
01940 _dbus_string_equal (const DBusString *a,
01941                     const DBusString *b)
01942 {
01943   const unsigned char *ap;
01944   const unsigned char *bp;
01945   const unsigned char *a_end;
01946   const DBusRealString *real_a = (const DBusRealString*) a;
01947   const DBusRealString *real_b = (const DBusRealString*) b;
01948   DBUS_GENERIC_STRING_PREAMBLE (real_a);
01949   DBUS_GENERIC_STRING_PREAMBLE (real_b);
01950 
01951   if (real_a->len != real_b->len)
01952     return FALSE;
01953 
01954   ap = real_a->str;
01955   bp = real_b->str;
01956   a_end = real_a->str + real_a->len;
01957   while (ap != a_end)
01958     {
01959       if (*ap != *bp)
01960         return FALSE;
01961       
01962       ++ap;
01963       ++bp;
01964     }
01965 
01966   return TRUE;
01967 }
01968 
01981 dbus_bool_t
01982 _dbus_string_equal_len (const DBusString *a,
01983                         const DBusString *b,
01984                         int               len)
01985 {
01986   const unsigned char *ap;
01987   const unsigned char *bp;
01988   const unsigned char *a_end;
01989   const DBusRealString *real_a = (const DBusRealString*) a;
01990   const DBusRealString *real_b = (const DBusRealString*) b;
01991   DBUS_GENERIC_STRING_PREAMBLE (real_a);
01992   DBUS_GENERIC_STRING_PREAMBLE (real_b);
01993 
01994   if (real_a->len != real_b->len &&
01995       (real_a->len < len || real_b->len < len))
01996     return FALSE;
01997 
01998   ap = real_a->str;
01999   bp = real_b->str;
02000   a_end = real_a->str + MIN (real_a->len, len);
02001   while (ap != a_end)
02002     {
02003       if (*ap != *bp)
02004         return FALSE;
02005       
02006       ++ap;
02007       ++bp;
02008     }
02009 
02010   return TRUE;
02011 }
02012 
02020 dbus_bool_t
02021 _dbus_string_equal_c_str (const DBusString *a,
02022                           const char       *c_str)
02023 {
02024   const unsigned char *ap;
02025   const unsigned char *bp;
02026   const unsigned char *a_end;
02027   const DBusRealString *real_a = (const DBusRealString*) a;
02028   DBUS_GENERIC_STRING_PREAMBLE (real_a);
02029   _dbus_assert (c_str != NULL);
02030   
02031   ap = real_a->str;
02032   bp = (const unsigned char*) c_str;
02033   a_end = real_a->str + real_a->len;
02034   while (ap != a_end && *bp)
02035     {
02036       if (*ap != *bp)
02037         return FALSE;
02038       
02039       ++ap;
02040       ++bp;
02041     }
02042 
02043   if (ap != a_end || *bp)
02044     return FALSE;
02045   
02046   return TRUE;
02047 }
02048 
02056 dbus_bool_t
02057 _dbus_string_starts_with_c_str (const DBusString *a,
02058                                 const char       *c_str)
02059 {
02060   const unsigned char *ap;
02061   const unsigned char *bp;
02062   const unsigned char *a_end;
02063   const DBusRealString *real_a = (const DBusRealString*) a;
02064   DBUS_GENERIC_STRING_PREAMBLE (real_a);
02065   _dbus_assert (c_str != NULL);
02066   
02067   ap = real_a->str;
02068   bp = (const unsigned char*) c_str;
02069   a_end = real_a->str + real_a->len;
02070   while (ap != a_end && *bp)
02071     {
02072       if (*ap != *bp)
02073         return FALSE;
02074       
02075       ++ap;
02076       ++bp;
02077     }
02078 
02079   if (*bp == '\0')
02080     return TRUE;
02081   else
02082     return FALSE;
02083 }
02084 
02094 dbus_bool_t
02095 _dbus_string_ends_with_c_str (const DBusString *a,
02096                               const char       *c_str)
02097 {
02098   const unsigned char *ap;
02099   const unsigned char *bp;
02100   const unsigned char *a_end;
02101   unsigned long c_str_len;
02102   const DBusRealString *real_a = (const DBusRealString*) a;
02103   DBUS_GENERIC_STRING_PREAMBLE (real_a);
02104   _dbus_assert (c_str != NULL);
02105   
02106   c_str_len = strlen (c_str);
02107   if (((unsigned long)real_a->len) < c_str_len)
02108     return FALSE;
02109   
02110   ap = real_a->str + (real_a->len - c_str_len);
02111   bp = (const unsigned char*) c_str;
02112   a_end = real_a->str + real_a->len;
02113   while (ap != a_end)
02114     {
02115       if (*ap != *bp)
02116         return FALSE;
02117       
02118       ++ap;
02119       ++bp;
02120     }
02121 
02122   _dbus_assert (*ap == '\0');
02123   _dbus_assert (*bp == '\0');
02124   
02125   return TRUE;
02126 }
02127 
02128 static const signed char base64_table[] = {
02129   /* 0 */ 'A',
02130   /* 1 */ 'B',
02131   /* 2 */ 'C',
02132   /* 3 */ 'D',
02133   /* 4 */ 'E',
02134   /* 5 */ 'F',
02135   /* 6 */ 'G',
02136   /* 7 */ 'H',
02137   /* 8 */ 'I',
02138   /* 9 */ 'J',
02139   /* 10 */ 'K',
02140   /* 11 */ 'L',
02141   /* 12 */ 'M',
02142   /* 13 */ 'N',
02143   /* 14 */ 'O',
02144   /* 15 */ 'P',
02145   /* 16 */ 'Q',
02146   /* 17 */ 'R',
02147   /* 18 */ 'S',
02148   /* 19 */ 'T',
02149   /* 20 */ 'U',
02150   /* 21 */ 'V',
02151   /* 22 */ 'W',
02152   /* 23 */ 'X',
02153   /* 24 */ 'Y',
02154   /* 25 */ 'Z',
02155   /* 26 */ 'a',
02156   /* 27 */ 'b',
02157   /* 28 */ 'c',
02158   /* 29 */ 'd',
02159   /* 30 */ 'e',
02160   /* 31 */ 'f',
02161   /* 32 */ 'g',
02162   /* 33 */ 'h',
02163   /* 34 */ 'i',
02164   /* 35 */ 'j',
02165   /* 36 */ 'k',
02166   /* 37 */ 'l',
02167   /* 38 */ 'm',
02168   /* 39 */ 'n',
02169   /* 40 */ 'o',
02170   /* 41 */ 'p',
02171   /* 42 */ 'q',
02172   /* 43 */ 'r',
02173   /* 44 */ 's',
02174   /* 45 */ 't',
02175   /* 46 */ 'u',
02176   /* 47 */ 'v',
02177   /* 48 */ 'w',
02178   /* 49 */ 'x',
02179   /* 50 */ 'y',
02180   /* 51 */ 'z',
02181   /* 52 */ '0',
02182   /* 53 */ '1',
02183   /* 54 */ '2',
02184   /* 55 */ '3',
02185   /* 56 */ '4',
02186   /* 57 */ '5',
02187   /* 58 */ '6',
02188   /* 59 */ '7',
02189   /* 60 */ '8',
02190   /* 61 */ '9',
02191   /* 62 */ '+',
02192   /* 63 */ '/'
02193 };
02194 
02196 #define UNBASE64_MIN_CHAR (43)
02197 
02198 #define UNBASE64_MAX_CHAR (122)
02199 
02202 #define UNBASE64_TABLE_OFFSET UNBASE64_MIN_CHAR
02203 static const signed char unbase64_table[] = {
02204   /* 43 + */ 62,
02205   /* 44 , */ -1,
02206   /* 45 - */ -1,
02207   /* 46 . */ -1,
02208   /* 47 / */ 63,
02209   /* 48 0 */ 52,
02210   /* 49 1 */ 53,
02211   /* 50 2 */ 54,
02212   /* 51 3 */ 55,
02213   /* 52 4 */ 56,
02214   /* 53 5 */ 57,
02215   /* 54 6 */ 58,
02216   /* 55 7 */ 59,
02217   /* 56 8 */ 60,
02218   /* 57 9 */ 61,
02219   /* 58 : */ -1,
02220   /* 59 ; */ -1,
02221   /* 60 < */ -1,
02222   /* 61 = */ -1,
02223   /* 62 > */ -1,
02224   /* 63 ? */ -1,
02225   /* 64 @ */ -1,
02226   /* 65 A */ 0,
02227   /* 66 B */ 1,
02228   /* 67 C */ 2,
02229   /* 68 D */ 3,
02230   /* 69 E */ 4,
02231   /* 70 F */ 5,
02232   /* 71 G */ 6,
02233   /* 72 H */ 7,
02234   /* 73 I */ 8,
02235   /* 74 J */ 9,
02236   /* 75 K */ 10,
02237   /* 76 L */ 11,
02238   /* 77 M */ 12,
02239   /* 78 N */ 13,
02240   /* 79 O */ 14,
02241   /* 80 P */ 15,
02242   /* 81 Q */ 16,
02243   /* 82 R */ 17,
02244   /* 83 S */ 18,
02245   /* 84 T */ 19,
02246   /* 85 U */ 20,
02247   /* 86 V */ 21,
02248   /* 87 W */ 22,
02249   /* 88 X */ 23,
02250   /* 89 Y */ 24,
02251   /* 90 Z */ 25,
02252   /* 91 [ */ -1,
02253   /* 92 \ */ -1,
02254   /* 93 ] */ -1,
02255   /* 94 ^ */ -1,
02256   /* 95 _ */ -1,
02257   /* 96 ` */ -1,
02258   /* 97 a */ 26,
02259   /* 98 b */ 27,
02260   /* 99 c */ 28,
02261   /* 100 d */ 29,
02262   /* 101 e */ 30,
02263   /* 102 f */ 31,
02264   /* 103 g */ 32,
02265   /* 104 h */ 33,
02266   /* 105 i */ 34,
02267   /* 106 j */ 35,
02268   /* 107 k */ 36,
02269   /* 108 l */ 37,
02270   /* 109 m */ 38,
02271   /* 110 n */ 39,
02272   /* 111 o */ 40,
02273   /* 112 p */ 41,
02274   /* 113 q */ 42,
02275   /* 114 r */ 43,
02276   /* 115 s */ 44,
02277   /* 116 t */ 45,
02278   /* 117 u */ 46,
02279   /* 118 v */ 47,
02280   /* 119 w */ 48,
02281   /* 120 x */ 49,
02282   /* 121 y */ 50,
02283   /* 122 z */ 51
02284 };
02285 
02295 dbus_bool_t
02296 _dbus_string_base64_encode (const DBusString *source,
02297                             int               start,
02298                             DBusString       *dest,
02299                             int               insert_at)
02300 {
02301   int source_len;
02302   unsigned int dest_len; /* unsigned for overflow checks below */
02303   const unsigned char *s;
02304   unsigned char *d;
02305   const unsigned char *triplet_end;
02306   const unsigned char *final_end;
02307   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);  
02308   _dbus_assert (source != dest);
02309   
02310   /* For each 24 bits (3 bytes) of input, we have 4 bytes of
02311    * output.
02312    */
02313   source_len = real_source->len - start;
02314   dest_len = (source_len / 3) * 4;
02315   if (source_len % 3 != 0)
02316     dest_len += 4;
02317 
02318   if (dest_len > (unsigned int) real_dest->max_length)
02319     return FALSE;
02320   
02321   if (source_len == 0)
02322     return TRUE;
02323   
02324   if (!open_gap (dest_len, real_dest, insert_at))
02325     return FALSE;
02326 
02327   d = real_dest->str + insert_at;
02328   s = real_source->str + start;
02329   final_end = real_source->str + (start + source_len);
02330   triplet_end = final_end - (source_len % 3);
02331   _dbus_assert (triplet_end <= final_end);
02332   _dbus_assert ((final_end - triplet_end) < 3);
02333 
02334 #define ENCODE_64(v) (base64_table[ (unsigned char) (v) ])
02335 #define SIX_BITS_MASK (0x3f)
02336   _dbus_assert (SIX_BITS_MASK < _DBUS_N_ELEMENTS (base64_table));
02337   
02338   while (s != triplet_end)
02339     {
02340       unsigned int triplet;
02341 
02342       triplet = s[2] | (s[1] << 8) | (s[0] << 16);
02343 
02344       /* Encode each 6 bits. */
02345 
02346       *d++ = ENCODE_64 (triplet >> 18);
02347       *d++ = ENCODE_64 ((triplet >> 12) & SIX_BITS_MASK);
02348       *d++ = ENCODE_64 ((triplet >> 6) & SIX_BITS_MASK);
02349       *d++ = ENCODE_64 (triplet & SIX_BITS_MASK);
02350       
02351       s += 3;
02352     }
02353 
02354   switch (final_end - triplet_end)
02355     {
02356     case 2:
02357       {
02358         unsigned int doublet;
02359         
02360         doublet = s[1] | (s[0] << 8);        
02361 
02362         *d++ = ENCODE_64 (doublet >> 12);
02363         *d++ = ENCODE_64 ((doublet >> 6) & SIX_BITS_MASK);
02364         *d++ = ENCODE_64 (doublet & SIX_BITS_MASK);
02365         *d++ = '=';
02366       }
02367       break;
02368     case 1:
02369       {
02370         unsigned int singlet;
02371         
02372         singlet = s[0];
02373 
02374         *d++ = ENCODE_64 ((singlet >> 6) & SIX_BITS_MASK);
02375         *d++ = ENCODE_64 (singlet & SIX_BITS_MASK);
02376         *d++ = '=';
02377         *d++ = '=';
02378       }
02379       break;
02380     case 0:
02381       break;
02382     }
02383 
02384   _dbus_assert (d == (real_dest->str + (insert_at + dest_len)));
02385 
02386   return TRUE;
02387 }
02388 
02403 dbus_bool_t
02404 _dbus_string_base64_decode (const DBusString *source,
02405                             int               start,
02406                             DBusString       *dest,
02407                             int               insert_at)
02408 {
02409   int source_len;
02410   const char *s;
02411   const char *end;
02412   DBusString result;
02413   unsigned int triplet = 0;
02414   int sextet_count;
02415   int pad_count;
02416   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
02417   _dbus_assert (source != dest);
02418   
02419   source_len = real_source->len - start;
02420   s = real_source->str + start;
02421   end = real_source->str + source_len;
02422 
02423   if (source_len == 0)
02424     return TRUE;
02425 
02426   if (!_dbus_string_init (&result))
02427     return FALSE;
02428 
02429   pad_count = 0;
02430   sextet_count = 0;
02431   while (s != end)
02432     {
02433       /* The idea is to just skip anything that isn't
02434        * a base64 char - it's allowed to have whitespace,
02435        * newlines, etc. in here. We also ignore trailing
02436        * base64 chars, though that's suspicious.
02437        */
02438       
02439       if (*s >= UNBASE64_MIN_CHAR &&
02440           *s <= UNBASE64_MAX_CHAR)
02441         {
02442           if (*s == '=')
02443             {
02444               /* '=' is padding, doesn't represent additional data
02445                * but does increment our count.
02446                */
02447               pad_count += 1;
02448               sextet_count += 1;
02449             }
02450           else
02451             {
02452               int val;
02453 
02454               val = unbase64_table[(*s) - UNBASE64_TABLE_OFFSET];
02455 
02456               if (val >= 0)
02457                 {
02458                   triplet <<= 6;
02459                   triplet |= (unsigned int) val;
02460                   sextet_count += 1;
02461                 }
02462             }
02463 
02464           if (sextet_count == 4)
02465             {
02466               /* no pad = 3 bytes, 1 pad = 2 bytes, 2 pad = 1 byte */
02467 
02468 
02469               /* AUDIT: Comment doesn't mention 4 pad => 0,
02470                *         3 pad => 1 byte, though the code should
02471                *        work fine if those are the required outputs.
02472                *
02473                *        I assume that the spec requires dropping
02474                *        the top two bits of, say, ///= which is > 2 
02475                *        bytes worth of bits. (Or otherwise, you couldn't
02476                *        actually represent 2 byte sequences.
02477                */
02478               
02479               if (pad_count < 1)
02480                 {
02481                   if (!_dbus_string_append_byte (&result,
02482                                                  triplet >> 16))
02483                     goto failed;
02484                 }
02485               
02486               if (pad_count < 2)
02487                 {
02488                   if (!_dbus_string_append_byte (&result,
02489                                                  (triplet >> 8) & 0xff))
02490                     goto failed;
02491                 }
02492               
02493               if (!_dbus_string_append_byte (&result,
02494                                              triplet & 0xff))
02495                 goto failed;
02496               
02497               sextet_count = 0;
02498               pad_count = 0;
02499               triplet = 0;
02500             }
02501         }
02502       
02503       ++s;
02504     }
02505 
02506   if (!_dbus_string_move (&result, 0, dest, insert_at))
02507     {
02508       _dbus_string_free (&result);
02509       return FALSE;
02510     }
02511 
02512   _dbus_string_free (&result);
02513 
02514   return TRUE;
02515 
02516  failed:
02517   _dbus_string_free (&result);
02518 
02519   return FALSE;
02520 }
02521 
02532 dbus_bool_t
02533 _dbus_string_hex_encode (const DBusString *source,
02534                          int               start,
02535                          DBusString       *dest,
02536                          int               insert_at)
02537 {
02538   DBusString result;
02539   const char hexdigits[16] = {
02540     '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
02541     'a', 'b', 'c', 'd', 'e', 'f'
02542   };
02543   const unsigned char *p;
02544   const unsigned char *end;
02545   dbus_bool_t retval;
02546   
02547   _dbus_assert (start <= _dbus_string_get_length (source));
02548 
02549   if (!_dbus_string_init (&result))
02550     return FALSE;
02551 
02552   retval = FALSE;
02553   
02554   p = (const unsigned char*) _dbus_string_get_const_data (source);
02555   end = p + _dbus_string_get_length (source);
02556   p += start;
02557   
02558   while (p != end)
02559     {
02560       if (!_dbus_string_append_byte (&result,
02561                                      hexdigits[(*p >> 4)]))
02562         goto out;
02563       
02564       if (!_dbus_string_append_byte (&result,
02565                                      hexdigits[(*p & 0x0f)]))
02566         goto out;
02567 
02568       ++p;
02569     }
02570 
02571   if (!_dbus_string_move (&result, 0, dest, insert_at))
02572     goto out;
02573 
02574   retval = TRUE;
02575 
02576  out:
02577   _dbus_string_free (&result);
02578   return retval;
02579 }
02580 
02590 dbus_bool_t
02591 _dbus_string_hex_decode (const DBusString *source,
02592                          int               start,
02593                          DBusString       *dest,
02594                          int               insert_at)
02595 {
02596   DBusString result;
02597   const unsigned char *p;
02598   const unsigned char *end;
02599   dbus_bool_t retval;
02600   dbus_bool_t high_bits;
02601   
02602   _dbus_assert (start <= _dbus_string_get_length (source));
02603 
02604   if (!_dbus_string_init (&result))
02605     return FALSE;
02606 
02607   retval = FALSE;
02608 
02609   high_bits = TRUE;
02610   p = (const unsigned char*) _dbus_string_get_const_data (source);
02611   end = p + _dbus_string_get_length (source);
02612   p += start;
02613   
02614   while (p != end)
02615     {
02616       unsigned int val;
02617 
02618       switch (*p)
02619         {
02620         case '0':
02621           val = 0;
02622           break;
02623         case '1':
02624           val = 1;
02625           break;
02626         case '2':
02627           val = 2;
02628           break;
02629         case '3':
02630           val = 3;
02631           break;
02632         case '4':
02633           val = 4;
02634           break;
02635         case '5':
02636           val = 5;
02637           break;
02638         case '6':
02639           val = 6;
02640           break;
02641         case '7':
02642           val = 7;
02643           break;
02644         case '8':
02645           val = 8;
02646           break;
02647         case '9':
02648           val = 9;
02649           break;
02650         case 'a':
02651         case 'A':
02652           val = 10;
02653           break;
02654         case 'b':
02655         case 'B':
02656           val = 11;
02657           break;
02658         case 'c':
02659         case 'C':
02660           val = 12;
02661           break;
02662         case 'd':
02663         case 'D':
02664           val = 13;
02665           break;
02666         case 'e':
02667         case 'E':
02668           val = 14;
02669           break;
02670         case 'f':
02671         case 'F':
02672           val = 15;
02673           break;
02674         default:
02675           val = 0;
02676           _dbus_verbose ("invalid character '%c' in hex encoded text\n",
02677                          *p);
02678           goto out;
02679         }
02680 
02681       if (high_bits)
02682         {
02683           if (!_dbus_string_append_byte (&result,
02684                                          val << 4))
02685             goto out;
02686         }
02687       else
02688         {
02689           int len;
02690           unsigned char b;
02691 
02692           len = _dbus_string_get_length (&result);
02693           
02694           b = _dbus_string_get_byte (&result, len - 1);
02695 
02696           b |= val;
02697 
02698           _dbus_string_set_byte (&result, len - 1, b);
02699         }
02700 
02701       high_bits = !high_bits;
02702 
02703       ++p;
02704     }
02705 
02706   if (!_dbus_string_move (&result, 0, dest, insert_at))
02707     goto out;
02708 
02709   retval = TRUE;
02710   
02711  out:
02712   _dbus_string_free (&result);  
02713   return retval;
02714 }
02715 
02729 dbus_bool_t
02730 _dbus_string_validate_ascii (const DBusString *str,
02731                              int               start,
02732                              int               len)
02733 {
02734   const unsigned char *s;
02735   const unsigned char *end;
02736   DBUS_CONST_STRING_PREAMBLE (str);
02737   _dbus_assert (start >= 0);
02738   _dbus_assert (start <= real->len);
02739   _dbus_assert (len >= 0);
02740   
02741   if (len > real->len - start)
02742     return FALSE;
02743   
02744   s = real->str + start;
02745   end = s + len;
02746   while (s != end)
02747     {
02748       if (_DBUS_UNLIKELY (*s == '\0' ||
02749                           ((*s & ~0x7f) != 0)))
02750         return FALSE;
02751         
02752       ++s;
02753     }
02754   
02755   return TRUE;
02756 }
02757 
02773 dbus_bool_t
02774 _dbus_string_validate_utf8  (const DBusString *str,
02775                              int               start,
02776                              int               len)
02777 {
02778   const unsigned char *p;
02779   const unsigned char *end;
02780   DBUS_CONST_STRING_PREAMBLE (str);
02781   _dbus_assert (start >= 0);
02782   _dbus_assert (start <= real->len);
02783   _dbus_assert (len >= 0);
02784 
02785   /* we are doing _DBUS_UNLIKELY() here which might be
02786    * dubious in a generic library like GLib, but in D-BUS
02787    * we know we're validating messages and that it would
02788    * only be evil/broken apps that would have invalid
02789    * UTF-8. Also, this function seems to be a performance
02790    * bottleneck in profiles.
02791    */
02792   
02793   if (_DBUS_UNLIKELY (len > real->len - start))
02794     return FALSE;
02795   
02796   p = real->str + start;
02797   end = p + len;
02798   
02799   while (p < end)
02800     {
02801       int i, mask = 0, char_len;
02802       dbus_unichar_t result;
02803       unsigned char c = (unsigned char) *p;
02804       
02805       UTF8_COMPUTE (c, mask, char_len);
02806 
02807       if (_DBUS_UNLIKELY (char_len == -1))
02808         break;
02809 
02810       /* check that the expected number of bytes exists in the remaining length */
02811       if (_DBUS_UNLIKELY ((end - p) < char_len))
02812         break;
02813         
02814       UTF8_GET (result, p, i, mask, char_len);
02815 
02816       if (_DBUS_UNLIKELY (UTF8_LENGTH (result) != char_len)) /* Check for overlong UTF-8 */
02817         break;
02818 
02819       if (_DBUS_UNLIKELY (result == (dbus_unichar_t)-1))
02820         break;
02821 
02822       if (_DBUS_UNLIKELY (!UNICODE_VALID (result)))
02823         break;
02824       
02825       p += char_len;
02826     }
02827 
02828   /* See that we covered the entire length if a length was
02829    * passed in
02830    */
02831   if (_DBUS_UNLIKELY (p != end))
02832     return FALSE;
02833   else
02834     return TRUE;
02835 }
02836 
02850 dbus_bool_t
02851 _dbus_string_validate_nul (const DBusString *str,
02852                            int               start,
02853                            int               len)
02854 {
02855   const unsigned char *s;
02856   const unsigned char *end;
02857   DBUS_CONST_STRING_PREAMBLE (str);
02858   _dbus_assert (start >= 0);
02859   _dbus_assert (len >= 0);
02860   _dbus_assert (start <= real->len);
02861   
02862   if (len > real->len - start)
02863     return FALSE;
02864   
02865   s = real->str + start;
02866   end = s + len;
02867   while (s != end)
02868     {
02869       if (_DBUS_UNLIKELY (*s != '\0'))
02870         return FALSE;
02871       ++s;
02872     }
02873   
02874   return TRUE;
02875 }
02876 
02894 dbus_bool_t
02895 _dbus_string_validate_path (const DBusString  *str,
02896                             int                start,
02897                             int                len)
02898 {
02899   const unsigned char *s;
02900   const unsigned char *end;
02901   const unsigned char *last_slash;
02902   
02903   DBUS_CONST_STRING_PREAMBLE (str);
02904   _dbus_assert (start >= 0);
02905   _dbus_assert (len >= 0);
02906   _dbus_assert (start <= real->len);
02907   
02908   if (len > real->len - start)
02909     return FALSE;
02910 
02911   if (len > DBUS_MAXIMUM_NAME_LENGTH)
02912     return FALSE;
02913 
02914   if (len == 0)
02915     return FALSE;
02916 
02917   s = real->str + start;
02918   end = s + len;
02919 
02920   if (*s != '/')
02921     return FALSE;
02922   last_slash = s;
02923   ++s;
02924   
02925   while (s != end)
02926     {
02927       if (*s == '/')
02928         {
02929           if ((s - last_slash) < 2)
02930             return FALSE; /* no empty path components allowed */
02931 
02932           last_slash = s;
02933         }
02934       
02935       ++s;
02936     }
02937 
02938   if ((end - last_slash) < 2 &&
02939       len > 1)
02940     return FALSE; /* trailing slash not allowed unless the string is "/" */
02941   
02942   return TRUE;
02943 }
02944 
02945 #define VALID_INITIAL_NAME_CHARACTER(c)         \
02946   ( ((c) >= 'A' && (c) <= 'Z') ||               \
02947     ((c) >= 'a' && (c) <= 'z') ||               \
02948     ((c) == '_') )
02949 
02950 #define VALID_NAME_CHARACTER(c)                 \
02951   ( ((c) >= '0' && (c) <= '9') ||               \
02952     ((c) >= 'A' && (c) <= 'Z') ||               \
02953     ((c) >= 'a' && (c) <= 'z') ||               \
02954     ((c) == '_') )
02955 
02969 dbus_bool_t
02970 _dbus_string_validate_interface (const DBusString  *str,
02971                                  int                start,
02972                                  int                len)
02973 {  
02974   const unsigned char *s;
02975   const unsigned char *end;
02976   const unsigned char *iface;
02977   const unsigned char *last_dot;
02978   
02979   DBUS_CONST_STRING_PREAMBLE (str);
02980   _dbus_assert (start >= 0);
02981   _dbus_assert (len >= 0);
02982   _dbus_assert (start <= real->len);
02983   
02984   if (len > real->len - start)
02985     return FALSE;
02986 
02987   if (len > DBUS_MAXIMUM_NAME_LENGTH)
02988     return FALSE;
02989 
02990   if (len == 0)
02991     return FALSE;
02992 
02993   last_dot = NULL;
02994   iface = real->str + start;
02995   end = iface + len;
02996   s = iface;
02997 
02998   /* check special cases of first char so it doesn't have to be done
02999    * in the loop. Note we know len > 0
03000    */
03001   if (_DBUS_UNLIKELY (*s == '.')) /* disallow starting with a . */
03002     return FALSE;
03003   else if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*s)))
03004     return FALSE;
03005   else
03006     ++s;
03007   
03008   while (s != end)
03009     {
03010       if (*s == '.')
03011         {
03012           if (_DBUS_UNLIKELY ((s + 1) == end))
03013             return FALSE;
03014           else if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*(s + 1))))
03015             return FALSE;
03016           last_dot = s;
03017           ++s; /* we just validated the next char, so skip two */
03018         }
03019       else if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s)))
03020         {
03021           return FALSE;
03022         }
03023       
03024       ++s;
03025     }
03026 
03027   if (_DBUS_UNLIKELY (last_dot == NULL))
03028     return FALSE;
03029   
03030   return TRUE;
03031 }
03032 
03046 dbus_bool_t
03047 _dbus_string_validate_member (const DBusString  *str,
03048                               int                start,
03049                               int                len)
03050 {
03051   const unsigned char *s;
03052   const unsigned char *end;
03053   const unsigned char *member;
03054   
03055   DBUS_CONST_STRING_PREAMBLE (str);
03056   _dbus_assert (start >= 0);
03057   _dbus_assert (len >= 0);
03058   _dbus_assert (start <= real->len);
03059   
03060   if (len > real->len - start)
03061     return FALSE;
03062 
03063   if (len > DBUS_MAXIMUM_NAME_LENGTH)
03064     return FALSE;
03065 
03066   if (len == 0)
03067     return FALSE;
03068 
03069   member = real->str + start;
03070   end = member + len;
03071   s = member;
03072 
03073   /* check special cases of first char so it doesn't have to be done
03074    * in the loop. Note we know len > 0
03075    */
03076 
03077   if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*s)))
03078     return FALSE;
03079   else
03080     ++s;
03081   
03082   while (s != end)
03083     {
03084       if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s)))
03085         {
03086           return FALSE;
03087         }
03088       
03089       ++s;
03090     }
03091   
03092   return TRUE;
03093 }
03094 
03108 dbus_bool_t
03109 _dbus_string_validate_error_name (const DBusString  *str,
03110                                   int                start,
03111                                   int                len)
03112 {
03113   /* Same restrictions as interface name at the moment */
03114   return _dbus_string_validate_interface (str, start, len);
03115 }
03116 
03117 /* This assumes the first char exists and is ':' */
03118 static dbus_bool_t
03119 _dbus_string_validate_base_service (const DBusString  *str,
03120                                     int                start,
03121                                     int                len)
03122 {
03123   const unsigned char *s;
03124   const unsigned char *end;
03125   const unsigned char *service;
03126   
03127   DBUS_CONST_STRING_PREAMBLE (str);
03128   _dbus_assert (start >= 0);
03129   _dbus_assert (len >= 0);
03130   _dbus_assert (start <= real->len);
03131   
03132   if (len > real->len - start)
03133     return FALSE;
03134 
03135   if (len > DBUS_MAXIMUM_NAME_LENGTH)
03136     return FALSE;
03137 
03138   _dbus_assert (len > 0);
03139 
03140   service = real->str + start;
03141   end = service + len;
03142   _dbus_assert (*service == ':');
03143   s = service + 1;
03144   
03145   while (s != end)
03146     {
03147       if (*s == '.')
03148         {
03149           if (_DBUS_UNLIKELY ((s + 1) == end))
03150             return FALSE;
03151           if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*(s + 1))))
03152             return FALSE;
03153           ++s; /* we just validated the next char, so skip two */
03154         }
03155       else if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s)))
03156         {
03157           return FALSE;
03158         }
03159       
03160       ++s;
03161     }
03162   
03163   return TRUE;
03164 }
03165 
03179 dbus_bool_t
03180 _dbus_string_validate_service (const DBusString  *str,
03181                                int                start,
03182                                int                len)
03183 {
03184   if (_DBUS_UNLIKELY (len == 0))
03185     return FALSE;
03186   if (_dbus_string_get_byte (str, start) == ':')
03187     return _dbus_string_validate_base_service (str, start, len);
03188   else
03189     return _dbus_string_validate_interface (str, start, len);
03190 }
03191 
03197 void
03198 _dbus_string_zero (DBusString *str)
03199 {
03200   DBUS_STRING_PREAMBLE (str);
03201 
03202   memset (real->str - real->align_offset, '\0', real->allocated);
03203 }
03206 #ifdef DBUS_BUILD_TESTS
03207 #include "dbus-test.h"
03208 #include <stdio.h>
03209 
03210 static void
03211 test_max_len (DBusString *str,
03212               int         max_len)
03213 {
03214   if (max_len > 0)
03215     {
03216       if (!_dbus_string_set_length (str, max_len - 1))
03217         _dbus_assert_not_reached ("setting len to one less than max should have worked");
03218     }
03219 
03220   if (!_dbus_string_set_length (str, max_len))
03221     _dbus_assert_not_reached ("setting len to max len should have worked");
03222 
03223   if (_dbus_string_set_length (str, max_len + 1))
03224     _dbus_assert_not_reached ("setting len to one more than max len should not have worked");
03225 
03226   if (!_dbus_string_set_length (str, 0))
03227     _dbus_assert_not_reached ("setting len to zero should have worked");
03228 }
03229 
03230 static void
03231 test_base64_roundtrip (const unsigned char *data,
03232                        int                  len)
03233 {
03234   DBusString orig;
03235   DBusString encoded;
03236   DBusString decoded;
03237 
03238   if (len < 0)
03239     len = strlen (data);
03240   
03241   if (!_dbus_string_init (&orig))
03242     _dbus_assert_not_reached ("could not init string");
03243 
03244   if (!_dbus_string_init (&encoded))
03245     _dbus_assert_not_reached ("could not init string");
03246   
03247   if (!_dbus_string_init (&decoded))
03248     _dbus_assert_not_reached ("could not init string");
03249 
03250   if (!_dbus_string_append_len (&orig, data, len))
03251     _dbus_assert_not_reached ("couldn't append orig data");
03252 
03253   if (!_dbus_string_base64_encode (&orig, 0, &encoded, 0))
03254     _dbus_assert_not_reached ("could not encode");
03255 
03256   if (!_dbus_string_base64_decode (&encoded, 0, &decoded, 0))
03257     _dbus_assert_not_reached ("could not decode");
03258 
03259   if (!_dbus_string_equal (&orig, &decoded))
03260     {
03261       const char *s;
03262       
03263       printf ("Original string %d bytes encoded %d bytes decoded %d bytes\n",
03264               _dbus_string_get_length (&orig),
03265               _dbus_string_get_length (&encoded),
03266               _dbus_string_get_length (&decoded));
03267       printf ("Original: %s\n", data);
03268       s = _dbus_string_get_const_data (&decoded);
03269       printf ("Decoded: %s\n", s);
03270       _dbus_assert_not_reached ("original string not the same as string decoded from base64");
03271     }
03272   
03273   _dbus_string_free (&orig);
03274   _dbus_string_free (&encoded);
03275   _dbus_string_free (&decoded);  
03276 }
03277 
03278 static void
03279 test_hex_roundtrip (const unsigned char *data,
03280                     int                  len)
03281 {
03282   DBusString orig;
03283   DBusString encoded;
03284   DBusString decoded;
03285 
03286   if (len < 0)
03287     len = strlen (data);
03288   
03289   if (!_dbus_string_init (&orig))
03290     _dbus_assert_not_reached ("could not init string");
03291 
03292   if (!_dbus_string_init (&encoded))
03293     _dbus_assert_not_reached ("could not init string");
03294   
03295   if (!_dbus_string_init (&decoded))
03296     _dbus_assert_not_reached ("could not init string");
03297 
03298   if (!_dbus_string_append_len (&orig, data, len))
03299     _dbus_assert_not_reached ("couldn't append orig data");
03300 
03301   if (!_dbus_string_hex_encode (&orig, 0, &encoded, 0))
03302     _dbus_assert_not_reached ("could not encode");
03303 
03304   if (!_dbus_string_hex_decode (&encoded, 0, &decoded, 0))
03305     _dbus_assert_not_reached ("could not decode");
03306     
03307   if (!_dbus_string_equal (&orig, &decoded))
03308     {
03309       const char *s;
03310       
03311       printf ("Original string %d bytes encoded %d bytes decoded %d bytes\n",
03312               _dbus_string_get_length (&orig),
03313               _dbus_string_get_length (&encoded),
03314               _dbus_string_get_length (&decoded));
03315       printf ("Original: %s\n", data);
03316       s = _dbus_string_get_const_data (&decoded);
03317       printf ("Decoded: %s\n", s);
03318       _dbus_assert_not_reached ("original string not the same as string decoded from base64");
03319     }
03320   
03321   _dbus_string_free (&orig);
03322   _dbus_string_free (&encoded);
03323   _dbus_string_free (&decoded);  
03324 }
03325 
03326 typedef void (* TestRoundtripFunc) (const unsigned char *data,
03327                                     int                  len);
03328 static void
03329 test_roundtrips (TestRoundtripFunc func)
03330 {
03331   (* func) ("Hello this is a string\n", -1);
03332   (* func) ("Hello this is a string\n1", -1);
03333   (* func) ("Hello this is a string\n12", -1);
03334   (* func) ("Hello this is a string\n123", -1);
03335   (* func) ("Hello this is a string\n1234", -1);
03336   (* func) ("Hello this is a string\n12345", -1);
03337   (* func) ("", 0);
03338   (* func) ("1", 1);
03339   (* func) ("12", 2);
03340   (* func) ("123", 3);
03341   (* func) ("1234", 4);
03342   (* func) ("12345", 5);
03343   (* func) ("", 1);
03344   (* func) ("1", 2);
03345   (* func) ("12", 3);
03346   (* func) ("123", 4);
03347   (* func) ("1234", 5);
03348   (* func) ("12345", 6);
03349   {
03350     unsigned char buf[512];
03351     int i;
03352     
03353     i = 0;
03354     while (i < _DBUS_N_ELEMENTS (buf))
03355       {
03356         buf[i] = i;
03357         ++i;
03358       }
03359     i = 0;
03360     while (i < _DBUS_N_ELEMENTS (buf))
03361       {
03362         (* func) (buf, i);
03363         ++i;
03364       }
03365   }
03366 }
03367 
03368 
03379 dbus_bool_t
03380 _dbus_string_test (void)
03381 {
03382   DBusString str;
03383   DBusString other;
03384   int i, end;
03385   long v;
03386   double d;
03387   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 };
03388   char *s;
03389   dbus_unichar_t ch;
03390   const char *valid_paths[] = {
03391     "/",
03392     "/foo/bar",
03393     "/foo",
03394     "/foo/bar/baz"
03395   };
03396   const char *invalid_paths[] = {
03397     "bar",
03398     "bar/baz",
03399     "/foo/bar/",
03400     "/foo/"
03401     "foo/",
03402     "boo//blah",
03403     "//",
03404     "
03405     "foo
03406     "Hello World",
03407     "",
03408     "   ",
03409     "foo bar"
03410   };
03411 
03412   const char *valid_interfaces[] = {
03413     "org.freedesktop.Foo",
03414     "Bar.Baz",
03415     "Blah.Blah.Blah.Blah.Blah",
03416     "a.b",
03417     "a.b.c.d.e.f.g",
03418     "a0.b1.c2.d3.e4.f5.g6",
03419     "abc123.foo27"
03420   };
03421   const char *invalid_interfaces[] = {
03422     ".",
03423     "",
03424     "..",
03425     ".Foo.Bar",
03426     "..Foo.Bar",
03427     "Foo.Bar.",
03428     "Foo.Bar..",
03429     "Foo",
03430     "9foo.bar.baz",
03431     "foo.bar..baz",
03432     "foo.bar...baz",
03433     "foo.bar.b..blah",
03434     ":",
03435     ":0-1",
03436     "10",
03437     ":11.34324",
03438     "0.0.0",
03439     "0..0",
03440     "foo.Bar.%",
03441     "foo.Bar!!",
03442     "!Foo.bar.bz",
03443     "foo.$.blah",
03444     "",
03445     "   ",
03446     "foo bar"
03447   };
03448 
03449   const char *valid_base_services[] = {
03450     ":0",
03451     ":a",
03452     ":",
03453     ":.a",
03454     ":.1",
03455     ":0.1",
03456     ":000.2222",
03457     ":.blah",
03458     ":abce.freedesktop.blah"
03459   };
03460   const char *invalid_base_services[] = {
03461     ":-",
03462     ":!",
03463     ":0-10",
03464     ":blah.",
03465     ":blah.",
03466     ":blah..org",
03467     ":blah.org..",
03468     ":..blah.org",
03469     "",
03470     "   ",
03471     "foo bar"
03472   };
03473 
03474   const char *valid_members[] = {
03475     "Hello",
03476     "Bar",
03477     "foobar",
03478     "_foobar",
03479     "foo89"
03480   };
03481 
03482   const char *invalid_members[] = {
03483     "9Hello",
03484     "10",
03485     "1",
03486     "foo-bar",
03487     "blah.org",
03488     ".blah",
03489     "blah.",
03490     "Hello.",
03491     "!foo",
03492     "",
03493     "   ",
03494     "foo bar"
03495   };
03496   
03497   i = 0;
03498   while (i < _DBUS_N_ELEMENTS (lens))
03499     {
03500       if (!_dbus_string_init (&str))
03501         _dbus_assert_not_reached ("failed to init string");
03502 
03503       set_max_length (&str, lens[i]);
03504       
03505       test_max_len (&str, lens[i]);
03506       _dbus_string_free (&str);
03507 
03508       ++i;
03509     }
03510 
03511   /* Test shortening and setting length */
03512   i = 0;
03513   while (i < _DBUS_N_ELEMENTS (lens))
03514     {
03515       int j;
03516       
03517       if (!_dbus_string_init (&str))
03518         _dbus_assert_not_reached ("failed to init string");
03519 
03520       set_max_length (&str, lens[i]);
03521       
03522       if (!_dbus_string_set_length (&str, lens[i]))
03523         _dbus_assert_not_reached ("failed to set string length");
03524 
03525       j = lens[i];
03526       while (j > 0)
03527         {
03528           _dbus_assert (_dbus_string_get_length (&str) == j);
03529           if (j > 0)
03530             {
03531               _dbus_string_shorten (&str, 1);
03532               _dbus_assert (_dbus_string_get_length (&str) == (j - 1));
03533             }
03534           --j;
03535         }
03536       
03537       _dbus_string_free (&str);
03538 
03539       ++i;
03540     }
03541 
03542   /* Test appending data */
03543   if (!_dbus_string_init (&str))
03544     _dbus_assert_not_reached ("failed to init string");
03545 
03546   i = 0;
03547   while (i < 10)
03548     {
03549       if (!_dbus_string_append (&str, "a"))
03550         _dbus_assert_not_reached ("failed to append string to string\n");
03551 
03552       _dbus_assert (_dbus_string_get_length (&str) == i * 2 + 1);
03553 
03554       if (!_dbus_string_append_byte (&str, 'b'))
03555         _dbus_assert_not_reached ("failed to append byte to string\n");
03556 
03557       _dbus_assert (_dbus_string_get_length (&str) == i * 2 + 2);
03558                     
03559       ++i;
03560     }
03561 
03562   _dbus_string_free (&str);
03563 
03564   /* Check steal_data */
03565   
03566   if (!_dbus_string_init (&str))
03567     _dbus_assert_not_reached ("failed to init string");
03568 
03569   if (!_dbus_string_append (&str, "Hello World"))
03570     _dbus_assert_not_reached ("could not append to string");
03571 
03572   i = _dbus_string_get_length (&str);
03573   
03574   if (!_dbus_string_steal_data (&str, &s))
03575     _dbus_assert_not_reached ("failed to steal data");
03576 
03577   _dbus_assert (_dbus_string_get_length (&str) == 0);
03578   _dbus_assert (((int)strlen (s)) == i);
03579 
03580   dbus_free (s);
03581 
03582   /* Check move */
03583   
03584   if (!_dbus_string_append (&str, "Hello World"))
03585     _dbus_assert_not_reached ("could not append to string");
03586 
03587   i = _dbus_string_get_length (&str);
03588 
03589   if (!_dbus_string_init (&other))
03590     _dbus_assert_not_reached ("could not init string");
03591   
03592   if (!_dbus_string_move (&str, 0, &other, 0))
03593     _dbus_assert_not_reached ("could not move");
03594 
03595   _dbus_assert (_dbus_string_get_length (&str) == 0);
03596   _dbus_assert (_dbus_string_get_length (&other) == i);
03597 
03598   if (!_dbus_string_append (&str, "Hello World"))
03599     _dbus_assert_not_reached ("could not append to string");
03600   
03601   if (!_dbus_string_move (&str, 0, &other, _dbus_string_get_length (&other)))
03602     _dbus_assert_not_reached ("could not move");
03603 
03604   _dbus_assert (_dbus_string_get_length (&str) == 0);
03605   _dbus_assert (_dbus_string_get_length (&other) == i * 2);
03606 
03607     if (!_dbus_string_append (&str, "Hello World"))
03608     _dbus_assert_not_reached ("could not append to string");
03609   
03610   if (!_dbus_string_move (&str, 0, &other, _dbus_string_get_length (&other) / 2))
03611     _dbus_assert_not_reached ("could not move");
03612 
03613   _dbus_assert (_dbus_string_get_length (&str) == 0);
03614   _dbus_assert (_dbus_string_get_length (&other) == i * 3);
03615   
03616   _dbus_string_free (&other);
03617 
03618   /* Check copy */
03619   
03620   if (!_dbus_string_append (&str, "Hello World"))
03621     _dbus_assert_not_reached ("could not append to string");
03622 
03623   i = _dbus_string_get_length (&str);
03624   
03625   if (!_dbus_string_init (&other))
03626     _dbus_assert_not_reached ("could not init string");
03627   
03628   if (!_dbus_string_copy (&str, 0, &other, 0))
03629     _dbus_assert_not_reached ("could not copy");
03630 
03631   _dbus_assert (_dbus_string_get_length (&str) == i);
03632   _dbus_assert (_dbus_string_get_length (&other) == i);
03633 
03634   if (!_dbus_string_copy (&str, 0, &other, _dbus_string_get_length (&other)))
03635     _dbus_assert_not_reached ("could not copy");
03636 
03637   _dbus_assert (_dbus_string_get_length (&str) == i);
03638   _dbus_assert (_dbus_string_get_length (&other) == i * 2);
03639   _dbus_assert (_dbus_string_equal_c_str (&other,
03640                                           "Hello WorldHello World"));
03641 
03642   if (!_dbus_string_copy (&str, 0, &other, _dbus_string_get_length (&other) / 2))
03643     _dbus_assert_not_reached ("could not copy");
03644 
03645   _dbus_assert (_dbus_string_get_length (&str) == i);
03646   _dbus_assert (_dbus_string_get_length (&other) == i * 3);
03647   _dbus_assert (_dbus_string_equal_c_str (&other,
03648                                           "Hello WorldHello WorldHello World"));
03649   
03650   _dbus_string_free (&str);
03651   _dbus_string_free (&other);
03652 
03653   /* Check replace */
03654 
03655   if (!_dbus_string_init (&str))
03656     _dbus_assert_not_reached ("failed to init string");
03657   
03658   if (!_dbus_string_append (&str, "Hello World"))
03659     _dbus_assert_not_reached ("could not append to string");
03660 
03661   i = _dbus_string_get_length (&str);
03662   
03663   if (!_dbus_string_init (&other))
03664     _dbus_assert_not_reached ("could not init string");
03665   
03666   if (!_dbus_string_replace_len (&str, 0, _dbus_string_get_length (&str),
03667                                  &other, 0, _dbus_string_get_length (&other)))
03668     _dbus_assert_not_reached ("could not replace");
03669 
03670   _dbus_assert (_dbus_string_get_length (&str) == i);
03671   _dbus_assert (_dbus_string_get_length (&other) == i);
03672   _dbus_assert (_dbus_string_equal_c_str (&other, "Hello World"));
03673   
03674   if (!_dbus_string_replace_len (&str, 0, _dbus_string_get_length (&str),
03675                                  &other, 5, 1))
03676     _dbus_assert_not_reached ("could not replace center space");
03677 
03678   _dbus_assert (_dbus_string_get_length (&str) == i);
03679   _dbus_assert (_dbus_string_get_length (&other) == i * 2 - 1);
03680   _dbus_assert (_dbus_string_equal_c_str (&other,
03681                                           "HelloHello WorldWorld"));
03682 
03683   
03684   if (!_dbus_string_replace_len (&str, 1, 1,
03685                                  &other,
03686                                  _dbus_string_get_length (&other) - 1,
03687                                  1))
03688     _dbus_assert_not_reached ("could not replace end character");
03689   
03690   _dbus_assert (_dbus_string_get_length (&str) == i);
03691   _dbus_assert (_dbus_string_get_length (&other) == i * 2 - 1);
03692   _dbus_assert (_dbus_string_equal_c_str (&other,
03693                                           "HelloHello WorldWorle"));
03694   
03695   _dbus_string_free (&str);
03696   _dbus_string_free (&other);
03697   
03698   /* Check append/get unichar */
03699   
03700   if (!_dbus_string_init (&str))
03701     _dbus_assert_not_reached ("failed to init string");
03702 
03703   ch = 0;
03704   if (!_dbus_string_append_unichar (&str, 0xfffc))
03705     _dbus_assert_not_reached ("failed to append unichar");
03706 
03707   _dbus_string_get_unichar (&str, 0, &ch, &i);
03708 
03709   _dbus_assert (ch == 0xfffc);
03710   _dbus_assert (i == _dbus_string_get_length (&str));
03711 
03712   _dbus_string_free (&str);
03713 
03714   /* Check insert/set/get byte */
03715   
03716   if (!_dbus_string_init (&str))
03717     _dbus_assert_not_reached ("failed to init string");
03718 
03719   if (!_dbus_string_append (&str, "Hello"))
03720     _dbus_assert_not_reached ("failed to append Hello");
03721 
03722   _dbus_assert (_dbus_string_get_byte (&str, 0) == 'H');
03723   _dbus_assert (_dbus_string_get_byte (&str, 1) == 'e');
03724   _dbus_assert (_dbus_string_get_byte (&str, 2) == 'l');
03725   _dbus_assert (_dbus_string_get_byte (&str, 3) == 'l');
03726   _dbus_assert (_dbus_string_get_byte (&str, 4) == 'o');
03727 
03728   _dbus_string_set_byte (&str, 1, 'q');
03729   _dbus_assert (_dbus_string_get_byte (&str, 1) == 'q');
03730 
03731   if (!_dbus_string_insert_bytes (&str, 0, 1, 255))
03732     _dbus_assert_not_reached ("can't insert byte");
03733 
03734   if (!_dbus_string_insert_bytes (&str, 2, 4, 'Z'))
03735     _dbus_assert_not_reached ("can't insert byte");
03736 
03737   if (!_dbus_string_insert_bytes (&str, _dbus_string_get_length (&str), 1, 'W'))
03738     _dbus_assert_not_reached ("can't insert byte");
03739   
03740   _dbus_assert (_dbus_string_get_byte (&str, 0) == 255);
03741   _dbus_assert (_dbus_string_get_byte (&str, 1) == 'H');
03742   _dbus_assert (_dbus_string_get_byte (&str, 2) == 'Z');
03743   _dbus_assert (_dbus_string_get_byte (&str, 3) == 'Z');
03744   _dbus_assert (_dbus_string_get_byte (&str, 4) == 'Z');
03745   _dbus_assert (_dbus_string_get_byte (&str, 5) == 'Z');
03746   _dbus_assert (_dbus_string_get_byte (&str, 6) == 'q');
03747   _dbus_assert (_dbus_string_get_byte (&str, 7) == 'l');
03748   _dbus_assert (_dbus_string_get_byte (&str, 8) == 'l');
03749   _dbus_assert (_dbus_string_get_byte (&str, 9) == 'o');
03750   _dbus_assert (_dbus_string_get_byte (&str, 10) == 'W');
03751 
03752   _dbus_string_free (&str);
03753   
03754   /* Check append/parse int/double */
03755   
03756   if (!_dbus_string_init (&str))
03757     _dbus_assert_not_reached ("failed to init string");
03758 
03759   if (!_dbus_string_append_int (&str, 27))
03760     _dbus_assert_not_reached ("failed to append int");
03761 
03762   i = _dbus_string_get_length (&str);
03763 
03764   if (!_dbus_string_parse_int (&str, 0, &v, &end))
03765     _dbus_assert_not_reached ("failed to parse int");
03766 
03767   _dbus_assert (v == 27);
03768   _dbus_assert (end == i);
03769 
03770   _dbus_string_free (&str);
03771   
03772   if (!_dbus_string_init (&str))
03773     _dbus_assert_not_reached ("failed to init string");
03774   
03775   if (!_dbus_string_append_double (&str, 50.3))
03776     _dbus_assert_not_reached ("failed to append float");
03777 
03778   i = _dbus_string_get_length (&str);
03779 
03780   if (!_dbus_string_parse_double (&str, 0, &d, &end))
03781     _dbus_assert_not_reached ("failed to parse float");
03782 
03783   _dbus_assert (d > (50.3 - 1e-6) && d < (50.3 + 1e-6));
03784   _dbus_assert (end == i);
03785 
03786   _dbus_string_free (&str);
03787 
03788   /* Test find */
03789   if (!_dbus_string_init (&str))
03790     _dbus_assert_not_reached ("failed to init string");
03791 
03792   if (!_dbus_string_append (&str, "Hello"))
03793     _dbus_assert_not_reached ("couldn't append to string");
03794   
03795   if (!_dbus_string_find (&str, 0, "He", &i))
03796     _dbus_assert_not_reached ("didn't find 'He'");
03797   _dbus_assert (i == 0);
03798 
03799   if (!_dbus_string_find (&str, 0, "Hello", &i))
03800     _dbus_assert_not_reached ("didn't find 'Hello'");
03801   _dbus_assert (i == 0);
03802   
03803   if (!_dbus_string_find (&str, 0, "ello", &i))
03804     _dbus_assert_not_reached ("didn't find 'ello'");
03805   _dbus_assert (i == 1);
03806 
03807   if (!_dbus_string_find (&str, 0, "lo", &i))
03808     _dbus_assert_not_reached ("didn't find 'lo'");
03809   _dbus_assert (i == 3);
03810 
03811   if (!_dbus_string_find (&str, 2, "lo", &i))
03812     _dbus_assert_not_reached ("didn't find 'lo'");
03813   _dbus_assert (i == 3);
03814 
03815   if (_dbus_string_find (&str, 4, "lo", &i))
03816     _dbus_assert_not_reached ("did find 'lo'");
03817   
03818   if (!_dbus_string_find (&str, 0, "l", &i))
03819     _dbus_assert_not_reached ("didn't find 'l'");
03820   _dbus_assert (i == 2);
03821 
03822   if (!_dbus_string_find (&str, 0, "H", &i))
03823     _dbus_assert_not_reached ("didn't find 'H'");
03824   _dbus_assert (i == 0);
03825 
03826   if (!_dbus_string_find (&str, 0, "", &i))
03827     _dbus_assert_not_reached ("didn't find ''");
03828   _dbus_assert (i == 0);
03829   
03830   if (_dbus_string_find (&str, 0, "Hello!", NULL))
03831     _dbus_assert_not_reached ("Did find 'Hello!'");
03832 
03833   if (_dbus_string_find (&str, 0, "Oh, Hello", NULL))
03834     _dbus_assert_not_reached ("Did find 'Oh, Hello'");
03835   
03836   if (_dbus_string_find (&str, 0, "ill", NULL))
03837     _dbus_assert_not_reached ("Did find 'ill'");
03838 
03839   if (_dbus_string_find (&str, 0, "q", NULL))
03840     _dbus_assert_not_reached ("Did find 'q'");
03841 
03842   if (!_dbus_string_find_to (&str, 0, 2, "He", NULL))
03843     _dbus_assert_not_reached ("Didn't find 'He'");
03844 
03845   if (_dbus_string_find_to (&str, 0, 2, "Hello", NULL))
03846     _dbus_assert_not_reached ("Did find 'Hello'");
03847 
03848   if (!_dbus_string_find_byte_backward (&str, _dbus_string_get_length (&str), 'H', &i))
03849     _dbus_assert_not_reached ("Did not find 'H'");
03850   _dbus_assert (i == 0);
03851 
03852   if (!_dbus_string_find_byte_backward (&str, _dbus_string_get_length (&str), 'o', &i))
03853     _dbus_assert_not_reached ("Did not find 'o'");
03854   _dbus_assert (i == _dbus_string_get_length (&str) - 1);
03855 
03856   if (_dbus_string_find_byte_backward (&str, _dbus_string_get_length (&str) - 1, 'o', &i))
03857     _dbus_assert_not_reached ("Did find 'o'");
03858   _dbus_assert (i == -1);
03859 
03860   if (_dbus_string_find_byte_backward (&str, 1, 'e', &i))
03861     _dbus_assert_not_reached ("Did find 'e'");
03862   _dbus_assert (i == -1);
03863 
03864   if (!_dbus_string_find_byte_backward (&str, 2, 'e', &i))
03865     _dbus_assert_not_reached ("Didn't find 'e'");
03866   _dbus_assert (i == 1);
03867   
03868   _dbus_string_free (&str);
03869 
03870   /* Base 64 and Hex encoding */
03871   test_roundtrips (test_base64_roundtrip);
03872   test_roundtrips (test_hex_roundtrip);
03873 
03874   /* Path validation */
03875   i = 0;
03876   while (i < (int) _DBUS_N_ELEMENTS (valid_paths))
03877     {
03878       _dbus_string_init_const (&str, valid_paths[i]);
03879 
03880       if (!_dbus_string_validate_path (&str, 0,
03881                                        _dbus_string_get_length (&str)))
03882         {
03883           _dbus_warn ("Path \"%s\" should have been valid\n", valid_paths[i]);
03884           _dbus_assert_not_reached ("invalid path");
03885         }
03886       
03887       ++i;
03888     }
03889 
03890   i = 0;
03891   while (i < (int) _DBUS_N_ELEMENTS (invalid_paths))
03892     {
03893       _dbus_string_init_const (&str, invalid_paths[i]);
03894       
03895       if (_dbus_string_validate_path (&str, 0,
03896                                       _dbus_string_get_length (&str)))
03897         {
03898           _dbus_warn ("Path \"%s\" should have been invalid\n", invalid_paths[i]);
03899           _dbus_assert_not_reached ("valid path");
03900         }
03901       
03902       ++i;
03903     }
03904 
03905   /* Interface validation */
03906   i = 0;
03907   while (i < (int) _DBUS_N_ELEMENTS (valid_interfaces))
03908     {
03909       _dbus_string_init_const (&str, valid_interfaces[i]);
03910 
03911       if (!_dbus_string_validate_interface (&str, 0,
03912                                             _dbus_string_get_length (&str)))
03913         {
03914           _dbus_warn ("Interface \"%s\" should have been valid\n", valid_interfaces[i]);
03915           _dbus_assert_not_reached ("invalid interface");
03916         }
03917       
03918       ++i;
03919     }
03920 
03921   i = 0;
03922   while (i < (int) _DBUS_N_ELEMENTS (invalid_interfaces))
03923     {
03924       _dbus_string_init_const (&str, invalid_interfaces[i]);
03925       
03926       if (_dbus_string_validate_interface (&str, 0,
03927                                            _dbus_string_get_length (&str)))
03928         {
03929           _dbus_warn ("Interface \"%s\" should have been invalid\n", invalid_interfaces[i]);
03930           _dbus_assert_not_reached ("valid interface");
03931         }
03932       
03933       ++i;
03934     }
03935 
03936   /* Service validation (check that valid interfaces are valid services,
03937    * and invalid interfaces are invalid services except if they start with ':')
03938    */
03939   i = 0;
03940   while (i < (int) _DBUS_N_ELEMENTS (valid_interfaces))
03941     {
03942       _dbus_string_init_const (&str, valid_interfaces[i]);
03943 
03944       if (!_dbus_string_validate_service (&str, 0,
03945                                           _dbus_string_get_length (&str)))
03946         {
03947           _dbus_warn ("Service \"%s\" should have been valid\n", valid_interfaces[i]);
03948           _dbus_assert_not_reached ("invalid service");
03949         }
03950       
03951       ++i;
03952     }
03953 
03954   i = 0;
03955   while (i < (int) _DBUS_N_ELEMENTS (invalid_interfaces))
03956     {
03957       if (invalid_interfaces[i][0] != ':')
03958         {
03959           _dbus_string_init_const (&str, invalid_interfaces[i]);
03960           
03961           if (_dbus_string_validate_service (&str, 0,
03962                                              _dbus_string_get_length (&str)))
03963             {
03964               _dbus_warn ("Service \"%s\" should have been invalid\n", invalid_interfaces[i]);
03965               _dbus_assert_not_reached ("valid service");
03966             }
03967         }
03968       
03969       ++i;
03970     }
03971 
03972   /* Base service validation */
03973   i = 0;
03974   while (i < (int) _DBUS_N_ELEMENTS (valid_base_services))
03975     {
03976       _dbus_string_init_const (&str, valid_base_services[i]);
03977 
03978       if (!_dbus_string_validate_service (&str, 0,
03979                                           _dbus_string_get_length (&str)))
03980         {
03981           _dbus_warn ("Service \"%s\" should have been valid\n", valid_base_services[i]);
03982           _dbus_assert_not_reached ("invalid base service");
03983         }
03984       
03985       ++i;
03986     }
03987 
03988   i = 0;
03989   while (i < (int) _DBUS_N_ELEMENTS (invalid_base_services))
03990     {
03991       _dbus_string_init_const (&str, invalid_base_services[i]);
03992       
03993       if (_dbus_string_validate_service (&str, 0,
03994                                          _dbus_string_get_length (&str)))
03995         {
03996           _dbus_warn ("Service \"%s\" should have been invalid\n", invalid_base_services[i]);
03997           _dbus_assert_not_reached ("valid base service");
03998         }
03999       
04000       ++i;
04001     }
04002 
04003 
04004   /* Error name validation (currently identical to interfaces)
04005    */
04006   i = 0;
04007   while (i < (int) _DBUS_N_ELEMENTS (valid_interfaces))
04008     {
04009       _dbus_string_init_const (&str, valid_interfaces[i]);
04010 
04011       if (!_dbus_string_validate_error_name (&str, 0,
04012                                              _dbus_string_get_length (&str)))
04013         {
04014           _dbus_warn ("Error name \"%s\" should have been valid\n", valid_interfaces[i]);
04015           _dbus_assert_not_reached ("invalid error name");
04016         }
04017       
04018       ++i;
04019     }
04020 
04021   i = 0;
04022   while (i < (int) _DBUS_N_ELEMENTS (invalid_interfaces))
04023     {
04024       if (invalid_interfaces[i][0] != ':')
04025         {
04026           _dbus_string_init_const (&str, invalid_interfaces[i]);
04027           
04028           if (_dbus_string_validate_error_name (&str, 0,
04029                                                 _dbus_string_get_length (&str)))
04030             {
04031               _dbus_warn ("Error name \"%s\" should have been invalid\n", invalid_interfaces[i]);
04032               _dbus_assert_not_reached ("valid error name");
04033             }
04034         }
04035       
04036       ++i;
04037     }
04038   
04039   /* Member validation */
04040   i = 0;
04041   while (i < (int) _DBUS_N_ELEMENTS (valid_members))
04042     {
04043       _dbus_string_init_const (&str, valid_members[i]);
04044 
04045       if (!_dbus_string_validate_member (&str, 0,
04046                                          _dbus_string_get_length (&str)))
04047         {
04048           _dbus_warn ("Member \"%s\" should have been valid\n", valid_members[i]);
04049           _dbus_assert_not_reached ("invalid member");
04050         }
04051       
04052       ++i;
04053     }
04054 
04055   i = 0;
04056   while (i < (int) _DBUS_N_ELEMENTS (invalid_members))
04057     {
04058       _dbus_string_init_const (&str, invalid_members[i]);
04059       
04060       if (_dbus_string_validate_member (&str, 0,
04061                                         _dbus_string_get_length (&str)))
04062         {
04063           _dbus_warn ("Member \"%s\" should have been invalid\n", invalid_members[i]);
04064           _dbus_assert_not_reached ("valid member");
04065         }
04066       
04067       ++i;
04068     }
04069 
04070   /* Validate claimed length longer than real length */
04071   _dbus_string_init_const (&str, "abc.efg");
04072   if (_dbus_string_validate_service (&str, 0, 8))
04073     _dbus_assert_not_reached ("validated too-long string");
04074   if (_dbus_string_validate_interface (&str, 0, 8))
04075     _dbus_assert_not_reached ("validated too-long string");
04076   if (_dbus_string_validate_error_name (&str, 0, 8))
04077     _dbus_assert_not_reached ("validated too-long string");
04078 
04079   _dbus_string_init_const (&str, "abc");
04080   if (_dbus_string_validate_member (&str, 0, 4))
04081     _dbus_assert_not_reached ("validated too-long string");
04082 
04083   /* Validate string exceeding max name length */
04084   if (!_dbus_string_init (&str))
04085     _dbus_assert_not_reached ("no memory");
04086 
04087   while (_dbus_string_get_length (&str) <= DBUS_MAXIMUM_NAME_LENGTH)
04088     if (!_dbus_string_append (&str, "abc.def"))
04089       _dbus_assert_not_reached ("no memory");
04090 
04091   if (_dbus_string_validate_service (&str, 0, _dbus_string_get_length (&str)))
04092     _dbus_assert_not_reached ("validated overmax string");
04093   if (_dbus_string_validate_interface (&str, 0, _dbus_string_get_length (&str)))
04094     _dbus_assert_not_reached ("validated overmax string");
04095   if (_dbus_string_validate_error_name (&str, 0, _dbus_string_get_length (&str)))
04096     _dbus_assert_not_reached ("validated overmax string");
04097 
04098   /* overlong member */
04099   _dbus_string_set_length (&str, 0);
04100   while (_dbus_string_get_length (&str) <= DBUS_MAXIMUM_NAME_LENGTH)
04101     if (!_dbus_string_append (&str, "abc"))
04102       _dbus_assert_not_reached ("no memory");  
04103 
04104   if (_dbus_string_validate_member (&str, 0, _dbus_string_get_length (&str)))
04105     _dbus_assert_not_reached ("validated overmax string");
04106 
04107   /* overlong base service */
04108   _dbus_string_set_length (&str, 0);
04109   _dbus_string_append (&str, ":");
04110   while (_dbus_string_get_length (&str) <= DBUS_MAXIMUM_NAME_LENGTH)
04111     if (!_dbus_string_append (&str, "abc"))
04112       _dbus_assert_not_reached ("no memory");  
04113 
04114   if (_dbus_string_validate_service (&str, 0, _dbus_string_get_length (&str)))
04115     _dbus_assert_not_reached ("validated overmax string");
04116   
04117   _dbus_string_free (&str);
04118   
04119   return TRUE;
04120 }
04121 
04122 #endif /* DBUS_BUILD_TESTS */

Generated on Sun Mar 21 03:52:06 2004 for D-BUS by doxygen 1.3.6-20040222