D-Bus  1.8.20
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 
00250   /* so it's safe if @p str returned by a failed
00251    * _dbus_string_init call
00252    * Bug: https://bugs.freedesktop.org/show_bug.cgi?id=65959
00253    */
00254   if (real->str == NULL)
00255     return;
00256 
00257   dbus_free (real->str - real->align_offset);
00258 
00259   real->invalid = TRUE;
00260 }
00261 
00262 static dbus_bool_t
00263 compact (DBusRealString *real,
00264          int             max_waste)
00265 {
00266   unsigned char *new_str;
00267   int new_allocated;
00268   int waste;
00269 
00270   waste = real->allocated - (real->len + _DBUS_STRING_ALLOCATION_PADDING);
00271 
00272   if (waste <= max_waste)
00273     return TRUE;
00274 
00275   new_allocated = real->len + _DBUS_STRING_ALLOCATION_PADDING;
00276 
00277   new_str = dbus_realloc (real->str - real->align_offset, new_allocated);
00278   if (_DBUS_UNLIKELY (new_str == NULL))
00279     return FALSE;
00280 
00281   real->str = new_str + real->align_offset;
00282   real->allocated = new_allocated;
00283   fixup_alignment (real);
00284 
00285   return TRUE;
00286 }
00287 
00288 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
00289 /* Not using this feature at the moment,
00290  * so marked DBUS_ENABLE_EMBEDDED_TESTS-only
00291  */
00301 void
00302 _dbus_string_lock (DBusString *str)
00303 {  
00304   DBUS_LOCKED_STRING_PREAMBLE (str); /* can lock multiple times */
00305 
00306   real->locked = TRUE;
00307 
00308   /* Try to realloc to avoid excess memory usage, since
00309    * we know we won't change the string further
00310    */
00311 #define MAX_WASTE 48
00312   compact (real, MAX_WASTE);
00313 }
00314 #endif /* DBUS_ENABLE_EMBEDDED_TESTS */
00315 
00316 static dbus_bool_t
00317 reallocate_for_length (DBusRealString *real,
00318                        int             new_length)
00319 {
00320   int new_allocated;
00321   unsigned char *new_str;
00322 
00323   /* at least double our old allocation to avoid O(n), avoiding
00324    * overflow
00325    */
00326   if (real->allocated > (_DBUS_STRING_MAX_LENGTH + _DBUS_STRING_ALLOCATION_PADDING) / 2)
00327     new_allocated = _DBUS_STRING_MAX_LENGTH + _DBUS_STRING_ALLOCATION_PADDING;
00328   else
00329     new_allocated = real->allocated * 2;
00330 
00331   /* if you change the code just above here, run the tests without
00332    * the following assert-only hack before you commit
00333    */
00334   /* This is keyed off asserts in addition to tests so when you
00335    * disable asserts to profile, you don't get this destroyer
00336    * of profiles.
00337    */
00338 #if defined (DBUS_ENABLE_EMBEDDED_TESTS) && !defined (DBUS_DISABLE_ASSERT)
00339   new_allocated = 0; /* ensure a realloc every time so that we go
00340                       * through all malloc failure codepaths
00341                       */
00342 #endif
00343 
00344   /* But be sure we always alloc at least space for the new length */
00345   new_allocated = MAX (new_allocated,
00346                        new_length + _DBUS_STRING_ALLOCATION_PADDING);
00347 
00348   _dbus_assert (new_allocated >= real->allocated); /* code relies on this */
00349   new_str = dbus_realloc (real->str - real->align_offset, new_allocated);
00350   if (_DBUS_UNLIKELY (new_str == NULL))
00351     return FALSE;
00352 
00353   real->str = new_str + real->align_offset;
00354   real->allocated = new_allocated;
00355   fixup_alignment (real);
00356 
00357   return TRUE;
00358 }
00359 
00371 dbus_bool_t
00372 _dbus_string_compact (DBusString *str,
00373                       int         max_waste)
00374 {
00375   DBUS_STRING_PREAMBLE (str);
00376 
00377   return compact (real, max_waste);
00378 }
00379 
00380 static dbus_bool_t
00381 set_length (DBusRealString *real,
00382             int             new_length)
00383 {
00384   /* Note, we are setting the length not including nul termination */
00385 
00386   /* exceeding max length is the same as failure to allocate memory */
00387   if (_DBUS_UNLIKELY (new_length > _DBUS_STRING_MAX_LENGTH))
00388     return FALSE;
00389   else if (new_length > (real->allocated - _DBUS_STRING_ALLOCATION_PADDING) &&
00390            _DBUS_UNLIKELY (!reallocate_for_length (real, new_length)))
00391     return FALSE;
00392   else
00393     {
00394       real->len = new_length;
00395       real->str[new_length] = '\0';
00396       return TRUE;
00397     }
00398 }
00399 
00400 static dbus_bool_t
00401 open_gap (int             len,
00402           DBusRealString *dest,
00403           int             insert_at)
00404 {
00405   if (len == 0)
00406     return TRUE;
00407 
00408   if (len > _DBUS_STRING_MAX_LENGTH - dest->len)
00409     return FALSE; /* detected overflow of dest->len + len below */
00410   
00411   if (!set_length (dest, dest->len + len))
00412     return FALSE;
00413 
00414   memmove (dest->str + insert_at + len, 
00415            dest->str + insert_at,
00416            dest->len - len - insert_at);
00417 
00418   return TRUE;
00419 }
00420 
00421 #ifndef _dbus_string_get_data
00422 
00433 char*
00434 _dbus_string_get_data (DBusString *str)
00435 {
00436   DBUS_STRING_PREAMBLE (str);
00437   
00438   return (char*) real->str;
00439 }
00440 #endif /* _dbus_string_get_data */
00441 
00442 /* only do the function if we don't have the macro */
00443 #ifndef _dbus_string_get_const_data
00444 
00450 const char*
00451 _dbus_string_get_const_data (const DBusString  *str)
00452 {
00453   DBUS_CONST_STRING_PREAMBLE (str);
00454   
00455   return (const char*) real->str;
00456 }
00457 #endif /* _dbus_string_get_const_data */
00458 
00472 char*
00473 _dbus_string_get_data_len (DBusString *str,
00474                            int         start,
00475                            int         len)
00476 {
00477   DBUS_STRING_PREAMBLE (str);
00478   _dbus_assert (start >= 0);
00479   _dbus_assert (len >= 0);
00480   _dbus_assert (start <= real->len);
00481   _dbus_assert (len <= real->len - start);
00482   
00483   return (char*) real->str + start;
00484 }
00485 
00486 /* only do the function if we don't have the macro */
00487 #ifndef _dbus_string_get_const_data_len
00488 
00496 const char*
00497 _dbus_string_get_const_data_len (const DBusString  *str,
00498                                  int                start,
00499                                  int                len)
00500 {
00501   DBUS_CONST_STRING_PREAMBLE (str);
00502   _dbus_assert (start >= 0);
00503   _dbus_assert (len >= 0);
00504   _dbus_assert (start <= real->len);
00505   _dbus_assert (len <= real->len - start);
00506   
00507   return (const char*) real->str + start;
00508 }
00509 #endif /* _dbus_string_get_const_data_len */
00510 
00511 /* only do the function if we don't have the macro */
00512 #ifndef _dbus_string_set_byte
00513 
00520 void
00521 _dbus_string_set_byte (DBusString    *str,
00522                        int            i,
00523                        unsigned char  byte)
00524 {
00525   DBUS_STRING_PREAMBLE (str);
00526   _dbus_assert (i < real->len);
00527   _dbus_assert (i >= 0);
00528   
00529   real->str[i] = byte;
00530 }
00531 #endif /* _dbus_string_set_byte */
00532 
00533 /* only have the function if we didn't create a macro */
00534 #ifndef _dbus_string_get_byte
00535 
00544 unsigned char
00545 _dbus_string_get_byte (const DBusString  *str,
00546                        int                start)
00547 {
00548   DBUS_CONST_STRING_PREAMBLE (str);
00549   _dbus_assert (start <= real->len);
00550   _dbus_assert (start >= 0);
00551   
00552   return real->str[start];
00553 }
00554 #endif /* _dbus_string_get_byte */
00555 
00566 dbus_bool_t
00567 _dbus_string_insert_bytes (DBusString   *str,
00568                            int           i,
00569                            int           n_bytes,
00570                            unsigned char byte)
00571 {
00572   DBUS_STRING_PREAMBLE (str);
00573   _dbus_assert (i <= real->len);
00574   _dbus_assert (i >= 0);
00575   _dbus_assert (n_bytes >= 0);
00576 
00577   if (n_bytes == 0)
00578     return TRUE;
00579   
00580   if (!open_gap (n_bytes, real, i))
00581     return FALSE;
00582   
00583   memset (real->str + i, byte, n_bytes);
00584 
00585   return TRUE;
00586 }
00587 
00596 dbus_bool_t
00597 _dbus_string_insert_byte (DBusString   *str,
00598                            int           i,
00599                            unsigned char byte)
00600 {
00601   DBUS_STRING_PREAMBLE (str);
00602   _dbus_assert (i <= real->len);
00603   _dbus_assert (i >= 0);
00604   
00605   if (!open_gap (1, real, i))
00606     return FALSE;
00607 
00608   real->str[i] = byte;
00609 
00610   return TRUE;
00611 }
00612 
00623 dbus_bool_t
00624 _dbus_string_steal_data (DBusString        *str,
00625                          char             **data_return)
00626 {
00627   DBUS_STRING_PREAMBLE (str);
00628   _dbus_assert (data_return != NULL);
00629 
00630   undo_alignment (real);
00631   
00632   *data_return = (char*) real->str;
00633 
00634   /* reset the string */
00635   if (!_dbus_string_init (str))
00636     {
00637       /* hrm, put it back then */
00638       real->str = (unsigned char*) *data_return;
00639       *data_return = NULL;
00640       fixup_alignment (real);
00641       return FALSE;
00642     }
00643 
00644   return TRUE;
00645 }
00646 
00654 dbus_bool_t
00655 _dbus_string_copy_data (const DBusString  *str,
00656                         char             **data_return)
00657 {
00658   DBUS_CONST_STRING_PREAMBLE (str);
00659   _dbus_assert (data_return != NULL);
00660   
00661   *data_return = dbus_malloc (real->len + 1);
00662   if (*data_return == NULL)
00663     return FALSE;
00664 
00665   memcpy (*data_return, real->str, real->len + 1);
00666 
00667   return TRUE;
00668 }
00669 
00679 void
00680 _dbus_string_copy_to_buffer (const DBusString  *str,
00681                              char              *buffer,
00682                              int                avail_len)
00683 {
00684   DBUS_CONST_STRING_PREAMBLE (str);
00685 
00686   _dbus_assert (avail_len >= 0);
00687   _dbus_assert (avail_len >= real->len);
00688   
00689   memcpy (buffer, real->str, real->len);
00690 }
00691 
00701 void
00702 _dbus_string_copy_to_buffer_with_nul (const DBusString  *str,
00703                                       char              *buffer,
00704                                       int                avail_len)
00705 {
00706   DBUS_CONST_STRING_PREAMBLE (str);
00707 
00708   _dbus_assert (avail_len >= 0);
00709   _dbus_assert (avail_len > real->len);
00710   
00711   memcpy (buffer, real->str, real->len+1);
00712 }
00713 
00714 /* Only have the function if we don't have the macro */
00715 #ifndef _dbus_string_get_length
00716 
00721 int
00722 _dbus_string_get_length (const DBusString  *str)
00723 {
00724   DBUS_CONST_STRING_PREAMBLE (str);
00725   
00726   return real->len;
00727 }
00728 #endif /* !_dbus_string_get_length */
00729 
00742 dbus_bool_t
00743 _dbus_string_lengthen (DBusString *str,
00744                        int         additional_length)
00745 {
00746   DBUS_STRING_PREAMBLE (str);  
00747   _dbus_assert (additional_length >= 0);
00748 
00749   if (_DBUS_UNLIKELY (additional_length > _DBUS_STRING_MAX_LENGTH - real->len))
00750     return FALSE; /* would overflow */
00751   
00752   return set_length (real,
00753                      real->len + additional_length);
00754 }
00755 
00762 void
00763 _dbus_string_shorten (DBusString *str,
00764                       int         length_to_remove)
00765 {
00766   DBUS_STRING_PREAMBLE (str);
00767   _dbus_assert (length_to_remove >= 0);
00768   _dbus_assert (length_to_remove <= real->len);
00769 
00770   set_length (real,
00771               real->len - length_to_remove);
00772 }
00773 
00784 dbus_bool_t
00785 _dbus_string_set_length (DBusString *str,
00786                          int         length)
00787 {
00788   DBUS_STRING_PREAMBLE (str);
00789   _dbus_assert (length >= 0);
00790 
00791   return set_length (real, length);
00792 }
00793 
00794 static dbus_bool_t
00795 align_insert_point_then_open_gap (DBusString *str,
00796                                   int        *insert_at_p,
00797                                   int         alignment,
00798                                   int         gap_size)
00799 {
00800   unsigned long new_len; /* ulong to avoid _DBUS_ALIGN_VALUE overflow */
00801   unsigned long gap_pos;
00802   int insert_at;
00803   int delta;
00804   DBUS_STRING_PREAMBLE (str);
00805   _dbus_assert (alignment >= 1);
00806   _dbus_assert (alignment <= 8); /* it has to be a bug if > 8 */
00807 
00808   insert_at = *insert_at_p;
00809 
00810   _dbus_assert (insert_at <= real->len);
00811   
00812   gap_pos = _DBUS_ALIGN_VALUE (insert_at, alignment);
00813   new_len = real->len + (gap_pos - insert_at) + gap_size;
00814   
00815   if (_DBUS_UNLIKELY (new_len > (unsigned long) _DBUS_STRING_MAX_LENGTH))
00816     return FALSE;
00817   
00818   delta = new_len - real->len;
00819   _dbus_assert (delta >= 0);
00820 
00821   if (delta == 0) /* only happens if gap_size == 0 and insert_at is aligned already */
00822     {
00823       _dbus_assert (((unsigned long) *insert_at_p) == gap_pos);
00824       return TRUE;
00825     }
00826 
00827   if (_DBUS_UNLIKELY (!open_gap (new_len - real->len,
00828                                  real, insert_at)))
00829     return FALSE;
00830 
00831   /* nul the padding if we had to add any padding */
00832   if (gap_size < delta)
00833     {
00834       memset (&real->str[insert_at], '\0',
00835               gap_pos - insert_at);
00836     }
00837 
00838   *insert_at_p = gap_pos;
00839   
00840   return TRUE;
00841 }
00842 
00843 static dbus_bool_t
00844 align_length_then_lengthen (DBusString *str,
00845                             int         alignment,
00846                             int         then_lengthen_by)
00847 {
00848   int insert_at;
00849 
00850   insert_at = _dbus_string_get_length (str);
00851   
00852   return align_insert_point_then_open_gap (str,
00853                                            &insert_at,
00854                                            alignment, then_lengthen_by);
00855 }
00856 
00865 dbus_bool_t
00866 _dbus_string_align_length (DBusString *str,
00867                            int         alignment)
00868 {
00869   return align_length_then_lengthen (str, alignment, 0);
00870 }
00871 
00881 dbus_bool_t
00882 _dbus_string_alloc_space (DBusString        *str,
00883                           int                extra_bytes)
00884 {
00885   if (!_dbus_string_lengthen (str, extra_bytes))
00886     return FALSE;
00887   _dbus_string_shorten (str, extra_bytes);
00888 
00889   return TRUE;
00890 }
00891 
00892 static dbus_bool_t
00893 append (DBusRealString *real,
00894         const char     *buffer,
00895         int             buffer_len)
00896 {
00897   if (buffer_len == 0)
00898     return TRUE;
00899 
00900   if (!_dbus_string_lengthen ((DBusString*)real, buffer_len))
00901     return FALSE;
00902 
00903   memcpy (real->str + (real->len - buffer_len),
00904           buffer,
00905           buffer_len);
00906 
00907   return TRUE;
00908 }
00909 
00917 dbus_bool_t
00918 _dbus_string_append (DBusString *str,
00919                      const char *buffer)
00920 {
00921   unsigned long buffer_len;
00922   
00923   DBUS_STRING_PREAMBLE (str);
00924   _dbus_assert (buffer != NULL);
00925   
00926   buffer_len = strlen (buffer);
00927   if (buffer_len > (unsigned long) _DBUS_STRING_MAX_LENGTH)
00928     return FALSE;
00929   
00930   return append (real, buffer, buffer_len);
00931 }
00932 
00934 #define ASSIGN_2_OCTETS(p, octets) \
00935   *((dbus_uint16_t*)(p)) = *((dbus_uint16_t*)(octets));
00936 
00938 #define ASSIGN_4_OCTETS(p, octets) \
00939   *((dbus_uint32_t*)(p)) = *((dbus_uint32_t*)(octets));
00940 
00942 #define ASSIGN_8_OCTETS(p, octets) \
00943   *((dbus_uint64_t*)(p)) = *((dbus_uint64_t*)(octets));
00944 
00954 dbus_bool_t
00955 _dbus_string_insert_2_aligned (DBusString         *str,
00956                                int                 insert_at,
00957                                const unsigned char octets[2])
00958 {
00959   DBUS_STRING_PREAMBLE (str);
00960   
00961   if (!align_insert_point_then_open_gap (str, &insert_at, 2, 2))
00962     return FALSE;
00963 
00964   ASSIGN_2_OCTETS (real->str + insert_at, octets);
00965 
00966   return TRUE;
00967 }
00968 
00978 dbus_bool_t
00979 _dbus_string_insert_4_aligned (DBusString         *str,
00980                                int                 insert_at,
00981                                const unsigned char octets[4])
00982 {
00983   DBUS_STRING_PREAMBLE (str);
00984   
00985   if (!align_insert_point_then_open_gap (str, &insert_at, 4, 4))
00986     return FALSE;
00987 
00988   ASSIGN_4_OCTETS (real->str + insert_at, octets);
00989 
00990   return TRUE;
00991 }
00992 
01002 dbus_bool_t
01003 _dbus_string_insert_8_aligned (DBusString         *str,
01004                                int                 insert_at,
01005                                const unsigned char octets[8])
01006 {
01007   DBUS_STRING_PREAMBLE (str);
01008   
01009   if (!align_insert_point_then_open_gap (str, &insert_at, 8, 8))
01010     return FALSE;
01011 
01012   _dbus_assert (_DBUS_ALIGN_VALUE (insert_at, 8) == (unsigned) insert_at);
01013   
01014   ASSIGN_8_OCTETS (real->str + insert_at, octets);
01015 
01016   return TRUE;
01017 }
01018 
01019 
01030 dbus_bool_t
01031 _dbus_string_insert_alignment (DBusString        *str,
01032                                int               *insert_at,
01033                                int                alignment)
01034 {
01035   DBUS_STRING_PREAMBLE (str);
01036   
01037   if (!align_insert_point_then_open_gap (str, insert_at, alignment, 0))
01038     return FALSE;
01039 
01040   _dbus_assert (_DBUS_ALIGN_VALUE (*insert_at, alignment) == (unsigned) *insert_at);
01041 
01042   return TRUE;
01043 }
01044 
01054 dbus_bool_t
01055 _dbus_string_append_printf_valist  (DBusString        *str,
01056                                     const char        *format,
01057                                     va_list            args)
01058 {
01059   int len;
01060   va_list args_copy;
01061 
01062   DBUS_STRING_PREAMBLE (str);
01063 
01064   DBUS_VA_COPY (args_copy, args);
01065 
01066   /* Measure the message length without terminating nul */
01067   len = _dbus_printf_string_upper_bound (format, args);
01068 
01069   if (len < 0)
01070     return FALSE;
01071 
01072   if (!_dbus_string_lengthen (str, len))
01073     {
01074       /* don't leak the copy */
01075       va_end (args_copy);
01076       return FALSE;
01077     }
01078   
01079   vsprintf ((char*) (real->str + (real->len - len)),
01080             format, args_copy);
01081 
01082   va_end (args_copy);
01083 
01084   return TRUE;
01085 }
01086 
01095 dbus_bool_t
01096 _dbus_string_append_printf (DBusString        *str,
01097                             const char        *format,
01098                             ...)
01099 {
01100   va_list args;
01101   dbus_bool_t retval;
01102   
01103   va_start (args, format);
01104   retval = _dbus_string_append_printf_valist (str, format, args);
01105   va_end (args);
01106 
01107   return retval;
01108 }
01109 
01118 dbus_bool_t
01119 _dbus_string_append_len (DBusString *str,
01120                          const char *buffer,
01121                          int         len)
01122 {
01123   DBUS_STRING_PREAMBLE (str);
01124   _dbus_assert (buffer != NULL);
01125   _dbus_assert (len >= 0);
01126 
01127   return append (real, buffer, len);
01128 }
01129 
01138 dbus_bool_t
01139 _dbus_string_append_byte (DBusString    *str,
01140                           unsigned char  byte)
01141 {
01142   DBUS_STRING_PREAMBLE (str);
01143 
01144   if (!set_length (real, real->len + 1))
01145     return FALSE;
01146 
01147   real->str[real->len-1] = byte;
01148 
01149   return TRUE;
01150 }
01151 
01152 static void
01153 delete (DBusRealString *real,
01154         int             start,
01155         int             len)
01156 {
01157   if (len == 0)
01158     return;
01159   
01160   memmove (real->str + start, real->str + start + len, real->len - (start + len));
01161   real->len -= len;
01162   real->str[real->len] = '\0';
01163 }
01164 
01174 void
01175 _dbus_string_delete (DBusString       *str,
01176                      int               start,
01177                      int               len)
01178 {
01179   DBUS_STRING_PREAMBLE (str);
01180   _dbus_assert (start >= 0);
01181   _dbus_assert (len >= 0);
01182   _dbus_assert (start <= real->len);
01183   _dbus_assert (len <= real->len - start);
01184   
01185   delete (real, start, len);
01186 }
01187 
01188 static dbus_bool_t
01189 copy (DBusRealString *source,
01190       int             start,
01191       int             len,
01192       DBusRealString *dest,
01193       int             insert_at)
01194 {
01195   if (len == 0)
01196     return TRUE;
01197 
01198   if (!open_gap (len, dest, insert_at))
01199     return FALSE;
01200   
01201   memmove (dest->str + insert_at,
01202            source->str + start,
01203            len);
01204 
01205   return TRUE;
01206 }
01207 
01217 #define DBUS_STRING_COPY_PREAMBLE(source, start, dest, insert_at)       \
01218   DBusRealString *real_source = (DBusRealString*) source;               \
01219   DBusRealString *real_dest = (DBusRealString*) dest;                   \
01220   _dbus_assert ((source) != (dest));                                    \
01221   DBUS_GENERIC_STRING_PREAMBLE (real_source);                           \
01222   DBUS_GENERIC_STRING_PREAMBLE (real_dest);                             \
01223   _dbus_assert (!real_dest->constant);                                  \
01224   _dbus_assert (!real_dest->locked);                                    \
01225   _dbus_assert ((start) >= 0);                                          \
01226   _dbus_assert ((start) <= real_source->len);                           \
01227   _dbus_assert ((insert_at) >= 0);                                      \
01228   _dbus_assert ((insert_at) <= real_dest->len)
01229 
01240 dbus_bool_t
01241 _dbus_string_move (DBusString       *source,
01242                    int               start,
01243                    DBusString       *dest,
01244                    int               insert_at)
01245 {
01246   DBusRealString *real_source = (DBusRealString*) source;
01247   _dbus_assert (start <= real_source->len);
01248   
01249   return _dbus_string_move_len (source, start,
01250                                 real_source->len - start,
01251                                 dest, insert_at);
01252 }
01253 
01264 dbus_bool_t
01265 _dbus_string_copy (const DBusString *source,
01266                    int               start,
01267                    DBusString       *dest,
01268                    int               insert_at)
01269 {
01270   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
01271 
01272   return copy (real_source, start,
01273                real_source->len - start,
01274                real_dest,
01275                insert_at);
01276 }
01277 
01289 dbus_bool_t
01290 _dbus_string_move_len (DBusString       *source,
01291                        int               start,
01292                        int               len,
01293                        DBusString       *dest,
01294                        int               insert_at)
01295 
01296 {
01297   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
01298   _dbus_assert (len >= 0);
01299   _dbus_assert ((start + len) <= real_source->len);
01300 
01301 
01302   if (len == 0)
01303     {
01304       return TRUE;
01305     }
01306   else if (start == 0 &&
01307            len == real_source->len &&
01308            real_dest->len == 0)
01309     {
01310       /* Short-circuit moving an entire existing string to an empty string
01311        * by just swapping the buffers.
01312        */
01313       /* we assume ->constant doesn't matter as you can't have
01314        * a constant string involved in a move.
01315        */
01316 #define ASSIGN_DATA(a, b) do {                  \
01317         (a)->str = (b)->str;                    \
01318         (a)->len = (b)->len;                    \
01319         (a)->allocated = (b)->allocated;        \
01320         (a)->align_offset = (b)->align_offset;  \
01321       } while (0)
01322       
01323       DBusRealString tmp;
01324 
01325       ASSIGN_DATA (&tmp, real_source);
01326       ASSIGN_DATA (real_source, real_dest);
01327       ASSIGN_DATA (real_dest, &tmp);
01328 
01329       return TRUE;
01330     }
01331   else
01332     {
01333       if (!copy (real_source, start, len,
01334                  real_dest,
01335                  insert_at))
01336         return FALSE;
01337       
01338       delete (real_source, start,
01339               len);
01340       
01341       return TRUE;
01342     }
01343 }
01344 
01356 dbus_bool_t
01357 _dbus_string_copy_len (const DBusString *source,
01358                        int               start,
01359                        int               len,
01360                        DBusString       *dest,
01361                        int               insert_at)
01362 {
01363   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
01364   _dbus_assert (len >= 0);
01365   _dbus_assert (start <= real_source->len);
01366   _dbus_assert (len <= real_source->len - start);
01367   
01368   return copy (real_source, start, len,
01369                real_dest,
01370                insert_at);
01371 }
01372 
01385 dbus_bool_t
01386 _dbus_string_replace_len (const DBusString *source,
01387                           int               start,
01388                           int               len,
01389                           DBusString       *dest,
01390                           int               replace_at,
01391                           int               replace_len)
01392 {
01393   DBUS_STRING_COPY_PREAMBLE (source, start, dest, replace_at);
01394   _dbus_assert (len >= 0);
01395   _dbus_assert (start <= real_source->len);
01396   _dbus_assert (len <= real_source->len - start);
01397   _dbus_assert (replace_at >= 0);
01398   _dbus_assert (replace_at <= real_dest->len);
01399   _dbus_assert (replace_len <= real_dest->len - replace_at);
01400 
01401   if (len == replace_len)
01402     {
01403       memmove (real_dest->str + replace_at,
01404                real_source->str + start, len);
01405     }
01406   else if (len < replace_len)
01407     {
01408       memmove (real_dest->str + replace_at,
01409                real_source->str + start, len);
01410       delete (real_dest, replace_at + len,
01411               replace_len - len);
01412     }
01413   else
01414     {
01415       int diff;
01416 
01417       _dbus_assert (len > replace_len);
01418 
01419       diff = len - replace_len;
01420 
01421       /* First of all we check if destination string can be enlarged as
01422        * required, then we overwrite previous bytes
01423        */
01424 
01425       if (!copy (real_source, start + replace_len, diff,
01426                  real_dest, replace_at + replace_len))
01427         return FALSE;
01428 
01429       memmove (real_dest->str + replace_at,
01430                real_source->str + start, replace_len);
01431     }
01432 
01433   return TRUE;
01434 }
01435 
01448 dbus_bool_t
01449 _dbus_string_split_on_byte (DBusString        *source,
01450                             unsigned char      byte,
01451                             DBusString        *tail)
01452 {
01453   int byte_position;
01454   char byte_string[2] = "";
01455   int head_length;
01456   int tail_length;
01457 
01458   byte_string[0] = (char) byte;
01459 
01460   if (!_dbus_string_find (source, 0, byte_string, &byte_position))
01461     return FALSE;
01462 
01463   head_length = byte_position;
01464   tail_length = _dbus_string_get_length (source) - head_length - 1;
01465 
01466   if (!_dbus_string_move_len (source, byte_position + 1, tail_length,
01467                               tail, 0))
01468     return FALSE;
01469 
01470   /* remove the trailing delimiter byte from the head now.
01471    */
01472   if (!_dbus_string_set_length (source, head_length))
01473     return FALSE;
01474 
01475   return TRUE;
01476 }
01477 
01478 /* Unicode macros and utf8_validate() from GLib Owen Taylor, Havoc
01479  * Pennington, and Tom Tromey are the authors and authorized relicense.
01480  */
01481 
01487 #define UTF8_COMPUTE(Char, Mask, Len)                                         \
01488   if (Char < 128)                                                             \
01489     {                                                                         \
01490       Len = 1;                                                                \
01491       Mask = 0x7f;                                                            \
01492     }                                                                         \
01493   else if ((Char & 0xe0) == 0xc0)                                             \
01494     {                                                                         \
01495       Len = 2;                                                                \
01496       Mask = 0x1f;                                                            \
01497     }                                                                         \
01498   else if ((Char & 0xf0) == 0xe0)                                             \
01499     {                                                                         \
01500       Len = 3;                                                                \
01501       Mask = 0x0f;                                                            \
01502     }                                                                         \
01503   else if ((Char & 0xf8) == 0xf0)                                             \
01504     {                                                                         \
01505       Len = 4;                                                                \
01506       Mask = 0x07;                                                            \
01507     }                                                                         \
01508   else if ((Char & 0xfc) == 0xf8)                                             \
01509     {                                                                         \
01510       Len = 5;                                                                \
01511       Mask = 0x03;                                                            \
01512     }                                                                         \
01513   else if ((Char & 0xfe) == 0xfc)                                             \
01514     {                                                                         \
01515       Len = 6;                                                                \
01516       Mask = 0x01;                                                            \
01517     }                                                                         \
01518   else                                                                        \
01519     {                                                                         \
01520       Len = 0;                                                               \
01521       Mask = 0;                                                               \
01522     }
01523 
01528 #define UTF8_LENGTH(Char)              \
01529   ((Char) < 0x80 ? 1 :                 \
01530    ((Char) < 0x800 ? 2 :               \
01531     ((Char) < 0x10000 ? 3 :            \
01532      ((Char) < 0x200000 ? 4 :          \
01533       ((Char) < 0x4000000 ? 5 : 6)))))
01534    
01544 #define UTF8_GET(Result, Chars, Count, Mask, Len)                             \
01545   (Result) = (Chars)[0] & (Mask);                                             \
01546   for ((Count) = 1; (Count) < (Len); ++(Count))                               \
01547     {                                                                         \
01548       if (((Chars)[(Count)] & 0xc0) != 0x80)                                  \
01549         {                                                                     \
01550           (Result) = -1;                                                      \
01551           break;                                                              \
01552         }                                                                     \
01553       (Result) <<= 6;                                                         \
01554       (Result) |= ((Chars)[(Count)] & 0x3f);                                  \
01555     }
01556 
01567 #define UNICODE_VALID(Char)                   \
01568     ((Char) < 0x110000 &&                     \
01569      (((Char) & 0xFFFFF800) != 0xD800))
01570 
01585 dbus_bool_t
01586 _dbus_string_find (const DBusString *str,
01587                    int               start,
01588                    const char       *substr,
01589                    int              *found)
01590 {
01591   return _dbus_string_find_to (str, start,
01592                                ((const DBusRealString*)str)->len,
01593                                substr, found);
01594 }
01595 
01608 dbus_bool_t
01609 _dbus_string_find_eol (const DBusString *str,
01610                        int               start,
01611                        int              *found,
01612                        int              *found_len)
01613 {
01614   int i;
01615 
01616   DBUS_CONST_STRING_PREAMBLE (str);
01617   _dbus_assert (start <= real->len);
01618   _dbus_assert (start >= 0);
01619   
01620   i = start;
01621   while (i < real->len)
01622     {
01623       if (real->str[i] == '\r') 
01624         {
01625           if ((i+1) < real->len && real->str[i+1] == '\n') /* "\r\n" */
01626             {
01627               if (found) 
01628                 *found = i;
01629               if (found_len)
01630                 *found_len = 2;
01631               return TRUE;
01632             } 
01633           else /* only "\r" */
01634             {
01635               if (found) 
01636                 *found = i;
01637               if (found_len)
01638                 *found_len = 1;
01639               return TRUE;
01640             }
01641         } 
01642       else if (real->str[i] == '\n')  /* only "\n" */
01643         {
01644           if (found) 
01645             *found = i;
01646           if (found_len)
01647             *found_len = 1;
01648           return TRUE;
01649         }
01650       ++i;
01651     }
01652 
01653   if (found)
01654     *found = real->len;
01655 
01656   if (found_len)
01657     *found_len = 0;
01658   
01659   return FALSE;
01660 }
01661 
01678 dbus_bool_t
01679 _dbus_string_find_to (const DBusString *str,
01680                       int               start,
01681                       int               end,
01682                       const char       *substr,
01683                       int              *found)
01684 {
01685   int i;
01686   DBUS_CONST_STRING_PREAMBLE (str);
01687   _dbus_assert (substr != NULL);
01688   _dbus_assert (start <= real->len);
01689   _dbus_assert (start >= 0);
01690   _dbus_assert (substr != NULL);
01691   _dbus_assert (end <= real->len);
01692   _dbus_assert (start <= end);
01693 
01694   /* we always "find" an empty string */
01695   if (*substr == '\0')
01696     {
01697       if (found)
01698         *found = start;
01699       return TRUE;
01700     }
01701 
01702   i = start;
01703   while (i < end)
01704     {
01705       if (real->str[i] == substr[0])
01706         {
01707           int j = i + 1;
01708           
01709           while (j < end)
01710             {
01711               if (substr[j - i] == '\0')
01712                 break;
01713               else if (real->str[j] != substr[j - i])
01714                 break;
01715               
01716               ++j;
01717             }
01718 
01719           if (substr[j - i] == '\0')
01720             {
01721               if (found)
01722                 *found = i;
01723               return TRUE;
01724             }
01725         }
01726       
01727       ++i;
01728     }
01729 
01730   if (found)
01731     *found = end;
01732   
01733   return FALSE;  
01734 }
01735 
01746 dbus_bool_t
01747 _dbus_string_find_blank (const DBusString *str,
01748                          int               start,
01749                          int              *found)
01750 {
01751   int i;
01752   DBUS_CONST_STRING_PREAMBLE (str);
01753   _dbus_assert (start <= real->len);
01754   _dbus_assert (start >= 0);
01755   
01756   i = start;
01757   while (i < real->len)
01758     {
01759       if (real->str[i] == ' ' ||
01760           real->str[i] == '\t')
01761         {
01762           if (found)
01763             *found = i;
01764           return TRUE;
01765         }
01766       
01767       ++i;
01768     }
01769 
01770   if (found)
01771     *found = real->len;
01772   
01773   return FALSE;
01774 }
01775 
01784 void
01785 _dbus_string_skip_blank (const DBusString *str,
01786                          int               start,
01787                          int              *end)
01788 {
01789   int i;
01790   DBUS_CONST_STRING_PREAMBLE (str);
01791   _dbus_assert (start <= real->len);
01792   _dbus_assert (start >= 0);
01793   
01794   i = start;
01795   while (i < real->len)
01796     {
01797       if (!DBUS_IS_ASCII_BLANK (real->str[i]))
01798         break;
01799       
01800       ++i;
01801     }
01802 
01803   _dbus_assert (i == real->len || !DBUS_IS_ASCII_WHITE (real->str[i]));
01804   
01805   if (end)
01806     *end = i;
01807 }
01808 
01809 
01818 void
01819 _dbus_string_skip_white (const DBusString *str,
01820                          int               start,
01821                          int              *end)
01822 {
01823   int i;
01824   DBUS_CONST_STRING_PREAMBLE (str);
01825   _dbus_assert (start <= real->len);
01826   _dbus_assert (start >= 0);
01827   
01828   i = start;
01829   while (i < real->len)
01830     {
01831       if (!DBUS_IS_ASCII_WHITE (real->str[i]))
01832         break;
01833       
01834       ++i;
01835     }
01836 
01837   _dbus_assert (i == real->len || !(DBUS_IS_ASCII_WHITE (real->str[i])));
01838   
01839   if (end)
01840     *end = i;
01841 }
01842 
01851 void
01852 _dbus_string_skip_white_reverse (const DBusString *str,
01853                                  int               end,
01854                                  int              *start)
01855 {
01856   int i;
01857   DBUS_CONST_STRING_PREAMBLE (str);
01858   _dbus_assert (end <= real->len);
01859   _dbus_assert (end >= 0);
01860   
01861   i = end;
01862   while (i > 0)
01863     {
01864       if (!DBUS_IS_ASCII_WHITE (real->str[i-1]))
01865         break;
01866       --i;
01867     }
01868 
01869   _dbus_assert (i >= 0 && (i == 0 || !(DBUS_IS_ASCII_WHITE (real->str[i-1]))));
01870   
01871   if (start)
01872     *start = i;
01873 }
01874 
01890 dbus_bool_t
01891 _dbus_string_pop_line (DBusString *source,
01892                        DBusString *dest)
01893 {
01894   int eol, eol_len;
01895   
01896   _dbus_string_set_length (dest, 0);
01897   
01898   eol = 0;
01899   eol_len = 0;
01900   if (!_dbus_string_find_eol (source, 0, &eol, &eol_len))
01901     {
01902       _dbus_assert (eol == _dbus_string_get_length (source));
01903       if (eol == 0)
01904         {
01905           /* If there's no newline and source has zero length, we're done */
01906           return FALSE;
01907         }
01908       /* otherwise, the last line of the file has no eol characters */
01909     }
01910 
01911   /* remember eol can be 0 if it's an empty line, but eol_len should not be zero also
01912    * since find_eol returned TRUE
01913    */
01914   
01915   if (!_dbus_string_move_len (source, 0, eol + eol_len, dest, 0))
01916     return FALSE;
01917   
01918   /* remove line ending */
01919   if (!_dbus_string_set_length (dest, eol))
01920     {
01921       _dbus_assert_not_reached ("out of memory when shortening a string");
01922       return FALSE;
01923     }
01924 
01925   return TRUE;
01926 }
01927 
01928 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
01929 
01935 void
01936 _dbus_string_delete_first_word (DBusString *str)
01937 {
01938   int i;
01939   
01940   if (_dbus_string_find_blank (str, 0, &i))
01941     _dbus_string_skip_blank (str, i, &i);
01942 
01943   _dbus_string_delete (str, 0, i);
01944 }
01945 #endif
01946 
01947 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
01948 
01953 void
01954 _dbus_string_delete_leading_blanks (DBusString *str)
01955 {
01956   int i;
01957   
01958   _dbus_string_skip_blank (str, 0, &i);
01959 
01960   if (i > 0)
01961     _dbus_string_delete (str, 0, i);
01962 }
01963 #endif
01964 
01970 void
01971 _dbus_string_chop_white(DBusString *str)
01972 {
01973   int i;
01974   
01975   _dbus_string_skip_white (str, 0, &i);
01976 
01977   if (i > 0)
01978     _dbus_string_delete (str, 0, i);
01979   
01980   _dbus_string_skip_white_reverse (str, _dbus_string_get_length (str), &i);
01981 
01982   _dbus_string_set_length (str, i);
01983 }
01984 
01994 dbus_bool_t
01995 _dbus_string_equal (const DBusString *a,
01996                     const DBusString *b)
01997 {
01998   const unsigned char *ap;
01999   const unsigned char *bp;
02000   const unsigned char *a_end;
02001   const DBusRealString *real_a = (const DBusRealString*) a;
02002   const DBusRealString *real_b = (const DBusRealString*) b;
02003   DBUS_GENERIC_STRING_PREAMBLE (real_a);
02004   DBUS_GENERIC_STRING_PREAMBLE (real_b);
02005 
02006   if (real_a->len != real_b->len)
02007     return FALSE;
02008 
02009   ap = real_a->str;
02010   bp = real_b->str;
02011   a_end = real_a->str + real_a->len;
02012   while (ap != a_end)
02013     {
02014       if (*ap != *bp)
02015         return FALSE;
02016       
02017       ++ap;
02018       ++bp;
02019     }
02020 
02021   return TRUE;
02022 }
02023 
02037 dbus_bool_t
02038 _dbus_string_equal_len (const DBusString *a,
02039                         const DBusString *b,
02040                         int               len)
02041 {
02042   const unsigned char *ap;
02043   const unsigned char *bp;
02044   const unsigned char *a_end;
02045   const DBusRealString *real_a = (const DBusRealString*) a;
02046   const DBusRealString *real_b = (const DBusRealString*) b;
02047   DBUS_GENERIC_STRING_PREAMBLE (real_a);
02048   DBUS_GENERIC_STRING_PREAMBLE (real_b);
02049 
02050   if (real_a->len != real_b->len &&
02051       (real_a->len < len || real_b->len < len))
02052     return FALSE;
02053 
02054   ap = real_a->str;
02055   bp = real_b->str;
02056   a_end = real_a->str + MIN (real_a->len, len);
02057   while (ap != a_end)
02058     {
02059       if (*ap != *bp)
02060         return FALSE;
02061       
02062       ++ap;
02063       ++bp;
02064     }
02065 
02066   return TRUE;
02067 }
02068 
02085 dbus_bool_t
02086 _dbus_string_equal_substring (const DBusString  *a,
02087                               int                a_start,
02088                               int                a_len,
02089                               const DBusString  *b,
02090                               int                b_start)
02091 {
02092   const unsigned char *ap;
02093   const unsigned char *bp;
02094   const unsigned char *a_end;
02095   const DBusRealString *real_a = (const DBusRealString*) a;
02096   const DBusRealString *real_b = (const DBusRealString*) b;
02097   DBUS_GENERIC_STRING_PREAMBLE (real_a);
02098   DBUS_GENERIC_STRING_PREAMBLE (real_b);
02099   _dbus_assert (a_start >= 0);
02100   _dbus_assert (a_len >= 0);
02101   _dbus_assert (a_start <= real_a->len);
02102   _dbus_assert (a_len <= real_a->len - a_start);
02103   _dbus_assert (b_start >= 0);
02104   _dbus_assert (b_start <= real_b->len);
02105   
02106   if (a_len > real_b->len - b_start)
02107     return FALSE;
02108 
02109   ap = real_a->str + a_start;
02110   bp = real_b->str + b_start;
02111   a_end = ap + a_len;
02112   while (ap != a_end)
02113     {
02114       if (*ap != *bp)
02115         return FALSE;
02116       
02117       ++ap;
02118       ++bp;
02119     }
02120 
02121   _dbus_assert (bp <= (real_b->str + real_b->len));
02122   
02123   return TRUE;
02124 }
02125 
02133 dbus_bool_t
02134 _dbus_string_equal_c_str (const DBusString *a,
02135                           const char       *c_str)
02136 {
02137   const unsigned char *ap;
02138   const unsigned char *bp;
02139   const unsigned char *a_end;
02140   const DBusRealString *real_a = (const DBusRealString*) a;
02141   DBUS_GENERIC_STRING_PREAMBLE (real_a);
02142   _dbus_assert (c_str != NULL);
02143   
02144   ap = real_a->str;
02145   bp = (const unsigned char*) c_str;
02146   a_end = real_a->str + real_a->len;
02147   while (ap != a_end && *bp)
02148     {
02149       if (*ap != *bp)
02150         return FALSE;
02151       
02152       ++ap;
02153       ++bp;
02154     }
02155 
02156   if (ap != a_end || *bp)
02157     return FALSE;
02158   
02159   return TRUE;
02160 }
02161 
02169 dbus_bool_t
02170 _dbus_string_starts_with_c_str (const DBusString *a,
02171                                 const char       *c_str)
02172 {
02173   const unsigned char *ap;
02174   const unsigned char *bp;
02175   const unsigned char *a_end;
02176   const DBusRealString *real_a = (const DBusRealString*) a;
02177   DBUS_GENERIC_STRING_PREAMBLE (real_a);
02178   _dbus_assert (c_str != NULL);
02179   
02180   ap = real_a->str;
02181   bp = (const unsigned char*) c_str;
02182   a_end = real_a->str + real_a->len;
02183   while (ap != a_end && *bp)
02184     {
02185       if (*ap != *bp)
02186         return FALSE;
02187       
02188       ++ap;
02189       ++bp;
02190     }
02191 
02192   if (*bp == '\0')
02193     return TRUE;
02194   else
02195     return FALSE;
02196 }
02197 
02206 dbus_bool_t
02207 _dbus_string_append_byte_as_hex (DBusString *str,
02208                                  unsigned char byte)
02209 {
02210   const char hexdigits[16] = {
02211     '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
02212     'a', 'b', 'c', 'd', 'e', 'f'
02213   };
02214 
02215   if (!_dbus_string_append_byte (str,
02216                                  hexdigits[(byte >> 4)]))
02217     return FALSE;
02218   
02219   if (!_dbus_string_append_byte (str,
02220                                  hexdigits[(byte & 0x0f)]))
02221     {
02222       _dbus_string_set_length (str,
02223                                _dbus_string_get_length (str) - 1);
02224       return FALSE;
02225     }
02226 
02227   return TRUE;
02228 }
02229 
02240 dbus_bool_t
02241 _dbus_string_hex_encode (const DBusString *source,
02242                          int               start,
02243                          DBusString       *dest,
02244                          int               insert_at)
02245 {
02246   DBusString result;
02247   const unsigned char *p;
02248   const unsigned char *end;
02249   dbus_bool_t retval;
02250   
02251   _dbus_assert (start <= _dbus_string_get_length (source));
02252 
02253   if (!_dbus_string_init (&result))
02254     return FALSE;
02255 
02256   retval = FALSE;
02257   
02258   p = (const unsigned char*) _dbus_string_get_const_data (source);
02259   end = p + _dbus_string_get_length (source);
02260   p += start;
02261   
02262   while (p != end)
02263     {
02264       if (!_dbus_string_append_byte_as_hex (&result, *p))
02265         goto out;
02266       
02267       ++p;
02268     }
02269 
02270   if (!_dbus_string_move (&result, 0, dest, insert_at))
02271     goto out;
02272 
02273   retval = TRUE;
02274 
02275  out:
02276   _dbus_string_free (&result);
02277   return retval;
02278 }
02279 
02290 dbus_bool_t
02291 _dbus_string_hex_decode (const DBusString *source,
02292                          int               start,
02293                          int              *end_return,
02294                          DBusString       *dest,
02295                          int               insert_at)
02296 {
02297   DBusString result;
02298   const unsigned char *p;
02299   const unsigned char *end;
02300   dbus_bool_t retval;
02301   dbus_bool_t high_bits;
02302   
02303   _dbus_assert (start <= _dbus_string_get_length (source));
02304 
02305   if (!_dbus_string_init (&result))
02306     return FALSE;
02307 
02308   retval = FALSE;
02309 
02310   high_bits = TRUE;
02311   p = (const unsigned char*) _dbus_string_get_const_data (source);
02312   end = p + _dbus_string_get_length (source);
02313   p += start;
02314   
02315   while (p != end)
02316     {
02317       unsigned int val;
02318 
02319       switch (*p)
02320         {
02321         case '0':
02322           val = 0;
02323           break;
02324         case '1':
02325           val = 1;
02326           break;
02327         case '2':
02328           val = 2;
02329           break;
02330         case '3':
02331           val = 3;
02332           break;
02333         case '4':
02334           val = 4;
02335           break;
02336         case '5':
02337           val = 5;
02338           break;
02339         case '6':
02340           val = 6;
02341           break;
02342         case '7':
02343           val = 7;
02344           break;
02345         case '8':
02346           val = 8;
02347           break;
02348         case '9':
02349           val = 9;
02350           break;
02351         case 'a':
02352         case 'A':
02353           val = 10;
02354           break;
02355         case 'b':
02356         case 'B':
02357           val = 11;
02358           break;
02359         case 'c':
02360         case 'C':
02361           val = 12;
02362           break;
02363         case 'd':
02364         case 'D':
02365           val = 13;
02366           break;
02367         case 'e':
02368         case 'E':
02369           val = 14;
02370           break;
02371         case 'f':
02372         case 'F':
02373           val = 15;
02374           break;
02375         default:
02376           goto done;
02377         }
02378 
02379       if (high_bits)
02380         {
02381           if (!_dbus_string_append_byte (&result,
02382                                          val << 4))
02383             goto out;
02384         }
02385       else
02386         {
02387           int len;
02388           unsigned char b;
02389 
02390           len = _dbus_string_get_length (&result);
02391           
02392           b = _dbus_string_get_byte (&result, len - 1);
02393 
02394           b |= val;
02395 
02396           _dbus_string_set_byte (&result, len - 1, b);
02397         }
02398 
02399       high_bits = !high_bits;
02400 
02401       ++p;
02402     }
02403 
02404  done:
02405   if (!_dbus_string_move (&result, 0, dest, insert_at))
02406     goto out;
02407 
02408   if (end_return)
02409     *end_return = p - (const unsigned char*) _dbus_string_get_const_data (source);
02410 
02411   retval = TRUE;
02412   
02413  out:
02414   _dbus_string_free (&result);  
02415   return retval;
02416 }
02417 
02431 dbus_bool_t
02432 _dbus_string_validate_ascii (const DBusString *str,
02433                              int               start,
02434                              int               len)
02435 {
02436   const unsigned char *s;
02437   const unsigned char *end;
02438   DBUS_CONST_STRING_PREAMBLE (str);
02439   _dbus_assert (start >= 0);
02440   _dbus_assert (start <= real->len);
02441   _dbus_assert (len >= 0);
02442   
02443   if (len > real->len - start)
02444     return FALSE;
02445   
02446   s = real->str + start;
02447   end = s + len;
02448   while (s != end)
02449     {
02450       if (_DBUS_UNLIKELY (!_DBUS_ISASCII (*s)))
02451         return FALSE;
02452         
02453       ++s;
02454     }
02455   
02456   return TRUE;
02457 }
02458 
02466 void
02467 _dbus_string_tolower_ascii (const DBusString *str,
02468                             int               start,
02469                             int               len)
02470 {
02471   unsigned char *s;
02472   unsigned char *end;
02473   DBUS_STRING_PREAMBLE (str);
02474   _dbus_assert (start >= 0);
02475   _dbus_assert (start <= real->len);
02476   _dbus_assert (len >= 0);
02477   _dbus_assert (len <= real->len - start);
02478 
02479   s = real->str + start;
02480   end = s + len;
02481 
02482   while (s != end)
02483     {
02484       if (*s >= 'A' && *s <= 'Z')
02485           *s += 'a' - 'A';
02486       ++s;
02487     }
02488 }
02489 
02497 void
02498 _dbus_string_toupper_ascii (const DBusString *str,
02499                             int               start,
02500                             int               len)
02501 {
02502   unsigned char *s;
02503   unsigned char *end;
02504   DBUS_STRING_PREAMBLE (str);
02505   _dbus_assert (start >= 0);
02506   _dbus_assert (start <= real->len);
02507   _dbus_assert (len >= 0);
02508   _dbus_assert (len <= real->len - start);
02509 
02510   s = real->str + start;
02511   end = s + len;
02512 
02513   while (s != end)
02514     {
02515       if (*s >= 'a' && *s <= 'z')
02516           *s += 'A' - 'a';
02517       ++s;
02518     }
02519 }
02520 
02536 dbus_bool_t
02537 _dbus_string_validate_utf8  (const DBusString *str,
02538                              int               start,
02539                              int               len)
02540 {
02541   const unsigned char *p;
02542   const unsigned char *end;
02543   DBUS_CONST_STRING_PREAMBLE (str);
02544   _dbus_assert (start >= 0);
02545   _dbus_assert (start <= real->len);
02546   _dbus_assert (len >= 0);
02547 
02548   /* we are doing _DBUS_UNLIKELY() here which might be
02549    * dubious in a generic library like GLib, but in D-Bus
02550    * we know we're validating messages and that it would
02551    * only be evil/broken apps that would have invalid
02552    * UTF-8. Also, this function seems to be a performance
02553    * bottleneck in profiles.
02554    */
02555   
02556   if (_DBUS_UNLIKELY (len > real->len - start))
02557     return FALSE;
02558   
02559   p = real->str + start;
02560   end = p + len;
02561   
02562   while (p < end)
02563     {
02564       int i, mask, char_len;
02565       dbus_unichar_t result;
02566 
02567       /* nul bytes considered invalid */
02568       if (*p == '\0')
02569         break;
02570       
02571       /* Special-case ASCII; this makes us go a lot faster in
02572        * D-Bus profiles where we are typically validating
02573        * function names and such. We have to know that
02574        * all following checks will pass for ASCII though,
02575        * comments follow ...
02576        */      
02577       if (*p < 128)
02578         {
02579           ++p;
02580           continue;
02581         }
02582       
02583       UTF8_COMPUTE (*p, mask, char_len);
02584 
02585       if (_DBUS_UNLIKELY (char_len == 0))  /* ASCII: char_len == 1 */
02586         break;
02587 
02588       /* check that the expected number of bytes exists in the remaining length */
02589       if (_DBUS_UNLIKELY ((end - p) < char_len)) /* ASCII: p < end and char_len == 1 */
02590         break;
02591         
02592       UTF8_GET (result, p, i, mask, char_len);
02593 
02594       /* Check for overlong UTF-8 */
02595       if (_DBUS_UNLIKELY (UTF8_LENGTH (result) != char_len)) /* ASCII: UTF8_LENGTH == 1 */
02596         break;
02597 #if 0
02598       /* The UNICODE_VALID check below will catch this */
02599       if (_DBUS_UNLIKELY (result == (dbus_unichar_t)-1)) /* ASCII: result = ascii value */
02600         break;
02601 #endif
02602 
02603       if (_DBUS_UNLIKELY (!UNICODE_VALID (result))) /* ASCII: always valid */
02604         break;
02605 
02606       /* UNICODE_VALID should have caught it */
02607       _dbus_assert (result != (dbus_unichar_t)-1);
02608       
02609       p += char_len;
02610     }
02611 
02612   /* See that we covered the entire length if a length was
02613    * passed in
02614    */
02615   if (_DBUS_UNLIKELY (p != end))
02616     return FALSE;
02617   else
02618     return TRUE;
02619 }
02620 
02634 dbus_bool_t
02635 _dbus_string_validate_nul (const DBusString *str,
02636                            int               start,
02637                            int               len)
02638 {
02639   const unsigned char *s;
02640   const unsigned char *end;
02641   DBUS_CONST_STRING_PREAMBLE (str);
02642   _dbus_assert (start >= 0);
02643   _dbus_assert (len >= 0);
02644   _dbus_assert (start <= real->len);
02645   
02646   if (len > real->len - start)
02647     return FALSE;
02648   
02649   s = real->str + start;
02650   end = s + len;
02651   while (s != end)
02652     {
02653       if (_DBUS_UNLIKELY (*s != '\0'))
02654         return FALSE;
02655       ++s;
02656     }
02657   
02658   return TRUE;
02659 }
02660 
02666 void
02667 _dbus_string_zero (DBusString *str)
02668 {
02669   DBUS_STRING_PREAMBLE (str);
02670 
02671   memset (real->str - real->align_offset, '\0', real->allocated);
02672 }
02675 /* tests are in dbus-string-util.c */