Back to index

cell-binutils  2.17cvs20070401
dyn-string.c
Go to the documentation of this file.
00001 /* An abstract string datatype.
00002    Copyright (C) 1998, 1999, 2000, 2002, 2004 Free Software Foundation, Inc.
00003    Contributed by Mark Mitchell (mark@markmitchell.com).
00004 
00005 This file is part of GNU CC.
00006    
00007 GNU CC is free software; you can redistribute it and/or modify
00008 it under the terms of the GNU General Public License as published by
00009 the Free Software Foundation; either version 2, or (at your option)
00010 any later version.
00011 
00012 In addition to the permissions in the GNU General Public License, the
00013 Free Software Foundation gives you unlimited permission to link the
00014 compiled version of this file into combinations with other programs,
00015 and to distribute those combinations without any restriction coming
00016 from the use of this file.  (The General Public License restrictions
00017 do apply in other respects; for example, they cover modification of
00018 the file, and distribution when not linked into a combined
00019 executable.)
00020 
00021 GNU CC is distributed in the hope that it will be useful,
00022 but WITHOUT ANY WARRANTY; without even the implied warranty of
00023 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00024 GNU General Public License for more details.
00025 
00026 You should have received a copy of the GNU General Public License
00027 along with GNU CC; see the file COPYING.  If not, write to
00028 the Free Software Foundation, 51 Franklin Street - Fifth Floor,
00029 Boston, MA 02110-1301, USA.  */
00030 
00031 #ifdef HAVE_CONFIG_H
00032 #include "config.h"
00033 #endif
00034 
00035 #include <stdio.h>
00036 
00037 #ifdef HAVE_STRING_H
00038 #include <string.h>
00039 #endif
00040 
00041 #ifdef HAVE_STDLIB_H
00042 #include <stdlib.h>
00043 #endif
00044 
00045 #include "libiberty.h"
00046 #include "dyn-string.h"
00047 
00048 /* Performs in-place initialization of a dyn_string struct.  This
00049    function can be used with a dyn_string struct on the stack or
00050    embedded in another object.  The contents of of the string itself
00051    are still dynamically allocated.  The string initially is capable
00052    of holding at least SPACE characeters, including the terminating
00053    NUL.  If SPACE is 0, it will silently be increated to 1.  
00054 
00055    If RETURN_ON_ALLOCATION_FAILURE is defined and memory allocation
00056    fails, returns 0.  Otherwise returns 1.  */
00057 
00058 int
00059 dyn_string_init (struct dyn_string *ds_struct_ptr, int space)
00060 {
00061   /* We need at least one byte in which to store the terminating NUL.  */
00062   if (space == 0)
00063     space = 1;
00064 
00065 #ifdef RETURN_ON_ALLOCATION_FAILURE
00066   ds_struct_ptr->s = (char *) malloc (space);
00067   if (ds_struct_ptr->s == NULL)
00068     return 0;
00069 #else
00070   ds_struct_ptr->s = XNEWVEC (char, space);
00071 #endif
00072   ds_struct_ptr->allocated = space;
00073   ds_struct_ptr->length = 0;
00074   ds_struct_ptr->s[0] = '\0';
00075 
00076   return 1;
00077 }
00078 
00079 /* Create a new dynamic string capable of holding at least SPACE
00080    characters, including the terminating NUL.  If SPACE is 0, it will
00081    be silently increased to 1.  If RETURN_ON_ALLOCATION_FAILURE is
00082    defined and memory allocation fails, returns NULL.  Otherwise
00083    returns the newly allocated string.  */
00084 
00085 dyn_string_t 
00086 dyn_string_new (int space)
00087 {
00088   dyn_string_t result;
00089 #ifdef RETURN_ON_ALLOCATION_FAILURE
00090   result = (dyn_string_t) malloc (sizeof (struct dyn_string));
00091   if (result == NULL)
00092     return NULL;
00093   if (!dyn_string_init (result, space))
00094     {
00095       free (result);
00096       return NULL;
00097     }
00098 #else
00099   result = XNEW (struct dyn_string);
00100   dyn_string_init (result, space);
00101 #endif
00102   return result;
00103 }
00104 
00105 /* Free the memory used by DS.  */
00106 
00107 void 
00108 dyn_string_delete (dyn_string_t ds)
00109 {
00110   free (ds->s);
00111   free (ds);
00112 }
00113 
00114 /* Returns the contents of DS in a buffer allocated with malloc.  It
00115    is the caller's responsibility to deallocate the buffer using free.
00116    DS is then set to the empty string.  Deletes DS itself.  */
00117 
00118 char*
00119 dyn_string_release (dyn_string_t ds)
00120 {
00121   /* Store the old buffer.  */
00122   char* result = ds->s;
00123   /* The buffer is no longer owned by DS.  */
00124   ds->s = NULL;
00125   /* Delete DS.  */
00126   free (ds);
00127   /* Return the old buffer.  */
00128   return result;
00129 }
00130 
00131 /* Increase the capacity of DS so it can hold at least SPACE
00132    characters, plus the terminating NUL.  This function will not (at
00133    present) reduce the capacity of DS.  Returns DS on success. 
00134 
00135    If RETURN_ON_ALLOCATION_FAILURE is defined and a memory allocation
00136    operation fails, deletes DS and returns NULL.  */
00137 
00138 dyn_string_t 
00139 dyn_string_resize (dyn_string_t ds, int space)
00140 {
00141   int new_allocated = ds->allocated;
00142 
00143   /* Increase SPACE to hold the NUL termination.  */
00144   ++space;
00145 
00146   /* Increase allocation by factors of two.  */
00147   while (space > new_allocated)
00148     new_allocated *= 2;
00149     
00150   if (new_allocated != ds->allocated)
00151     {
00152       ds->allocated = new_allocated;
00153       /* We actually need more space.  */
00154 #ifdef RETURN_ON_ALLOCATION_FAILURE
00155       ds->s = (char *) realloc (ds->s, ds->allocated);
00156       if (ds->s == NULL)
00157        {
00158          free (ds);
00159          return NULL;
00160        }
00161 #else
00162       ds->s = XRESIZEVEC (char, ds->s, ds->allocated);
00163 #endif
00164     }
00165 
00166   return ds;
00167 }
00168 
00169 /* Sets the contents of DS to the empty string.  */
00170 
00171 void
00172 dyn_string_clear (dyn_string_t ds)
00173 {
00174   /* A dyn_string always has room for at least the NUL terminator.  */
00175   ds->s[0] = '\0';
00176   ds->length = 0;
00177 }
00178 
00179 /* Makes the contents of DEST the same as the contents of SRC.  DEST
00180    and SRC must be distinct.  Returns 1 on success.  On failure, if
00181    RETURN_ON_ALLOCATION_FAILURE, deletes DEST and returns 0.  */
00182 
00183 int
00184 dyn_string_copy (dyn_string_t dest, dyn_string_t src)
00185 {
00186   if (dest == src)
00187     abort ();
00188 
00189   /* Make room in DEST.  */
00190   if (dyn_string_resize (dest, src->length) == NULL)
00191     return 0;
00192   /* Copy DEST into SRC.  */
00193   strcpy (dest->s, src->s);
00194   /* Update the size of DEST.  */
00195   dest->length = src->length;
00196   return 1;
00197 }
00198 
00199 /* Copies SRC, a NUL-terminated string, into DEST.  Returns 1 on
00200    success.  On failure, if RETURN_ON_ALLOCATION_FAILURE, deletes DEST
00201    and returns 0.  */
00202 
00203 int
00204 dyn_string_copy_cstr (dyn_string_t dest, const char *src)
00205 {
00206   int length = strlen (src);
00207   /* Make room in DEST.  */
00208   if (dyn_string_resize (dest, length) == NULL)
00209     return 0;
00210   /* Copy DEST into SRC.  */
00211   strcpy (dest->s, src);
00212   /* Update the size of DEST.  */
00213   dest->length = length;
00214   return 1;
00215 }
00216 
00217 /* Inserts SRC at the beginning of DEST.  DEST is expanded as
00218    necessary.  SRC and DEST must be distinct.  Returns 1 on success.
00219    On failure, if RETURN_ON_ALLOCATION_FAILURE, deletes DEST and
00220    returns 0.  */
00221 
00222 int
00223 dyn_string_prepend (dyn_string_t dest, dyn_string_t src)
00224 {
00225   return dyn_string_insert (dest, 0, src);
00226 }
00227 
00228 /* Inserts SRC, a NUL-terminated string, at the beginning of DEST.
00229    DEST is expanded as necessary.  Returns 1 on success.  On failure,
00230    if RETURN_ON_ALLOCATION_FAILURE, deletes DEST and returns 0. */
00231 
00232 int
00233 dyn_string_prepend_cstr (dyn_string_t dest, const char *src)
00234 {
00235   return dyn_string_insert_cstr (dest, 0, src);
00236 }
00237 
00238 /* Inserts SRC into DEST starting at position POS.  DEST is expanded
00239    as necessary.  SRC and DEST must be distinct.  Returns 1 on
00240    success.  On failure, if RETURN_ON_ALLOCATION_FAILURE, deletes DEST
00241    and returns 0.  */
00242 
00243 int
00244 dyn_string_insert (dyn_string_t dest, int pos, dyn_string_t src)
00245 {
00246   int i;
00247 
00248   if (src == dest)
00249     abort ();
00250 
00251   if (dyn_string_resize (dest, dest->length + src->length) == NULL)
00252     return 0;
00253   /* Make room for the insertion.  Be sure to copy the NUL.  */
00254   for (i = dest->length; i >= pos; --i)
00255     dest->s[i + src->length] = dest->s[i];
00256   /* Splice in the new stuff.  */
00257   strncpy (dest->s + pos, src->s, src->length);
00258   /* Compute the new length.  */
00259   dest->length += src->length;
00260   return 1;
00261 }
00262 
00263 /* Inserts SRC, a NUL-terminated string, into DEST starting at
00264    position POS.  DEST is expanded as necessary.  Returns 1 on
00265    success.  On failure, RETURN_ON_ALLOCATION_FAILURE, deletes DEST
00266    and returns 0.  */
00267 
00268 int
00269 dyn_string_insert_cstr (dyn_string_t dest, int pos, const char *src)
00270 {
00271   int i;
00272   int length = strlen (src);
00273 
00274   if (dyn_string_resize (dest, dest->length + length) == NULL)
00275     return 0;
00276   /* Make room for the insertion.  Be sure to copy the NUL.  */
00277   for (i = dest->length; i >= pos; --i)
00278     dest->s[i + length] = dest->s[i];
00279   /* Splice in the new stuff.  */
00280   strncpy (dest->s + pos, src, length);
00281   /* Compute the new length.  */
00282   dest->length += length;
00283   return 1;
00284 }
00285 
00286 /* Inserts character C into DEST starting at position POS.  DEST is
00287    expanded as necessary.  Returns 1 on success.  On failure,
00288    RETURN_ON_ALLOCATION_FAILURE, deletes DEST and returns 0.  */
00289 
00290 int
00291 dyn_string_insert_char (dyn_string_t dest, int pos, int c)
00292 {
00293   int i;
00294 
00295   if (dyn_string_resize (dest, dest->length + 1) == NULL)
00296     return 0;
00297   /* Make room for the insertion.  Be sure to copy the NUL.  */
00298   for (i = dest->length; i >= pos; --i)
00299     dest->s[i + 1] = dest->s[i];
00300   /* Add the new character.  */
00301   dest->s[pos] = c;
00302   /* Compute the new length.  */
00303   ++dest->length;
00304   return 1;
00305 }
00306      
00307 /* Append S to DS, resizing DS if necessary.  Returns 1 on success.
00308    On failure, if RETURN_ON_ALLOCATION_FAILURE, deletes DEST and
00309    returns 0.  */
00310 
00311 int
00312 dyn_string_append (dyn_string_t dest, dyn_string_t s)
00313 {
00314   if (dyn_string_resize (dest, dest->length + s->length) == 0)
00315     return 0;
00316   strcpy (dest->s + dest->length, s->s);
00317   dest->length += s->length;
00318   return 1;
00319 }
00320 
00321 /* Append the NUL-terminated string S to DS, resizing DS if necessary.
00322    Returns 1 on success.  On failure, if RETURN_ON_ALLOCATION_FAILURE,
00323    deletes DEST and returns 0.  */
00324 
00325 int
00326 dyn_string_append_cstr (dyn_string_t dest, const char *s)
00327 {
00328   int len = strlen (s);
00329 
00330   /* The new length is the old length plus the size of our string, plus
00331      one for the null at the end.  */
00332   if (dyn_string_resize (dest, dest->length + len) == NULL)
00333     return 0;
00334   strcpy (dest->s + dest->length, s);
00335   dest->length += len;
00336   return 1;
00337 }
00338 
00339 /* Appends C to the end of DEST.  Returns 1 on success.  On failiure,
00340    if RETURN_ON_ALLOCATION_FAILURE, deletes DEST and returns 0.  */
00341 
00342 int
00343 dyn_string_append_char (dyn_string_t dest, int c)
00344 {
00345   /* Make room for the extra character.  */
00346   if (dyn_string_resize (dest, dest->length + 1) == NULL)
00347     return 0;
00348   /* Append the character; it will overwrite the old NUL.  */
00349   dest->s[dest->length] = c;
00350   /* Add a new NUL at the end.  */
00351   dest->s[dest->length + 1] = '\0';
00352   /* Update the length.  */
00353   ++(dest->length);
00354   return 1;
00355 }
00356 
00357 /* Sets the contents of DEST to the substring of SRC starting at START
00358    and ending before END.  START must be less than or equal to END,
00359    and both must be between zero and the length of SRC, inclusive.
00360    Returns 1 on success.  On failure, if RETURN_ON_ALLOCATION_FAILURE,
00361    deletes DEST and returns 0.  */
00362 
00363 int
00364 dyn_string_substring (dyn_string_t dest, dyn_string_t src,
00365                       int start, int end)
00366 {
00367   int i;
00368   int length = end - start;
00369 
00370   if (start > end || start > src->length || end > src->length)
00371     abort ();
00372 
00373   /* Make room for the substring.  */
00374   if (dyn_string_resize (dest, length) == NULL)
00375     return 0;
00376   /* Copy the characters in the substring,  */
00377   for (i = length; --i >= 0; )
00378     dest->s[i] = src->s[start + i];
00379   /* NUL-terimate the result.  */
00380   dest->s[length] = '\0';
00381   /* Record the length of the substring.  */
00382   dest->length = length;
00383 
00384   return 1;
00385 }
00386 
00387 /* Returns non-zero if DS1 and DS2 have the same contents.  */
00388 
00389 int
00390 dyn_string_eq (dyn_string_t ds1, dyn_string_t ds2)
00391 {
00392   /* If DS1 and DS2 have different lengths, they must not be the same.  */
00393   if (ds1->length != ds2->length)
00394     return 0;
00395   else
00396     return !strcmp (ds1->s, ds2->s);
00397 }