D-Bus 1.4.14
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 (len < 0)
01259     return FALSE;
01260 
01261   if (!_dbus_string_lengthen (str, len))
01262     {
01263       /* don't leak the copy */
01264       va_end (args_copy);
01265       return FALSE;
01266     }
01267   
01268   vsprintf ((char*) (real->str + (real->len - len)),
01269             format, args_copy);
01270 
01271   va_end (args_copy);
01272 
01273   return TRUE;
01274 }
01275 
01284 dbus_bool_t
01285 _dbus_string_append_printf (DBusString        *str,
01286                             const char        *format,
01287                             ...)
01288 {
01289   va_list args;
01290   dbus_bool_t retval;
01291   
01292   va_start (args, format);
01293   retval = _dbus_string_append_printf_valist (str, format, args);
01294   va_end (args);
01295 
01296   return retval;
01297 }
01298 
01307 dbus_bool_t
01308 _dbus_string_append_len (DBusString *str,
01309                          const char *buffer,
01310                          int         len)
01311 {
01312   DBUS_STRING_PREAMBLE (str);
01313   _dbus_assert (buffer != NULL);
01314   _dbus_assert (len >= 0);
01315 
01316   return append (real, buffer, len);
01317 }
01318 
01327 dbus_bool_t
01328 _dbus_string_append_byte (DBusString    *str,
01329                           unsigned char  byte)
01330 {
01331   DBUS_STRING_PREAMBLE (str);
01332 
01333   if (!set_length (real, real->len + 1))
01334     return FALSE;
01335 
01336   real->str[real->len-1] = byte;
01337 
01338   return TRUE;
01339 }
01340 
01341 #ifdef DBUS_BUILD_TESTS
01342 
01349 dbus_bool_t
01350 _dbus_string_append_unichar (DBusString    *str,
01351                              dbus_unichar_t ch)
01352 {
01353   int len;
01354   int first;
01355   int i;
01356   unsigned char *out;
01357   
01358   DBUS_STRING_PREAMBLE (str);
01359 
01360   /* this code is from GLib but is pretty standard I think */
01361   
01362   len = 0;
01363   
01364   if (ch < 0x80)
01365     {
01366       first = 0;
01367       len = 1;
01368     }
01369   else if (ch < 0x800)
01370     {
01371       first = 0xc0;
01372       len = 2;
01373     }
01374   else if (ch < 0x10000)
01375     {
01376       first = 0xe0;
01377       len = 3;
01378     }
01379    else if (ch < 0x200000)
01380     {
01381       first = 0xf0;
01382       len = 4;
01383     }
01384   else if (ch < 0x4000000)
01385     {
01386       first = 0xf8;
01387       len = 5;
01388     }
01389   else
01390     {
01391       first = 0xfc;
01392       len = 6;
01393     }
01394 
01395   if (len > (real->max_length - real->len))
01396     return FALSE; /* real->len + len would overflow */
01397   
01398   if (!set_length (real, real->len + len))
01399     return FALSE;
01400 
01401   out = real->str + (real->len - len);
01402   
01403   for (i = len - 1; i > 0; --i)
01404     {
01405       out[i] = (ch & 0x3f) | 0x80;
01406       ch >>= 6;
01407     }
01408   out[0] = ch | first;
01409 
01410   return TRUE;
01411 }
01412 #endif /* DBUS_BUILD_TESTS */
01413 
01414 static void
01415 delete (DBusRealString *real,
01416         int             start,
01417         int             len)
01418 {
01419   if (len == 0)
01420     return;
01421   
01422   memmove (real->str + start, real->str + start + len, real->len - (start + len));
01423   real->len -= len;
01424   real->str[real->len] = '\0';
01425 }
01426 
01436 void
01437 _dbus_string_delete (DBusString       *str,
01438                      int               start,
01439                      int               len)
01440 {
01441   DBUS_STRING_PREAMBLE (str);
01442   _dbus_assert (start >= 0);
01443   _dbus_assert (len >= 0);
01444   _dbus_assert (start <= real->len);
01445   _dbus_assert (len <= real->len - start);
01446   
01447   delete (real, start, len);
01448 }
01449 
01450 static dbus_bool_t
01451 copy (DBusRealString *source,
01452       int             start,
01453       int             len,
01454       DBusRealString *dest,
01455       int             insert_at)
01456 {
01457   if (len == 0)
01458     return TRUE;
01459 
01460   if (!open_gap (len, dest, insert_at))
01461     return FALSE;
01462   
01463   memmove (dest->str + insert_at,
01464            source->str + start,
01465            len);
01466 
01467   return TRUE;
01468 }
01469 
01479 #define DBUS_STRING_COPY_PREAMBLE(source, start, dest, insert_at)       \
01480   DBusRealString *real_source = (DBusRealString*) source;               \
01481   DBusRealString *real_dest = (DBusRealString*) dest;                   \
01482   _dbus_assert ((source) != (dest));                                    \
01483   DBUS_GENERIC_STRING_PREAMBLE (real_source);                           \
01484   DBUS_GENERIC_STRING_PREAMBLE (real_dest);                             \
01485   _dbus_assert (!real_dest->constant);                                  \
01486   _dbus_assert (!real_dest->locked);                                    \
01487   _dbus_assert ((start) >= 0);                                          \
01488   _dbus_assert ((start) <= real_source->len);                           \
01489   _dbus_assert ((insert_at) >= 0);                                      \
01490   _dbus_assert ((insert_at) <= real_dest->len)
01491 
01502 dbus_bool_t
01503 _dbus_string_move (DBusString       *source,
01504                    int               start,
01505                    DBusString       *dest,
01506                    int               insert_at)
01507 {
01508   DBusRealString *real_source = (DBusRealString*) source;
01509   _dbus_assert (start <= real_source->len);
01510   
01511   return _dbus_string_move_len (source, start,
01512                                 real_source->len - start,
01513                                 dest, insert_at);
01514 }
01515 
01526 dbus_bool_t
01527 _dbus_string_copy (const DBusString *source,
01528                    int               start,
01529                    DBusString       *dest,
01530                    int               insert_at)
01531 {
01532   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
01533 
01534   return copy (real_source, start,
01535                real_source->len - start,
01536                real_dest,
01537                insert_at);
01538 }
01539 
01554 dbus_bool_t
01555 _dbus_string_move_len (DBusString       *source,
01556                        int               start,
01557                        int               len,
01558                        DBusString       *dest,
01559                        int               insert_at)
01560 
01561 {
01562   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
01563   _dbus_assert (len >= 0);
01564   _dbus_assert ((start + len) <= real_source->len);
01565 
01566 
01567   if (len == 0)
01568     {
01569       return TRUE;
01570     }
01571   else if (start == 0 &&
01572            len == real_source->len &&
01573            real_dest->len == 0)
01574     {
01575       /* Short-circuit moving an entire existing string to an empty string
01576        * by just swapping the buffers.
01577        */
01578       /* we assume ->constant doesn't matter as you can't have
01579        * a constant string involved in a move.
01580        */
01581 #define ASSIGN_DATA(a, b) do {                  \
01582         (a)->str = (b)->str;                    \
01583         (a)->len = (b)->len;                    \
01584         (a)->allocated = (b)->allocated;        \
01585         (a)->align_offset = (b)->align_offset;  \
01586       } while (0)
01587       
01588       DBusRealString tmp;
01589 
01590       ASSIGN_DATA (&tmp, real_source);
01591       ASSIGN_DATA (real_source, real_dest);
01592       ASSIGN_DATA (real_dest, &tmp);
01593 
01594       return TRUE;
01595     }
01596   else
01597     {
01598       if (!copy (real_source, start, len,
01599                  real_dest,
01600                  insert_at))
01601         return FALSE;
01602       
01603       delete (real_source, start,
01604               len);
01605       
01606       return TRUE;
01607     }
01608 }
01609 
01621 dbus_bool_t
01622 _dbus_string_copy_len (const DBusString *source,
01623                        int               start,
01624                        int               len,
01625                        DBusString       *dest,
01626                        int               insert_at)
01627 {
01628   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
01629   _dbus_assert (len >= 0);
01630   _dbus_assert (start <= real_source->len);
01631   _dbus_assert (len <= real_source->len - start);
01632   
01633   return copy (real_source, start, len,
01634                real_dest,
01635                insert_at);
01636 }
01637 
01659 dbus_bool_t
01660 _dbus_string_replace_len (const DBusString *source,
01661                           int               start,
01662                           int               len,
01663                           DBusString       *dest,
01664                           int               replace_at,
01665                           int               replace_len)
01666 {
01667   DBUS_STRING_COPY_PREAMBLE (source, start, dest, replace_at);
01668   _dbus_assert (len >= 0);
01669   _dbus_assert (start <= real_source->len);
01670   _dbus_assert (len <= real_source->len - start);
01671   _dbus_assert (replace_at >= 0);
01672   _dbus_assert (replace_at <= real_dest->len);
01673   _dbus_assert (replace_len <= real_dest->len - replace_at);
01674 
01675   if (!copy (real_source, start, len,
01676              real_dest, replace_at))
01677     return FALSE;
01678 
01679   delete (real_dest, replace_at + len, replace_len);
01680 
01681   return TRUE;
01682 }
01683 
01696 dbus_bool_t
01697 _dbus_string_split_on_byte (DBusString        *source,
01698                             unsigned char      byte,
01699                             DBusString        *tail)
01700 {
01701   int byte_position;
01702   char byte_string[2] = "";
01703   int head_length;
01704   int tail_length;
01705 
01706   byte_string[0] = (char) byte;
01707 
01708   if (!_dbus_string_find (source, 0, byte_string, &byte_position))
01709     return FALSE;
01710 
01711   head_length = byte_position;
01712   tail_length = _dbus_string_get_length (source) - head_length - 1;
01713 
01714   if (!_dbus_string_move_len (source, byte_position + 1, tail_length,
01715                               tail, 0))
01716     return FALSE;
01717 
01718   /* remove the trailing delimiter byte from the head now.
01719    */
01720   if (!_dbus_string_set_length (source, head_length))
01721     return FALSE;
01722 
01723   return TRUE;
01724 }
01725 
01726 /* Unicode macros and utf8_validate() from GLib Owen Taylor, Havoc
01727  * Pennington, and Tom Tromey are the authors and authorized relicense.
01728  */
01729 
01735 #define UTF8_COMPUTE(Char, Mask, Len)                                         \
01736   if (Char < 128)                                                             \
01737     {                                                                         \
01738       Len = 1;                                                                \
01739       Mask = 0x7f;                                                            \
01740     }                                                                         \
01741   else if ((Char & 0xe0) == 0xc0)                                             \
01742     {                                                                         \
01743       Len = 2;                                                                \
01744       Mask = 0x1f;                                                            \
01745     }                                                                         \
01746   else if ((Char & 0xf0) == 0xe0)                                             \
01747     {                                                                         \
01748       Len = 3;                                                                \
01749       Mask = 0x0f;                                                            \
01750     }                                                                         \
01751   else if ((Char & 0xf8) == 0xf0)                                             \
01752     {                                                                         \
01753       Len = 4;                                                                \
01754       Mask = 0x07;                                                            \
01755     }                                                                         \
01756   else if ((Char & 0xfc) == 0xf8)                                             \
01757     {                                                                         \
01758       Len = 5;                                                                \
01759       Mask = 0x03;                                                            \
01760     }                                                                         \
01761   else if ((Char & 0xfe) == 0xfc)                                             \
01762     {                                                                         \
01763       Len = 6;                                                                \
01764       Mask = 0x01;                                                            \
01765     }                                                                         \
01766   else                                                                        \
01767     {                                                                         \
01768       Len = 0;                                                               \
01769       Mask = 0;                                                               \
01770     }
01771 
01776 #define UTF8_LENGTH(Char)              \
01777   ((Char) < 0x80 ? 1 :                 \
01778    ((Char) < 0x800 ? 2 :               \
01779     ((Char) < 0x10000 ? 3 :            \
01780      ((Char) < 0x200000 ? 4 :          \
01781       ((Char) < 0x4000000 ? 5 : 6)))))
01782    
01792 #define UTF8_GET(Result, Chars, Count, Mask, Len)                             \
01793   (Result) = (Chars)[0] & (Mask);                                             \
01794   for ((Count) = 1; (Count) < (Len); ++(Count))                               \
01795     {                                                                         \
01796       if (((Chars)[(Count)] & 0xc0) != 0x80)                                  \
01797         {                                                                     \
01798           (Result) = -1;                                                      \
01799           break;                                                              \
01800         }                                                                     \
01801       (Result) <<= 6;                                                         \
01802       (Result) |= ((Chars)[(Count)] & 0x3f);                                  \
01803     }
01804 
01821 #define UNICODE_VALID(Char)                   \
01822     ((Char) < 0x110000 &&                     \
01823      (((Char) & 0xFFFFF800) != 0xD800) &&     \
01824      ((Char) < 0xFDD0 || (Char) > 0xFDEF) &&  \
01825      ((Char) & 0xFFFE) != 0xFFFE)
01826 
01827 #ifdef DBUS_BUILD_TESTS
01828 
01838 void
01839 _dbus_string_get_unichar (const DBusString *str,
01840                           int               start,
01841                           dbus_unichar_t   *ch_return,
01842                           int              *end_return)
01843 {
01844   int i, mask, len;
01845   dbus_unichar_t result;
01846   unsigned char c;
01847   unsigned char *p;
01848   DBUS_CONST_STRING_PREAMBLE (str);
01849   _dbus_assert (start >= 0);
01850   _dbus_assert (start <= real->len);
01851   
01852   if (ch_return)
01853     *ch_return = 0;
01854   if (end_return)
01855     *end_return = real->len;
01856   
01857   mask = 0;
01858   p = real->str + start;
01859   c = *p;
01860   
01861   UTF8_COMPUTE (c, mask, len);
01862   if (len == 0)
01863     return;
01864   UTF8_GET (result, p, i, mask, len);
01865 
01866   if (result == (dbus_unichar_t)-1)
01867     return;
01868 
01869   if (ch_return)
01870     *ch_return = result;
01871   if (end_return)
01872     *end_return = start + len;
01873 }
01874 #endif /* DBUS_BUILD_TESTS */
01875 
01890 dbus_bool_t
01891 _dbus_string_find (const DBusString *str,
01892                    int               start,
01893                    const char       *substr,
01894                    int              *found)
01895 {
01896   return _dbus_string_find_to (str, start,
01897                                ((const DBusRealString*)str)->len,
01898                                substr, found);
01899 }
01900 
01913 dbus_bool_t
01914 _dbus_string_find_eol (const DBusString *str,
01915                        int               start,
01916                        int              *found,
01917                        int              *found_len)
01918 {
01919   int i;
01920 
01921   DBUS_CONST_STRING_PREAMBLE (str);
01922   _dbus_assert (start <= real->len);
01923   _dbus_assert (start >= 0);
01924   
01925   i = start;
01926   while (i < real->len)
01927     {
01928       if (real->str[i] == '\r') 
01929         {
01930           if ((i+1) < real->len && real->str[i+1] == '\n') /* "\r\n" */
01931             {
01932               if (found) 
01933                 *found = i;
01934               if (found_len)
01935                 *found_len = 2;
01936               return TRUE;
01937             } 
01938           else /* only "\r" */
01939             {
01940               if (found) 
01941                 *found = i;
01942               if (found_len)
01943                 *found_len = 1;
01944               return TRUE;
01945             }
01946         } 
01947       else if (real->str[i] == '\n')  /* only "\n" */
01948         {
01949           if (found) 
01950             *found = i;
01951           if (found_len)
01952             *found_len = 1;
01953           return TRUE;
01954         }
01955       ++i;
01956     }
01957 
01958   if (found)
01959     *found = real->len;
01960 
01961   if (found_len)
01962     *found_len = 0;
01963   
01964   return FALSE;
01965 }
01966 
01983 dbus_bool_t
01984 _dbus_string_find_to (const DBusString *str,
01985                       int               start,
01986                       int               end,
01987                       const char       *substr,
01988                       int              *found)
01989 {
01990   int i;
01991   DBUS_CONST_STRING_PREAMBLE (str);
01992   _dbus_assert (substr != NULL);
01993   _dbus_assert (start <= real->len);
01994   _dbus_assert (start >= 0);
01995   _dbus_assert (substr != NULL);
01996   _dbus_assert (end <= real->len);
01997   _dbus_assert (start <= end);
01998 
01999   /* we always "find" an empty string */
02000   if (*substr == '\0')
02001     {
02002       if (found)
02003         *found = start;
02004       return TRUE;
02005     }
02006 
02007   i = start;
02008   while (i < end)
02009     {
02010       if (real->str[i] == substr[0])
02011         {
02012           int j = i + 1;
02013           
02014           while (j < end)
02015             {
02016               if (substr[j - i] == '\0')
02017                 break;
02018               else if (real->str[j] != substr[j - i])
02019                 break;
02020               
02021               ++j;
02022             }
02023 
02024           if (substr[j - i] == '\0')
02025             {
02026               if (found)
02027                 *found = i;
02028               return TRUE;
02029             }
02030         }
02031       
02032       ++i;
02033     }
02034 
02035   if (found)
02036     *found = end;
02037   
02038   return FALSE;  
02039 }
02040 
02051 dbus_bool_t
02052 _dbus_string_find_blank (const DBusString *str,
02053                          int               start,
02054                          int              *found)
02055 {
02056   int i;
02057   DBUS_CONST_STRING_PREAMBLE (str);
02058   _dbus_assert (start <= real->len);
02059   _dbus_assert (start >= 0);
02060   
02061   i = start;
02062   while (i < real->len)
02063     {
02064       if (real->str[i] == ' ' ||
02065           real->str[i] == '\t')
02066         {
02067           if (found)
02068             *found = i;
02069           return TRUE;
02070         }
02071       
02072       ++i;
02073     }
02074 
02075   if (found)
02076     *found = real->len;
02077   
02078   return FALSE;
02079 }
02080 
02089 void
02090 _dbus_string_skip_blank (const DBusString *str,
02091                          int               start,
02092                          int              *end)
02093 {
02094   int i;
02095   DBUS_CONST_STRING_PREAMBLE (str);
02096   _dbus_assert (start <= real->len);
02097   _dbus_assert (start >= 0);
02098   
02099   i = start;
02100   while (i < real->len)
02101     {
02102       if (!DBUS_IS_ASCII_BLANK (real->str[i]))
02103         break;
02104       
02105       ++i;
02106     }
02107 
02108   _dbus_assert (i == real->len || !DBUS_IS_ASCII_WHITE (real->str[i]));
02109   
02110   if (end)
02111     *end = i;
02112 }
02113 
02114 
02123 void
02124 _dbus_string_skip_white (const DBusString *str,
02125                          int               start,
02126                          int              *end)
02127 {
02128   int i;
02129   DBUS_CONST_STRING_PREAMBLE (str);
02130   _dbus_assert (start <= real->len);
02131   _dbus_assert (start >= 0);
02132   
02133   i = start;
02134   while (i < real->len)
02135     {
02136       if (!DBUS_IS_ASCII_WHITE (real->str[i]))
02137         break;
02138       
02139       ++i;
02140     }
02141 
02142   _dbus_assert (i == real->len || !(DBUS_IS_ASCII_WHITE (real->str[i])));
02143   
02144   if (end)
02145     *end = i;
02146 }
02147 
02156 void
02157 _dbus_string_skip_white_reverse (const DBusString *str,
02158                                  int               end,
02159                                  int              *start)
02160 {
02161   int i;
02162   DBUS_CONST_STRING_PREAMBLE (str);
02163   _dbus_assert (end <= real->len);
02164   _dbus_assert (end >= 0);
02165   
02166   i = end;
02167   while (i > 0)
02168     {
02169       if (!DBUS_IS_ASCII_WHITE (real->str[i-1]))
02170         break;
02171       --i;
02172     }
02173 
02174   _dbus_assert (i >= 0 && (i == 0 || !(DBUS_IS_ASCII_WHITE (real->str[i-1]))));
02175   
02176   if (start)
02177     *start = i;
02178 }
02179 
02195 dbus_bool_t
02196 _dbus_string_pop_line (DBusString *source,
02197                        DBusString *dest)
02198 {
02199   int eol, eol_len;
02200   
02201   _dbus_string_set_length (dest, 0);
02202   
02203   eol = 0;
02204   eol_len = 0;
02205   if (!_dbus_string_find_eol (source, 0, &eol, &eol_len))
02206     {
02207       _dbus_assert (eol == _dbus_string_get_length (source));
02208       if (eol == 0)
02209         {
02210           /* If there's no newline and source has zero length, we're done */
02211           return FALSE;
02212         }
02213       /* otherwise, the last line of the file has no eol characters */
02214     }
02215 
02216   /* remember eol can be 0 if it's an empty line, but eol_len should not be zero also
02217    * since find_eol returned TRUE
02218    */
02219   
02220   if (!_dbus_string_move_len (source, 0, eol + eol_len, dest, 0))
02221     return FALSE;
02222   
02223   /* remove line ending */
02224   if (!_dbus_string_set_length (dest, eol))
02225     {
02226       _dbus_assert_not_reached ("out of memory when shortening a string");
02227       return FALSE;
02228     }
02229 
02230   return TRUE;
02231 }
02232 
02233 #ifdef DBUS_BUILD_TESTS
02234 
02240 void
02241 _dbus_string_delete_first_word (DBusString *str)
02242 {
02243   int i;
02244   
02245   if (_dbus_string_find_blank (str, 0, &i))
02246     _dbus_string_skip_blank (str, i, &i);
02247 
02248   _dbus_string_delete (str, 0, i);
02249 }
02250 #endif
02251 
02252 #ifdef DBUS_BUILD_TESTS
02253 
02258 void
02259 _dbus_string_delete_leading_blanks (DBusString *str)
02260 {
02261   int i;
02262   
02263   _dbus_string_skip_blank (str, 0, &i);
02264 
02265   if (i > 0)
02266     _dbus_string_delete (str, 0, i);
02267 }
02268 #endif
02269 
02275 void
02276 _dbus_string_chop_white(DBusString *str)
02277 {
02278   int i;
02279   
02280   _dbus_string_skip_white (str, 0, &i);
02281 
02282   if (i > 0)
02283     _dbus_string_delete (str, 0, i);
02284   
02285   _dbus_string_skip_white_reverse (str, _dbus_string_get_length (str), &i);
02286 
02287   _dbus_string_set_length (str, i);
02288 }
02289 
02299 dbus_bool_t
02300 _dbus_string_equal (const DBusString *a,
02301                     const DBusString *b)
02302 {
02303   const unsigned char *ap;
02304   const unsigned char *bp;
02305   const unsigned char *a_end;
02306   const DBusRealString *real_a = (const DBusRealString*) a;
02307   const DBusRealString *real_b = (const DBusRealString*) b;
02308   DBUS_GENERIC_STRING_PREAMBLE (real_a);
02309   DBUS_GENERIC_STRING_PREAMBLE (real_b);
02310 
02311   if (real_a->len != real_b->len)
02312     return FALSE;
02313 
02314   ap = real_a->str;
02315   bp = real_b->str;
02316   a_end = real_a->str + real_a->len;
02317   while (ap != a_end)
02318     {
02319       if (*ap != *bp)
02320         return FALSE;
02321       
02322       ++ap;
02323       ++bp;
02324     }
02325 
02326   return TRUE;
02327 }
02328 
02342 dbus_bool_t
02343 _dbus_string_equal_len (const DBusString *a,
02344                         const DBusString *b,
02345                         int               len)
02346 {
02347   const unsigned char *ap;
02348   const unsigned char *bp;
02349   const unsigned char *a_end;
02350   const DBusRealString *real_a = (const DBusRealString*) a;
02351   const DBusRealString *real_b = (const DBusRealString*) b;
02352   DBUS_GENERIC_STRING_PREAMBLE (real_a);
02353   DBUS_GENERIC_STRING_PREAMBLE (real_b);
02354 
02355   if (real_a->len != real_b->len &&
02356       (real_a->len < len || real_b->len < len))
02357     return FALSE;
02358 
02359   ap = real_a->str;
02360   bp = real_b->str;
02361   a_end = real_a->str + MIN (real_a->len, len);
02362   while (ap != a_end)
02363     {
02364       if (*ap != *bp)
02365         return FALSE;
02366       
02367       ++ap;
02368       ++bp;
02369     }
02370 
02371   return TRUE;
02372 }
02373 
02390 dbus_bool_t
02391 _dbus_string_equal_substring (const DBusString  *a,
02392                               int                a_start,
02393                               int                a_len,
02394                               const DBusString  *b,
02395                               int                b_start)
02396 {
02397   const unsigned char *ap;
02398   const unsigned char *bp;
02399   const unsigned char *a_end;
02400   const DBusRealString *real_a = (const DBusRealString*) a;
02401   const DBusRealString *real_b = (const DBusRealString*) b;
02402   DBUS_GENERIC_STRING_PREAMBLE (real_a);
02403   DBUS_GENERIC_STRING_PREAMBLE (real_b);
02404   _dbus_assert (a_start >= 0);
02405   _dbus_assert (a_len >= 0);
02406   _dbus_assert (a_start <= real_a->len);
02407   _dbus_assert (a_len <= real_a->len - a_start);
02408   _dbus_assert (b_start >= 0);
02409   _dbus_assert (b_start <= real_b->len);
02410   
02411   if (a_len > real_b->len - b_start)
02412     return FALSE;
02413 
02414   ap = real_a->str + a_start;
02415   bp = real_b->str + b_start;
02416   a_end = ap + a_len;
02417   while (ap != a_end)
02418     {
02419       if (*ap != *bp)
02420         return FALSE;
02421       
02422       ++ap;
02423       ++bp;
02424     }
02425 
02426   _dbus_assert (bp <= (real_b->str + real_b->len));
02427   
02428   return TRUE;
02429 }
02430 
02438 dbus_bool_t
02439 _dbus_string_equal_c_str (const DBusString *a,
02440                           const char       *c_str)
02441 {
02442   const unsigned char *ap;
02443   const unsigned char *bp;
02444   const unsigned char *a_end;
02445   const DBusRealString *real_a = (const DBusRealString*) a;
02446   DBUS_GENERIC_STRING_PREAMBLE (real_a);
02447   _dbus_assert (c_str != NULL);
02448   
02449   ap = real_a->str;
02450   bp = (const unsigned char*) c_str;
02451   a_end = real_a->str + real_a->len;
02452   while (ap != a_end && *bp)
02453     {
02454       if (*ap != *bp)
02455         return FALSE;
02456       
02457       ++ap;
02458       ++bp;
02459     }
02460 
02461   if (ap != a_end || *bp)
02462     return FALSE;
02463   
02464   return TRUE;
02465 }
02466 
02467 #ifdef DBUS_BUILD_TESTS
02468 
02475 dbus_bool_t
02476 _dbus_string_starts_with_c_str (const DBusString *a,
02477                                 const char       *c_str)
02478 {
02479   const unsigned char *ap;
02480   const unsigned char *bp;
02481   const unsigned char *a_end;
02482   const DBusRealString *real_a = (const DBusRealString*) a;
02483   DBUS_GENERIC_STRING_PREAMBLE (real_a);
02484   _dbus_assert (c_str != NULL);
02485   
02486   ap = real_a->str;
02487   bp = (const unsigned char*) c_str;
02488   a_end = real_a->str + real_a->len;
02489   while (ap != a_end && *bp)
02490     {
02491       if (*ap != *bp)
02492         return FALSE;
02493       
02494       ++ap;
02495       ++bp;
02496     }
02497 
02498   if (*bp == '\0')
02499     return TRUE;
02500   else
02501     return FALSE;
02502 }
02503 #endif /* DBUS_BUILD_TESTS */
02504 
02513 dbus_bool_t
02514 _dbus_string_append_byte_as_hex (DBusString *str,
02515                                  int         byte)
02516 {
02517   const char hexdigits[16] = {
02518     '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
02519     'a', 'b', 'c', 'd', 'e', 'f'
02520   };
02521 
02522   if (!_dbus_string_append_byte (str,
02523                                  hexdigits[(byte >> 4)]))
02524     return FALSE;
02525   
02526   if (!_dbus_string_append_byte (str,
02527                                  hexdigits[(byte & 0x0f)]))
02528     {
02529       _dbus_string_set_length (str,
02530                                _dbus_string_get_length (str) - 1);
02531       return FALSE;
02532     }
02533 
02534   return TRUE;
02535 }
02536 
02547 dbus_bool_t
02548 _dbus_string_hex_encode (const DBusString *source,
02549                          int               start,
02550                          DBusString       *dest,
02551                          int               insert_at)
02552 {
02553   DBusString result;
02554   const unsigned char *p;
02555   const unsigned char *end;
02556   dbus_bool_t retval;
02557   
02558   _dbus_assert (start <= _dbus_string_get_length (source));
02559 
02560   if (!_dbus_string_init (&result))
02561     return FALSE;
02562 
02563   retval = FALSE;
02564   
02565   p = (const unsigned char*) _dbus_string_get_const_data (source);
02566   end = p + _dbus_string_get_length (source);
02567   p += start;
02568   
02569   while (p != end)
02570     {
02571       if (!_dbus_string_append_byte_as_hex (&result, *p))
02572         goto out;
02573       
02574       ++p;
02575     }
02576 
02577   if (!_dbus_string_move (&result, 0, dest, insert_at))
02578     goto out;
02579 
02580   retval = TRUE;
02581 
02582  out:
02583   _dbus_string_free (&result);
02584   return retval;
02585 }
02586 
02597 dbus_bool_t
02598 _dbus_string_hex_decode (const DBusString *source,
02599                          int               start,
02600                          int              *end_return,
02601                          DBusString       *dest,
02602                          int               insert_at)
02603 {
02604   DBusString result;
02605   const unsigned char *p;
02606   const unsigned char *end;
02607   dbus_bool_t retval;
02608   dbus_bool_t high_bits;
02609   
02610   _dbus_assert (start <= _dbus_string_get_length (source));
02611 
02612   if (!_dbus_string_init (&result))
02613     return FALSE;
02614 
02615   retval = FALSE;
02616 
02617   high_bits = TRUE;
02618   p = (const unsigned char*) _dbus_string_get_const_data (source);
02619   end = p + _dbus_string_get_length (source);
02620   p += start;
02621   
02622   while (p != end)
02623     {
02624       unsigned int val;
02625 
02626       switch (*p)
02627         {
02628         case '0':
02629           val = 0;
02630           break;
02631         case '1':
02632           val = 1;
02633           break;
02634         case '2':
02635           val = 2;
02636           break;
02637         case '3':
02638           val = 3;
02639           break;
02640         case '4':
02641           val = 4;
02642           break;
02643         case '5':
02644           val = 5;
02645           break;
02646         case '6':
02647           val = 6;
02648           break;
02649         case '7':
02650           val = 7;
02651           break;
02652         case '8':
02653           val = 8;
02654           break;
02655         case '9':
02656           val = 9;
02657           break;
02658         case 'a':
02659         case 'A':
02660           val = 10;
02661           break;
02662         case 'b':
02663         case 'B':
02664           val = 11;
02665           break;
02666         case 'c':
02667         case 'C':
02668           val = 12;
02669           break;
02670         case 'd':
02671         case 'D':
02672           val = 13;
02673           break;
02674         case 'e':
02675         case 'E':
02676           val = 14;
02677           break;
02678         case 'f':
02679         case 'F':
02680           val = 15;
02681           break;
02682         default:
02683           goto done;
02684         }
02685 
02686       if (high_bits)
02687         {
02688           if (!_dbus_string_append_byte (&result,
02689                                          val << 4))
02690             goto out;
02691         }
02692       else
02693         {
02694           int len;
02695           unsigned char b;
02696 
02697           len = _dbus_string_get_length (&result);
02698           
02699           b = _dbus_string_get_byte (&result, len - 1);
02700 
02701           b |= val;
02702 
02703           _dbus_string_set_byte (&result, len - 1, b);
02704         }
02705 
02706       high_bits = !high_bits;
02707 
02708       ++p;
02709     }
02710 
02711  done:
02712   if (!_dbus_string_move (&result, 0, dest, insert_at))
02713     goto out;
02714 
02715   if (end_return)
02716     *end_return = p - (const unsigned char*) _dbus_string_get_const_data (source);
02717 
02718   retval = TRUE;
02719   
02720  out:
02721   _dbus_string_free (&result);  
02722   return retval;
02723 }
02724 
02738 dbus_bool_t
02739 _dbus_string_validate_ascii (const DBusString *str,
02740                              int               start,
02741                              int               len)
02742 {
02743   const unsigned char *s;
02744   const unsigned char *end;
02745   DBUS_CONST_STRING_PREAMBLE (str);
02746   _dbus_assert (start >= 0);
02747   _dbus_assert (start <= real->len);
02748   _dbus_assert (len >= 0);
02749   
02750   if (len > real->len - start)
02751     return FALSE;
02752   
02753   s = real->str + start;
02754   end = s + len;
02755   while (s != end)
02756     {
02757       if (_DBUS_UNLIKELY (!_DBUS_ISASCII (*s)))
02758         return FALSE;
02759         
02760       ++s;
02761     }
02762   
02763   return TRUE;
02764 }
02765 
02773 void
02774 _dbus_string_tolower_ascii (const DBusString *str,
02775                             int               start,
02776                             int               len)
02777 {
02778   unsigned char *s;
02779   unsigned char *end;
02780   DBUS_STRING_PREAMBLE (str);
02781   _dbus_assert (start >= 0);
02782   _dbus_assert (start <= real->len);
02783   _dbus_assert (len >= 0);
02784   _dbus_assert (len <= real->len - start);
02785 
02786   s = real->str + start;
02787   end = s + len;
02788 
02789   while (s != end)
02790     {
02791       if (*s >= 'A' && *s <= 'Z')
02792           *s += 'a' - 'A';
02793       ++s;
02794     }
02795 }
02796 
02804 void
02805 _dbus_string_toupper_ascii (const DBusString *str,
02806                             int               start,
02807                             int               len)
02808 {
02809   unsigned char *s;
02810   unsigned char *end;
02811   DBUS_STRING_PREAMBLE (str);
02812   _dbus_assert (start >= 0);
02813   _dbus_assert (start <= real->len);
02814   _dbus_assert (len >= 0);
02815   _dbus_assert (len <= real->len - start);
02816 
02817   s = real->str + start;
02818   end = s + len;
02819 
02820   while (s != end)
02821     {
02822       if (*s >= 'a' && *s <= 'z')
02823           *s += 'A' - 'a';
02824       ++s;
02825     }
02826 }
02827 
02843 dbus_bool_t
02844 _dbus_string_validate_utf8  (const DBusString *str,
02845                              int               start,
02846                              int               len)
02847 {
02848   const unsigned char *p;
02849   const unsigned char *end;
02850   DBUS_CONST_STRING_PREAMBLE (str);
02851   _dbus_assert (start >= 0);
02852   _dbus_assert (start <= real->len);
02853   _dbus_assert (len >= 0);
02854 
02855   /* we are doing _DBUS_UNLIKELY() here which might be
02856    * dubious in a generic library like GLib, but in D-Bus
02857    * we know we're validating messages and that it would
02858    * only be evil/broken apps that would have invalid
02859    * UTF-8. Also, this function seems to be a performance
02860    * bottleneck in profiles.
02861    */
02862   
02863   if (_DBUS_UNLIKELY (len > real->len - start))
02864     return FALSE;
02865   
02866   p = real->str + start;
02867   end = p + len;
02868   
02869   while (p < end)
02870     {
02871       int i, mask, char_len;
02872       dbus_unichar_t result;
02873 
02874       /* nul bytes considered invalid */
02875       if (*p == '\0')
02876         break;
02877       
02878       /* Special-case ASCII; this makes us go a lot faster in
02879        * D-Bus profiles where we are typically validating
02880        * function names and such. We have to know that
02881        * all following checks will pass for ASCII though,
02882        * comments follow ...
02883        */      
02884       if (*p < 128)
02885         {
02886           ++p;
02887           continue;
02888         }
02889       
02890       UTF8_COMPUTE (*p, mask, char_len);
02891 
02892       if (_DBUS_UNLIKELY (char_len == 0))  /* ASCII: char_len == 1 */
02893         break;
02894 
02895       /* check that the expected number of bytes exists in the remaining length */
02896       if (_DBUS_UNLIKELY ((end - p) < char_len)) /* ASCII: p < end and char_len == 1 */
02897         break;
02898         
02899       UTF8_GET (result, p, i, mask, char_len);
02900 
02901       /* Check for overlong UTF-8 */
02902       if (_DBUS_UNLIKELY (UTF8_LENGTH (result) != char_len)) /* ASCII: UTF8_LENGTH == 1 */
02903         break;
02904 #if 0
02905       /* The UNICODE_VALID check below will catch this */
02906       if (_DBUS_UNLIKELY (result == (dbus_unichar_t)-1)) /* ASCII: result = ascii value */
02907         break;
02908 #endif
02909 
02910       if (_DBUS_UNLIKELY (!UNICODE_VALID (result))) /* ASCII: always valid */
02911         break;
02912 
02913       /* UNICODE_VALID should have caught it */
02914       _dbus_assert (result != (dbus_unichar_t)-1);
02915       
02916       p += char_len;
02917     }
02918 
02919   /* See that we covered the entire length if a length was
02920    * passed in
02921    */
02922   if (_DBUS_UNLIKELY (p != end))
02923     return FALSE;
02924   else
02925     return TRUE;
02926 }
02927 
02941 dbus_bool_t
02942 _dbus_string_validate_nul (const DBusString *str,
02943                            int               start,
02944                            int               len)
02945 {
02946   const unsigned char *s;
02947   const unsigned char *end;
02948   DBUS_CONST_STRING_PREAMBLE (str);
02949   _dbus_assert (start >= 0);
02950   _dbus_assert (len >= 0);
02951   _dbus_assert (start <= real->len);
02952   
02953   if (len > real->len - start)
02954     return FALSE;
02955   
02956   s = real->str + start;
02957   end = s + len;
02958   while (s != end)
02959     {
02960       if (_DBUS_UNLIKELY (*s != '\0'))
02961         return FALSE;
02962       ++s;
02963     }
02964   
02965   return TRUE;
02966 }
02967 
02973 void
02974 _dbus_string_zero (DBusString *str)
02975 {
02976   DBUS_STRING_PREAMBLE (str);
02977 
02978   memset (real->str - real->align_offset, '\0', real->allocated);
02979 }
02982 /* tests are in dbus-string-util.c */