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

dbus-string.c

00001 /* -*- mode: C; c-file-style: "gnu" -*- */
00002 /* dbus-string.c String utility class (internal to D-BUS implementation)
00003  * 
00004  * Copyright (C) 2002, 2003 Red Hat, Inc.
00005  *
00006  * Licensed under the Academic Free License version 2.1
00007  * 
00008  * This program is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * This program is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  * 
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program; if not, write to the Free Software
00020  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021  *
00022  */
00023 
00024 #include "dbus-internals.h"
00025 #include "dbus-string.h"
00026 /* we allow a system header here, for speed/convenience */
00027 #include <string.h>
00028 /* for vsnprintf */
00029 #include <stdio.h>
00030 #include "dbus-marshal.h"
00031 #define DBUS_CAN_USE_DBUS_STRING_PRIVATE 1
00032 #include "dbus-string-private.h"
00033 #include "dbus-protocol.h"
00034 /* for DBUS_VA_COPY */
00035 #include "dbus-sysdeps.h"
00036 
00079 #define ALLOCATION_PADDING 8
00080 
00085 #define MAX_MAX_LENGTH (_DBUS_INT_MAX - ALLOCATION_PADDING)
00086 
00092 #define DBUS_GENERIC_STRING_PREAMBLE(real) _dbus_assert ((real) != NULL); _dbus_assert (!(real)->invalid); _dbus_assert ((real)->len >= 0); _dbus_assert ((real)->allocated >= 0); _dbus_assert ((real)->max_length >= 0); _dbus_assert ((real)->len <= ((real)->allocated - ALLOCATION_PADDING)); _dbus_assert ((real)->len <= (real)->max_length)
00093 
00100 #define DBUS_STRING_PREAMBLE(str) DBusRealString *real = (DBusRealString*) str; \
00101   DBUS_GENERIC_STRING_PREAMBLE (real);                                          \
00102   _dbus_assert (!(real)->constant);                                             \
00103   _dbus_assert (!(real)->locked)
00104 
00112 #define DBUS_LOCKED_STRING_PREAMBLE(str) DBusRealString *real = (DBusRealString*) str; \
00113   DBUS_GENERIC_STRING_PREAMBLE (real);                                                 \
00114   _dbus_assert (!(real)->constant)
00115 
00121 #define DBUS_CONST_STRING_PREAMBLE(str) const DBusRealString *real = (DBusRealString*) str; \
00122   DBUS_GENERIC_STRING_PREAMBLE (real)
00123 
00131 static void
00132 fixup_alignment (DBusRealString *real)
00133 {
00134   char *aligned;
00135   char *real_block;
00136   unsigned int old_align_offset;
00137 
00138   /* we have to have extra space in real->allocated for the align offset and nul byte */
00139   _dbus_assert (real->len <= real->allocated - ALLOCATION_PADDING);
00140   
00141   old_align_offset = real->align_offset;
00142   real_block = real->str - old_align_offset;
00143   
00144   aligned = _DBUS_ALIGN_ADDRESS (real_block, 8);
00145 
00146   real->align_offset = aligned - real_block;
00147   real->str = aligned;
00148   
00149   if (old_align_offset != real->align_offset)
00150     {
00151       /* Here comes the suck */
00152       memmove (real_block + real->align_offset,
00153                real_block + old_align_offset,
00154                real->len + 1);
00155     }
00156 
00157   _dbus_assert (real->align_offset < 8);
00158   _dbus_assert (_DBUS_ALIGN_ADDRESS (real->str, 8) == real->str);
00159 }
00160 
00161 static void
00162 undo_alignment (DBusRealString *real)
00163 {
00164   if (real->align_offset != 0)
00165     {
00166       memmove (real->str - real->align_offset,
00167                real->str,
00168                real->len + 1);
00169 
00170       real->str = real->str - real->align_offset;
00171       real->align_offset = 0;
00172     }
00173 }
00174 
00184 dbus_bool_t
00185 _dbus_string_init_preallocated (DBusString *str,
00186                                 int         allocate_size)
00187 {
00188   DBusRealString *real;
00189   
00190   _dbus_assert (str != NULL);
00191 
00192   _dbus_assert (sizeof (DBusString) == sizeof (DBusRealString));
00193   
00194   real = (DBusRealString*) str;
00195 
00196   /* It's very important not to touch anything
00197    * other than real->str if we're going to fail,
00198    * since we also use this function to reset
00199    * an existing string, e.g. in _dbus_string_steal_data()
00200    */
00201   
00202   real->str = dbus_malloc (ALLOCATION_PADDING + allocate_size);
00203   if (real->str == NULL)
00204     return FALSE;  
00205   
00206   real->allocated = ALLOCATION_PADDING + allocate_size;
00207   real->len = 0;
00208   real->str[real->len] = '\0';
00209   
00210   real->max_length = MAX_MAX_LENGTH;
00211   real->constant = FALSE;
00212   real->locked = FALSE;
00213   real->invalid = FALSE;
00214   real->align_offset = 0;
00215   
00216   fixup_alignment (real);
00217   
00218   return TRUE;
00219 }
00220 
00228 dbus_bool_t
00229 _dbus_string_init (DBusString *str)
00230 {
00231   return _dbus_string_init_preallocated (str, 0);
00232 }
00233 
00234 /* The max length thing is sort of a historical artifact
00235  * from a feature that turned out to be dumb; perhaps
00236  * we should purge it entirely. The problem with
00237  * the feature is that it looks like memory allocation
00238  * failure, but is not a transient or resolvable failure.
00239  */
00240 static void
00241 set_max_length (DBusString *str,
00242                 int         max_length)
00243 {
00244   DBusRealString *real;
00245   
00246   real = (DBusRealString*) str;
00247 
00248   real->max_length = max_length;
00249 }
00250 
00260 void
00261 _dbus_string_init_const (DBusString *str,
00262                          const char *value)
00263 {
00264   _dbus_assert (value != NULL);
00265   
00266   _dbus_string_init_const_len (str, value,
00267                                strlen (value));
00268 }
00269 
00280 void
00281 _dbus_string_init_const_len (DBusString *str,
00282                              const char *value,
00283                              int         len)
00284 {
00285   DBusRealString *real;
00286   
00287   _dbus_assert (str != NULL);
00288   _dbus_assert (value != NULL);
00289   _dbus_assert (len <= MAX_MAX_LENGTH);
00290   _dbus_assert (len >= 0);
00291   
00292   real = (DBusRealString*) str;
00293   
00294   real->str = (char*) value;
00295   real->len = len;
00296   real->allocated = real->len + ALLOCATION_PADDING; /* a lie, just to avoid special-case assertions... */
00297   real->max_length = real->len + 1;
00298   real->constant = TRUE;
00299   real->invalid = FALSE;
00300 
00301   /* We don't require const strings to be 8-byte aligned as the
00302    * memory is coming from elsewhere.
00303    */
00304 }
00305 
00311 void
00312 _dbus_string_free (DBusString *str)
00313 {
00314   DBusRealString *real = (DBusRealString*) str;
00315   DBUS_GENERIC_STRING_PREAMBLE (real);
00316   
00317   if (real->constant)
00318     return;
00319   dbus_free (real->str - real->align_offset);
00320 
00321   real->invalid = TRUE;
00322 }
00323 
00324 #ifdef DBUS_BUILD_TESTS
00325 /* Not using this feature at the moment,
00326  * so marked DBUS_BUILD_TESTS-only
00327  */
00337 void
00338 _dbus_string_lock (DBusString *str)
00339 {  
00340   DBUS_LOCKED_STRING_PREAMBLE (str); /* can lock multiple times */
00341 
00342   real->locked = TRUE;
00343 
00344   /* Try to realloc to avoid excess memory usage, since
00345    * we know we won't change the string further
00346    */
00347 #define MAX_WASTE 48
00348   if (real->allocated - MAX_WASTE > real->len)
00349     {
00350       char *new_str;
00351       int new_allocated;
00352 
00353       new_allocated = real->len + ALLOCATION_PADDING;
00354 
00355       new_str = dbus_realloc (real->str - real->align_offset,
00356                               new_allocated);
00357       if (new_str != NULL)
00358         {
00359           real->str = new_str + real->align_offset;
00360           real->allocated = new_allocated;
00361           fixup_alignment (real);
00362         }
00363     }
00364 }
00365 #endif /* DBUS_BUILD_TESTS */
00366 
00367 static dbus_bool_t
00368 reallocate_for_length (DBusRealString *real,
00369                        int             new_length)
00370 {
00371   int new_allocated;
00372   char *new_str;
00373 
00374   /* at least double our old allocation to avoid O(n), avoiding
00375    * overflow
00376    */
00377   if (real->allocated > (MAX_MAX_LENGTH + ALLOCATION_PADDING) / 2)
00378     new_allocated = MAX_MAX_LENGTH + ALLOCATION_PADDING;
00379   else
00380     new_allocated = real->allocated * 2;
00381 
00382   /* if you change the code just above here, run the tests without
00383    * the following before you commit
00384    */
00385 #ifdef DBUS_BUILD_TESTS
00386   new_allocated = 0; /* ensure a realloc every time so that we go
00387                       * through all malloc failure codepaths
00388                       */
00389 #endif
00390       
00391   /* But be sure we always alloc at least space for the new length */
00392   new_allocated = MAX (new_allocated, new_length + ALLOCATION_PADDING);
00393 
00394   _dbus_assert (new_allocated >= real->allocated); /* code relies on this */
00395   new_str = dbus_realloc (real->str - real->align_offset, new_allocated);
00396   if (new_str == NULL)
00397     return FALSE;
00398 
00399   real->str = new_str + real->align_offset;
00400   real->allocated = new_allocated;
00401   fixup_alignment (real);
00402 
00403   return TRUE;
00404 }
00405 
00406 static dbus_bool_t
00407 set_length (DBusRealString *real,
00408             int             new_length)
00409 {
00410   /* Note, we are setting the length not including nul termination */
00411 
00412   /* exceeding max length is the same as failure to allocate memory */
00413   if (new_length > real->max_length)
00414     return FALSE;
00415   else if (new_length > (real->allocated - ALLOCATION_PADDING) &&
00416            !reallocate_for_length (real, new_length))
00417     return FALSE;
00418   else
00419     {
00420       real->len = new_length;
00421       real->str[real->len] = '\0';
00422       return TRUE;
00423     }
00424 }
00425 
00426 static dbus_bool_t
00427 open_gap (int             len,
00428           DBusRealString *dest,
00429           int             insert_at)
00430 {
00431   if (len == 0)
00432     return TRUE;
00433 
00434   if (len > dest->max_length - dest->len)
00435     return FALSE; /* detected overflow of dest->len + len below */
00436   
00437   if (!set_length (dest, dest->len + len))
00438     return FALSE;
00439 
00440   memmove (dest->str + insert_at + len, 
00441            dest->str + insert_at,
00442            dest->len - len - insert_at);
00443 
00444   return TRUE;
00445 }
00446 
00458 char*
00459 _dbus_string_get_data (DBusString *str)
00460 {
00461   DBUS_STRING_PREAMBLE (str);
00462   
00463   return real->str;
00464 }
00465 
00472 const char*
00473 _dbus_string_get_const_data (const DBusString  *str)
00474 {
00475   DBUS_CONST_STRING_PREAMBLE (str);
00476   
00477   return real->str;
00478 }
00479 
00493 char*
00494 _dbus_string_get_data_len (DBusString *str,
00495                            int         start,
00496                            int         len)
00497 {
00498   DBUS_STRING_PREAMBLE (str);
00499   _dbus_assert (start >= 0);
00500   _dbus_assert (len >= 0);
00501   _dbus_assert (start <= real->len);
00502   _dbus_assert (len <= real->len - start);
00503   
00504   return real->str + start;
00505 }
00506 
00515 const char*
00516 _dbus_string_get_const_data_len (const DBusString  *str,
00517                                  int                start,
00518                                  int                len)
00519 {
00520   DBUS_CONST_STRING_PREAMBLE (str);
00521   _dbus_assert (start >= 0);
00522   _dbus_assert (len >= 0);
00523   _dbus_assert (start <= real->len);
00524   _dbus_assert (len <= real->len - start);
00525   
00526   return real->str + start;
00527 }
00528 
00536 void
00537 _dbus_string_set_byte (DBusString    *str,
00538                        int            i,
00539                        unsigned char  byte)
00540 {
00541   DBUS_STRING_PREAMBLE (str);
00542   _dbus_assert (i < real->len);
00543   _dbus_assert (i >= 0);
00544   
00545   real->str[i] = byte;
00546 }
00547 
00557 unsigned char
00558 _dbus_string_get_byte (const DBusString  *str,
00559                        int                start)
00560 {
00561   DBUS_CONST_STRING_PREAMBLE (str);
00562   _dbus_assert (start <= real->len);
00563   _dbus_assert (start >= 0);
00564   
00565   return real->str[start];
00566 }
00567 
00578 dbus_bool_t
00579 _dbus_string_insert_bytes (DBusString   *str,
00580                            int           i,
00581                            int           n_bytes,
00582                            unsigned char byte)
00583 {
00584   DBUS_STRING_PREAMBLE (str);
00585   _dbus_assert (i <= real->len);
00586   _dbus_assert (i >= 0);
00587   _dbus_assert (n_bytes >= 0);
00588 
00589   if (n_bytes == 0)
00590     return TRUE;
00591   
00592   if (!open_gap (n_bytes, real, i))
00593     return FALSE;
00594   
00595   memset (real->str + i, byte, n_bytes);
00596 
00597   return TRUE;
00598 }
00599 
00610 dbus_bool_t
00611 _dbus_string_steal_data (DBusString        *str,
00612                          char             **data_return)
00613 {
00614   int old_max_length;
00615   DBUS_STRING_PREAMBLE (str);
00616   _dbus_assert (data_return != NULL);
00617 
00618   undo_alignment (real);
00619   
00620   *data_return = real->str;
00621 
00622   old_max_length = real->max_length;
00623   
00624   /* reset the string */
00625   if (!_dbus_string_init (str))
00626     {
00627       /* hrm, put it back then */
00628       real->str = *data_return;
00629       *data_return = NULL;
00630       fixup_alignment (real);
00631       return FALSE;
00632     }
00633 
00634   real->max_length = old_max_length;
00635 
00636   return TRUE;
00637 }
00638 
00654 dbus_bool_t
00655 _dbus_string_steal_data_len (DBusString        *str,
00656                              char             **data_return,
00657                              int                start,
00658                              int                len)
00659 {
00660   DBusString dest;
00661   DBUS_STRING_PREAMBLE (str);
00662   _dbus_assert (data_return != NULL);
00663   _dbus_assert (start >= 0);
00664   _dbus_assert (len >= 0);
00665   _dbus_assert (start <= real->len);
00666   _dbus_assert (len <= real->len - start);
00667 
00668   if (!_dbus_string_init (&dest))
00669     return FALSE;
00670 
00671   set_max_length (&dest, real->max_length);
00672   
00673   if (!_dbus_string_move_len (str, start, len, &dest, 0))
00674     {
00675       _dbus_string_free (&dest);
00676       return FALSE;
00677     }
00678 
00679   _dbus_warn ("Broken code in _dbus_string_steal_data_len(), see @todo, FIXME\n");
00680   if (!_dbus_string_steal_data (&dest, data_return))
00681     {
00682       _dbus_string_free (&dest);
00683       return FALSE;
00684     }
00685 
00686   _dbus_string_free (&dest);
00687   return TRUE;
00688 }
00689 
00690 
00698 dbus_bool_t
00699 _dbus_string_copy_data (const DBusString  *str,
00700                         char             **data_return)
00701 {
00702   DBUS_CONST_STRING_PREAMBLE (str);
00703   _dbus_assert (data_return != NULL);
00704   
00705   *data_return = dbus_malloc (real->len + 1);
00706   if (*data_return == NULL)
00707     return FALSE;
00708 
00709   memcpy (*data_return, real->str, real->len + 1);
00710 
00711   return TRUE;
00712 }
00713 
00723 dbus_bool_t
00724 _dbus_string_copy_data_len (const DBusString  *str,
00725                             char             **data_return,
00726                             int                start,
00727                             int                len)
00728 {
00729   DBusString dest;
00730 
00731   DBUS_CONST_STRING_PREAMBLE (str);
00732   _dbus_assert (data_return != NULL);
00733   _dbus_assert (start >= 0);
00734   _dbus_assert (len >= 0);
00735   _dbus_assert (start <= real->len);
00736   _dbus_assert (len <= real->len - start);
00737 
00738   if (!_dbus_string_init (&dest))
00739     return FALSE;
00740 
00741   set_max_length (&dest, real->max_length);
00742 
00743   if (!_dbus_string_copy_len (str, start, len, &dest, 0))
00744     {
00745       _dbus_string_free (&dest);
00746       return FALSE;
00747     }
00748 
00749   if (!_dbus_string_steal_data (&dest, data_return))
00750     {
00751       _dbus_string_free (&dest);
00752       return FALSE;
00753     }
00754 
00755   _dbus_string_free (&dest);
00756   return TRUE;
00757 }
00758 
00764 int
00765 _dbus_string_get_length (const DBusString  *str)
00766 {
00767   DBUS_CONST_STRING_PREAMBLE (str);
00768   
00769   return real->len;
00770 }
00771 
00784 dbus_bool_t
00785 _dbus_string_lengthen (DBusString *str,
00786                        int         additional_length)
00787 {
00788   DBUS_STRING_PREAMBLE (str);  
00789   _dbus_assert (additional_length >= 0);
00790 
00791   if (additional_length > real->max_length - real->len)
00792     return FALSE; /* would overflow */
00793   
00794   return set_length (real,
00795                      real->len + additional_length);
00796 }
00797 
00804 void
00805 _dbus_string_shorten (DBusString *str,
00806                       int         length_to_remove)
00807 {
00808   DBUS_STRING_PREAMBLE (str);
00809   _dbus_assert (length_to_remove >= 0);
00810   _dbus_assert (length_to_remove <= real->len);
00811 
00812   set_length (real,
00813               real->len - length_to_remove);
00814 }
00815 
00826 dbus_bool_t
00827 _dbus_string_set_length (DBusString *str,
00828                          int         length)
00829 {
00830   DBUS_STRING_PREAMBLE (str);
00831   _dbus_assert (length >= 0);
00832 
00833   return set_length (real, length);
00834 }
00835 
00836 static dbus_bool_t
00837 align_length_then_lengthen (DBusString *str,
00838                             int         alignment,
00839                             int         then_lengthen_by)
00840 {
00841   unsigned long new_len; /* ulong to avoid _DBUS_ALIGN_VALUE overflow */
00842   int delta;
00843   DBUS_STRING_PREAMBLE (str);
00844   _dbus_assert (alignment >= 1);
00845   _dbus_assert (alignment <= 8); /* it has to be a bug if > 8 */
00846 
00847   new_len = _DBUS_ALIGN_VALUE (real->len, alignment);
00848   if (new_len > (unsigned long) real->max_length - then_lengthen_by)
00849     return FALSE;
00850   new_len += then_lengthen_by;
00851   
00852   delta = new_len - real->len;
00853   _dbus_assert (delta >= 0);
00854 
00855   if (delta == 0)
00856     return TRUE;
00857 
00858   if (!set_length (real, new_len))
00859     return FALSE;
00860 
00861   /* delta == padding + then_lengthen_by
00862    * new_len == old_len + padding + then_lengthen_by
00863    */
00864   if (then_lengthen_by < delta)
00865     {
00866       unsigned int i;
00867       i = new_len - delta;
00868       while (i < (new_len - then_lengthen_by))
00869         {
00870           real->str[i] = '\0';
00871           ++i;
00872         }
00873     }
00874       
00875   return TRUE;
00876 }
00877 
00886 dbus_bool_t
00887 _dbus_string_align_length (DBusString *str,
00888                            int         alignment)
00889 {
00890   return align_length_then_lengthen (str, alignment, 0);
00891 }
00892 
00893 static dbus_bool_t
00894 append (DBusRealString *real,
00895         const char     *buffer,
00896         int             buffer_len)
00897 {
00898   if (buffer_len == 0)
00899     return TRUE;
00900 
00901   if (!_dbus_string_lengthen ((DBusString*)real, buffer_len))
00902     return FALSE;
00903 
00904   memcpy (real->str + (real->len - buffer_len),
00905           buffer,
00906           buffer_len);
00907 
00908   return TRUE;
00909 }
00910 
00918 dbus_bool_t
00919 _dbus_string_append (DBusString *str,
00920                      const char *buffer)
00921 {
00922   unsigned long buffer_len;
00923   
00924   DBUS_STRING_PREAMBLE (str);
00925   _dbus_assert (buffer != NULL);
00926   
00927   buffer_len = strlen (buffer);
00928   if (buffer_len > (unsigned long) real->max_length)
00929     return FALSE;
00930   
00931   return append (real, buffer, buffer_len);
00932 }
00933 
00942 dbus_bool_t
00943 _dbus_string_append_4_aligned (DBusString         *str,
00944                                const unsigned char octets[4])
00945 {
00946   dbus_uint32_t *p;
00947   DBUS_STRING_PREAMBLE (str);
00948   
00949   if (!align_length_then_lengthen (str, 4, 4))
00950     return FALSE;
00951 
00952   p = (dbus_uint32_t*) (real->str + (real->len - 4));
00953   *p = *((dbus_uint32_t*)octets);
00954 
00955   return TRUE;
00956 }
00957 
00966 dbus_bool_t
00967 _dbus_string_append_8_aligned (DBusString         *str,
00968                                const unsigned char octets[8])
00969 {
00970 #ifdef DBUS_HAVE_INT64
00971   dbus_uint64_t *p;
00972   DBUS_STRING_PREAMBLE (str);
00973   
00974   if (!align_length_then_lengthen (str, 8, 8))
00975     return FALSE;
00976 
00977   p = (dbus_uint64_t*) (real->str + (real->len - 8));
00978   *p = *((dbus_uint64_t*)octets);
00979 #else
00980   unsigned char *p;
00981   DBUS_STRING_PREAMBLE (str);
00982   
00983   if (!align_length_then_lengthen (str, 8, 8))
00984     return FALSE;
00985 
00986   p = real->str + (real->len - 8);
00987   
00988   *p++ = octets[0];
00989   *p++ = octets[1];
00990   *p++ = octets[2];
00991   *p++ = octets[3];
00992   *p++ = octets[4];
00993   *p++ = octets[5];
00994   *p++ = octets[6];
00995   *p++ = octets[7];
00996   _dbus_assert (p == (real->str + real->len));
00997 #endif
00998 
00999   return TRUE;
01000 }
01001 
01011 dbus_bool_t
01012 _dbus_string_append_printf_valist  (DBusString        *str,
01013                                     const char        *format,
01014                                     va_list            args)
01015 {
01016   int len;
01017   char c;
01018   va_list args_copy;
01019 
01020   DBUS_STRING_PREAMBLE (str);
01021 
01022   DBUS_VA_COPY (args_copy, args);
01023 
01024   /* Measure the message length without terminating nul */
01025   len = vsnprintf (&c, 1, format, args);
01026 
01027   if (!_dbus_string_lengthen (str, len))
01028     {
01029       /* don't leak the copy */
01030       va_end (args_copy);
01031       return FALSE;
01032     }
01033   
01034   vsprintf (real->str + (real->len - len),
01035             format, args_copy);
01036 
01037   va_end (args_copy);
01038 
01039   return TRUE;
01040 }
01041 
01050 dbus_bool_t
01051 _dbus_string_append_printf (DBusString        *str,
01052                             const char        *format,
01053                             ...)
01054 {
01055   va_list args;
01056   dbus_bool_t retval;
01057   
01058   va_start (args, format);
01059   retval = _dbus_string_append_printf_valist (str, format, args);
01060   va_end (args);
01061 
01062   return retval;
01063 }
01064 
01073 dbus_bool_t
01074 _dbus_string_append_len (DBusString *str,
01075                          const char *buffer,
01076                          int         len)
01077 {
01078   DBUS_STRING_PREAMBLE (str);
01079   _dbus_assert (buffer != NULL);
01080   _dbus_assert (len >= 0);
01081 
01082   return append (real, buffer, len);
01083 }
01084 
01093 dbus_bool_t
01094 _dbus_string_append_byte (DBusString    *str,
01095                           unsigned char  byte)
01096 {
01097   DBUS_STRING_PREAMBLE (str);
01098 
01099   if (!set_length (real, real->len + 1))
01100     return FALSE;
01101 
01102   real->str[real->len-1] = byte;
01103 
01104   return TRUE;
01105 }
01106 
01114 dbus_bool_t
01115 _dbus_string_append_unichar (DBusString    *str,
01116                              dbus_unichar_t ch)
01117 {
01118   int len;
01119   int first;
01120   int i;
01121   char *out;
01122   
01123   DBUS_STRING_PREAMBLE (str);
01124 
01125   /* this code is from GLib but is pretty standard I think */
01126   
01127   len = 0;
01128   
01129   if (ch < 0x80)
01130     {
01131       first = 0;
01132       len = 1;
01133     }
01134   else if (ch < 0x800)
01135     {
01136       first = 0xc0;
01137       len = 2;
01138     }
01139   else if (ch < 0x10000)
01140     {
01141       first = 0xe0;
01142       len = 3;
01143     }
01144    else if (ch < 0x200000)
01145     {
01146       first = 0xf0;
01147       len = 4;
01148     }
01149   else if (ch < 0x4000000)
01150     {
01151       first = 0xf8;
01152       len = 5;
01153     }
01154   else
01155     {
01156       first = 0xfc;
01157       len = 6;
01158     }
01159 
01160   if (len > (real->max_length - real->len))
01161     return FALSE; /* real->len + len would overflow */
01162   
01163   if (!set_length (real, real->len + len))
01164     return FALSE;
01165 
01166   out = real->str + (real->len - len);
01167   
01168   for (i = len - 1; i > 0; --i)
01169     {
01170       out[i] = (ch & 0x3f) | 0x80;
01171       ch >>= 6;
01172     }
01173   out[0] = ch | first;
01174 
01175   return TRUE;
01176 }
01177 
01178 static void
01179 delete (DBusRealString *real,
01180         int             start,
01181         int             len)
01182 {
01183   if (len == 0)
01184     return;
01185   
01186   memmove (real->str + start, real->str + start + len, real->len - (start + len));
01187   real->len -= len;
01188   real->str[real->len] = '\0';
01189 }
01190 
01200 void
01201 _dbus_string_delete (DBusString       *str,
01202                      int               start,
01203                      int               len)
01204 {
01205   DBUS_STRING_PREAMBLE (str);
01206   _dbus_assert (start >= 0);
01207   _dbus_assert (len >= 0);
01208   _dbus_assert (start <= real->len);
01209   _dbus_assert (len <= real->len - start);
01210   
01211   delete (real, start, len);
01212 }
01213 
01214 static dbus_bool_t
01215 copy (DBusRealString *source,
01216       int             start,
01217       int             len,
01218       DBusRealString *dest,
01219       int             insert_at)
01220 {
01221   if (len == 0)
01222     return TRUE;
01223 
01224   if (!open_gap (len, dest, insert_at))
01225     return FALSE;
01226   
01227   memcpy (dest->str + insert_at,
01228           source->str + start,
01229           len);
01230 
01231   return TRUE;
01232 }
01233 
01243 #define DBUS_STRING_COPY_PREAMBLE(source, start, dest, insert_at)       \
01244   DBusRealString *real_source = (DBusRealString*) source;               \
01245   DBusRealString *real_dest = (DBusRealString*) dest;                   \
01246   _dbus_assert ((source) != (dest));                                    \
01247   DBUS_GENERIC_STRING_PREAMBLE (real_source);                           \
01248   DBUS_GENERIC_STRING_PREAMBLE (real_dest);                             \
01249   _dbus_assert (!real_dest->constant);                                  \
01250   _dbus_assert (!real_dest->locked);                                    \
01251   _dbus_assert ((start) >= 0);                                          \
01252   _dbus_assert ((start) <= real_source->len);                           \
01253   _dbus_assert ((insert_at) >= 0);                                      \
01254   _dbus_assert ((insert_at) <= real_dest->len)
01255 
01266 dbus_bool_t
01267 _dbus_string_move (DBusString       *source,
01268                    int               start,
01269                    DBusString       *dest,
01270                    int               insert_at)
01271 {
01272   DBusRealString *real_source = (DBusRealString*) source;
01273   _dbus_assert (start <= real_source->len);
01274   
01275   return _dbus_string_move_len (source, start,
01276                                 real_source->len - start,
01277                                 dest, insert_at);
01278 }
01279 
01290 dbus_bool_t
01291 _dbus_string_copy (const DBusString *source,
01292                    int               start,
01293                    DBusString       *dest,
01294                    int               insert_at)
01295 {
01296   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
01297 
01298   return copy (real_source, start,
01299                real_source->len - start,
01300                real_dest,
01301                insert_at);
01302 }
01303 
01318 dbus_bool_t
01319 _dbus_string_move_len (DBusString       *source,
01320                        int               start,
01321                        int               len,
01322                        DBusString       *dest,
01323                        int               insert_at)
01324 
01325 {
01326   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
01327   _dbus_assert (len >= 0);
01328   _dbus_assert ((start + len) <= real_source->len);
01329 
01330 
01331   if (len == 0)
01332     {
01333       return TRUE;
01334     }
01335   else if (start == 0 &&
01336            len == real_source->len &&
01337            real_dest->len == 0)
01338     {
01339       /* Short-circuit moving an entire existing string to an empty string
01340        * by just swapping the buffers.
01341        */
01342       /* we assume ->constant doesn't matter as you can't have
01343        * a constant string involved in a move.
01344        */
01345 #define ASSIGN_DATA(a, b) do {                  \
01346         (a)->str = (b)->str;                    \
01347         (a)->len = (b)->len;                    \
01348         (a)->allocated = (b)->allocated;        \
01349         (a)->align_offset = (b)->align_offset;  \
01350       } while (0)
01351       
01352       DBusRealString tmp;
01353 
01354       ASSIGN_DATA (&tmp, real_source);
01355       ASSIGN_DATA (real_source, real_dest);
01356       ASSIGN_DATA (real_dest, &tmp);
01357 
01358       return TRUE;
01359     }
01360   else
01361     {
01362       if (!copy (real_source, start, len,
01363                  real_dest,
01364                  insert_at))
01365         return FALSE;
01366       
01367       delete (real_source, start,
01368               len);
01369       
01370       return TRUE;
01371     }
01372 }
01373 
01385 dbus_bool_t
01386 _dbus_string_copy_len (const DBusString *source,
01387                        int               start,
01388                        int               len,
01389                        DBusString       *dest,
01390                        int               insert_at)
01391 {
01392   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
01393   _dbus_assert (len >= 0);
01394   _dbus_assert (start <= real_source->len);
01395   _dbus_assert (len <= real_source->len - start);
01396   
01397   return copy (real_source, start, len,
01398                real_dest,
01399                insert_at);
01400 }
01401 
01423 dbus_bool_t
01424 _dbus_string_replace_len (const DBusString *source,
01425                           int               start,
01426                           int               len,
01427                           DBusString       *dest,
01428                           int               replace_at,
01429                           int               replace_len)
01430 {
01431   DBUS_STRING_COPY_PREAMBLE (source, start, dest, replace_at);
01432   _dbus_assert (len >= 0);
01433   _dbus_assert (start <= real_source->len);
01434   _dbus_assert (len <= real_source->len - start);
01435   _dbus_assert (replace_at >= 0);
01436   _dbus_assert (replace_at <= real_dest->len);
01437   _dbus_assert (replace_len <= real_dest->len - replace_at);
01438 
01439   if (!copy (real_source, start, len,
01440              real_dest, replace_at))
01441     return FALSE;
01442 
01443   delete (real_dest, replace_at + len, replace_len);
01444 
01445   return TRUE;
01446 }
01447 
01448 /* Unicode macros and utf8_validate() from GLib Owen Taylor, Havoc
01449  * Pennington, and Tom Tromey are the authors and authorized relicense.
01450  */
01451 
01457 #define UTF8_COMPUTE(Char, Mask, Len)                                         \
01458   if (Char < 128)                                                             \
01459     {                                                                         \
01460       Len = 1;                                                                \
01461       Mask = 0x7f;                                                            \
01462     }                                                                         \
01463   else if ((Char & 0xe0) == 0xc0)                                             \
01464     {                                                                         \
01465       Len = 2;                                                                \
01466       Mask = 0x1f;                                                            \
01467     }                                                                         \
01468   else if ((Char & 0xf0) == 0xe0)                                             \
01469     {                                                                         \
01470       Len = 3;                                                                \
01471       Mask = 0x0f;                                                            \
01472     }                                                                         \
01473   else if ((Char & 0xf8) == 0xf0)                                             \
01474     {                                                                         \
01475       Len = 4;                                                                \
01476       Mask = 0x07;                                                            \
01477     }                                                                         \
01478   else if ((Char & 0xfc) == 0xf8)                                             \
01479     {                                                                         \
01480       Len = 5;                                                                \
01481       Mask = 0x03;                                                            \
01482     }                                                                         \
01483   else if ((Char & 0xfe) == 0xfc)                                             \
01484     {                                                                         \
01485       Len = 6;                                                                \
01486       Mask = 0x01;                                                            \
01487     }                                                                         \
01488   else                                                                        \
01489     Len = -1;
01490 
01495 #define UTF8_LENGTH(Char)              \
01496   ((Char) < 0x80 ? 1 :                 \
01497    ((Char) < 0x800 ? 2 :               \
01498     ((Char) < 0x10000 ? 3 :            \
01499      ((Char) < 0x200000 ? 4 :          \
01500       ((Char) < 0x4000000 ? 5 : 6)))))
01501    
01511 #define UTF8_GET(Result, Chars, Count, Mask, Len)                             \
01512   (Result) = (Chars)[0] & (Mask);                                             \
01513   for ((Count) = 1; (Count) < (Len); ++(Count))                               \
01514     {                                                                         \
01515       if (((Chars)[(Count)] & 0xc0) != 0x80)                                  \
01516         {                                                                     \
01517           (Result) = -1;                                                      \
01518           break;                                                              \
01519         }                                                                     \
01520       (Result) <<= 6;                                                         \
01521       (Result) |= ((Chars)[(Count)] & 0x3f);                                  \
01522     }
01523 
01529 #define UNICODE_VALID(Char)                   \
01530     ((Char) < 0x110000 &&                     \
01531      (((Char) & 0xFFFFF800) != 0xD800) &&     \
01532      ((Char) < 0xFDD0 || (Char) > 0xFDEF) &&  \
01533      ((Char) & 0xFFFF) != 0xFFFF)
01534 
01545 void
01546 _dbus_string_get_unichar (const DBusString *str,
01547                           int               start,
01548                           dbus_unichar_t   *ch_return,
01549                           int              *end_return)
01550 {
01551   int i, mask, len;
01552   dbus_unichar_t result;
01553   unsigned char c;
01554   unsigned char *p;
01555   DBUS_CONST_STRING_PREAMBLE (str);
01556   _dbus_assert (start >= 0);
01557   _dbus_assert (start <= real->len);
01558   
01559   if (ch_return)
01560     *ch_return = 0;
01561   if (end_return)
01562     *end_return = real->len;
01563   
01564   mask = 0;
01565   p = real->str + start;
01566   c = *p;
01567   
01568   UTF8_COMPUTE (c, mask, len);
01569   if (len == -1)
01570     return;
01571   UTF8_GET (result, p, i, mask, len);
01572 
01573   if (result == (dbus_unichar_t)-1)
01574     return;
01575 
01576   if (ch_return)
01577     *ch_return = result;
01578   if (end_return)
01579     *end_return = start + len;
01580 }
01581 
01596 dbus_bool_t
01597 _dbus_string_find (const DBusString *str,
01598                    int               start,
01599                    const char       *substr,
01600                    int              *found)
01601 {
01602   return _dbus_string_find_to (str, start,
01603                                ((const DBusRealString*)str)->len,
01604                                substr, found);
01605 }
01606 
01623 dbus_bool_t
01624 _dbus_string_find_to (const DBusString *str,
01625                       int               start,
01626                       int               end,
01627                       const char       *substr,
01628                       int              *found)
01629 {
01630   int i;
01631   DBUS_CONST_STRING_PREAMBLE (str);
01632   _dbus_assert (substr != NULL);
01633   _dbus_assert (start <= real->len);
01634   _dbus_assert (start >= 0);
01635   _dbus_assert (substr != NULL);
01636   _dbus_assert (end <= real->len);
01637   _dbus_assert (start <= end);
01638 
01639   /* we always "find" an empty string */
01640   if (*substr == '\0')
01641     {
01642       if (found)
01643         *found = start;
01644       return TRUE;
01645     }
01646 
01647   i = start;
01648   while (i < end)
01649     {
01650       if (real->str[i] == substr[0])
01651         {
01652           int j = i + 1;
01653           
01654           while (j < end)
01655             {
01656               if (substr[j - i] == '\0')
01657                 break;
01658               else if (real->str[j] != substr[j - i])
01659                 break;
01660               
01661               ++j;
01662             }
01663 
01664           if (substr[j - i] == '\0')
01665             {
01666               if (found)
01667                 *found = i;
01668               return TRUE;
01669             }
01670         }
01671       
01672       ++i;
01673     }
01674 
01675   if (found)
01676     *found = end;
01677   
01678   return FALSE;  
01679 }
01680 
01691 dbus_bool_t
01692 _dbus_string_find_byte_backward (const DBusString  *str,
01693                                  int                start,
01694                                  unsigned char      byte,
01695                                  int               *found)
01696 {
01697   int i;
01698   DBUS_CONST_STRING_PREAMBLE (str);
01699   _dbus_assert (start <= real->len);
01700   _dbus_assert (start >= 0);
01701   _dbus_assert (found != NULL);
01702 
01703   i = start - 1;
01704   while (i >= 0)
01705     {
01706       if (real->str[i] == byte)
01707         break;
01708       
01709       --i;
01710     }
01711 
01712   if (found)
01713     *found = i;
01714 
01715   return i >= 0;
01716 }
01717 
01728 dbus_bool_t
01729 _dbus_string_find_blank (const DBusString *str,
01730                          int               start,
01731                          int              *found)
01732 {
01733   int i;
01734   DBUS_CONST_STRING_PREAMBLE (str);
01735   _dbus_assert (start <= real->len);
01736   _dbus_assert (start >= 0);
01737   
01738   i = start;
01739   while (i < real->len)
01740     {
01741       if (real->str[i] == ' ' ||
01742           real->str[i] == '\t')
01743         {
01744           if (found)
01745             *found = i;
01746           return TRUE;
01747         }
01748       
01749       ++i;
01750     }
01751 
01752   if (found)
01753     *found = real->len;
01754   
01755   return FALSE;
01756 }
01757 
01766 void
01767 _dbus_string_skip_blank (const DBusString *str,
01768                          int               start,
01769                          int              *end)
01770 {
01771   int i;
01772   DBUS_CONST_STRING_PREAMBLE (str);
01773   _dbus_assert (start <= real->len);
01774   _dbus_assert (start >= 0);
01775   
01776   i = start;
01777   while (i < real->len)
01778     {
01779       if (!(real->str[i] == ' ' ||
01780             real->str[i] == '\t'))
01781         break;
01782       
01783       ++i;
01784     }
01785 
01786   _dbus_assert (i == real->len || !(real->str[i] == ' ' ||
01787                                     real->str[i] == '\t'));
01788   
01789   if (end)
01790     *end = i;
01791 }
01792 
01801 void
01802 _dbus_string_skip_white (const DBusString *str,
01803                          int               start,
01804                          int              *end)
01805 {
01806   int i;
01807   DBUS_CONST_STRING_PREAMBLE (str);
01808   _dbus_assert (start <= real->len);
01809   _dbus_assert (start >= 0);
01810   
01811   i = start;
01812   while (i < real->len)
01813     {
01814       if (!(real->str[i] == ' ' ||
01815             real->str[i] == '\n' ||
01816             real->str[i] == '\r' ||
01817             real->str[i] == '\t'))
01818         break;
01819       
01820       ++i;
01821     }
01822 
01823   _dbus_assert (i == real->len || !(real->str[i] == ' ' ||
01824                                     real->str[i] == '\t'));
01825   
01826   if (end)
01827     *end = i;
01828 }
01829 
01845 dbus_bool_t
01846 _dbus_string_pop_line (DBusString *source,
01847                        DBusString *dest)
01848 {
01849   int eol;
01850   dbus_bool_t have_newline;
01851   
01852   _dbus_string_set_length (dest, 0);
01853   
01854   eol = 0;
01855   if (_dbus_string_find (source, 0, "\n", &eol))
01856     {
01857       have_newline = TRUE;
01858       eol += 1; /* include newline */
01859     }
01860   else
01861     {
01862       eol = _dbus_string_get_length (source);
01863       have_newline = FALSE;
01864     }
01865 
01866   if (eol == 0)
01867     return FALSE; /* eof */
01868   
01869   if (!_dbus_string_move_len (source, 0, eol,
01870                               dest, 0))
01871     {
01872       return FALSE;
01873     }
01874 
01875   /* dump the newline and the \r if we have one */
01876   if (have_newline)
01877     {
01878       dbus_bool_t have_cr;
01879       
01880       _dbus_assert (_dbus_string_get_length (dest) > 0);
01881 
01882       if (_dbus_string_get_length (dest) > 1 &&
01883           _dbus_string_get_byte (dest,
01884                                  _dbus_string_get_length (dest) - 2) == '\r')
01885         have_cr = TRUE;
01886       else
01887         have_cr = FALSE;
01888         
01889       _dbus_string_set_length (dest,
01890                                _dbus_string_get_length (dest) -
01891                                (have_cr ? 2 : 1));
01892     }
01893   
01894   return TRUE;
01895 }
01896 
01903 void
01904 _dbus_string_delete_first_word (DBusString *str)
01905 {
01906   int i;
01907   
01908   if (_dbus_string_find_blank (str, 0, &i))
01909     _dbus_string_skip_blank (str, i, &i);
01910 
01911   _dbus_string_delete (str, 0, i);
01912 }
01913 
01919 void
01920 _dbus_string_delete_leading_blanks (DBusString *str)
01921 {
01922   int i;
01923   
01924   _dbus_string_skip_blank (str, 0, &i);
01925 
01926   if (i > 0)
01927     _dbus_string_delete (str, 0, i);
01928 }
01929 
01939 dbus_bool_t
01940 _dbus_string_equal (const DBusString *a,
01941                     const DBusString *b)
01942 {
01943   const unsigned char *ap;
01944   const unsigned char *bp;
01945   const unsigned char *a_end;
01946   const DBusRealString *real_a = (const DBusRealString*) a;
01947   const DBusRealString *real_b = (const DBusRealString*) b;
01948   DBUS_GENERIC_STRING_PREAMBLE (real_a);
01949   DBUS_GENERIC_STRING_PREAMBLE (real_b);
01950 
01951   if (real_a->len != real_b->len)
01952     return FALSE;
01953 
01954   ap = real_a->str;
01955   bp = real_b->str;
01956   a_end = real_a->str + real_a->len;
01957   while (ap != a_end)
01958     {
01959       if (*ap != *bp)
01960         return FALSE;
01961       
01962       ++ap;
01963       ++bp;
01964     }
01965 
01966   return TRUE;
01967 }
01968 
01981 dbus_bool_t
01982 _dbus_string_equal_len (const DBusString *a,
01983                         const DBusString *b,
01984                         int               len)
01985 {
01986   const unsigned char *ap;
01987   const unsigned char *bp;
01988   const unsigned char *a_end;
01989   const DBusRealString *real_a = (const DBusRealString*) a;
01990   const DBusRealString *real_b = (const DBusRealString*) b;
01991   DBUS_GENERIC_STRING_PREAMBLE (real_a);
01992   DBUS_GENERIC_STRING_PREAMBLE (real_b);
01993 
01994   if (real_a->len != real_b->len &&
01995       (real_a->len < len || real_b->len < len))
01996     return FALSE;
01997 
01998   ap = real_a->str;
01999   bp = real_b->str;
02000   a_end = real_a->str + MIN (real_a->len, len);
02001   while (ap != a_end)
02002     {
02003       if (*ap != *bp)
02004         return FALSE;
02005       
02006       ++ap;
02007       ++bp;
02008     }
02009 
02010   return TRUE;
02011 }
02012 
02020 dbus_bool_t
02021 _dbus_string_equal_c_str (const DBusString *a,
02022                           const char       *c_str)
02023 {
02024   const unsigned char *ap;
02025   const unsigned char *bp;
02026   const unsigned char *a_end;
02027   const DBusRealString *real_a = (const DBusRealString*) a;
02028   DBUS_GENERIC_STRING_PREAMBLE (real_a);
02029   _dbus_assert (c_str != NULL);
02030   
02031   ap = real_a->str;
02032   bp = (const unsigned char*) c_str;
02033   a_end = real_a->str + real_a->len;
02034   while (ap != a_end && *bp)
02035     {
02036       if (*ap != *bp)
02037         return FALSE;
02038       
02039       ++ap;
02040       ++bp;
02041     }
02042 
02043   if (ap != a_end || *bp)
02044     return FALSE;
02045   
02046   return TRUE;
02047 }
02048 
02056 dbus_bool_t
02057 _dbus_string_starts_with_c_str (const DBusString *a,
02058                                 const char       *c_str)
02059 {
02060   const unsigned char *ap;
02061   const unsigned char *bp;
02062   const unsigned char *a_end;
02063   const DBusRealString *real_a = (const DBusRealString*) a;
02064   DBUS_GENERIC_STRING_PREAMBLE (real_a);
02065   _dbus_assert (c_str != NULL);
02066   
02067   ap = real_a->str;
02068   bp = (const unsigned char*) c_str;
02069   a_end = real_a->str + real_a->len;
02070   while (ap != a_end && *bp)
02071     {
02072       if (*ap != *bp)
02073         return FALSE;
02074       
02075       ++ap;
02076       ++bp;
02077     }
02078 
02079   if (*bp == '\0')
02080     return TRUE;
02081   else
02082     return FALSE;
02083 }
02084 
02094 dbus_bool_t
02095 _dbus_string_ends_with_c_str (const DBusString *a,
02096                               const char       *c_str)
02097 {
02098   const unsigned char *ap;
02099   const unsigned char *bp;
02100   const unsigned char *a_end;
02101   unsigned long c_str_len;
02102   const DBusRealString *real_a = (const DBusRealString*) a;
02103   DBUS_GENERIC_STRING_PREAMBLE (real_a);
02104   _dbus_assert (c_str != NULL);
02105   
02106   c_str_len = strlen (c_str);
02107   if (((unsigned long)real_a->len) < c_str_len)
02108     return FALSE;
02109   
02110   ap = real_a->str + (real_a->len - c_str_len);
02111   bp = (const unsigned char*) c_str;
02112   a_end = real_a->str + real_a->len;
02113   while (ap != a_end)
02114     {
02115       if (*ap != *bp)
02116         return FALSE;
02117       
02118       ++ap;
02119       ++bp;
02120     }
02121 
02122   _dbus_assert (*ap == '\0');
02123   _dbus_assert (*bp == '\0');
02124   
02125   return TRUE;
02126 }
02127 
02138 dbus_bool_t
02139 _dbus_string_hex_encode (const DBusString *source,
02140                          int               start,
02141                          DBusString       *dest,
02142                          int               insert_at)
02143 {
02144   DBusString result;
02145   const char hexdigits[16] = {
02146     '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
02147     'a', 'b', 'c', 'd', 'e', 'f'
02148   };
02149   const unsigned char *p;
02150   const unsigned char *end;
02151   dbus_bool_t retval;
02152   
02153   _dbus_assert (start <= _dbus_string_get_length (source));
02154 
02155   if (!_dbus_string_init (&result))
02156     return FALSE;
02157 
02158   retval = FALSE;
02159   
02160   p = (const unsigned char*) _dbus_string_get_const_data (source);
02161   end = p + _dbus_string_get_length (source);
02162   p += start;
02163   
02164   while (p != end)
02165     {
02166       if (!_dbus_string_append_byte (&result,
02167                                      hexdigits[(*p >> 4)]))
02168         goto out;
02169       
02170       if (!_dbus_string_append_byte (&result,
02171                                      hexdigits[(*p & 0x0f)]))
02172         goto out;
02173 
02174       ++p;
02175     }
02176 
02177   if (!_dbus_string_move (&result, 0, dest, insert_at))
02178     goto out;
02179 
02180   retval = TRUE;
02181 
02182  out:
02183   _dbus_string_free (&result);
02184   return retval;
02185 }
02186 
02197 dbus_bool_t
02198 _dbus_string_hex_decode (const DBusString *source,
02199                          int               start,
02200                          int              *end_return,
02201                          DBusString       *dest,
02202                          int               insert_at)
02203 {
02204   DBusString result;
02205   const unsigned char *p;
02206   const unsigned char *end;
02207   dbus_bool_t retval;
02208   dbus_bool_t high_bits;
02209   
02210   _dbus_assert (start <= _dbus_string_get_length (source));
02211 
02212   if (!_dbus_string_init (&result))
02213     return FALSE;
02214 
02215   retval = FALSE;
02216 
02217   high_bits = TRUE;
02218   p = (const unsigned char*) _dbus_string_get_const_data (source);
02219   end = p + _dbus_string_get_length (source);
02220   p += start;
02221   
02222   while (p != end)
02223     {
02224       unsigned int val;
02225 
02226       switch (*p)
02227         {
02228         case '0':
02229           val = 0;
02230           break;
02231         case '1':
02232           val = 1;
02233           break;
02234         case '2':
02235           val = 2;
02236           break;
02237         case '3':
02238           val = 3;
02239           break;
02240         case '4':
02241           val = 4;
02242           break;
02243         case '5':
02244           val = 5;
02245           break;
02246         case '6':
02247           val = 6;
02248           break;
02249         case '7':
02250           val = 7;
02251           break;
02252         case '8':
02253           val = 8;
02254           break;
02255         case '9':
02256           val = 9;
02257           break;
02258         case 'a':
02259         case 'A':
02260           val = 10;
02261           break;
02262         case 'b':
02263         case 'B':
02264           val = 11;
02265           break;
02266         case 'c':
02267         case 'C':
02268           val = 12;
02269           break;
02270         case 'd':
02271         case 'D':
02272           val = 13;
02273           break;
02274         case 'e':
02275         case 'E':
02276           val = 14;
02277           break;
02278         case 'f':
02279         case 'F':
02280           val = 15;
02281           break;
02282         default:
02283           goto done;
02284         }
02285 
02286       if (high_bits)
02287         {
02288           if (!_dbus_string_append_byte (&result,
02289                                          val << 4))
02290             goto out;
02291         }
02292       else
02293         {
02294           int len;
02295           unsigned char b;
02296 
02297           len = _dbus_string_get_length (&result);
02298           
02299           b = _dbus_string_get_byte (&result, len - 1);
02300 
02301           b |= val;
02302 
02303           _dbus_string_set_byte (&result, len - 1, b);
02304         }
02305 
02306       high_bits = !high_bits;
02307 
02308       ++p;
02309     }
02310 
02311  done:
02312   if (!_dbus_string_move (&result, 0, dest, insert_at))
02313     goto out;
02314 
02315   if (end_return)
02316     *end_return = p - (const unsigned char*) _dbus_string_get_const_data (source);
02317 
02318   retval = TRUE;
02319   
02320  out:
02321   _dbus_string_free (&result);  
02322   return retval;
02323 }
02324 
02338 dbus_bool_t
02339 _dbus_string_validate_ascii (const DBusString *str,
02340                              int               start,
02341                              int               len)
02342 {
02343   const unsigned char *s;
02344   const unsigned char *end;
02345   DBUS_CONST_STRING_PREAMBLE (str);
02346   _dbus_assert (start >= 0);
02347   _dbus_assert (start <= real->len);
02348   _dbus_assert (len >= 0);
02349   
02350   if (len > real->len - start)
02351     return FALSE;
02352   
02353   s = real->str + start;
02354   end = s + len;
02355   while (s != end)
02356     {
02357       if (_DBUS_UNLIKELY (*s == '\0' ||
02358                           ((*s & ~0x7f) != 0)))
02359         return FALSE;
02360         
02361       ++s;
02362     }
02363   
02364   return TRUE;
02365 }
02366 
02382 dbus_bool_t
02383 _dbus_string_validate_utf8  (const DBusString *str,
02384                              int               start,
02385                              int               len)
02386 {
02387   const unsigned char *p;
02388   const unsigned char *end;
02389   DBUS_CONST_STRING_PREAMBLE (str);
02390   _dbus_assert (start >= 0);
02391   _dbus_assert (start <= real->len);
02392   _dbus_assert (len >= 0);
02393 
02394   /* we are doing _DBUS_UNLIKELY() here which might be
02395    * dubious in a generic library like GLib, but in D-BUS
02396    * we know we're validating messages and that it would
02397    * only be evil/broken apps that would have invalid
02398    * UTF-8. Also, this function seems to be a performance
02399    * bottleneck in profiles.
02400    */
02401   
02402   if (_DBUS_UNLIKELY (len > real->len - start))
02403     return FALSE;
02404   
02405   p = real->str + start;
02406   end = p + len;
02407   
02408   while (p < end)
02409     {
02410       int i, mask = 0, char_len;
02411       dbus_unichar_t result;
02412       unsigned char c = (unsigned char) *p;
02413       
02414       UTF8_COMPUTE (c, mask, char_len);
02415 
02416       if (_DBUS_UNLIKELY (char_len == -1))
02417         break;
02418 
02419       /* check that the expected number of bytes exists in the remaining length */
02420       if (_DBUS_UNLIKELY ((end - p) < char_len))
02421         break;
02422         
02423       UTF8_GET (result, p, i, mask, char_len);
02424 
02425       if (_DBUS_UNLIKELY (UTF8_LENGTH (result) != char_len)) /* Check for overlong UTF-8 */
02426         break;
02427 
02428       if (_DBUS_UNLIKELY (result == (dbus_unichar_t)-1))
02429         break;
02430 
02431       if (_DBUS_UNLIKELY (!UNICODE_VALID (result)))
02432         break;
02433       
02434       p += char_len;
02435     }
02436 
02437   /* See that we covered the entire length if a length was
02438    * passed in
02439    */
02440   if (_DBUS_UNLIKELY (p != end))
02441     return FALSE;
02442   else
02443     return TRUE;
02444 }
02445 
02459 dbus_bool_t
02460 _dbus_string_validate_nul (const DBusString *str,
02461                            int               start,
02462                            int               len)
02463 {
02464   const unsigned char *s;
02465   const unsigned char *end;
02466   DBUS_CONST_STRING_PREAMBLE (str);
02467   _dbus_assert (start >= 0);
02468   _dbus_assert (len >= 0);
02469   _dbus_assert (start <= real->len);
02470   
02471   if (len > real->len - start)
02472     return FALSE;
02473   
02474   s = real->str + start;
02475   end = s + len;
02476   while (s != end)
02477     {
02478       if (_DBUS_UNLIKELY (*s != '\0'))
02479         return FALSE;
02480       ++s;
02481     }
02482   
02483   return TRUE;
02484 }
02485 
02503 dbus_bool_t
02504 _dbus_string_validate_path (const DBusString  *str,
02505                             int                start,
02506                             int                len)
02507 {
02508   const unsigned char *s;
02509   const unsigned char *end;
02510   const unsigned char *last_slash;
02511   
02512   DBUS_CONST_STRING_PREAMBLE (str);
02513   _dbus_assert (start >= 0);
02514   _dbus_assert (len >= 0);
02515   _dbus_assert (start <= real->len);
02516   
02517   if (len > real->len - start)
02518     return FALSE;
02519 
02520   if (len > DBUS_MAXIMUM_NAME_LENGTH)
02521     return FALSE;
02522 
02523   if (len == 0)
02524     return FALSE;
02525 
02526   s = real->str + start;
02527   end = s + len;
02528 
02529   if (*s != '/')
02530     return FALSE;
02531   last_slash = s;
02532   ++s;
02533   
02534   while (s != end)
02535     {
02536       if (*s == '/')
02537         {
02538           if ((s - last_slash) < 2)
02539             return FALSE; /* no empty path components allowed */
02540 
02541           last_slash = s;
02542         }
02543       
02544       ++s;
02545     }
02546 
02547   if ((end - last_slash) < 2 &&
02548       len > 1)
02549     return FALSE; /* trailing slash not allowed unless the string is "/" */
02550   
02551   return TRUE;
02552 }
02553 
02558 #define VALID_INITIAL_NAME_CHARACTER(c)         \
02559   ( ((c) >= 'A' && (c) <= 'Z') ||               \
02560     ((c) >= 'a' && (c) <= 'z') ||               \
02561     ((c) == '_') )
02562 
02567 #define VALID_NAME_CHARACTER(c)                 \
02568   ( ((c) >= '0' && (c) <= '9') ||               \
02569     ((c) >= 'A' && (c) <= 'Z') ||               \
02570     ((c) >= 'a' && (c) <= 'z') ||               \
02571     ((c) == '_') )
02572 
02586 dbus_bool_t
02587 _dbus_string_validate_interface (const DBusString  *str,
02588                                  int                start,
02589                                  int                len)
02590 {  
02591   const unsigned char *s;
02592   const unsigned char *end;
02593   const unsigned char *iface;
02594   const unsigned char *last_dot;
02595   
02596   DBUS_CONST_STRING_PREAMBLE (str);
02597   _dbus_assert (start >= 0);
02598   _dbus_assert (len >= 0);
02599   _dbus_assert (start <= real->len);
02600   
02601   if (len > real->len - start)
02602     return FALSE;
02603 
02604   if (len > DBUS_MAXIMUM_NAME_LENGTH)
02605     return FALSE;
02606 
02607   if (len == 0)
02608     return FALSE;
02609 
02610   last_dot = NULL;
02611   iface = real->str + start;
02612   end = iface + len;
02613   s = iface;
02614 
02615   /* check special cases of first char so it doesn't have to be done
02616    * in the loop. Note we know len > 0
02617    */
02618   if (_DBUS_UNLIKELY (*s == '.')) /* disallow starting with a . */
02619     return FALSE;
02620   else if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*s)))
02621     return FALSE;
02622   else
02623     ++s;
02624   
02625   while (s != end)
02626     {
02627       if (*s == '.')
02628         {
02629           if (_DBUS_UNLIKELY ((s + 1) == end))
02630             return FALSE;
02631           else if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*(s + 1))))
02632             return FALSE;
02633           last_dot = s;
02634           ++s; /* we just validated the next char, so skip two */
02635         }
02636       else if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s)))
02637         {
02638           return FALSE;
02639         }
02640       
02641       ++s;
02642     }
02643 
02644   if (_DBUS_UNLIKELY (last_dot == NULL))
02645     return FALSE;
02646   
02647   return TRUE;
02648 }
02649 
02663 dbus_bool_t
02664 _dbus_string_validate_member (const DBusString  *str,
02665                               int                start,
02666                               int                len)
02667 {
02668   const unsigned char *s;
02669   const unsigned char *end;
02670   const unsigned char *member;
02671   
02672   DBUS_CONST_STRING_PREAMBLE (str);
02673   _dbus_assert (start >= 0);
02674   _dbus_assert (len >= 0);
02675   _dbus_assert (start <= real->len);
02676   
02677   if (len > real->len - start)
02678     return FALSE;
02679 
02680   if (len > DBUS_MAXIMUM_NAME_LENGTH)
02681     return FALSE;
02682 
02683   if (len == 0)
02684     return FALSE;
02685 
02686   member = real->str + start;
02687   end = member + len;
02688   s = member;
02689 
02690   /* check special cases of first char so it doesn't have to be done
02691    * in the loop. Note we know len > 0
02692    */
02693 
02694   if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*s)))
02695     return FALSE;
02696   else
02697     ++s;
02698   
02699   while (s != end)
02700     {
02701       if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s)))
02702         {
02703           return FALSE;
02704         }
02705       
02706       ++s;
02707     }
02708   
02709   return TRUE;
02710 }
02711 
02725 dbus_bool_t
02726 _dbus_string_validate_error_name (const DBusString  *str,
02727                                   int                start,
02728                                   int                len)
02729 {
02730   /* Same restrictions as interface name at the moment */
02731   return _dbus_string_validate_interface (str, start, len);
02732 }
02733 
02734 /* This assumes the first char exists and is ':' */
02735 static dbus_bool_t
02736 _dbus_string_validate_base_service (const DBusString  *str,
02737                                     int                start,
02738                                     int                len)
02739 {
02740   const unsigned char *s;
02741   const unsigned char *end;
02742   const unsigned char *service;
02743   
02744   DBUS_CONST_STRING_PREAMBLE (str);
02745   _dbus_assert (start >= 0);
02746   _dbus_assert (len >= 0);
02747   _dbus_assert (start <= real->len);
02748   
02749   if (len > real->len - start)
02750     return FALSE;
02751 
02752   if (len > DBUS_MAXIMUM_NAME_LENGTH)
02753     return FALSE;
02754 
02755   _dbus_assert (len > 0);
02756 
02757   service = real->str + start;
02758   end = service + len;
02759   _dbus_assert (*service == ':');
02760   s = service + 1;
02761   
02762   while (s != end)
02763     {
02764       if (*s == '.')
02765         {
02766           if (_DBUS_UNLIKELY ((s + 1) == end))
02767             return FALSE;
02768           if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*(s + 1))))
02769             return FALSE;
02770           ++s; /* we just validated the next char, so skip two */
02771         }
02772       else if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s)))
02773         {
02774           return FALSE;
02775         }
02776       
02777       ++s;
02778     }
02779   
02780   return TRUE;
02781 }
02782 
02796 dbus_bool_t
02797 _dbus_string_validate_service (const DBusString  *str,
02798                                int                start,
02799                                int                len)
02800 {
02801   if (_DBUS_UNLIKELY (len == 0))
02802     return FALSE;
02803   if (_dbus_string_get_byte (str, start) == ':')
02804     return _dbus_string_validate_base_service (str, start, len);
02805   else
02806     return _dbus_string_validate_interface (str, start, len);
02807 }
02808 
02814 void
02815 _dbus_string_zero (DBusString *str)
02816 {
02817   DBUS_STRING_PREAMBLE (str);
02818 
02819   memset (real->str - real->align_offset, '\0', real->allocated);
02820 }
02823 #ifdef DBUS_BUILD_TESTS
02824 #include "dbus-test.h"
02825 #include <stdio.h>
02826 
02840 dbus_bool_t
02841 _dbus_string_parse_basic_type (const DBusString  *str,
02842                                char               type,
02843                                int                start,
02844                                void              *value,
02845                                int               *end_return)
02846 {
02847   int end = start;
02848 
02849   switch (type)
02850     {
02851     case DBUS_TYPE_BOOLEAN:
02852       {
02853         int len = _dbus_string_get_length (str) - start;
02854         if (len >= 5 && _dbus_string_find_to (str, start, start + 5, "false", NULL))
02855           {
02856             end += 5;
02857             *(unsigned char *) value = TRUE;
02858           }
02859         else if (len >= 4 && _dbus_string_find_to (str, start, start + 4, "true", NULL))
02860           {
02861             end += 4;
02862             *(unsigned char *) value = FALSE;
02863           }
02864         else
02865           _dbus_warn ("could not parse BOOLEAN\n");
02866         break;
02867       }
02868     case DBUS_TYPE_BYTE:
02869       {
02870         long val = 0;
02871 
02872         if (_dbus_string_get_byte (str, start) == '\'' &&
02873             _dbus_string_get_length (str) >= start + 4 &&
02874             _dbus_string_get_byte (str, start + 1) == '\\' &&
02875             _dbus_string_get_byte (str, start + 2) == '\'' &&
02876             _dbus_string_get_byte (str, start + 3) == '\'')
02877           {
02878             val = '\'';
02879             end += 4;
02880           }
02881         else if (_dbus_string_get_byte (str, start) == '\'' &&
02882                  _dbus_string_get_length (str) >= start + 3 &&
02883                  _dbus_string_get_byte (str, start + 2) == '\'')
02884           {
02885             val = _dbus_string_get_byte (str, start + 1);
02886             end += 3;
02887           }
02888         else
02889           {
02890             if (!_dbus_string_parse_int (str, start, &val, &end)) 
02891               _dbus_warn ("Failed to parse integer for BYTE\n");
02892           }
02893 
02894         if (val > 255)
02895           _dbus_warn ("A byte must be in range 0-255 not %ld\n", val);
02896 
02897         *(unsigned char *) value = val;
02898         break;
02899       }
02900     case DBUS_TYPE_INT32:
02901       {
02902         long val;
02903         if (_dbus_string_parse_int (str, start, &val, &end))
02904           *(dbus_int32_t *)value = val;
02905         break;
02906       }
02907     case DBUS_TYPE_UINT32:
02908       {
02909         unsigned long val;
02910         if (_dbus_string_parse_uint (str, start, &val, &end))
02911           *(dbus_uint32_t *)value = val;
02912         break;
02913       }
02914 #ifdef DBUS_HAVE_INT64
02915     case DBUS_TYPE_INT64:
02916     case DBUS_TYPE_UINT64: 
02917       /* use stroll oull */
02918       _dbus_assert_not_reached ("string -> [u]int64 not supported yet");
02919       break;
02920 #endif /* DBUS_HAVE_INT64 */
02921     case DBUS_TYPE_DOUBLE:
02922       _dbus_string_parse_double (str, start, value, &end);
02923       break;
02924     default:
02925       _dbus_assert_not_reached ("not a basic type");
02926       break;
02927     }
02928   if (end_return)
02929     *end_return = end;
02930 
02931   return end != start;
02932 }
02933 
02934 static void
02935 test_max_len (DBusString *str,
02936               int         max_len)
02937 {
02938   if (max_len > 0)
02939     {
02940       if (!_dbus_string_set_length (str, max_len - 1))
02941         _dbus_assert_not_reached ("setting len to one less than max should have worked");
02942     }
02943 
02944   if (!_dbus_string_set_length (str, max_len))
02945     _dbus_assert_not_reached ("setting len to max len should have worked");
02946 
02947   if (_dbus_string_set_length (str, max_len + 1))
02948     _dbus_assert_not_reached ("setting len to one more than max len should not have worked");
02949 
02950   if (!_dbus_string_set_length (str, 0))
02951     _dbus_assert_not_reached ("setting len to zero should have worked");
02952 }
02953 
02954 static void
02955 test_hex_roundtrip (const unsigned char *data,
02956                     int                  len)
02957 {
02958   DBusString orig;
02959   DBusString encoded;
02960   DBusString decoded;
02961   int end;
02962 
02963   if (len < 0)
02964     len = strlen (data);
02965   
02966   if (!_dbus_string_init (&orig))
02967     _dbus_assert_not_reached ("could not init string");
02968 
02969   if (!_dbus_string_init (&encoded))
02970     _dbus_assert_not_reached ("could not init string");
02971   
02972   if (!_dbus_string_init (&decoded))
02973     _dbus_assert_not_reached ("could not init string");
02974 
02975   if (!_dbus_string_append_len (&orig, data, len))
02976     _dbus_assert_not_reached ("couldn't append orig data");
02977 
02978   if (!_dbus_string_hex_encode (&orig, 0, &encoded, 0))
02979     _dbus_assert_not_reached ("could not encode");
02980 
02981   if (!_dbus_string_hex_decode (&encoded, 0, &end, &decoded, 0))
02982     _dbus_assert_not_reached ("could not decode");
02983     
02984   _dbus_assert (_dbus_string_get_length (&encoded) == end);
02985 
02986   if (!_dbus_string_equal (&orig, &decoded))
02987     {
02988       const char *s;
02989       
02990       printf ("Original string %d bytes encoded %d bytes decoded %d bytes\n",
02991               _dbus_string_get_length (&orig),
02992               _dbus_string_get_length (&encoded),
02993               _dbus_string_get_length (&decoded));
02994       printf ("Original: %s\n", data);
02995       s = _dbus_string_get_const_data (&decoded);
02996       printf ("Decoded: %s\n", s);
02997       _dbus_assert_not_reached ("original string not the same as string decoded from hex");
02998     }
02999   
03000   _dbus_string_free (&orig);
03001   _dbus_string_free (&encoded);
03002   _dbus_string_free (&decoded);  
03003 }
03004 
03005 typedef void (* TestRoundtripFunc) (const unsigned char *data,
03006                                     int                  len);
03007 static void
03008 test_roundtrips (TestRoundtripFunc func)
03009 {
03010   (* func) ("Hello this is a string\n", -1);
03011   (* func) ("Hello this is a string\n1", -1);
03012   (* func) ("Hello this is a string\n12", -1);
03013   (* func) ("Hello this is a string\n123", -1);
03014   (* func) ("Hello this is a string\n1234", -1);
03015   (* func) ("Hello this is a string\n12345", -1);
03016   (* func) ("", 0);
03017   (* func) ("1", 1);
03018   (* func) ("12", 2);
03019   (* func) ("123", 3);
03020   (* func) ("1234", 4);
03021   (* func) ("12345", 5);
03022   (* func) ("", 1);
03023   (* func) ("1", 2);
03024   (* func) ("12", 3);
03025   (* func) ("123", 4);
03026   (* func) ("1234", 5);
03027   (* func) ("12345", 6);
03028   {
03029     unsigned char buf[512];
03030     int i;
03031     
03032     i = 0;
03033     while (i < _DBUS_N_ELEMENTS (buf))
03034       {
03035         buf[i] = i;
03036         ++i;
03037       }
03038     i = 0;
03039     while (i < _DBUS_N_ELEMENTS (buf))
03040       {
03041         (* func) (buf, i);
03042         ++i;
03043       }
03044   }
03045 }
03046 
03047 
03058 dbus_bool_t
03059 _dbus_string_test (void)
03060 {
03061   DBusString str;
03062   DBusString other;
03063   int i, end;
03064   long v;
03065   double d;
03066   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 };
03067   char *s;
03068   dbus_unichar_t ch;
03069   const char *valid_paths[] = {
03070     "/",
03071     "/foo/bar",
03072     "/foo",
03073     "/foo/bar/baz"
03074   };
03075   const char *invalid_paths[] = {
03076     "bar",
03077     "bar/baz",
03078     "/foo/bar/",
03079     "/foo/"
03080     "foo/",
03081     "boo//blah",
03082     "//",
03083     "
03084     "foo
03085     "Hello World",
03086     "",
03087     "   ",
03088     "foo bar"
03089   };
03090 
03091   const char *valid_interfaces[] = {
03092     "org.freedesktop.Foo",
03093     "Bar.Baz",
03094     "Blah.Blah.Blah.Blah.Blah",
03095     "a.b",
03096     "a.b.c.d.e.f.g",
03097     "a0.b1.c2.d3.e4.f5.g6",
03098     "abc123.foo27"
03099   };
03100   const char *invalid_interfaces[] = {
03101     ".",
03102     "",
03103     "..",
03104     ".Foo.Bar",
03105     "..Foo.Bar",
03106     "Foo.Bar.",
03107     "Foo.Bar..",
03108     "Foo",
03109     "9foo.bar.baz",
03110     "foo.bar..baz",
03111     "foo.bar...baz",
03112     "foo.bar.b..blah",
03113     ":",
03114     ":0-1",
03115     "10",
03116     ":11.34324",
03117     "0.0.0",
03118     "0..0",
03119     "foo.Bar.%",
03120     "foo.Bar!!",
03121     "!Foo.bar.bz",
03122     "foo.$.blah",
03123     "",
03124     "   ",
03125     "foo bar"
03126   };
03127 
03128   const char *valid_base_services[] = {
03129     ":0",
03130     ":a",
03131     ":",
03132     ":.a",
03133     ":.1",
03134     ":0.1",
03135     ":000.2222",
03136     ":.blah",
03137     ":abce.freedesktop.blah"
03138   };
03139   const char *invalid_base_services[] = {
03140     ":-",
03141     ":!",
03142     ":0-10",
03143     ":blah.",
03144     ":blah.",
03145     ":blah..org",
03146     ":blah.org..",
03147     ":..blah.org",
03148     "",
03149     "   ",
03150     "foo bar"
03151   };
03152 
03153   const char *valid_members[] = {
03154     "Hello",
03155     "Bar",
03156     "foobar",
03157     "_foobar",
03158     "foo89"
03159   };
03160 
03161   const char *invalid_members[] = {
03162     "9Hello",
03163     "10",
03164     "1",
03165     "foo-bar",
03166     "blah.org",
03167     ".blah",
03168     "blah.",
03169     "Hello.",
03170     "!foo",
03171     "",
03172     "   ",
03173     "foo bar"
03174   };
03175   
03176   i = 0;
03177   while (i < _DBUS_N_ELEMENTS (lens))
03178     {
03179       if (!_dbus_string_init (&str))
03180         _dbus_assert_not_reached ("failed to init string");
03181 
03182       set_max_length (&str, lens[i]);
03183       
03184       test_max_len (&str, lens[i]);
03185       _dbus_string_free (&str);
03186 
03187       ++i;
03188     }
03189 
03190   /* Test shortening and setting length */
03191   i = 0;
03192   while (i < _DBUS_N_ELEMENTS (lens))
03193     {
03194       int j;
03195       
03196       if (!_dbus_string_init (&str))
03197         _dbus_assert_not_reached ("failed to init string");
03198 
03199       set_max_length (&str, lens[i]);
03200       
03201       if (!_dbus_string_set_length (&str, lens[i]))
03202         _dbus_assert_not_reached ("failed to set string length");
03203 
03204       j = lens[i];
03205       while (j > 0)
03206         {
03207           _dbus_assert (_dbus_string_get_length (&str) == j);
03208           if (j > 0)
03209             {
03210               _dbus_string_shorten (&str, 1);
03211               _dbus_assert (_dbus_string_get_length (&str) == (j - 1));
03212             }
03213           --j;
03214         }
03215       
03216       _dbus_string_free (&str);
03217 
03218       ++i;
03219     }
03220 
03221   /* Test appending data */
03222   if (!_dbus_string_init (&str))
03223     _dbus_assert_not_reached ("failed to init string");
03224 
03225   i = 0;
03226   while (i < 10)
03227     {
03228       if (!_dbus_string_append (&str, "a"))
03229         _dbus_assert_not_reached ("failed to append string to string\n");
03230 
03231       _dbus_assert (_dbus_string_get_length (&str) == i * 2 + 1);
03232 
03233       if (!_dbus_string_append_byte (&str, 'b'))
03234         _dbus_assert_not_reached ("failed to append byte to string\n");
03235 
03236       _dbus_assert (_dbus_string_get_length (&str) == i * 2 + 2);
03237                     
03238       ++i;
03239     }
03240 
03241   _dbus_string_free (&str);
03242 
03243   /* Check steal_data */
03244   
03245   if (!_dbus_string_init (&str))
03246     _dbus_assert_not_reached ("failed to init string");
03247 
03248   if (!_dbus_string_append (&str, "Hello World"))
03249     _dbus_assert_not_reached ("could not append to string");
03250 
03251   i = _dbus_string_get_length (&str);
03252   
03253   if (!_dbus_string_steal_data (&str, &s))
03254     _dbus_assert_not_reached ("failed to steal data");
03255 
03256   _dbus_assert (_dbus_string_get_length (&str) == 0);
03257   _dbus_assert (((int)strlen (s)) == i);
03258 
03259   dbus_free (s);
03260 
03261   /* Check move */
03262   
03263   if (!_dbus_string_append (&str, "Hello World"))
03264     _dbus_assert_not_reached ("could not append to string");
03265 
03266   i = _dbus_string_get_length (&str);
03267 
03268   if (!_dbus_string_init (&other))
03269     _dbus_assert_not_reached ("could not init string");
03270   
03271   if (!_dbus_string_move (&str, 0, &other, 0))
03272     _dbus_assert_not_reached ("could not move");
03273 
03274   _dbus_assert (_dbus_string_get_length (&str) == 0);
03275   _dbus_assert (_dbus_string_get_length (&other) == i);
03276 
03277   if (!_dbus_string_append (&str, "Hello World"))
03278     _dbus_assert_not_reached ("could not append to string");
03279   
03280   if (!_dbus_string_move (&str, 0, &other, _dbus_string_get_length (&other)))
03281     _dbus_assert_not_reached ("could not move");
03282 
03283   _dbus_assert (_dbus_string_get_length (&str) == 0);
03284   _dbus_assert (_dbus_string_get_length (&other) == i * 2);
03285 
03286     if (!_dbus_string_append (&str, "Hello World"))
03287     _dbus_assert_not_reached ("could not append to string");
03288   
03289   if (!_dbus_string_move (&str, 0, &other, _dbus_string_get_length (&other) / 2))
03290     _dbus_assert_not_reached ("could not move");
03291 
03292   _dbus_assert (_dbus_string_get_length (&str) == 0);
03293   _dbus_assert (_dbus_string_get_length (&other) == i * 3);
03294   
03295   _dbus_string_free (&other);
03296 
03297   /* Check copy */
03298   
03299   if (!_dbus_string_append (&str, "Hello World"))
03300     _dbus_assert_not_reached ("could not append to string");
03301 
03302   i = _dbus_string_get_length (&str);
03303   
03304   if (!_dbus_string_init (&other))
03305     _dbus_assert_not_reached ("could not init string");
03306   
03307   if (!_dbus_string_copy (&str, 0, &other, 0))
03308     _dbus_assert_not_reached ("could not copy");
03309 
03310   _dbus_assert (_dbus_string_get_length (&str) == i);
03311   _dbus_assert (_dbus_string_get_length (&other) == i);
03312 
03313   if (!_dbus_string_copy (&str, 0, &other, _dbus_string_get_length (&other)))
03314     _dbus_assert_not_reached ("could not copy");
03315 
03316   _dbus_assert (_dbus_string_get_length (&str) == i);
03317   _dbus_assert (_dbus_string_get_length (&other) == i * 2);
03318   _dbus_assert (_dbus_string_equal_c_str (&other,
03319                                           "Hello WorldHello World"));
03320 
03321   if (!_dbus_string_copy (&str, 0, &other, _dbus_string_get_length (&other) / 2))
03322     _dbus_assert_not_reached ("could not copy");
03323 
03324   _dbus_assert (_dbus_string_get_length (&str) == i);
03325   _dbus_assert (_dbus_string_get_length (&other) == i * 3);
03326   _dbus_assert (_dbus_string_equal_c_str (&other,
03327                                           "Hello WorldHello WorldHello World"));
03328   
03329   _dbus_string_free (&str);
03330   _dbus_string_free (&other);
03331 
03332   /* Check replace */
03333 
03334   if (!_dbus_string_init (&str))
03335     _dbus_assert_not_reached ("failed to init string");
03336   
03337   if (!_dbus_string_append (&str, "Hello World"))
03338     _dbus_assert_not_reached ("could not append to string");
03339 
03340   i = _dbus_string_get_length (&str);
03341   
03342   if (!_dbus_string_init (&other))
03343     _dbus_assert_not_reached ("could not init string");
03344   
03345   if (!_dbus_string_replace_len (&str, 0, _dbus_string_get_length (&str),
03346                                  &other, 0, _dbus_string_get_length (&other)))
03347     _dbus_assert_not_reached ("could not replace");
03348 
03349   _dbus_assert (_dbus_string_get_length (&str) == i);
03350   _dbus_assert (_dbus_string_get_length (&other) == i);
03351   _dbus_assert (_dbus_string_equal_c_str (&other, "Hello World"));
03352   
03353   if (!_dbus_string_replace_len (&str, 0, _dbus_string_get_length (&str),
03354                                  &other, 5, 1))
03355     _dbus_assert_not_reached ("could not replace center space");
03356 
03357   _dbus_assert (_dbus_string_get_length (&str) == i);
03358   _dbus_assert (_dbus_string_get_length (&other) == i * 2 - 1);
03359   _dbus_assert (_dbus_string_equal_c_str (&other,
03360                                           "HelloHello WorldWorld"));
03361 
03362   
03363   if (!_dbus_string_replace_len (&str, 1, 1,
03364                                  &other,
03365                                  _dbus_string_get_length (&other) - 1,
03366                                  1))
03367     _dbus_assert_not_reached ("could not replace end character");
03368   
03369   _dbus_assert (_dbus_string_get_length (&str) == i);
03370   _dbus_assert (_dbus_string_get_length (&other) == i * 2 - 1);
03371   _dbus_assert (_dbus_string_equal_c_str (&other,
03372                                           "HelloHello WorldWorle"));
03373   
03374   _dbus_string_free (&str);
03375   _dbus_string_free (&other);
03376   
03377   /* Check append/get unichar */
03378   
03379   if (!_dbus_string_init (&str))
03380     _dbus_assert_not_reached ("failed to init string");
03381 
03382   ch = 0;
03383   if (!_dbus_string_append_unichar (&str, 0xfffc))
03384     _dbus_assert_not_reached ("failed to append unichar");
03385 
03386   _dbus_string_get_unichar (&str, 0, &ch, &i);
03387 
03388   _dbus_assert (ch == 0xfffc);
03389   _dbus_assert (i == _dbus_string_get_length (&str));
03390 
03391   _dbus_string_free (&str);
03392 
03393   /* Check insert/set/get byte */
03394   
03395   if (!_dbus_string_init (&str))
03396     _dbus_assert_not_reached ("failed to init string");
03397 
03398   if (!_dbus_string_append (&str, "Hello"))
03399     _dbus_assert_not_reached ("failed to append Hello");
03400 
03401   _dbus_assert (_dbus_string_get_byte (&str, 0) == 'H');
03402   _dbus_assert (_dbus_string_get_byte (&str, 1) == 'e');
03403   _dbus_assert (_dbus_string_get_byte (&str, 2) == 'l');
03404   _dbus_assert (_dbus_string_get_byte (&str, 3) == 'l');
03405   _dbus_assert (_dbus_string_get_byte (&str, 4) == 'o');
03406 
03407   _dbus_string_set_byte (&str, 1, 'q');
03408   _dbus_assert (_dbus_string_get_byte (&str, 1) == 'q');
03409 
03410   if (!_dbus_string_insert_bytes (&str, 0, 1, 255))
03411     _dbus_assert_not_reached ("can't insert byte");
03412 
03413   if (!_dbus_string_insert_bytes (&str, 2, 4, 'Z'))
03414     _dbus_assert_not_reached ("can't insert byte");
03415 
03416   if (!_dbus_string_insert_bytes (&str, _dbus_string_get_length (&str), 1, 'W'))
03417     _dbus_assert_not_reached ("can't insert byte");
03418   
03419   _dbus_assert (_dbus_string_get_byte (&str, 0) == 255);
03420   _dbus_assert (_dbus_string_get_byte (&str, 1) == 'H');
03421   _dbus_assert (_dbus_string_get_byte (&str, 2) == 'Z');
03422   _dbus_assert (_dbus_string_get_byte (&str, 3) == 'Z');
03423   _dbus_assert (_dbus_string_get_byte (&str, 4) == 'Z');
03424   _dbus_assert (_dbus_string_get_byte (&str, 5) == 'Z');
03425   _dbus_assert (_dbus_string_get_byte (&str, 6) == 'q');
03426   _dbus_assert (_dbus_string_get_byte (&str, 7) == 'l');
03427   _dbus_assert (_dbus_string_get_byte (&str, 8) == 'l');
03428   _dbus_assert (_dbus_string_get_byte (&str, 9) == 'o');
03429   _dbus_assert (_dbus_string_get_byte (&str, 10) == 'W');
03430 
03431   _dbus_string_free (&str);
03432   
03433   /* Check append/parse int/double */
03434   
03435   if (!_dbus_string_init (&str))
03436     _dbus_assert_not_reached ("failed to init string");
03437 
03438   if (!_dbus_string_append_int (&str, 27))
03439     _dbus_assert_not_reached ("failed to append int");
03440 
03441   i = _dbus_string_get_length (&str);
03442 
03443   if (!_dbus_string_parse_int (&str, 0, &v, &end))
03444     _dbus_assert_not_reached ("failed to parse int");
03445 
03446   _dbus_assert (v == 27);
03447   _dbus_assert (end == i);
03448 
03449   _dbus_string_free (&str);
03450   
03451   if (!_dbus_string_init (&str))
03452     _dbus_assert_not_reached ("failed to init string");
03453   
03454   if (!_dbus_string_append_double (&str, 50.3))
03455     _dbus_assert_not_reached ("failed to append float");
03456 
03457   i = _dbus_string_get_length (&str);
03458 
03459   if (!_dbus_string_parse_double (&str, 0, &d, &end))
03460     _dbus_assert_not_reached ("failed to parse float");
03461 
03462   _dbus_assert (d > (50.3 - 1e-6) && d < (50.3 + 1e-6));
03463   _dbus_assert (end == i);
03464 
03465   _dbus_string_free (&str);
03466 
03467   /* Test find */
03468   if (!_dbus_string_init (&str))
03469     _dbus_assert_not_reached ("failed to init string");
03470 
03471   if (!_dbus_string_append (&str, "Hello"))
03472     _dbus_assert_not_reached ("couldn't append to string");
03473   
03474   if (!_dbus_string_find (&str, 0, "He", &i))
03475     _dbus_assert_not_reached ("didn't find 'He'");
03476   _dbus_assert (i == 0);
03477 
03478   if (!_dbus_string_find (&str, 0, "Hello", &i))
03479     _dbus_assert_not_reached ("didn't find 'Hello'");
03480   _dbus_assert (i == 0);
03481   
03482   if (!_dbus_string_find (&str, 0, "ello", &i))
03483     _dbus_assert_not_reached ("didn't find 'ello'");
03484   _dbus_assert (i == 1);
03485 
03486   if (!_dbus_string_find (&str, 0, "lo", &i))
03487     _dbus_assert_not_reached ("didn't find 'lo'");
03488   _dbus_assert (i == 3);
03489 
03490   if (!_dbus_string_find (&str, 2, "lo", &i))
03491     _dbus_assert_not_reached ("didn't find 'lo'");
03492   _dbus_assert (i == 3);
03493 
03494   if (_dbus_string_find (&str, 4, "lo", &i))
03495     _dbus_assert_not_reached ("did find 'lo'");
03496   
03497   if (!_dbus_string_find (&str, 0, "l", &i))
03498     _dbus_assert_not_reached ("didn't find 'l'");
03499   _dbus_assert (i == 2);
03500 
03501   if (!_dbus_string_find (&str, 0, "H", &i))
03502     _dbus_assert_not_reached ("didn't find 'H'");
03503   _dbus_assert (i == 0);
03504 
03505   if (!_dbus_string_find (&str, 0, "", &i))
03506     _dbus_assert_not_reached ("didn't find ''");
03507   _dbus_assert (i == 0);
03508   
03509   if (_dbus_string_find (&str, 0, "Hello!", NULL))
03510     _dbus_assert_not_reached ("Did find 'Hello!'");
03511 
03512   if (_dbus_string_find (&str, 0, "Oh, Hello", NULL))
03513     _dbus_assert_not_reached ("Did find 'Oh, Hello'");
03514   
03515   if (_dbus_string_find (&str, 0, "ill", NULL))
03516     _dbus_assert_not_reached ("Did find 'ill'");
03517 
03518   if (_dbus_string_find (&str, 0, "q", NULL))
03519     _dbus_assert_not_reached ("Did find 'q'");
03520 
03521   if (!_dbus_string_find_to (&str, 0, 2, "He", NULL))
03522     _dbus_assert_not_reached ("Didn't find 'He'");
03523 
03524   if (_dbus_string_find_to (&str, 0, 2, "Hello", NULL))
03525     _dbus_assert_not_reached ("Did find 'Hello'");
03526 
03527   if (!_dbus_string_find_byte_backward (&str, _dbus_string_get_length (&str), 'H', &i))
03528     _dbus_assert_not_reached ("Did not find 'H'");
03529   _dbus_assert (i == 0);
03530 
03531   if (!_dbus_string_find_byte_backward (&str, _dbus_string_get_length (&str), 'o', &i))
03532     _dbus_assert_not_reached ("Did not find 'o'");
03533   _dbus_assert (i == _dbus_string_get_length (&str) - 1);
03534 
03535   if (_dbus_string_find_byte_backward (&str, _dbus_string_get_length (&str) - 1, 'o', &i))
03536     _dbus_assert_not_reached ("Did find 'o'");
03537   _dbus_assert (i == -1);
03538 
03539   if (_dbus_string_find_byte_backward (&str, 1, 'e', &i))
03540     _dbus_assert_not_reached ("Did find 'e'");
03541   _dbus_assert (i == -1);
03542 
03543   if (!_dbus_string_find_byte_backward (&str, 2, 'e', &i))
03544     _dbus_assert_not_reached ("Didn't find 'e'");
03545   _dbus_assert (i == 1);
03546   
03547   _dbus_string_free (&str);
03548 
03549   /* Hex encoding */
03550   _dbus_string_init_const (&str, "cafebabe, this is a bogus hex string");
03551   if (!_dbus_string_init (&other))
03552     _dbus_assert_not_reached ("could not init string");
03553 
03554   if (!_dbus_string_hex_decode (&str, 0, &end, &other, 0))
03555     _dbus_assert_not_reached ("deccoded bogus hex string with no error");
03556 
03557   _dbus_assert (end == 8);
03558 
03559   _dbus_string_free (&other);
03560 
03561   test_roundtrips (test_hex_roundtrip);
03562 
03563   /* Path validation */
03564   i = 0;
03565   while (i < (int) _DBUS_N_ELEMENTS (valid_paths))
03566     {
03567       _dbus_string_init_const (&str, valid_paths[i]);
03568 
03569       if (!_dbus_string_validate_path (&str, 0,
03570                                        _dbus_string_get_length (&str)))
03571         {
03572           _dbus_warn ("Path \"%s\" should have been valid\n", valid_paths[i]);
03573           _dbus_assert_not_reached ("invalid path");
03574         }
03575       
03576       ++i;
03577     }
03578 
03579   i = 0;
03580   while (i < (int) _DBUS_N_ELEMENTS (invalid_paths))
03581     {
03582       _dbus_string_init_const (&str, invalid_paths[i]);
03583       
03584       if (_dbus_string_validate_path (&str, 0,
03585                                       _dbus_string_get_length (&str)))
03586         {
03587           _dbus_warn ("Path \"%s\" should have been invalid\n", invalid_paths[i]);
03588           _dbus_assert_not_reached ("valid path");
03589         }
03590       
03591       ++i;
03592     }
03593 
03594   /* Interface validation */
03595   i = 0;
03596   while (i < (int) _DBUS_N_ELEMENTS (valid_interfaces))
03597     {
03598       _dbus_string_init_const (&str, valid_interfaces[i]);
03599 
03600       if (!_dbus_string_validate_interface (&str, 0,
03601                                             _dbus_string_get_length (&str)))
03602         {
03603           _dbus_warn ("Interface \"%s\" should have been valid\n", valid_interfaces[i]);
03604           _dbus_assert_not_reached ("invalid interface");
03605         }
03606       
03607       ++i;
03608     }
03609 
03610   i = 0;
03611   while (i < (int) _DBUS_N_ELEMENTS (invalid_interfaces))
03612     {
03613       _dbus_string_init_const (&str, invalid_interfaces[i]);
03614       
03615       if (_dbus_string_validate_interface (&str, 0,
03616                                            _dbus_string_get_length (&str)))
03617         {
03618           _dbus_warn ("Interface \"%s\" should have been invalid\n", invalid_interfaces[i]);
03619           _dbus_assert_not_reached ("valid interface");
03620         }
03621       
03622       ++i;
03623     }
03624 
03625   /* Service validation (check that valid interfaces are valid services,
03626    * and invalid interfaces are invalid services except if they start with ':')
03627    */
03628   i = 0;
03629   while (i < (int) _DBUS_N_ELEMENTS (valid_interfaces))
03630     {
03631       _dbus_string_init_const (&str, valid_interfaces[i]);
03632 
03633       if (!_dbus_string_validate_service (&str, 0,
03634                                           _dbus_string_get_length (&str)))
03635         {
03636           _dbus_warn ("Service \"%s\" should have been valid\n", valid_interfaces[i]);
03637           _dbus_assert_not_reached ("invalid service");
03638         }
03639       
03640       ++i;
03641     }
03642 
03643   i = 0;
03644   while (i < (int) _DBUS_N_ELEMENTS (invalid_interfaces))
03645     {
03646       if (invalid_interfaces[i][0] != ':')
03647         {
03648           _dbus_string_init_const (&str, invalid_interfaces[i]);
03649           
03650           if (_dbus_string_validate_service (&str, 0,
03651                                              _dbus_string_get_length (&str)))
03652             {
03653               _dbus_warn ("Service \"%s\" should have been invalid\n", invalid_interfaces[i]);
03654               _dbus_assert_not_reached ("valid service");
03655             }
03656         }
03657       
03658       ++i;
03659     }
03660 
03661   /* Base service validation */
03662   i = 0;
03663   while (i < (int) _DBUS_N_ELEMENTS (valid_base_services))
03664     {
03665       _dbus_string_init_const (&str, valid_base_services[i]);
03666 
03667       if (!_dbus_string_validate_service (&str, 0,
03668                                           _dbus_string_get_length (&str)))
03669         {
03670           _dbus_warn ("Service \"%s\" should have been valid\n", valid_base_services[i]);
03671           _dbus_assert_not_reached ("invalid base service");
03672         }
03673       
03674       ++i;
03675     }
03676 
03677   i = 0;
03678   while (i < (int) _DBUS_N_ELEMENTS (invalid_base_services))
03679     {
03680       _dbus_string_init_const (&str, invalid_base_services[i]);
03681       
03682       if (_dbus_string_validate_service (&str, 0,
03683                                          _dbus_string_get_length (&str)))
03684         {
03685           _dbus_warn ("Service \"%s\" should have been invalid\n", invalid_base_services[i]);
03686           _dbus_assert_not_reached ("valid base service");
03687         }
03688       
03689       ++i;
03690     }
03691 
03692 
03693   /* Error name validation (currently identical to interfaces)
03694    */
03695   i = 0;
03696   while (i < (int) _DBUS_N_ELEMENTS (valid_interfaces))
03697     {
03698       _dbus_string_init_const (&str, valid_interfaces[i]);
03699 
03700       if (!_dbus_string_validate_error_name (&str, 0,
03701                                              _dbus_string_get_length (&str)))
03702         {
03703           _dbus_warn ("Error name \"%s\" should have been valid\n", valid_interfaces[i]);
03704           _dbus_assert_not_reached ("invalid error name");
03705         }
03706       
03707       ++i;
03708     }
03709 
03710   i = 0;
03711   while (i < (int) _DBUS_N_ELEMENTS (invalid_interfaces))
03712     {
03713       if (invalid_interfaces[i][0] != ':')
03714         {
03715           _dbus_string_init_const (&str, invalid_interfaces[i]);
03716           
03717           if (_dbus_string_validate_error_name (&str, 0,
03718                                                 _dbus_string_get_length (&str)))
03719             {
03720               _dbus_warn ("Error name \"%s\" should have been invalid\n", invalid_interfaces[i]);
03721               _dbus_assert_not_reached ("valid error name");
03722             }
03723         }
03724       
03725       ++i;
03726     }
03727   
03728   /* Member validation */
03729   i = 0;
03730   while (i < (int) _DBUS_N_ELEMENTS (valid_members))
03731     {
03732       _dbus_string_init_const (&str, valid_members[i]);
03733 
03734       if (!_dbus_string_validate_member (&str, 0,
03735                                          _dbus_string_get_length (&str)))
03736         {
03737           _dbus_warn ("Member \"%s\" should have been valid\n", valid_members[i]);
03738           _dbus_assert_not_reached ("invalid member");
03739         }
03740       
03741       ++i;
03742     }
03743 
03744   i = 0;
03745   while (i < (int) _DBUS_N_ELEMENTS (invalid_members))
03746     {
03747       _dbus_string_init_const (&str, invalid_members[i]);
03748       
03749       if (_dbus_string_validate_member (&str, 0,
03750                                         _dbus_string_get_length (&str)))
03751         {
03752           _dbus_warn ("Member \"%s\" should have been invalid\n", invalid_members[i]);
03753           _dbus_assert_not_reached ("valid member");
03754         }
03755       
03756       ++i;
03757     }
03758 
03759   /* Validate claimed length longer than real length */
03760   _dbus_string_init_const (&str, "abc.efg");
03761   if (_dbus_string_validate_service (&str, 0, 8))
03762     _dbus_assert_not_reached ("validated too-long string");
03763   if (_dbus_string_validate_interface (&str, 0, 8))
03764     _dbus_assert_not_reached ("validated too-long string");
03765   if (_dbus_string_validate_error_name (&str, 0, 8))
03766     _dbus_assert_not_reached ("validated too-long string");
03767 
03768   _dbus_string_init_const (&str, "abc");
03769   if (_dbus_string_validate_member (&str, 0, 4))
03770     _dbus_assert_not_reached ("validated too-long string");
03771 
03772   /* Validate string exceeding max name length */
03773   if (!_dbus_string_init (&str))
03774     _dbus_assert_not_reached ("no memory");
03775 
03776   while (_dbus_string_get_length (&str) <= DBUS_MAXIMUM_NAME_LENGTH)
03777     if (!_dbus_string_append (&str, "abc.def"))
03778       _dbus_assert_not_reached ("no memory");
03779 
03780   if (_dbus_string_validate_service (&str, 0, _dbus_string_get_length (&str)))
03781     _dbus_assert_not_reached ("validated overmax string");
03782   if (_dbus_string_validate_interface (&str, 0, _dbus_string_get_length (&str)))
03783     _dbus_assert_not_reached ("validated overmax string");
03784   if (_dbus_string_validate_error_name (&str, 0, _dbus_string_get_length (&str)))
03785     _dbus_assert_not_reached ("validated overmax string");
03786 
03787   /* overlong member */
03788   _dbus_string_set_length (&str, 0);
03789   while (_dbus_string_get_length (&str) <= DBUS_MAXIMUM_NAME_LENGTH)
03790     if (!_dbus_string_append (&str, "abc"))
03791       _dbus_assert_not_reached ("no memory");  
03792 
03793   if (_dbus_string_validate_member (&str, 0, _dbus_string_get_length (&str)))
03794     _dbus_assert_not_reached ("validated overmax string");
03795 
03796   /* overlong base service */
03797   _dbus_string_set_length (&str, 0);
03798   _dbus_string_append (&str, ":");
03799   while (_dbus_string_get_length (&str) <= DBUS_MAXIMUM_NAME_LENGTH)
03800     if (!_dbus_string_append (&str, "abc"))
03801       _dbus_assert_not_reached ("no memory");  
03802 
03803   if (_dbus_string_validate_service (&str, 0, _dbus_string_get_length (&str)))
03804     _dbus_assert_not_reached ("validated overmax string");
03805   
03806   _dbus_string_free (&str);
03807   
03808   return TRUE;
03809 }
03810 
03811 #endif /* DBUS_BUILD_TESTS */

Generated on Sat Sep 25 19:17:13 2004 for D-BUS by  doxygen 1.3.8-20040913