D-Bus  1.6.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 
00969 dbus_bool_t
00970 _dbus_string_insert_2_aligned (DBusString         *str,
00971                                int                 insert_at,
00972                                const unsigned char octets[4])
00973 {
00974   DBUS_STRING_PREAMBLE (str);
00975   
00976   if (!align_insert_point_then_open_gap (str, &insert_at, 2, 2))
00977     return FALSE;
00978 
00979   ASSIGN_2_OCTETS (real->str + insert_at, octets);
00980 
00981   return TRUE;
00982 }
00983 
00993 dbus_bool_t
00994 _dbus_string_insert_4_aligned (DBusString         *str,
00995                                int                 insert_at,
00996                                const unsigned char octets[4])
00997 {
00998   DBUS_STRING_PREAMBLE (str);
00999   
01000   if (!align_insert_point_then_open_gap (str, &insert_at, 4, 4))
01001     return FALSE;
01002 
01003   ASSIGN_4_OCTETS (real->str + insert_at, octets);
01004 
01005   return TRUE;
01006 }
01007 
01017 dbus_bool_t
01018 _dbus_string_insert_8_aligned (DBusString         *str,
01019                                int                 insert_at,
01020                                const unsigned char octets[8])
01021 {
01022   DBUS_STRING_PREAMBLE (str);
01023   
01024   if (!align_insert_point_then_open_gap (str, &insert_at, 8, 8))
01025     return FALSE;
01026 
01027   _dbus_assert (_DBUS_ALIGN_VALUE (insert_at, 8) == (unsigned) insert_at);
01028   
01029   ASSIGN_8_OCTETS (real->str + insert_at, octets);
01030 
01031   return TRUE;
01032 }
01033 
01034 
01045 dbus_bool_t
01046 _dbus_string_insert_alignment (DBusString        *str,
01047                                int               *insert_at,
01048                                int                alignment)
01049 {
01050   DBUS_STRING_PREAMBLE (str);
01051   
01052   if (!align_insert_point_then_open_gap (str, insert_at, alignment, 0))
01053     return FALSE;
01054 
01055   _dbus_assert (_DBUS_ALIGN_VALUE (*insert_at, alignment) == (unsigned) *insert_at);
01056 
01057   return TRUE;
01058 }
01059 
01069 dbus_bool_t
01070 _dbus_string_append_printf_valist  (DBusString        *str,
01071                                     const char        *format,
01072                                     va_list            args)
01073 {
01074   int len;
01075   va_list args_copy;
01076 
01077   DBUS_STRING_PREAMBLE (str);
01078 
01079   DBUS_VA_COPY (args_copy, args);
01080 
01081   /* Measure the message length without terminating nul */
01082   len = _dbus_printf_string_upper_bound (format, args);
01083 
01084   if (len < 0)
01085     return FALSE;
01086 
01087   if (!_dbus_string_lengthen (str, len))
01088     {
01089       /* don't leak the copy */
01090       va_end (args_copy);
01091       return FALSE;
01092     }
01093   
01094   vsprintf ((char*) (real->str + (real->len - len)),
01095             format, args_copy);
01096 
01097   va_end (args_copy);
01098 
01099   return TRUE;
01100 }
01101 
01110 dbus_bool_t
01111 _dbus_string_append_printf (DBusString        *str,
01112                             const char        *format,
01113                             ...)
01114 {
01115   va_list args;
01116   dbus_bool_t retval;
01117   
01118   va_start (args, format);
01119   retval = _dbus_string_append_printf_valist (str, format, args);
01120   va_end (args);
01121 
01122   return retval;
01123 }
01124 
01133 dbus_bool_t
01134 _dbus_string_append_len (DBusString *str,
01135                          const char *buffer,
01136                          int         len)
01137 {
01138   DBUS_STRING_PREAMBLE (str);
01139   _dbus_assert (buffer != NULL);
01140   _dbus_assert (len >= 0);
01141 
01142   return append (real, buffer, len);
01143 }
01144 
01153 dbus_bool_t
01154 _dbus_string_append_byte (DBusString    *str,
01155                           unsigned char  byte)
01156 {
01157   DBUS_STRING_PREAMBLE (str);
01158 
01159   if (!set_length (real, real->len + 1))
01160     return FALSE;
01161 
01162   real->str[real->len-1] = byte;
01163 
01164   return TRUE;
01165 }
01166 
01167 static void
01168 delete (DBusRealString *real,
01169         int             start,
01170         int             len)
01171 {
01172   if (len == 0)
01173     return;
01174   
01175   memmove (real->str + start, real->str + start + len, real->len - (start + len));
01176   real->len -= len;
01177   real->str[real->len] = '\0';
01178 }
01179 
01189 void
01190 _dbus_string_delete (DBusString       *str,
01191                      int               start,
01192                      int               len)
01193 {
01194   DBUS_STRING_PREAMBLE (str);
01195   _dbus_assert (start >= 0);
01196   _dbus_assert (len >= 0);
01197   _dbus_assert (start <= real->len);
01198   _dbus_assert (len <= real->len - start);
01199   
01200   delete (real, start, len);
01201 }
01202 
01203 static dbus_bool_t
01204 copy (DBusRealString *source,
01205       int             start,
01206       int             len,
01207       DBusRealString *dest,
01208       int             insert_at)
01209 {
01210   if (len == 0)
01211     return TRUE;
01212 
01213   if (!open_gap (len, dest, insert_at))
01214     return FALSE;
01215   
01216   memmove (dest->str + insert_at,
01217            source->str + start,
01218            len);
01219 
01220   return TRUE;
01221 }
01222 
01232 #define DBUS_STRING_COPY_PREAMBLE(source, start, dest, insert_at)       \
01233   DBusRealString *real_source = (DBusRealString*) source;               \
01234   DBusRealString *real_dest = (DBusRealString*) dest;                   \
01235   _dbus_assert ((source) != (dest));                                    \
01236   DBUS_GENERIC_STRING_PREAMBLE (real_source);                           \
01237   DBUS_GENERIC_STRING_PREAMBLE (real_dest);                             \
01238   _dbus_assert (!real_dest->constant);                                  \
01239   _dbus_assert (!real_dest->locked);                                    \
01240   _dbus_assert ((start) >= 0);                                          \
01241   _dbus_assert ((start) <= real_source->len);                           \
01242   _dbus_assert ((insert_at) >= 0);                                      \
01243   _dbus_assert ((insert_at) <= real_dest->len)
01244 
01255 dbus_bool_t
01256 _dbus_string_move (DBusString       *source,
01257                    int               start,
01258                    DBusString       *dest,
01259                    int               insert_at)
01260 {
01261   DBusRealString *real_source = (DBusRealString*) source;
01262   _dbus_assert (start <= real_source->len);
01263   
01264   return _dbus_string_move_len (source, start,
01265                                 real_source->len - start,
01266                                 dest, insert_at);
01267 }
01268 
01279 dbus_bool_t
01280 _dbus_string_copy (const DBusString *source,
01281                    int               start,
01282                    DBusString       *dest,
01283                    int               insert_at)
01284 {
01285   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
01286 
01287   return copy (real_source, start,
01288                real_source->len - start,
01289                real_dest,
01290                insert_at);
01291 }
01292 
01304 dbus_bool_t
01305 _dbus_string_move_len (DBusString       *source,
01306                        int               start,
01307                        int               len,
01308                        DBusString       *dest,
01309                        int               insert_at)
01310 
01311 {
01312   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
01313   _dbus_assert (len >= 0);
01314   _dbus_assert ((start + len) <= real_source->len);
01315 
01316 
01317   if (len == 0)
01318     {
01319       return TRUE;
01320     }
01321   else if (start == 0 &&
01322            len == real_source->len &&
01323            real_dest->len == 0)
01324     {
01325       /* Short-circuit moving an entire existing string to an empty string
01326        * by just swapping the buffers.
01327        */
01328       /* we assume ->constant doesn't matter as you can't have
01329        * a constant string involved in a move.
01330        */
01331 #define ASSIGN_DATA(a, b) do {                  \
01332         (a)->str = (b)->str;                    \
01333         (a)->len = (b)->len;                    \
01334         (a)->allocated = (b)->allocated;        \
01335         (a)->align_offset = (b)->align_offset;  \
01336       } while (0)
01337       
01338       DBusRealString tmp;
01339 
01340       ASSIGN_DATA (&tmp, real_source);
01341       ASSIGN_DATA (real_source, real_dest);
01342       ASSIGN_DATA (real_dest, &tmp);
01343 
01344       return TRUE;
01345     }
01346   else
01347     {
01348       if (!copy (real_source, start, len,
01349                  real_dest,
01350                  insert_at))
01351         return FALSE;
01352       
01353       delete (real_source, start,
01354               len);
01355       
01356       return TRUE;
01357     }
01358 }
01359 
01371 dbus_bool_t
01372 _dbus_string_copy_len (const DBusString *source,
01373                        int               start,
01374                        int               len,
01375                        DBusString       *dest,
01376                        int               insert_at)
01377 {
01378   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
01379   _dbus_assert (len >= 0);
01380   _dbus_assert (start <= real_source->len);
01381   _dbus_assert (len <= real_source->len - start);
01382   
01383   return copy (real_source, start, len,
01384                real_dest,
01385                insert_at);
01386 }
01387 
01400 dbus_bool_t
01401 _dbus_string_replace_len (const DBusString *source,
01402                           int               start,
01403                           int               len,
01404                           DBusString       *dest,
01405                           int               replace_at,
01406                           int               replace_len)
01407 {
01408   DBUS_STRING_COPY_PREAMBLE (source, start, dest, replace_at);
01409   _dbus_assert (len >= 0);
01410   _dbus_assert (start <= real_source->len);
01411   _dbus_assert (len <= real_source->len - start);
01412   _dbus_assert (replace_at >= 0);
01413   _dbus_assert (replace_at <= real_dest->len);
01414   _dbus_assert (replace_len <= real_dest->len - replace_at);
01415 
01416   if (len == replace_len)
01417     {
01418       memmove (real_dest->str + replace_at,
01419                real_source->str + start, len);
01420     }
01421   else if (len < replace_len)
01422     {
01423       memmove (real_dest->str + replace_at,
01424                real_source->str + start, len);
01425       delete (real_dest, replace_at + len,
01426               replace_len - len);
01427     }
01428   else
01429     {
01430       int diff;
01431 
01432       _dbus_assert (len > replace_len);
01433 
01434       diff = len - replace_len;
01435 
01436       /* First of all we check if destination string can be enlarged as
01437        * required, then we overwrite previous bytes
01438        */
01439 
01440       if (!copy (real_source, start + replace_len, diff,
01441                  real_dest, replace_at + replace_len))
01442         return FALSE;
01443 
01444       memmove (real_dest->str + replace_at,
01445                real_source->str + start, replace_len);
01446     }
01447 
01448   return TRUE;
01449 }
01450 
01463 dbus_bool_t
01464 _dbus_string_split_on_byte (DBusString        *source,
01465                             unsigned char      byte,
01466                             DBusString        *tail)
01467 {
01468   int byte_position;
01469   char byte_string[2] = "";
01470   int head_length;
01471   int tail_length;
01472 
01473   byte_string[0] = (char) byte;
01474 
01475   if (!_dbus_string_find (source, 0, byte_string, &byte_position))
01476     return FALSE;
01477 
01478   head_length = byte_position;
01479   tail_length = _dbus_string_get_length (source) - head_length - 1;
01480 
01481   if (!_dbus_string_move_len (source, byte_position + 1, tail_length,
01482                               tail, 0))
01483     return FALSE;
01484 
01485   /* remove the trailing delimiter byte from the head now.
01486    */
01487   if (!_dbus_string_set_length (source, head_length))
01488     return FALSE;
01489 
01490   return TRUE;
01491 }
01492 
01493 /* Unicode macros and utf8_validate() from GLib Owen Taylor, Havoc
01494  * Pennington, and Tom Tromey are the authors and authorized relicense.
01495  */
01496 
01502 #define UTF8_COMPUTE(Char, Mask, Len)                                         \
01503   if (Char < 128)                                                             \
01504     {                                                                         \
01505       Len = 1;                                                                \
01506       Mask = 0x7f;                                                            \
01507     }                                                                         \
01508   else if ((Char & 0xe0) == 0xc0)                                             \
01509     {                                                                         \
01510       Len = 2;                                                                \
01511       Mask = 0x1f;                                                            \
01512     }                                                                         \
01513   else if ((Char & 0xf0) == 0xe0)                                             \
01514     {                                                                         \
01515       Len = 3;                                                                \
01516       Mask = 0x0f;                                                            \
01517     }                                                                         \
01518   else if ((Char & 0xf8) == 0xf0)                                             \
01519     {                                                                         \
01520       Len = 4;                                                                \
01521       Mask = 0x07;                                                            \
01522     }                                                                         \
01523   else if ((Char & 0xfc) == 0xf8)                                             \
01524     {                                                                         \
01525       Len = 5;                                                                \
01526       Mask = 0x03;                                                            \
01527     }                                                                         \
01528   else if ((Char & 0xfe) == 0xfc)                                             \
01529     {                                                                         \
01530       Len = 6;                                                                \
01531       Mask = 0x01;                                                            \
01532     }                                                                         \
01533   else                                                                        \
01534     {                                                                         \
01535       Len = 0;                                                               \
01536       Mask = 0;                                                               \
01537     }
01538 
01543 #define UTF8_LENGTH(Char)              \
01544   ((Char) < 0x80 ? 1 :                 \
01545    ((Char) < 0x800 ? 2 :               \
01546     ((Char) < 0x10000 ? 3 :            \
01547      ((Char) < 0x200000 ? 4 :          \
01548       ((Char) < 0x4000000 ? 5 : 6)))))
01549    
01559 #define UTF8_GET(Result, Chars, Count, Mask, Len)                             \
01560   (Result) = (Chars)[0] & (Mask);                                             \
01561   for ((Count) = 1; (Count) < (Len); ++(Count))                               \
01562     {                                                                         \
01563       if (((Chars)[(Count)] & 0xc0) != 0x80)                                  \
01564         {                                                                     \
01565           (Result) = -1;                                                      \
01566           break;                                                              \
01567         }                                                                     \
01568       (Result) <<= 6;                                                         \
01569       (Result) |= ((Chars)[(Count)] & 0x3f);                                  \
01570     }
01571 
01588 #define UNICODE_VALID(Char)                   \
01589     ((Char) < 0x110000 &&                     \
01590      (((Char) & 0xFFFFF800) != 0xD800) &&     \
01591      ((Char) < 0xFDD0 || (Char) > 0xFDEF) &&  \
01592      ((Char) & 0xFFFE) != 0xFFFE)
01593 
01608 dbus_bool_t
01609 _dbus_string_find (const DBusString *str,
01610                    int               start,
01611                    const char       *substr,
01612                    int              *found)
01613 {
01614   return _dbus_string_find_to (str, start,
01615                                ((const DBusRealString*)str)->len,
01616                                substr, found);
01617 }
01618 
01631 dbus_bool_t
01632 _dbus_string_find_eol (const DBusString *str,
01633                        int               start,
01634                        int              *found,
01635                        int              *found_len)
01636 {
01637   int i;
01638 
01639   DBUS_CONST_STRING_PREAMBLE (str);
01640   _dbus_assert (start <= real->len);
01641   _dbus_assert (start >= 0);
01642   
01643   i = start;
01644   while (i < real->len)
01645     {
01646       if (real->str[i] == '\r') 
01647         {
01648           if ((i+1) < real->len && real->str[i+1] == '\n') /* "\r\n" */
01649             {
01650               if (found) 
01651                 *found = i;
01652               if (found_len)
01653                 *found_len = 2;
01654               return TRUE;
01655             } 
01656           else /* only "\r" */
01657             {
01658               if (found) 
01659                 *found = i;
01660               if (found_len)
01661                 *found_len = 1;
01662               return TRUE;
01663             }
01664         } 
01665       else if (real->str[i] == '\n')  /* only "\n" */
01666         {
01667           if (found) 
01668             *found = i;
01669           if (found_len)
01670             *found_len = 1;
01671           return TRUE;
01672         }
01673       ++i;
01674     }
01675 
01676   if (found)
01677     *found = real->len;
01678 
01679   if (found_len)
01680     *found_len = 0;
01681   
01682   return FALSE;
01683 }
01684 
01701 dbus_bool_t
01702 _dbus_string_find_to (const DBusString *str,
01703                       int               start,
01704                       int               end,
01705                       const char       *substr,
01706                       int              *found)
01707 {
01708   int i;
01709   DBUS_CONST_STRING_PREAMBLE (str);
01710   _dbus_assert (substr != NULL);
01711   _dbus_assert (start <= real->len);
01712   _dbus_assert (start >= 0);
01713   _dbus_assert (substr != NULL);
01714   _dbus_assert (end <= real->len);
01715   _dbus_assert (start <= end);
01716 
01717   /* we always "find" an empty string */
01718   if (*substr == '\0')
01719     {
01720       if (found)
01721         *found = start;
01722       return TRUE;
01723     }
01724 
01725   i = start;
01726   while (i < end)
01727     {
01728       if (real->str[i] == substr[0])
01729         {
01730           int j = i + 1;
01731           
01732           while (j < end)
01733             {
01734               if (substr[j - i] == '\0')
01735                 break;
01736               else if (real->str[j] != substr[j - i])
01737                 break;
01738               
01739               ++j;
01740             }
01741 
01742           if (substr[j - i] == '\0')
01743             {
01744               if (found)
01745                 *found = i;
01746               return TRUE;
01747             }
01748         }
01749       
01750       ++i;
01751     }
01752 
01753   if (found)
01754     *found = end;
01755   
01756   return FALSE;  
01757 }
01758 
01769 dbus_bool_t
01770 _dbus_string_find_blank (const DBusString *str,
01771                          int               start,
01772                          int              *found)
01773 {
01774   int i;
01775   DBUS_CONST_STRING_PREAMBLE (str);
01776   _dbus_assert (start <= real->len);
01777   _dbus_assert (start >= 0);
01778   
01779   i = start;
01780   while (i < real->len)
01781     {
01782       if (real->str[i] == ' ' ||
01783           real->str[i] == '\t')
01784         {
01785           if (found)
01786             *found = i;
01787           return TRUE;
01788         }
01789       
01790       ++i;
01791     }
01792 
01793   if (found)
01794     *found = real->len;
01795   
01796   return FALSE;
01797 }
01798 
01807 void
01808 _dbus_string_skip_blank (const DBusString *str,
01809                          int               start,
01810                          int              *end)
01811 {
01812   int i;
01813   DBUS_CONST_STRING_PREAMBLE (str);
01814   _dbus_assert (start <= real->len);
01815   _dbus_assert (start >= 0);
01816   
01817   i = start;
01818   while (i < real->len)
01819     {
01820       if (!DBUS_IS_ASCII_BLANK (real->str[i]))
01821         break;
01822       
01823       ++i;
01824     }
01825 
01826   _dbus_assert (i == real->len || !DBUS_IS_ASCII_WHITE (real->str[i]));
01827   
01828   if (end)
01829     *end = i;
01830 }
01831 
01832 
01841 void
01842 _dbus_string_skip_white (const DBusString *str,
01843                          int               start,
01844                          int              *end)
01845 {
01846   int i;
01847   DBUS_CONST_STRING_PREAMBLE (str);
01848   _dbus_assert (start <= real->len);
01849   _dbus_assert (start >= 0);
01850   
01851   i = start;
01852   while (i < real->len)
01853     {
01854       if (!DBUS_IS_ASCII_WHITE (real->str[i]))
01855         break;
01856       
01857       ++i;
01858     }
01859 
01860   _dbus_assert (i == real->len || !(DBUS_IS_ASCII_WHITE (real->str[i])));
01861   
01862   if (end)
01863     *end = i;
01864 }
01865 
01874 void
01875 _dbus_string_skip_white_reverse (const DBusString *str,
01876                                  int               end,
01877                                  int              *start)
01878 {
01879   int i;
01880   DBUS_CONST_STRING_PREAMBLE (str);
01881   _dbus_assert (end <= real->len);
01882   _dbus_assert (end >= 0);
01883   
01884   i = end;
01885   while (i > 0)
01886     {
01887       if (!DBUS_IS_ASCII_WHITE (real->str[i-1]))
01888         break;
01889       --i;
01890     }
01891 
01892   _dbus_assert (i >= 0 && (i == 0 || !(DBUS_IS_ASCII_WHITE (real->str[i-1]))));
01893   
01894   if (start)
01895     *start = i;
01896 }
01897 
01913 dbus_bool_t
01914 _dbus_string_pop_line (DBusString *source,
01915                        DBusString *dest)
01916 {
01917   int eol, eol_len;
01918   
01919   _dbus_string_set_length (dest, 0);
01920   
01921   eol = 0;
01922   eol_len = 0;
01923   if (!_dbus_string_find_eol (source, 0, &eol, &eol_len))
01924     {
01925       _dbus_assert (eol == _dbus_string_get_length (source));
01926       if (eol == 0)
01927         {
01928           /* If there's no newline and source has zero length, we're done */
01929           return FALSE;
01930         }
01931       /* otherwise, the last line of the file has no eol characters */
01932     }
01933 
01934   /* remember eol can be 0 if it's an empty line, but eol_len should not be zero also
01935    * since find_eol returned TRUE
01936    */
01937   
01938   if (!_dbus_string_move_len (source, 0, eol + eol_len, dest, 0))
01939     return FALSE;
01940   
01941   /* remove line ending */
01942   if (!_dbus_string_set_length (dest, eol))
01943     {
01944       _dbus_assert_not_reached ("out of memory when shortening a string");
01945       return FALSE;
01946     }
01947 
01948   return TRUE;
01949 }
01950 
01951 #ifdef DBUS_BUILD_TESTS
01952 
01958 void
01959 _dbus_string_delete_first_word (DBusString *str)
01960 {
01961   int i;
01962   
01963   if (_dbus_string_find_blank (str, 0, &i))
01964     _dbus_string_skip_blank (str, i, &i);
01965 
01966   _dbus_string_delete (str, 0, i);
01967 }
01968 #endif
01969 
01970 #ifdef DBUS_BUILD_TESTS
01971 
01976 void
01977 _dbus_string_delete_leading_blanks (DBusString *str)
01978 {
01979   int i;
01980   
01981   _dbus_string_skip_blank (str, 0, &i);
01982 
01983   if (i > 0)
01984     _dbus_string_delete (str, 0, i);
01985 }
01986 #endif
01987 
01993 void
01994 _dbus_string_chop_white(DBusString *str)
01995 {
01996   int i;
01997   
01998   _dbus_string_skip_white (str, 0, &i);
01999 
02000   if (i > 0)
02001     _dbus_string_delete (str, 0, i);
02002   
02003   _dbus_string_skip_white_reverse (str, _dbus_string_get_length (str), &i);
02004 
02005   _dbus_string_set_length (str, i);
02006 }
02007 
02017 dbus_bool_t
02018 _dbus_string_equal (const DBusString *a,
02019                     const DBusString *b)
02020 {
02021   const unsigned char *ap;
02022   const unsigned char *bp;
02023   const unsigned char *a_end;
02024   const DBusRealString *real_a = (const DBusRealString*) a;
02025   const DBusRealString *real_b = (const DBusRealString*) b;
02026   DBUS_GENERIC_STRING_PREAMBLE (real_a);
02027   DBUS_GENERIC_STRING_PREAMBLE (real_b);
02028 
02029   if (real_a->len != real_b->len)
02030     return FALSE;
02031 
02032   ap = real_a->str;
02033   bp = real_b->str;
02034   a_end = real_a->str + real_a->len;
02035   while (ap != a_end)
02036     {
02037       if (*ap != *bp)
02038         return FALSE;
02039       
02040       ++ap;
02041       ++bp;
02042     }
02043 
02044   return TRUE;
02045 }
02046 
02060 dbus_bool_t
02061 _dbus_string_equal_len (const DBusString *a,
02062                         const DBusString *b,
02063                         int               len)
02064 {
02065   const unsigned char *ap;
02066   const unsigned char *bp;
02067   const unsigned char *a_end;
02068   const DBusRealString *real_a = (const DBusRealString*) a;
02069   const DBusRealString *real_b = (const DBusRealString*) b;
02070   DBUS_GENERIC_STRING_PREAMBLE (real_a);
02071   DBUS_GENERIC_STRING_PREAMBLE (real_b);
02072 
02073   if (real_a->len != real_b->len &&
02074       (real_a->len < len || real_b->len < len))
02075     return FALSE;
02076 
02077   ap = real_a->str;
02078   bp = real_b->str;
02079   a_end = real_a->str + MIN (real_a->len, len);
02080   while (ap != a_end)
02081     {
02082       if (*ap != *bp)
02083         return FALSE;
02084       
02085       ++ap;
02086       ++bp;
02087     }
02088 
02089   return TRUE;
02090 }
02091 
02108 dbus_bool_t
02109 _dbus_string_equal_substring (const DBusString  *a,
02110                               int                a_start,
02111                               int                a_len,
02112                               const DBusString  *b,
02113                               int                b_start)
02114 {
02115   const unsigned char *ap;
02116   const unsigned char *bp;
02117   const unsigned char *a_end;
02118   const DBusRealString *real_a = (const DBusRealString*) a;
02119   const DBusRealString *real_b = (const DBusRealString*) b;
02120   DBUS_GENERIC_STRING_PREAMBLE (real_a);
02121   DBUS_GENERIC_STRING_PREAMBLE (real_b);
02122   _dbus_assert (a_start >= 0);
02123   _dbus_assert (a_len >= 0);
02124   _dbus_assert (a_start <= real_a->len);
02125   _dbus_assert (a_len <= real_a->len - a_start);
02126   _dbus_assert (b_start >= 0);
02127   _dbus_assert (b_start <= real_b->len);
02128   
02129   if (a_len > real_b->len - b_start)
02130     return FALSE;
02131 
02132   ap = real_a->str + a_start;
02133   bp = real_b->str + b_start;
02134   a_end = ap + a_len;
02135   while (ap != a_end)
02136     {
02137       if (*ap != *bp)
02138         return FALSE;
02139       
02140       ++ap;
02141       ++bp;
02142     }
02143 
02144   _dbus_assert (bp <= (real_b->str + real_b->len));
02145   
02146   return TRUE;
02147 }
02148 
02156 dbus_bool_t
02157 _dbus_string_equal_c_str (const DBusString *a,
02158                           const char       *c_str)
02159 {
02160   const unsigned char *ap;
02161   const unsigned char *bp;
02162   const unsigned char *a_end;
02163   const DBusRealString *real_a = (const DBusRealString*) a;
02164   DBUS_GENERIC_STRING_PREAMBLE (real_a);
02165   _dbus_assert (c_str != NULL);
02166   
02167   ap = real_a->str;
02168   bp = (const unsigned char*) c_str;
02169   a_end = real_a->str + real_a->len;
02170   while (ap != a_end && *bp)
02171     {
02172       if (*ap != *bp)
02173         return FALSE;
02174       
02175       ++ap;
02176       ++bp;
02177     }
02178 
02179   if (ap != a_end || *bp)
02180     return FALSE;
02181   
02182   return TRUE;
02183 }
02184 
02192 dbus_bool_t
02193 _dbus_string_starts_with_c_str (const DBusString *a,
02194                                 const char       *c_str)
02195 {
02196   const unsigned char *ap;
02197   const unsigned char *bp;
02198   const unsigned char *a_end;
02199   const DBusRealString *real_a = (const DBusRealString*) a;
02200   DBUS_GENERIC_STRING_PREAMBLE (real_a);
02201   _dbus_assert (c_str != NULL);
02202   
02203   ap = real_a->str;
02204   bp = (const unsigned char*) c_str;
02205   a_end = real_a->str + real_a->len;
02206   while (ap != a_end && *bp)
02207     {
02208       if (*ap != *bp)
02209         return FALSE;
02210       
02211       ++ap;
02212       ++bp;
02213     }
02214 
02215   if (*bp == '\0')
02216     return TRUE;
02217   else
02218     return FALSE;
02219 }
02220 
02229 dbus_bool_t
02230 _dbus_string_append_byte_as_hex (DBusString *str,
02231                                  int         byte)
02232 {
02233   const char hexdigits[16] = {
02234     '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
02235     'a', 'b', 'c', 'd', 'e', 'f'
02236   };
02237 
02238   if (!_dbus_string_append_byte (str,
02239                                  hexdigits[(byte >> 4)]))
02240     return FALSE;
02241   
02242   if (!_dbus_string_append_byte (str,
02243                                  hexdigits[(byte & 0x0f)]))
02244     {
02245       _dbus_string_set_length (str,
02246                                _dbus_string_get_length (str) - 1);
02247       return FALSE;
02248     }
02249 
02250   return TRUE;
02251 }
02252 
02263 dbus_bool_t
02264 _dbus_string_hex_encode (const DBusString *source,
02265                          int               start,
02266                          DBusString       *dest,
02267                          int               insert_at)
02268 {
02269   DBusString result;
02270   const unsigned char *p;
02271   const unsigned char *end;
02272   dbus_bool_t retval;
02273   
02274   _dbus_assert (start <= _dbus_string_get_length (source));
02275 
02276   if (!_dbus_string_init (&result))
02277     return FALSE;
02278 
02279   retval = FALSE;
02280   
02281   p = (const unsigned char*) _dbus_string_get_const_data (source);
02282   end = p + _dbus_string_get_length (source);
02283   p += start;
02284   
02285   while (p != end)
02286     {
02287       if (!_dbus_string_append_byte_as_hex (&result, *p))
02288         goto out;
02289       
02290       ++p;
02291     }
02292 
02293   if (!_dbus_string_move (&result, 0, dest, insert_at))
02294     goto out;
02295 
02296   retval = TRUE;
02297 
02298  out:
02299   _dbus_string_free (&result);
02300   return retval;
02301 }
02302 
02313 dbus_bool_t
02314 _dbus_string_hex_decode (const DBusString *source,
02315                          int               start,
02316                          int              *end_return,
02317                          DBusString       *dest,
02318                          int               insert_at)
02319 {
02320   DBusString result;
02321   const unsigned char *p;
02322   const unsigned char *end;
02323   dbus_bool_t retval;
02324   dbus_bool_t high_bits;
02325   
02326   _dbus_assert (start <= _dbus_string_get_length (source));
02327 
02328   if (!_dbus_string_init (&result))
02329     return FALSE;
02330 
02331   retval = FALSE;
02332 
02333   high_bits = TRUE;
02334   p = (const unsigned char*) _dbus_string_get_const_data (source);
02335   end = p + _dbus_string_get_length (source);
02336   p += start;
02337   
02338   while (p != end)
02339     {
02340       unsigned int val;
02341 
02342       switch (*p)
02343         {
02344         case '0':
02345           val = 0;
02346           break;
02347         case '1':
02348           val = 1;
02349           break;
02350         case '2':
02351           val = 2;
02352           break;
02353         case '3':
02354           val = 3;
02355           break;
02356         case '4':
02357           val = 4;
02358           break;
02359         case '5':
02360           val = 5;
02361           break;
02362         case '6':
02363           val = 6;
02364           break;
02365         case '7':
02366           val = 7;
02367           break;
02368         case '8':
02369           val = 8;
02370           break;
02371         case '9':
02372           val = 9;
02373           break;
02374         case 'a':
02375         case 'A':
02376           val = 10;
02377           break;
02378         case 'b':
02379         case 'B':
02380           val = 11;
02381           break;
02382         case 'c':
02383         case 'C':
02384           val = 12;
02385           break;
02386         case 'd':
02387         case 'D':
02388           val = 13;
02389           break;
02390         case 'e':
02391         case 'E':
02392           val = 14;
02393           break;
02394         case 'f':
02395         case 'F':
02396           val = 15;
02397           break;
02398         default:
02399           goto done;
02400         }
02401 
02402       if (high_bits)
02403         {
02404           if (!_dbus_string_append_byte (&result,
02405                                          val << 4))
02406             goto out;
02407         }
02408       else
02409         {
02410           int len;
02411           unsigned char b;
02412 
02413           len = _dbus_string_get_length (&result);
02414           
02415           b = _dbus_string_get_byte (&result, len - 1);
02416 
02417           b |= val;
02418 
02419           _dbus_string_set_byte (&result, len - 1, b);
02420         }
02421 
02422       high_bits = !high_bits;
02423 
02424       ++p;
02425     }
02426 
02427  done:
02428   if (!_dbus_string_move (&result, 0, dest, insert_at))
02429     goto out;
02430 
02431   if (end_return)
02432     *end_return = p - (const unsigned char*) _dbus_string_get_const_data (source);
02433 
02434   retval = TRUE;
02435   
02436  out:
02437   _dbus_string_free (&result);  
02438   return retval;
02439 }
02440 
02454 dbus_bool_t
02455 _dbus_string_validate_ascii (const DBusString *str,
02456                              int               start,
02457                              int               len)
02458 {
02459   const unsigned char *s;
02460   const unsigned char *end;
02461   DBUS_CONST_STRING_PREAMBLE (str);
02462   _dbus_assert (start >= 0);
02463   _dbus_assert (start <= real->len);
02464   _dbus_assert (len >= 0);
02465   
02466   if (len > real->len - start)
02467     return FALSE;
02468   
02469   s = real->str + start;
02470   end = s + len;
02471   while (s != end)
02472     {
02473       if (_DBUS_UNLIKELY (!_DBUS_ISASCII (*s)))
02474         return FALSE;
02475         
02476       ++s;
02477     }
02478   
02479   return TRUE;
02480 }
02481 
02489 void
02490 _dbus_string_tolower_ascii (const DBusString *str,
02491                             int               start,
02492                             int               len)
02493 {
02494   unsigned char *s;
02495   unsigned char *end;
02496   DBUS_STRING_PREAMBLE (str);
02497   _dbus_assert (start >= 0);
02498   _dbus_assert (start <= real->len);
02499   _dbus_assert (len >= 0);
02500   _dbus_assert (len <= real->len - start);
02501 
02502   s = real->str + start;
02503   end = s + len;
02504 
02505   while (s != end)
02506     {
02507       if (*s >= 'A' && *s <= 'Z')
02508           *s += 'a' - 'A';
02509       ++s;
02510     }
02511 }
02512 
02520 void
02521 _dbus_string_toupper_ascii (const DBusString *str,
02522                             int               start,
02523                             int               len)
02524 {
02525   unsigned char *s;
02526   unsigned char *end;
02527   DBUS_STRING_PREAMBLE (str);
02528   _dbus_assert (start >= 0);
02529   _dbus_assert (start <= real->len);
02530   _dbus_assert (len >= 0);
02531   _dbus_assert (len <= real->len - start);
02532 
02533   s = real->str + start;
02534   end = s + len;
02535 
02536   while (s != end)
02537     {
02538       if (*s >= 'a' && *s <= 'z')
02539           *s += 'A' - 'a';
02540       ++s;
02541     }
02542 }
02543 
02559 dbus_bool_t
02560 _dbus_string_validate_utf8  (const DBusString *str,
02561                              int               start,
02562                              int               len)
02563 {
02564   const unsigned char *p;
02565   const unsigned char *end;
02566   DBUS_CONST_STRING_PREAMBLE (str);
02567   _dbus_assert (start >= 0);
02568   _dbus_assert (start <= real->len);
02569   _dbus_assert (len >= 0);
02570 
02571   /* we are doing _DBUS_UNLIKELY() here which might be
02572    * dubious in a generic library like GLib, but in D-Bus
02573    * we know we're validating messages and that it would
02574    * only be evil/broken apps that would have invalid
02575    * UTF-8. Also, this function seems to be a performance
02576    * bottleneck in profiles.
02577    */
02578   
02579   if (_DBUS_UNLIKELY (len > real->len - start))
02580     return FALSE;
02581   
02582   p = real->str + start;
02583   end = p + len;
02584   
02585   while (p < end)
02586     {
02587       int i, mask, char_len;
02588       dbus_unichar_t result;
02589 
02590       /* nul bytes considered invalid */
02591       if (*p == '\0')
02592         break;
02593       
02594       /* Special-case ASCII; this makes us go a lot faster in
02595        * D-Bus profiles where we are typically validating
02596        * function names and such. We have to know that
02597        * all following checks will pass for ASCII though,
02598        * comments follow ...
02599        */      
02600       if (*p < 128)
02601         {
02602           ++p;
02603           continue;
02604         }
02605       
02606       UTF8_COMPUTE (*p, mask, char_len);
02607 
02608       if (_DBUS_UNLIKELY (char_len == 0))  /* ASCII: char_len == 1 */
02609         break;
02610 
02611       /* check that the expected number of bytes exists in the remaining length */
02612       if (_DBUS_UNLIKELY ((end - p) < char_len)) /* ASCII: p < end and char_len == 1 */
02613         break;
02614         
02615       UTF8_GET (result, p, i, mask, char_len);
02616 
02617       /* Check for overlong UTF-8 */
02618       if (_DBUS_UNLIKELY (UTF8_LENGTH (result) != char_len)) /* ASCII: UTF8_LENGTH == 1 */
02619         break;
02620 #if 0
02621       /* The UNICODE_VALID check below will catch this */
02622       if (_DBUS_UNLIKELY (result == (dbus_unichar_t)-1)) /* ASCII: result = ascii value */
02623         break;
02624 #endif
02625 
02626       if (_DBUS_UNLIKELY (!UNICODE_VALID (result))) /* ASCII: always valid */
02627         break;
02628 
02629       /* UNICODE_VALID should have caught it */
02630       _dbus_assert (result != (dbus_unichar_t)-1);
02631       
02632       p += char_len;
02633     }
02634 
02635   /* See that we covered the entire length if a length was
02636    * passed in
02637    */
02638   if (_DBUS_UNLIKELY (p != end))
02639     return FALSE;
02640   else
02641     return TRUE;
02642 }
02643 
02657 dbus_bool_t
02658 _dbus_string_validate_nul (const DBusString *str,
02659                            int               start,
02660                            int               len)
02661 {
02662   const unsigned char *s;
02663   const unsigned char *end;
02664   DBUS_CONST_STRING_PREAMBLE (str);
02665   _dbus_assert (start >= 0);
02666   _dbus_assert (len >= 0);
02667   _dbus_assert (start <= real->len);
02668   
02669   if (len > real->len - start)
02670     return FALSE;
02671   
02672   s = real->str + start;
02673   end = s + len;
02674   while (s != end)
02675     {
02676       if (_DBUS_UNLIKELY (*s != '\0'))
02677         return FALSE;
02678       ++s;
02679     }
02680   
02681   return TRUE;
02682 }
02683 
02689 void
02690 _dbus_string_zero (DBusString *str)
02691 {
02692   DBUS_STRING_PREAMBLE (str);
02693 
02694   memset (real->str - real->align_offset, '\0', real->allocated);
02695 }
02698 /* tests are in dbus-string-util.c */