D-Bus  1.5.8
dbus-string.c
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
00002 /* dbus-string.c String utility class (internal to D-Bus implementation)
00003  * 
00004  * Copyright (C) 2002, 2003, 2004, 2005 Red Hat, Inc.
00005  * Copyright (C) 2006 Ralf Habacker <ralf.habacker@freenet.de>
00006  *
00007  * Licensed under the Academic Free License version 2.1
00008  * 
00009  * This program is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  * 
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00022  *
00023  */
00024 
00025 #include <config.h>
00026 #include "dbus-internals.h"
00027 #include "dbus-string.h"
00028 /* we allow a system header here, for speed/convenience */
00029 #include <string.h>
00030 /* for vsnprintf */
00031 #include <stdio.h>
00032 #define DBUS_CAN_USE_DBUS_STRING_PRIVATE 1
00033 #include "dbus-string-private.h"
00034 #include "dbus-marshal-basic.h" /* probably should be removed by moving the usage of DBUS_TYPE
00035                                  * into the marshaling-related files
00036                                  */
00037 /* for DBUS_VA_COPY */
00038 #include "dbus-sysdeps.h"
00039 
00078 static void
00079 fixup_alignment (DBusRealString *real)
00080 {
00081   unsigned char *aligned;
00082   unsigned char *real_block;
00083   unsigned int old_align_offset;
00084 
00085   /* we have to have extra space in real->allocated for the align offset and nul byte */
00086   _dbus_assert (real->len <= real->allocated - _DBUS_STRING_ALLOCATION_PADDING);
00087   
00088   old_align_offset = real->align_offset;
00089   real_block = real->str - old_align_offset;
00090   
00091   aligned = _DBUS_ALIGN_ADDRESS (real_block, 8);
00092 
00093   real->align_offset = aligned - real_block;
00094   real->str = aligned;
00095   
00096   if (old_align_offset != real->align_offset)
00097     {
00098       /* Here comes the suck */
00099       memmove (real_block + real->align_offset,
00100                real_block + old_align_offset,
00101                real->len + 1);
00102     }
00103 
00104   _dbus_assert (real->align_offset < 8);
00105   _dbus_assert (_DBUS_ALIGN_ADDRESS (real->str, 8) == real->str);
00106 }
00107 
00108 static void
00109 undo_alignment (DBusRealString *real)
00110 {
00111   if (real->align_offset != 0)
00112     {
00113       memmove (real->str - real->align_offset,
00114                real->str,
00115                real->len + 1);
00116 
00117       real->str = real->str - real->align_offset;
00118       real->align_offset = 0;
00119     }
00120 }
00121 
00131 dbus_bool_t
00132 _dbus_string_init_preallocated (DBusString *str,
00133                                 int         allocate_size)
00134 {
00135   DBusRealString *real;
00136   
00137   _dbus_assert (str != NULL);
00138 
00139   _dbus_assert (sizeof (DBusString) == sizeof (DBusRealString));
00140   
00141   real = (DBusRealString*) str;
00142 
00143   /* It's very important not to touch anything
00144    * other than real->str if we're going to fail,
00145    * since we also use this function to reset
00146    * an existing string, e.g. in _dbus_string_steal_data()
00147    */
00148   
00149   real->str = dbus_malloc (_DBUS_STRING_ALLOCATION_PADDING + allocate_size);
00150   if (real->str == NULL)
00151     return FALSE;  
00152   
00153   real->allocated = _DBUS_STRING_ALLOCATION_PADDING + allocate_size;
00154   real->len = 0;
00155   real->str[real->len] = '\0';
00156   
00157   real->constant = FALSE;
00158   real->locked = FALSE;
00159   real->invalid = FALSE;
00160   real->align_offset = 0;
00161   
00162   fixup_alignment (real);
00163   
00164   return TRUE;
00165 }
00166 
00174 dbus_bool_t
00175 _dbus_string_init (DBusString *str)
00176 {
00177   return _dbus_string_init_preallocated (str, 0);
00178 }
00179 
00189 void
00190 _dbus_string_init_const (DBusString *str,
00191                          const char *value)
00192 {
00193   _dbus_assert (value != NULL);
00194   
00195   _dbus_string_init_const_len (str, value,
00196                                strlen (value));
00197 }
00198 
00209 void
00210 _dbus_string_init_const_len (DBusString *str,
00211                              const char *value,
00212                              int         len)
00213 {
00214   DBusRealString *real;
00215   
00216   _dbus_assert (str != NULL);
00217   _dbus_assert (len == 0 || value != NULL);
00218   _dbus_assert (len <= _DBUS_STRING_MAX_LENGTH);
00219   _dbus_assert (len >= 0);
00220   
00221   real = (DBusRealString*) str;
00222   
00223   real->str = (unsigned char*) value;
00224   real->len = len;
00225   real->allocated = real->len + _DBUS_STRING_ALLOCATION_PADDING; /* a lie, just to avoid special-case assertions... */
00226   real->constant = TRUE;
00227   real->locked = TRUE;
00228   real->invalid = FALSE;
00229   real->align_offset = 0;
00230 
00231   /* We don't require const strings to be 8-byte aligned as the
00232    * memory is coming from elsewhere.
00233    */
00234 }
00235 
00241 void
00242 _dbus_string_free (DBusString *str)
00243 {
00244   DBusRealString *real = (DBusRealString*) str;
00245   DBUS_GENERIC_STRING_PREAMBLE (real);
00246   
00247   if (real->constant)
00248     return;
00249   dbus_free (real->str - real->align_offset);
00250 
00251   real->invalid = TRUE;
00252 }
00253 
00254 static dbus_bool_t
00255 compact (DBusRealString *real,
00256          int             max_waste)
00257 {
00258   unsigned char *new_str;
00259   int new_allocated;
00260   int waste;
00261 
00262   waste = real->allocated - (real->len + _DBUS_STRING_ALLOCATION_PADDING);
00263 
00264   if (waste <= max_waste)
00265     return TRUE;
00266 
00267   new_allocated = real->len + _DBUS_STRING_ALLOCATION_PADDING;
00268 
00269   new_str = dbus_realloc (real->str - real->align_offset, new_allocated);
00270   if (_DBUS_UNLIKELY (new_str == NULL))
00271     return FALSE;
00272 
00273   real->str = new_str + real->align_offset;
00274   real->allocated = new_allocated;
00275   fixup_alignment (real);
00276 
00277   return TRUE;
00278 }
00279 
00280 #ifdef DBUS_BUILD_TESTS
00281 /* Not using this feature at the moment,
00282  * so marked DBUS_BUILD_TESTS-only
00283  */
00293 void
00294 _dbus_string_lock (DBusString *str)
00295 {  
00296   DBUS_LOCKED_STRING_PREAMBLE (str); /* can lock multiple times */
00297 
00298   real->locked = TRUE;
00299 
00300   /* Try to realloc to avoid excess memory usage, since
00301    * we know we won't change the string further
00302    */
00303 #define MAX_WASTE 48
00304   compact (real, MAX_WASTE);
00305 }
00306 #endif /* DBUS_BUILD_TESTS */
00307 
00308 static dbus_bool_t
00309 reallocate_for_length (DBusRealString *real,
00310                        int             new_length)
00311 {
00312   int new_allocated;
00313   unsigned char *new_str;
00314 
00315   /* at least double our old allocation to avoid O(n), avoiding
00316    * overflow
00317    */
00318   if (real->allocated > (_DBUS_STRING_MAX_LENGTH + _DBUS_STRING_ALLOCATION_PADDING) / 2)
00319     new_allocated = _DBUS_STRING_MAX_LENGTH + _DBUS_STRING_ALLOCATION_PADDING;
00320   else
00321     new_allocated = real->allocated * 2;
00322 
00323   /* if you change the code just above here, run the tests without
00324    * the following assert-only hack before you commit
00325    */
00326   /* This is keyed off asserts in addition to tests so when you
00327    * disable asserts to profile, you don't get this destroyer
00328    * of profiles.
00329    */
00330 #ifdef DBUS_DISABLE_ASSERT
00331 #else
00332 #ifdef DBUS_BUILD_TESTS
00333   new_allocated = 0; /* ensure a realloc every time so that we go
00334                       * through all malloc failure codepaths
00335                       */
00336 #endif /* DBUS_BUILD_TESTS */
00337 #endif /* !DBUS_DISABLE_ASSERT */
00338 
00339   /* But be sure we always alloc at least space for the new length */
00340   new_allocated = MAX (new_allocated,
00341                        new_length + _DBUS_STRING_ALLOCATION_PADDING);
00342 
00343   _dbus_assert (new_allocated >= real->allocated); /* code relies on this */
00344   new_str = dbus_realloc (real->str - real->align_offset, new_allocated);
00345   if (_DBUS_UNLIKELY (new_str == NULL))
00346     return FALSE;
00347 
00348   real->str = new_str + real->align_offset;
00349   real->allocated = new_allocated;
00350   fixup_alignment (real);
00351 
00352   return TRUE;
00353 }
00354 
00366 dbus_bool_t
00367 _dbus_string_compact (DBusString *str,
00368                       int         max_waste)
00369 {
00370   DBUS_STRING_PREAMBLE (str);
00371 
00372   return compact (real, max_waste);
00373 }
00374 
00375 static dbus_bool_t
00376 set_length (DBusRealString *real,
00377             int             new_length)
00378 {
00379   /* Note, we are setting the length not including nul termination */
00380 
00381   /* exceeding max length is the same as failure to allocate memory */
00382   if (_DBUS_UNLIKELY (new_length > _DBUS_STRING_MAX_LENGTH))
00383     return FALSE;
00384   else if (new_length > (real->allocated - _DBUS_STRING_ALLOCATION_PADDING) &&
00385            _DBUS_UNLIKELY (!reallocate_for_length (real, new_length)))
00386     return FALSE;
00387   else
00388     {
00389       real->len = new_length;
00390       real->str[new_length] = '\0';
00391       return TRUE;
00392     }
00393 }
00394 
00395 static dbus_bool_t
00396 open_gap (int             len,
00397           DBusRealString *dest,
00398           int             insert_at)
00399 {
00400   if (len == 0)
00401     return TRUE;
00402 
00403   if (len > _DBUS_STRING_MAX_LENGTH - dest->len)
00404     return FALSE; /* detected overflow of dest->len + len below */
00405   
00406   if (!set_length (dest, dest->len + len))
00407     return FALSE;
00408 
00409   memmove (dest->str + insert_at + len, 
00410            dest->str + insert_at,
00411            dest->len - len - insert_at);
00412 
00413   return TRUE;
00414 }
00415 
00416 #ifndef _dbus_string_get_data
00417 
00428 char*
00429 _dbus_string_get_data (DBusString *str)
00430 {
00431   DBUS_STRING_PREAMBLE (str);
00432   
00433   return (char*) real->str;
00434 }
00435 #endif /* _dbus_string_get_data */
00436 
00437 /* only do the function if we don't have the macro */
00438 #ifndef _dbus_string_get_const_data
00439 
00445 const char*
00446 _dbus_string_get_const_data (const DBusString  *str)
00447 {
00448   DBUS_CONST_STRING_PREAMBLE (str);
00449   
00450   return (const char*) real->str;
00451 }
00452 #endif /* _dbus_string_get_const_data */
00453 
00467 char*
00468 _dbus_string_get_data_len (DBusString *str,
00469                            int         start,
00470                            int         len)
00471 {
00472   DBUS_STRING_PREAMBLE (str);
00473   _dbus_assert (start >= 0);
00474   _dbus_assert (len >= 0);
00475   _dbus_assert (start <= real->len);
00476   _dbus_assert (len <= real->len - start);
00477   
00478   return (char*) real->str + start;
00479 }
00480 
00481 /* only do the function if we don't have the macro */
00482 #ifndef _dbus_string_get_const_data_len
00483 
00491 const char*
00492 _dbus_string_get_const_data_len (const DBusString  *str,
00493                                  int                start,
00494                                  int                len)
00495 {
00496   DBUS_CONST_STRING_PREAMBLE (str);
00497   _dbus_assert (start >= 0);
00498   _dbus_assert (len >= 0);
00499   _dbus_assert (start <= real->len);
00500   _dbus_assert (len <= real->len - start);
00501   
00502   return (const char*) real->str + start;
00503 }
00504 #endif /* _dbus_string_get_const_data_len */
00505 
00506 /* only do the function if we don't have the macro */
00507 #ifndef _dbus_string_set_byte
00508 
00515 void
00516 _dbus_string_set_byte (DBusString    *str,
00517                        int            i,
00518                        unsigned char  byte)
00519 {
00520   DBUS_STRING_PREAMBLE (str);
00521   _dbus_assert (i < real->len);
00522   _dbus_assert (i >= 0);
00523   
00524   real->str[i] = byte;
00525 }
00526 #endif /* _dbus_string_set_byte */
00527 
00528 /* only have the function if we didn't create a macro */
00529 #ifndef _dbus_string_get_byte
00530 
00539 unsigned char
00540 _dbus_string_get_byte (const DBusString  *str,
00541                        int                start)
00542 {
00543   DBUS_CONST_STRING_PREAMBLE (str);
00544   _dbus_assert (start <= real->len);
00545   _dbus_assert (start >= 0);
00546   
00547   return real->str[start];
00548 }
00549 #endif /* _dbus_string_get_byte */
00550 
00561 dbus_bool_t
00562 _dbus_string_insert_bytes (DBusString   *str,
00563                            int           i,
00564                            int           n_bytes,
00565                            unsigned char byte)
00566 {
00567   DBUS_STRING_PREAMBLE (str);
00568   _dbus_assert (i <= real->len);
00569   _dbus_assert (i >= 0);
00570   _dbus_assert (n_bytes >= 0);
00571 
00572   if (n_bytes == 0)
00573     return TRUE;
00574   
00575   if (!open_gap (n_bytes, real, i))
00576     return FALSE;
00577   
00578   memset (real->str + i, byte, n_bytes);
00579 
00580   return TRUE;
00581 }
00582 
00591 dbus_bool_t
00592 _dbus_string_insert_byte (DBusString   *str,
00593                            int           i,
00594                            unsigned char byte)
00595 {
00596   DBUS_STRING_PREAMBLE (str);
00597   _dbus_assert (i <= real->len);
00598   _dbus_assert (i >= 0);
00599   
00600   if (!open_gap (1, real, i))
00601     return FALSE;
00602 
00603   real->str[i] = byte;
00604 
00605   return TRUE;
00606 }
00607 
00618 dbus_bool_t
00619 _dbus_string_steal_data (DBusString        *str,
00620                          char             **data_return)
00621 {
00622   DBUS_STRING_PREAMBLE (str);
00623   _dbus_assert (data_return != NULL);
00624 
00625   undo_alignment (real);
00626   
00627   *data_return = (char*) real->str;
00628 
00629   /* reset the string */
00630   if (!_dbus_string_init (str))
00631     {
00632       /* hrm, put it back then */
00633       real->str = (unsigned char*) *data_return;
00634       *data_return = NULL;
00635       fixup_alignment (real);
00636       return FALSE;
00637     }
00638 
00639   return TRUE;
00640 }
00641 
00649 dbus_bool_t
00650 _dbus_string_copy_data (const DBusString  *str,
00651                         char             **data_return)
00652 {
00653   DBUS_CONST_STRING_PREAMBLE (str);
00654   _dbus_assert (data_return != NULL);
00655   
00656   *data_return = dbus_malloc (real->len + 1);
00657   if (*data_return == NULL)
00658     return FALSE;
00659 
00660   memcpy (*data_return, real->str, real->len + 1);
00661 
00662   return TRUE;
00663 }
00664 
00674 void
00675 _dbus_string_copy_to_buffer (const DBusString  *str,
00676                              char              *buffer,
00677                              int                avail_len)
00678 {
00679   DBUS_CONST_STRING_PREAMBLE (str);
00680 
00681   _dbus_assert (avail_len >= 0);
00682   _dbus_assert (avail_len >= real->len);
00683   
00684   memcpy (buffer, real->str, real->len);
00685 }
00686 
00696 void
00697 _dbus_string_copy_to_buffer_with_nul (const DBusString  *str,
00698                                       char              *buffer,
00699                                       int                avail_len)
00700 {
00701   DBUS_CONST_STRING_PREAMBLE (str);
00702 
00703   _dbus_assert (avail_len >= 0);
00704   _dbus_assert (avail_len > real->len);
00705   
00706   memcpy (buffer, real->str, real->len+1);
00707 }
00708 
00709 /* Only have the function if we don't have the macro */
00710 #ifndef _dbus_string_get_length
00711 
00716 int
00717 _dbus_string_get_length (const DBusString  *str)
00718 {
00719   DBUS_CONST_STRING_PREAMBLE (str);
00720   
00721   return real->len;
00722 }
00723 #endif /* !_dbus_string_get_length */
00724 
00737 dbus_bool_t
00738 _dbus_string_lengthen (DBusString *str,
00739                        int         additional_length)
00740 {
00741   DBUS_STRING_PREAMBLE (str);  
00742   _dbus_assert (additional_length >= 0);
00743 
00744   if (_DBUS_UNLIKELY (additional_length > _DBUS_STRING_MAX_LENGTH - real->len))
00745     return FALSE; /* would overflow */
00746   
00747   return set_length (real,
00748                      real->len + additional_length);
00749 }
00750 
00757 void
00758 _dbus_string_shorten (DBusString *str,
00759                       int         length_to_remove)
00760 {
00761   DBUS_STRING_PREAMBLE (str);
00762   _dbus_assert (length_to_remove >= 0);
00763   _dbus_assert (length_to_remove <= real->len);
00764 
00765   set_length (real,
00766               real->len - length_to_remove);
00767 }
00768 
00779 dbus_bool_t
00780 _dbus_string_set_length (DBusString *str,
00781                          int         length)
00782 {
00783   DBUS_STRING_PREAMBLE (str);
00784   _dbus_assert (length >= 0);
00785 
00786   return set_length (real, length);
00787 }
00788 
00789 static dbus_bool_t
00790 align_insert_point_then_open_gap (DBusString *str,
00791                                   int        *insert_at_p,
00792                                   int         alignment,
00793                                   int         gap_size)
00794 {
00795   unsigned long new_len; /* ulong to avoid _DBUS_ALIGN_VALUE overflow */
00796   unsigned long gap_pos;
00797   int insert_at;
00798   int delta;
00799   DBUS_STRING_PREAMBLE (str);
00800   _dbus_assert (alignment >= 1);
00801   _dbus_assert (alignment <= 8); /* it has to be a bug if > 8 */
00802 
00803   insert_at = *insert_at_p;
00804 
00805   _dbus_assert (insert_at <= real->len);
00806   
00807   gap_pos = _DBUS_ALIGN_VALUE (insert_at, alignment);
00808   new_len = real->len + (gap_pos - insert_at) + gap_size;
00809   
00810   if (_DBUS_UNLIKELY (new_len > (unsigned long) _DBUS_STRING_MAX_LENGTH))
00811     return FALSE;
00812   
00813   delta = new_len - real->len;
00814   _dbus_assert (delta >= 0);
00815 
00816   if (delta == 0) /* only happens if gap_size == 0 and insert_at is aligned already */
00817     {
00818       _dbus_assert (((unsigned long) *insert_at_p) == gap_pos);
00819       return TRUE;
00820     }
00821 
00822   if (_DBUS_UNLIKELY (!open_gap (new_len - real->len,
00823                                  real, insert_at)))
00824     return FALSE;
00825 
00826   /* nul the padding if we had to add any padding */
00827   if (gap_size < delta)
00828     {
00829       memset (&real->str[insert_at], '\0',
00830               gap_pos - insert_at);
00831     }
00832 
00833   *insert_at_p = gap_pos;
00834   
00835   return TRUE;
00836 }
00837 
00838 static dbus_bool_t
00839 align_length_then_lengthen (DBusString *str,
00840                             int         alignment,
00841                             int         then_lengthen_by)
00842 {
00843   int insert_at;
00844 
00845   insert_at = _dbus_string_get_length (str);
00846   
00847   return align_insert_point_then_open_gap (str,
00848                                            &insert_at,
00849                                            alignment, then_lengthen_by);
00850 }
00851 
00860 dbus_bool_t
00861 _dbus_string_align_length (DBusString *str,
00862                            int         alignment)
00863 {
00864   return align_length_then_lengthen (str, alignment, 0);
00865 }
00866 
00876 dbus_bool_t
00877 _dbus_string_alloc_space (DBusString        *str,
00878                           int                extra_bytes)
00879 {
00880   if (!_dbus_string_lengthen (str, extra_bytes))
00881     return FALSE;
00882   _dbus_string_shorten (str, extra_bytes);
00883 
00884   return TRUE;
00885 }
00886 
00887 static dbus_bool_t
00888 append (DBusRealString *real,
00889         const char     *buffer,
00890         int             buffer_len)
00891 {
00892   if (buffer_len == 0)
00893     return TRUE;
00894 
00895   if (!_dbus_string_lengthen ((DBusString*)real, buffer_len))
00896     return FALSE;
00897 
00898   memcpy (real->str + (real->len - buffer_len),
00899           buffer,
00900           buffer_len);
00901 
00902   return TRUE;
00903 }
00904 
00912 dbus_bool_t
00913 _dbus_string_append (DBusString *str,
00914                      const char *buffer)
00915 {
00916   unsigned long buffer_len;
00917   
00918   DBUS_STRING_PREAMBLE (str);
00919   _dbus_assert (buffer != NULL);
00920   
00921   buffer_len = strlen (buffer);
00922   if (buffer_len > (unsigned long) _DBUS_STRING_MAX_LENGTH)
00923     return FALSE;
00924   
00925   return append (real, buffer, buffer_len);
00926 }
00927 
00929 #define ASSIGN_2_OCTETS(p, octets) \
00930   *((dbus_uint16_t*)(p)) = *((dbus_uint16_t*)(octets));
00931 
00933 #define ASSIGN_4_OCTETS(p, octets) \
00934   *((dbus_uint32_t*)(p)) = *((dbus_uint32_t*)(octets));
00935 
00936 #ifdef DBUS_HAVE_INT64
00937 
00938 #define ASSIGN_8_OCTETS(p, octets) \
00939   *((dbus_uint64_t*)(p)) = *((dbus_uint64_t*)(octets));
00940 #else
00941 
00942 #define ASSIGN_8_OCTETS(p, octets)              \
00943 do {                                            \
00944   unsigned char *b;                             \
00945                                                 \
00946   b = p;                                        \
00947                                                 \
00948   *b++ = octets[0];                             \
00949   *b++ = octets[1];                             \
00950   *b++ = octets[2];                             \
00951   *b++ = octets[3];                             \
00952   *b++ = octets[4];                             \
00953   *b++ = octets[5];                             \
00954   *b++ = octets[6];                             \
00955   *b++ = octets[7];                             \
00956   _dbus_assert (b == p + 8);                    \
00957 } while (0)
00958 #endif /* DBUS_HAVE_INT64 */
00959 
00960 #ifdef DBUS_BUILD_TESTS
00961 
00969 dbus_bool_t
00970 _dbus_string_append_4_aligned (DBusString         *str,
00971                                const unsigned char octets[4])
00972 {
00973   DBUS_STRING_PREAMBLE (str);
00974   
00975   if (!align_length_then_lengthen (str, 4, 4))
00976     return FALSE;
00977 
00978   ASSIGN_4_OCTETS (real->str + (real->len - 4), octets);
00979 
00980   return TRUE;
00981 }
00982 #endif /* DBUS_BUILD_TESTS */
00983 
00984 #ifdef DBUS_BUILD_TESTS
00985 
00993 dbus_bool_t
00994 _dbus_string_append_8_aligned (DBusString         *str,
00995                                const unsigned char octets[8])
00996 {
00997   DBUS_STRING_PREAMBLE (str);
00998   
00999   if (!align_length_then_lengthen (str, 8, 8))
01000     return FALSE;
01001 
01002   ASSIGN_8_OCTETS (real->str + (real->len - 8), octets);
01003 
01004   return TRUE;
01005 }
01006 #endif /* DBUS_BUILD_TESTS */
01007 
01017 dbus_bool_t
01018 _dbus_string_insert_2_aligned (DBusString         *str,
01019                                int                 insert_at,
01020                                const unsigned char octets[4])
01021 {
01022   DBUS_STRING_PREAMBLE (str);
01023   
01024   if (!align_insert_point_then_open_gap (str, &insert_at, 2, 2))
01025     return FALSE;
01026 
01027   ASSIGN_2_OCTETS (real->str + insert_at, octets);
01028 
01029   return TRUE;
01030 }
01031 
01041 dbus_bool_t
01042 _dbus_string_insert_4_aligned (DBusString         *str,
01043                                int                 insert_at,
01044                                const unsigned char octets[4])
01045 {
01046   DBUS_STRING_PREAMBLE (str);
01047   
01048   if (!align_insert_point_then_open_gap (str, &insert_at, 4, 4))
01049     return FALSE;
01050 
01051   ASSIGN_4_OCTETS (real->str + insert_at, octets);
01052 
01053   return TRUE;
01054 }
01055 
01065 dbus_bool_t
01066 _dbus_string_insert_8_aligned (DBusString         *str,
01067                                int                 insert_at,
01068                                const unsigned char octets[8])
01069 {
01070   DBUS_STRING_PREAMBLE (str);
01071   
01072   if (!align_insert_point_then_open_gap (str, &insert_at, 8, 8))
01073     return FALSE;
01074 
01075   _dbus_assert (_DBUS_ALIGN_VALUE (insert_at, 8) == (unsigned) insert_at);
01076   
01077   ASSIGN_8_OCTETS (real->str + insert_at, octets);
01078 
01079   return TRUE;
01080 }
01081 
01082 
01093 dbus_bool_t
01094 _dbus_string_insert_alignment (DBusString        *str,
01095                                int               *insert_at,
01096                                int                alignment)
01097 {
01098   DBUS_STRING_PREAMBLE (str);
01099   
01100   if (!align_insert_point_then_open_gap (str, insert_at, alignment, 0))
01101     return FALSE;
01102 
01103   _dbus_assert (_DBUS_ALIGN_VALUE (*insert_at, alignment) == (unsigned) *insert_at);
01104 
01105   return TRUE;
01106 }
01107 
01117 dbus_bool_t
01118 _dbus_string_append_printf_valist  (DBusString        *str,
01119                                     const char        *format,
01120                                     va_list            args)
01121 {
01122   int len;
01123   va_list args_copy;
01124 
01125   DBUS_STRING_PREAMBLE (str);
01126 
01127   DBUS_VA_COPY (args_copy, args);
01128 
01129   /* Measure the message length without terminating nul */
01130   len = _dbus_printf_string_upper_bound (format, args);
01131 
01132   if (len < 0)
01133     return FALSE;
01134 
01135   if (!_dbus_string_lengthen (str, len))
01136     {
01137       /* don't leak the copy */
01138       va_end (args_copy);
01139       return FALSE;
01140     }
01141   
01142   vsprintf ((char*) (real->str + (real->len - len)),
01143             format, args_copy);
01144 
01145   va_end (args_copy);
01146 
01147   return TRUE;
01148 }
01149 
01158 dbus_bool_t
01159 _dbus_string_append_printf (DBusString        *str,
01160                             const char        *format,
01161                             ...)
01162 {
01163   va_list args;
01164   dbus_bool_t retval;
01165   
01166   va_start (args, format);
01167   retval = _dbus_string_append_printf_valist (str, format, args);
01168   va_end (args);
01169 
01170   return retval;
01171 }
01172 
01181 dbus_bool_t
01182 _dbus_string_append_len (DBusString *str,
01183                          const char *buffer,
01184                          int         len)
01185 {
01186   DBUS_STRING_PREAMBLE (str);
01187   _dbus_assert (buffer != NULL);
01188   _dbus_assert (len >= 0);
01189 
01190   return append (real, buffer, len);
01191 }
01192 
01201 dbus_bool_t
01202 _dbus_string_append_byte (DBusString    *str,
01203                           unsigned char  byte)
01204 {
01205   DBUS_STRING_PREAMBLE (str);
01206 
01207   if (!set_length (real, real->len + 1))
01208     return FALSE;
01209 
01210   real->str[real->len-1] = byte;
01211 
01212   return TRUE;
01213 }
01214 
01215 #ifdef DBUS_BUILD_TESTS
01216 
01223 dbus_bool_t
01224 _dbus_string_append_unichar (DBusString    *str,
01225                              dbus_unichar_t ch)
01226 {
01227   int len;
01228   int first;
01229   int i;
01230   unsigned char *out;
01231   
01232   DBUS_STRING_PREAMBLE (str);
01233 
01234   /* this code is from GLib but is pretty standard I think */
01235   
01236   len = 0;
01237   
01238   if (ch < 0x80)
01239     {
01240       first = 0;
01241       len = 1;
01242     }
01243   else if (ch < 0x800)
01244     {
01245       first = 0xc0;
01246       len = 2;
01247     }
01248   else if (ch < 0x10000)
01249     {
01250       first = 0xe0;
01251       len = 3;
01252     }
01253    else if (ch < 0x200000)
01254     {
01255       first = 0xf0;
01256       len = 4;
01257     }
01258   else if (ch < 0x4000000)
01259     {
01260       first = 0xf8;
01261       len = 5;
01262     }
01263   else
01264     {
01265       first = 0xfc;
01266       len = 6;
01267     }
01268 
01269   if (len > (_DBUS_STRING_MAX_LENGTH - real->len))
01270     return FALSE; /* real->len + len would overflow */
01271   
01272   if (!set_length (real, real->len + len))
01273     return FALSE;
01274 
01275   out = real->str + (real->len - len);
01276   
01277   for (i = len - 1; i > 0; --i)
01278     {
01279       out[i] = (ch & 0x3f) | 0x80;
01280       ch >>= 6;
01281     }
01282   out[0] = ch | first;
01283 
01284   return TRUE;
01285 }
01286 #endif /* DBUS_BUILD_TESTS */
01287 
01288 static void
01289 delete (DBusRealString *real,
01290         int             start,
01291         int             len)
01292 {
01293   if (len == 0)
01294     return;
01295   
01296   memmove (real->str + start, real->str + start + len, real->len - (start + len));
01297   real->len -= len;
01298   real->str[real->len] = '\0';
01299 }
01300 
01310 void
01311 _dbus_string_delete (DBusString       *str,
01312                      int               start,
01313                      int               len)
01314 {
01315   DBUS_STRING_PREAMBLE (str);
01316   _dbus_assert (start >= 0);
01317   _dbus_assert (len >= 0);
01318   _dbus_assert (start <= real->len);
01319   _dbus_assert (len <= real->len - start);
01320   
01321   delete (real, start, len);
01322 }
01323 
01324 static dbus_bool_t
01325 copy (DBusRealString *source,
01326       int             start,
01327       int             len,
01328       DBusRealString *dest,
01329       int             insert_at)
01330 {
01331   if (len == 0)
01332     return TRUE;
01333 
01334   if (!open_gap (len, dest, insert_at))
01335     return FALSE;
01336   
01337   memmove (dest->str + insert_at,
01338            source->str + start,
01339            len);
01340 
01341   return TRUE;
01342 }
01343 
01353 #define DBUS_STRING_COPY_PREAMBLE(source, start, dest, insert_at)       \
01354   DBusRealString *real_source = (DBusRealString*) source;               \
01355   DBusRealString *real_dest = (DBusRealString*) dest;                   \
01356   _dbus_assert ((source) != (dest));                                    \
01357   DBUS_GENERIC_STRING_PREAMBLE (real_source);                           \
01358   DBUS_GENERIC_STRING_PREAMBLE (real_dest);                             \
01359   _dbus_assert (!real_dest->constant);                                  \
01360   _dbus_assert (!real_dest->locked);                                    \
01361   _dbus_assert ((start) >= 0);                                          \
01362   _dbus_assert ((start) <= real_source->len);                           \
01363   _dbus_assert ((insert_at) >= 0);                                      \
01364   _dbus_assert ((insert_at) <= real_dest->len)
01365 
01376 dbus_bool_t
01377 _dbus_string_move (DBusString       *source,
01378                    int               start,
01379                    DBusString       *dest,
01380                    int               insert_at)
01381 {
01382   DBusRealString *real_source = (DBusRealString*) source;
01383   _dbus_assert (start <= real_source->len);
01384   
01385   return _dbus_string_move_len (source, start,
01386                                 real_source->len - start,
01387                                 dest, insert_at);
01388 }
01389 
01400 dbus_bool_t
01401 _dbus_string_copy (const DBusString *source,
01402                    int               start,
01403                    DBusString       *dest,
01404                    int               insert_at)
01405 {
01406   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
01407 
01408   return copy (real_source, start,
01409                real_source->len - start,
01410                real_dest,
01411                insert_at);
01412 }
01413 
01425 dbus_bool_t
01426 _dbus_string_move_len (DBusString       *source,
01427                        int               start,
01428                        int               len,
01429                        DBusString       *dest,
01430                        int               insert_at)
01431 
01432 {
01433   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
01434   _dbus_assert (len >= 0);
01435   _dbus_assert ((start + len) <= real_source->len);
01436 
01437 
01438   if (len == 0)
01439     {
01440       return TRUE;
01441     }
01442   else if (start == 0 &&
01443            len == real_source->len &&
01444            real_dest->len == 0)
01445     {
01446       /* Short-circuit moving an entire existing string to an empty string
01447        * by just swapping the buffers.
01448        */
01449       /* we assume ->constant doesn't matter as you can't have
01450        * a constant string involved in a move.
01451        */
01452 #define ASSIGN_DATA(a, b) do {                  \
01453         (a)->str = (b)->str;                    \
01454         (a)->len = (b)->len;                    \
01455         (a)->allocated = (b)->allocated;        \
01456         (a)->align_offset = (b)->align_offset;  \
01457       } while (0)
01458       
01459       DBusRealString tmp;
01460 
01461       ASSIGN_DATA (&tmp, real_source);
01462       ASSIGN_DATA (real_source, real_dest);
01463       ASSIGN_DATA (real_dest, &tmp);
01464 
01465       return TRUE;
01466     }
01467   else
01468     {
01469       if (!copy (real_source, start, len,
01470                  real_dest,
01471                  insert_at))
01472         return FALSE;
01473       
01474       delete (real_source, start,
01475               len);
01476       
01477       return TRUE;
01478     }
01479 }
01480 
01492 dbus_bool_t
01493 _dbus_string_copy_len (const DBusString *source,
01494                        int               start,
01495                        int               len,
01496                        DBusString       *dest,
01497                        int               insert_at)
01498 {
01499   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
01500   _dbus_assert (len >= 0);
01501   _dbus_assert (start <= real_source->len);
01502   _dbus_assert (len <= real_source->len - start);
01503   
01504   return copy (real_source, start, len,
01505                real_dest,
01506                insert_at);
01507 }
01508 
01521 dbus_bool_t
01522 _dbus_string_replace_len (const DBusString *source,
01523                           int               start,
01524                           int               len,
01525                           DBusString       *dest,
01526                           int               replace_at,
01527                           int               replace_len)
01528 {
01529   DBUS_STRING_COPY_PREAMBLE (source, start, dest, replace_at);
01530   _dbus_assert (len >= 0);
01531   _dbus_assert (start <= real_source->len);
01532   _dbus_assert (len <= real_source->len - start);
01533   _dbus_assert (replace_at >= 0);
01534   _dbus_assert (replace_at <= real_dest->len);
01535   _dbus_assert (replace_len <= real_dest->len - replace_at);
01536 
01537   if (len == replace_len)
01538     {
01539       memmove (real_dest->str + replace_at,
01540                real_source->str + start, len);
01541     }
01542   else if (len < replace_len)
01543     {
01544       memmove (real_dest->str + replace_at,
01545                real_source->str + start, len);
01546       delete (real_dest, replace_at + len,
01547               replace_len - len);
01548     }
01549   else
01550     {
01551       int diff;
01552 
01553       _dbus_assert (len > replace_len);
01554 
01555       diff = len - replace_len;
01556 
01557       /* First of all we check if destination string can be enlarged as
01558        * required, then we overwrite previous bytes
01559        */
01560 
01561       if (!copy (real_source, start + replace_len, diff,
01562                  real_dest, replace_at + replace_len))
01563         return FALSE;
01564 
01565       memmove (real_dest->str + replace_at,
01566                real_source->str + start, replace_len);
01567     }
01568 
01569   return TRUE;
01570 }
01571 
01584 dbus_bool_t
01585 _dbus_string_split_on_byte (DBusString        *source,
01586                             unsigned char      byte,
01587                             DBusString        *tail)
01588 {
01589   int byte_position;
01590   char byte_string[2] = "";
01591   int head_length;
01592   int tail_length;
01593 
01594   byte_string[0] = (char) byte;
01595 
01596   if (!_dbus_string_find (source, 0, byte_string, &byte_position))
01597     return FALSE;
01598 
01599   head_length = byte_position;
01600   tail_length = _dbus_string_get_length (source) - head_length - 1;
01601 
01602   if (!_dbus_string_move_len (source, byte_position + 1, tail_length,
01603                               tail, 0))
01604     return FALSE;
01605 
01606   /* remove the trailing delimiter byte from the head now.
01607    */
01608   if (!_dbus_string_set_length (source, head_length))
01609     return FALSE;
01610 
01611   return TRUE;
01612 }
01613 
01614 /* Unicode macros and utf8_validate() from GLib Owen Taylor, Havoc
01615  * Pennington, and Tom Tromey are the authors and authorized relicense.
01616  */
01617 
01623 #define UTF8_COMPUTE(Char, Mask, Len)                                         \
01624   if (Char < 128)                                                             \
01625     {                                                                         \
01626       Len = 1;                                                                \
01627       Mask = 0x7f;                                                            \
01628     }                                                                         \
01629   else if ((Char & 0xe0) == 0xc0)                                             \
01630     {                                                                         \
01631       Len = 2;                                                                \
01632       Mask = 0x1f;                                                            \
01633     }                                                                         \
01634   else if ((Char & 0xf0) == 0xe0)                                             \
01635     {                                                                         \
01636       Len = 3;                                                                \
01637       Mask = 0x0f;                                                            \
01638     }                                                                         \
01639   else if ((Char & 0xf8) == 0xf0)                                             \
01640     {                                                                         \
01641       Len = 4;                                                                \
01642       Mask = 0x07;                                                            \
01643     }                                                                         \
01644   else if ((Char & 0xfc) == 0xf8)                                             \
01645     {                                                                         \
01646       Len = 5;                                                                \
01647       Mask = 0x03;                                                            \
01648     }                                                                         \
01649   else if ((Char & 0xfe) == 0xfc)                                             \
01650     {                                                                         \
01651       Len = 6;                                                                \
01652       Mask = 0x01;                                                            \
01653     }                                                                         \
01654   else                                                                        \
01655     {                                                                         \
01656       Len = 0;                                                               \
01657       Mask = 0;                                                               \
01658     }
01659 
01664 #define UTF8_LENGTH(Char)              \
01665   ((Char) < 0x80 ? 1 :                 \
01666    ((Char) < 0x800 ? 2 :               \
01667     ((Char) < 0x10000 ? 3 :            \
01668      ((Char) < 0x200000 ? 4 :          \
01669       ((Char) < 0x4000000 ? 5 : 6)))))
01670    
01680 #define UTF8_GET(Result, Chars, Count, Mask, Len)                             \
01681   (Result) = (Chars)[0] & (Mask);                                             \
01682   for ((Count) = 1; (Count) < (Len); ++(Count))                               \
01683     {                                                                         \
01684       if (((Chars)[(Count)] & 0xc0) != 0x80)                                  \
01685         {                                                                     \
01686           (Result) = -1;                                                      \
01687           break;                                                              \
01688         }                                                                     \
01689       (Result) <<= 6;                                                         \
01690       (Result) |= ((Chars)[(Count)] & 0x3f);                                  \
01691     }
01692 
01709 #define UNICODE_VALID(Char)                   \
01710     ((Char) < 0x110000 &&                     \
01711      (((Char) & 0xFFFFF800) != 0xD800) &&     \
01712      ((Char) < 0xFDD0 || (Char) > 0xFDEF) &&  \
01713      ((Char) & 0xFFFE) != 0xFFFE)
01714 
01715 #ifdef DBUS_BUILD_TESTS
01716 
01726 void
01727 _dbus_string_get_unichar (const DBusString *str,
01728                           int               start,
01729                           dbus_unichar_t   *ch_return,
01730                           int              *end_return)
01731 {
01732   int i, mask, len;
01733   dbus_unichar_t result;
01734   unsigned char c;
01735   unsigned char *p;
01736   DBUS_CONST_STRING_PREAMBLE (str);
01737   _dbus_assert (start >= 0);
01738   _dbus_assert (start <= real->len);
01739   
01740   if (ch_return)
01741     *ch_return = 0;
01742   if (end_return)
01743     *end_return = real->len;
01744   
01745   mask = 0;
01746   p = real->str + start;
01747   c = *p;
01748   
01749   UTF8_COMPUTE (c, mask, len);
01750   if (len == 0)
01751     return;
01752   UTF8_GET (result, p, i, mask, len);
01753 
01754   if (result == (dbus_unichar_t)-1)
01755     return;
01756 
01757   if (ch_return)
01758     *ch_return = result;
01759   if (end_return)
01760     *end_return = start + len;
01761 }
01762 #endif /* DBUS_BUILD_TESTS */
01763 
01778 dbus_bool_t
01779 _dbus_string_find (const DBusString *str,
01780                    int               start,
01781                    const char       *substr,
01782                    int              *found)
01783 {
01784   return _dbus_string_find_to (str, start,
01785                                ((const DBusRealString*)str)->len,
01786                                substr, found);
01787 }
01788 
01801 dbus_bool_t
01802 _dbus_string_find_eol (const DBusString *str,
01803                        int               start,
01804                        int              *found,
01805                        int              *found_len)
01806 {
01807   int i;
01808 
01809   DBUS_CONST_STRING_PREAMBLE (str);
01810   _dbus_assert (start <= real->len);
01811   _dbus_assert (start >= 0);
01812   
01813   i = start;
01814   while (i < real->len)
01815     {
01816       if (real->str[i] == '\r') 
01817         {
01818           if ((i+1) < real->len && real->str[i+1] == '\n') /* "\r\n" */
01819             {
01820               if (found) 
01821                 *found = i;
01822               if (found_len)
01823                 *found_len = 2;
01824               return TRUE;
01825             } 
01826           else /* only "\r" */
01827             {
01828               if (found) 
01829                 *found = i;
01830               if (found_len)
01831                 *found_len = 1;
01832               return TRUE;
01833             }
01834         } 
01835       else if (real->str[i] == '\n')  /* only "\n" */
01836         {
01837           if (found) 
01838             *found = i;
01839           if (found_len)
01840             *found_len = 1;
01841           return TRUE;
01842         }
01843       ++i;
01844     }
01845 
01846   if (found)
01847     *found = real->len;
01848 
01849   if (found_len)
01850     *found_len = 0;
01851   
01852   return FALSE;
01853 }
01854 
01871 dbus_bool_t
01872 _dbus_string_find_to (const DBusString *str,
01873                       int               start,
01874                       int               end,
01875                       const char       *substr,
01876                       int              *found)
01877 {
01878   int i;
01879   DBUS_CONST_STRING_PREAMBLE (str);
01880   _dbus_assert (substr != NULL);
01881   _dbus_assert (start <= real->len);
01882   _dbus_assert (start >= 0);
01883   _dbus_assert (substr != NULL);
01884   _dbus_assert (end <= real->len);
01885   _dbus_assert (start <= end);
01886 
01887   /* we always "find" an empty string */
01888   if (*substr == '\0')
01889     {
01890       if (found)
01891         *found = start;
01892       return TRUE;
01893     }
01894 
01895   i = start;
01896   while (i < end)
01897     {
01898       if (real->str[i] == substr[0])
01899         {
01900           int j = i + 1;
01901           
01902           while (j < end)
01903             {
01904               if (substr[j - i] == '\0')
01905                 break;
01906               else if (real->str[j] != substr[j - i])
01907                 break;
01908               
01909               ++j;
01910             }
01911 
01912           if (substr[j - i] == '\0')
01913             {
01914               if (found)
01915                 *found = i;
01916               return TRUE;
01917             }
01918         }
01919       
01920       ++i;
01921     }
01922 
01923   if (found)
01924     *found = end;
01925   
01926   return FALSE;  
01927 }
01928 
01939 dbus_bool_t
01940 _dbus_string_find_blank (const DBusString *str,
01941                          int               start,
01942                          int              *found)
01943 {
01944   int i;
01945   DBUS_CONST_STRING_PREAMBLE (str);
01946   _dbus_assert (start <= real->len);
01947   _dbus_assert (start >= 0);
01948   
01949   i = start;
01950   while (i < real->len)
01951     {
01952       if (real->str[i] == ' ' ||
01953           real->str[i] == '\t')
01954         {
01955           if (found)
01956             *found = i;
01957           return TRUE;
01958         }
01959       
01960       ++i;
01961     }
01962 
01963   if (found)
01964     *found = real->len;
01965   
01966   return FALSE;
01967 }
01968 
01977 void
01978 _dbus_string_skip_blank (const DBusString *str,
01979                          int               start,
01980                          int              *end)
01981 {
01982   int i;
01983   DBUS_CONST_STRING_PREAMBLE (str);
01984   _dbus_assert (start <= real->len);
01985   _dbus_assert (start >= 0);
01986   
01987   i = start;
01988   while (i < real->len)
01989     {
01990       if (!DBUS_IS_ASCII_BLANK (real->str[i]))
01991         break;
01992       
01993       ++i;
01994     }
01995 
01996   _dbus_assert (i == real->len || !DBUS_IS_ASCII_WHITE (real->str[i]));
01997   
01998   if (end)
01999     *end = i;
02000 }
02001 
02002 
02011 void
02012 _dbus_string_skip_white (const DBusString *str,
02013                          int               start,
02014                          int              *end)
02015 {
02016   int i;
02017   DBUS_CONST_STRING_PREAMBLE (str);
02018   _dbus_assert (start <= real->len);
02019   _dbus_assert (start >= 0);
02020   
02021   i = start;
02022   while (i < real->len)
02023     {
02024       if (!DBUS_IS_ASCII_WHITE (real->str[i]))
02025         break;
02026       
02027       ++i;
02028     }
02029 
02030   _dbus_assert (i == real->len || !(DBUS_IS_ASCII_WHITE (real->str[i])));
02031   
02032   if (end)
02033     *end = i;
02034 }
02035 
02044 void
02045 _dbus_string_skip_white_reverse (const DBusString *str,
02046                                  int               end,
02047                                  int              *start)
02048 {
02049   int i;
02050   DBUS_CONST_STRING_PREAMBLE (str);
02051   _dbus_assert (end <= real->len);
02052   _dbus_assert (end >= 0);
02053   
02054   i = end;
02055   while (i > 0)
02056     {
02057       if (!DBUS_IS_ASCII_WHITE (real->str[i-1]))
02058         break;
02059       --i;
02060     }
02061 
02062   _dbus_assert (i >= 0 && (i == 0 || !(DBUS_IS_ASCII_WHITE (real->str[i-1]))));
02063   
02064   if (start)
02065     *start = i;
02066 }
02067 
02083 dbus_bool_t
02084 _dbus_string_pop_line (DBusString *source,
02085                        DBusString *dest)
02086 {
02087   int eol, eol_len;
02088   
02089   _dbus_string_set_length (dest, 0);
02090   
02091   eol = 0;
02092   eol_len = 0;
02093   if (!_dbus_string_find_eol (source, 0, &eol, &eol_len))
02094     {
02095       _dbus_assert (eol == _dbus_string_get_length (source));
02096       if (eol == 0)
02097         {
02098           /* If there's no newline and source has zero length, we're done */
02099           return FALSE;
02100         }
02101       /* otherwise, the last line of the file has no eol characters */
02102     }
02103 
02104   /* remember eol can be 0 if it's an empty line, but eol_len should not be zero also
02105    * since find_eol returned TRUE
02106    */
02107   
02108   if (!_dbus_string_move_len (source, 0, eol + eol_len, dest, 0))
02109     return FALSE;
02110   
02111   /* remove line ending */
02112   if (!_dbus_string_set_length (dest, eol))
02113     {
02114       _dbus_assert_not_reached ("out of memory when shortening a string");
02115       return FALSE;
02116     }
02117 
02118   return TRUE;
02119 }
02120 
02121 #ifdef DBUS_BUILD_TESTS
02122 
02128 void
02129 _dbus_string_delete_first_word (DBusString *str)
02130 {
02131   int i;
02132   
02133   if (_dbus_string_find_blank (str, 0, &i))
02134     _dbus_string_skip_blank (str, i, &i);
02135 
02136   _dbus_string_delete (str, 0, i);
02137 }
02138 #endif
02139 
02140 #ifdef DBUS_BUILD_TESTS
02141 
02146 void
02147 _dbus_string_delete_leading_blanks (DBusString *str)
02148 {
02149   int i;
02150   
02151   _dbus_string_skip_blank (str, 0, &i);
02152 
02153   if (i > 0)
02154     _dbus_string_delete (str, 0, i);
02155 }
02156 #endif
02157 
02163 void
02164 _dbus_string_chop_white(DBusString *str)
02165 {
02166   int i;
02167   
02168   _dbus_string_skip_white (str, 0, &i);
02169 
02170   if (i > 0)
02171     _dbus_string_delete (str, 0, i);
02172   
02173   _dbus_string_skip_white_reverse (str, _dbus_string_get_length (str), &i);
02174 
02175   _dbus_string_set_length (str, i);
02176 }
02177 
02187 dbus_bool_t
02188 _dbus_string_equal (const DBusString *a,
02189                     const DBusString *b)
02190 {
02191   const unsigned char *ap;
02192   const unsigned char *bp;
02193   const unsigned char *a_end;
02194   const DBusRealString *real_a = (const DBusRealString*) a;
02195   const DBusRealString *real_b = (const DBusRealString*) b;
02196   DBUS_GENERIC_STRING_PREAMBLE (real_a);
02197   DBUS_GENERIC_STRING_PREAMBLE (real_b);
02198 
02199   if (real_a->len != real_b->len)
02200     return FALSE;
02201 
02202   ap = real_a->str;
02203   bp = real_b->str;
02204   a_end = real_a->str + real_a->len;
02205   while (ap != a_end)
02206     {
02207       if (*ap != *bp)
02208         return FALSE;
02209       
02210       ++ap;
02211       ++bp;
02212     }
02213 
02214   return TRUE;
02215 }
02216 
02230 dbus_bool_t
02231 _dbus_string_equal_len (const DBusString *a,
02232                         const DBusString *b,
02233                         int               len)
02234 {
02235   const unsigned char *ap;
02236   const unsigned char *bp;
02237   const unsigned char *a_end;
02238   const DBusRealString *real_a = (const DBusRealString*) a;
02239   const DBusRealString *real_b = (const DBusRealString*) b;
02240   DBUS_GENERIC_STRING_PREAMBLE (real_a);
02241   DBUS_GENERIC_STRING_PREAMBLE (real_b);
02242 
02243   if (real_a->len != real_b->len &&
02244       (real_a->len < len || real_b->len < len))
02245     return FALSE;
02246 
02247   ap = real_a->str;
02248   bp = real_b->str;
02249   a_end = real_a->str + MIN (real_a->len, len);
02250   while (ap != a_end)
02251     {
02252       if (*ap != *bp)
02253         return FALSE;
02254       
02255       ++ap;
02256       ++bp;
02257     }
02258 
02259   return TRUE;
02260 }
02261 
02278 dbus_bool_t
02279 _dbus_string_equal_substring (const DBusString  *a,
02280                               int                a_start,
02281                               int                a_len,
02282                               const DBusString  *b,
02283                               int                b_start)
02284 {
02285   const unsigned char *ap;
02286   const unsigned char *bp;
02287   const unsigned char *a_end;
02288   const DBusRealString *real_a = (const DBusRealString*) a;
02289   const DBusRealString *real_b = (const DBusRealString*) b;
02290   DBUS_GENERIC_STRING_PREAMBLE (real_a);
02291   DBUS_GENERIC_STRING_PREAMBLE (real_b);
02292   _dbus_assert (a_start >= 0);
02293   _dbus_assert (a_len >= 0);
02294   _dbus_assert (a_start <= real_a->len);
02295   _dbus_assert (a_len <= real_a->len - a_start);
02296   _dbus_assert (b_start >= 0);
02297   _dbus_assert (b_start <= real_b->len);
02298   
02299   if (a_len > real_b->len - b_start)
02300     return FALSE;
02301 
02302   ap = real_a->str + a_start;
02303   bp = real_b->str + b_start;
02304   a_end = ap + a_len;
02305   while (ap != a_end)
02306     {
02307       if (*ap != *bp)
02308         return FALSE;
02309       
02310       ++ap;
02311       ++bp;
02312     }
02313 
02314   _dbus_assert (bp <= (real_b->str + real_b->len));
02315   
02316   return TRUE;
02317 }
02318 
02326 dbus_bool_t
02327 _dbus_string_equal_c_str (const DBusString *a,
02328                           const char       *c_str)
02329 {
02330   const unsigned char *ap;
02331   const unsigned char *bp;
02332   const unsigned char *a_end;
02333   const DBusRealString *real_a = (const DBusRealString*) a;
02334   DBUS_GENERIC_STRING_PREAMBLE (real_a);
02335   _dbus_assert (c_str != NULL);
02336   
02337   ap = real_a->str;
02338   bp = (const unsigned char*) c_str;
02339   a_end = real_a->str + real_a->len;
02340   while (ap != a_end && *bp)
02341     {
02342       if (*ap != *bp)
02343         return FALSE;
02344       
02345       ++ap;
02346       ++bp;
02347     }
02348 
02349   if (ap != a_end || *bp)
02350     return FALSE;
02351   
02352   return TRUE;
02353 }
02354 
02355 #ifdef DBUS_BUILD_TESTS
02356 
02363 dbus_bool_t
02364 _dbus_string_starts_with_c_str (const DBusString *a,
02365                                 const char       *c_str)
02366 {
02367   const unsigned char *ap;
02368   const unsigned char *bp;
02369   const unsigned char *a_end;
02370   const DBusRealString *real_a = (const DBusRealString*) a;
02371   DBUS_GENERIC_STRING_PREAMBLE (real_a);
02372   _dbus_assert (c_str != NULL);
02373   
02374   ap = real_a->str;
02375   bp = (const unsigned char*) c_str;
02376   a_end = real_a->str + real_a->len;
02377   while (ap != a_end && *bp)
02378     {
02379       if (*ap != *bp)
02380         return FALSE;
02381       
02382       ++ap;
02383       ++bp;
02384     }
02385 
02386   if (*bp == '\0')
02387     return TRUE;
02388   else
02389     return FALSE;
02390 }
02391 #endif /* DBUS_BUILD_TESTS */
02392 
02401 dbus_bool_t
02402 _dbus_string_append_byte_as_hex (DBusString *str,
02403                                  int         byte)
02404 {
02405   const char hexdigits[16] = {
02406     '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
02407     'a', 'b', 'c', 'd', 'e', 'f'
02408   };
02409 
02410   if (!_dbus_string_append_byte (str,
02411                                  hexdigits[(byte >> 4)]))
02412     return FALSE;
02413   
02414   if (!_dbus_string_append_byte (str,
02415                                  hexdigits[(byte & 0x0f)]))
02416     {
02417       _dbus_string_set_length (str,
02418                                _dbus_string_get_length (str) - 1);
02419       return FALSE;
02420     }
02421 
02422   return TRUE;
02423 }
02424 
02435 dbus_bool_t
02436 _dbus_string_hex_encode (const DBusString *source,
02437                          int               start,
02438                          DBusString       *dest,
02439                          int               insert_at)
02440 {
02441   DBusString result;
02442   const unsigned char *p;
02443   const unsigned char *end;
02444   dbus_bool_t retval;
02445   
02446   _dbus_assert (start <= _dbus_string_get_length (source));
02447 
02448   if (!_dbus_string_init (&result))
02449     return FALSE;
02450 
02451   retval = FALSE;
02452   
02453   p = (const unsigned char*) _dbus_string_get_const_data (source);
02454   end = p + _dbus_string_get_length (source);
02455   p += start;
02456   
02457   while (p != end)
02458     {
02459       if (!_dbus_string_append_byte_as_hex (&result, *p))
02460         goto out;
02461       
02462       ++p;
02463     }
02464 
02465   if (!_dbus_string_move (&result, 0, dest, insert_at))
02466     goto out;
02467 
02468   retval = TRUE;
02469 
02470  out:
02471   _dbus_string_free (&result);
02472   return retval;
02473 }
02474 
02485 dbus_bool_t
02486 _dbus_string_hex_decode (const DBusString *source,
02487                          int               start,
02488                          int              *end_return,
02489                          DBusString       *dest,
02490                          int               insert_at)
02491 {
02492   DBusString result;
02493   const unsigned char *p;
02494   const unsigned char *end;
02495   dbus_bool_t retval;
02496   dbus_bool_t high_bits;
02497   
02498   _dbus_assert (start <= _dbus_string_get_length (source));
02499 
02500   if (!_dbus_string_init (&result))
02501     return FALSE;
02502 
02503   retval = FALSE;
02504 
02505   high_bits = TRUE;
02506   p = (const unsigned char*) _dbus_string_get_const_data (source);
02507   end = p + _dbus_string_get_length (source);
02508   p += start;
02509   
02510   while (p != end)
02511     {
02512       unsigned int val;
02513 
02514       switch (*p)
02515         {
02516         case '0':
02517           val = 0;
02518           break;
02519         case '1':
02520           val = 1;
02521           break;
02522         case '2':
02523           val = 2;
02524           break;
02525         case '3':
02526           val = 3;
02527           break;
02528         case '4':
02529           val = 4;
02530           break;
02531         case '5':
02532           val = 5;
02533           break;
02534         case '6':
02535           val = 6;
02536           break;
02537         case '7':
02538           val = 7;
02539           break;
02540         case '8':
02541           val = 8;
02542           break;
02543         case '9':
02544           val = 9;
02545           break;
02546         case 'a':
02547         case 'A':
02548           val = 10;
02549           break;
02550         case 'b':
02551         case 'B':
02552           val = 11;
02553           break;
02554         case 'c':
02555         case 'C':
02556           val = 12;
02557           break;
02558         case 'd':
02559         case 'D':
02560           val = 13;
02561           break;
02562         case 'e':
02563         case 'E':
02564           val = 14;
02565           break;
02566         case 'f':
02567         case 'F':
02568           val = 15;
02569           break;
02570         default:
02571           goto done;
02572         }
02573 
02574       if (high_bits)
02575         {
02576           if (!_dbus_string_append_byte (&result,
02577                                          val << 4))
02578             goto out;
02579         }
02580       else
02581         {
02582           int len;
02583           unsigned char b;
02584 
02585           len = _dbus_string_get_length (&result);
02586           
02587           b = _dbus_string_get_byte (&result, len - 1);
02588 
02589           b |= val;
02590 
02591           _dbus_string_set_byte (&result, len - 1, b);
02592         }
02593 
02594       high_bits = !high_bits;
02595 
02596       ++p;
02597     }
02598 
02599  done:
02600   if (!_dbus_string_move (&result, 0, dest, insert_at))
02601     goto out;
02602 
02603   if (end_return)
02604     *end_return = p - (const unsigned char*) _dbus_string_get_const_data (source);
02605 
02606   retval = TRUE;
02607   
02608  out:
02609   _dbus_string_free (&result);  
02610   return retval;
02611 }
02612 
02626 dbus_bool_t
02627 _dbus_string_validate_ascii (const DBusString *str,
02628                              int               start,
02629                              int               len)
02630 {
02631   const unsigned char *s;
02632   const unsigned char *end;
02633   DBUS_CONST_STRING_PREAMBLE (str);
02634   _dbus_assert (start >= 0);
02635   _dbus_assert (start <= real->len);
02636   _dbus_assert (len >= 0);
02637   
02638   if (len > real->len - start)
02639     return FALSE;
02640   
02641   s = real->str + start;
02642   end = s + len;
02643   while (s != end)
02644     {
02645       if (_DBUS_UNLIKELY (!_DBUS_ISASCII (*s)))
02646         return FALSE;
02647         
02648       ++s;
02649     }
02650   
02651   return TRUE;
02652 }
02653 
02661 void
02662 _dbus_string_tolower_ascii (const DBusString *str,
02663                             int               start,
02664                             int               len)
02665 {
02666   unsigned char *s;
02667   unsigned char *end;
02668   DBUS_STRING_PREAMBLE (str);
02669   _dbus_assert (start >= 0);
02670   _dbus_assert (start <= real->len);
02671   _dbus_assert (len >= 0);
02672   _dbus_assert (len <= real->len - start);
02673 
02674   s = real->str + start;
02675   end = s + len;
02676 
02677   while (s != end)
02678     {
02679       if (*s >= 'A' && *s <= 'Z')
02680           *s += 'a' - 'A';
02681       ++s;
02682     }
02683 }
02684 
02692 void
02693 _dbus_string_toupper_ascii (const DBusString *str,
02694                             int               start,
02695                             int               len)
02696 {
02697   unsigned char *s;
02698   unsigned char *end;
02699   DBUS_STRING_PREAMBLE (str);
02700   _dbus_assert (start >= 0);
02701   _dbus_assert (start <= real->len);
02702   _dbus_assert (len >= 0);
02703   _dbus_assert (len <= real->len - start);
02704 
02705   s = real->str + start;
02706   end = s + len;
02707 
02708   while (s != end)
02709     {
02710       if (*s >= 'a' && *s <= 'z')
02711           *s += 'A' - 'a';
02712       ++s;
02713     }
02714 }
02715 
02731 dbus_bool_t
02732 _dbus_string_validate_utf8  (const DBusString *str,
02733                              int               start,
02734                              int               len)
02735 {
02736   const unsigned char *p;
02737   const unsigned char *end;
02738   DBUS_CONST_STRING_PREAMBLE (str);
02739   _dbus_assert (start >= 0);
02740   _dbus_assert (start <= real->len);
02741   _dbus_assert (len >= 0);
02742 
02743   /* we are doing _DBUS_UNLIKELY() here which might be
02744    * dubious in a generic library like GLib, but in D-Bus
02745    * we know we're validating messages and that it would
02746    * only be evil/broken apps that would have invalid
02747    * UTF-8. Also, this function seems to be a performance
02748    * bottleneck in profiles.
02749    */
02750   
02751   if (_DBUS_UNLIKELY (len > real->len - start))
02752     return FALSE;
02753   
02754   p = real->str + start;
02755   end = p + len;
02756   
02757   while (p < end)
02758     {
02759       int i, mask, char_len;
02760       dbus_unichar_t result;
02761 
02762       /* nul bytes considered invalid */
02763       if (*p == '\0')
02764         break;
02765       
02766       /* Special-case ASCII; this makes us go a lot faster in
02767        * D-Bus profiles where we are typically validating
02768        * function names and such. We have to know that
02769        * all following checks will pass for ASCII though,
02770        * comments follow ...
02771        */      
02772       if (*p < 128)
02773         {
02774           ++p;
02775           continue;
02776         }
02777       
02778       UTF8_COMPUTE (*p, mask, char_len);
02779 
02780       if (_DBUS_UNLIKELY (char_len == 0))  /* ASCII: char_len == 1 */
02781         break;
02782 
02783       /* check that the expected number of bytes exists in the remaining length */
02784       if (_DBUS_UNLIKELY ((end - p) < char_len)) /* ASCII: p < end and char_len == 1 */
02785         break;
02786         
02787       UTF8_GET (result, p, i, mask, char_len);
02788 
02789       /* Check for overlong UTF-8 */
02790       if (_DBUS_UNLIKELY (UTF8_LENGTH (result) != char_len)) /* ASCII: UTF8_LENGTH == 1 */
02791         break;
02792 #if 0
02793       /* The UNICODE_VALID check below will catch this */
02794       if (_DBUS_UNLIKELY (result == (dbus_unichar_t)-1)) /* ASCII: result = ascii value */
02795         break;
02796 #endif
02797 
02798       if (_DBUS_UNLIKELY (!UNICODE_VALID (result))) /* ASCII: always valid */
02799         break;
02800 
02801       /* UNICODE_VALID should have caught it */
02802       _dbus_assert (result != (dbus_unichar_t)-1);
02803       
02804       p += char_len;
02805     }
02806 
02807   /* See that we covered the entire length if a length was
02808    * passed in
02809    */
02810   if (_DBUS_UNLIKELY (p != end))
02811     return FALSE;
02812   else
02813     return TRUE;
02814 }
02815 
02829 dbus_bool_t
02830 _dbus_string_validate_nul (const DBusString *str,
02831                            int               start,
02832                            int               len)
02833 {
02834   const unsigned char *s;
02835   const unsigned char *end;
02836   DBUS_CONST_STRING_PREAMBLE (str);
02837   _dbus_assert (start >= 0);
02838   _dbus_assert (len >= 0);
02839   _dbus_assert (start <= real->len);
02840   
02841   if (len > real->len - start)
02842     return FALSE;
02843   
02844   s = real->str + start;
02845   end = s + len;
02846   while (s != end)
02847     {
02848       if (_DBUS_UNLIKELY (*s != '\0'))
02849         return FALSE;
02850       ++s;
02851     }
02852   
02853   return TRUE;
02854 }
02855 
02861 void
02862 _dbus_string_zero (DBusString *str)
02863 {
02864   DBUS_STRING_PREAMBLE (str);
02865 
02866   memset (real->str - real->align_offset, '\0', real->allocated);
02867 }
02870 /* tests are in dbus-string-util.c */