• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List

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 "dbus-internals.h"
00026 #include "dbus-string.h"
00027 /* we allow a system header here, for speed/convenience */
00028 #include <string.h>
00029 /* for vsnprintf */
00030 #include <stdio.h>
00031 #define DBUS_CAN_USE_DBUS_STRING_PRIVATE 1
00032 #include "dbus-string-private.h"
00033 #include "dbus-marshal-basic.h" /* probably should be removed by moving the usage of DBUS_TYPE
00034                                  * into the marshaling-related files
00035                                  */
00036 /* for DBUS_VA_COPY */
00037 #include "dbus-sysdeps.h"
00038 
00077 static void
00078 fixup_alignment (DBusRealString *real)
00079 {
00080   unsigned char *aligned;
00081   unsigned char *real_block;
00082   unsigned int old_align_offset;
00083 
00084   /* we have to have extra space in real->allocated for the align offset and nul byte */
00085   _dbus_assert (real->len <= real->allocated - _DBUS_STRING_ALLOCATION_PADDING);
00086   
00087   old_align_offset = real->align_offset;
00088   real_block = real->str - old_align_offset;
00089   
00090   aligned = _DBUS_ALIGN_ADDRESS (real_block, 8);
00091 
00092   real->align_offset = aligned - real_block;
00093   real->str = aligned;
00094   
00095   if (old_align_offset != real->align_offset)
00096     {
00097       /* Here comes the suck */
00098       memmove (real_block + real->align_offset,
00099                real_block + old_align_offset,
00100                real->len + 1);
00101     }
00102 
00103   _dbus_assert (real->align_offset < 8);
00104   _dbus_assert (_DBUS_ALIGN_ADDRESS (real->str, 8) == real->str);
00105 }
00106 
00107 static void
00108 undo_alignment (DBusRealString *real)
00109 {
00110   if (real->align_offset != 0)
00111     {
00112       memmove (real->str - real->align_offset,
00113                real->str,
00114                real->len + 1);
00115 
00116       real->str = real->str - real->align_offset;
00117       real->align_offset = 0;
00118     }
00119 }
00120 
00130 dbus_bool_t
00131 _dbus_string_init_preallocated (DBusString *str,
00132                                 int         allocate_size)
00133 {
00134   DBusRealString *real;
00135   
00136   _dbus_assert (str != NULL);
00137 
00138   _dbus_assert (sizeof (DBusString) == sizeof (DBusRealString));
00139   
00140   real = (DBusRealString*) str;
00141 
00142   /* It's very important not to touch anything
00143    * other than real->str if we're going to fail,
00144    * since we also use this function to reset
00145    * an existing string, e.g. in _dbus_string_steal_data()
00146    */
00147   
00148   real->str = dbus_malloc (_DBUS_STRING_ALLOCATION_PADDING + allocate_size);
00149   if (real->str == NULL)
00150     return FALSE;  
00151   
00152   real->allocated = _DBUS_STRING_ALLOCATION_PADDING + allocate_size;
00153   real->len = 0;
00154   real->str[real->len] = '\0';
00155   
00156   real->max_length = _DBUS_STRING_MAX_MAX_LENGTH;
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 
00180 #ifdef DBUS_BUILD_TESTS
00181 /* The max length thing is sort of a historical artifact
00182  * from a feature that turned out to be dumb; perhaps
00183  * we should purge it entirely. The problem with
00184  * the feature is that it looks like memory allocation
00185  * failure, but is not a transient or resolvable failure.
00186  */
00187 static void
00188 set_max_length (DBusString *str,
00189                 int         max_length)
00190 {
00191   DBusRealString *real;
00192   
00193   real = (DBusRealString*) str;
00194 
00195   real->max_length = max_length;
00196 }
00197 #endif /* DBUS_BUILD_TESTS */
00198 
00208 void
00209 _dbus_string_init_const (DBusString *str,
00210                          const char *value)
00211 {
00212   _dbus_assert (value != NULL);
00213   
00214   _dbus_string_init_const_len (str, value,
00215                                strlen (value));
00216 }
00217 
00228 void
00229 _dbus_string_init_const_len (DBusString *str,
00230                              const char *value,
00231                              int         len)
00232 {
00233   DBusRealString *real;
00234   
00235   _dbus_assert (str != NULL);
00236   _dbus_assert (len == 0 || value != NULL);
00237   _dbus_assert (len <= _DBUS_STRING_MAX_MAX_LENGTH);
00238   _dbus_assert (len >= 0);
00239   
00240   real = (DBusRealString*) str;
00241   
00242   real->str = (unsigned char*) value;
00243   real->len = len;
00244   real->allocated = real->len + _DBUS_STRING_ALLOCATION_PADDING; /* a lie, just to avoid special-case assertions... */
00245   real->max_length = real->len + 1;
00246   real->constant = TRUE;
00247   real->locked = TRUE;
00248   real->invalid = FALSE;
00249   real->align_offset = 0;
00250 
00251   /* We don't require const strings to be 8-byte aligned as the
00252    * memory is coming from elsewhere.
00253    */
00254 }
00255 
00261 void
00262 _dbus_string_free (DBusString *str)
00263 {
00264   DBusRealString *real = (DBusRealString*) str;
00265   DBUS_GENERIC_STRING_PREAMBLE (real);
00266   
00267   if (real->constant)
00268     return;
00269   dbus_free (real->str - real->align_offset);
00270 
00271   real->invalid = TRUE;
00272 }
00273 
00274 static dbus_bool_t
00275 compact (DBusRealString *real,
00276          int             max_waste)
00277 {
00278   unsigned char *new_str;
00279   int new_allocated;
00280   int waste;
00281 
00282   waste = real->allocated - (real->len + _DBUS_STRING_ALLOCATION_PADDING);
00283 
00284   if (waste <= max_waste)
00285     return TRUE;
00286 
00287   new_allocated = real->len + _DBUS_STRING_ALLOCATION_PADDING;
00288 
00289   new_str = dbus_realloc (real->str - real->align_offset, new_allocated);
00290   if (_DBUS_UNLIKELY (new_str == NULL))
00291     return FALSE;
00292 
00293   real->str = new_str + real->align_offset;
00294   real->allocated = new_allocated;
00295   fixup_alignment (real);
00296 
00297   return TRUE;
00298 }
00299 
00300 #ifdef DBUS_BUILD_TESTS
00301 /* Not using this feature at the moment,
00302  * so marked DBUS_BUILD_TESTS-only
00303  */
00313 void
00314 _dbus_string_lock (DBusString *str)
00315 {  
00316   DBUS_LOCKED_STRING_PREAMBLE (str); /* can lock multiple times */
00317 
00318   real->locked = TRUE;
00319 
00320   /* Try to realloc to avoid excess memory usage, since
00321    * we know we won't change the string further
00322    */
00323 #define MAX_WASTE 48
00324   compact (real, MAX_WASTE);
00325 }
00326 #endif /* DBUS_BUILD_TESTS */
00327 
00328 static dbus_bool_t
00329 reallocate_for_length (DBusRealString *real,
00330                        int             new_length)
00331 {
00332   int new_allocated;
00333   unsigned char *new_str;
00334 
00335   /* at least double our old allocation to avoid O(n), avoiding
00336    * overflow
00337    */
00338   if (real->allocated > (_DBUS_STRING_MAX_MAX_LENGTH + _DBUS_STRING_ALLOCATION_PADDING) / 2)
00339     new_allocated = _DBUS_STRING_MAX_MAX_LENGTH + _DBUS_STRING_ALLOCATION_PADDING;
00340   else
00341     new_allocated = real->allocated * 2;
00342 
00343   /* if you change the code just above here, run the tests without
00344    * the following assert-only hack before you commit
00345    */
00346   /* This is keyed off asserts in addition to tests so when you
00347    * disable asserts to profile, you don't get this destroyer
00348    * of profiles.
00349    */
00350 #ifdef DBUS_DISABLE_ASSERT
00351 #else
00352 #ifdef DBUS_BUILD_TESTS
00353   new_allocated = 0; /* ensure a realloc every time so that we go
00354                       * through all malloc failure codepaths
00355                       */
00356 #endif /* DBUS_BUILD_TESTS */
00357 #endif /* !DBUS_DISABLE_ASSERT */
00358 
00359   /* But be sure we always alloc at least space for the new length */
00360   new_allocated = MAX (new_allocated,
00361                        new_length + _DBUS_STRING_ALLOCATION_PADDING);
00362 
00363   _dbus_assert (new_allocated >= real->allocated); /* code relies on this */
00364   new_str = dbus_realloc (real->str - real->align_offset, new_allocated);
00365   if (_DBUS_UNLIKELY (new_str == NULL))
00366     return FALSE;
00367 
00368   real->str = new_str + real->align_offset;
00369   real->allocated = new_allocated;
00370   fixup_alignment (real);
00371 
00372   return TRUE;
00373 }
00374 
00386 dbus_bool_t
00387 _dbus_string_compact (DBusString *str,
00388                       int         max_waste)
00389 {
00390   DBUS_STRING_PREAMBLE (str);
00391 
00392   return compact (real, max_waste);
00393 }
00394 
00395 static dbus_bool_t
00396 set_length (DBusRealString *real,
00397             int             new_length)
00398 {
00399   /* Note, we are setting the length not including nul termination */
00400 
00401   /* exceeding max length is the same as failure to allocate memory */
00402   if (_DBUS_UNLIKELY (new_length > real->max_length))
00403     return FALSE;
00404   else if (new_length > (real->allocated - _DBUS_STRING_ALLOCATION_PADDING) &&
00405            _DBUS_UNLIKELY (!reallocate_for_length (real, new_length)))
00406     return FALSE;
00407   else
00408     {
00409       real->len = new_length;
00410       real->str[new_length] = '\0';
00411       return TRUE;
00412     }
00413 }
00414 
00415 static dbus_bool_t
00416 open_gap (int             len,
00417           DBusRealString *dest,
00418           int             insert_at)
00419 {
00420   if (len == 0)
00421     return TRUE;
00422 
00423   if (len > dest->max_length - dest->len)
00424     return FALSE; /* detected overflow of dest->len + len below */
00425   
00426   if (!set_length (dest, dest->len + len))
00427     return FALSE;
00428 
00429   memmove (dest->str + insert_at + len, 
00430            dest->str + insert_at,
00431            dest->len - len - insert_at);
00432 
00433   return TRUE;
00434 }
00435 
00436 #ifndef _dbus_string_get_data
00437 
00448 char*
00449 _dbus_string_get_data (DBusString *str)
00450 {
00451   DBUS_STRING_PREAMBLE (str);
00452   
00453   return (char*) real->str;
00454 }
00455 #endif /* _dbus_string_get_data */
00456 
00457 /* only do the function if we don't have the macro */
00458 #ifndef _dbus_string_get_const_data
00459 
00465 const char*
00466 _dbus_string_get_const_data (const DBusString  *str)
00467 {
00468   DBUS_CONST_STRING_PREAMBLE (str);
00469   
00470   return (const char*) real->str;
00471 }
00472 #endif /* _dbus_string_get_const_data */
00473 
00487 char*
00488 _dbus_string_get_data_len (DBusString *str,
00489                            int         start,
00490                            int         len)
00491 {
00492   DBUS_STRING_PREAMBLE (str);
00493   _dbus_assert (start >= 0);
00494   _dbus_assert (len >= 0);
00495   _dbus_assert (start <= real->len);
00496   _dbus_assert (len <= real->len - start);
00497   
00498   return (char*) real->str + start;
00499 }
00500 
00501 /* only do the function if we don't have the macro */
00502 #ifndef _dbus_string_get_const_data_len
00503 
00511 const char*
00512 _dbus_string_get_const_data_len (const DBusString  *str,
00513                                  int                start,
00514                                  int                len)
00515 {
00516   DBUS_CONST_STRING_PREAMBLE (str);
00517   _dbus_assert (start >= 0);
00518   _dbus_assert (len >= 0);
00519   _dbus_assert (start <= real->len);
00520   _dbus_assert (len <= real->len - start);
00521   
00522   return (const char*) real->str + start;
00523 }
00524 #endif /* _dbus_string_get_const_data_len */
00525 
00526 /* only do the function if we don't have the macro */
00527 #ifndef _dbus_string_set_byte
00528 
00535 void
00536 _dbus_string_set_byte (DBusString    *str,
00537                        int            i,
00538                        unsigned char  byte)
00539 {
00540   DBUS_STRING_PREAMBLE (str);
00541   _dbus_assert (i < real->len);
00542   _dbus_assert (i >= 0);
00543   
00544   real->str[i] = byte;
00545 }
00546 #endif /* _dbus_string_set_byte */
00547 
00548 /* only have the function if we didn't create a macro */
00549 #ifndef _dbus_string_get_byte
00550 
00559 unsigned char
00560 _dbus_string_get_byte (const DBusString  *str,
00561                        int                start)
00562 {
00563   DBUS_CONST_STRING_PREAMBLE (str);
00564   _dbus_assert (start <= real->len);
00565   _dbus_assert (start >= 0);
00566   
00567   return real->str[start];
00568 }
00569 #endif /* _dbus_string_get_byte */
00570 
00581 dbus_bool_t
00582 _dbus_string_insert_bytes (DBusString   *str,
00583                            int           i,
00584                            int           n_bytes,
00585                            unsigned char byte)
00586 {
00587   DBUS_STRING_PREAMBLE (str);
00588   _dbus_assert (i <= real->len);
00589   _dbus_assert (i >= 0);
00590   _dbus_assert (n_bytes >= 0);
00591 
00592   if (n_bytes == 0)
00593     return TRUE;
00594   
00595   if (!open_gap (n_bytes, real, i))
00596     return FALSE;
00597   
00598   memset (real->str + i, byte, n_bytes);
00599 
00600   return TRUE;
00601 }
00602 
00611 dbus_bool_t
00612 _dbus_string_insert_byte (DBusString   *str,
00613                            int           i,
00614                            unsigned char byte)
00615 {
00616   DBUS_STRING_PREAMBLE (str);
00617   _dbus_assert (i <= real->len);
00618   _dbus_assert (i >= 0);
00619   
00620   if (!open_gap (1, real, i))
00621     return FALSE;
00622 
00623   real->str[i] = byte;
00624 
00625   return TRUE;
00626 }
00627 
00638 dbus_bool_t
00639 _dbus_string_steal_data (DBusString        *str,
00640                          char             **data_return)
00641 {
00642   int old_max_length;
00643   DBUS_STRING_PREAMBLE (str);
00644   _dbus_assert (data_return != NULL);
00645 
00646   undo_alignment (real);
00647   
00648   *data_return = (char*) real->str;
00649 
00650   old_max_length = real->max_length;
00651   
00652   /* reset the string */
00653   if (!_dbus_string_init (str))
00654     {
00655       /* hrm, put it back then */
00656       real->str = (unsigned char*) *data_return;
00657       *data_return = NULL;
00658       fixup_alignment (real);
00659       return FALSE;
00660     }
00661 
00662   real->max_length = old_max_length;
00663 
00664   return TRUE;
00665 }
00666 
00667 #ifdef DBUS_BUILD_TESTS
00668 
00683 dbus_bool_t
00684 _dbus_string_steal_data_len (DBusString        *str,
00685                              char             **data_return,
00686                              int                start,
00687                              int                len)
00688 {
00689   DBusString dest;
00690   DBUS_STRING_PREAMBLE (str);
00691   _dbus_assert (data_return != NULL);
00692   _dbus_assert (start >= 0);
00693   _dbus_assert (len >= 0);
00694   _dbus_assert (start <= real->len);
00695   _dbus_assert (len <= real->len - start);
00696 
00697   if (!_dbus_string_init (&dest))
00698     return FALSE;
00699 
00700   set_max_length (&dest, real->max_length);
00701   
00702   if (!_dbus_string_move_len (str, start, len, &dest, 0))
00703     {
00704       _dbus_string_free (&dest);
00705       return FALSE;
00706     }
00707 
00708   _dbus_warn ("Broken code in _dbus_string_steal_data_len(), see @todo, FIXME\n");
00709   if (!_dbus_string_steal_data (&dest, data_return))
00710     {
00711       _dbus_string_free (&dest);
00712       return FALSE;
00713     }
00714 
00715   _dbus_string_free (&dest);
00716   return TRUE;
00717 }
00718 #endif /* DBUS_BUILD_TESTS */
00719 
00727 dbus_bool_t
00728 _dbus_string_copy_data (const DBusString  *str,
00729                         char             **data_return)
00730 {
00731   DBUS_CONST_STRING_PREAMBLE (str);
00732   _dbus_assert (data_return != NULL);
00733   
00734   *data_return = dbus_malloc (real->len + 1);
00735   if (*data_return == NULL)
00736     return FALSE;
00737 
00738   memcpy (*data_return, real->str, real->len + 1);
00739 
00740   return TRUE;
00741 }
00742 
00752 void
00753 _dbus_string_copy_to_buffer (const DBusString  *str,
00754                              char              *buffer,
00755                              int                avail_len)
00756 {
00757   DBUS_CONST_STRING_PREAMBLE (str);
00758 
00759   _dbus_assert (avail_len >= 0);
00760   _dbus_assert (avail_len >= real->len);
00761   
00762   memcpy (buffer, real->str, real->len);
00763 }
00764 
00774 void
00775 _dbus_string_copy_to_buffer_with_nul (const DBusString  *str,
00776                                       char              *buffer,
00777                                       int                avail_len)
00778 {
00779   DBUS_CONST_STRING_PREAMBLE (str);
00780 
00781   _dbus_assert (avail_len >= 0);
00782   _dbus_assert (avail_len > real->len);
00783   
00784   memcpy (buffer, real->str, real->len+1);
00785 }
00786 
00787 #ifdef DBUS_BUILD_TESTS
00788 
00797 dbus_bool_t
00798 _dbus_string_copy_data_len (const DBusString  *str,
00799                             char             **data_return,
00800                             int                start,
00801                             int                len)
00802 {
00803   DBusString dest;
00804 
00805   DBUS_CONST_STRING_PREAMBLE (str);
00806   _dbus_assert (data_return != NULL);
00807   _dbus_assert (start >= 0);
00808   _dbus_assert (len >= 0);
00809   _dbus_assert (start <= real->len);
00810   _dbus_assert (len <= real->len - start);
00811 
00812   if (!_dbus_string_init (&dest))
00813     return FALSE;
00814 
00815   set_max_length (&dest, real->max_length);
00816 
00817   if (!_dbus_string_copy_len (str, start, len, &dest, 0))
00818     {
00819       _dbus_string_free (&dest);
00820       return FALSE;
00821     }
00822 
00823   if (!_dbus_string_steal_data (&dest, data_return))
00824     {
00825       _dbus_string_free (&dest);
00826       return FALSE;
00827     }
00828 
00829   _dbus_string_free (&dest);
00830   return TRUE;
00831 }
00832 #endif /* DBUS_BUILD_TESTS */
00833 
00834 /* Only have the function if we don't have the macro */
00835 #ifndef _dbus_string_get_length
00836 
00841 int
00842 _dbus_string_get_length (const DBusString  *str)
00843 {
00844   DBUS_CONST_STRING_PREAMBLE (str);
00845   
00846   return real->len;
00847 }
00848 #endif /* !_dbus_string_get_length */
00849 
00862 dbus_bool_t
00863 _dbus_string_lengthen (DBusString *str,
00864                        int         additional_length)
00865 {
00866   DBUS_STRING_PREAMBLE (str);  
00867   _dbus_assert (additional_length >= 0);
00868 
00869   if (_DBUS_UNLIKELY (additional_length > real->max_length - real->len))
00870     return FALSE; /* would overflow */
00871   
00872   return set_length (real,
00873                      real->len + additional_length);
00874 }
00875 
00882 void
00883 _dbus_string_shorten (DBusString *str,
00884                       int         length_to_remove)
00885 {
00886   DBUS_STRING_PREAMBLE (str);
00887   _dbus_assert (length_to_remove >= 0);
00888   _dbus_assert (length_to_remove <= real->len);
00889 
00890   set_length (real,
00891               real->len - length_to_remove);
00892 }
00893 
00904 dbus_bool_t
00905 _dbus_string_set_length (DBusString *str,
00906                          int         length)
00907 {
00908   DBUS_STRING_PREAMBLE (str);
00909   _dbus_assert (length >= 0);
00910 
00911   return set_length (real, length);
00912 }
00913 
00914 static dbus_bool_t
00915 align_insert_point_then_open_gap (DBusString *str,
00916                                   int        *insert_at_p,
00917                                   int         alignment,
00918                                   int         gap_size)
00919 {
00920   unsigned long new_len; /* ulong to avoid _DBUS_ALIGN_VALUE overflow */
00921   unsigned long gap_pos;
00922   int insert_at;
00923   int delta;
00924   DBUS_STRING_PREAMBLE (str);
00925   _dbus_assert (alignment >= 1);
00926   _dbus_assert (alignment <= 8); /* it has to be a bug if > 8 */
00927 
00928   insert_at = *insert_at_p;
00929 
00930   _dbus_assert (insert_at <= real->len);
00931   
00932   gap_pos = _DBUS_ALIGN_VALUE (insert_at, alignment);
00933   new_len = real->len + (gap_pos - insert_at) + gap_size;
00934   
00935   if (_DBUS_UNLIKELY (new_len > (unsigned long) real->max_length))
00936     return FALSE;
00937   
00938   delta = new_len - real->len;
00939   _dbus_assert (delta >= 0);
00940 
00941   if (delta == 0) /* only happens if gap_size == 0 and insert_at is aligned already */
00942     {
00943       _dbus_assert (((unsigned long) *insert_at_p) == gap_pos);
00944       return TRUE;
00945     }
00946 
00947   if (_DBUS_UNLIKELY (!open_gap (new_len - real->len,
00948                                  real, insert_at)))
00949     return FALSE;
00950 
00951   /* nul the padding if we had to add any padding */
00952   if (gap_size < delta)
00953     {
00954       memset (&real->str[insert_at], '\0',
00955               gap_pos - insert_at);
00956     }
00957 
00958   *insert_at_p = gap_pos;
00959   
00960   return TRUE;
00961 }
00962 
00963 static dbus_bool_t
00964 align_length_then_lengthen (DBusString *str,
00965                             int         alignment,
00966                             int         then_lengthen_by)
00967 {
00968   int insert_at;
00969 
00970   insert_at = _dbus_string_get_length (str);
00971   
00972   return align_insert_point_then_open_gap (str,
00973                                            &insert_at,
00974                                            alignment, then_lengthen_by);
00975 }
00976 
00985 dbus_bool_t
00986 _dbus_string_align_length (DBusString *str,
00987                            int         alignment)
00988 {
00989   return align_length_then_lengthen (str, alignment, 0);
00990 }
00991 
01001 dbus_bool_t
01002 _dbus_string_alloc_space (DBusString        *str,
01003                           int                extra_bytes)
01004 {
01005   if (!_dbus_string_lengthen (str, extra_bytes))
01006     return FALSE;
01007   _dbus_string_shorten (str, extra_bytes);
01008 
01009   return TRUE;
01010 }
01011 
01012 static dbus_bool_t
01013 append (DBusRealString *real,
01014         const char     *buffer,
01015         int             buffer_len)
01016 {
01017   if (buffer_len == 0)
01018     return TRUE;
01019 
01020   if (!_dbus_string_lengthen ((DBusString*)real, buffer_len))
01021     return FALSE;
01022 
01023   memcpy (real->str + (real->len - buffer_len),
01024           buffer,
01025           buffer_len);
01026 
01027   return TRUE;
01028 }
01029 
01037 dbus_bool_t
01038 _dbus_string_append (DBusString *str,
01039                      const char *buffer)
01040 {
01041   unsigned long buffer_len;
01042   
01043   DBUS_STRING_PREAMBLE (str);
01044   _dbus_assert (buffer != NULL);
01045   
01046   buffer_len = strlen (buffer);
01047   if (buffer_len > (unsigned long) real->max_length)
01048     return FALSE;
01049   
01050   return append (real, buffer, buffer_len);
01051 }
01052 
01054 #define ASSIGN_2_OCTETS(p, octets) \
01055   *((dbus_uint16_t*)(p)) = *((dbus_uint16_t*)(octets));
01056 
01058 #define ASSIGN_4_OCTETS(p, octets) \
01059   *((dbus_uint32_t*)(p)) = *((dbus_uint32_t*)(octets));
01060 
01061 #ifdef DBUS_HAVE_INT64
01062 
01063 #define ASSIGN_8_OCTETS(p, octets) \
01064   *((dbus_uint64_t*)(p)) = *((dbus_uint64_t*)(octets));
01065 #else
01066 
01067 #define ASSIGN_8_OCTETS(p, octets)              \
01068 do {                                            \
01069   unsigned char *b;                             \
01070                                                 \
01071   b = p;                                        \
01072                                                 \
01073   *b++ = octets[0];                             \
01074   *b++ = octets[1];                             \
01075   *b++ = octets[2];                             \
01076   *b++ = octets[3];                             \
01077   *b++ = octets[4];                             \
01078   *b++ = octets[5];                             \
01079   *b++ = octets[6];                             \
01080   *b++ = octets[7];                             \
01081   _dbus_assert (b == p + 8);                    \
01082 } while (0)
01083 #endif /* DBUS_HAVE_INT64 */
01084 
01085 #ifdef DBUS_BUILD_TESTS
01086 
01094 dbus_bool_t
01095 _dbus_string_append_4_aligned (DBusString         *str,
01096                                const unsigned char octets[4])
01097 {
01098   DBUS_STRING_PREAMBLE (str);
01099   
01100   if (!align_length_then_lengthen (str, 4, 4))
01101     return FALSE;
01102 
01103   ASSIGN_4_OCTETS (real->str + (real->len - 4), octets);
01104 
01105   return TRUE;
01106 }
01107 #endif /* DBUS_BUILD_TESTS */
01108 
01109 #ifdef DBUS_BUILD_TESTS
01110 
01118 dbus_bool_t
01119 _dbus_string_append_8_aligned (DBusString         *str,
01120                                const unsigned char octets[8])
01121 {
01122   DBUS_STRING_PREAMBLE (str);
01123   
01124   if (!align_length_then_lengthen (str, 8, 8))
01125     return FALSE;
01126 
01127   ASSIGN_8_OCTETS (real->str + (real->len - 8), octets);
01128 
01129   return TRUE;
01130 }
01131 #endif /* DBUS_BUILD_TESTS */
01132 
01142 dbus_bool_t
01143 _dbus_string_insert_2_aligned (DBusString         *str,
01144                                int                 insert_at,
01145                                const unsigned char octets[4])
01146 {
01147   DBUS_STRING_PREAMBLE (str);
01148   
01149   if (!align_insert_point_then_open_gap (str, &insert_at, 2, 2))
01150     return FALSE;
01151 
01152   ASSIGN_2_OCTETS (real->str + insert_at, octets);
01153 
01154   return TRUE;
01155 }
01156 
01166 dbus_bool_t
01167 _dbus_string_insert_4_aligned (DBusString         *str,
01168                                int                 insert_at,
01169                                const unsigned char octets[4])
01170 {
01171   DBUS_STRING_PREAMBLE (str);
01172   
01173   if (!align_insert_point_then_open_gap (str, &insert_at, 4, 4))
01174     return FALSE;
01175 
01176   ASSIGN_4_OCTETS (real->str + insert_at, octets);
01177 
01178   return TRUE;
01179 }
01180 
01190 dbus_bool_t
01191 _dbus_string_insert_8_aligned (DBusString         *str,
01192                                int                 insert_at,
01193                                const unsigned char octets[8])
01194 {
01195   DBUS_STRING_PREAMBLE (str);
01196   
01197   if (!align_insert_point_then_open_gap (str, &insert_at, 8, 8))
01198     return FALSE;
01199 
01200   _dbus_assert (_DBUS_ALIGN_VALUE (insert_at, 8) == (unsigned) insert_at);
01201   
01202   ASSIGN_8_OCTETS (real->str + insert_at, octets);
01203 
01204   return TRUE;
01205 }
01206 
01207 
01218 dbus_bool_t
01219 _dbus_string_insert_alignment (DBusString        *str,
01220                                int               *insert_at,
01221                                int                alignment)
01222 {
01223   DBUS_STRING_PREAMBLE (str);
01224   
01225   if (!align_insert_point_then_open_gap (str, insert_at, alignment, 0))
01226     return FALSE;
01227 
01228   _dbus_assert (_DBUS_ALIGN_VALUE (*insert_at, alignment) == (unsigned) *insert_at);
01229 
01230   return TRUE;
01231 }
01232 
01242 dbus_bool_t
01243 _dbus_string_append_printf_valist  (DBusString        *str,
01244                                     const char        *format,
01245                                     va_list            args)
01246 {
01247   int len;
01248   va_list args_copy;
01249 
01250   DBUS_STRING_PREAMBLE (str);
01251 
01252   DBUS_VA_COPY (args_copy, args);
01253 
01254   /* Measure the message length without terminating nul */
01255   len = _dbus_printf_string_upper_bound (format, args);
01256 
01257   if (!_dbus_string_lengthen (str, len))
01258     {
01259       /* don't leak the copy */
01260       va_end (args_copy);
01261       return FALSE;
01262     }
01263   
01264   vsprintf ((char*) (real->str + (real->len - len)),
01265             format, args_copy);
01266 
01267   va_end (args_copy);
01268 
01269   return TRUE;
01270 }
01271 
01280 dbus_bool_t
01281 _dbus_string_append_printf (DBusString        *str,
01282                             const char        *format,
01283                             ...)
01284 {
01285   va_list args;
01286   dbus_bool_t retval;
01287   
01288   va_start (args, format);
01289   retval = _dbus_string_append_printf_valist (str, format, args);
01290   va_end (args);
01291 
01292   return retval;
01293 }
01294 
01303 dbus_bool_t
01304 _dbus_string_append_len (DBusString *str,
01305                          const char *buffer,
01306                          int         len)
01307 {
01308   DBUS_STRING_PREAMBLE (str);
01309   _dbus_assert (buffer != NULL);
01310   _dbus_assert (len >= 0);
01311 
01312   return append (real, buffer, len);
01313 }
01314 
01323 dbus_bool_t
01324 _dbus_string_append_byte (DBusString    *str,
01325                           unsigned char  byte)
01326 {
01327   DBUS_STRING_PREAMBLE (str);
01328 
01329   if (!set_length (real, real->len + 1))
01330     return FALSE;
01331 
01332   real->str[real->len-1] = byte;
01333 
01334   return TRUE;
01335 }
01336 
01337 #ifdef DBUS_BUILD_TESTS
01338 
01345 dbus_bool_t
01346 _dbus_string_append_unichar (DBusString    *str,
01347                              dbus_unichar_t ch)
01348 {
01349   int len;
01350   int first;
01351   int i;
01352   unsigned char *out;
01353   
01354   DBUS_STRING_PREAMBLE (str);
01355 
01356   /* this code is from GLib but is pretty standard I think */
01357   
01358   len = 0;
01359   
01360   if (ch < 0x80)
01361     {
01362       first = 0;
01363       len = 1;
01364     }
01365   else if (ch < 0x800)
01366     {
01367       first = 0xc0;
01368       len = 2;
01369     }
01370   else if (ch < 0x10000)
01371     {
01372       first = 0xe0;
01373       len = 3;
01374     }
01375    else if (ch < 0x200000)
01376     {
01377       first = 0xf0;
01378       len = 4;
01379     }
01380   else if (ch < 0x4000000)
01381     {
01382       first = 0xf8;
01383       len = 5;
01384     }
01385   else
01386     {
01387       first = 0xfc;
01388       len = 6;
01389     }
01390 
01391   if (len > (real->max_length - real->len))
01392     return FALSE; /* real->len + len would overflow */
01393   
01394   if (!set_length (real, real->len + len))
01395     return FALSE;
01396 
01397   out = real->str + (real->len - len);
01398   
01399   for (i = len - 1; i > 0; --i)
01400     {
01401       out[i] = (ch & 0x3f) | 0x80;
01402       ch >>= 6;
01403     }
01404   out[0] = ch | first;
01405 
01406   return TRUE;
01407 }
01408 #endif /* DBUS_BUILD_TESTS */
01409 
01410 static void
01411 delete (DBusRealString *real,
01412         int             start,
01413         int             len)
01414 {
01415   if (len == 0)
01416     return;
01417   
01418   memmove (real->str + start, real->str + start + len, real->len - (start + len));
01419   real->len -= len;
01420   real->str[real->len] = '\0';
01421 }
01422 
01432 void
01433 _dbus_string_delete (DBusString       *str,
01434                      int               start,
01435                      int               len)
01436 {
01437   DBUS_STRING_PREAMBLE (str);
01438   _dbus_assert (start >= 0);
01439   _dbus_assert (len >= 0);
01440   _dbus_assert (start <= real->len);
01441   _dbus_assert (len <= real->len - start);
01442   
01443   delete (real, start, len);
01444 }
01445 
01446 static dbus_bool_t
01447 copy (DBusRealString *source,
01448       int             start,
01449       int             len,
01450       DBusRealString *dest,
01451       int             insert_at)
01452 {
01453   if (len == 0)
01454     return TRUE;
01455 
01456   if (!open_gap (len, dest, insert_at))
01457     return FALSE;
01458   
01459   memmove (dest->str + insert_at,
01460            source->str + start,
01461            len);
01462 
01463   return TRUE;
01464 }
01465 
01475 #define DBUS_STRING_COPY_PREAMBLE(source, start, dest, insert_at)       \
01476   DBusRealString *real_source = (DBusRealString*) source;               \
01477   DBusRealString *real_dest = (DBusRealString*) dest;                   \
01478   _dbus_assert ((source) != (dest));                                    \
01479   DBUS_GENERIC_STRING_PREAMBLE (real_source);                           \
01480   DBUS_GENERIC_STRING_PREAMBLE (real_dest);                             \
01481   _dbus_assert (!real_dest->constant);                                  \
01482   _dbus_assert (!real_dest->locked);                                    \
01483   _dbus_assert ((start) >= 0);                                          \
01484   _dbus_assert ((start) <= real_source->len);                           \
01485   _dbus_assert ((insert_at) >= 0);                                      \
01486   _dbus_assert ((insert_at) <= real_dest->len)
01487 
01498 dbus_bool_t
01499 _dbus_string_move (DBusString       *source,
01500                    int               start,
01501                    DBusString       *dest,
01502                    int               insert_at)
01503 {
01504   DBusRealString *real_source = (DBusRealString*) source;
01505   _dbus_assert (start <= real_source->len);
01506   
01507   return _dbus_string_move_len (source, start,
01508                                 real_source->len - start,
01509                                 dest, insert_at);
01510 }
01511 
01522 dbus_bool_t
01523 _dbus_string_copy (const DBusString *source,
01524                    int               start,
01525                    DBusString       *dest,
01526                    int               insert_at)
01527 {
01528   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
01529 
01530   return copy (real_source, start,
01531                real_source->len - start,
01532                real_dest,
01533                insert_at);
01534 }
01535 
01550 dbus_bool_t
01551 _dbus_string_move_len (DBusString       *source,
01552                        int               start,
01553                        int               len,
01554                        DBusString       *dest,
01555                        int               insert_at)
01556 
01557 {
01558   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
01559   _dbus_assert (len >= 0);
01560   _dbus_assert ((start + len) <= real_source->len);
01561 
01562 
01563   if (len == 0)
01564     {
01565       return TRUE;
01566     }
01567   else if (start == 0 &&
01568            len == real_source->len &&
01569            real_dest->len == 0)
01570     {
01571       /* Short-circuit moving an entire existing string to an empty string
01572        * by just swapping the buffers.
01573        */
01574       /* we assume ->constant doesn't matter as you can't have
01575        * a constant string involved in a move.
01576        */
01577 #define ASSIGN_DATA(a, b) do {                  \
01578         (a)->str = (b)->str;                    \
01579         (a)->len = (b)->len;                    \
01580         (a)->allocated = (b)->allocated;        \
01581         (a)->align_offset = (b)->align_offset;  \
01582       } while (0)
01583       
01584       DBusRealString tmp;
01585 
01586       ASSIGN_DATA (&tmp, real_source);
01587       ASSIGN_DATA (real_source, real_dest);
01588       ASSIGN_DATA (real_dest, &tmp);
01589 
01590       return TRUE;
01591     }
01592   else
01593     {
01594       if (!copy (real_source, start, len,
01595                  real_dest,
01596                  insert_at))
01597         return FALSE;
01598       
01599       delete (real_source, start,
01600               len);
01601       
01602       return TRUE;
01603     }
01604 }
01605 
01617 dbus_bool_t
01618 _dbus_string_copy_len (const DBusString *source,
01619                        int               start,
01620                        int               len,
01621                        DBusString       *dest,
01622                        int               insert_at)
01623 {
01624   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
01625   _dbus_assert (len >= 0);
01626   _dbus_assert (start <= real_source->len);
01627   _dbus_assert (len <= real_source->len - start);
01628   
01629   return copy (real_source, start, len,
01630                real_dest,
01631                insert_at);
01632 }
01633 
01655 dbus_bool_t
01656 _dbus_string_replace_len (const DBusString *source,
01657                           int               start,
01658                           int               len,
01659                           DBusString       *dest,
01660                           int               replace_at,
01661                           int               replace_len)
01662 {
01663   DBUS_STRING_COPY_PREAMBLE (source, start, dest, replace_at);
01664   _dbus_assert (len >= 0);
01665   _dbus_assert (start <= real_source->len);
01666   _dbus_assert (len <= real_source->len - start);
01667   _dbus_assert (replace_at >= 0);
01668   _dbus_assert (replace_at <= real_dest->len);
01669   _dbus_assert (replace_len <= real_dest->len - replace_at);
01670 
01671   if (!copy (real_source, start, len,
01672              real_dest, replace_at))
01673     return FALSE;
01674 
01675   delete (real_dest, replace_at + len, replace_len);
01676 
01677   return TRUE;
01678 }
01679 
01692 dbus_bool_t
01693 _dbus_string_split_on_byte (DBusString        *source,
01694                             unsigned char      byte,
01695                             DBusString        *tail)
01696 {
01697   int byte_position;
01698   char byte_string[2] = "";
01699   int head_length;
01700   int tail_length;
01701 
01702   byte_string[0] = (char) byte;
01703 
01704   if (!_dbus_string_find (source, 0, byte_string, &byte_position))
01705     return FALSE;
01706 
01707   head_length = byte_position;
01708   tail_length = _dbus_string_get_length (source) - head_length - 1;
01709 
01710   if (!_dbus_string_move_len (source, byte_position + 1, tail_length,
01711                               tail, 0))
01712     return FALSE;
01713 
01714   /* remove the trailing delimiter byte from the head now.
01715    */
01716   if (!_dbus_string_set_length (source, head_length))
01717     return FALSE;
01718 
01719   return TRUE;
01720 }
01721 
01722 /* Unicode macros and utf8_validate() from GLib Owen Taylor, Havoc
01723  * Pennington, and Tom Tromey are the authors and authorized relicense.
01724  */
01725 
01731 #define UTF8_COMPUTE(Char, Mask, Len)                                         \
01732   if (Char < 128)                                                             \
01733     {                                                                         \
01734       Len = 1;                                                                \
01735       Mask = 0x7f;                                                            \
01736     }                                                                         \
01737   else if ((Char & 0xe0) == 0xc0)                                             \
01738     {                                                                         \
01739       Len = 2;                                                                \
01740       Mask = 0x1f;                                                            \
01741     }                                                                         \
01742   else if ((Char & 0xf0) == 0xe0)                                             \
01743     {                                                                         \
01744       Len = 3;                                                                \
01745       Mask = 0x0f;                                                            \
01746     }                                                                         \
01747   else if ((Char & 0xf8) == 0xf0)                                             \
01748     {                                                                         \
01749       Len = 4;                                                                \
01750       Mask = 0x07;                                                            \
01751     }                                                                         \
01752   else if ((Char & 0xfc) == 0xf8)                                             \
01753     {                                                                         \
01754       Len = 5;                                                                \
01755       Mask = 0x03;                                                            \
01756     }                                                                         \
01757   else if ((Char & 0xfe) == 0xfc)                                             \
01758     {                                                                         \
01759       Len = 6;                                                                \
01760       Mask = 0x01;                                                            \
01761     }                                                                         \
01762   else                                                                        \
01763     {                                                                         \
01764       Len = 0;                                                               \
01765       Mask = 0;                                                               \
01766     }
01767 
01772 #define UTF8_LENGTH(Char)              \
01773   ((Char) < 0x80 ? 1 :                 \
01774    ((Char) < 0x800 ? 2 :               \
01775     ((Char) < 0x10000 ? 3 :            \
01776      ((Char) < 0x200000 ? 4 :          \
01777       ((Char) < 0x4000000 ? 5 : 6)))))
01778    
01788 #define UTF8_GET(Result, Chars, Count, Mask, Len)                             \
01789   (Result) = (Chars)[0] & (Mask);                                             \
01790   for ((Count) = 1; (Count) < (Len); ++(Count))                               \
01791     {                                                                         \
01792       if (((Chars)[(Count)] & 0xc0) != 0x80)                                  \
01793         {                                                                     \
01794           (Result) = -1;                                                      \
01795           break;                                                              \
01796         }                                                                     \
01797       (Result) <<= 6;                                                         \
01798       (Result) |= ((Chars)[(Count)] & 0x3f);                                  \
01799     }
01800 
01817 #define UNICODE_VALID(Char)                   \
01818     ((Char) < 0x110000 &&                     \
01819      (((Char) & 0xFFFFF800) != 0xD800) &&     \
01820      ((Char) < 0xFDD0 || (Char) > 0xFDEF) &&  \
01821      ((Char) & 0xFFFE) != 0xFFFE)
01822 
01823 #ifdef DBUS_BUILD_TESTS
01824 
01834 void
01835 _dbus_string_get_unichar (const DBusString *str,
01836                           int               start,
01837                           dbus_unichar_t   *ch_return,
01838                           int              *end_return)
01839 {
01840   int i, mask, len;
01841   dbus_unichar_t result;
01842   unsigned char c;
01843   unsigned char *p;
01844   DBUS_CONST_STRING_PREAMBLE (str);
01845   _dbus_assert (start >= 0);
01846   _dbus_assert (start <= real->len);
01847   
01848   if (ch_return)
01849     *ch_return = 0;
01850   if (end_return)
01851     *end_return = real->len;
01852   
01853   mask = 0;
01854   p = real->str + start;
01855   c = *p;
01856   
01857   UTF8_COMPUTE (c, mask, len);
01858   if (len == 0)
01859     return;
01860   UTF8_GET (result, p, i, mask, len);
01861 
01862   if (result == (dbus_unichar_t)-1)
01863     return;
01864 
01865   if (ch_return)
01866     *ch_return = result;
01867   if (end_return)
01868     *end_return = start + len;
01869 }
01870 #endif /* DBUS_BUILD_TESTS */
01871 
01886 dbus_bool_t
01887 _dbus_string_find (const DBusString *str,
01888                    int               start,
01889                    const char       *substr,
01890                    int              *found)
01891 {
01892   return _dbus_string_find_to (str, start,
01893                                ((const DBusRealString*)str)->len,
01894                                substr, found);
01895 }
01896 
01909 dbus_bool_t
01910 _dbus_string_find_eol (const DBusString *str,
01911                        int               start,
01912                        int              *found,
01913                        int              *found_len)
01914 {
01915   int i;
01916 
01917   DBUS_CONST_STRING_PREAMBLE (str);
01918   _dbus_assert (start <= real->len);
01919   _dbus_assert (start >= 0);
01920   
01921   i = start;
01922   while (i < real->len)
01923     {
01924       if (real->str[i] == '\r') 
01925         {
01926           if ((i+1) < real->len && real->str[i+1] == '\n') /* "\r\n" */
01927             {
01928               if (found) 
01929                 *found = i;
01930               if (found_len)
01931                 *found_len = 2;
01932               return TRUE;
01933             } 
01934           else /* only "\r" */
01935             {
01936               if (found) 
01937                 *found = i;
01938               if (found_len)
01939                 *found_len = 1;
01940               return TRUE;
01941             }
01942         } 
01943       else if (real->str[i] == '\n')  /* only "\n" */
01944         {
01945           if (found) 
01946             *found = i;
01947           if (found_len)
01948             *found_len = 1;
01949           return TRUE;
01950         }
01951       ++i;
01952     }
01953 
01954   if (found)
01955     *found = real->len;
01956 
01957   if (found_len)
01958     *found_len = 0;
01959   
01960   return FALSE;
01961 }
01962 
01979 dbus_bool_t
01980 _dbus_string_find_to (const DBusString *str,
01981                       int               start,
01982                       int               end,
01983                       const char       *substr,
01984                       int              *found)
01985 {
01986   int i;
01987   DBUS_CONST_STRING_PREAMBLE (str);
01988   _dbus_assert (substr != NULL);
01989   _dbus_assert (start <= real->len);
01990   _dbus_assert (start >= 0);
01991   _dbus_assert (substr != NULL);
01992   _dbus_assert (end <= real->len);
01993   _dbus_assert (start <= end);
01994 
01995   /* we always "find" an empty string */
01996   if (*substr == '\0')
01997     {
01998       if (found)
01999         *found = start;
02000       return TRUE;
02001     }
02002 
02003   i = start;
02004   while (i < end)
02005     {
02006       if (real->str[i] == substr[0])
02007         {
02008           int j = i + 1;
02009           
02010           while (j < end)
02011             {
02012               if (substr[j - i] == '\0')
02013                 break;
02014               else if (real->str[j] != substr[j - i])
02015                 break;
02016               
02017               ++j;
02018             }
02019 
02020           if (substr[j - i] == '\0')
02021             {
02022               if (found)
02023                 *found = i;
02024               return TRUE;
02025             }
02026         }
02027       
02028       ++i;
02029     }
02030 
02031   if (found)
02032     *found = end;
02033   
02034   return FALSE;  
02035 }
02036 
02047 dbus_bool_t
02048 _dbus_string_find_blank (const DBusString *str,
02049                          int               start,
02050                          int              *found)
02051 {
02052   int i;
02053   DBUS_CONST_STRING_PREAMBLE (str);
02054   _dbus_assert (start <= real->len);
02055   _dbus_assert (start >= 0);
02056   
02057   i = start;
02058   while (i < real->len)
02059     {
02060       if (real->str[i] == ' ' ||
02061           real->str[i] == '\t')
02062         {
02063           if (found)
02064             *found = i;
02065           return TRUE;
02066         }
02067       
02068       ++i;
02069     }
02070 
02071   if (found)
02072     *found = real->len;
02073   
02074   return FALSE;
02075 }
02076 
02085 void
02086 _dbus_string_skip_blank (const DBusString *str,
02087                          int               start,
02088                          int              *end)
02089 {
02090   int i;
02091   DBUS_CONST_STRING_PREAMBLE (str);
02092   _dbus_assert (start <= real->len);
02093   _dbus_assert (start >= 0);
02094   
02095   i = start;
02096   while (i < real->len)
02097     {
02098       if (!DBUS_IS_ASCII_BLANK (real->str[i]))
02099         break;
02100       
02101       ++i;
02102     }
02103 
02104   _dbus_assert (i == real->len || !DBUS_IS_ASCII_WHITE (real->str[i]));
02105   
02106   if (end)
02107     *end = i;
02108 }
02109 
02110 
02119 void
02120 _dbus_string_skip_white (const DBusString *str,
02121                          int               start,
02122                          int              *end)
02123 {
02124   int i;
02125   DBUS_CONST_STRING_PREAMBLE (str);
02126   _dbus_assert (start <= real->len);
02127   _dbus_assert (start >= 0);
02128   
02129   i = start;
02130   while (i < real->len)
02131     {
02132       if (!DBUS_IS_ASCII_WHITE (real->str[i]))
02133         break;
02134       
02135       ++i;
02136     }
02137 
02138   _dbus_assert (i == real->len || !(DBUS_IS_ASCII_WHITE (real->str[i])));
02139   
02140   if (end)
02141     *end = i;
02142 }
02143 
02152 void
02153 _dbus_string_skip_white_reverse (const DBusString *str,
02154                                  int               end,
02155                                  int              *start)
02156 {
02157   int i;
02158   DBUS_CONST_STRING_PREAMBLE (str);
02159   _dbus_assert (end <= real->len);
02160   _dbus_assert (end >= 0);
02161   
02162   i = end;
02163   while (i > 0)
02164     {
02165       if (!DBUS_IS_ASCII_WHITE (real->str[i-1]))
02166         break;
02167       --i;
02168     }
02169 
02170   _dbus_assert (i >= 0 && (i == 0 || !(DBUS_IS_ASCII_WHITE (real->str[i-1]))));
02171   
02172   if (start)
02173     *start = i;
02174 }
02175 
02191 dbus_bool_t
02192 _dbus_string_pop_line (DBusString *source,
02193                        DBusString *dest)
02194 {
02195   int eol, eol_len;
02196   
02197   _dbus_string_set_length (dest, 0);
02198   
02199   eol = 0;
02200   eol_len = 0;
02201   if (!_dbus_string_find_eol (source, 0, &eol, &eol_len))
02202     {
02203       _dbus_assert (eol == _dbus_string_get_length (source));
02204       if (eol == 0)
02205         {
02206           /* If there's no newline and source has zero length, we're done */
02207           return FALSE;
02208         }
02209       /* otherwise, the last line of the file has no eol characters */
02210     }
02211 
02212   /* remember eol can be 0 if it's an empty line, but eol_len should not be zero also
02213    * since find_eol returned TRUE
02214    */
02215   
02216   if (!_dbus_string_move_len (source, 0, eol + eol_len, dest, 0))
02217     return FALSE;
02218   
02219   /* remove line ending */
02220   if (!_dbus_string_set_length (dest, eol))
02221     {
02222       _dbus_assert_not_reached ("out of memory when shortening a string");
02223       return FALSE;
02224     }
02225 
02226   return TRUE;
02227 }
02228 
02229 #ifdef DBUS_BUILD_TESTS
02230 
02236 void
02237 _dbus_string_delete_first_word (DBusString *str)
02238 {
02239   int i;
02240   
02241   if (_dbus_string_find_blank (str, 0, &i))
02242     _dbus_string_skip_blank (str, i, &i);
02243 
02244   _dbus_string_delete (str, 0, i);
02245 }
02246 #endif
02247 
02248 #ifdef DBUS_BUILD_TESTS
02249 
02254 void
02255 _dbus_string_delete_leading_blanks (DBusString *str)
02256 {
02257   int i;
02258   
02259   _dbus_string_skip_blank (str, 0, &i);
02260 
02261   if (i > 0)
02262     _dbus_string_delete (str, 0, i);
02263 }
02264 #endif
02265 
02271 void
02272 _dbus_string_chop_white(DBusString *str)
02273 {
02274   int i;
02275   
02276   _dbus_string_skip_white (str, 0, &i);
02277 
02278   if (i > 0)
02279     _dbus_string_delete (str, 0, i);
02280   
02281   _dbus_string_skip_white_reverse (str, _dbus_string_get_length (str), &i);
02282 
02283   _dbus_string_set_length (str, i);
02284 }
02285 
02295 dbus_bool_t
02296 _dbus_string_equal (const DBusString *a,
02297                     const DBusString *b)
02298 {
02299   const unsigned char *ap;
02300   const unsigned char *bp;
02301   const unsigned char *a_end;
02302   const DBusRealString *real_a = (const DBusRealString*) a;
02303   const DBusRealString *real_b = (const DBusRealString*) b;
02304   DBUS_GENERIC_STRING_PREAMBLE (real_a);
02305   DBUS_GENERIC_STRING_PREAMBLE (real_b);
02306 
02307   if (real_a->len != real_b->len)
02308     return FALSE;
02309 
02310   ap = real_a->str;
02311   bp = real_b->str;
02312   a_end = real_a->str + real_a->len;
02313   while (ap != a_end)
02314     {
02315       if (*ap != *bp)
02316         return FALSE;
02317       
02318       ++ap;
02319       ++bp;
02320     }
02321 
02322   return TRUE;
02323 }
02324 
02325 #ifdef DBUS_BUILD_TESTS
02326 
02339 dbus_bool_t
02340 _dbus_string_equal_len (const DBusString *a,
02341                         const DBusString *b,
02342                         int               len)
02343 {
02344   const unsigned char *ap;
02345   const unsigned char *bp;
02346   const unsigned char *a_end;
02347   const DBusRealString *real_a = (const DBusRealString*) a;
02348   const DBusRealString *real_b = (const DBusRealString*) b;
02349   DBUS_GENERIC_STRING_PREAMBLE (real_a);
02350   DBUS_GENERIC_STRING_PREAMBLE (real_b);
02351 
02352   if (real_a->len != real_b->len &&
02353       (real_a->len < len || real_b->len < len))
02354     return FALSE;
02355 
02356   ap = real_a->str;
02357   bp = real_b->str;
02358   a_end = real_a->str + MIN (real_a->len, len);
02359   while (ap != a_end)
02360     {
02361       if (*ap != *bp)
02362         return FALSE;
02363       
02364       ++ap;
02365       ++bp;
02366     }
02367 
02368   return TRUE;
02369 }
02370 #endif /* DBUS_BUILD_TESTS */
02371 
02388 dbus_bool_t
02389 _dbus_string_equal_substring (const DBusString  *a,
02390                               int                a_start,
02391                               int                a_len,
02392                               const DBusString  *b,
02393                               int                b_start)
02394 {
02395   const unsigned char *ap;
02396   const unsigned char *bp;
02397   const unsigned char *a_end;
02398   const DBusRealString *real_a = (const DBusRealString*) a;
02399   const DBusRealString *real_b = (const DBusRealString*) b;
02400   DBUS_GENERIC_STRING_PREAMBLE (real_a);
02401   DBUS_GENERIC_STRING_PREAMBLE (real_b);
02402   _dbus_assert (a_start >= 0);
02403   _dbus_assert (a_len >= 0);
02404   _dbus_assert (a_start <= real_a->len);
02405   _dbus_assert (a_len <= real_a->len - a_start);
02406   _dbus_assert (b_start >= 0);
02407   _dbus_assert (b_start <= real_b->len);
02408   
02409   if (a_len > real_b->len - b_start)
02410     return FALSE;
02411 
02412   ap = real_a->str + a_start;
02413   bp = real_b->str + b_start;
02414   a_end = ap + a_len;
02415   while (ap != a_end)
02416     {
02417       if (*ap != *bp)
02418         return FALSE;
02419       
02420       ++ap;
02421       ++bp;
02422     }
02423 
02424   _dbus_assert (bp <= (real_b->str + real_b->len));
02425   
02426   return TRUE;
02427 }
02428 
02436 dbus_bool_t
02437 _dbus_string_equal_c_str (const DBusString *a,
02438                           const char       *c_str)
02439 {
02440   const unsigned char *ap;
02441   const unsigned char *bp;
02442   const unsigned char *a_end;
02443   const DBusRealString *real_a = (const DBusRealString*) a;
02444   DBUS_GENERIC_STRING_PREAMBLE (real_a);
02445   _dbus_assert (c_str != NULL);
02446   
02447   ap = real_a->str;
02448   bp = (const unsigned char*) c_str;
02449   a_end = real_a->str + real_a->len;
02450   while (ap != a_end && *bp)
02451     {
02452       if (*ap != *bp)
02453         return FALSE;
02454       
02455       ++ap;
02456       ++bp;
02457     }
02458 
02459   if (ap != a_end || *bp)
02460     return FALSE;
02461   
02462   return TRUE;
02463 }
02464 
02465 #ifdef DBUS_BUILD_TESTS
02466 
02473 dbus_bool_t
02474 _dbus_string_starts_with_c_str (const DBusString *a,
02475                                 const char       *c_str)
02476 {
02477   const unsigned char *ap;
02478   const unsigned char *bp;
02479   const unsigned char *a_end;
02480   const DBusRealString *real_a = (const DBusRealString*) a;
02481   DBUS_GENERIC_STRING_PREAMBLE (real_a);
02482   _dbus_assert (c_str != NULL);
02483   
02484   ap = real_a->str;
02485   bp = (const unsigned char*) c_str;
02486   a_end = real_a->str + real_a->len;
02487   while (ap != a_end && *bp)
02488     {
02489       if (*ap != *bp)
02490         return FALSE;
02491       
02492       ++ap;
02493       ++bp;
02494     }
02495 
02496   if (*bp == '\0')
02497     return TRUE;
02498   else
02499     return FALSE;
02500 }
02501 #endif /* DBUS_BUILD_TESTS */
02502 
02511 dbus_bool_t
02512 _dbus_string_append_byte_as_hex (DBusString *str,
02513                                  int         byte)
02514 {
02515   const char hexdigits[16] = {
02516     '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
02517     'a', 'b', 'c', 'd', 'e', 'f'
02518   };
02519 
02520   if (!_dbus_string_append_byte (str,
02521                                  hexdigits[(byte >> 4)]))
02522     return FALSE;
02523   
02524   if (!_dbus_string_append_byte (str,
02525                                  hexdigits[(byte & 0x0f)]))
02526     {
02527       _dbus_string_set_length (str,
02528                                _dbus_string_get_length (str) - 1);
02529       return FALSE;
02530     }
02531 
02532   return TRUE;
02533 }
02534 
02545 dbus_bool_t
02546 _dbus_string_hex_encode (const DBusString *source,
02547                          int               start,
02548                          DBusString       *dest,
02549                          int               insert_at)
02550 {
02551   DBusString result;
02552   const unsigned char *p;
02553   const unsigned char *end;
02554   dbus_bool_t retval;
02555   
02556   _dbus_assert (start <= _dbus_string_get_length (source));
02557 
02558   if (!_dbus_string_init (&result))
02559     return FALSE;
02560 
02561   retval = FALSE;
02562   
02563   p = (const unsigned char*) _dbus_string_get_const_data (source);
02564   end = p + _dbus_string_get_length (source);
02565   p += start;
02566   
02567   while (p != end)
02568     {
02569       if (!_dbus_string_append_byte_as_hex (&result, *p))
02570         goto out;
02571       
02572       ++p;
02573     }
02574 
02575   if (!_dbus_string_move (&result, 0, dest, insert_at))
02576     goto out;
02577 
02578   retval = TRUE;
02579 
02580  out:
02581   _dbus_string_free (&result);
02582   return retval;
02583 }
02584 
02595 dbus_bool_t
02596 _dbus_string_hex_decode (const DBusString *source,
02597                          int               start,
02598                          int              *end_return,
02599                          DBusString       *dest,
02600                          int               insert_at)
02601 {
02602   DBusString result;
02603   const unsigned char *p;
02604   const unsigned char *end;
02605   dbus_bool_t retval;
02606   dbus_bool_t high_bits;
02607   
02608   _dbus_assert (start <= _dbus_string_get_length (source));
02609 
02610   if (!_dbus_string_init (&result))
02611     return FALSE;
02612 
02613   retval = FALSE;
02614 
02615   high_bits = TRUE;
02616   p = (const unsigned char*) _dbus_string_get_const_data (source);
02617   end = p + _dbus_string_get_length (source);
02618   p += start;
02619   
02620   while (p != end)
02621     {
02622       unsigned int val;
02623 
02624       switch (*p)
02625         {
02626         case '0':
02627           val = 0;
02628           break;
02629         case '1':
02630           val = 1;
02631           break;
02632         case '2':
02633           val = 2;
02634           break;
02635         case '3':
02636           val = 3;
02637           break;
02638         case '4':
02639           val = 4;
02640           break;
02641         case '5':
02642           val = 5;
02643           break;
02644         case '6':
02645           val = 6;
02646           break;
02647         case '7':
02648           val = 7;
02649           break;
02650         case '8':
02651           val = 8;
02652           break;
02653         case '9':
02654           val = 9;
02655           break;
02656         case 'a':
02657         case 'A':
02658           val = 10;
02659           break;
02660         case 'b':
02661         case 'B':
02662           val = 11;
02663           break;
02664         case 'c':
02665         case 'C':
02666           val = 12;
02667           break;
02668         case 'd':
02669         case 'D':
02670           val = 13;
02671           break;
02672         case 'e':
02673         case 'E':
02674           val = 14;
02675           break;
02676         case 'f':
02677         case 'F':
02678           val = 15;
02679           break;
02680         default:
02681           goto done;
02682         }
02683 
02684       if (high_bits)
02685         {
02686           if (!_dbus_string_append_byte (&result,
02687                                          val << 4))
02688             goto out;
02689         }
02690       else
02691         {
02692           int len;
02693           unsigned char b;
02694 
02695           len = _dbus_string_get_length (&result);
02696           
02697           b = _dbus_string_get_byte (&result, len - 1);
02698 
02699           b |= val;
02700 
02701           _dbus_string_set_byte (&result, len - 1, b);
02702         }
02703 
02704       high_bits = !high_bits;
02705 
02706       ++p;
02707     }
02708 
02709  done:
02710   if (!_dbus_string_move (&result, 0, dest, insert_at))
02711     goto out;
02712 
02713   if (end_return)
02714     *end_return = p - (const unsigned char*) _dbus_string_get_const_data (source);
02715 
02716   retval = TRUE;
02717   
02718  out:
02719   _dbus_string_free (&result);  
02720   return retval;
02721 }
02722 
02736 dbus_bool_t
02737 _dbus_string_validate_ascii (const DBusString *str,
02738                              int               start,
02739                              int               len)
02740 {
02741   const unsigned char *s;
02742   const unsigned char *end;
02743   DBUS_CONST_STRING_PREAMBLE (str);
02744   _dbus_assert (start >= 0);
02745   _dbus_assert (start <= real->len);
02746   _dbus_assert (len >= 0);
02747   
02748   if (len > real->len - start)
02749     return FALSE;
02750   
02751   s = real->str + start;
02752   end = s + len;
02753   while (s != end)
02754     {
02755       if (_DBUS_UNLIKELY (!_DBUS_ISASCII (*s)))
02756         return FALSE;
02757         
02758       ++s;
02759     }
02760   
02761   return TRUE;
02762 }
02763 
02779 dbus_bool_t
02780 _dbus_string_validate_utf8  (const DBusString *str,
02781                              int               start,
02782                              int               len)
02783 {
02784   const unsigned char *p;
02785   const unsigned char *end;
02786   DBUS_CONST_STRING_PREAMBLE (str);
02787   _dbus_assert (start >= 0);
02788   _dbus_assert (start <= real->len);
02789   _dbus_assert (len >= 0);
02790 
02791   /* we are doing _DBUS_UNLIKELY() here which might be
02792    * dubious in a generic library like GLib, but in D-Bus
02793    * we know we're validating messages and that it would
02794    * only be evil/broken apps that would have invalid
02795    * UTF-8. Also, this function seems to be a performance
02796    * bottleneck in profiles.
02797    */
02798   
02799   if (_DBUS_UNLIKELY (len > real->len - start))
02800     return FALSE;
02801   
02802   p = real->str + start;
02803   end = p + len;
02804   
02805   while (p < end)
02806     {
02807       int i, mask, char_len;
02808       dbus_unichar_t result;
02809 
02810       /* nul bytes considered invalid */
02811       if (*p == '\0')
02812         break;
02813       
02814       /* Special-case ASCII; this makes us go a lot faster in
02815        * D-Bus profiles where we are typically validating
02816        * function names and such. We have to know that
02817        * all following checks will pass for ASCII though,
02818        * comments follow ...
02819        */      
02820       if (*p < 128)
02821         {
02822           ++p;
02823           continue;
02824         }
02825       
02826       UTF8_COMPUTE (*p, mask, char_len);
02827 
02828       if (_DBUS_UNLIKELY (char_len == 0))  /* ASCII: char_len == 1 */
02829         break;
02830 
02831       /* check that the expected number of bytes exists in the remaining length */
02832       if (_DBUS_UNLIKELY ((end - p) < char_len)) /* ASCII: p < end and char_len == 1 */
02833         break;
02834         
02835       UTF8_GET (result, p, i, mask, char_len);
02836 
02837       /* Check for overlong UTF-8 */
02838       if (_DBUS_UNLIKELY (UTF8_LENGTH (result) != char_len)) /* ASCII: UTF8_LENGTH == 1 */
02839         break;
02840 #if 0
02841       /* The UNICODE_VALID check below will catch this */
02842       if (_DBUS_UNLIKELY (result == (dbus_unichar_t)-1)) /* ASCII: result = ascii value */
02843         break;
02844 #endif
02845 
02846       if (_DBUS_UNLIKELY (!UNICODE_VALID (result))) /* ASCII: always valid */
02847         break;
02848 
02849       /* UNICODE_VALID should have caught it */
02850       _dbus_assert (result != (dbus_unichar_t)-1);
02851       
02852       p += char_len;
02853     }
02854 
02855   /* See that we covered the entire length if a length was
02856    * passed in
02857    */
02858   if (_DBUS_UNLIKELY (p != end))
02859     return FALSE;
02860   else
02861     return TRUE;
02862 }
02863 
02877 dbus_bool_t
02878 _dbus_string_validate_nul (const DBusString *str,
02879                            int               start,
02880                            int               len)
02881 {
02882   const unsigned char *s;
02883   const unsigned char *end;
02884   DBUS_CONST_STRING_PREAMBLE (str);
02885   _dbus_assert (start >= 0);
02886   _dbus_assert (len >= 0);
02887   _dbus_assert (start <= real->len);
02888   
02889   if (len > real->len - start)
02890     return FALSE;
02891   
02892   s = real->str + start;
02893   end = s + len;
02894   while (s != end)
02895     {
02896       if (_DBUS_UNLIKELY (*s != '\0'))
02897         return FALSE;
02898       ++s;
02899     }
02900   
02901   return TRUE;
02902 }
02903 
02909 void
02910 _dbus_string_zero (DBusString *str)
02911 {
02912   DBUS_STRING_PREAMBLE (str);
02913 
02914   memset (real->str - real->align_offset, '\0', real->allocated);
02915 }
02918 /* tests are in dbus-string-util.c */

Generated on Sun Feb 20 2011 22:33:43 for D-Bus by  doxygen 1.7.1