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

Generated on Tue Feb 10 18:14:08 2004 for D-BUS by doxygen 1.3.5