D-Bus  1.10.12
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_STATIC_ASSERT (sizeof (DBusString) == sizeof (DBusRealString));
00138 
00139   _dbus_assert (str != NULL);
00140 
00141   real = (DBusRealString*) str;
00142 
00143   /* It's very important not to touch anything
00144    * other than real->str if we're going to fail,
00145    * since we also use this function to reset
00146    * an existing string, e.g. in _dbus_string_steal_data()
00147    */
00148   
00149   real->str = dbus_malloc (_DBUS_STRING_ALLOCATION_PADDING + allocate_size);
00150   if (real->str == NULL)
00151     return FALSE;  
00152   
00153   real->allocated = _DBUS_STRING_ALLOCATION_PADDING + allocate_size;
00154   real->len = 0;
00155   real->str[real->len] = '\0';
00156   
00157   real->constant = FALSE;
00158   real->locked = FALSE;
00159   real->invalid = FALSE;
00160   real->align_offset = 0;
00161   
00162   fixup_alignment (real);
00163   
00164   return TRUE;
00165 }
00166 
00174 dbus_bool_t
00175 _dbus_string_init (DBusString *str)
00176 {
00177   return _dbus_string_init_preallocated (str, 0);
00178 }
00179 
00189 void
00190 _dbus_string_init_const (DBusString *str,
00191                          const char *value)
00192 {
00193   _dbus_assert (value != NULL);
00194   
00195   _dbus_string_init_const_len (str, value,
00196                                strlen (value));
00197 }
00198 
00209 void
00210 _dbus_string_init_const_len (DBusString *str,
00211                              const char *value,
00212                              int         len)
00213 {
00214   DBusRealString *real;
00215   
00216   _dbus_assert (str != NULL);
00217   _dbus_assert (len == 0 || value != NULL);
00218   _dbus_assert (len <= _DBUS_STRING_MAX_LENGTH);
00219   _dbus_assert (len >= 0);
00220   
00221   real = (DBusRealString*) str;
00222   
00223   real->str = (unsigned char*) value;
00224   real->len = len;
00225   real->allocated = real->len + _DBUS_STRING_ALLOCATION_PADDING; /* a lie, just to avoid special-case assertions... */
00226   real->constant = TRUE;
00227   real->locked = TRUE;
00228   real->invalid = FALSE;
00229   real->align_offset = 0;
00230 
00231   /* We don't require const strings to be 8-byte aligned as the
00232    * memory is coming from elsewhere.
00233    */
00234 }
00235 
00244 dbus_bool_t
00245 _dbus_string_init_from_string(DBusString       *str,
00246                               const DBusString *from)
00247 {
00248  if (!_dbus_string_init (str))
00249      return FALSE;
00250  return _dbus_string_append (str, _dbus_string_get_const_data (from));
00251 }
00252 
00258 void
00259 _dbus_string_free (DBusString *str)
00260 {
00261   DBusRealString *real = (DBusRealString*) str;
00262   DBUS_GENERIC_STRING_PREAMBLE (real);
00263   
00264   if (real->constant)
00265     return;
00266 
00267   /* so it's safe if @p str returned by a failed
00268    * _dbus_string_init call
00269    * Bug: https://bugs.freedesktop.org/show_bug.cgi?id=65959
00270    */
00271   if (real->str == NULL)
00272     return;
00273 
00274   dbus_free (real->str - real->align_offset);
00275 
00276   real->invalid = TRUE;
00277 }
00278 
00279 static dbus_bool_t
00280 compact (DBusRealString *real,
00281          int             max_waste)
00282 {
00283   unsigned char *new_str;
00284   int new_allocated;
00285   int waste;
00286 
00287   waste = real->allocated - (real->len + _DBUS_STRING_ALLOCATION_PADDING);
00288 
00289   if (waste <= max_waste)
00290     return TRUE;
00291 
00292   new_allocated = real->len + _DBUS_STRING_ALLOCATION_PADDING;
00293 
00294   new_str = dbus_realloc (real->str - real->align_offset, new_allocated);
00295   if (_DBUS_UNLIKELY (new_str == NULL))
00296     return FALSE;
00297 
00298   real->str = new_str + real->align_offset;
00299   real->allocated = new_allocated;
00300   fixup_alignment (real);
00301 
00302   return TRUE;
00303 }
00304 
00305 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
00306 /* Not using this feature at the moment,
00307  * so marked DBUS_ENABLE_EMBEDDED_TESTS-only
00308  */
00318 void
00319 _dbus_string_lock (DBusString *str)
00320 {  
00321   DBUS_LOCKED_STRING_PREAMBLE (str); /* can lock multiple times */
00322 
00323   real->locked = TRUE;
00324 
00325   /* Try to realloc to avoid excess memory usage, since
00326    * we know we won't change the string further
00327    */
00328 #define MAX_WASTE 48
00329   compact (real, MAX_WASTE);
00330 }
00331 #endif /* DBUS_ENABLE_EMBEDDED_TESTS */
00332 
00333 static dbus_bool_t
00334 reallocate_for_length (DBusRealString *real,
00335                        int             new_length)
00336 {
00337   int new_allocated;
00338   unsigned char *new_str;
00339 
00340   /* at least double our old allocation to avoid O(n), avoiding
00341    * overflow
00342    */
00343   if (real->allocated > (_DBUS_STRING_MAX_LENGTH + _DBUS_STRING_ALLOCATION_PADDING) / 2)
00344     new_allocated = _DBUS_STRING_MAX_LENGTH + _DBUS_STRING_ALLOCATION_PADDING;
00345   else
00346     new_allocated = real->allocated * 2;
00347 
00348   /* if you change the code just above here, run the tests without
00349    * the following assert-only hack before you commit
00350    */
00351   /* This is keyed off asserts in addition to tests so when you
00352    * disable asserts to profile, you don't get this destroyer
00353    * of profiles.
00354    */
00355 #if defined (DBUS_ENABLE_EMBEDDED_TESTS) && !defined (DBUS_DISABLE_ASSERT)
00356   new_allocated = 0; /* ensure a realloc every time so that we go
00357                       * through all malloc failure codepaths
00358                       */
00359 #endif
00360 
00361   /* But be sure we always alloc at least space for the new length */
00362   new_allocated = MAX (new_allocated,
00363                        new_length + _DBUS_STRING_ALLOCATION_PADDING);
00364 
00365   _dbus_assert (new_allocated >= real->allocated); /* code relies on this */
00366   new_str = dbus_realloc (real->str - real->align_offset, new_allocated);
00367   if (_DBUS_UNLIKELY (new_str == NULL))
00368     return FALSE;
00369 
00370   real->str = new_str + real->align_offset;
00371   real->allocated = new_allocated;
00372   fixup_alignment (real);
00373 
00374   return TRUE;
00375 }
00376 
00388 dbus_bool_t
00389 _dbus_string_compact (DBusString *str,
00390                       int         max_waste)
00391 {
00392   DBUS_STRING_PREAMBLE (str);
00393 
00394   return compact (real, max_waste);
00395 }
00396 
00397 static dbus_bool_t
00398 set_length (DBusRealString *real,
00399             int             new_length)
00400 {
00401   /* Note, we are setting the length not including nul termination */
00402 
00403   /* exceeding max length is the same as failure to allocate memory */
00404   if (_DBUS_UNLIKELY (new_length > _DBUS_STRING_MAX_LENGTH))
00405     return FALSE;
00406   else if (new_length > (real->allocated - _DBUS_STRING_ALLOCATION_PADDING) &&
00407            _DBUS_UNLIKELY (!reallocate_for_length (real, new_length)))
00408     return FALSE;
00409   else
00410     {
00411       real->len = new_length;
00412       real->str[new_length] = '\0';
00413       return TRUE;
00414     }
00415 }
00416 
00417 static dbus_bool_t
00418 open_gap (int             len,
00419           DBusRealString *dest,
00420           int             insert_at)
00421 {
00422   if (len == 0)
00423     return TRUE;
00424 
00425   if (len > _DBUS_STRING_MAX_LENGTH - dest->len)
00426     return FALSE; /* detected overflow of dest->len + len below */
00427   
00428   if (!set_length (dest, dest->len + len))
00429     return FALSE;
00430 
00431   memmove (dest->str + insert_at + len, 
00432            dest->str + insert_at,
00433            dest->len - len - insert_at);
00434 
00435   return TRUE;
00436 }
00437 
00438 #ifndef _dbus_string_get_data
00439 
00450 char*
00451 _dbus_string_get_data (DBusString *str)
00452 {
00453   DBUS_STRING_PREAMBLE (str);
00454   
00455   return (char*) real->str;
00456 }
00457 #endif /* _dbus_string_get_data */
00458 
00459 /* only do the function if we don't have the macro */
00460 #ifndef _dbus_string_get_const_data
00461 
00467 const char*
00468 _dbus_string_get_const_data (const DBusString  *str)
00469 {
00470   DBUS_CONST_STRING_PREAMBLE (str);
00471   
00472   return (const char*) real->str;
00473 }
00474 #endif /* _dbus_string_get_const_data */
00475 
00489 char*
00490 _dbus_string_get_data_len (DBusString *str,
00491                            int         start,
00492                            int         len)
00493 {
00494   DBUS_STRING_PREAMBLE (str);
00495   _dbus_assert (start >= 0);
00496   _dbus_assert (len >= 0);
00497   _dbus_assert (start <= real->len);
00498   _dbus_assert (len <= real->len - start);
00499   
00500   return (char*) real->str + start;
00501 }
00502 
00503 /* only do the function if we don't have the macro */
00504 #ifndef _dbus_string_get_const_data_len
00505 
00513 const char*
00514 _dbus_string_get_const_data_len (const DBusString  *str,
00515                                  int                start,
00516                                  int                len)
00517 {
00518   DBUS_CONST_STRING_PREAMBLE (str);
00519   _dbus_assert (start >= 0);
00520   _dbus_assert (len >= 0);
00521   _dbus_assert (start <= real->len);
00522   _dbus_assert (len <= real->len - start);
00523   
00524   return (const char*) real->str + start;
00525 }
00526 #endif /* _dbus_string_get_const_data_len */
00527 
00528 /* only do the function if we don't have the macro */
00529 #ifndef _dbus_string_set_byte
00530 
00537 void
00538 _dbus_string_set_byte (DBusString    *str,
00539                        int            i,
00540                        unsigned char  byte)
00541 {
00542   DBUS_STRING_PREAMBLE (str);
00543   _dbus_assert (i < real->len);
00544   _dbus_assert (i >= 0);
00545   
00546   real->str[i] = byte;
00547 }
00548 #endif /* _dbus_string_set_byte */
00549 
00550 /* only have the function if we didn't create a macro */
00551 #ifndef _dbus_string_get_byte
00552 
00561 unsigned char
00562 _dbus_string_get_byte (const DBusString  *str,
00563                        int                start)
00564 {
00565   DBUS_CONST_STRING_PREAMBLE (str);
00566   _dbus_assert (start <= real->len);
00567   _dbus_assert (start >= 0);
00568   
00569   return real->str[start];
00570 }
00571 #endif /* _dbus_string_get_byte */
00572 
00583 dbus_bool_t
00584 _dbus_string_insert_bytes (DBusString   *str,
00585                            int           i,
00586                            int           n_bytes,
00587                            unsigned char byte)
00588 {
00589   DBUS_STRING_PREAMBLE (str);
00590   _dbus_assert (i <= real->len);
00591   _dbus_assert (i >= 0);
00592   _dbus_assert (n_bytes >= 0);
00593 
00594   if (n_bytes == 0)
00595     return TRUE;
00596   
00597   if (!open_gap (n_bytes, real, i))
00598     return FALSE;
00599   
00600   memset (real->str + i, byte, n_bytes);
00601 
00602   return TRUE;
00603 }
00604 
00613 dbus_bool_t
00614 _dbus_string_insert_byte (DBusString   *str,
00615                            int           i,
00616                            unsigned char byte)
00617 {
00618   DBUS_STRING_PREAMBLE (str);
00619   _dbus_assert (i <= real->len);
00620   _dbus_assert (i >= 0);
00621   
00622   if (!open_gap (1, real, i))
00623     return FALSE;
00624 
00625   real->str[i] = byte;
00626 
00627   return TRUE;
00628 }
00629 
00640 dbus_bool_t
00641 _dbus_string_steal_data (DBusString        *str,
00642                          char             **data_return)
00643 {
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   /* reset the string */
00652   if (!_dbus_string_init (str))
00653     {
00654       /* hrm, put it back then */
00655       real->str = (unsigned char*) *data_return;
00656       *data_return = NULL;
00657       fixup_alignment (real);
00658       return FALSE;
00659     }
00660 
00661   return TRUE;
00662 }
00663 
00671 dbus_bool_t
00672 _dbus_string_copy_data (const DBusString  *str,
00673                         char             **data_return)
00674 {
00675   DBUS_CONST_STRING_PREAMBLE (str);
00676   _dbus_assert (data_return != NULL);
00677   
00678   *data_return = dbus_malloc (real->len + 1);
00679   if (*data_return == NULL)
00680     return FALSE;
00681 
00682   memcpy (*data_return, real->str, real->len + 1);
00683 
00684   return TRUE;
00685 }
00686 
00696 void
00697 _dbus_string_copy_to_buffer (const DBusString  *str,
00698                              char              *buffer,
00699                              int                avail_len)
00700 {
00701   DBUS_CONST_STRING_PREAMBLE (str);
00702 
00703   _dbus_assert (avail_len >= 0);
00704   _dbus_assert (avail_len >= real->len);
00705   
00706   memcpy (buffer, real->str, real->len);
00707 }
00708 
00718 void
00719 _dbus_string_copy_to_buffer_with_nul (const DBusString  *str,
00720                                       char              *buffer,
00721                                       int                avail_len)
00722 {
00723   DBUS_CONST_STRING_PREAMBLE (str);
00724 
00725   _dbus_assert (avail_len >= 0);
00726   _dbus_assert (avail_len > real->len);
00727   
00728   memcpy (buffer, real->str, real->len+1);
00729 }
00730 
00731 /* Only have the function if we don't have the macro */
00732 #ifndef _dbus_string_get_length
00733 
00738 int
00739 _dbus_string_get_length (const DBusString  *str)
00740 {
00741   DBUS_CONST_STRING_PREAMBLE (str);
00742   
00743   return real->len;
00744 }
00745 #endif /* !_dbus_string_get_length */
00746 
00759 dbus_bool_t
00760 _dbus_string_lengthen (DBusString *str,
00761                        int         additional_length)
00762 {
00763   DBUS_STRING_PREAMBLE (str);  
00764   _dbus_assert (additional_length >= 0);
00765 
00766   if (_DBUS_UNLIKELY (additional_length > _DBUS_STRING_MAX_LENGTH - real->len))
00767     return FALSE; /* would overflow */
00768   
00769   return set_length (real,
00770                      real->len + additional_length);
00771 }
00772 
00779 void
00780 _dbus_string_shorten (DBusString *str,
00781                       int         length_to_remove)
00782 {
00783   DBUS_STRING_PREAMBLE (str);
00784   _dbus_assert (length_to_remove >= 0);
00785   _dbus_assert (length_to_remove <= real->len);
00786 
00787   set_length (real,
00788               real->len - length_to_remove);
00789 }
00790 
00801 dbus_bool_t
00802 _dbus_string_set_length (DBusString *str,
00803                          int         length)
00804 {
00805   DBUS_STRING_PREAMBLE (str);
00806   _dbus_assert (length >= 0);
00807 
00808   return set_length (real, length);
00809 }
00810 
00811 static dbus_bool_t
00812 align_insert_point_then_open_gap (DBusString *str,
00813                                   int        *insert_at_p,
00814                                   int         alignment,
00815                                   int         gap_size)
00816 {
00817   unsigned long new_len; /* ulong to avoid _DBUS_ALIGN_VALUE overflow */
00818   unsigned long gap_pos;
00819   int insert_at;
00820   int delta;
00821   DBUS_STRING_PREAMBLE (str);
00822   _dbus_assert (alignment >= 1);
00823   _dbus_assert (alignment <= 8); /* it has to be a bug if > 8 */
00824 
00825   insert_at = *insert_at_p;
00826 
00827   _dbus_assert (insert_at <= real->len);
00828   
00829   gap_pos = _DBUS_ALIGN_VALUE (insert_at, alignment);
00830   new_len = real->len + (gap_pos - insert_at) + gap_size;
00831   
00832   if (_DBUS_UNLIKELY (new_len > (unsigned long) _DBUS_STRING_MAX_LENGTH))
00833     return FALSE;
00834   
00835   delta = new_len - real->len;
00836   _dbus_assert (delta >= 0);
00837 
00838   if (delta == 0) /* only happens if gap_size == 0 and insert_at is aligned already */
00839     {
00840       _dbus_assert (((unsigned long) *insert_at_p) == gap_pos);
00841       return TRUE;
00842     }
00843 
00844   if (_DBUS_UNLIKELY (!open_gap (new_len - real->len,
00845                                  real, insert_at)))
00846     return FALSE;
00847 
00848   /* nul the padding if we had to add any padding */
00849   if (gap_size < delta)
00850     {
00851       memset (&real->str[insert_at], '\0',
00852               gap_pos - insert_at);
00853     }
00854 
00855   *insert_at_p = gap_pos;
00856   
00857   return TRUE;
00858 }
00859 
00860 static dbus_bool_t
00861 align_length_then_lengthen (DBusString *str,
00862                             int         alignment,
00863                             int         then_lengthen_by)
00864 {
00865   int insert_at;
00866 
00867   insert_at = _dbus_string_get_length (str);
00868   
00869   return align_insert_point_then_open_gap (str,
00870                                            &insert_at,
00871                                            alignment, then_lengthen_by);
00872 }
00873 
00882 dbus_bool_t
00883 _dbus_string_align_length (DBusString *str,
00884                            int         alignment)
00885 {
00886   return align_length_then_lengthen (str, alignment, 0);
00887 }
00888 
00898 dbus_bool_t
00899 _dbus_string_alloc_space (DBusString        *str,
00900                           int                extra_bytes)
00901 {
00902   if (!_dbus_string_lengthen (str, extra_bytes))
00903     return FALSE;
00904   _dbus_string_shorten (str, extra_bytes);
00905 
00906   return TRUE;
00907 }
00908 
00909 static dbus_bool_t
00910 append (DBusRealString *real,
00911         const char     *buffer,
00912         int             buffer_len)
00913 {
00914   if (buffer_len == 0)
00915     return TRUE;
00916 
00917   if (!_dbus_string_lengthen ((DBusString*)real, buffer_len))
00918     return FALSE;
00919 
00920   memcpy (real->str + (real->len - buffer_len),
00921           buffer,
00922           buffer_len);
00923 
00924   return TRUE;
00925 }
00926 
00934 dbus_bool_t
00935 _dbus_string_append (DBusString *str,
00936                      const char *buffer)
00937 {
00938   unsigned long buffer_len;
00939   
00940   DBUS_STRING_PREAMBLE (str);
00941   _dbus_assert (buffer != NULL);
00942   
00943   buffer_len = strlen (buffer);
00944   if (buffer_len > (unsigned long) _DBUS_STRING_MAX_LENGTH)
00945     return FALSE;
00946   
00947   return append (real, buffer, buffer_len);
00948 }
00949 
00951 #define ASSIGN_2_OCTETS(p, octets) \
00952   *((dbus_uint16_t*)(p)) = *((dbus_uint16_t*)(octets));
00953 
00955 #define ASSIGN_4_OCTETS(p, octets) \
00956   *((dbus_uint32_t*)(p)) = *((dbus_uint32_t*)(octets));
00957 
00959 #define ASSIGN_8_OCTETS(p, octets) \
00960   *((dbus_uint64_t*)(p)) = *((dbus_uint64_t*)(octets));
00961 
00971 dbus_bool_t
00972 _dbus_string_insert_2_aligned (DBusString         *str,
00973                                int                 insert_at,
00974                                const unsigned char octets[2])
00975 {
00976   DBUS_STRING_PREAMBLE (str);
00977   
00978   if (!align_insert_point_then_open_gap (str, &insert_at, 2, 2))
00979     return FALSE;
00980 
00981   ASSIGN_2_OCTETS (real->str + insert_at, octets);
00982 
00983   return TRUE;
00984 }
00985 
00995 dbus_bool_t
00996 _dbus_string_insert_4_aligned (DBusString         *str,
00997                                int                 insert_at,
00998                                const unsigned char octets[4])
00999 {
01000   DBUS_STRING_PREAMBLE (str);
01001   
01002   if (!align_insert_point_then_open_gap (str, &insert_at, 4, 4))
01003     return FALSE;
01004 
01005   ASSIGN_4_OCTETS (real->str + insert_at, octets);
01006 
01007   return TRUE;
01008 }
01009 
01019 dbus_bool_t
01020 _dbus_string_insert_8_aligned (DBusString         *str,
01021                                int                 insert_at,
01022                                const unsigned char octets[8])
01023 {
01024   DBUS_STRING_PREAMBLE (str);
01025   
01026   if (!align_insert_point_then_open_gap (str, &insert_at, 8, 8))
01027     return FALSE;
01028 
01029   _dbus_assert (_DBUS_ALIGN_VALUE (insert_at, 8) == (unsigned) insert_at);
01030   
01031   ASSIGN_8_OCTETS (real->str + insert_at, octets);
01032 
01033   return TRUE;
01034 }
01035 
01036 
01047 dbus_bool_t
01048 _dbus_string_insert_alignment (DBusString        *str,
01049                                int               *insert_at,
01050                                int                alignment)
01051 {
01052   DBUS_STRING_PREAMBLE (str);
01053   
01054   if (!align_insert_point_then_open_gap (str, insert_at, alignment, 0))
01055     return FALSE;
01056 
01057   _dbus_assert (_DBUS_ALIGN_VALUE (*insert_at, alignment) == (unsigned) *insert_at);
01058 
01059   return TRUE;
01060 }
01061 
01071 dbus_bool_t
01072 _dbus_string_append_printf_valist  (DBusString        *str,
01073                                     const char        *format,
01074                                     va_list            args)
01075 {
01076   dbus_bool_t ret = FALSE;
01077   int len;
01078   va_list args_copy;
01079 
01080   DBUS_STRING_PREAMBLE (str);
01081 
01082   DBUS_VA_COPY (args_copy, args);
01083 
01084   /* Measure the message length without terminating nul */
01085   len = _dbus_printf_string_upper_bound (format, args);
01086 
01087   if (len < 0)
01088     goto out;
01089 
01090   if (!_dbus_string_lengthen (str, len))
01091     {
01092       goto out;
01093     }
01094   
01095   vsprintf ((char*) (real->str + (real->len - len)),
01096             format, args_copy);
01097   ret = TRUE;
01098 
01099 out:
01100   va_end (args_copy);
01101 
01102   return ret;
01103 }
01104 
01113 dbus_bool_t
01114 _dbus_string_append_printf (DBusString        *str,
01115                             const char        *format,
01116                             ...)
01117 {
01118   va_list args;
01119   dbus_bool_t retval;
01120   
01121   va_start (args, format);
01122   retval = _dbus_string_append_printf_valist (str, format, args);
01123   va_end (args);
01124 
01125   return retval;
01126 }
01127 
01136 dbus_bool_t
01137 _dbus_string_append_len (DBusString *str,
01138                          const char *buffer,
01139                          int         len)
01140 {
01141   DBUS_STRING_PREAMBLE (str);
01142   _dbus_assert (buffer != NULL);
01143   _dbus_assert (len >= 0);
01144 
01145   return append (real, buffer, len);
01146 }
01147 
01156 dbus_bool_t
01157 _dbus_string_append_byte (DBusString    *str,
01158                           unsigned char  byte)
01159 {
01160   DBUS_STRING_PREAMBLE (str);
01161 
01162   if (!set_length (real, real->len + 1))
01163     return FALSE;
01164 
01165   real->str[real->len-1] = byte;
01166 
01167   return TRUE;
01168 }
01169 
01170 static void
01171 delete (DBusRealString *real,
01172         int             start,
01173         int             len)
01174 {
01175   if (len == 0)
01176     return;
01177   
01178   memmove (real->str + start, real->str + start + len, real->len - (start + len));
01179   real->len -= len;
01180   real->str[real->len] = '\0';
01181 }
01182 
01192 void
01193 _dbus_string_delete (DBusString       *str,
01194                      int               start,
01195                      int               len)
01196 {
01197   DBUS_STRING_PREAMBLE (str);
01198   _dbus_assert (start >= 0);
01199   _dbus_assert (len >= 0);
01200   _dbus_assert (start <= real->len);
01201   _dbus_assert (len <= real->len - start);
01202   
01203   delete (real, start, len);
01204 }
01205 
01206 static dbus_bool_t
01207 copy (DBusRealString *source,
01208       int             start,
01209       int             len,
01210       DBusRealString *dest,
01211       int             insert_at)
01212 {
01213   if (len == 0)
01214     return TRUE;
01215 
01216   if (!open_gap (len, dest, insert_at))
01217     return FALSE;
01218   
01219   memmove (dest->str + insert_at,
01220            source->str + start,
01221            len);
01222 
01223   return TRUE;
01224 }
01225 
01235 #define DBUS_STRING_COPY_PREAMBLE(source, start, dest, insert_at)       \
01236   DBusRealString *real_source = (DBusRealString*) source;               \
01237   DBusRealString *real_dest = (DBusRealString*) dest;                   \
01238   _dbus_assert ((source) != (dest));                                    \
01239   DBUS_GENERIC_STRING_PREAMBLE (real_source);                           \
01240   DBUS_GENERIC_STRING_PREAMBLE (real_dest);                             \
01241   _dbus_assert (!real_dest->constant);                                  \
01242   _dbus_assert (!real_dest->locked);                                    \
01243   _dbus_assert ((start) >= 0);                                          \
01244   _dbus_assert ((start) <= real_source->len);                           \
01245   _dbus_assert ((insert_at) >= 0);                                      \
01246   _dbus_assert ((insert_at) <= real_dest->len)
01247 
01258 dbus_bool_t
01259 _dbus_string_move (DBusString       *source,
01260                    int               start,
01261                    DBusString       *dest,
01262                    int               insert_at)
01263 {
01264   DBusRealString *real_source = (DBusRealString*) source;
01265   _dbus_assert (start <= real_source->len);
01266   
01267   return _dbus_string_move_len (source, start,
01268                                 real_source->len - start,
01269                                 dest, insert_at);
01270 }
01271 
01282 dbus_bool_t
01283 _dbus_string_copy (const DBusString *source,
01284                    int               start,
01285                    DBusString       *dest,
01286                    int               insert_at)
01287 {
01288   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
01289 
01290   return copy (real_source, start,
01291                real_source->len - start,
01292                real_dest,
01293                insert_at);
01294 }
01295 
01307 dbus_bool_t
01308 _dbus_string_move_len (DBusString       *source,
01309                        int               start,
01310                        int               len,
01311                        DBusString       *dest,
01312                        int               insert_at)
01313 
01314 {
01315   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
01316   _dbus_assert (len >= 0);
01317   _dbus_assert ((start + len) <= real_source->len);
01318 
01319 
01320   if (len == 0)
01321     {
01322       return TRUE;
01323     }
01324   else if (start == 0 &&
01325            len == real_source->len &&
01326            real_dest->len == 0)
01327     {
01328       /* Short-circuit moving an entire existing string to an empty string
01329        * by just swapping the buffers.
01330        */
01331       /* we assume ->constant doesn't matter as you can't have
01332        * a constant string involved in a move.
01333        */
01334 #define ASSIGN_DATA(a, b) do {                  \
01335         (a)->str = (b)->str;                    \
01336         (a)->len = (b)->len;                    \
01337         (a)->allocated = (b)->allocated;        \
01338         (a)->align_offset = (b)->align_offset;  \
01339       } while (0)
01340       
01341       DBusRealString tmp;
01342 
01343       ASSIGN_DATA (&tmp, real_source);
01344       ASSIGN_DATA (real_source, real_dest);
01345       ASSIGN_DATA (real_dest, &tmp);
01346 
01347       return TRUE;
01348     }
01349   else
01350     {
01351       if (!copy (real_source, start, len,
01352                  real_dest,
01353                  insert_at))
01354         return FALSE;
01355       
01356       delete (real_source, start,
01357               len);
01358       
01359       return TRUE;
01360     }
01361 }
01362 
01374 dbus_bool_t
01375 _dbus_string_copy_len (const DBusString *source,
01376                        int               start,
01377                        int               len,
01378                        DBusString       *dest,
01379                        int               insert_at)
01380 {
01381   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
01382   _dbus_assert (len >= 0);
01383   _dbus_assert (start <= real_source->len);
01384   _dbus_assert (len <= real_source->len - start);
01385   
01386   return copy (real_source, start, len,
01387                real_dest,
01388                insert_at);
01389 }
01390 
01403 dbus_bool_t
01404 _dbus_string_replace_len (const DBusString *source,
01405                           int               start,
01406                           int               len,
01407                           DBusString       *dest,
01408                           int               replace_at,
01409                           int               replace_len)
01410 {
01411   DBUS_STRING_COPY_PREAMBLE (source, start, dest, replace_at);
01412   _dbus_assert (len >= 0);
01413   _dbus_assert (start <= real_source->len);
01414   _dbus_assert (len <= real_source->len - start);
01415   _dbus_assert (replace_at >= 0);
01416   _dbus_assert (replace_at <= real_dest->len);
01417   _dbus_assert (replace_len <= real_dest->len - replace_at);
01418 
01419   if (len == replace_len)
01420     {
01421       memmove (real_dest->str + replace_at,
01422                real_source->str + start, len);
01423     }
01424   else if (len < replace_len)
01425     {
01426       memmove (real_dest->str + replace_at,
01427                real_source->str + start, len);
01428       delete (real_dest, replace_at + len,
01429               replace_len - len);
01430     }
01431   else
01432     {
01433       int diff;
01434 
01435       _dbus_assert (len > replace_len);
01436 
01437       diff = len - replace_len;
01438 
01439       /* First of all we check if destination string can be enlarged as
01440        * required, then we overwrite previous bytes
01441        */
01442 
01443       if (!copy (real_source, start + replace_len, diff,
01444                  real_dest, replace_at + replace_len))
01445         return FALSE;
01446 
01447       memmove (real_dest->str + replace_at,
01448                real_source->str + start, replace_len);
01449     }
01450 
01451   return TRUE;
01452 }
01453 
01466 dbus_bool_t
01467 _dbus_string_split_on_byte (DBusString        *source,
01468                             unsigned char      byte,
01469                             DBusString        *tail)
01470 {
01471   int byte_position;
01472   char byte_string[2] = "";
01473   int head_length;
01474   int tail_length;
01475 
01476   byte_string[0] = (char) byte;
01477 
01478   if (!_dbus_string_find (source, 0, byte_string, &byte_position))
01479     return FALSE;
01480 
01481   head_length = byte_position;
01482   tail_length = _dbus_string_get_length (source) - head_length - 1;
01483 
01484   if (!_dbus_string_move_len (source, byte_position + 1, tail_length,
01485                               tail, 0))
01486     return FALSE;
01487 
01488   /* remove the trailing delimiter byte from the head now.
01489    */
01490   if (!_dbus_string_set_length (source, head_length))
01491     return FALSE;
01492 
01493   return TRUE;
01494 }
01495 
01496 /* Unicode macros and utf8_validate() from GLib Owen Taylor, Havoc
01497  * Pennington, and Tom Tromey are the authors and authorized relicense.
01498  */
01499 
01505 #define UTF8_COMPUTE(Char, Mask, Len)                                         \
01506   if (Char < 128)                                                             \
01507     {                                                                         \
01508       Len = 1;                                                                \
01509       Mask = 0x7f;                                                            \
01510     }                                                                         \
01511   else if ((Char & 0xe0) == 0xc0)                                             \
01512     {                                                                         \
01513       Len = 2;                                                                \
01514       Mask = 0x1f;                                                            \
01515     }                                                                         \
01516   else if ((Char & 0xf0) == 0xe0)                                             \
01517     {                                                                         \
01518       Len = 3;                                                                \
01519       Mask = 0x0f;                                                            \
01520     }                                                                         \
01521   else if ((Char & 0xf8) == 0xf0)                                             \
01522     {                                                                         \
01523       Len = 4;                                                                \
01524       Mask = 0x07;                                                            \
01525     }                                                                         \
01526   else if ((Char & 0xfc) == 0xf8)                                             \
01527     {                                                                         \
01528       Len = 5;                                                                \
01529       Mask = 0x03;                                                            \
01530     }                                                                         \
01531   else if ((Char & 0xfe) == 0xfc)                                             \
01532     {                                                                         \
01533       Len = 6;                                                                \
01534       Mask = 0x01;                                                            \
01535     }                                                                         \
01536   else                                                                        \
01537     {                                                                         \
01538       Len = 0;                                                               \
01539       Mask = 0;                                                               \
01540     }
01541 
01546 #define UTF8_LENGTH(Char)              \
01547   ((Char) < 0x80 ? 1 :                 \
01548    ((Char) < 0x800 ? 2 :               \
01549     ((Char) < 0x10000 ? 3 :            \
01550      ((Char) < 0x200000 ? 4 :          \
01551       ((Char) < 0x4000000 ? 5 : 6)))))
01552    
01562 #define UTF8_GET(Result, Chars, Count, Mask, Len)                             \
01563   (Result) = (Chars)[0] & (Mask);                                             \
01564   for ((Count) = 1; (Count) < (Len); ++(Count))                               \
01565     {                                                                         \
01566       if (((Chars)[(Count)] & 0xc0) != 0x80)                                  \
01567         {                                                                     \
01568           (Result) = -1;                                                      \
01569           break;                                                              \
01570         }                                                                     \
01571       (Result) <<= 6;                                                         \
01572       (Result) |= ((Chars)[(Count)] & 0x3f);                                  \
01573     }
01574 
01585 #define UNICODE_VALID(Char)                   \
01586     ((Char) < 0x110000 &&                     \
01587      (((Char) & 0xFFFFF800) != 0xD800))
01588 
01603 dbus_bool_t
01604 _dbus_string_find (const DBusString *str,
01605                    int               start,
01606                    const char       *substr,
01607                    int              *found)
01608 {
01609   return _dbus_string_find_to (str, start,
01610                                ((const DBusRealString*)str)->len,
01611                                substr, found);
01612 }
01613 
01626 dbus_bool_t
01627 _dbus_string_find_eol (const DBusString *str,
01628                        int               start,
01629                        int              *found,
01630                        int              *found_len)
01631 {
01632   int i;
01633 
01634   DBUS_CONST_STRING_PREAMBLE (str);
01635   _dbus_assert (start <= real->len);
01636   _dbus_assert (start >= 0);
01637   
01638   i = start;
01639   while (i < real->len)
01640     {
01641       if (real->str[i] == '\r') 
01642         {
01643           if ((i+1) < real->len && real->str[i+1] == '\n') /* "\r\n" */
01644             {
01645               if (found) 
01646                 *found = i;
01647               if (found_len)
01648                 *found_len = 2;
01649               return TRUE;
01650             } 
01651           else /* only "\r" */
01652             {
01653               if (found) 
01654                 *found = i;
01655               if (found_len)
01656                 *found_len = 1;
01657               return TRUE;
01658             }
01659         } 
01660       else if (real->str[i] == '\n')  /* only "\n" */
01661         {
01662           if (found) 
01663             *found = i;
01664           if (found_len)
01665             *found_len = 1;
01666           return TRUE;
01667         }
01668       ++i;
01669     }
01670 
01671   if (found)
01672     *found = real->len;
01673 
01674   if (found_len)
01675     *found_len = 0;
01676   
01677   return FALSE;
01678 }
01679 
01696 dbus_bool_t
01697 _dbus_string_find_to (const DBusString *str,
01698                       int               start,
01699                       int               end,
01700                       const char       *substr,
01701                       int              *found)
01702 {
01703   int i;
01704   DBUS_CONST_STRING_PREAMBLE (str);
01705   _dbus_assert (substr != NULL);
01706   _dbus_assert (start <= real->len);
01707   _dbus_assert (start >= 0);
01708   _dbus_assert (substr != NULL);
01709   _dbus_assert (end <= real->len);
01710   _dbus_assert (start <= end);
01711 
01712   /* we always "find" an empty string */
01713   if (*substr == '\0')
01714     {
01715       if (found)
01716         *found = start;
01717       return TRUE;
01718     }
01719 
01720   i = start;
01721   while (i < end)
01722     {
01723       if (real->str[i] == substr[0])
01724         {
01725           int j = i + 1;
01726           
01727           while (j < end)
01728             {
01729               if (substr[j - i] == '\0')
01730                 break;
01731               else if (real->str[j] != substr[j - i])
01732                 break;
01733               
01734               ++j;
01735             }
01736 
01737           if (substr[j - i] == '\0')
01738             {
01739               if (found)
01740                 *found = i;
01741               return TRUE;
01742             }
01743         }
01744       
01745       ++i;
01746     }
01747 
01748   if (found)
01749     *found = end;
01750   
01751   return FALSE;  
01752 }
01753 
01764 dbus_bool_t
01765 _dbus_string_find_blank (const DBusString *str,
01766                          int               start,
01767                          int              *found)
01768 {
01769   int i;
01770   DBUS_CONST_STRING_PREAMBLE (str);
01771   _dbus_assert (start <= real->len);
01772   _dbus_assert (start >= 0);
01773   
01774   i = start;
01775   while (i < real->len)
01776     {
01777       if (real->str[i] == ' ' ||
01778           real->str[i] == '\t')
01779         {
01780           if (found)
01781             *found = i;
01782           return TRUE;
01783         }
01784       
01785       ++i;
01786     }
01787 
01788   if (found)
01789     *found = real->len;
01790   
01791   return FALSE;
01792 }
01793 
01802 void
01803 _dbus_string_skip_blank (const DBusString *str,
01804                          int               start,
01805                          int              *end)
01806 {
01807   int i;
01808   DBUS_CONST_STRING_PREAMBLE (str);
01809   _dbus_assert (start <= real->len);
01810   _dbus_assert (start >= 0);
01811   
01812   i = start;
01813   while (i < real->len)
01814     {
01815       if (!DBUS_IS_ASCII_BLANK (real->str[i]))
01816         break;
01817       
01818       ++i;
01819     }
01820 
01821   _dbus_assert (i == real->len || !DBUS_IS_ASCII_WHITE (real->str[i]));
01822   
01823   if (end)
01824     *end = i;
01825 }
01826 
01827 
01836 void
01837 _dbus_string_skip_white (const DBusString *str,
01838                          int               start,
01839                          int              *end)
01840 {
01841   int i;
01842   DBUS_CONST_STRING_PREAMBLE (str);
01843   _dbus_assert (start <= real->len);
01844   _dbus_assert (start >= 0);
01845   
01846   i = start;
01847   while (i < real->len)
01848     {
01849       if (!DBUS_IS_ASCII_WHITE (real->str[i]))
01850         break;
01851       
01852       ++i;
01853     }
01854 
01855   _dbus_assert (i == real->len || !(DBUS_IS_ASCII_WHITE (real->str[i])));
01856   
01857   if (end)
01858     *end = i;
01859 }
01860 
01869 void
01870 _dbus_string_skip_white_reverse (const DBusString *str,
01871                                  int               end,
01872                                  int              *start)
01873 {
01874   int i;
01875   DBUS_CONST_STRING_PREAMBLE (str);
01876   _dbus_assert (end <= real->len);
01877   _dbus_assert (end >= 0);
01878   
01879   i = end;
01880   while (i > 0)
01881     {
01882       if (!DBUS_IS_ASCII_WHITE (real->str[i-1]))
01883         break;
01884       --i;
01885     }
01886 
01887   _dbus_assert (i >= 0 && (i == 0 || !(DBUS_IS_ASCII_WHITE (real->str[i-1]))));
01888   
01889   if (start)
01890     *start = i;
01891 }
01892 
01908 dbus_bool_t
01909 _dbus_string_pop_line (DBusString *source,
01910                        DBusString *dest)
01911 {
01912   int eol, eol_len;
01913   
01914   _dbus_string_set_length (dest, 0);
01915   
01916   eol = 0;
01917   eol_len = 0;
01918   if (!_dbus_string_find_eol (source, 0, &eol, &eol_len))
01919     {
01920       _dbus_assert (eol == _dbus_string_get_length (source));
01921       if (eol == 0)
01922         {
01923           /* If there's no newline and source has zero length, we're done */
01924           return FALSE;
01925         }
01926       /* otherwise, the last line of the file has no eol characters */
01927     }
01928 
01929   /* remember eol can be 0 if it's an empty line, but eol_len should not be zero also
01930    * since find_eol returned TRUE
01931    */
01932   
01933   if (!_dbus_string_move_len (source, 0, eol + eol_len, dest, 0))
01934     return FALSE;
01935   
01936   /* remove line ending */
01937   if (!_dbus_string_set_length (dest, eol))
01938     {
01939       _dbus_assert_not_reached ("out of memory when shortening a string");
01940       return FALSE;
01941     }
01942 
01943   return TRUE;
01944 }
01945 
01946 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
01947 
01953 void
01954 _dbus_string_delete_first_word (DBusString *str)
01955 {
01956   int i;
01957   
01958   if (_dbus_string_find_blank (str, 0, &i))
01959     _dbus_string_skip_blank (str, i, &i);
01960 
01961   _dbus_string_delete (str, 0, i);
01962 }
01963 #endif
01964 
01965 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
01966 
01971 void
01972 _dbus_string_delete_leading_blanks (DBusString *str)
01973 {
01974   int i;
01975   
01976   _dbus_string_skip_blank (str, 0, &i);
01977 
01978   if (i > 0)
01979     _dbus_string_delete (str, 0, i);
01980 }
01981 #endif
01982 
01988 void
01989 _dbus_string_chop_white(DBusString *str)
01990 {
01991   int i;
01992   
01993   _dbus_string_skip_white (str, 0, &i);
01994 
01995   if (i > 0)
01996     _dbus_string_delete (str, 0, i);
01997   
01998   _dbus_string_skip_white_reverse (str, _dbus_string_get_length (str), &i);
01999 
02000   _dbus_string_set_length (str, i);
02001 }
02002 
02012 dbus_bool_t
02013 _dbus_string_equal (const DBusString *a,
02014                     const DBusString *b)
02015 {
02016   const unsigned char *ap;
02017   const unsigned char *bp;
02018   const unsigned char *a_end;
02019   const DBusRealString *real_a = (const DBusRealString*) a;
02020   const DBusRealString *real_b = (const DBusRealString*) b;
02021   DBUS_GENERIC_STRING_PREAMBLE (real_a);
02022   DBUS_GENERIC_STRING_PREAMBLE (real_b);
02023 
02024   if (real_a->len != real_b->len)
02025     return FALSE;
02026 
02027   ap = real_a->str;
02028   bp = real_b->str;
02029   a_end = real_a->str + real_a->len;
02030   while (ap != a_end)
02031     {
02032       if (*ap != *bp)
02033         return FALSE;
02034       
02035       ++ap;
02036       ++bp;
02037     }
02038 
02039   return TRUE;
02040 }
02041 
02055 dbus_bool_t
02056 _dbus_string_equal_len (const DBusString *a,
02057                         const DBusString *b,
02058                         int               len)
02059 {
02060   const unsigned char *ap;
02061   const unsigned char *bp;
02062   const unsigned char *a_end;
02063   const DBusRealString *real_a = (const DBusRealString*) a;
02064   const DBusRealString *real_b = (const DBusRealString*) b;
02065   DBUS_GENERIC_STRING_PREAMBLE (real_a);
02066   DBUS_GENERIC_STRING_PREAMBLE (real_b);
02067 
02068   if (real_a->len != real_b->len &&
02069       (real_a->len < len || real_b->len < len))
02070     return FALSE;
02071 
02072   ap = real_a->str;
02073   bp = real_b->str;
02074   a_end = real_a->str + MIN (real_a->len, len);
02075   while (ap != a_end)
02076     {
02077       if (*ap != *bp)
02078         return FALSE;
02079       
02080       ++ap;
02081       ++bp;
02082     }
02083 
02084   return TRUE;
02085 }
02086 
02103 dbus_bool_t
02104 _dbus_string_equal_substring (const DBusString  *a,
02105                               int                a_start,
02106                               int                a_len,
02107                               const DBusString  *b,
02108                               int                b_start)
02109 {
02110   const unsigned char *ap;
02111   const unsigned char *bp;
02112   const unsigned char *a_end;
02113   const DBusRealString *real_a = (const DBusRealString*) a;
02114   const DBusRealString *real_b = (const DBusRealString*) b;
02115   DBUS_GENERIC_STRING_PREAMBLE (real_a);
02116   DBUS_GENERIC_STRING_PREAMBLE (real_b);
02117   _dbus_assert (a_start >= 0);
02118   _dbus_assert (a_len >= 0);
02119   _dbus_assert (a_start <= real_a->len);
02120   _dbus_assert (a_len <= real_a->len - a_start);
02121   _dbus_assert (b_start >= 0);
02122   _dbus_assert (b_start <= real_b->len);
02123   
02124   if (a_len > real_b->len - b_start)
02125     return FALSE;
02126 
02127   ap = real_a->str + a_start;
02128   bp = real_b->str + b_start;
02129   a_end = ap + a_len;
02130   while (ap != a_end)
02131     {
02132       if (*ap != *bp)
02133         return FALSE;
02134       
02135       ++ap;
02136       ++bp;
02137     }
02138 
02139   _dbus_assert (bp <= (real_b->str + real_b->len));
02140   
02141   return TRUE;
02142 }
02143 
02151 dbus_bool_t
02152 _dbus_string_equal_c_str (const DBusString *a,
02153                           const char       *c_str)
02154 {
02155   const unsigned char *ap;
02156   const unsigned char *bp;
02157   const unsigned char *a_end;
02158   const DBusRealString *real_a = (const DBusRealString*) a;
02159   DBUS_GENERIC_STRING_PREAMBLE (real_a);
02160   _dbus_assert (c_str != NULL);
02161   
02162   ap = real_a->str;
02163   bp = (const unsigned char*) c_str;
02164   a_end = real_a->str + real_a->len;
02165   while (ap != a_end && *bp)
02166     {
02167       if (*ap != *bp)
02168         return FALSE;
02169       
02170       ++ap;
02171       ++bp;
02172     }
02173 
02174   if (ap != a_end || *bp)
02175     return FALSE;
02176   
02177   return TRUE;
02178 }
02179 
02187 dbus_bool_t
02188 _dbus_string_starts_with_c_str (const DBusString *a,
02189                                 const char       *c_str)
02190 {
02191   const unsigned char *ap;
02192   const unsigned char *bp;
02193   const unsigned char *a_end;
02194   const DBusRealString *real_a = (const DBusRealString*) a;
02195   DBUS_GENERIC_STRING_PREAMBLE (real_a);
02196   _dbus_assert (c_str != NULL);
02197   
02198   ap = real_a->str;
02199   bp = (const unsigned char*) c_str;
02200   a_end = real_a->str + real_a->len;
02201   while (ap != a_end && *bp)
02202     {
02203       if (*ap != *bp)
02204         return FALSE;
02205       
02206       ++ap;
02207       ++bp;
02208     }
02209 
02210   if (*bp == '\0')
02211     return TRUE;
02212   else
02213     return FALSE;
02214 }
02215 
02224 dbus_bool_t
02225 _dbus_string_append_byte_as_hex (DBusString *str,
02226                                  unsigned char byte)
02227 {
02228   const char hexdigits[16] = {
02229     '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
02230     'a', 'b', 'c', 'd', 'e', 'f'
02231   };
02232 
02233   if (!_dbus_string_append_byte (str,
02234                                  hexdigits[(byte >> 4)]))
02235     return FALSE;
02236   
02237   if (!_dbus_string_append_byte (str,
02238                                  hexdigits[(byte & 0x0f)]))
02239     {
02240       _dbus_string_set_length (str,
02241                                _dbus_string_get_length (str) - 1);
02242       return FALSE;
02243     }
02244 
02245   return TRUE;
02246 }
02247 
02258 dbus_bool_t
02259 _dbus_string_hex_encode (const DBusString *source,
02260                          int               start,
02261                          DBusString       *dest,
02262                          int               insert_at)
02263 {
02264   DBusString result;
02265   const unsigned char *p;
02266   const unsigned char *end;
02267   dbus_bool_t retval;
02268   
02269   _dbus_assert (start <= _dbus_string_get_length (source));
02270 
02271   if (!_dbus_string_init (&result))
02272     return FALSE;
02273 
02274   retval = FALSE;
02275   
02276   p = (const unsigned char*) _dbus_string_get_const_data (source);
02277   end = p + _dbus_string_get_length (source);
02278   p += start;
02279   
02280   while (p != end)
02281     {
02282       if (!_dbus_string_append_byte_as_hex (&result, *p))
02283         goto out;
02284       
02285       ++p;
02286     }
02287 
02288   if (!_dbus_string_move (&result, 0, dest, insert_at))
02289     goto out;
02290 
02291   retval = TRUE;
02292 
02293  out:
02294   _dbus_string_free (&result);
02295   return retval;
02296 }
02297 
02308 dbus_bool_t
02309 _dbus_string_hex_decode (const DBusString *source,
02310                          int               start,
02311                          int              *end_return,
02312                          DBusString       *dest,
02313                          int               insert_at)
02314 {
02315   DBusString result;
02316   const unsigned char *p;
02317   const unsigned char *end;
02318   dbus_bool_t retval;
02319   dbus_bool_t high_bits;
02320   
02321   _dbus_assert (start <= _dbus_string_get_length (source));
02322 
02323   if (!_dbus_string_init (&result))
02324     return FALSE;
02325 
02326   retval = FALSE;
02327 
02328   high_bits = TRUE;
02329   p = (const unsigned char*) _dbus_string_get_const_data (source);
02330   end = p + _dbus_string_get_length (source);
02331   p += start;
02332   
02333   while (p != end)
02334     {
02335       unsigned int val;
02336 
02337       switch (*p)
02338         {
02339         case '0':
02340           val = 0;
02341           break;
02342         case '1':
02343           val = 1;
02344           break;
02345         case '2':
02346           val = 2;
02347           break;
02348         case '3':
02349           val = 3;
02350           break;
02351         case '4':
02352           val = 4;
02353           break;
02354         case '5':
02355           val = 5;
02356           break;
02357         case '6':
02358           val = 6;
02359           break;
02360         case '7':
02361           val = 7;
02362           break;
02363         case '8':
02364           val = 8;
02365           break;
02366         case '9':
02367           val = 9;
02368           break;
02369         case 'a':
02370         case 'A':
02371           val = 10;
02372           break;
02373         case 'b':
02374         case 'B':
02375           val = 11;
02376           break;
02377         case 'c':
02378         case 'C':
02379           val = 12;
02380           break;
02381         case 'd':
02382         case 'D':
02383           val = 13;
02384           break;
02385         case 'e':
02386         case 'E':
02387           val = 14;
02388           break;
02389         case 'f':
02390         case 'F':
02391           val = 15;
02392           break;
02393         default:
02394           goto done;
02395         }
02396 
02397       if (high_bits)
02398         {
02399           if (!_dbus_string_append_byte (&result,
02400                                          val << 4))
02401             goto out;
02402         }
02403       else
02404         {
02405           int len;
02406           unsigned char b;
02407 
02408           len = _dbus_string_get_length (&result);
02409           
02410           b = _dbus_string_get_byte (&result, len - 1);
02411 
02412           b |= val;
02413 
02414           _dbus_string_set_byte (&result, len - 1, b);
02415         }
02416 
02417       high_bits = !high_bits;
02418 
02419       ++p;
02420     }
02421 
02422  done:
02423   if (!_dbus_string_move (&result, 0, dest, insert_at))
02424     goto out;
02425 
02426   if (end_return)
02427     *end_return = p - (const unsigned char*) _dbus_string_get_const_data (source);
02428 
02429   retval = TRUE;
02430   
02431  out:
02432   _dbus_string_free (&result);  
02433   return retval;
02434 }
02435 
02449 dbus_bool_t
02450 _dbus_string_validate_ascii (const DBusString *str,
02451                              int               start,
02452                              int               len)
02453 {
02454   const unsigned char *s;
02455   const unsigned char *end;
02456   DBUS_CONST_STRING_PREAMBLE (str);
02457   _dbus_assert (start >= 0);
02458   _dbus_assert (start <= real->len);
02459   _dbus_assert (len >= 0);
02460   
02461   if (len > real->len - start)
02462     return FALSE;
02463   
02464   s = real->str + start;
02465   end = s + len;
02466   while (s != end)
02467     {
02468       if (_DBUS_UNLIKELY (!_DBUS_ISASCII (*s)))
02469         return FALSE;
02470         
02471       ++s;
02472     }
02473   
02474   return TRUE;
02475 }
02476 
02484 void
02485 _dbus_string_tolower_ascii (const DBusString *str,
02486                             int               start,
02487                             int               len)
02488 {
02489   unsigned char *s;
02490   unsigned char *end;
02491   DBUS_STRING_PREAMBLE (str);
02492   _dbus_assert (start >= 0);
02493   _dbus_assert (start <= real->len);
02494   _dbus_assert (len >= 0);
02495   _dbus_assert (len <= real->len - start);
02496 
02497   s = real->str + start;
02498   end = s + len;
02499 
02500   while (s != end)
02501     {
02502       if (*s >= 'A' && *s <= 'Z')
02503           *s += 'a' - 'A';
02504       ++s;
02505     }
02506 }
02507 
02515 void
02516 _dbus_string_toupper_ascii (const DBusString *str,
02517                             int               start,
02518                             int               len)
02519 {
02520   unsigned char *s;
02521   unsigned char *end;
02522   DBUS_STRING_PREAMBLE (str);
02523   _dbus_assert (start >= 0);
02524   _dbus_assert (start <= real->len);
02525   _dbus_assert (len >= 0);
02526   _dbus_assert (len <= real->len - start);
02527 
02528   s = real->str + start;
02529   end = s + len;
02530 
02531   while (s != end)
02532     {
02533       if (*s >= 'a' && *s <= 'z')
02534           *s += 'A' - 'a';
02535       ++s;
02536     }
02537 }
02538 
02554 dbus_bool_t
02555 _dbus_string_validate_utf8  (const DBusString *str,
02556                              int               start,
02557                              int               len)
02558 {
02559   const unsigned char *p;
02560   const unsigned char *end;
02561   DBUS_CONST_STRING_PREAMBLE (str);
02562   _dbus_assert (start >= 0);
02563   _dbus_assert (start <= real->len);
02564   _dbus_assert (len >= 0);
02565 
02566   /* we are doing _DBUS_UNLIKELY() here which might be
02567    * dubious in a generic library like GLib, but in D-Bus
02568    * we know we're validating messages and that it would
02569    * only be evil/broken apps that would have invalid
02570    * UTF-8. Also, this function seems to be a performance
02571    * bottleneck in profiles.
02572    */
02573   
02574   if (_DBUS_UNLIKELY (len > real->len - start))
02575     return FALSE;
02576   
02577   p = real->str + start;
02578   end = p + len;
02579   
02580   while (p < end)
02581     {
02582       int i, mask, char_len;
02583       dbus_unichar_t result;
02584 
02585       /* nul bytes considered invalid */
02586       if (*p == '\0')
02587         break;
02588       
02589       /* Special-case ASCII; this makes us go a lot faster in
02590        * D-Bus profiles where we are typically validating
02591        * function names and such. We have to know that
02592        * all following checks will pass for ASCII though,
02593        * comments follow ...
02594        */      
02595       if (*p < 128)
02596         {
02597           ++p;
02598           continue;
02599         }
02600       
02601       UTF8_COMPUTE (*p, mask, char_len);
02602 
02603       if (_DBUS_UNLIKELY (char_len == 0))  /* ASCII: char_len == 1 */
02604         break;
02605 
02606       /* check that the expected number of bytes exists in the remaining length */
02607       if (_DBUS_UNLIKELY ((end - p) < char_len)) /* ASCII: p < end and char_len == 1 */
02608         break;
02609         
02610       UTF8_GET (result, p, i, mask, char_len);
02611 
02612       /* Check for overlong UTF-8 */
02613       if (_DBUS_UNLIKELY (UTF8_LENGTH (result) != char_len)) /* ASCII: UTF8_LENGTH == 1 */
02614         break;
02615 #if 0
02616       /* The UNICODE_VALID check below will catch this */
02617       if (_DBUS_UNLIKELY (result == (dbus_unichar_t)-1)) /* ASCII: result = ascii value */
02618         break;
02619 #endif
02620 
02621       if (_DBUS_UNLIKELY (!UNICODE_VALID (result))) /* ASCII: always valid */
02622         break;
02623 
02624       /* UNICODE_VALID should have caught it */
02625       _dbus_assert (result != (dbus_unichar_t)-1);
02626       
02627       p += char_len;
02628     }
02629 
02630   /* See that we covered the entire length if a length was
02631    * passed in
02632    */
02633   if (_DBUS_UNLIKELY (p != end))
02634     return FALSE;
02635   else
02636     return TRUE;
02637 }
02638 
02652 dbus_bool_t
02653 _dbus_string_validate_nul (const DBusString *str,
02654                            int               start,
02655                            int               len)
02656 {
02657   const unsigned char *s;
02658   const unsigned char *end;
02659   DBUS_CONST_STRING_PREAMBLE (str);
02660   _dbus_assert (start >= 0);
02661   _dbus_assert (len >= 0);
02662   _dbus_assert (start <= real->len);
02663   
02664   if (len > real->len - start)
02665     return FALSE;
02666   
02667   s = real->str + start;
02668   end = s + len;
02669   while (s != end)
02670     {
02671       if (_DBUS_UNLIKELY (*s != '\0'))
02672         return FALSE;
02673       ++s;
02674     }
02675   
02676   return TRUE;
02677 }
02678 
02684 void
02685 _dbus_string_zero (DBusString *str)
02686 {
02687   DBUS_STRING_PREAMBLE (str);
02688 
02689   memset (real->str - real->align_offset, '\0', real->allocated);
02690 }
02693 /* tests are in dbus-string-util.c */