dbus-string.c

00001 /* -*- mode: C; c-file-style: "gnu" -*- */
00002 /* dbus-string.c String utility class (internal to D-Bus implementation)
00003  * 
00004  * Copyright (C) 2002, 2003, 2004, 2005 Red Hat, Inc.
00005  *
00006  * Licensed under the Academic Free License version 2.1
00007  * 
00008  * This program is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * This program is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  * 
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program; if not, write to the Free Software
00020  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021  *
00022  */
00023 
00024 #include "dbus-internals.h"
00025 #include "dbus-string.h"
00026 /* we allow a system header here, for speed/convenience */
00027 #include <string.h>
00028 /* for vsnprintf */
00029 #include <stdio.h>
00030 #define DBUS_CAN_USE_DBUS_STRING_PRIVATE 1
00031 #include "dbus-string-private.h"
00032 #include "dbus-marshal-basic.h" /* probably should be removed by moving the usage of DBUS_TYPE
00033                                  * into the marshaling-related files
00034                                  */
00035 /* for DBUS_VA_COPY */
00036 #include "dbus-sysdeps.h"
00037 
00076 static void
00077 fixup_alignment (DBusRealString *real)
00078 {
00079   unsigned char *aligned;
00080   unsigned char *real_block;
00081   unsigned int old_align_offset;
00082 
00083   /* we have to have extra space in real->allocated for the align offset and nul byte */
00084   _dbus_assert (real->len <= real->allocated - _DBUS_STRING_ALLOCATION_PADDING);
00085   
00086   old_align_offset = real->align_offset;
00087   real_block = real->str - old_align_offset;
00088   
00089   aligned = _DBUS_ALIGN_ADDRESS (real_block, 8);
00090 
00091   real->align_offset = aligned - real_block;
00092   real->str = aligned;
00093   
00094   if (old_align_offset != real->align_offset)
00095     {
00096       /* Here comes the suck */
00097       memmove (real_block + real->align_offset,
00098                real_block + old_align_offset,
00099                real->len + 1);
00100     }
00101 
00102   _dbus_assert (real->align_offset < 8);
00103   _dbus_assert (_DBUS_ALIGN_ADDRESS (real->str, 8) == real->str);
00104 }
00105 
00106 static void
00107 undo_alignment (DBusRealString *real)
00108 {
00109   if (real->align_offset != 0)
00110     {
00111       memmove (real->str - real->align_offset,
00112                real->str,
00113                real->len + 1);
00114 
00115       real->str = real->str - real->align_offset;
00116       real->align_offset = 0;
00117     }
00118 }
00119 
00129 dbus_bool_t
00130 _dbus_string_init_preallocated (DBusString *str,
00131                                 int         allocate_size)
00132 {
00133   DBusRealString *real;
00134   
00135   _dbus_assert (str != NULL);
00136 
00137   _dbus_assert (sizeof (DBusString) == sizeof (DBusRealString));
00138   
00139   real = (DBusRealString*) str;
00140 
00141   /* It's very important not to touch anything
00142    * other than real->str if we're going to fail,
00143    * since we also use this function to reset
00144    * an existing string, e.g. in _dbus_string_steal_data()
00145    */
00146   
00147   real->str = dbus_malloc (_DBUS_STRING_ALLOCATION_PADDING + allocate_size);
00148   if (real->str == NULL)
00149     return FALSE;  
00150   
00151   real->allocated = _DBUS_STRING_ALLOCATION_PADDING + allocate_size;
00152   real->len = 0;
00153   real->str[real->len] = '\0';
00154   
00155   real->max_length = _DBUS_STRING_MAX_MAX_LENGTH;
00156   real->constant = FALSE;
00157   real->locked = FALSE;
00158   real->invalid = FALSE;
00159   real->align_offset = 0;
00160   
00161   fixup_alignment (real);
00162   
00163   return TRUE;
00164 }
00165 
00173 dbus_bool_t
00174 _dbus_string_init (DBusString *str)
00175 {
00176   return _dbus_string_init_preallocated (str, 0);
00177 }
00178 
00179 #ifdef DBUS_BUILD_TESTS
00180 /* The max length thing is sort of a historical artifact
00181  * from a feature that turned out to be dumb; perhaps
00182  * we should purge it entirely. The problem with
00183  * the feature is that it looks like memory allocation
00184  * failure, but is not a transient or resolvable failure.
00185  */
00186 static void
00187 set_max_length (DBusString *str,
00188                 int         max_length)
00189 {
00190   DBusRealString *real;
00191   
00192   real = (DBusRealString*) str;
00193 
00194   real->max_length = max_length;
00195 }
00196 #endif /* DBUS_BUILD_TESTS */
00197 
00207 void
00208 _dbus_string_init_const (DBusString *str,
00209                          const char *value)
00210 {
00211   _dbus_assert (value != NULL);
00212   
00213   _dbus_string_init_const_len (str, value,
00214                                strlen (value));
00215 }
00216 
00227 void
00228 _dbus_string_init_const_len (DBusString *str,
00229                              const char *value,
00230                              int         len)
00231 {
00232   DBusRealString *real;
00233   
00234   _dbus_assert (str != NULL);
00235   _dbus_assert (len == 0 || value != NULL);
00236   _dbus_assert (len <= _DBUS_STRING_MAX_MAX_LENGTH);
00237   _dbus_assert (len >= 0);
00238   
00239   real = (DBusRealString*) str;
00240   
00241   real->str = (unsigned char*) value;
00242   real->len = len;
00243   real->allocated = real->len + _DBUS_STRING_ALLOCATION_PADDING; /* a lie, just to avoid special-case assertions... */
00244   real->max_length = real->len + 1;
00245   real->constant = TRUE;
00246   real->locked = TRUE;
00247   real->invalid = FALSE;
00248   real->align_offset = 0;
00249 
00250   /* We don't require const strings to be 8-byte aligned as the
00251    * memory is coming from elsewhere.
00252    */
00253 }
00254 
00260 void
00261 _dbus_string_free (DBusString *str)
00262 {
00263   DBusRealString *real = (DBusRealString*) str;
00264   DBUS_GENERIC_STRING_PREAMBLE (real);
00265   
00266   if (real->constant)
00267     return;
00268   dbus_free (real->str - real->align_offset);
00269 
00270   real->invalid = TRUE;
00271 }
00272 
00273 #ifdef DBUS_BUILD_TESTS
00274 /* Not using this feature at the moment,
00275  * so marked DBUS_BUILD_TESTS-only
00276  */
00286 void
00287 _dbus_string_lock (DBusString *str)
00288 {  
00289   DBUS_LOCKED_STRING_PREAMBLE (str); /* can lock multiple times */
00290 
00291   real->locked = TRUE;
00292 
00293   /* Try to realloc to avoid excess memory usage, since
00294    * we know we won't change the string further
00295    */
00296 #define MAX_WASTE 48
00297   if (real->allocated - MAX_WASTE > real->len)
00298     {
00299       unsigned char *new_str;
00300       int new_allocated;
00301 
00302       new_allocated = real->len + _DBUS_STRING_ALLOCATION_PADDING;
00303 
00304       new_str = dbus_realloc (real->str - real->align_offset,
00305                               new_allocated);
00306       if (new_str != NULL)
00307         {
00308           real->str = new_str + real->align_offset;
00309           real->allocated = new_allocated;
00310           fixup_alignment (real);
00311         }
00312     }
00313 }
00314 #endif /* DBUS_BUILD_TESTS */
00315 
00316 static dbus_bool_t
00317 reallocate_for_length (DBusRealString *real,
00318                        int             new_length)
00319 {
00320   int new_allocated;
00321   unsigned char *new_str;
00322 
00323   /* at least double our old allocation to avoid O(n), avoiding
00324    * overflow
00325    */
00326   if (real->allocated > (_DBUS_STRING_MAX_MAX_LENGTH + _DBUS_STRING_ALLOCATION_PADDING) / 2)
00327     new_allocated = _DBUS_STRING_MAX_MAX_LENGTH + _DBUS_STRING_ALLOCATION_PADDING;
00328   else
00329     new_allocated = real->allocated * 2;
00330 
00331   /* if you change the code just above here, run the tests without
00332    * the following assert-only hack before you commit
00333    */
00334   /* This is keyed off asserts in addition to tests so when you
00335    * disable asserts to profile, you don't get this destroyer
00336    * of profiles.
00337    */
00338 #ifdef DBUS_DISABLE_ASSERT
00339 #else
00340 #ifdef DBUS_BUILD_TESTS
00341   new_allocated = 0; /* ensure a realloc every time so that we go
00342                       * through all malloc failure codepaths
00343                       */
00344 #endif /* DBUS_BUILD_TESTS */
00345 #endif /* !DBUS_DISABLE_ASSERT */
00346 
00347   /* But be sure we always alloc at least space for the new length */
00348   new_allocated = MAX (new_allocated,
00349                        new_length + _DBUS_STRING_ALLOCATION_PADDING);
00350 
00351   _dbus_assert (new_allocated >= real->allocated); /* code relies on this */
00352   new_str = dbus_realloc (real->str - real->align_offset, new_allocated);
00353   if (_DBUS_UNLIKELY (new_str == NULL))
00354     return FALSE;
00355 
00356   real->str = new_str + real->align_offset;
00357   real->allocated = new_allocated;
00358   fixup_alignment (real);
00359 
00360   return TRUE;
00361 }
00362 
00363 static dbus_bool_t
00364 set_length (DBusRealString *real,
00365             int             new_length)
00366 {
00367   /* Note, we are setting the length not including nul termination */
00368 
00369   /* exceeding max length is the same as failure to allocate memory */
00370   if (_DBUS_UNLIKELY (new_length > real->max_length))
00371     return FALSE;
00372   else if (new_length > (real->allocated - _DBUS_STRING_ALLOCATION_PADDING) &&
00373            _DBUS_UNLIKELY (!reallocate_for_length (real, new_length)))
00374     return FALSE;
00375   else
00376     {
00377       real->len = new_length;
00378       real->str[new_length] = '\0';
00379       return TRUE;
00380     }
00381 }
00382 
00383 static dbus_bool_t
00384 open_gap (int             len,
00385           DBusRealString *dest,
00386           int             insert_at)
00387 {
00388   if (len == 0)
00389     return TRUE;
00390 
00391   if (len > dest->max_length - dest->len)
00392     return FALSE; /* detected overflow of dest->len + len below */
00393   
00394   if (!set_length (dest, dest->len + len))
00395     return FALSE;
00396 
00397   memmove (dest->str + insert_at + len, 
00398            dest->str + insert_at,
00399            dest->len - len - insert_at);
00400 
00401   return TRUE;
00402 }
00403 
00404 #ifndef _dbus_string_get_data
00405 
00416 char*
00417 _dbus_string_get_data (DBusString *str)
00418 {
00419   DBUS_STRING_PREAMBLE (str);
00420   
00421   return (char*) real->str;
00422 }
00423 #endif /* _dbus_string_get_data */
00424 
00425 /* only do the function if we don't have the macro */
00426 #ifndef _dbus_string_get_const_data
00427 
00433 const char*
00434 _dbus_string_get_const_data (const DBusString  *str)
00435 {
00436   DBUS_CONST_STRING_PREAMBLE (str);
00437   
00438   return (const char*) real->str;
00439 }
00440 #endif /* _dbus_string_get_const_data */
00441 
00455 char*
00456 _dbus_string_get_data_len (DBusString *str,
00457                            int         start,
00458                            int         len)
00459 {
00460   DBUS_STRING_PREAMBLE (str);
00461   _dbus_assert (start >= 0);
00462   _dbus_assert (len >= 0);
00463   _dbus_assert (start <= real->len);
00464   _dbus_assert (len <= real->len - start);
00465   
00466   return (char*) real->str + start;
00467 }
00468 
00469 /* only do the function if we don't have the macro */
00470 #ifndef _dbus_string_get_const_data_len
00471 
00479 const char*
00480 _dbus_string_get_const_data_len (const DBusString  *str,
00481                                  int                start,
00482                                  int                len)
00483 {
00484   DBUS_CONST_STRING_PREAMBLE (str);
00485   _dbus_assert (start >= 0);
00486   _dbus_assert (len >= 0);
00487   _dbus_assert (start <= real->len);
00488   _dbus_assert (len <= real->len - start);
00489   
00490   return (const char*) real->str + start;
00491 }
00492 #endif /* _dbus_string_get_const_data_len */
00493 
00494 /* only do the function if we don't have the macro */
00495 #ifndef _dbus_string_set_byte
00496 
00503 void
00504 _dbus_string_set_byte (DBusString    *str,
00505                        int            i,
00506                        unsigned char  byte)
00507 {
00508   DBUS_STRING_PREAMBLE (str);
00509   _dbus_assert (i < real->len);
00510   _dbus_assert (i >= 0);
00511   
00512   real->str[i] = byte;
00513 }
00514 #endif /* _dbus_string_set_byte */
00515 
00516 /* only have the function if we didn't create a macro */
00517 #ifndef _dbus_string_get_byte
00518 
00527 unsigned char
00528 _dbus_string_get_byte (const DBusString  *str,
00529                        int                start)
00530 {
00531   DBUS_CONST_STRING_PREAMBLE (str);
00532   _dbus_assert (start <= real->len);
00533   _dbus_assert (start >= 0);
00534   
00535   return real->str[start];
00536 }
00537 #endif /* _dbus_string_get_byte */
00538 
00549 dbus_bool_t
00550 _dbus_string_insert_bytes (DBusString   *str,
00551                            int           i,
00552                            int           n_bytes,
00553                            unsigned char byte)
00554 {
00555   DBUS_STRING_PREAMBLE (str);
00556   _dbus_assert (i <= real->len);
00557   _dbus_assert (i >= 0);
00558   _dbus_assert (n_bytes >= 0);
00559 
00560   if (n_bytes == 0)
00561     return TRUE;
00562   
00563   if (!open_gap (n_bytes, real, i))
00564     return FALSE;
00565   
00566   memset (real->str + i, byte, n_bytes);
00567 
00568   return TRUE;
00569 }
00570 
00579 dbus_bool_t
00580 _dbus_string_insert_byte (DBusString   *str,
00581                            int           i,
00582                            unsigned char byte)
00583 {
00584   DBUS_STRING_PREAMBLE (str);
00585   _dbus_assert (i <= real->len);
00586   _dbus_assert (i >= 0);
00587   
00588   if (!open_gap (1, real, i))
00589     return FALSE;
00590 
00591   real->str[i] = byte;
00592 
00593   return TRUE;
00594 }
00595 
00606 dbus_bool_t
00607 _dbus_string_steal_data (DBusString        *str,
00608                          char             **data_return)
00609 {
00610   int old_max_length;
00611   DBUS_STRING_PREAMBLE (str);
00612   _dbus_assert (data_return != NULL);
00613 
00614   undo_alignment (real);
00615   
00616   *data_return = (char*) real->str;
00617 
00618   old_max_length = real->max_length;
00619   
00620   /* reset the string */
00621   if (!_dbus_string_init (str))
00622     {
00623       /* hrm, put it back then */
00624       real->str = (unsigned char*) *data_return;
00625       *data_return = NULL;
00626       fixup_alignment (real);
00627       return FALSE;
00628     }
00629 
00630   real->max_length = old_max_length;
00631 
00632   return TRUE;
00633 }
00634 
00635 #ifdef DBUS_BUILD_TESTS
00636 
00651 dbus_bool_t
00652 _dbus_string_steal_data_len (DBusString        *str,
00653                              char             **data_return,
00654                              int                start,
00655                              int                len)
00656 {
00657   DBusString dest;
00658   DBUS_STRING_PREAMBLE (str);
00659   _dbus_assert (data_return != NULL);
00660   _dbus_assert (start >= 0);
00661   _dbus_assert (len >= 0);
00662   _dbus_assert (start <= real->len);
00663   _dbus_assert (len <= real->len - start);
00664 
00665   if (!_dbus_string_init (&dest))
00666     return FALSE;
00667 
00668   set_max_length (&dest, real->max_length);
00669   
00670   if (!_dbus_string_move_len (str, start, len, &dest, 0))
00671     {
00672       _dbus_string_free (&dest);
00673       return FALSE;
00674     }
00675 
00676   _dbus_warn ("Broken code in _dbus_string_steal_data_len(), see @todo, FIXME\n");
00677   if (!_dbus_string_steal_data (&dest, data_return))
00678     {
00679       _dbus_string_free (&dest);
00680       return FALSE;
00681     }
00682 
00683   _dbus_string_free (&dest);
00684   return TRUE;
00685 }
00686 #endif /* DBUS_BUILD_TESTS */
00687 
00695 dbus_bool_t
00696 _dbus_string_copy_data (const DBusString  *str,
00697                         char             **data_return)
00698 {
00699   DBUS_CONST_STRING_PREAMBLE (str);
00700   _dbus_assert (data_return != NULL);
00701   
00702   *data_return = dbus_malloc (real->len + 1);
00703   if (*data_return == NULL)
00704     return FALSE;
00705 
00706   memcpy (*data_return, real->str, real->len + 1);
00707 
00708   return TRUE;
00709 }
00710 
00719 void
00720 _dbus_string_copy_to_buffer (const DBusString  *str,
00721                              char              *buffer,
00722                              int                avail_len)
00723 {
00724   int copy_len;
00725   DBUS_CONST_STRING_PREAMBLE (str);
00726 
00727   _dbus_assert (avail_len >= 0);
00728 
00729   copy_len = MIN (avail_len, real->len+1);
00730   memcpy (buffer, real->str, copy_len);
00731   if (avail_len > 0 && avail_len == copy_len)
00732     buffer[avail_len-1] = '\0';
00733 }
00734 
00735 #ifdef DBUS_BUILD_TESTS
00736 
00745 dbus_bool_t
00746 _dbus_string_copy_data_len (const DBusString  *str,
00747                             char             **data_return,
00748                             int                start,
00749                             int                len)
00750 {
00751   DBusString dest;
00752 
00753   DBUS_CONST_STRING_PREAMBLE (str);
00754   _dbus_assert (data_return != NULL);
00755   _dbus_assert (start >= 0);
00756   _dbus_assert (len >= 0);
00757   _dbus_assert (start <= real->len);
00758   _dbus_assert (len <= real->len - start);
00759 
00760   if (!_dbus_string_init (&dest))
00761     return FALSE;
00762 
00763   set_max_length (&dest, real->max_length);
00764 
00765   if (!_dbus_string_copy_len (str, start, len, &dest, 0))
00766     {
00767       _dbus_string_free (&dest);
00768       return FALSE;
00769     }
00770 
00771   if (!_dbus_string_steal_data (&dest, data_return))
00772     {
00773       _dbus_string_free (&dest);
00774       return FALSE;
00775     }
00776 
00777   _dbus_string_free (&dest);
00778   return TRUE;
00779 }
00780 #endif /* DBUS_BUILD_TESTS */
00781 
00782 /* Only have the function if we don't have the macro */
00783 #ifndef _dbus_string_get_length
00784 
00789 int
00790 _dbus_string_get_length (const DBusString  *str)
00791 {
00792   DBUS_CONST_STRING_PREAMBLE (str);
00793   
00794   return real->len;
00795 }
00796 #endif /* !_dbus_string_get_length */
00797 
00810 dbus_bool_t
00811 _dbus_string_lengthen (DBusString *str,
00812                        int         additional_length)
00813 {
00814   DBUS_STRING_PREAMBLE (str);  
00815   _dbus_assert (additional_length >= 0);
00816 
00817   if (_DBUS_UNLIKELY (additional_length > real->max_length - real->len))
00818     return FALSE; /* would overflow */
00819   
00820   return set_length (real,
00821                      real->len + additional_length);
00822 }
00823 
00830 void
00831 _dbus_string_shorten (DBusString *str,
00832                       int         length_to_remove)
00833 {
00834   DBUS_STRING_PREAMBLE (str);
00835   _dbus_assert (length_to_remove >= 0);
00836   _dbus_assert (length_to_remove <= real->len);
00837 
00838   set_length (real,
00839               real->len - length_to_remove);
00840 }
00841 
00852 dbus_bool_t
00853 _dbus_string_set_length (DBusString *str,
00854                          int         length)
00855 {
00856   DBUS_STRING_PREAMBLE (str);
00857   _dbus_assert (length >= 0);
00858 
00859   return set_length (real, length);
00860 }
00861 
00862 static dbus_bool_t
00863 align_insert_point_then_open_gap (DBusString *str,
00864                                   int        *insert_at_p,
00865                                   int         alignment,
00866                                   int         gap_size)
00867 {
00868   unsigned long new_len; /* ulong to avoid _DBUS_ALIGN_VALUE overflow */
00869   unsigned long gap_pos;
00870   int insert_at;
00871   int delta;
00872   DBUS_STRING_PREAMBLE (str);
00873   _dbus_assert (alignment >= 1);
00874   _dbus_assert (alignment <= 8); /* it has to be a bug if > 8 */
00875 
00876   insert_at = *insert_at_p;
00877 
00878   _dbus_assert (insert_at <= real->len);
00879   
00880   gap_pos = _DBUS_ALIGN_VALUE (insert_at, alignment);
00881   new_len = real->len + (gap_pos - insert_at) + gap_size;
00882   
00883   if (_DBUS_UNLIKELY (new_len > (unsigned long) real->max_length))
00884     return FALSE;
00885   
00886   delta = new_len - real->len;
00887   _dbus_assert (delta >= 0);
00888 
00889   if (delta == 0) /* only happens if gap_size == 0 and insert_at is aligned already */
00890     {
00891       _dbus_assert (((unsigned long) *insert_at_p) == gap_pos);
00892       return TRUE;
00893     }
00894 
00895   if (_DBUS_UNLIKELY (!open_gap (new_len - real->len,
00896                                  real, insert_at)))
00897     return FALSE;
00898 
00899   /* nul the padding if we had to add any padding */
00900   if (gap_size < delta)
00901     {
00902       memset (&real->str[insert_at], '\0',
00903               gap_pos - insert_at);
00904     }
00905 
00906   *insert_at_p = gap_pos;
00907   
00908   return TRUE;
00909 }
00910 
00911 static dbus_bool_t
00912 align_length_then_lengthen (DBusString *str,
00913                             int         alignment,
00914                             int         then_lengthen_by)
00915 {
00916   int insert_at;
00917 
00918   insert_at = _dbus_string_get_length (str);
00919   
00920   return align_insert_point_then_open_gap (str,
00921                                            &insert_at,
00922                                            alignment, then_lengthen_by);
00923 }
00924 
00933 dbus_bool_t
00934 _dbus_string_align_length (DBusString *str,
00935                            int         alignment)
00936 {
00937   return align_length_then_lengthen (str, alignment, 0);
00938 }
00939 
00949 dbus_bool_t
00950 _dbus_string_alloc_space (DBusString        *str,
00951                           int                extra_bytes)
00952 {
00953   if (!_dbus_string_lengthen (str, extra_bytes))
00954     return FALSE;
00955   _dbus_string_shorten (str, extra_bytes);
00956 
00957   return TRUE;
00958 }
00959 
00960 static dbus_bool_t
00961 append (DBusRealString *real,
00962         const char     *buffer,
00963         int             buffer_len)
00964 {
00965   if (buffer_len == 0)
00966     return TRUE;
00967 
00968   if (!_dbus_string_lengthen ((DBusString*)real, buffer_len))
00969     return FALSE;
00970 
00971   memcpy (real->str + (real->len - buffer_len),
00972           buffer,
00973           buffer_len);
00974 
00975   return TRUE;
00976 }
00977 
00985 dbus_bool_t
00986 _dbus_string_append (DBusString *str,
00987                      const char *buffer)
00988 {
00989   unsigned long buffer_len;
00990   
00991   DBUS_STRING_PREAMBLE (str);
00992   _dbus_assert (buffer != NULL);
00993   
00994   buffer_len = strlen (buffer);
00995   if (buffer_len > (unsigned long) real->max_length)
00996     return FALSE;
00997   
00998   return append (real, buffer, buffer_len);
00999 }
01000 
01002 #define ASSIGN_2_OCTETS(p, octets) \
01003   *((dbus_uint16_t*)(p)) = *((dbus_uint16_t*)(octets));
01004 
01006 #define ASSIGN_4_OCTETS(p, octets) \
01007   *((dbus_uint32_t*)(p)) = *((dbus_uint32_t*)(octets));
01008 
01009 #ifdef DBUS_HAVE_INT64
01010 
01011 #define ASSIGN_8_OCTETS(p, octets) \
01012   *((dbus_uint64_t*)(p)) = *((dbus_uint64_t*)(octets));
01013 #else
01014 
01015 #define ASSIGN_8_OCTETS(p, octets)              \
01016 do {                                            \
01017   unsigned char *b;                             \
01018                                                 \
01019   b = p;                                        \
01020                                                 \
01021   *b++ = octets[0];                             \
01022   *b++ = octets[1];                             \
01023   *b++ = octets[2];                             \
01024   *b++ = octets[3];                             \
01025   *b++ = octets[4];                             \
01026   *b++ = octets[5];                             \
01027   *b++ = octets[6];                             \
01028   *b++ = octets[7];                             \
01029   _dbus_assert (b == p + 8);                    \
01030 } while (0)
01031 #endif /* DBUS_HAVE_INT64 */
01032 
01033 #ifdef DBUS_BUILD_TESTS
01034 
01042 dbus_bool_t
01043 _dbus_string_append_4_aligned (DBusString         *str,
01044                                const unsigned char octets[4])
01045 {
01046   DBUS_STRING_PREAMBLE (str);
01047   
01048   if (!align_length_then_lengthen (str, 4, 4))
01049     return FALSE;
01050 
01051   ASSIGN_4_OCTETS (real->str + (real->len - 4), octets);
01052 
01053   return TRUE;
01054 }
01055 #endif /* DBUS_BUILD_TESTS */
01056 
01057 #ifdef DBUS_BUILD_TESTS
01058 
01066 dbus_bool_t
01067 _dbus_string_append_8_aligned (DBusString         *str,
01068                                const unsigned char octets[8])
01069 {
01070   DBUS_STRING_PREAMBLE (str);
01071   
01072   if (!align_length_then_lengthen (str, 8, 8))
01073     return FALSE;
01074 
01075   ASSIGN_8_OCTETS (real->str + (real->len - 8), octets);
01076 
01077   return TRUE;
01078 }
01079 #endif /* DBUS_BUILD_TESTS */
01080 
01090 dbus_bool_t
01091 _dbus_string_insert_2_aligned (DBusString         *str,
01092                                int                 insert_at,
01093                                const unsigned char octets[4])
01094 {
01095   DBUS_STRING_PREAMBLE (str);
01096   
01097   if (!align_insert_point_then_open_gap (str, &insert_at, 2, 2))
01098     return FALSE;
01099 
01100   ASSIGN_2_OCTETS (real->str + insert_at, octets);
01101 
01102   return TRUE;
01103 }
01104 
01114 dbus_bool_t
01115 _dbus_string_insert_4_aligned (DBusString         *str,
01116                                int                 insert_at,
01117                                const unsigned char octets[4])
01118 {
01119   DBUS_STRING_PREAMBLE (str);
01120   
01121   if (!align_insert_point_then_open_gap (str, &insert_at, 4, 4))
01122     return FALSE;
01123 
01124   ASSIGN_4_OCTETS (real->str + insert_at, octets);
01125 
01126   return TRUE;
01127 }
01128 
01138 dbus_bool_t
01139 _dbus_string_insert_8_aligned (DBusString         *str,
01140                                int                 insert_at,
01141                                const unsigned char octets[8])
01142 {
01143   DBUS_STRING_PREAMBLE (str);
01144   
01145   if (!align_insert_point_then_open_gap (str, &insert_at, 8, 8))
01146     return FALSE;
01147 
01148   _dbus_assert (_DBUS_ALIGN_VALUE (insert_at, 8) == (unsigned) insert_at);
01149   
01150   ASSIGN_8_OCTETS (real->str + insert_at, octets);
01151 
01152   return TRUE;
01153 }
01154 
01155 
01166 dbus_bool_t
01167 _dbus_string_insert_alignment (DBusString        *str,
01168                                int               *insert_at,
01169                                int                alignment)
01170 {
01171   DBUS_STRING_PREAMBLE (str);
01172   
01173   if (!align_insert_point_then_open_gap (str, insert_at, alignment, 0))
01174     return FALSE;
01175 
01176   _dbus_assert (_DBUS_ALIGN_VALUE (*insert_at, alignment) == (unsigned) *insert_at);
01177 
01178   return TRUE;
01179 }
01180 
01190 dbus_bool_t
01191 _dbus_string_append_printf_valist  (DBusString        *str,
01192                                     const char        *format,
01193                                     va_list            args)
01194 {
01195   int len;
01196   va_list args_copy;
01197 
01198   DBUS_STRING_PREAMBLE (str);
01199 
01200   DBUS_VA_COPY (args_copy, args);
01201 
01202   /* Measure the message length without terminating nul */
01203   len = _dbus_printf_string_upper_bound (format, args);
01204 
01205   if (!_dbus_string_lengthen (str, len))
01206     {
01207       /* don't leak the copy */
01208       va_end (args_copy);
01209       return FALSE;
01210     }
01211   
01212   vsprintf ((char*) (real->str + (real->len - len)),
01213             format, args_copy);
01214 
01215   va_end (args_copy);
01216 
01217   return TRUE;
01218 }
01219 
01228 dbus_bool_t
01229 _dbus_string_append_printf (DBusString        *str,
01230                             const char        *format,
01231                             ...)
01232 {
01233   va_list args;
01234   dbus_bool_t retval;
01235   
01236   va_start (args, format);
01237   retval = _dbus_string_append_printf_valist (str, format, args);
01238   va_end (args);
01239 
01240   return retval;
01241 }
01242 
01251 dbus_bool_t
01252 _dbus_string_append_len (DBusString *str,
01253                          const char *buffer,
01254                          int         len)
01255 {
01256   DBUS_STRING_PREAMBLE (str);
01257   _dbus_assert (buffer != NULL);
01258   _dbus_assert (len >= 0);
01259 
01260   return append (real, buffer, len);
01261 }
01262 
01271 dbus_bool_t
01272 _dbus_string_append_byte (DBusString    *str,
01273                           unsigned char  byte)
01274 {
01275   DBUS_STRING_PREAMBLE (str);
01276 
01277   if (!set_length (real, real->len + 1))
01278     return FALSE;
01279 
01280   real->str[real->len-1] = byte;
01281 
01282   return TRUE;
01283 }
01284 
01285 #ifdef DBUS_BUILD_TESTS
01286 
01293 dbus_bool_t
01294 _dbus_string_append_unichar (DBusString    *str,
01295                              dbus_unichar_t ch)
01296 {
01297   int len;
01298   int first;
01299   int i;
01300   unsigned char *out;
01301   
01302   DBUS_STRING_PREAMBLE (str);
01303 
01304   /* this code is from GLib but is pretty standard I think */
01305   
01306   len = 0;
01307   
01308   if (ch < 0x80)
01309     {
01310       first = 0;
01311       len = 1;
01312     }
01313   else if (ch < 0x800)
01314     {
01315       first = 0xc0;
01316       len = 2;
01317     }
01318   else if (ch < 0x10000)
01319     {
01320       first = 0xe0;
01321       len = 3;
01322     }
01323    else if (ch < 0x200000)
01324     {
01325       first = 0xf0;
01326       len = 4;
01327     }
01328   else if (ch < 0x4000000)
01329     {
01330       first = 0xf8;
01331       len = 5;
01332     }
01333   else
01334     {
01335       first = 0xfc;
01336       len = 6;
01337     }
01338 
01339   if (len > (real->max_length - real->len))
01340     return FALSE; /* real->len + len would overflow */
01341   
01342   if (!set_length (real, real->len + len))
01343     return FALSE;
01344 
01345   out = real->str + (real->len - len);
01346   
01347   for (i = len - 1; i > 0; --i)
01348     {
01349       out[i] = (ch & 0x3f) | 0x80;
01350       ch >>= 6;
01351     }
01352   out[0] = ch | first;
01353 
01354   return TRUE;
01355 }
01356 #endif /* DBUS_BUILD_TESTS */
01357 
01358 static void
01359 delete (DBusRealString *real,
01360         int             start,
01361         int             len)
01362 {
01363   if (len == 0)
01364     return;
01365   
01366   memmove (real->str + start, real->str + start + len, real->len - (start + len));
01367   real->len -= len;
01368   real->str[real->len] = '\0';
01369 }
01370 
01380 void
01381 _dbus_string_delete (DBusString       *str,
01382                      int               start,
01383                      int               len)
01384 {
01385   DBUS_STRING_PREAMBLE (str);
01386   _dbus_assert (start >= 0);
01387   _dbus_assert (len >= 0);
01388   _dbus_assert (start <= real->len);
01389   _dbus_assert (len <= real->len - start);
01390   
01391   delete (real, start, len);
01392 }
01393 
01394 static dbus_bool_t
01395 copy (DBusRealString *source,
01396       int             start,
01397       int             len,
01398       DBusRealString *dest,
01399       int             insert_at)
01400 {
01401   if (len == 0)
01402     return TRUE;
01403 
01404   if (!open_gap (len, dest, insert_at))
01405     return FALSE;
01406   
01407   memmove (dest->str + insert_at,
01408            source->str + start,
01409            len);
01410 
01411   return TRUE;
01412 }
01413 
01423 #define DBUS_STRING_COPY_PREAMBLE(source, start, dest, insert_at)       \
01424   DBusRealString *real_source = (DBusRealString*) source;               \
01425   DBusRealString *real_dest = (DBusRealString*) dest;                   \
01426   _dbus_assert ((source) != (dest));                                    \
01427   DBUS_GENERIC_STRING_PREAMBLE (real_source);                           \
01428   DBUS_GENERIC_STRING_PREAMBLE (real_dest);                             \
01429   _dbus_assert (!real_dest->constant);                                  \
01430   _dbus_assert (!real_dest->locked);                                    \
01431   _dbus_assert ((start) >= 0);                                          \
01432   _dbus_assert ((start) <= real_source->len);                           \
01433   _dbus_assert ((insert_at) >= 0);                                      \
01434   _dbus_assert ((insert_at) <= real_dest->len)
01435 
01446 dbus_bool_t
01447 _dbus_string_move (DBusString       *source,
01448                    int               start,
01449                    DBusString       *dest,
01450                    int               insert_at)
01451 {
01452   DBusRealString *real_source = (DBusRealString*) source;
01453   _dbus_assert (start <= real_source->len);
01454   
01455   return _dbus_string_move_len (source, start,
01456                                 real_source->len - start,
01457                                 dest, insert_at);
01458 }
01459 
01470 dbus_bool_t
01471 _dbus_string_copy (const DBusString *source,
01472                    int               start,
01473                    DBusString       *dest,
01474                    int               insert_at)
01475 {
01476   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
01477 
01478   return copy (real_source, start,
01479                real_source->len - start,
01480                real_dest,
01481                insert_at);
01482 }
01483 
01498 dbus_bool_t
01499 _dbus_string_move_len (DBusString       *source,
01500                        int               start,
01501                        int               len,
01502                        DBusString       *dest,
01503                        int               insert_at)
01504 
01505 {
01506   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
01507   _dbus_assert (len >= 0);
01508   _dbus_assert ((start + len) <= real_source->len);
01509 
01510 
01511   if (len == 0)
01512     {
01513       return TRUE;
01514     }
01515   else if (start == 0 &&
01516            len == real_source->len &&
01517            real_dest->len == 0)
01518     {
01519       /* Short-circuit moving an entire existing string to an empty string
01520        * by just swapping the buffers.
01521        */
01522       /* we assume ->constant doesn't matter as you can't have
01523        * a constant string involved in a move.
01524        */
01525 #define ASSIGN_DATA(a, b) do {                  \
01526         (a)->str = (b)->str;                    \
01527         (a)->len = (b)->len;                    \
01528         (a)->allocated = (b)->allocated;        \
01529         (a)->align_offset = (b)->align_offset;  \
01530       } while (0)
01531       
01532       DBusRealString tmp;
01533 
01534       ASSIGN_DATA (&tmp, real_source);
01535       ASSIGN_DATA (real_source, real_dest);
01536       ASSIGN_DATA (real_dest, &tmp);
01537 
01538       return TRUE;
01539     }
01540   else
01541     {
01542       if (!copy (real_source, start, len,
01543                  real_dest,
01544                  insert_at))
01545         return FALSE;
01546       
01547       delete (real_source, start,
01548               len);
01549       
01550       return TRUE;
01551     }
01552 }
01553 
01565 dbus_bool_t
01566 _dbus_string_copy_len (const DBusString *source,
01567                        int               start,
01568                        int               len,
01569                        DBusString       *dest,
01570                        int               insert_at)
01571 {
01572   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
01573   _dbus_assert (len >= 0);
01574   _dbus_assert (start <= real_source->len);
01575   _dbus_assert (len <= real_source->len - start);
01576   
01577   return copy (real_source, start, len,
01578                real_dest,
01579                insert_at);
01580 }
01581 
01603 dbus_bool_t
01604 _dbus_string_replace_len (const DBusString *source,
01605                           int               start,
01606                           int               len,
01607                           DBusString       *dest,
01608                           int               replace_at,
01609                           int               replace_len)
01610 {
01611   DBUS_STRING_COPY_PREAMBLE (source, start, dest, replace_at);
01612   _dbus_assert (len >= 0);
01613   _dbus_assert (start <= real_source->len);
01614   _dbus_assert (len <= real_source->len - start);
01615   _dbus_assert (replace_at >= 0);
01616   _dbus_assert (replace_at <= real_dest->len);
01617   _dbus_assert (replace_len <= real_dest->len - replace_at);
01618 
01619   if (!copy (real_source, start, len,
01620              real_dest, replace_at))
01621     return FALSE;
01622 
01623   delete (real_dest, replace_at + len, replace_len);
01624 
01625   return TRUE;
01626 }
01627 
01628 /* Unicode macros and utf8_validate() from GLib Owen Taylor, Havoc
01629  * Pennington, and Tom Tromey are the authors and authorized relicense.
01630  */
01631 
01637 #define UTF8_COMPUTE(Char, Mask, Len)                                         \
01638   if (Char < 128)                                                             \
01639     {                                                                         \
01640       Len = 1;                                                                \
01641       Mask = 0x7f;                                                            \
01642     }                                                                         \
01643   else if ((Char & 0xe0) == 0xc0)                                             \
01644     {                                                                         \
01645       Len = 2;                                                                \
01646       Mask = 0x1f;                                                            \
01647     }                                                                         \
01648   else if ((Char & 0xf0) == 0xe0)                                             \
01649     {                                                                         \
01650       Len = 3;                                                                \
01651       Mask = 0x0f;                                                            \
01652     }                                                                         \
01653   else if ((Char & 0xf8) == 0xf0)                                             \
01654     {                                                                         \
01655       Len = 4;                                                                \
01656       Mask = 0x07;                                                            \
01657     }                                                                         \
01658   else if ((Char & 0xfc) == 0xf8)                                             \
01659     {                                                                         \
01660       Len = 5;                                                                \
01661       Mask = 0x03;                                                            \
01662     }                                                                         \
01663   else if ((Char & 0xfe) == 0xfc)                                             \
01664     {                                                                         \
01665       Len = 6;                                                                \
01666       Mask = 0x01;                                                            \
01667     }                                                                         \
01668   else                                                                        \
01669     {                                                                         \
01670       Len = 0;                                                               \
01671       Mask = 0;                                                               \
01672     }
01673 
01678 #define UTF8_LENGTH(Char)              \
01679   ((Char) < 0x80 ? 1 :                 \
01680    ((Char) < 0x800 ? 2 :               \
01681     ((Char) < 0x10000 ? 3 :            \
01682      ((Char) < 0x200000 ? 4 :          \
01683       ((Char) < 0x4000000 ? 5 : 6)))))
01684    
01694 #define UTF8_GET(Result, Chars, Count, Mask, Len)                             \
01695   (Result) = (Chars)[0] & (Mask);                                             \
01696   for ((Count) = 1; (Count) < (Len); ++(Count))                               \
01697     {                                                                         \
01698       if (((Chars)[(Count)] & 0xc0) != 0x80)                                  \
01699         {                                                                     \
01700           (Result) = -1;                                                      \
01701           break;                                                              \
01702         }                                                                     \
01703       (Result) <<= 6;                                                         \
01704       (Result) |= ((Chars)[(Count)] & 0x3f);                                  \
01705     }
01706 
01712 #define UNICODE_VALID(Char)                   \
01713     ((Char) < 0x110000 &&                     \
01714      (((Char) & 0xFFFFF800) != 0xD800) &&     \
01715      ((Char) < 0xFDD0 || (Char) > 0xFDEF) &&  \
01716      ((Char) & 0xFFFF) != 0xFFFF)
01717 
01718 #ifdef DBUS_BUILD_TESTS
01719 
01729 void
01730 _dbus_string_get_unichar (const DBusString *str,
01731                           int               start,
01732                           dbus_unichar_t   *ch_return,
01733                           int              *end_return)
01734 {
01735   int i, mask, len;
01736   dbus_unichar_t result;
01737   unsigned char c;
01738   unsigned char *p;
01739   DBUS_CONST_STRING_PREAMBLE (str);
01740   _dbus_assert (start >= 0);
01741   _dbus_assert (start <= real->len);
01742   
01743   if (ch_return)
01744     *ch_return = 0;
01745   if (end_return)
01746     *end_return = real->len;
01747   
01748   mask = 0;
01749   p = real->str + start;
01750   c = *p;
01751   
01752   UTF8_COMPUTE (c, mask, len);
01753   if (len == 0)
01754     return;
01755   UTF8_GET (result, p, i, mask, len);
01756 
01757   if (result == (dbus_unichar_t)-1)
01758     return;
01759 
01760   if (ch_return)
01761     *ch_return = result;
01762   if (end_return)
01763     *end_return = start + len;
01764 }
01765 #endif /* DBUS_BUILD_TESTS */
01766 
01781 dbus_bool_t
01782 _dbus_string_find (const DBusString *str,
01783                    int               start,
01784                    const char       *substr,
01785                    int              *found)
01786 {
01787   return _dbus_string_find_to (str, start,
01788                                ((const DBusRealString*)str)->len,
01789                                substr, found);
01790 }
01791 
01808 dbus_bool_t
01809 _dbus_string_find_to (const DBusString *str,
01810                       int               start,
01811                       int               end,
01812                       const char       *substr,
01813                       int              *found)
01814 {
01815   int i;
01816   DBUS_CONST_STRING_PREAMBLE (str);
01817   _dbus_assert (substr != NULL);
01818   _dbus_assert (start <= real->len);
01819   _dbus_assert (start >= 0);
01820   _dbus_assert (substr != NULL);
01821   _dbus_assert (end <= real->len);
01822   _dbus_assert (start <= end);
01823 
01824   /* we always "find" an empty string */
01825   if (*substr == '\0')
01826     {
01827       if (found)
01828         *found = start;
01829       return TRUE;
01830     }
01831 
01832   i = start;
01833   while (i < end)
01834     {
01835       if (real->str[i] == substr[0])
01836         {
01837           int j = i + 1;
01838           
01839           while (j < end)
01840             {
01841               if (substr[j - i] == '\0')
01842                 break;
01843               else if (real->str[j] != substr[j - i])
01844                 break;
01845               
01846               ++j;
01847             }
01848 
01849           if (substr[j - i] == '\0')
01850             {
01851               if (found)
01852                 *found = i;
01853               return TRUE;
01854             }
01855         }
01856       
01857       ++i;
01858     }
01859 
01860   if (found)
01861     *found = end;
01862   
01863   return FALSE;  
01864 }
01865 
01876 dbus_bool_t
01877 _dbus_string_find_blank (const DBusString *str,
01878                          int               start,
01879                          int              *found)
01880 {
01881   int i;
01882   DBUS_CONST_STRING_PREAMBLE (str);
01883   _dbus_assert (start <= real->len);
01884   _dbus_assert (start >= 0);
01885   
01886   i = start;
01887   while (i < real->len)
01888     {
01889       if (real->str[i] == ' ' ||
01890           real->str[i] == '\t')
01891         {
01892           if (found)
01893             *found = i;
01894           return TRUE;
01895         }
01896       
01897       ++i;
01898     }
01899 
01900   if (found)
01901     *found = real->len;
01902   
01903   return FALSE;
01904 }
01905 
01914 void
01915 _dbus_string_skip_blank (const DBusString *str,
01916                          int               start,
01917                          int              *end)
01918 {
01919   int i;
01920   DBUS_CONST_STRING_PREAMBLE (str);
01921   _dbus_assert (start <= real->len);
01922   _dbus_assert (start >= 0);
01923   
01924   i = start;
01925   while (i < real->len)
01926     {
01927       if (!DBUS_IS_ASCII_BLANK (real->str[i]))
01928         break;
01929       
01930       ++i;
01931     }
01932 
01933   _dbus_assert (i == real->len || !DBUS_IS_ASCII_WHITE (real->str[i]));
01934   
01935   if (end)
01936     *end = i;
01937 }
01938 
01939 
01948 void
01949 _dbus_string_skip_white (const DBusString *str,
01950                          int               start,
01951                          int              *end)
01952 {
01953   int i;
01954   DBUS_CONST_STRING_PREAMBLE (str);
01955   _dbus_assert (start <= real->len);
01956   _dbus_assert (start >= 0);
01957   
01958   i = start;
01959   while (i < real->len)
01960     {
01961       if (!DBUS_IS_ASCII_WHITE (real->str[i]))
01962         break;
01963       
01964       ++i;
01965     }
01966 
01967   _dbus_assert (i == real->len || !(DBUS_IS_ASCII_WHITE (real->str[i])));
01968   
01969   if (end)
01970     *end = i;
01971 }
01972 
01981 void
01982 _dbus_string_skip_white_reverse (const DBusString *str,
01983                                  int               end,
01984                                  int              *start)
01985 {
01986   int i;
01987   DBUS_CONST_STRING_PREAMBLE (str);
01988   _dbus_assert (end <= real->len);
01989   _dbus_assert (end >= 0);
01990   
01991   i = end;
01992   while (i > 0)
01993     {
01994       if (!DBUS_IS_ASCII_WHITE (real->str[i-1]))
01995         break;
01996       --i;
01997     }
01998 
01999   _dbus_assert (i >= 0 && (i == 0 || !(DBUS_IS_ASCII_WHITE (real->str[i-1]))));
02000   
02001   if (start)
02002     *start = i;
02003 }
02004 
02020 dbus_bool_t
02021 _dbus_string_pop_line (DBusString *source,
02022                        DBusString *dest)
02023 {
02024   int eol;
02025   dbus_bool_t have_newline;
02026   
02027   _dbus_string_set_length (dest, 0);
02028   
02029   eol = 0;
02030   if (_dbus_string_find (source, 0, "\n", &eol))
02031     {
02032       have_newline = TRUE;
02033       eol += 1; /* include newline */
02034     }
02035   else
02036     {
02037       eol = _dbus_string_get_length (source);
02038       have_newline = FALSE;
02039     }
02040 
02041   if (eol == 0)
02042     return FALSE; /* eof */
02043   
02044   if (!_dbus_string_move_len (source, 0, eol,
02045                               dest, 0))
02046     {
02047       return FALSE;
02048     }
02049 
02050   /* dump the newline and the \r if we have one */
02051   if (have_newline)
02052     {
02053       dbus_bool_t have_cr;
02054       
02055       _dbus_assert (_dbus_string_get_length (dest) > 0);
02056 
02057       if (_dbus_string_get_length (dest) > 1 &&
02058           _dbus_string_get_byte (dest,
02059                                  _dbus_string_get_length (dest) - 2) == '\r')
02060         have_cr = TRUE;
02061       else
02062         have_cr = FALSE;
02063         
02064       _dbus_string_set_length (dest,
02065                                _dbus_string_get_length (dest) -
02066                                (have_cr ? 2 : 1));
02067     }
02068   
02069   return TRUE;
02070 }
02071 
02072 #ifdef DBUS_BUILD_TESTS
02073 
02079 void
02080 _dbus_string_delete_first_word (DBusString *str)
02081 {
02082   int i;
02083   
02084   if (_dbus_string_find_blank (str, 0, &i))
02085     _dbus_string_skip_blank (str, i, &i);
02086 
02087   _dbus_string_delete (str, 0, i);
02088 }
02089 #endif
02090 
02091 #ifdef DBUS_BUILD_TESTS
02092 
02097 void
02098 _dbus_string_delete_leading_blanks (DBusString *str)
02099 {
02100   int i;
02101   
02102   _dbus_string_skip_blank (str, 0, &i);
02103 
02104   if (i > 0)
02105     _dbus_string_delete (str, 0, i);
02106 }
02107 #endif
02108 
02114 void
02115 _dbus_string_chop_white(DBusString *str)
02116 {
02117   int i;
02118   
02119   _dbus_string_skip_white (str, 0, &i);
02120 
02121   if (i > 0)
02122     _dbus_string_delete (str, 0, i);
02123   
02124   _dbus_string_skip_white_reverse (str, _dbus_string_get_length (str), &i);
02125 
02126   _dbus_string_set_length (str, i);
02127 }
02128 
02138 dbus_bool_t
02139 _dbus_string_equal (const DBusString *a,
02140                     const DBusString *b)
02141 {
02142   const unsigned char *ap;
02143   const unsigned char *bp;
02144   const unsigned char *a_end;
02145   const DBusRealString *real_a = (const DBusRealString*) a;
02146   const DBusRealString *real_b = (const DBusRealString*) b;
02147   DBUS_GENERIC_STRING_PREAMBLE (real_a);
02148   DBUS_GENERIC_STRING_PREAMBLE (real_b);
02149 
02150   if (real_a->len != real_b->len)
02151     return FALSE;
02152 
02153   ap = real_a->str;
02154   bp = real_b->str;
02155   a_end = real_a->str + real_a->len;
02156   while (ap != a_end)
02157     {
02158       if (*ap != *bp)
02159         return FALSE;
02160       
02161       ++ap;
02162       ++bp;
02163     }
02164 
02165   return TRUE;
02166 }
02167 
02168 #ifdef DBUS_BUILD_TESTS
02169 
02182 dbus_bool_t
02183 _dbus_string_equal_len (const DBusString *a,
02184                         const DBusString *b,
02185                         int               len)
02186 {
02187   const unsigned char *ap;
02188   const unsigned char *bp;
02189   const unsigned char *a_end;
02190   const DBusRealString *real_a = (const DBusRealString*) a;
02191   const DBusRealString *real_b = (const DBusRealString*) b;
02192   DBUS_GENERIC_STRING_PREAMBLE (real_a);
02193   DBUS_GENERIC_STRING_PREAMBLE (real_b);
02194 
02195   if (real_a->len != real_b->len &&
02196       (real_a->len < len || real_b->len < len))
02197     return FALSE;
02198 
02199   ap = real_a->str;
02200   bp = real_b->str;
02201   a_end = real_a->str + MIN (real_a->len, len);
02202   while (ap != a_end)
02203     {
02204       if (*ap != *bp)
02205         return FALSE;
02206       
02207       ++ap;
02208       ++bp;
02209     }
02210 
02211   return TRUE;
02212 }
02213 #endif /* DBUS_BUILD_TESTS */
02214 
02231 dbus_bool_t
02232 _dbus_string_equal_substring (const DBusString  *a,
02233                               int                a_start,
02234                               int                a_len,
02235                               const DBusString  *b,
02236                               int                b_start)
02237 {
02238   const unsigned char *ap;
02239   const unsigned char *bp;
02240   const unsigned char *a_end;
02241   const DBusRealString *real_a = (const DBusRealString*) a;
02242   const DBusRealString *real_b = (const DBusRealString*) b;
02243   DBUS_GENERIC_STRING_PREAMBLE (real_a);
02244   DBUS_GENERIC_STRING_PREAMBLE (real_b);
02245   _dbus_assert (a_start >= 0);
02246   _dbus_assert (a_len >= 0);
02247   _dbus_assert (a_start <= real_a->len);
02248   _dbus_assert (a_len <= real_a->len - a_start);
02249   _dbus_assert (b_start >= 0);
02250   _dbus_assert (b_start <= real_b->len);
02251   
02252   if (a_len > real_b->len - b_start)
02253     return FALSE;
02254 
02255   ap = real_a->str + a_start;
02256   bp = real_b->str + b_start;
02257   a_end = ap + a_len;
02258   while (ap != a_end)
02259     {
02260       if (*ap != *bp)
02261         return FALSE;
02262       
02263       ++ap;
02264       ++bp;
02265     }
02266 
02267   _dbus_assert (bp <= (real_b->str + real_b->len));
02268   
02269   return TRUE;
02270 }
02271 
02279 dbus_bool_t
02280 _dbus_string_equal_c_str (const DBusString *a,
02281                           const char       *c_str)
02282 {
02283   const unsigned char *ap;
02284   const unsigned char *bp;
02285   const unsigned char *a_end;
02286   const DBusRealString *real_a = (const DBusRealString*) a;
02287   DBUS_GENERIC_STRING_PREAMBLE (real_a);
02288   _dbus_assert (c_str != NULL);
02289   
02290   ap = real_a->str;
02291   bp = (const unsigned char*) c_str;
02292   a_end = real_a->str + real_a->len;
02293   while (ap != a_end && *bp)
02294     {
02295       if (*ap != *bp)
02296         return FALSE;
02297       
02298       ++ap;
02299       ++bp;
02300     }
02301 
02302   if (ap != a_end || *bp)
02303     return FALSE;
02304   
02305   return TRUE;
02306 }
02307 
02308 #ifdef DBUS_BUILD_TESTS
02309 
02316 dbus_bool_t
02317 _dbus_string_starts_with_c_str (const DBusString *a,
02318                                 const char       *c_str)
02319 {
02320   const unsigned char *ap;
02321   const unsigned char *bp;
02322   const unsigned char *a_end;
02323   const DBusRealString *real_a = (const DBusRealString*) a;
02324   DBUS_GENERIC_STRING_PREAMBLE (real_a);
02325   _dbus_assert (c_str != NULL);
02326   
02327   ap = real_a->str;
02328   bp = (const unsigned char*) c_str;
02329   a_end = real_a->str + real_a->len;
02330   while (ap != a_end && *bp)
02331     {
02332       if (*ap != *bp)
02333         return FALSE;
02334       
02335       ++ap;
02336       ++bp;
02337     }
02338 
02339   if (*bp == '\0')
02340     return TRUE;
02341   else
02342     return FALSE;
02343 }
02344 #endif /* DBUS_BUILD_TESTS */
02345 
02354 dbus_bool_t
02355 _dbus_string_append_byte_as_hex (DBusString *str,
02356                                  int         byte)
02357 {
02358   const char hexdigits[16] = {
02359     '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
02360     'a', 'b', 'c', 'd', 'e', 'f'
02361   };
02362 
02363   if (!_dbus_string_append_byte (str,
02364                                  hexdigits[(byte >> 4)]))
02365     return FALSE;
02366   
02367   if (!_dbus_string_append_byte (str,
02368                                  hexdigits[(byte & 0x0f)]))
02369     {
02370       _dbus_string_set_length (str,
02371                                _dbus_string_get_length (str) - 1);
02372       return FALSE;
02373     }
02374 
02375   return TRUE;
02376 }
02377 
02388 dbus_bool_t
02389 _dbus_string_hex_encode (const DBusString *source,
02390                          int               start,
02391                          DBusString       *dest,
02392                          int               insert_at)
02393 {
02394   DBusString result;
02395   const unsigned char *p;
02396   const unsigned char *end;
02397   dbus_bool_t retval;
02398   
02399   _dbus_assert (start <= _dbus_string_get_length (source));
02400 
02401   if (!_dbus_string_init (&result))
02402     return FALSE;
02403 
02404   retval = FALSE;
02405   
02406   p = (const unsigned char*) _dbus_string_get_const_data (source);
02407   end = p + _dbus_string_get_length (source);
02408   p += start;
02409   
02410   while (p != end)
02411     {
02412       if (!_dbus_string_append_byte_as_hex (&result, *p))
02413         goto out;
02414       
02415       ++p;
02416     }
02417 
02418   if (!_dbus_string_move (&result, 0, dest, insert_at))
02419     goto out;
02420 
02421   retval = TRUE;
02422 
02423  out:
02424   _dbus_string_free (&result);
02425   return retval;
02426 }
02427 
02438 dbus_bool_t
02439 _dbus_string_hex_decode (const DBusString *source,
02440                          int               start,
02441                          int              *end_return,
02442                          DBusString       *dest,
02443                          int               insert_at)
02444 {
02445   DBusString result;
02446   const unsigned char *p;
02447   const unsigned char *end;
02448   dbus_bool_t retval;
02449   dbus_bool_t high_bits;
02450   
02451   _dbus_assert (start <= _dbus_string_get_length (source));
02452 
02453   if (!_dbus_string_init (&result))
02454     return FALSE;
02455 
02456   retval = FALSE;
02457 
02458   high_bits = TRUE;
02459   p = (const unsigned char*) _dbus_string_get_const_data (source);
02460   end = p + _dbus_string_get_length (source);
02461   p += start;
02462   
02463   while (p != end)
02464     {
02465       unsigned int val;
02466 
02467       switch (*p)
02468         {
02469         case '0':
02470           val = 0;
02471           break;
02472         case '1':
02473           val = 1;
02474           break;
02475         case '2':
02476           val = 2;
02477           break;
02478         case '3':
02479           val = 3;
02480           break;
02481         case '4':
02482           val = 4;
02483           break;
02484         case '5':
02485           val = 5;
02486           break;
02487         case '6':
02488           val = 6;
02489           break;
02490         case '7':
02491           val = 7;
02492           break;
02493         case '8':
02494           val = 8;
02495           break;
02496         case '9':
02497           val = 9;
02498           break;
02499         case 'a':
02500         case 'A':
02501           val = 10;
02502           break;
02503         case 'b':
02504         case 'B':
02505           val = 11;
02506           break;
02507         case 'c':
02508         case 'C':
02509           val = 12;
02510           break;
02511         case 'd':
02512         case 'D':
02513           val = 13;
02514           break;
02515         case 'e':
02516         case 'E':
02517           val = 14;
02518           break;
02519         case 'f':
02520         case 'F':
02521           val = 15;
02522           break;
02523         default:
02524           goto done;
02525         }
02526 
02527       if (high_bits)
02528         {
02529           if (!_dbus_string_append_byte (&result,
02530                                          val << 4))
02531             goto out;
02532         }
02533       else
02534         {
02535           int len;
02536           unsigned char b;
02537 
02538           len = _dbus_string_get_length (&result);
02539           
02540           b = _dbus_string_get_byte (&result, len - 1);
02541 
02542           b |= val;
02543 
02544           _dbus_string_set_byte (&result, len - 1, b);
02545         }
02546 
02547       high_bits = !high_bits;
02548 
02549       ++p;
02550     }
02551 
02552  done:
02553   if (!_dbus_string_move (&result, 0, dest, insert_at))
02554     goto out;
02555 
02556   if (end_return)
02557     *end_return = p - (const unsigned char*) _dbus_string_get_const_data (source);
02558 
02559   retval = TRUE;
02560   
02561  out:
02562   _dbus_string_free (&result);  
02563   return retval;
02564 }
02565 
02579 dbus_bool_t
02580 _dbus_string_validate_ascii (const DBusString *str,
02581                              int               start,
02582                              int               len)
02583 {
02584   const unsigned char *s;
02585   const unsigned char *end;
02586   DBUS_CONST_STRING_PREAMBLE (str);
02587   _dbus_assert (start >= 0);
02588   _dbus_assert (start <= real->len);
02589   _dbus_assert (len >= 0);
02590   
02591   if (len > real->len - start)
02592     return FALSE;
02593   
02594   s = real->str + start;
02595   end = s + len;
02596   while (s != end)
02597     {
02598       if (_DBUS_UNLIKELY (!_DBUS_ISASCII (*s)))
02599         return FALSE;
02600         
02601       ++s;
02602     }
02603   
02604   return TRUE;
02605 }
02606 
02622 dbus_bool_t
02623 _dbus_string_validate_utf8  (const DBusString *str,
02624                              int               start,
02625                              int               len)
02626 {
02627   const unsigned char *p;
02628   const unsigned char *end;
02629   DBUS_CONST_STRING_PREAMBLE (str);
02630   _dbus_assert (start >= 0);
02631   _dbus_assert (start <= real->len);
02632   _dbus_assert (len >= 0);
02633 
02634   /* we are doing _DBUS_UNLIKELY() here which might be
02635    * dubious in a generic library like GLib, but in D-Bus
02636    * we know we're validating messages and that it would
02637    * only be evil/broken apps that would have invalid
02638    * UTF-8. Also, this function seems to be a performance
02639    * bottleneck in profiles.
02640    */
02641   
02642   if (_DBUS_UNLIKELY (len > real->len - start))
02643     return FALSE;
02644   
02645   p = real->str + start;
02646   end = p + len;
02647   
02648   while (p < end)
02649     {
02650       int i, mask, char_len;
02651       dbus_unichar_t result;
02652 
02653       /* nul bytes considered invalid */
02654       if (*p == '\0')
02655         break;
02656       
02657       /* Special-case ASCII; this makes us go a lot faster in
02658        * D-Bus profiles where we are typically validating
02659        * function names and such. We have to know that
02660        * all following checks will pass for ASCII though,
02661        * comments follow ...
02662        */      
02663       if (*p < 128)
02664         {
02665           ++p;
02666           continue;
02667         }
02668       
02669       UTF8_COMPUTE (*p, mask, char_len);
02670 
02671       if (_DBUS_UNLIKELY (char_len == 0))  /* ASCII: char_len == 1 */
02672         break;
02673 
02674       /* check that the expected number of bytes exists in the remaining length */
02675       if (_DBUS_UNLIKELY ((end - p) < char_len)) /* ASCII: p < end and char_len == 1 */
02676         break;
02677         
02678       UTF8_GET (result, p, i, mask, char_len);
02679 
02680       /* Check for overlong UTF-8 */
02681       if (_DBUS_UNLIKELY (UTF8_LENGTH (result) != char_len)) /* ASCII: UTF8_LENGTH == 1 */
02682         break;
02683 #if 0
02684       /* The UNICODE_VALID check below will catch this */
02685       if (_DBUS_UNLIKELY (result == (dbus_unichar_t)-1)) /* ASCII: result = ascii value */
02686         break;
02687 #endif
02688 
02689       if (_DBUS_UNLIKELY (!UNICODE_VALID (result))) /* ASCII: always valid */
02690         break;
02691 
02692       /* UNICODE_VALID should have caught it */
02693       _dbus_assert (result != (dbus_unichar_t)-1);
02694       
02695       p += char_len;
02696     }
02697 
02698   /* See that we covered the entire length if a length was
02699    * passed in
02700    */
02701   if (_DBUS_UNLIKELY (p != end))
02702     return FALSE;
02703   else
02704     return TRUE;
02705 }
02706 
02720 dbus_bool_t
02721 _dbus_string_validate_nul (const DBusString *str,
02722                            int               start,
02723                            int               len)
02724 {
02725   const unsigned char *s;
02726   const unsigned char *end;
02727   DBUS_CONST_STRING_PREAMBLE (str);
02728   _dbus_assert (start >= 0);
02729   _dbus_assert (len >= 0);
02730   _dbus_assert (start <= real->len);
02731   
02732   if (len > real->len - start)
02733     return FALSE;
02734   
02735   s = real->str + start;
02736   end = s + len;
02737   while (s != end)
02738     {
02739       if (_DBUS_UNLIKELY (*s != '\0'))
02740         return FALSE;
02741       ++s;
02742     }
02743   
02744   return TRUE;
02745 }
02746 
02752 void
02753 _dbus_string_zero (DBusString *str)
02754 {
02755   DBUS_STRING_PREAMBLE (str);
02756 
02757   memset (real->str - real->align_offset, '\0', real->allocated);
02758 }
02761 /* tests are in dbus-string-util.c */

Generated on Fri Sep 21 18:12:13 2007 for D-Bus by  doxygen 1.5.1