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