Main Page   Modules   Data Structures   File List   Data Fields   Related Pages  

dbus-string.c

00001 /* -*- mode: C; c-file-style: "gnu" -*- */
00002 /* dbus-string.c String utility class (internal to D-BUS implementation)
00003  * 
00004  * Copyright (C) 2002, 2003 Red Hat, Inc.
00005  *
00006  * Licensed under the Academic Free License version 1.2
00007  * 
00008  * This program is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * This program is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  * 
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program; if not, write to the Free Software
00020  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021  *
00022  */
00023 
00024 #include "dbus-internals.h"
00025 #include "dbus-string.h"
00026 /* we allow a system header here, for speed/convenience */
00027 #include <string.h>
00028 #include "dbus-marshal.h"
00029 #define DBUS_CAN_USE_DBUS_STRING_PRIVATE 1
00030 #include "dbus-string-private.h"
00031 #include "dbus-protocol.h"
00032 
00075 #define ALLOCATION_PADDING 8
00076 
00081 #define MAX_MAX_LENGTH (_DBUS_INT_MAX - ALLOCATION_PADDING)
00082 
00088 #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)
00089 
00096 #define DBUS_STRING_PREAMBLE(str) DBusRealString *real = (DBusRealString*) str; \
00097   DBUS_GENERIC_STRING_PREAMBLE (real);                                          \
00098   _dbus_assert (!(real)->constant);                                             \
00099   _dbus_assert (!(real)->locked)
00100 
00108 #define DBUS_LOCKED_STRING_PREAMBLE(str) DBusRealString *real = (DBusRealString*) str; \
00109   DBUS_GENERIC_STRING_PREAMBLE (real);                                                 \
00110   _dbus_assert (!(real)->constant)
00111 
00117 #define DBUS_CONST_STRING_PREAMBLE(str) const DBusRealString *real = (DBusRealString*) str; \
00118   DBUS_GENERIC_STRING_PREAMBLE (real)
00119 
00127 static void
00128 fixup_alignment (DBusRealString *real)
00129 {
00130   char *aligned;
00131   char *real_block;
00132   unsigned int old_align_offset;
00133 
00134   /* we have to have extra space in real->allocated for the align offset and nul byte */
00135   _dbus_assert (real->len <= real->allocated - ALLOCATION_PADDING);
00136   
00137   old_align_offset = real->align_offset;
00138   real_block = real->str - old_align_offset;
00139   
00140   aligned = _DBUS_ALIGN_ADDRESS (real_block, 8);
00141 
00142   real->align_offset = aligned - real_block;
00143   real->str = aligned;
00144   
00145   if (old_align_offset != real->align_offset)
00146     {
00147       /* Here comes the suck */
00148       memmove (real_block + real->align_offset,
00149                real_block + old_align_offset,
00150                real->len + 1);
00151     }
00152 
00153   _dbus_assert (real->align_offset < 8);
00154   _dbus_assert (_DBUS_ALIGN_ADDRESS (real->str, 8) == real->str);
00155 }
00156 
00157 static void
00158 undo_alignment (DBusRealString *real)
00159 {
00160   if (real->align_offset != 0)
00161     {
00162       memmove (real->str - real->align_offset,
00163                real->str,
00164                real->len + 1);
00165 
00166       real->str = real->str - real->align_offset;
00167       real->align_offset = 0;
00168     }
00169 }
00170 
00180 dbus_bool_t
00181 _dbus_string_init_preallocated (DBusString *str,
00182                                 int         allocate_size)
00183 {
00184   DBusRealString *real;
00185   
00186   _dbus_assert (str != NULL);
00187 
00188   _dbus_assert (sizeof (DBusString) == sizeof (DBusRealString));
00189   
00190   real = (DBusRealString*) str;
00191 
00192   /* It's very important not to touch anything
00193    * other than real->str if we're going to fail,
00194    * since we also use this function to reset
00195    * an existing string, e.g. in _dbus_string_steal_data()
00196    */
00197   
00198   real->str = dbus_malloc (ALLOCATION_PADDING + allocate_size);
00199   if (real->str == NULL)
00200     return FALSE;  
00201   
00202   real->allocated = ALLOCATION_PADDING + allocate_size;
00203   real->len = 0;
00204   real->str[real->len] = '\0';
00205   
00206   real->max_length = MAX_MAX_LENGTH;
00207   real->constant = FALSE;
00208   real->locked = FALSE;
00209   real->invalid = FALSE;
00210   real->align_offset = 0;
00211   
00212   fixup_alignment (real);
00213   
00214   return TRUE;
00215 }
00216 
00224 dbus_bool_t
00225 _dbus_string_init (DBusString *str)
00226 {
00227   return _dbus_string_init_preallocated (str, 0);
00228 }
00229 
00230 /* The max length thing is sort of a historical artifact
00231  * from a feature that turned out to be dumb; perhaps
00232  * we should purge it entirely. The problem with
00233  * the feature is that it looks like memory allocation
00234  * failure, but is not a transient or resolvable failure.
00235  */
00236 static void
00237 set_max_length (DBusString *str,
00238                 int         max_length)
00239 {
00240   DBusRealString *real;
00241   
00242   real = (DBusRealString*) str;
00243 
00244   real->max_length = max_length;
00245 }
00246 
00256 void
00257 _dbus_string_init_const (DBusString *str,
00258                          const char *value)
00259 {
00260   _dbus_assert (value != NULL);
00261   
00262   _dbus_string_init_const_len (str, value,
00263                                strlen (value));
00264 }
00265 
00276 void
00277 _dbus_string_init_const_len (DBusString *str,
00278                              const char *value,
00279                              int         len)
00280 {
00281   DBusRealString *real;
00282   
00283   _dbus_assert (str != NULL);
00284   _dbus_assert (value != NULL);
00285   _dbus_assert (len <= MAX_MAX_LENGTH);
00286   _dbus_assert (len >= 0);
00287   
00288   real = (DBusRealString*) str;
00289   
00290   real->str = (char*) value;
00291   real->len = len;
00292   real->allocated = real->len + ALLOCATION_PADDING; /* a lie, just to avoid special-case assertions... */
00293   real->max_length = real->len + 1;
00294   real->constant = TRUE;
00295   real->invalid = FALSE;
00296 
00297   /* We don't require const strings to be 8-byte aligned as the
00298    * memory is coming from elsewhere.
00299    */
00300 }
00301 
00307 void
00308 _dbus_string_free (DBusString *str)
00309 {
00310   DBusRealString *real = (DBusRealString*) str;
00311   DBUS_GENERIC_STRING_PREAMBLE (real);
00312   
00313   if (real->constant)
00314     return;
00315   dbus_free (real->str - real->align_offset);
00316 
00317   real->invalid = TRUE;
00318 }
00319 
00320 #ifdef DBUS_BUILD_TESTS
00321 /* Not using this feature at the moment,
00322  * so marked DBUS_BUILD_TESTS-only
00323  */
00333 void
00334 _dbus_string_lock (DBusString *str)
00335 {  
00336   DBUS_LOCKED_STRING_PREAMBLE (str); /* can lock multiple times */
00337 
00338   real->locked = TRUE;
00339 
00340   /* Try to realloc to avoid excess memory usage, since
00341    * we know we won't change the string further
00342    */
00343 #define MAX_WASTE 48
00344   if (real->allocated - MAX_WASTE > real->len)
00345     {
00346       char *new_str;
00347       int new_allocated;
00348 
00349       new_allocated = real->len + ALLOCATION_PADDING;
00350 
00351       new_str = dbus_realloc (real->str - real->align_offset,
00352                               new_allocated);
00353       if (new_str != NULL)
00354         {
00355           real->str = new_str + real->align_offset;
00356           real->allocated = new_allocated;
00357           fixup_alignment (real);
00358         }
00359     }
00360 }
00361 #endif /* DBUS_BUILD_TESTS */
00362 
00363 static dbus_bool_t
00364 reallocate_for_length (DBusRealString *real,
00365                        int             new_length)
00366 {
00367   int new_allocated;
00368   char *new_str;
00369 
00370   /* at least double our old allocation to avoid O(n), avoiding
00371    * overflow
00372    */
00373   if (real->allocated > (MAX_MAX_LENGTH + ALLOCATION_PADDING) / 2)
00374     new_allocated = MAX_MAX_LENGTH + ALLOCATION_PADDING;
00375   else
00376     new_allocated = real->allocated * 2;
00377 
00378   /* if you change the code just above here, run the tests without
00379    * the following before you commit
00380    */
00381 #ifdef DBUS_BUILD_TESTS
00382   new_allocated = 0; /* ensure a realloc every time so that we go
00383                       * through all malloc failure codepaths
00384                       */
00385 #endif
00386       
00387   /* But be sure we always alloc at least space for the new length */
00388   new_allocated = MAX (new_allocated, new_length + ALLOCATION_PADDING);
00389 
00390   _dbus_assert (new_allocated >= real->allocated); /* code relies on this */
00391   new_str = dbus_realloc (real->str - real->align_offset, new_allocated);
00392   if (new_str == NULL)
00393     return FALSE;
00394 
00395   real->str = new_str + real->align_offset;
00396   real->allocated = new_allocated;
00397   fixup_alignment (real);
00398 
00399   return TRUE;
00400 }
00401 
00402 static dbus_bool_t
00403 set_length (DBusRealString *real,
00404             int             new_length)
00405 {
00406   /* Note, we are setting the length not including nul termination */
00407 
00408   /* exceeding max length is the same as failure to allocate memory */
00409   if (new_length > real->max_length)
00410     return FALSE;
00411   else if (new_length > (real->allocated - ALLOCATION_PADDING) &&
00412            !reallocate_for_length (real, new_length))
00413     return FALSE;
00414   else
00415     {
00416       real->len = new_length;
00417       real->str[real->len] = '\0';
00418       return TRUE;
00419     }
00420 }
00421 
00422 static dbus_bool_t
00423 open_gap (int             len,
00424           DBusRealString *dest,
00425           int             insert_at)
00426 {
00427   if (len == 0)
00428     return TRUE;
00429 
00430   if (len > dest->max_length - dest->len)
00431     return FALSE; /* detected overflow of dest->len + len below */
00432   
00433   if (!set_length (dest, dest->len + len))
00434     return FALSE;
00435 
00436   memmove (dest->str + insert_at + len, 
00437            dest->str + insert_at,
00438            dest->len - len - insert_at);
00439 
00440   return TRUE;
00441 }
00442 
00454 char*
00455 _dbus_string_get_data (DBusString *str)
00456 {
00457   DBUS_STRING_PREAMBLE (str);
00458   
00459   return real->str;
00460 }
00461 
00468 const char*
00469 _dbus_string_get_const_data (const DBusString  *str)
00470 {
00471   DBUS_CONST_STRING_PREAMBLE (str);
00472   
00473   return real->str;
00474 }
00475 
00489 char*
00490 _dbus_string_get_data_len (DBusString *str,
00491                            int         start,
00492                            int         len)
00493 {
00494   DBUS_STRING_PREAMBLE (str);
00495   _dbus_assert (start >= 0);
00496   _dbus_assert (len >= 0);
00497   _dbus_assert (start <= real->len);
00498   _dbus_assert (len <= real->len - start);
00499   
00500   return real->str + start;
00501 }
00502 
00511 const char*
00512 _dbus_string_get_const_data_len (const DBusString  *str,
00513                                  int                start,
00514                                  int                len)
00515 {
00516   DBUS_CONST_STRING_PREAMBLE (str);
00517   _dbus_assert (start >= 0);
00518   _dbus_assert (len >= 0);
00519   _dbus_assert (start <= real->len);
00520   _dbus_assert (len <= real->len - start);
00521   
00522   return real->str + start;
00523 }
00524 
00532 void
00533 _dbus_string_set_byte (DBusString    *str,
00534                        int            i,
00535                        unsigned char  byte)
00536 {
00537   DBUS_STRING_PREAMBLE (str);
00538   _dbus_assert (i < real->len);
00539   _dbus_assert (i >= 0);
00540   
00541   real->str[i] = byte;
00542 }
00543 
00551 unsigned char
00552 _dbus_string_get_byte (const DBusString  *str,
00553                        int                start)
00554 {
00555   DBUS_CONST_STRING_PREAMBLE (str);
00556   _dbus_assert (start < real->len);
00557   _dbus_assert (start >= 0);
00558   
00559   return real->str[start];
00560 }
00561 
00570 dbus_bool_t
00571 _dbus_string_insert_byte (DBusString   *str,
00572                           int           i,
00573                           unsigned char byte)
00574 {
00575   DBUS_STRING_PREAMBLE (str);
00576   _dbus_assert (i <= real->len);
00577   _dbus_assert (i >= 0);
00578   
00579   if (!open_gap (1, real, i))
00580     return FALSE;
00581   
00582   real->str[i] = byte;
00583 
00584   return TRUE;
00585 }
00586 
00597 dbus_bool_t
00598 _dbus_string_steal_data (DBusString        *str,
00599                          char             **data_return)
00600 {
00601   int old_max_length;
00602   DBUS_STRING_PREAMBLE (str);
00603   _dbus_assert (data_return != NULL);
00604 
00605   undo_alignment (real);
00606   
00607   *data_return = real->str;
00608 
00609   old_max_length = real->max_length;
00610   
00611   /* reset the string */
00612   if (!_dbus_string_init (str))
00613     {
00614       /* hrm, put it back then */
00615       real->str = *data_return;
00616       *data_return = NULL;
00617       fixup_alignment (real);
00618       return FALSE;
00619     }
00620 
00621   real->max_length = old_max_length;
00622 
00623   return TRUE;
00624 }
00625 
00641 dbus_bool_t
00642 _dbus_string_steal_data_len (DBusString        *str,
00643                              char             **data_return,
00644                              int                start,
00645                              int                len)
00646 {
00647   DBusString dest;
00648   DBUS_STRING_PREAMBLE (str);
00649   _dbus_assert (data_return != NULL);
00650   _dbus_assert (start >= 0);
00651   _dbus_assert (len >= 0);
00652   _dbus_assert (start <= real->len);
00653   _dbus_assert (len <= real->len - start);
00654 
00655   if (!_dbus_string_init (&dest))
00656     return FALSE;
00657 
00658   set_max_length (&dest, real->max_length);
00659   
00660   if (!_dbus_string_move_len (str, start, len, &dest, 0))
00661     {
00662       _dbus_string_free (&dest);
00663       return FALSE;
00664     }
00665 
00666   _dbus_warn ("Broken code in _dbus_string_steal_data_len(), see @todo, FIXME\n");
00667   if (!_dbus_string_steal_data (&dest, data_return))
00668     {
00669       _dbus_string_free (&dest);
00670       return FALSE;
00671     }
00672 
00673   _dbus_string_free (&dest);
00674   return TRUE;
00675 }
00676 
00677 
00685 dbus_bool_t
00686 _dbus_string_copy_data (const DBusString  *str,
00687                         char             **data_return)
00688 {
00689   DBUS_CONST_STRING_PREAMBLE (str);
00690   _dbus_assert (data_return != NULL);
00691   
00692   *data_return = dbus_malloc (real->len + 1);
00693   if (*data_return == NULL)
00694     return FALSE;
00695 
00696   memcpy (*data_return, real->str, real->len + 1);
00697 
00698   return TRUE;
00699 }
00700 
00710 dbus_bool_t
00711 _dbus_string_copy_data_len (const DBusString  *str,
00712                             char             **data_return,
00713                             int                start,
00714                             int                len)
00715 {
00716   DBusString dest;
00717 
00718   DBUS_CONST_STRING_PREAMBLE (str);
00719   _dbus_assert (data_return != NULL);
00720   _dbus_assert (start >= 0);
00721   _dbus_assert (len >= 0);
00722   _dbus_assert (start <= real->len);
00723   _dbus_assert (len <= real->len - start);
00724 
00725   if (!_dbus_string_init (&dest))
00726     return FALSE;
00727 
00728   set_max_length (&dest, real->max_length);
00729 
00730   if (!_dbus_string_copy_len (str, start, len, &dest, 0))
00731     {
00732       _dbus_string_free (&dest);
00733       return FALSE;
00734     }
00735 
00736   if (!_dbus_string_steal_data (&dest, data_return))
00737     {
00738       _dbus_string_free (&dest);
00739       return FALSE;
00740     }
00741 
00742   _dbus_string_free (&dest);
00743   return TRUE;
00744 }
00745 
00751 int
00752 _dbus_string_get_length (const DBusString  *str)
00753 {
00754   DBUS_CONST_STRING_PREAMBLE (str);
00755   
00756   return real->len;
00757 }
00758 
00771 dbus_bool_t
00772 _dbus_string_lengthen (DBusString *str,
00773                        int         additional_length)
00774 {
00775   DBUS_STRING_PREAMBLE (str);  
00776   _dbus_assert (additional_length >= 0);
00777 
00778   if (additional_length > real->max_length - real->len)
00779     return FALSE; /* would overflow */
00780   
00781   return set_length (real,
00782                      real->len + additional_length);
00783 }
00784 
00791 void
00792 _dbus_string_shorten (DBusString *str,
00793                       int         length_to_remove)
00794 {
00795   DBUS_STRING_PREAMBLE (str);
00796   _dbus_assert (length_to_remove >= 0);
00797   _dbus_assert (length_to_remove <= real->len);
00798 
00799   set_length (real,
00800               real->len - length_to_remove);
00801 }
00802 
00813 dbus_bool_t
00814 _dbus_string_set_length (DBusString *str,
00815                          int         length)
00816 {
00817   DBUS_STRING_PREAMBLE (str);
00818   _dbus_assert (length >= 0);
00819 
00820   return set_length (real, length);
00821 }
00822 
00823 static dbus_bool_t
00824 align_length_then_lengthen (DBusString *str,
00825                             int         alignment,
00826                             int         then_lengthen_by)
00827 {
00828   unsigned long new_len; /* ulong to avoid _DBUS_ALIGN_VALUE overflow */
00829   int delta;
00830   DBUS_STRING_PREAMBLE (str);
00831   _dbus_assert (alignment >= 1);
00832   _dbus_assert (alignment <= 8); /* it has to be a bug if > 8 */
00833 
00834   new_len = _DBUS_ALIGN_VALUE (real->len, alignment);
00835   if (new_len > (unsigned long) real->max_length - then_lengthen_by)
00836     return FALSE;
00837   new_len += then_lengthen_by;
00838   
00839   delta = new_len - real->len;
00840   _dbus_assert (delta >= 0);
00841 
00842   if (delta == 0)
00843     return TRUE;
00844 
00845   if (!set_length (real, new_len))
00846     return FALSE;
00847 
00848   /* delta == padding + then_lengthen_by
00849    * new_len == old_len + padding + then_lengthen_by
00850    */
00851   if (then_lengthen_by < delta)
00852     {
00853       unsigned int i;
00854       i = new_len - delta;
00855       while (i < (new_len - then_lengthen_by))
00856         {
00857           real->str[i] = '\0';
00858           ++i;
00859         }
00860     }
00861       
00862   return TRUE;
00863 }
00864 
00873 dbus_bool_t
00874 _dbus_string_align_length (DBusString *str,
00875                            int         alignment)
00876 {
00877   return align_length_then_lengthen (str, alignment, 0);
00878 }
00879 
00880 static dbus_bool_t
00881 append (DBusRealString *real,
00882         const char     *buffer,
00883         int             buffer_len)
00884 {
00885   if (buffer_len == 0)
00886     return TRUE;
00887 
00888   if (!_dbus_string_lengthen ((DBusString*)real, buffer_len))
00889     return FALSE;
00890 
00891   memcpy (real->str + (real->len - buffer_len),
00892           buffer,
00893           buffer_len);
00894 
00895   return TRUE;
00896 }
00897 
00905 dbus_bool_t
00906 _dbus_string_append (DBusString *str,
00907                      const char *buffer)
00908 {
00909   unsigned long buffer_len;
00910   
00911   DBUS_STRING_PREAMBLE (str);
00912   _dbus_assert (buffer != NULL);
00913   
00914   buffer_len = strlen (buffer);
00915   if (buffer_len > (unsigned long) real->max_length)
00916     return FALSE;
00917   
00918   return append (real, buffer, buffer_len);
00919 }
00920 
00929 dbus_bool_t
00930 _dbus_string_append_4_aligned (DBusString         *str,
00931                                const unsigned char octets[4])
00932 {
00933   dbus_uint32_t *p;
00934   DBUS_STRING_PREAMBLE (str);
00935   
00936   if (!align_length_then_lengthen (str, 4, 4))
00937     return FALSE;
00938 
00939   p = (dbus_uint32_t*) (real->str + (real->len - 4));
00940   *p = *((dbus_uint32_t*)octets);
00941 
00942   return TRUE;
00943 }
00944 
00953 dbus_bool_t
00954 _dbus_string_append_8_aligned (DBusString         *str,
00955                                const unsigned char octets[8])
00956 {
00957 #ifdef DBUS_HAVE_INT64
00958   dbus_uint64_t *p;
00959   DBUS_STRING_PREAMBLE (str);
00960   
00961   if (!align_length_then_lengthen (str, 8, 8))
00962     return FALSE;
00963 
00964   p = (dbus_uint64_t*) (real->str + (real->len - 8));
00965   *p = *((dbus_uint64_t*)octets);
00966 #else
00967   char *p;
00968   DBUS_STRING_PREAMBLE (str);
00969   
00970   if (!align_length_then_lengthen (str, 8, 8))
00971     return FALSE;
00972 
00973   p = real->str + (real->len - 8);
00974   
00975   *p++ = octets[0];
00976   *p++ = octets[1];
00977   *p++ = octets[2];
00978   *p++ = octets[3];
00979   *p++ = octets[4];
00980   *p++ = octets[5];
00981   *p++ = octets[6];
00982   *p++ = octets[7];
00983   _dbus_assert (p == (real->str + real->len));
00984 #endif
00985 
00986   return TRUE;
00987 }
00988 
00997 dbus_bool_t
00998 _dbus_string_append_len (DBusString *str,
00999                          const char *buffer,
01000                          int         len)
01001 {
01002   DBUS_STRING_PREAMBLE (str);
01003   _dbus_assert (buffer != NULL);
01004   _dbus_assert (len >= 0);
01005 
01006   return append (real, buffer, len);
01007 }
01008 
01017 dbus_bool_t
01018 _dbus_string_append_byte (DBusString    *str,
01019                           unsigned char  byte)
01020 {
01021   DBUS_STRING_PREAMBLE (str);
01022 
01023   if (!set_length (real, real->len + 1))
01024     return FALSE;
01025 
01026   real->str[real->len-1] = byte;
01027 
01028   return TRUE;
01029 }
01030 
01038 dbus_bool_t
01039 _dbus_string_append_unichar (DBusString    *str,
01040                              dbus_unichar_t ch)
01041 {
01042   int len;
01043   int first;
01044   int i;
01045   char *out;
01046   
01047   DBUS_STRING_PREAMBLE (str);
01048 
01049   /* this code is from GLib but is pretty standard I think */
01050   
01051   len = 0;
01052   
01053   if (ch < 0x80)
01054     {
01055       first = 0;
01056       len = 1;
01057     }
01058   else if (ch < 0x800)
01059     {
01060       first = 0xc0;
01061       len = 2;
01062     }
01063   else if (ch < 0x10000)
01064     {
01065       first = 0xe0;
01066       len = 3;
01067     }
01068    else if (ch < 0x200000)
01069     {
01070       first = 0xf0;
01071       len = 4;
01072     }
01073   else if (ch < 0x4000000)
01074     {
01075       first = 0xf8;
01076       len = 5;
01077     }
01078   else
01079     {
01080       first = 0xfc;
01081       len = 6;
01082     }
01083 
01084   if (len > (real->max_length - real->len))
01085     return FALSE; /* real->len + len would overflow */
01086   
01087   if (!set_length (real, real->len + len))
01088     return FALSE;
01089 
01090   out = real->str + (real->len - len);
01091   
01092   for (i = len - 1; i > 0; --i)
01093     {
01094       out[i] = (ch & 0x3f) | 0x80;
01095       ch >>= 6;
01096     }
01097   out[0] = ch | first;
01098 
01099   return TRUE;
01100 }
01101 
01102 static void
01103 delete (DBusRealString *real,
01104         int             start,
01105         int             len)
01106 {
01107   if (len == 0)
01108     return;
01109   
01110   memmove (real->str + start, real->str + start + len, real->len - (start + len));
01111   real->len -= len;
01112   real->str[real->len] = '\0';
01113 }
01114 
01124 void
01125 _dbus_string_delete (DBusString       *str,
01126                      int               start,
01127                      int               len)
01128 {
01129   DBUS_STRING_PREAMBLE (str);
01130   _dbus_assert (start >= 0);
01131   _dbus_assert (len >= 0);
01132   _dbus_assert (start <= real->len);
01133   _dbus_assert (len <= real->len - start);
01134   
01135   delete (real, start, len);
01136 }
01137 
01138 static dbus_bool_t
01139 copy (DBusRealString *source,
01140       int             start,
01141       int             len,
01142       DBusRealString *dest,
01143       int             insert_at)
01144 {
01145   if (len == 0)
01146     return TRUE;
01147 
01148   if (!open_gap (len, dest, insert_at))
01149     return FALSE;
01150   
01151   memcpy (dest->str + insert_at,
01152           source->str + start,
01153           len);
01154 
01155   return TRUE;
01156 }
01157 
01167 #define DBUS_STRING_COPY_PREAMBLE(source, start, dest, insert_at)       \
01168   DBusRealString *real_source = (DBusRealString*) source;               \
01169   DBusRealString *real_dest = (DBusRealString*) dest;                   \
01170   _dbus_assert ((source) != (dest));                                    \
01171   DBUS_GENERIC_STRING_PREAMBLE (real_source);                           \
01172   DBUS_GENERIC_STRING_PREAMBLE (real_dest);                             \
01173   _dbus_assert (!real_dest->constant);                                  \
01174   _dbus_assert (!real_dest->locked);                                    \
01175   _dbus_assert ((start) >= 0);                                          \
01176   _dbus_assert ((start) <= real_source->len);                           \
01177   _dbus_assert ((insert_at) >= 0);                                      \
01178   _dbus_assert ((insert_at) <= real_dest->len)
01179 
01190 dbus_bool_t
01191 _dbus_string_move (DBusString       *source,
01192                    int               start,
01193                    DBusString       *dest,
01194                    int               insert_at)
01195 {
01196   DBusRealString *real_source = (DBusRealString*) source;
01197   _dbus_assert (start <= real_source->len);
01198   
01199   return _dbus_string_move_len (source, start,
01200                                 real_source->len - start,
01201                                 dest, insert_at);
01202 }
01203 
01214 dbus_bool_t
01215 _dbus_string_copy (const DBusString *source,
01216                    int               start,
01217                    DBusString       *dest,
01218                    int               insert_at)
01219 {
01220   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
01221 
01222   return copy (real_source, start,
01223                real_source->len - start,
01224                real_dest,
01225                insert_at);
01226 }
01227 
01242 dbus_bool_t
01243 _dbus_string_move_len (DBusString       *source,
01244                        int               start,
01245                        int               len,
01246                        DBusString       *dest,
01247                        int               insert_at)
01248 
01249 {
01250   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
01251   _dbus_assert (len >= 0);
01252   _dbus_assert ((start + len) <= real_source->len);
01253 
01254 
01255   if (len == 0)
01256     {
01257       return TRUE;
01258     }
01259   else if (start == 0 &&
01260            len == real_source->len &&
01261            real_dest->len == 0)
01262     {
01263       /* Short-circuit moving an entire existing string to an empty string
01264        * by just swapping the buffers.
01265        */
01266       /* we assume ->constant doesn't matter as you can't have
01267        * a constant string involved in a move.
01268        */
01269 #define ASSIGN_DATA(a, b) do {                  \
01270         (a)->str = (b)->str;                    \
01271         (a)->len = (b)->len;                    \
01272         (a)->allocated = (b)->allocated;        \
01273         (a)->align_offset = (b)->align_offset;  \
01274       } while (0)
01275       
01276       DBusRealString tmp;
01277 
01278       ASSIGN_DATA (&tmp, real_source);
01279       ASSIGN_DATA (real_source, real_dest);
01280       ASSIGN_DATA (real_dest, &tmp);
01281 
01282       return TRUE;
01283     }
01284   else
01285     {
01286       if (!copy (real_source, start, len,
01287                  real_dest,
01288                  insert_at))
01289         return FALSE;
01290       
01291       delete (real_source, start,
01292               len);
01293       
01294       return TRUE;
01295     }
01296 }
01297 
01309 dbus_bool_t
01310 _dbus_string_copy_len (const DBusString *source,
01311                        int               start,
01312                        int               len,
01313                        DBusString       *dest,
01314                        int               insert_at)
01315 {
01316   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
01317   _dbus_assert (len >= 0);
01318   _dbus_assert (start <= real_source->len);
01319   _dbus_assert (len <= real_source->len - start);
01320   
01321   return copy (real_source, start, len,
01322                real_dest,
01323                insert_at);
01324 }
01325 
01347 dbus_bool_t
01348 _dbus_string_replace_len (const DBusString *source,
01349                           int               start,
01350                           int               len,
01351                           DBusString       *dest,
01352                           int               replace_at,
01353                           int               replace_len)
01354 {
01355   DBUS_STRING_COPY_PREAMBLE (source, start, dest, replace_at);
01356   _dbus_assert (len >= 0);
01357   _dbus_assert (start <= real_source->len);
01358   _dbus_assert (len <= real_source->len - start);
01359   _dbus_assert (replace_at >= 0);
01360   _dbus_assert (replace_at <= real_dest->len);
01361   _dbus_assert (replace_len <= real_dest->len - replace_at);
01362 
01363   if (!copy (real_source, start, len,
01364              real_dest, replace_at))
01365     return FALSE;
01366 
01367   delete (real_dest, replace_at + len, replace_len);
01368 
01369   return TRUE;
01370 }
01371 
01372 /* Unicode macros and utf8_validate() from GLib Owen Taylor, Havoc
01373  * Pennington, and Tom Tromey are the authors and authorized relicense.
01374  */
01375 
01381 #define UTF8_COMPUTE(Char, Mask, Len)                                         \
01382   if (Char < 128)                                                             \
01383     {                                                                         \
01384       Len = 1;                                                                \
01385       Mask = 0x7f;                                                            \
01386     }                                                                         \
01387   else if ((Char & 0xe0) == 0xc0)                                             \
01388     {                                                                         \
01389       Len = 2;                                                                \
01390       Mask = 0x1f;                                                            \
01391     }                                                                         \
01392   else if ((Char & 0xf0) == 0xe0)                                             \
01393     {                                                                         \
01394       Len = 3;                                                                \
01395       Mask = 0x0f;                                                            \
01396     }                                                                         \
01397   else if ((Char & 0xf8) == 0xf0)                                             \
01398     {                                                                         \
01399       Len = 4;                                                                \
01400       Mask = 0x07;                                                            \
01401     }                                                                         \
01402   else if ((Char & 0xfc) == 0xf8)                                             \
01403     {                                                                         \
01404       Len = 5;                                                                \
01405       Mask = 0x03;                                                            \
01406     }                                                                         \
01407   else if ((Char & 0xfe) == 0xfc)                                             \
01408     {                                                                         \
01409       Len = 6;                                                                \
01410       Mask = 0x01;                                                            \
01411     }                                                                         \
01412   else                                                                        \
01413     Len = -1;
01414 
01419 #define UTF8_LENGTH(Char)              \
01420   ((Char) < 0x80 ? 1 :                 \
01421    ((Char) < 0x800 ? 2 :               \
01422     ((Char) < 0x10000 ? 3 :            \
01423      ((Char) < 0x200000 ? 4 :          \
01424       ((Char) < 0x4000000 ? 5 : 6)))))
01425    
01435 #define UTF8_GET(Result, Chars, Count, Mask, Len)                             \
01436   (Result) = (Chars)[0] & (Mask);                                             \
01437   for ((Count) = 1; (Count) < (Len); ++(Count))                               \
01438     {                                                                         \
01439       if (((Chars)[(Count)] & 0xc0) != 0x80)                                  \
01440         {                                                                     \
01441           (Result) = -1;                                                      \
01442           break;                                                              \
01443         }                                                                     \
01444       (Result) <<= 6;                                                         \
01445       (Result) |= ((Chars)[(Count)] & 0x3f);                                  \
01446     }
01447 
01453 #define UNICODE_VALID(Char)                   \
01454     ((Char) < 0x110000 &&                     \
01455      (((Char) & 0xFFFFF800) != 0xD800) &&     \
01456      ((Char) < 0xFDD0 || (Char) > 0xFDEF) &&  \
01457      ((Char) & 0xFFFF) != 0xFFFF)
01458 
01469 void
01470 _dbus_string_get_unichar (const DBusString *str,
01471                           int               start,
01472                           dbus_unichar_t   *ch_return,
01473                           int              *end_return)
01474 {
01475   int i, mask, len;
01476   dbus_unichar_t result;
01477   unsigned char c;
01478   unsigned char *p;
01479   DBUS_CONST_STRING_PREAMBLE (str);
01480   _dbus_assert (start >= 0);
01481   _dbus_assert (start <= real->len);
01482   
01483   if (ch_return)
01484     *ch_return = 0;
01485   if (end_return)
01486     *end_return = real->len;
01487   
01488   mask = 0;
01489   p = real->str + start;
01490   c = *p;
01491   
01492   UTF8_COMPUTE (c, mask, len);
01493   if (len == -1)
01494     return;
01495   UTF8_GET (result, p, i, mask, len);
01496 
01497   if (result == (dbus_unichar_t)-1)
01498     return;
01499 
01500   if (ch_return)
01501     *ch_return = result;
01502   if (end_return)
01503     *end_return = start + len;
01504 }
01505 
01520 dbus_bool_t
01521 _dbus_string_find (const DBusString *str,
01522                    int               start,
01523                    const char       *substr,
01524                    int              *found)
01525 {
01526   return _dbus_string_find_to (str, start,
01527                                ((const DBusRealString*)str)->len,
01528                                substr, found);
01529 }
01530 
01547 dbus_bool_t
01548 _dbus_string_find_to (const DBusString *str,
01549                       int               start,
01550                       int               end,
01551                       const char       *substr,
01552                       int              *found)
01553 {
01554   int i;
01555   DBUS_CONST_STRING_PREAMBLE (str);
01556   _dbus_assert (substr != NULL);
01557   _dbus_assert (start <= real->len);
01558   _dbus_assert (start >= 0);
01559   _dbus_assert (substr != NULL);
01560   _dbus_assert (end <= real->len);
01561   _dbus_assert (start <= end);
01562 
01563   /* we always "find" an empty string */
01564   if (*substr == '\0')
01565     {
01566       if (found)
01567         *found = start;
01568       return TRUE;
01569     }
01570 
01571   i = start;
01572   while (i < end)
01573     {
01574       if (real->str[i] == substr[0])
01575         {
01576           int j = i + 1;
01577           
01578           while (j < end)
01579             {
01580               if (substr[j - i] == '\0')
01581                 break;
01582               else if (real->str[j] != substr[j - i])
01583                 break;
01584               
01585               ++j;
01586             }
01587 
01588           if (substr[j - i] == '\0')
01589             {
01590               if (found)
01591                 *found = i;
01592               return TRUE;
01593             }
01594         }
01595       
01596       ++i;
01597     }
01598 
01599   if (found)
01600     *found = end;
01601   
01602   return FALSE;  
01603 }
01604 
01615 dbus_bool_t
01616 _dbus_string_find_byte_backward (const DBusString  *str,
01617                                  int                start,
01618                                  unsigned char      byte,
01619                                  int               *found)
01620 {
01621   int i;
01622   DBUS_CONST_STRING_PREAMBLE (str);
01623   _dbus_assert (start <= real->len);
01624   _dbus_assert (start >= 0);
01625   _dbus_assert (found != NULL);
01626 
01627   i = start - 1;
01628   while (i >= 0)
01629     {
01630       if (real->str[i] == byte)
01631         break;
01632       
01633       --i;
01634     }
01635 
01636   if (found)
01637     *found = i;
01638 
01639   return i >= 0;
01640 }
01641 
01652 dbus_bool_t
01653 _dbus_string_find_blank (const DBusString *str,
01654                          int               start,
01655                          int              *found)
01656 {
01657   int i;
01658   DBUS_CONST_STRING_PREAMBLE (str);
01659   _dbus_assert (start <= real->len);
01660   _dbus_assert (start >= 0);
01661   
01662   i = start;
01663   while (i < real->len)
01664     {
01665       if (real->str[i] == ' ' ||
01666           real->str[i] == '\t')
01667         {
01668           if (found)
01669             *found = i;
01670           return TRUE;
01671         }
01672       
01673       ++i;
01674     }
01675 
01676   if (found)
01677     *found = real->len;
01678   
01679   return FALSE;
01680 }
01681 
01690 void
01691 _dbus_string_skip_blank (const DBusString *str,
01692                          int               start,
01693                          int              *end)
01694 {
01695   int i;
01696   DBUS_CONST_STRING_PREAMBLE (str);
01697   _dbus_assert (start <= real->len);
01698   _dbus_assert (start >= 0);
01699   
01700   i = start;
01701   while (i < real->len)
01702     {
01703       if (!(real->str[i] == ' ' ||
01704             real->str[i] == '\t'))
01705         break;
01706       
01707       ++i;
01708     }
01709 
01710   _dbus_assert (i == real->len || !(real->str[i] == ' ' ||
01711                                     real->str[i] == '\t'));
01712   
01713   if (end)
01714     *end = i;
01715 }
01716 
01725 void
01726 _dbus_string_skip_white (const DBusString *str,
01727                          int               start,
01728                          int              *end)
01729 {
01730   int i;
01731   DBUS_CONST_STRING_PREAMBLE (str);
01732   _dbus_assert (start <= real->len);
01733   _dbus_assert (start >= 0);
01734   
01735   i = start;
01736   while (i < real->len)
01737     {
01738       if (!(real->str[i] == ' ' ||
01739             real->str[i] == '\n' ||
01740             real->str[i] == '\r' ||
01741             real->str[i] == '\t'))
01742         break;
01743       
01744       ++i;
01745     }
01746 
01747   _dbus_assert (i == real->len || !(real->str[i] == ' ' ||
01748                                     real->str[i] == '\t'));
01749   
01750   if (end)
01751     *end = i;
01752 }
01753 
01769 dbus_bool_t
01770 _dbus_string_pop_line (DBusString *source,
01771                        DBusString *dest)
01772 {
01773   int eol;
01774   dbus_bool_t have_newline;
01775   
01776   _dbus_string_set_length (dest, 0);
01777   
01778   eol = 0;
01779   if (_dbus_string_find (source, 0, "\n", &eol))
01780     {
01781       have_newline = TRUE;
01782       eol += 1; /* include newline */
01783     }
01784   else
01785     {
01786       eol = _dbus_string_get_length (source);
01787       have_newline = FALSE;
01788     }
01789 
01790   if (eol == 0)
01791     return FALSE; /* eof */
01792   
01793   if (!_dbus_string_move_len (source, 0, eol,
01794                               dest, 0))
01795     {
01796       return FALSE;
01797     }
01798 
01799   /* dump the newline and the \r if we have one */
01800   if (have_newline)
01801     {
01802       dbus_bool_t have_cr;
01803       
01804       _dbus_assert (_dbus_string_get_length (dest) > 0);
01805 
01806       if (_dbus_string_get_length (dest) > 1 &&
01807           _dbus_string_get_byte (dest,
01808                                  _dbus_string_get_length (dest) - 2) == '\r')
01809         have_cr = TRUE;
01810       else
01811         have_cr = FALSE;
01812         
01813       _dbus_string_set_length (dest,
01814                                _dbus_string_get_length (dest) -
01815                                (have_cr ? 2 : 1));
01816     }
01817   
01818   return TRUE;
01819 }
01820 
01827 void
01828 _dbus_string_delete_first_word (DBusString *str)
01829 {
01830   int i;
01831   
01832   if (_dbus_string_find_blank (str, 0, &i))
01833     _dbus_string_skip_blank (str, i, &i);
01834 
01835   _dbus_string_delete (str, 0, i);
01836 }
01837 
01843 void
01844 _dbus_string_delete_leading_blanks (DBusString *str)
01845 {
01846   int i;
01847   
01848   _dbus_string_skip_blank (str, 0, &i);
01849 
01850   if (i > 0)
01851     _dbus_string_delete (str, 0, i);
01852 }
01853 
01863 dbus_bool_t
01864 _dbus_string_equal (const DBusString *a,
01865                     const DBusString *b)
01866 {
01867   const unsigned char *ap;
01868   const unsigned char *bp;
01869   const unsigned char *a_end;
01870   const DBusRealString *real_a = (const DBusRealString*) a;
01871   const DBusRealString *real_b = (const DBusRealString*) b;
01872   DBUS_GENERIC_STRING_PREAMBLE (real_a);
01873   DBUS_GENERIC_STRING_PREAMBLE (real_b);
01874 
01875   if (real_a->len != real_b->len)
01876     return FALSE;
01877 
01878   ap = real_a->str;
01879   bp = real_b->str;
01880   a_end = real_a->str + real_a->len;
01881   while (ap != a_end)
01882     {
01883       if (*ap != *bp)
01884         return FALSE;
01885       
01886       ++ap;
01887       ++bp;
01888     }
01889 
01890   return TRUE;
01891 }
01892 
01905 dbus_bool_t
01906 _dbus_string_equal_len (const DBusString *a,
01907                         const DBusString *b,
01908                         int               len)
01909 {
01910   const unsigned char *ap;
01911   const unsigned char *bp;
01912   const unsigned char *a_end;
01913   const DBusRealString *real_a = (const DBusRealString*) a;
01914   const DBusRealString *real_b = (const DBusRealString*) b;
01915   DBUS_GENERIC_STRING_PREAMBLE (real_a);
01916   DBUS_GENERIC_STRING_PREAMBLE (real_b);
01917 
01918   if (real_a->len != real_b->len &&
01919       (real_a->len < len || real_b->len < len))
01920     return FALSE;
01921 
01922   ap = real_a->str;
01923   bp = real_b->str;
01924   a_end = real_a->str + MIN (real_a->len, len);
01925   while (ap != a_end)
01926     {
01927       if (*ap != *bp)
01928         return FALSE;
01929       
01930       ++ap;
01931       ++bp;
01932     }
01933 
01934   return TRUE;
01935 }
01936 
01944 dbus_bool_t
01945 _dbus_string_equal_c_str (const DBusString *a,
01946                           const char       *c_str)
01947 {
01948   const unsigned char *ap;
01949   const unsigned char *bp;
01950   const unsigned char *a_end;
01951   const DBusRealString *real_a = (const DBusRealString*) a;
01952   DBUS_GENERIC_STRING_PREAMBLE (real_a);
01953   _dbus_assert (c_str != NULL);
01954   
01955   ap = real_a->str;
01956   bp = (const unsigned char*) c_str;
01957   a_end = real_a->str + real_a->len;
01958   while (ap != a_end && *bp)
01959     {
01960       if (*ap != *bp)
01961         return FALSE;
01962       
01963       ++ap;
01964       ++bp;
01965     }
01966 
01967   if (ap != a_end || *bp)
01968     return FALSE;
01969   
01970   return TRUE;
01971 }
01972 
01980 dbus_bool_t
01981 _dbus_string_starts_with_c_str (const DBusString *a,
01982                                 const char       *c_str)
01983 {
01984   const unsigned char *ap;
01985   const unsigned char *bp;
01986   const unsigned char *a_end;
01987   const DBusRealString *real_a = (const DBusRealString*) a;
01988   DBUS_GENERIC_STRING_PREAMBLE (real_a);
01989   _dbus_assert (c_str != NULL);
01990   
01991   ap = real_a->str;
01992   bp = (const unsigned char*) c_str;
01993   a_end = real_a->str + real_a->len;
01994   while (ap != a_end && *bp)
01995     {
01996       if (*ap != *bp)
01997         return FALSE;
01998       
01999       ++ap;
02000       ++bp;
02001     }
02002 
02003   if (*bp == '\0')
02004     return TRUE;
02005   else
02006     return FALSE;
02007 }
02008 
02018 dbus_bool_t
02019 _dbus_string_ends_with_c_str (const DBusString *a,
02020                               const char       *c_str)
02021 {
02022   const unsigned char *ap;
02023   const unsigned char *bp;
02024   const unsigned char *a_end;
02025   unsigned long c_str_len;
02026   const DBusRealString *real_a = (const DBusRealString*) a;
02027   DBUS_GENERIC_STRING_PREAMBLE (real_a);
02028   _dbus_assert (c_str != NULL);
02029   
02030   c_str_len = strlen (c_str);
02031   if (((unsigned long)real_a->len) < c_str_len)
02032     return FALSE;
02033   
02034   ap = real_a->str + (real_a->len - c_str_len);
02035   bp = (const unsigned char*) c_str;
02036   a_end = real_a->str + real_a->len;
02037   while (ap != a_end)
02038     {
02039       if (*ap != *bp)
02040         return FALSE;
02041       
02042       ++ap;
02043       ++bp;
02044     }
02045 
02046   _dbus_assert (*ap == '\0');
02047   _dbus_assert (*bp == '\0');
02048   
02049   return TRUE;
02050 }
02051 
02052 static const signed char base64_table[] = {
02053   /* 0 */ 'A',
02054   /* 1 */ 'B',
02055   /* 2 */ 'C',
02056   /* 3 */ 'D',
02057   /* 4 */ 'E',
02058   /* 5 */ 'F',
02059   /* 6 */ 'G',
02060   /* 7 */ 'H',
02061   /* 8 */ 'I',
02062   /* 9 */ 'J',
02063   /* 10 */ 'K',
02064   /* 11 */ 'L',
02065   /* 12 */ 'M',
02066   /* 13 */ 'N',
02067   /* 14 */ 'O',
02068   /* 15 */ 'P',
02069   /* 16 */ 'Q',
02070   /* 17 */ 'R',
02071   /* 18 */ 'S',
02072   /* 19 */ 'T',
02073   /* 20 */ 'U',
02074   /* 21 */ 'V',
02075   /* 22 */ 'W',
02076   /* 23 */ 'X',
02077   /* 24 */ 'Y',
02078   /* 25 */ 'Z',
02079   /* 26 */ 'a',
02080   /* 27 */ 'b',
02081   /* 28 */ 'c',
02082   /* 29 */ 'd',
02083   /* 30 */ 'e',
02084   /* 31 */ 'f',
02085   /* 32 */ 'g',
02086   /* 33 */ 'h',
02087   /* 34 */ 'i',
02088   /* 35 */ 'j',
02089   /* 36 */ 'k',
02090   /* 37 */ 'l',
02091   /* 38 */ 'm',
02092   /* 39 */ 'n',
02093   /* 40 */ 'o',
02094   /* 41 */ 'p',
02095   /* 42 */ 'q',
02096   /* 43 */ 'r',
02097   /* 44 */ 's',
02098   /* 45 */ 't',
02099   /* 46 */ 'u',
02100   /* 47 */ 'v',
02101   /* 48 */ 'w',
02102   /* 49 */ 'x',
02103   /* 50 */ 'y',
02104   /* 51 */ 'z',
02105   /* 52 */ '0',
02106   /* 53 */ '1',
02107   /* 54 */ '2',
02108   /* 55 */ '3',
02109   /* 56 */ '4',
02110   /* 57 */ '5',
02111   /* 58 */ '6',
02112   /* 59 */ '7',
02113   /* 60 */ '8',
02114   /* 61 */ '9',
02115   /* 62 */ '+',
02116   /* 63 */ '/'
02117 };
02118 
02120 #define UNBASE64_MIN_CHAR (43)
02121 
02122 #define UNBASE64_MAX_CHAR (122)
02123 
02126 #define UNBASE64_TABLE_OFFSET UNBASE64_MIN_CHAR
02127 static const signed char unbase64_table[] = {
02128   /* 43 + */ 62,
02129   /* 44 , */ -1,
02130   /* 45 - */ -1,
02131   /* 46 . */ -1,
02132   /* 47 / */ 63,
02133   /* 48 0 */ 52,
02134   /* 49 1 */ 53,
02135   /* 50 2 */ 54,
02136   /* 51 3 */ 55,
02137   /* 52 4 */ 56,
02138   /* 53 5 */ 57,
02139   /* 54 6 */ 58,
02140   /* 55 7 */ 59,
02141   /* 56 8 */ 60,
02142   /* 57 9 */ 61,
02143   /* 58 : */ -1,
02144   /* 59 ; */ -1,
02145   /* 60 < */ -1,
02146   /* 61 = */ -1,
02147   /* 62 > */ -1,
02148   /* 63 ? */ -1,
02149   /* 64 @ */ -1,
02150   /* 65 A */ 0,
02151   /* 66 B */ 1,
02152   /* 67 C */ 2,
02153   /* 68 D */ 3,
02154   /* 69 E */ 4,
02155   /* 70 F */ 5,
02156   /* 71 G */ 6,
02157   /* 72 H */ 7,
02158   /* 73 I */ 8,
02159   /* 74 J */ 9,
02160   /* 75 K */ 10,
02161   /* 76 L */ 11,
02162   /* 77 M */ 12,
02163   /* 78 N */ 13,
02164   /* 79 O */ 14,
02165   /* 80 P */ 15,
02166   /* 81 Q */ 16,
02167   /* 82 R */ 17,
02168   /* 83 S */ 18,
02169   /* 84 T */ 19,
02170   /* 85 U */ 20,
02171   /* 86 V */ 21,
02172   /* 87 W */ 22,
02173   /* 88 X */ 23,
02174   /* 89 Y */ 24,
02175   /* 90 Z */ 25,
02176   /* 91 [ */ -1,
02177   /* 92 \ */ -1,
02178   /* 93 ] */ -1,
02179   /* 94 ^ */ -1,
02180   /* 95 _ */ -1,
02181   /* 96 ` */ -1,
02182   /* 97 a */ 26,
02183   /* 98 b */ 27,
02184   /* 99 c */ 28,
02185   /* 100 d */ 29,
02186   /* 101 e */ 30,
02187   /* 102 f */ 31,
02188   /* 103 g */ 32,
02189   /* 104 h */ 33,
02190   /* 105 i */ 34,
02191   /* 106 j */ 35,
02192   /* 107 k */ 36,
02193   /* 108 l */ 37,
02194   /* 109 m */ 38,
02195   /* 110 n */ 39,
02196   /* 111 o */ 40,
02197   /* 112 p */ 41,
02198   /* 113 q */ 42,
02199   /* 114 r */ 43,
02200   /* 115 s */ 44,
02201   /* 116 t */ 45,
02202   /* 117 u */ 46,
02203   /* 118 v */ 47,
02204   /* 119 w */ 48,
02205   /* 120 x */ 49,
02206   /* 121 y */ 50,
02207   /* 122 z */ 51
02208 };
02209 
02219 dbus_bool_t
02220 _dbus_string_base64_encode (const DBusString *source,
02221                             int               start,
02222                             DBusString       *dest,
02223                             int               insert_at)
02224 {
02225   int source_len;
02226   unsigned int dest_len; /* unsigned for overflow checks below */
02227   const unsigned char *s;
02228   unsigned char *d;
02229   const unsigned char *triplet_end;
02230   const unsigned char *final_end;
02231   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);  
02232   _dbus_assert (source != dest);
02233   
02234   /* For each 24 bits (3 bytes) of input, we have 4 bytes of
02235    * output.
02236    */
02237   source_len = real_source->len - start;
02238   dest_len = (source_len / 3) * 4;
02239   if (source_len % 3 != 0)
02240     dest_len += 4;
02241 
02242   if (dest_len > (unsigned int) real_dest->max_length)
02243     return FALSE;
02244   
02245   if (source_len == 0)
02246     return TRUE;
02247   
02248   if (!open_gap (dest_len, real_dest, insert_at))
02249     return FALSE;
02250 
02251   d = real_dest->str + insert_at;
02252   s = real_source->str + start;
02253   final_end = real_source->str + (start + source_len);
02254   triplet_end = final_end - (source_len % 3);
02255   _dbus_assert (triplet_end <= final_end);
02256   _dbus_assert ((final_end - triplet_end) < 3);
02257 
02258 #define ENCODE_64(v) (base64_table[ (unsigned char) (v) ])
02259 #define SIX_BITS_MASK (0x3f)
02260   _dbus_assert (SIX_BITS_MASK < _DBUS_N_ELEMENTS (base64_table));
02261   
02262   while (s != triplet_end)
02263     {
02264       unsigned int triplet;
02265 
02266       triplet = s[2] | (s[1] << 8) | (s[0] << 16);
02267 
02268       /* Encode each 6 bits. */
02269 
02270       *d++ = ENCODE_64 (triplet >> 18);
02271       *d++ = ENCODE_64 ((triplet >> 12) & SIX_BITS_MASK);
02272       *d++ = ENCODE_64 ((triplet >> 6) & SIX_BITS_MASK);
02273       *d++ = ENCODE_64 (triplet & SIX_BITS_MASK);
02274       
02275       s += 3;
02276     }
02277 
02278   switch (final_end - triplet_end)
02279     {
02280     case 2:
02281       {
02282         unsigned int doublet;
02283         
02284         doublet = s[1] | (s[0] << 8);        
02285 
02286         *d++ = ENCODE_64 (doublet >> 12);
02287         *d++ = ENCODE_64 ((doublet >> 6) & SIX_BITS_MASK);
02288         *d++ = ENCODE_64 (doublet & SIX_BITS_MASK);
02289         *d++ = '=';
02290       }
02291       break;
02292     case 1:
02293       {
02294         unsigned int singlet;
02295         
02296         singlet = s[0];
02297 
02298         *d++ = ENCODE_64 ((singlet >> 6) & SIX_BITS_MASK);
02299         *d++ = ENCODE_64 (singlet & SIX_BITS_MASK);
02300         *d++ = '=';
02301         *d++ = '=';
02302       }
02303       break;
02304     case 0:
02305       break;
02306     }
02307 
02308   _dbus_assert (d == (real_dest->str + (insert_at + dest_len)));
02309 
02310   return TRUE;
02311 }
02312 
02327 dbus_bool_t
02328 _dbus_string_base64_decode (const DBusString *source,
02329                             int               start,
02330                             DBusString       *dest,
02331                             int               insert_at)
02332 {
02333   int source_len;
02334   const char *s;
02335   const char *end;
02336   DBusString result;
02337   unsigned int triplet = 0;
02338   int sextet_count;
02339   int pad_count;
02340   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
02341   _dbus_assert (source != dest);
02342   
02343   source_len = real_source->len - start;
02344   s = real_source->str + start;
02345   end = real_source->str + source_len;
02346 
02347   if (source_len == 0)
02348     return TRUE;
02349 
02350   if (!_dbus_string_init (&result))
02351     return FALSE;
02352 
02353   pad_count = 0;
02354   sextet_count = 0;
02355   while (s != end)
02356     {
02357       /* The idea is to just skip anything that isn't
02358        * a base64 char - it's allowed to have whitespace,
02359        * newlines, etc. in here. We also ignore trailing
02360        * base64 chars, though that's suspicious.
02361        */
02362       
02363       if (*s >= UNBASE64_MIN_CHAR &&
02364           *s <= UNBASE64_MAX_CHAR)
02365         {
02366           if (*s == '=')
02367             {
02368               /* '=' is padding, doesn't represent additional data
02369                * but does increment our count.
02370                */
02371               pad_count += 1;
02372               sextet_count += 1;
02373             }
02374           else
02375             {
02376               int val;
02377 
02378               val = unbase64_table[(*s) - UNBASE64_TABLE_OFFSET];
02379 
02380               if (val >= 0)
02381                 {
02382                   triplet <<= 6;
02383                   triplet |= (unsigned int) val;
02384                   sextet_count += 1;
02385                 }
02386             }
02387 
02388           if (sextet_count == 4)
02389             {
02390               /* no pad = 3 bytes, 1 pad = 2 bytes, 2 pad = 1 byte */
02391 
02392 
02393               /* AUDIT: Comment doesn't mention 4 pad => 0,
02394                *         3 pad => 1 byte, though the code should
02395                *        work fine if those are the required outputs.
02396                *
02397                *        I assume that the spec requires dropping
02398                *        the top two bits of, say, 
02399                *        bytes worth of bits. (Or otherwise, you couldn't
02400                *        actually represent 2 byte sequences.
02401                */
02402               
02403               if (pad_count < 1)
02404                 {
02405                   if (!_dbus_string_append_byte (&result,
02406                                                  triplet >> 16))
02407                     goto failed;
02408                 }
02409               
02410               if (pad_count < 2)
02411                 {
02412                   if (!_dbus_string_append_byte (&result,
02413                                                  (triplet >> 8) & 0xff))
02414                     goto failed;
02415                 }
02416               
02417               if (!_dbus_string_append_byte (&result,
02418                                              triplet & 0xff))
02419                 goto failed;
02420               
02421               sextet_count = 0;
02422               pad_count = 0;
02423               triplet = 0;
02424             }
02425         }
02426       
02427       ++s;
02428     }
02429 
02430   if (!_dbus_string_move (&result, 0, dest, insert_at))
02431     {
02432       _dbus_string_free (&result);
02433       return FALSE;
02434     }
02435 
02436   _dbus_string_free (&result);
02437 
02438   return TRUE;
02439 
02440  failed:
02441   _dbus_string_free (&result);
02442 
02443   return FALSE;
02444 }
02445 
02456 dbus_bool_t
02457 _dbus_string_hex_encode (const DBusString *source,
02458                          int               start,
02459                          DBusString       *dest,
02460                          int               insert_at)
02461 {
02462   DBusString result;
02463   const char hexdigits[16] = {
02464     '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
02465     'a', 'b', 'c', 'd', 'e', 'f'
02466   };
02467   const unsigned char *p;
02468   const unsigned char *end;
02469   dbus_bool_t retval;
02470   
02471   _dbus_assert (start <= _dbus_string_get_length (source));
02472 
02473   if (!_dbus_string_init (&result))
02474     return FALSE;
02475 
02476   retval = FALSE;
02477   
02478   p = (const unsigned char*) _dbus_string_get_const_data (source);
02479   end = p + _dbus_string_get_length (source);
02480   p += start;
02481   
02482   while (p != end)
02483     {
02484       if (!_dbus_string_append_byte (&result,
02485                                      hexdigits[(*p >> 4)]))
02486         goto out;
02487       
02488       if (!_dbus_string_append_byte (&result,
02489                                      hexdigits[(*p & 0x0f)]))
02490         goto out;
02491 
02492       ++p;
02493     }
02494 
02495   if (!_dbus_string_move (&result, 0, dest, insert_at))
02496     goto out;
02497 
02498   retval = TRUE;
02499 
02500  out:
02501   _dbus_string_free (&result);
02502   return retval;
02503 }
02504 
02514 dbus_bool_t
02515 _dbus_string_hex_decode (const DBusString *source,
02516                          int               start,
02517                          DBusString       *dest,
02518                          int               insert_at)
02519 {
02520   DBusString result;
02521   const unsigned char *p;
02522   const unsigned char *end;
02523   dbus_bool_t retval;
02524   dbus_bool_t high_bits;
02525   
02526   _dbus_assert (start <= _dbus_string_get_length (source));
02527 
02528   if (!_dbus_string_init (&result))
02529     return FALSE;
02530 
02531   retval = FALSE;
02532 
02533   high_bits = TRUE;
02534   p = (const unsigned char*) _dbus_string_get_const_data (source);
02535   end = p + _dbus_string_get_length (source);
02536   p += start;
02537   
02538   while (p != end)
02539     {
02540       unsigned int val;
02541 
02542       switch (*p)
02543         {
02544         case '0':
02545           val = 0;
02546           break;
02547         case '1':
02548           val = 1;
02549           break;
02550         case '2':
02551           val = 2;
02552           break;
02553         case '3':
02554           val = 3;
02555           break;
02556         case '4':
02557           val = 4;
02558           break;
02559         case '5':
02560           val = 5;
02561           break;
02562         case '6':
02563           val = 6;
02564           break;
02565         case '7':
02566           val = 7;
02567           break;
02568         case '8':
02569           val = 8;
02570           break;
02571         case '9':
02572           val = 9;
02573           break;
02574         case 'a':
02575         case 'A':
02576           val = 10;
02577           break;
02578         case 'b':
02579         case 'B':
02580           val = 11;
02581           break;
02582         case 'c':
02583         case 'C':
02584           val = 12;
02585           break;
02586         case 'd':
02587         case 'D':
02588           val = 13;
02589           break;
02590         case 'e':
02591         case 'E':
02592           val = 14;
02593           break;
02594         case 'f':
02595         case 'F':
02596           val = 15;
02597           break;
02598         default:
02599           val = 0;
02600           _dbus_verbose ("invalid character '%c' in hex encoded text\n",
02601                          *p);
02602           goto out;
02603         }
02604 
02605       if (high_bits)
02606         {
02607           if (!_dbus_string_append_byte (&result,
02608                                          val << 4))
02609             goto out;
02610         }
02611       else
02612         {
02613           int len;
02614           unsigned char b;
02615 
02616           len = _dbus_string_get_length (&result);
02617           
02618           b = _dbus_string_get_byte (&result, len - 1);
02619 
02620           b |= val;
02621 
02622           _dbus_string_set_byte (&result, len - 1, b);
02623         }
02624 
02625       high_bits = !high_bits;
02626 
02627       ++p;
02628     }
02629 
02630   if (!_dbus_string_move (&result, 0, dest, insert_at))
02631     goto out;
02632 
02633   retval = TRUE;
02634   
02635  out:
02636   _dbus_string_free (&result);  
02637   return retval;
02638 }
02639 
02653 dbus_bool_t
02654 _dbus_string_validate_ascii (const DBusString *str,
02655                              int               start,
02656                              int               len)
02657 {
02658   const unsigned char *s;
02659   const unsigned char *end;
02660   DBUS_CONST_STRING_PREAMBLE (str);
02661   _dbus_assert (start >= 0);
02662   _dbus_assert (start <= real->len);
02663   _dbus_assert (len >= 0);
02664   
02665   if (len > real->len - start)
02666     return FALSE;
02667   
02668   s = real->str + start;
02669   end = s + len;
02670   while (s != end)
02671     {
02672       if (*s == '\0' ||
02673           ((*s & ~0x7f) != 0))
02674         return FALSE;
02675         
02676       ++s;
02677     }
02678   
02679   return TRUE;
02680 }
02681 
02697 dbus_bool_t
02698 _dbus_string_validate_utf8  (const DBusString *str,
02699                              int               start,
02700                              int               len)
02701 {
02702   const unsigned char *p;
02703   const unsigned char *end;
02704   DBUS_CONST_STRING_PREAMBLE (str);
02705   _dbus_assert (start >= 0);
02706   _dbus_assert (start <= real->len);
02707   _dbus_assert (len >= 0);
02708 
02709   if (len > real->len - start)
02710     return FALSE;
02711   
02712   p = real->str + start;
02713   end = p + len;
02714   
02715   while (p < end)
02716     {
02717       int i, mask = 0, char_len;
02718       dbus_unichar_t result;
02719       unsigned char c = (unsigned char) *p;
02720       
02721       UTF8_COMPUTE (c, mask, char_len);
02722 
02723       if (char_len == -1)
02724         break;
02725 
02726       /* check that the expected number of bytes exists in the remaining length */
02727       if ((end - p) < char_len)
02728         break;
02729         
02730       UTF8_GET (result, p, i, mask, char_len);
02731 
02732       if (UTF8_LENGTH (result) != char_len) /* Check for overlong UTF-8 */
02733         break;
02734 
02735       if (result == (dbus_unichar_t)-1)
02736         break;
02737 
02738       if (!UNICODE_VALID (result))
02739         break;
02740       
02741       p += char_len;
02742     }
02743 
02744   /* See that we covered the entire length if a length was
02745    * passed in
02746    */
02747   if (p != end)
02748     return FALSE;
02749   else
02750     return TRUE;
02751 }
02752 
02766 dbus_bool_t
02767 _dbus_string_validate_nul (const DBusString *str,
02768                            int               start,
02769                            int               len)
02770 {
02771   const unsigned char *s;
02772   const unsigned char *end;
02773   DBUS_CONST_STRING_PREAMBLE (str);
02774   _dbus_assert (start >= 0);
02775   _dbus_assert (len >= 0);
02776   _dbus_assert (start <= real->len);
02777   
02778   if (len > real->len - start)
02779     return FALSE;
02780   
02781   s = real->str + start;
02782   end = s + len;
02783   while (s != end)
02784     {
02785       if (*s != '\0')
02786         return FALSE;
02787       ++s;
02788     }
02789   
02790   return TRUE;
02791 }
02792 
02807 dbus_bool_t
02808 _dbus_string_validate_name (const DBusString  *str,
02809                             int                start,
02810                             int                len)
02811 {
02812   const unsigned char *s;
02813   const unsigned char *end;
02814   dbus_bool_t saw_dot;
02815   
02816   DBUS_CONST_STRING_PREAMBLE (str);
02817   _dbus_assert (start >= 0);
02818   _dbus_assert (len >= 0);
02819   _dbus_assert (start <= real->len);
02820   
02821   if (len > real->len - start)
02822     return FALSE;
02823 
02824   if (len > DBUS_MAXIMUM_NAME_LENGTH)
02825     return FALSE;
02826 
02827   if (len == 0)
02828     return FALSE;
02829 
02830   saw_dot = FALSE;
02831   s = real->str + start;
02832   end = s + len;
02833   while (s != end)
02834     {
02835       if (*s == '.')
02836         {
02837           saw_dot = TRUE;
02838           break;
02839         }
02840       
02841       ++s;
02842     }
02843 
02844   if (!saw_dot)
02845     return FALSE;
02846   
02847   return TRUE;
02848 }
02849 
02850 
02865 dbus_bool_t
02866 _dbus_string_validate_service (const DBusString  *str,
02867                                int                start,
02868                                int                len)
02869 {
02870   const unsigned char *s;
02871   const unsigned char *end;
02872   dbus_bool_t saw_dot;
02873   dbus_bool_t is_base_service;
02874   
02875   DBUS_CONST_STRING_PREAMBLE (str);
02876   _dbus_assert (start >= 0);
02877   _dbus_assert (len >= 0);
02878   _dbus_assert (start <= real->len);
02879   
02880   if (len > real->len - start)
02881     return FALSE;
02882 
02883   if (len > DBUS_MAXIMUM_NAME_LENGTH)
02884     return FALSE;
02885 
02886   if (len == 0)
02887     return FALSE;
02888 
02889   is_base_service = _dbus_string_get_byte (str, start) == ':';
02890   if (is_base_service)
02891     return TRUE; /* can have any content */
02892 
02893   /* non-base-service must have the '.' indicating a namespace */
02894   
02895   saw_dot = FALSE;
02896   s = real->str + start;
02897   end = s + len;
02898   while (s != end)
02899     {
02900       if (*s == '.')
02901         {
02902           saw_dot = TRUE;
02903           break;
02904         }
02905       
02906       ++s;
02907     }
02908   
02909   return saw_dot;
02910 }
02911 
02917 void
02918 _dbus_string_zero (DBusString *str)
02919 {
02920   DBUS_STRING_PREAMBLE (str);
02921 
02922   memset (real->str - real->align_offset, '\0', real->allocated);
02923 }
02926 #ifdef DBUS_BUILD_TESTS
02927 #include "dbus-test.h"
02928 #include <stdio.h>
02929 
02930 static void
02931 test_max_len (DBusString *str,
02932               int         max_len)
02933 {
02934   if (max_len > 0)
02935     {
02936       if (!_dbus_string_set_length (str, max_len - 1))
02937         _dbus_assert_not_reached ("setting len to one less than max should have worked");
02938     }
02939 
02940   if (!_dbus_string_set_length (str, max_len))
02941     _dbus_assert_not_reached ("setting len to max len should have worked");
02942 
02943   if (_dbus_string_set_length (str, max_len + 1))
02944     _dbus_assert_not_reached ("setting len to one more than max len should not have worked");
02945 
02946   if (!_dbus_string_set_length (str, 0))
02947     _dbus_assert_not_reached ("setting len to zero should have worked");
02948 }
02949 
02950 static void
02951 test_base64_roundtrip (const unsigned char *data,
02952                        int                  len)
02953 {
02954   DBusString orig;
02955   DBusString encoded;
02956   DBusString decoded;
02957 
02958   if (len < 0)
02959     len = strlen (data);
02960   
02961   if (!_dbus_string_init (&orig))
02962     _dbus_assert_not_reached ("could not init string");
02963 
02964   if (!_dbus_string_init (&encoded))
02965     _dbus_assert_not_reached ("could not init string");
02966   
02967   if (!_dbus_string_init (&decoded))
02968     _dbus_assert_not_reached ("could not init string");
02969 
02970   if (!_dbus_string_append_len (&orig, data, len))
02971     _dbus_assert_not_reached ("couldn't append orig data");
02972 
02973   if (!_dbus_string_base64_encode (&orig, 0, &encoded, 0))
02974     _dbus_assert_not_reached ("could not encode");
02975 
02976   if (!_dbus_string_base64_decode (&encoded, 0, &decoded, 0))
02977     _dbus_assert_not_reached ("could not decode");
02978 
02979   if (!_dbus_string_equal (&orig, &decoded))
02980     {
02981       const char *s;
02982       
02983       printf ("Original string %d bytes encoded %d bytes decoded %d bytes\n",
02984               _dbus_string_get_length (&orig),
02985               _dbus_string_get_length (&encoded),
02986               _dbus_string_get_length (&decoded));
02987       printf ("Original: %s\n", data);
02988       s = _dbus_string_get_const_data (&decoded);
02989       printf ("Decoded: %s\n", s);
02990       _dbus_assert_not_reached ("original string not the same as string decoded from base64");
02991     }
02992   
02993   _dbus_string_free (&orig);
02994   _dbus_string_free (&encoded);
02995   _dbus_string_free (&decoded);  
02996 }
02997 
02998 static void
02999 test_hex_roundtrip (const unsigned char *data,
03000                     int                  len)
03001 {
03002   DBusString orig;
03003   DBusString encoded;
03004   DBusString decoded;
03005 
03006   if (len < 0)
03007     len = strlen (data);
03008   
03009   if (!_dbus_string_init (&orig))
03010     _dbus_assert_not_reached ("could not init string");
03011 
03012   if (!_dbus_string_init (&encoded))
03013     _dbus_assert_not_reached ("could not init string");
03014   
03015   if (!_dbus_string_init (&decoded))
03016     _dbus_assert_not_reached ("could not init string");
03017 
03018   if (!_dbus_string_append_len (&orig, data, len))
03019     _dbus_assert_not_reached ("couldn't append orig data");
03020 
03021   if (!_dbus_string_hex_encode (&orig, 0, &encoded, 0))
03022     _dbus_assert_not_reached ("could not encode");
03023 
03024   if (!_dbus_string_hex_decode (&encoded, 0, &decoded, 0))
03025     _dbus_assert_not_reached ("could not decode");
03026     
03027   if (!_dbus_string_equal (&orig, &decoded))
03028     {
03029       const char *s;
03030       
03031       printf ("Original string %d bytes encoded %d bytes decoded %d bytes\n",
03032               _dbus_string_get_length (&orig),
03033               _dbus_string_get_length (&encoded),
03034               _dbus_string_get_length (&decoded));
03035       printf ("Original: %s\n", data);
03036       s = _dbus_string_get_const_data (&decoded);
03037       printf ("Decoded: %s\n", s);
03038       _dbus_assert_not_reached ("original string not the same as string decoded from base64");
03039     }
03040   
03041   _dbus_string_free (&orig);
03042   _dbus_string_free (&encoded);
03043   _dbus_string_free (&decoded);  
03044 }
03045 
03046 typedef void (* TestRoundtripFunc) (const unsigned char *data,
03047                                     int                  len);
03048 static void
03049 test_roundtrips (TestRoundtripFunc func)
03050 {
03051   (* func) ("Hello this is a string\n", -1);
03052   (* func) ("Hello this is a string\n1", -1);
03053   (* func) ("Hello this is a string\n12", -1);
03054   (* func) ("Hello this is a string\n123", -1);
03055   (* func) ("Hello this is a string\n1234", -1);
03056   (* func) ("Hello this is a string\n12345", -1);
03057   (* func) ("", 0);
03058   (* func) ("1", 1);
03059   (* func) ("12", 2);
03060   (* func) ("123", 3);
03061   (* func) ("1234", 4);
03062   (* func) ("12345", 5);
03063   (* func) ("", 1);
03064   (* func) ("1", 2);
03065   (* func) ("12", 3);
03066   (* func) ("123", 4);
03067   (* func) ("1234", 5);
03068   (* func) ("12345", 6);
03069   {
03070     unsigned char buf[512];
03071     int i;
03072     
03073     i = 0;
03074     while (i < _DBUS_N_ELEMENTS (buf))
03075       {
03076         buf[i] = i;
03077         ++i;
03078       }
03079     i = 0;
03080     while (i < _DBUS_N_ELEMENTS (buf))
03081       {
03082         (* func) (buf, i);
03083         ++i;
03084       }
03085   }
03086 }
03087 
03088 
03099 dbus_bool_t
03100 _dbus_string_test (void)
03101 {
03102   DBusString str;
03103   DBusString other;
03104   int i, end;
03105   long v;
03106   double d;
03107   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 };
03108   char *s;
03109   dbus_unichar_t ch;
03110   
03111   i = 0;
03112   while (i < _DBUS_N_ELEMENTS (lens))
03113     {
03114       if (!_dbus_string_init (&str))
03115         _dbus_assert_not_reached ("failed to init string");
03116 
03117       set_max_length (&str, lens[i]);
03118       
03119       test_max_len (&str, lens[i]);
03120       _dbus_string_free (&str);
03121 
03122       ++i;
03123     }
03124 
03125   /* Test shortening and setting length */
03126   i = 0;
03127   while (i < _DBUS_N_ELEMENTS (lens))
03128     {
03129       int j;
03130       
03131       if (!_dbus_string_init (&str))
03132         _dbus_assert_not_reached ("failed to init string");
03133 
03134       set_max_length (&str, lens[i]);
03135       
03136       if (!_dbus_string_set_length (&str, lens[i]))
03137         _dbus_assert_not_reached ("failed to set string length");
03138 
03139       j = lens[i];
03140       while (j > 0)
03141         {
03142           _dbus_assert (_dbus_string_get_length (&str) == j);
03143           if (j > 0)
03144             {
03145               _dbus_string_shorten (&str, 1);
03146               _dbus_assert (_dbus_string_get_length (&str) == (j - 1));
03147             }
03148           --j;
03149         }
03150       
03151       _dbus_string_free (&str);
03152 
03153       ++i;
03154     }
03155 
03156   /* Test appending data */
03157   if (!_dbus_string_init (&str))
03158     _dbus_assert_not_reached ("failed to init string");
03159 
03160   i = 0;
03161   while (i < 10)
03162     {
03163       if (!_dbus_string_append (&str, "a"))
03164         _dbus_assert_not_reached ("failed to append string to string\n");
03165 
03166       _dbus_assert (_dbus_string_get_length (&str) == i * 2 + 1);
03167 
03168       if (!_dbus_string_append_byte (&str, 'b'))
03169         _dbus_assert_not_reached ("failed to append byte to string\n");
03170 
03171       _dbus_assert (_dbus_string_get_length (&str) == i * 2 + 2);
03172                     
03173       ++i;
03174     }
03175 
03176   _dbus_string_free (&str);
03177 
03178   /* Check steal_data */
03179   
03180   if (!_dbus_string_init (&str))
03181     _dbus_assert_not_reached ("failed to init string");
03182 
03183   if (!_dbus_string_append (&str, "Hello World"))
03184     _dbus_assert_not_reached ("could not append to string");
03185 
03186   i = _dbus_string_get_length (&str);
03187   
03188   if (!_dbus_string_steal_data (&str, &s))
03189     _dbus_assert_not_reached ("failed to steal data");
03190 
03191   _dbus_assert (_dbus_string_get_length (&str) == 0);
03192   _dbus_assert (((int)strlen (s)) == i);
03193 
03194   dbus_free (s);
03195 
03196   /* Check move */
03197   
03198   if (!_dbus_string_append (&str, "Hello World"))
03199     _dbus_assert_not_reached ("could not append to string");
03200 
03201   i = _dbus_string_get_length (&str);
03202 
03203   if (!_dbus_string_init (&other))
03204     _dbus_assert_not_reached ("could not init string");
03205   
03206   if (!_dbus_string_move (&str, 0, &other, 0))
03207     _dbus_assert_not_reached ("could not move");
03208 
03209   _dbus_assert (_dbus_string_get_length (&str) == 0);
03210   _dbus_assert (_dbus_string_get_length (&other) == i);
03211 
03212   if (!_dbus_string_append (&str, "Hello World"))
03213     _dbus_assert_not_reached ("could not append to string");
03214   
03215   if (!_dbus_string_move (&str, 0, &other, _dbus_string_get_length (&other)))
03216     _dbus_assert_not_reached ("could not move");
03217 
03218   _dbus_assert (_dbus_string_get_length (&str) == 0);
03219   _dbus_assert (_dbus_string_get_length (&other) == i * 2);
03220 
03221     if (!_dbus_string_append (&str, "Hello World"))
03222     _dbus_assert_not_reached ("could not append to string");
03223   
03224   if (!_dbus_string_move (&str, 0, &other, _dbus_string_get_length (&other) / 2))
03225     _dbus_assert_not_reached ("could not move");
03226 
03227   _dbus_assert (_dbus_string_get_length (&str) == 0);
03228   _dbus_assert (_dbus_string_get_length (&other) == i * 3);
03229   
03230   _dbus_string_free (&other);
03231 
03232   /* Check copy */
03233   
03234   if (!_dbus_string_append (&str, "Hello World"))
03235     _dbus_assert_not_reached ("could not append to string");
03236 
03237   i = _dbus_string_get_length (&str);
03238   
03239   if (!_dbus_string_init (&other))
03240     _dbus_assert_not_reached ("could not init string");
03241   
03242   if (!_dbus_string_copy (&str, 0, &other, 0))
03243     _dbus_assert_not_reached ("could not copy");
03244 
03245   _dbus_assert (_dbus_string_get_length (&str) == i);
03246   _dbus_assert (_dbus_string_get_length (&other) == i);
03247 
03248   if (!_dbus_string_copy (&str, 0, &other, _dbus_string_get_length (&other)))
03249     _dbus_assert_not_reached ("could not copy");
03250 
03251   _dbus_assert (_dbus_string_get_length (&str) == i);
03252   _dbus_assert (_dbus_string_get_length (&other) == i * 2);
03253   _dbus_assert (_dbus_string_equal_c_str (&other,
03254                                           "Hello WorldHello World"));
03255 
03256   if (!_dbus_string_copy (&str, 0, &other, _dbus_string_get_length (&other) / 2))
03257     _dbus_assert_not_reached ("could not copy");
03258 
03259   _dbus_assert (_dbus_string_get_length (&str) == i);
03260   _dbus_assert (_dbus_string_get_length (&other) == i * 3);
03261   _dbus_assert (_dbus_string_equal_c_str (&other,
03262                                           "Hello WorldHello WorldHello World"));
03263   
03264   _dbus_string_free (&str);
03265   _dbus_string_free (&other);
03266 
03267   /* Check replace */
03268 
03269   if (!_dbus_string_init (&str))
03270     _dbus_assert_not_reached ("failed to init string");
03271   
03272   if (!_dbus_string_append (&str, "Hello World"))
03273     _dbus_assert_not_reached ("could not append to string");
03274 
03275   i = _dbus_string_get_length (&str);
03276   
03277   if (!_dbus_string_init (&other))
03278     _dbus_assert_not_reached ("could not init string");
03279   
03280   if (!_dbus_string_replace_len (&str, 0, _dbus_string_get_length (&str),
03281                                  &other, 0, _dbus_string_get_length (&other)))
03282     _dbus_assert_not_reached ("could not replace");
03283 
03284   _dbus_assert (_dbus_string_get_length (&str) == i);
03285   _dbus_assert (_dbus_string_get_length (&other) == i);
03286   _dbus_assert (_dbus_string_equal_c_str (&other, "Hello World"));
03287   
03288   if (!_dbus_string_replace_len (&str, 0, _dbus_string_get_length (&str),
03289                                  &other, 5, 1))
03290     _dbus_assert_not_reached ("could not replace center space");
03291 
03292   _dbus_assert (_dbus_string_get_length (&str) == i);
03293   _dbus_assert (_dbus_string_get_length (&other) == i * 2 - 1);
03294   _dbus_assert (_dbus_string_equal_c_str (&other,
03295                                           "HelloHello WorldWorld"));
03296 
03297   
03298   if (!_dbus_string_replace_len (&str, 1, 1,
03299                                  &other,
03300                                  _dbus_string_get_length (&other) - 1,
03301                                  1))
03302     _dbus_assert_not_reached ("could not replace end character");
03303   
03304   _dbus_assert (_dbus_string_get_length (&str) == i);
03305   _dbus_assert (_dbus_string_get_length (&other) == i * 2 - 1);
03306   _dbus_assert (_dbus_string_equal_c_str (&other,
03307                                           "HelloHello WorldWorle"));
03308   
03309   _dbus_string_free (&str);
03310   _dbus_string_free (&other);
03311   
03312   /* Check append/get unichar */
03313   
03314   if (!_dbus_string_init (&str))
03315     _dbus_assert_not_reached ("failed to init string");
03316 
03317   ch = 0;
03318   if (!_dbus_string_append_unichar (&str, 0xfffc))
03319     _dbus_assert_not_reached ("failed to append unichar");
03320 
03321   _dbus_string_get_unichar (&str, 0, &ch, &i);
03322 
03323   _dbus_assert (ch == 0xfffc);
03324   _dbus_assert (i == _dbus_string_get_length (&str));
03325 
03326   _dbus_string_free (&str);
03327 
03328   /* Check insert/set/get byte */
03329   
03330   if (!_dbus_string_init (&str))
03331     _dbus_assert_not_reached ("failed to init string");
03332 
03333   if (!_dbus_string_append (&str, "Hello"))
03334     _dbus_assert_not_reached ("failed to append Hello");
03335 
03336   _dbus_assert (_dbus_string_get_byte (&str, 0) == 'H');
03337   _dbus_assert (_dbus_string_get_byte (&str, 1) == 'e');
03338   _dbus_assert (_dbus_string_get_byte (&str, 2) == 'l');
03339   _dbus_assert (_dbus_string_get_byte (&str, 3) == 'l');
03340   _dbus_assert (_dbus_string_get_byte (&str, 4) == 'o');
03341 
03342   _dbus_string_set_byte (&str, 1, 'q');
03343   _dbus_assert (_dbus_string_get_byte (&str, 1) == 'q');
03344 
03345   if (!_dbus_string_insert_byte (&str, 0, 255))
03346     _dbus_assert_not_reached ("can't insert byte");
03347 
03348   if (!_dbus_string_insert_byte (&str, 2, 'Z'))
03349     _dbus_assert_not_reached ("can't insert byte");
03350 
03351   if (!_dbus_string_insert_byte (&str, _dbus_string_get_length (&str), 'W'))
03352     _dbus_assert_not_reached ("can't insert byte");
03353   
03354   _dbus_assert (_dbus_string_get_byte (&str, 0) == 255);
03355   _dbus_assert (_dbus_string_get_byte (&str, 1) == 'H');
03356   _dbus_assert (_dbus_string_get_byte (&str, 2) == 'Z');
03357   _dbus_assert (_dbus_string_get_byte (&str, 3) == 'q');
03358   _dbus_assert (_dbus_string_get_byte (&str, 4) == 'l');
03359   _dbus_assert (_dbus_string_get_byte (&str, 5) == 'l');
03360   _dbus_assert (_dbus_string_get_byte (&str, 6) == 'o');
03361   _dbus_assert (_dbus_string_get_byte (&str, 7) == 'W');
03362 
03363   _dbus_string_free (&str);
03364   
03365   /* Check append/parse int/double */
03366   
03367   if (!_dbus_string_init (&str))
03368     _dbus_assert_not_reached ("failed to init string");
03369 
03370   if (!_dbus_string_append_int (&str, 27))
03371     _dbus_assert_not_reached ("failed to append int");
03372 
03373   i = _dbus_string_get_length (&str);
03374 
03375   if (!_dbus_string_parse_int (&str, 0, &v, &end))
03376     _dbus_assert_not_reached ("failed to parse int");
03377 
03378   _dbus_assert (v == 27);
03379   _dbus_assert (end == i);
03380 
03381   _dbus_string_free (&str);
03382   
03383   if (!_dbus_string_init (&str))
03384     _dbus_assert_not_reached ("failed to init string");
03385   
03386   if (!_dbus_string_append_double (&str, 50.3))
03387     _dbus_assert_not_reached ("failed to append float");
03388 
03389   i = _dbus_string_get_length (&str);
03390 
03391   if (!_dbus_string_parse_double (&str, 0, &d, &end))
03392     _dbus_assert_not_reached ("failed to parse float");
03393 
03394   _dbus_assert (d > (50.3 - 1e-6) && d < (50.3 + 1e-6));
03395   _dbus_assert (end == i);
03396 
03397   _dbus_string_free (&str);
03398 
03399   /* Test find */
03400   if (!_dbus_string_init (&str))
03401     _dbus_assert_not_reached ("failed to init string");
03402 
03403   if (!_dbus_string_append (&str, "Hello"))
03404     _dbus_assert_not_reached ("couldn't append to string");
03405   
03406   if (!_dbus_string_find (&str, 0, "He", &i))
03407     _dbus_assert_not_reached ("didn't find 'He'");
03408   _dbus_assert (i == 0);
03409 
03410   if (!_dbus_string_find (&str, 0, "Hello", &i))
03411     _dbus_assert_not_reached ("didn't find 'Hello'");
03412   _dbus_assert (i == 0);
03413   
03414   if (!_dbus_string_find (&str, 0, "ello", &i))
03415     _dbus_assert_not_reached ("didn't find 'ello'");
03416   _dbus_assert (i == 1);
03417 
03418   if (!_dbus_string_find (&str, 0, "lo", &i))
03419     _dbus_assert_not_reached ("didn't find 'lo'");
03420   _dbus_assert (i == 3);
03421 
03422   if (!_dbus_string_find (&str, 2, "lo", &i))
03423     _dbus_assert_not_reached ("didn't find 'lo'");
03424   _dbus_assert (i == 3);
03425 
03426   if (_dbus_string_find (&str, 4, "lo", &i))
03427     _dbus_assert_not_reached ("did find 'lo'");
03428   
03429   if (!_dbus_string_find (&str, 0, "l", &i))
03430     _dbus_assert_not_reached ("didn't find 'l'");
03431   _dbus_assert (i == 2);
03432 
03433   if (!_dbus_string_find (&str, 0, "H", &i))
03434     _dbus_assert_not_reached ("didn't find 'H'");
03435   _dbus_assert (i == 0);
03436 
03437   if (!_dbus_string_find (&str, 0, "", &i))
03438     _dbus_assert_not_reached ("didn't find ''");
03439   _dbus_assert (i == 0);
03440   
03441   if (_dbus_string_find (&str, 0, "Hello!", NULL))
03442     _dbus_assert_not_reached ("Did find 'Hello!'");
03443 
03444   if (_dbus_string_find (&str, 0, "Oh, Hello", NULL))
03445     _dbus_assert_not_reached ("Did find 'Oh, Hello'");
03446   
03447   if (_dbus_string_find (&str, 0, "ill", NULL))
03448     _dbus_assert_not_reached ("Did find 'ill'");
03449 
03450   if (_dbus_string_find (&str, 0, "q", NULL))
03451     _dbus_assert_not_reached ("Did find 'q'");
03452 
03453   if (!_dbus_string_find_to (&str, 0, 2, "He", NULL))
03454     _dbus_assert_not_reached ("Didn't find 'He'");
03455 
03456   if (_dbus_string_find_to (&str, 0, 2, "Hello", NULL))
03457     _dbus_assert_not_reached ("Did find 'Hello'");
03458 
03459   if (!_dbus_string_find_byte_backward (&str, _dbus_string_get_length (&str), 'H', &i))
03460     _dbus_assert_not_reached ("Did not find 'H'");
03461   _dbus_assert (i == 0);
03462 
03463   if (!_dbus_string_find_byte_backward (&str, _dbus_string_get_length (&str), 'o', &i))
03464     _dbus_assert_not_reached ("Did not find 'o'");
03465   _dbus_assert (i == _dbus_string_get_length (&str) - 1);
03466 
03467   if (_dbus_string_find_byte_backward (&str, _dbus_string_get_length (&str) - 1, 'o', &i))
03468     _dbus_assert_not_reached ("Did find 'o'");
03469   _dbus_assert (i == -1);
03470 
03471   if (_dbus_string_find_byte_backward (&str, 1, 'e', &i))
03472     _dbus_assert_not_reached ("Did find 'e'");
03473   _dbus_assert (i == -1);
03474 
03475   if (!_dbus_string_find_byte_backward (&str, 2, 'e', &i))
03476     _dbus_assert_not_reached ("Didn't find 'e'");
03477   _dbus_assert (i == 1);
03478   
03479   _dbus_string_free (&str);
03480 
03481   /* Base 64 and Hex encoding */
03482   test_roundtrips (test_base64_roundtrip);
03483   test_roundtrips (test_hex_roundtrip);
03484   
03485   return TRUE;
03486 }
03487 
03488 #endif /* DBUS_BUILD_TESTS */

Generated on Wed Oct 22 14:05:04 2003 for D-BUS by doxygen1.3-rc3