D-Bus 1.6.12

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 
01582 #define UNICODE_VALID(Char)                   \
01583     ((Char) < 0x110000 &&                     \
01584      (((Char) & 0xFFFFF800) != 0xD800))
01585 
01600 dbus_bool_t
01601 _dbus_string_find (const DBusString *str,
01602                    int               start,
01603                    const char       *substr,
01604                    int              *found)
01605 {
01606   return _dbus_string_find_to (str, start,
01607                                ((const DBusRealString*)str)->len,
01608                                substr, found);
01609 }
01610 
01623 dbus_bool_t
01624 _dbus_string_find_eol (const DBusString *str,
01625                        int               start,
01626                        int              *found,
01627                        int              *found_len)
01628 {
01629   int i;
01630 
01631   DBUS_CONST_STRING_PREAMBLE (str);
01632   _dbus_assert (start <= real->len);
01633   _dbus_assert (start >= 0);
01634   
01635   i = start;
01636   while (i < real->len)
01637     {
01638       if (real->str[i] == '\r') 
01639         {
01640           if ((i+1) < real->len && real->str[i+1] == '\n') /* "\r\n" */
01641             {
01642               if (found) 
01643                 *found = i;
01644               if (found_len)
01645                 *found_len = 2;
01646               return TRUE;
01647             } 
01648           else /* only "\r" */
01649             {
01650               if (found) 
01651                 *found = i;
01652               if (found_len)
01653                 *found_len = 1;
01654               return TRUE;
01655             }
01656         } 
01657       else if (real->str[i] == '\n')  /* only "\n" */
01658         {
01659           if (found) 
01660             *found = i;
01661           if (found_len)
01662             *found_len = 1;
01663           return TRUE;
01664         }
01665       ++i;
01666     }
01667 
01668   if (found)
01669     *found = real->len;
01670 
01671   if (found_len)
01672     *found_len = 0;
01673   
01674   return FALSE;
01675 }
01676 
01693 dbus_bool_t
01694 _dbus_string_find_to (const DBusString *str,
01695                       int               start,
01696                       int               end,
01697                       const char       *substr,
01698                       int              *found)
01699 {
01700   int i;
01701   DBUS_CONST_STRING_PREAMBLE (str);
01702   _dbus_assert (substr != NULL);
01703   _dbus_assert (start <= real->len);
01704   _dbus_assert (start >= 0);
01705   _dbus_assert (substr != NULL);
01706   _dbus_assert (end <= real->len);
01707   _dbus_assert (start <= end);
01708 
01709   /* we always "find" an empty string */
01710   if (*substr == '\0')
01711     {
01712       if (found)
01713         *found = start;
01714       return TRUE;
01715     }
01716 
01717   i = start;
01718   while (i < end)
01719     {
01720       if (real->str[i] == substr[0])
01721         {
01722           int j = i + 1;
01723           
01724           while (j < end)
01725             {
01726               if (substr[j - i] == '\0')
01727                 break;
01728               else if (real->str[j] != substr[j - i])
01729                 break;
01730               
01731               ++j;
01732             }
01733 
01734           if (substr[j - i] == '\0')
01735             {
01736               if (found)
01737                 *found = i;
01738               return TRUE;
01739             }
01740         }
01741       
01742       ++i;
01743     }
01744 
01745   if (found)
01746     *found = end;
01747   
01748   return FALSE;  
01749 }
01750 
01761 dbus_bool_t
01762 _dbus_string_find_blank (const DBusString *str,
01763                          int               start,
01764                          int              *found)
01765 {
01766   int i;
01767   DBUS_CONST_STRING_PREAMBLE (str);
01768   _dbus_assert (start <= real->len);
01769   _dbus_assert (start >= 0);
01770   
01771   i = start;
01772   while (i < real->len)
01773     {
01774       if (real->str[i] == ' ' ||
01775           real->str[i] == '\t')
01776         {
01777           if (found)
01778             *found = i;
01779           return TRUE;
01780         }
01781       
01782       ++i;
01783     }
01784 
01785   if (found)
01786     *found = real->len;
01787   
01788   return FALSE;
01789 }
01790 
01799 void
01800 _dbus_string_skip_blank (const DBusString *str,
01801                          int               start,
01802                          int              *end)
01803 {
01804   int i;
01805   DBUS_CONST_STRING_PREAMBLE (str);
01806   _dbus_assert (start <= real->len);
01807   _dbus_assert (start >= 0);
01808   
01809   i = start;
01810   while (i < real->len)
01811     {
01812       if (!DBUS_IS_ASCII_BLANK (real->str[i]))
01813         break;
01814       
01815       ++i;
01816     }
01817 
01818   _dbus_assert (i == real->len || !DBUS_IS_ASCII_WHITE (real->str[i]));
01819   
01820   if (end)
01821     *end = i;
01822 }
01823 
01824 
01833 void
01834 _dbus_string_skip_white (const DBusString *str,
01835                          int               start,
01836                          int              *end)
01837 {
01838   int i;
01839   DBUS_CONST_STRING_PREAMBLE (str);
01840   _dbus_assert (start <= real->len);
01841   _dbus_assert (start >= 0);
01842   
01843   i = start;
01844   while (i < real->len)
01845     {
01846       if (!DBUS_IS_ASCII_WHITE (real->str[i]))
01847         break;
01848       
01849       ++i;
01850     }
01851 
01852   _dbus_assert (i == real->len || !(DBUS_IS_ASCII_WHITE (real->str[i])));
01853   
01854   if (end)
01855     *end = i;
01856 }
01857 
01866 void
01867 _dbus_string_skip_white_reverse (const DBusString *str,
01868                                  int               end,
01869                                  int              *start)
01870 {
01871   int i;
01872   DBUS_CONST_STRING_PREAMBLE (str);
01873   _dbus_assert (end <= real->len);
01874   _dbus_assert (end >= 0);
01875   
01876   i = end;
01877   while (i > 0)
01878     {
01879       if (!DBUS_IS_ASCII_WHITE (real->str[i-1]))
01880         break;
01881       --i;
01882     }
01883 
01884   _dbus_assert (i >= 0 && (i == 0 || !(DBUS_IS_ASCII_WHITE (real->str[i-1]))));
01885   
01886   if (start)
01887     *start = i;
01888 }
01889 
01905 dbus_bool_t
01906 _dbus_string_pop_line (DBusString *source,
01907                        DBusString *dest)
01908 {
01909   int eol, eol_len;
01910   
01911   _dbus_string_set_length (dest, 0);
01912   
01913   eol = 0;
01914   eol_len = 0;
01915   if (!_dbus_string_find_eol (source, 0, &eol, &eol_len))
01916     {
01917       _dbus_assert (eol == _dbus_string_get_length (source));
01918       if (eol == 0)
01919         {
01920           /* If there's no newline and source has zero length, we're done */
01921           return FALSE;
01922         }
01923       /* otherwise, the last line of the file has no eol characters */
01924     }
01925 
01926   /* remember eol can be 0 if it's an empty line, but eol_len should not be zero also
01927    * since find_eol returned TRUE
01928    */
01929   
01930   if (!_dbus_string_move_len (source, 0, eol + eol_len, dest, 0))
01931     return FALSE;
01932   
01933   /* remove line ending */
01934   if (!_dbus_string_set_length (dest, eol))
01935     {
01936       _dbus_assert_not_reached ("out of memory when shortening a string");
01937       return FALSE;
01938     }
01939 
01940   return TRUE;
01941 }
01942 
01943 #ifdef DBUS_BUILD_TESTS
01944 
01950 void
01951 _dbus_string_delete_first_word (DBusString *str)
01952 {
01953   int i;
01954   
01955   if (_dbus_string_find_blank (str, 0, &i))
01956     _dbus_string_skip_blank (str, i, &i);
01957 
01958   _dbus_string_delete (str, 0, i);
01959 }
01960 #endif
01961 
01962 #ifdef DBUS_BUILD_TESTS
01963 
01968 void
01969 _dbus_string_delete_leading_blanks (DBusString *str)
01970 {
01971   int i;
01972   
01973   _dbus_string_skip_blank (str, 0, &i);
01974 
01975   if (i > 0)
01976     _dbus_string_delete (str, 0, i);
01977 }
01978 #endif
01979 
01985 void
01986 _dbus_string_chop_white(DBusString *str)
01987 {
01988   int i;
01989   
01990   _dbus_string_skip_white (str, 0, &i);
01991 
01992   if (i > 0)
01993     _dbus_string_delete (str, 0, i);
01994   
01995   _dbus_string_skip_white_reverse (str, _dbus_string_get_length (str), &i);
01996 
01997   _dbus_string_set_length (str, i);
01998 }
01999 
02009 dbus_bool_t
02010 _dbus_string_equal (const DBusString *a,
02011                     const DBusString *b)
02012 {
02013   const unsigned char *ap;
02014   const unsigned char *bp;
02015   const unsigned char *a_end;
02016   const DBusRealString *real_a = (const DBusRealString*) a;
02017   const DBusRealString *real_b = (const DBusRealString*) b;
02018   DBUS_GENERIC_STRING_PREAMBLE (real_a);
02019   DBUS_GENERIC_STRING_PREAMBLE (real_b);
02020 
02021   if (real_a->len != real_b->len)
02022     return FALSE;
02023 
02024   ap = real_a->str;
02025   bp = real_b->str;
02026   a_end = real_a->str + real_a->len;
02027   while (ap != a_end)
02028     {
02029       if (*ap != *bp)
02030         return FALSE;
02031       
02032       ++ap;
02033       ++bp;
02034     }
02035 
02036   return TRUE;
02037 }
02038 
02052 dbus_bool_t
02053 _dbus_string_equal_len (const DBusString *a,
02054                         const DBusString *b,
02055                         int               len)
02056 {
02057   const unsigned char *ap;
02058   const unsigned char *bp;
02059   const unsigned char *a_end;
02060   const DBusRealString *real_a = (const DBusRealString*) a;
02061   const DBusRealString *real_b = (const DBusRealString*) b;
02062   DBUS_GENERIC_STRING_PREAMBLE (real_a);
02063   DBUS_GENERIC_STRING_PREAMBLE (real_b);
02064 
02065   if (real_a->len != real_b->len &&
02066       (real_a->len < len || real_b->len < len))
02067     return FALSE;
02068 
02069   ap = real_a->str;
02070   bp = real_b->str;
02071   a_end = real_a->str + MIN (real_a->len, len);
02072   while (ap != a_end)
02073     {
02074       if (*ap != *bp)
02075         return FALSE;
02076       
02077       ++ap;
02078       ++bp;
02079     }
02080 
02081   return TRUE;
02082 }
02083 
02100 dbus_bool_t
02101 _dbus_string_equal_substring (const DBusString  *a,
02102                               int                a_start,
02103                               int                a_len,
02104                               const DBusString  *b,
02105                               int                b_start)
02106 {
02107   const unsigned char *ap;
02108   const unsigned char *bp;
02109   const unsigned char *a_end;
02110   const DBusRealString *real_a = (const DBusRealString*) a;
02111   const DBusRealString *real_b = (const DBusRealString*) b;
02112   DBUS_GENERIC_STRING_PREAMBLE (real_a);
02113   DBUS_GENERIC_STRING_PREAMBLE (real_b);
02114   _dbus_assert (a_start >= 0);
02115   _dbus_assert (a_len >= 0);
02116   _dbus_assert (a_start <= real_a->len);
02117   _dbus_assert (a_len <= real_a->len - a_start);
02118   _dbus_assert (b_start >= 0);
02119   _dbus_assert (b_start <= real_b->len);
02120   
02121   if (a_len > real_b->len - b_start)
02122     return FALSE;
02123 
02124   ap = real_a->str + a_start;
02125   bp = real_b->str + b_start;
02126   a_end = ap + a_len;
02127   while (ap != a_end)
02128     {
02129       if (*ap != *bp)
02130         return FALSE;
02131       
02132       ++ap;
02133       ++bp;
02134     }
02135 
02136   _dbus_assert (bp <= (real_b->str + real_b->len));
02137   
02138   return TRUE;
02139 }
02140 
02148 dbus_bool_t
02149 _dbus_string_equal_c_str (const DBusString *a,
02150                           const char       *c_str)
02151 {
02152   const unsigned char *ap;
02153   const unsigned char *bp;
02154   const unsigned char *a_end;
02155   const DBusRealString *real_a = (const DBusRealString*) a;
02156   DBUS_GENERIC_STRING_PREAMBLE (real_a);
02157   _dbus_assert (c_str != NULL);
02158   
02159   ap = real_a->str;
02160   bp = (const unsigned char*) c_str;
02161   a_end = real_a->str + real_a->len;
02162   while (ap != a_end && *bp)
02163     {
02164       if (*ap != *bp)
02165         return FALSE;
02166       
02167       ++ap;
02168       ++bp;
02169     }
02170 
02171   if (ap != a_end || *bp)
02172     return FALSE;
02173   
02174   return TRUE;
02175 }
02176 
02184 dbus_bool_t
02185 _dbus_string_starts_with_c_str (const DBusString *a,
02186                                 const char       *c_str)
02187 {
02188   const unsigned char *ap;
02189   const unsigned char *bp;
02190   const unsigned char *a_end;
02191   const DBusRealString *real_a = (const DBusRealString*) a;
02192   DBUS_GENERIC_STRING_PREAMBLE (real_a);
02193   _dbus_assert (c_str != NULL);
02194   
02195   ap = real_a->str;
02196   bp = (const unsigned char*) c_str;
02197   a_end = real_a->str + real_a->len;
02198   while (ap != a_end && *bp)
02199     {
02200       if (*ap != *bp)
02201         return FALSE;
02202       
02203       ++ap;
02204       ++bp;
02205     }
02206 
02207   if (*bp == '\0')
02208     return TRUE;
02209   else
02210     return FALSE;
02211 }
02212 
02221 dbus_bool_t
02222 _dbus_string_append_byte_as_hex (DBusString *str,
02223                                  int         byte)
02224 {
02225   const char hexdigits[16] = {
02226     '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
02227     'a', 'b', 'c', 'd', 'e', 'f'
02228   };
02229 
02230   if (!_dbus_string_append_byte (str,
02231                                  hexdigits[(byte >> 4)]))
02232     return FALSE;
02233   
02234   if (!_dbus_string_append_byte (str,
02235                                  hexdigits[(byte & 0x0f)]))
02236     {
02237       _dbus_string_set_length (str,
02238                                _dbus_string_get_length (str) - 1);
02239       return FALSE;
02240     }
02241 
02242   return TRUE;
02243 }
02244 
02255 dbus_bool_t
02256 _dbus_string_hex_encode (const DBusString *source,
02257                          int               start,
02258                          DBusString       *dest,
02259                          int               insert_at)
02260 {
02261   DBusString result;
02262   const unsigned char *p;
02263   const unsigned char *end;
02264   dbus_bool_t retval;
02265   
02266   _dbus_assert (start <= _dbus_string_get_length (source));
02267 
02268   if (!_dbus_string_init (&result))
02269     return FALSE;
02270 
02271   retval = FALSE;
02272   
02273   p = (const unsigned char*) _dbus_string_get_const_data (source);
02274   end = p + _dbus_string_get_length (source);
02275   p += start;
02276   
02277   while (p != end)
02278     {
02279       if (!_dbus_string_append_byte_as_hex (&result, *p))
02280         goto out;
02281       
02282       ++p;
02283     }
02284 
02285   if (!_dbus_string_move (&result, 0, dest, insert_at))
02286     goto out;
02287 
02288   retval = TRUE;
02289 
02290  out:
02291   _dbus_string_free (&result);
02292   return retval;
02293 }
02294 
02305 dbus_bool_t
02306 _dbus_string_hex_decode (const DBusString *source,
02307                          int               start,
02308                          int              *end_return,
02309                          DBusString       *dest,
02310                          int               insert_at)
02311 {
02312   DBusString result;
02313   const unsigned char *p;
02314   const unsigned char *end;
02315   dbus_bool_t retval;
02316   dbus_bool_t high_bits;
02317   
02318   _dbus_assert (start <= _dbus_string_get_length (source));
02319 
02320   if (!_dbus_string_init (&result))
02321     return FALSE;
02322 
02323   retval = FALSE;
02324 
02325   high_bits = TRUE;
02326   p = (const unsigned char*) _dbus_string_get_const_data (source);
02327   end = p + _dbus_string_get_length (source);
02328   p += start;
02329   
02330   while (p != end)
02331     {
02332       unsigned int val;
02333 
02334       switch (*p)
02335         {
02336         case '0':
02337           val = 0;
02338           break;
02339         case '1':
02340           val = 1;
02341           break;
02342         case '2':
02343           val = 2;
02344           break;
02345         case '3':
02346           val = 3;
02347           break;
02348         case '4':
02349           val = 4;
02350           break;
02351         case '5':
02352           val = 5;
02353           break;
02354         case '6':
02355           val = 6;
02356           break;
02357         case '7':
02358           val = 7;
02359           break;
02360         case '8':
02361           val = 8;
02362           break;
02363         case '9':
02364           val = 9;
02365           break;
02366         case 'a':
02367         case 'A':
02368           val = 10;
02369           break;
02370         case 'b':
02371         case 'B':
02372           val = 11;
02373           break;
02374         case 'c':
02375         case 'C':
02376           val = 12;
02377           break;
02378         case 'd':
02379         case 'D':
02380           val = 13;
02381           break;
02382         case 'e':
02383         case 'E':
02384           val = 14;
02385           break;
02386         case 'f':
02387         case 'F':
02388           val = 15;
02389           break;
02390         default:
02391           goto done;
02392         }
02393 
02394       if (high_bits)
02395         {
02396           if (!_dbus_string_append_byte (&result,
02397                                          val << 4))
02398             goto out;
02399         }
02400       else
02401         {
02402           int len;
02403           unsigned char b;
02404 
02405           len = _dbus_string_get_length (&result);
02406           
02407           b = _dbus_string_get_byte (&result, len - 1);
02408 
02409           b |= val;
02410 
02411           _dbus_string_set_byte (&result, len - 1, b);
02412         }
02413 
02414       high_bits = !high_bits;
02415 
02416       ++p;
02417     }
02418 
02419  done:
02420   if (!_dbus_string_move (&result, 0, dest, insert_at))
02421     goto out;
02422 
02423   if (end_return)
02424     *end_return = p - (const unsigned char*) _dbus_string_get_const_data (source);
02425 
02426   retval = TRUE;
02427   
02428  out:
02429   _dbus_string_free (&result);  
02430   return retval;
02431 }
02432 
02446 dbus_bool_t
02447 _dbus_string_validate_ascii (const DBusString *str,
02448                              int               start,
02449                              int               len)
02450 {
02451   const unsigned char *s;
02452   const unsigned char *end;
02453   DBUS_CONST_STRING_PREAMBLE (str);
02454   _dbus_assert (start >= 0);
02455   _dbus_assert (start <= real->len);
02456   _dbus_assert (len >= 0);
02457   
02458   if (len > real->len - start)
02459     return FALSE;
02460   
02461   s = real->str + start;
02462   end = s + len;
02463   while (s != end)
02464     {
02465       if (_DBUS_UNLIKELY (!_DBUS_ISASCII (*s)))
02466         return FALSE;
02467         
02468       ++s;
02469     }
02470   
02471   return TRUE;
02472 }
02473 
02481 void
02482 _dbus_string_tolower_ascii (const DBusString *str,
02483                             int               start,
02484                             int               len)
02485 {
02486   unsigned char *s;
02487   unsigned char *end;
02488   DBUS_STRING_PREAMBLE (str);
02489   _dbus_assert (start >= 0);
02490   _dbus_assert (start <= real->len);
02491   _dbus_assert (len >= 0);
02492   _dbus_assert (len <= real->len - start);
02493 
02494   s = real->str + start;
02495   end = s + len;
02496 
02497   while (s != end)
02498     {
02499       if (*s >= 'A' && *s <= 'Z')
02500           *s += 'a' - 'A';
02501       ++s;
02502     }
02503 }
02504 
02512 void
02513 _dbus_string_toupper_ascii (const DBusString *str,
02514                             int               start,
02515                             int               len)
02516 {
02517   unsigned char *s;
02518   unsigned char *end;
02519   DBUS_STRING_PREAMBLE (str);
02520   _dbus_assert (start >= 0);
02521   _dbus_assert (start <= real->len);
02522   _dbus_assert (len >= 0);
02523   _dbus_assert (len <= real->len - start);
02524 
02525   s = real->str + start;
02526   end = s + len;
02527 
02528   while (s != end)
02529     {
02530       if (*s >= 'a' && *s <= 'z')
02531           *s += 'A' - 'a';
02532       ++s;
02533     }
02534 }
02535 
02551 dbus_bool_t
02552 _dbus_string_validate_utf8  (const DBusString *str,
02553                              int               start,
02554                              int               len)
02555 {
02556   const unsigned char *p;
02557   const unsigned char *end;
02558   DBUS_CONST_STRING_PREAMBLE (str);
02559   _dbus_assert (start >= 0);
02560   _dbus_assert (start <= real->len);
02561   _dbus_assert (len >= 0);
02562 
02563   /* we are doing _DBUS_UNLIKELY() here which might be
02564    * dubious in a generic library like GLib, but in D-Bus
02565    * we know we're validating messages and that it would
02566    * only be evil/broken apps that would have invalid
02567    * UTF-8. Also, this function seems to be a performance
02568    * bottleneck in profiles.
02569    */
02570   
02571   if (_DBUS_UNLIKELY (len > real->len - start))
02572     return FALSE;
02573   
02574   p = real->str + start;
02575   end = p + len;
02576   
02577   while (p < end)
02578     {
02579       int i, mask, char_len;
02580       dbus_unichar_t result;
02581 
02582       /* nul bytes considered invalid */
02583       if (*p == '\0')
02584         break;
02585       
02586       /* Special-case ASCII; this makes us go a lot faster in
02587        * D-Bus profiles where we are typically validating
02588        * function names and such. We have to know that
02589        * all following checks will pass for ASCII though,
02590        * comments follow ...
02591        */      
02592       if (*p < 128)
02593         {
02594           ++p;
02595           continue;
02596         }
02597       
02598       UTF8_COMPUTE (*p, mask, char_len);
02599 
02600       if (_DBUS_UNLIKELY (char_len == 0))  /* ASCII: char_len == 1 */
02601         break;
02602 
02603       /* check that the expected number of bytes exists in the remaining length */
02604       if (_DBUS_UNLIKELY ((end - p) < char_len)) /* ASCII: p < end and char_len == 1 */
02605         break;
02606         
02607       UTF8_GET (result, p, i, mask, char_len);
02608 
02609       /* Check for overlong UTF-8 */
02610       if (_DBUS_UNLIKELY (UTF8_LENGTH (result) != char_len)) /* ASCII: UTF8_LENGTH == 1 */
02611         break;
02612 #if 0
02613       /* The UNICODE_VALID check below will catch this */
02614       if (_DBUS_UNLIKELY (result == (dbus_unichar_t)-1)) /* ASCII: result = ascii value */
02615         break;
02616 #endif
02617 
02618       if (_DBUS_UNLIKELY (!UNICODE_VALID (result))) /* ASCII: always valid */
02619         break;
02620 
02621       /* UNICODE_VALID should have caught it */
02622       _dbus_assert (result != (dbus_unichar_t)-1);
02623       
02624       p += char_len;
02625     }
02626 
02627   /* See that we covered the entire length if a length was
02628    * passed in
02629    */
02630   if (_DBUS_UNLIKELY (p != end))
02631     return FALSE;
02632   else
02633     return TRUE;
02634 }
02635 
02649 dbus_bool_t
02650 _dbus_string_validate_nul (const DBusString *str,
02651                            int               start,
02652                            int               len)
02653 {
02654   const unsigned char *s;
02655   const unsigned char *end;
02656   DBUS_CONST_STRING_PREAMBLE (str);
02657   _dbus_assert (start >= 0);
02658   _dbus_assert (len >= 0);
02659   _dbus_assert (start <= real->len);
02660   
02661   if (len > real->len - start)
02662     return FALSE;
02663   
02664   s = real->str + start;
02665   end = s + len;
02666   while (s != end)
02667     {
02668       if (_DBUS_UNLIKELY (*s != '\0'))
02669         return FALSE;
02670       ++s;
02671     }
02672   
02673   return TRUE;
02674 }
02675 
02681 void
02682 _dbus_string_zero (DBusString *str)
02683 {
02684   DBUS_STRING_PREAMBLE (str);
02685 
02686   memset (real->str - real->align_offset, '\0', real->allocated);
02687 }
02690 /* tests are in dbus-string-util.c */