Home | History | Annotate | Line # | Download | only in libiberty
dyn-string.c revision 1.1
      1  1.1  skrll /* An abstract string datatype.
      2  1.1  skrll    Copyright (C) 1998, 1999, 2000, 2002, 2004 Free Software Foundation, Inc.
      3  1.1  skrll    Contributed by Mark Mitchell (mark (at) markmitchell.com).
      4  1.1  skrll 
      5  1.1  skrll This file is part of GNU CC.
      6  1.1  skrll 
      7  1.1  skrll GNU CC is free software; you can redistribute it and/or modify
      8  1.1  skrll it under the terms of the GNU General Public License as published by
      9  1.1  skrll the Free Software Foundation; either version 2, or (at your option)
     10  1.1  skrll any later version.
     11  1.1  skrll 
     12  1.1  skrll In addition to the permissions in the GNU General Public License, the
     13  1.1  skrll Free Software Foundation gives you unlimited permission to link the
     14  1.1  skrll compiled version of this file into combinations with other programs,
     15  1.1  skrll and to distribute those combinations without any restriction coming
     16  1.1  skrll from the use of this file.  (The General Public License restrictions
     17  1.1  skrll do apply in other respects; for example, they cover modification of
     18  1.1  skrll the file, and distribution when not linked into a combined
     19  1.1  skrll executable.)
     20  1.1  skrll 
     21  1.1  skrll GNU CC is distributed in the hope that it will be useful,
     22  1.1  skrll but WITHOUT ANY WARRANTY; without even the implied warranty of
     23  1.1  skrll MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     24  1.1  skrll GNU General Public License for more details.
     25  1.1  skrll 
     26  1.1  skrll You should have received a copy of the GNU General Public License
     27  1.1  skrll along with GNU CC; see the file COPYING.  If not, write to
     28  1.1  skrll the Free Software Foundation, 51 Franklin Street - Fifth Floor,
     29  1.1  skrll Boston, MA 02110-1301, USA.  */
     30  1.1  skrll 
     31  1.1  skrll #ifdef HAVE_CONFIG_H
     32  1.1  skrll #include "config.h"
     33  1.1  skrll #endif
     34  1.1  skrll 
     35  1.1  skrll #include <stdio.h>
     36  1.1  skrll 
     37  1.1  skrll #ifdef HAVE_STRING_H
     38  1.1  skrll #include <string.h>
     39  1.1  skrll #endif
     40  1.1  skrll 
     41  1.1  skrll #ifdef HAVE_STDLIB_H
     42  1.1  skrll #include <stdlib.h>
     43  1.1  skrll #endif
     44  1.1  skrll 
     45  1.1  skrll #include "libiberty.h"
     46  1.1  skrll #include "dyn-string.h"
     47  1.1  skrll 
     48  1.1  skrll /* Performs in-place initialization of a dyn_string struct.  This
     49  1.1  skrll    function can be used with a dyn_string struct on the stack or
     50  1.1  skrll    embedded in another object.  The contents of of the string itself
     51  1.1  skrll    are still dynamically allocated.  The string initially is capable
     52  1.1  skrll    of holding at least SPACE characeters, including the terminating
     53  1.1  skrll    NUL.  If SPACE is 0, it will silently be increated to 1.
     54  1.1  skrll 
     55  1.1  skrll    If RETURN_ON_ALLOCATION_FAILURE is defined and memory allocation
     56  1.1  skrll    fails, returns 0.  Otherwise returns 1.  */
     57  1.1  skrll 
     58  1.1  skrll int
     59  1.1  skrll dyn_string_init (struct dyn_string *ds_struct_ptr, int space)
     60  1.1  skrll {
     61  1.1  skrll   /* We need at least one byte in which to store the terminating NUL.  */
     62  1.1  skrll   if (space == 0)
     63  1.1  skrll     space = 1;
     64  1.1  skrll 
     65  1.1  skrll #ifdef RETURN_ON_ALLOCATION_FAILURE
     66  1.1  skrll   ds_struct_ptr->s = (char *) malloc (space);
     67  1.1  skrll   if (ds_struct_ptr->s == NULL)
     68  1.1  skrll     return 0;
     69  1.1  skrll #else
     70  1.1  skrll   ds_struct_ptr->s = XNEWVEC (char, space);
     71  1.1  skrll #endif
     72  1.1  skrll   ds_struct_ptr->allocated = space;
     73  1.1  skrll   ds_struct_ptr->length = 0;
     74  1.1  skrll   ds_struct_ptr->s[0] = '\0';
     75  1.1  skrll 
     76  1.1  skrll   return 1;
     77  1.1  skrll }
     78  1.1  skrll 
     79  1.1  skrll /* Create a new dynamic string capable of holding at least SPACE
     80  1.1  skrll    characters, including the terminating NUL.  If SPACE is 0, it will
     81  1.1  skrll    be silently increased to 1.  If RETURN_ON_ALLOCATION_FAILURE is
     82  1.1  skrll    defined and memory allocation fails, returns NULL.  Otherwise
     83  1.1  skrll    returns the newly allocated string.  */
     84  1.1  skrll 
     85  1.1  skrll dyn_string_t
     86  1.1  skrll dyn_string_new (int space)
     87  1.1  skrll {
     88  1.1  skrll   dyn_string_t result;
     89  1.1  skrll #ifdef RETURN_ON_ALLOCATION_FAILURE
     90  1.1  skrll   result = (dyn_string_t) malloc (sizeof (struct dyn_string));
     91  1.1  skrll   if (result == NULL)
     92  1.1  skrll     return NULL;
     93  1.1  skrll   if (!dyn_string_init (result, space))
     94  1.1  skrll     {
     95  1.1  skrll       free (result);
     96  1.1  skrll       return NULL;
     97  1.1  skrll     }
     98  1.1  skrll #else
     99  1.1  skrll   result = XNEW (struct dyn_string);
    100  1.1  skrll   dyn_string_init (result, space);
    101  1.1  skrll #endif
    102  1.1  skrll   return result;
    103  1.1  skrll }
    104  1.1  skrll 
    105  1.1  skrll /* Free the memory used by DS.  */
    106  1.1  skrll 
    107  1.1  skrll void
    108  1.1  skrll dyn_string_delete (dyn_string_t ds)
    109  1.1  skrll {
    110  1.1  skrll   free (ds->s);
    111  1.1  skrll   free (ds);
    112  1.1  skrll }
    113  1.1  skrll 
    114  1.1  skrll /* Returns the contents of DS in a buffer allocated with malloc.  It
    115  1.1  skrll    is the caller's responsibility to deallocate the buffer using free.
    116  1.1  skrll    DS is then set to the empty string.  Deletes DS itself.  */
    117  1.1  skrll 
    118  1.1  skrll char*
    119  1.1  skrll dyn_string_release (dyn_string_t ds)
    120  1.1  skrll {
    121  1.1  skrll   /* Store the old buffer.  */
    122  1.1  skrll   char* result = ds->s;
    123  1.1  skrll   /* The buffer is no longer owned by DS.  */
    124  1.1  skrll   ds->s = NULL;
    125  1.1  skrll   /* Delete DS.  */
    126  1.1  skrll   free (ds);
    127  1.1  skrll   /* Return the old buffer.  */
    128  1.1  skrll   return result;
    129  1.1  skrll }
    130  1.1  skrll 
    131  1.1  skrll /* Increase the capacity of DS so it can hold at least SPACE
    132  1.1  skrll    characters, plus the terminating NUL.  This function will not (at
    133  1.1  skrll    present) reduce the capacity of DS.  Returns DS on success.
    134  1.1  skrll 
    135  1.1  skrll    If RETURN_ON_ALLOCATION_FAILURE is defined and a memory allocation
    136  1.1  skrll    operation fails, deletes DS and returns NULL.  */
    137  1.1  skrll 
    138  1.1  skrll dyn_string_t
    139  1.1  skrll dyn_string_resize (dyn_string_t ds, int space)
    140  1.1  skrll {
    141  1.1  skrll   int new_allocated = ds->allocated;
    142  1.1  skrll 
    143  1.1  skrll   /* Increase SPACE to hold the NUL termination.  */
    144  1.1  skrll   ++space;
    145  1.1  skrll 
    146  1.1  skrll   /* Increase allocation by factors of two.  */
    147  1.1  skrll   while (space > new_allocated)
    148  1.1  skrll     new_allocated *= 2;
    149  1.1  skrll 
    150  1.1  skrll   if (new_allocated != ds->allocated)
    151  1.1  skrll     {
    152  1.1  skrll       ds->allocated = new_allocated;
    153  1.1  skrll       /* We actually need more space.  */
    154  1.1  skrll #ifdef RETURN_ON_ALLOCATION_FAILURE
    155  1.1  skrll       ds->s = (char *) realloc (ds->s, ds->allocated);
    156  1.1  skrll       if (ds->s == NULL)
    157  1.1  skrll 	{
    158  1.1  skrll 	  free (ds);
    159  1.1  skrll 	  return NULL;
    160  1.1  skrll 	}
    161  1.1  skrll #else
    162  1.1  skrll       ds->s = XRESIZEVEC (char, ds->s, ds->allocated);
    163  1.1  skrll #endif
    164  1.1  skrll     }
    165  1.1  skrll 
    166  1.1  skrll   return ds;
    167  1.1  skrll }
    168  1.1  skrll 
    169  1.1  skrll /* Sets the contents of DS to the empty string.  */
    170  1.1  skrll 
    171  1.1  skrll void
    172  1.1  skrll dyn_string_clear (dyn_string_t ds)
    173  1.1  skrll {
    174  1.1  skrll   /* A dyn_string always has room for at least the NUL terminator.  */
    175  1.1  skrll   ds->s[0] = '\0';
    176  1.1  skrll   ds->length = 0;
    177  1.1  skrll }
    178  1.1  skrll 
    179  1.1  skrll /* Makes the contents of DEST the same as the contents of SRC.  DEST
    180  1.1  skrll    and SRC must be distinct.  Returns 1 on success.  On failure, if
    181  1.1  skrll    RETURN_ON_ALLOCATION_FAILURE, deletes DEST and returns 0.  */
    182  1.1  skrll 
    183  1.1  skrll int
    184  1.1  skrll dyn_string_copy (dyn_string_t dest, dyn_string_t src)
    185  1.1  skrll {
    186  1.1  skrll   if (dest == src)
    187  1.1  skrll     abort ();
    188  1.1  skrll 
    189  1.1  skrll   /* Make room in DEST.  */
    190  1.1  skrll   if (dyn_string_resize (dest, src->length) == NULL)
    191  1.1  skrll     return 0;
    192  1.1  skrll   /* Copy DEST into SRC.  */
    193  1.1  skrll   strcpy (dest->s, src->s);
    194  1.1  skrll   /* Update the size of DEST.  */
    195  1.1  skrll   dest->length = src->length;
    196  1.1  skrll   return 1;
    197  1.1  skrll }
    198  1.1  skrll 
    199  1.1  skrll /* Copies SRC, a NUL-terminated string, into DEST.  Returns 1 on
    200  1.1  skrll    success.  On failure, if RETURN_ON_ALLOCATION_FAILURE, deletes DEST
    201  1.1  skrll    and returns 0.  */
    202  1.1  skrll 
    203  1.1  skrll int
    204  1.1  skrll dyn_string_copy_cstr (dyn_string_t dest, const char *src)
    205  1.1  skrll {
    206  1.1  skrll   int length = strlen (src);
    207  1.1  skrll   /* Make room in DEST.  */
    208  1.1  skrll   if (dyn_string_resize (dest, length) == NULL)
    209  1.1  skrll     return 0;
    210  1.1  skrll   /* Copy DEST into SRC.  */
    211  1.1  skrll   strcpy (dest->s, src);
    212  1.1  skrll   /* Update the size of DEST.  */
    213  1.1  skrll   dest->length = length;
    214  1.1  skrll   return 1;
    215  1.1  skrll }
    216  1.1  skrll 
    217  1.1  skrll /* Inserts SRC at the beginning of DEST.  DEST is expanded as
    218  1.1  skrll    necessary.  SRC and DEST must be distinct.  Returns 1 on success.
    219  1.1  skrll    On failure, if RETURN_ON_ALLOCATION_FAILURE, deletes DEST and
    220  1.1  skrll    returns 0.  */
    221  1.1  skrll 
    222  1.1  skrll int
    223  1.1  skrll dyn_string_prepend (dyn_string_t dest, dyn_string_t src)
    224  1.1  skrll {
    225  1.1  skrll   return dyn_string_insert (dest, 0, src);
    226  1.1  skrll }
    227  1.1  skrll 
    228  1.1  skrll /* Inserts SRC, a NUL-terminated string, at the beginning of DEST.
    229  1.1  skrll    DEST is expanded as necessary.  Returns 1 on success.  On failure,
    230  1.1  skrll    if RETURN_ON_ALLOCATION_FAILURE, deletes DEST and returns 0. */
    231  1.1  skrll 
    232  1.1  skrll int
    233  1.1  skrll dyn_string_prepend_cstr (dyn_string_t dest, const char *src)
    234  1.1  skrll {
    235  1.1  skrll   return dyn_string_insert_cstr (dest, 0, src);
    236  1.1  skrll }
    237  1.1  skrll 
    238  1.1  skrll /* Inserts SRC into DEST starting at position POS.  DEST is expanded
    239  1.1  skrll    as necessary.  SRC and DEST must be distinct.  Returns 1 on
    240  1.1  skrll    success.  On failure, if RETURN_ON_ALLOCATION_FAILURE, deletes DEST
    241  1.1  skrll    and returns 0.  */
    242  1.1  skrll 
    243  1.1  skrll int
    244  1.1  skrll dyn_string_insert (dyn_string_t dest, int pos, dyn_string_t src)
    245  1.1  skrll {
    246  1.1  skrll   int i;
    247  1.1  skrll 
    248  1.1  skrll   if (src == dest)
    249  1.1  skrll     abort ();
    250  1.1  skrll 
    251  1.1  skrll   if (dyn_string_resize (dest, dest->length + src->length) == NULL)
    252  1.1  skrll     return 0;
    253  1.1  skrll   /* Make room for the insertion.  Be sure to copy the NUL.  */
    254  1.1  skrll   for (i = dest->length; i >= pos; --i)
    255  1.1  skrll     dest->s[i + src->length] = dest->s[i];
    256  1.1  skrll   /* Splice in the new stuff.  */
    257  1.1  skrll   strncpy (dest->s + pos, src->s, src->length);
    258  1.1  skrll   /* Compute the new length.  */
    259  1.1  skrll   dest->length += src->length;
    260  1.1  skrll   return 1;
    261  1.1  skrll }
    262  1.1  skrll 
    263  1.1  skrll /* Inserts SRC, a NUL-terminated string, into DEST starting at
    264  1.1  skrll    position POS.  DEST is expanded as necessary.  Returns 1 on
    265  1.1  skrll    success.  On failure, RETURN_ON_ALLOCATION_FAILURE, deletes DEST
    266  1.1  skrll    and returns 0.  */
    267  1.1  skrll 
    268  1.1  skrll int
    269  1.1  skrll dyn_string_insert_cstr (dyn_string_t dest, int pos, const char *src)
    270  1.1  skrll {
    271  1.1  skrll   int i;
    272  1.1  skrll   int length = strlen (src);
    273  1.1  skrll 
    274  1.1  skrll   if (dyn_string_resize (dest, dest->length + length) == NULL)
    275  1.1  skrll     return 0;
    276  1.1  skrll   /* Make room for the insertion.  Be sure to copy the NUL.  */
    277  1.1  skrll   for (i = dest->length; i >= pos; --i)
    278  1.1  skrll     dest->s[i + length] = dest->s[i];
    279  1.1  skrll   /* Splice in the new stuff.  */
    280  1.1  skrll   strncpy (dest->s + pos, src, length);
    281  1.1  skrll   /* Compute the new length.  */
    282  1.1  skrll   dest->length += length;
    283  1.1  skrll   return 1;
    284  1.1  skrll }
    285  1.1  skrll 
    286  1.1  skrll /* Inserts character C into DEST starting at position POS.  DEST is
    287  1.1  skrll    expanded as necessary.  Returns 1 on success.  On failure,
    288  1.1  skrll    RETURN_ON_ALLOCATION_FAILURE, deletes DEST and returns 0.  */
    289  1.1  skrll 
    290  1.1  skrll int
    291  1.1  skrll dyn_string_insert_char (dyn_string_t dest, int pos, int c)
    292  1.1  skrll {
    293  1.1  skrll   int i;
    294  1.1  skrll 
    295  1.1  skrll   if (dyn_string_resize (dest, dest->length + 1) == NULL)
    296  1.1  skrll     return 0;
    297  1.1  skrll   /* Make room for the insertion.  Be sure to copy the NUL.  */
    298  1.1  skrll   for (i = dest->length; i >= pos; --i)
    299  1.1  skrll     dest->s[i + 1] = dest->s[i];
    300  1.1  skrll   /* Add the new character.  */
    301  1.1  skrll   dest->s[pos] = c;
    302  1.1  skrll   /* Compute the new length.  */
    303  1.1  skrll   ++dest->length;
    304  1.1  skrll   return 1;
    305  1.1  skrll }
    306  1.1  skrll 
    307  1.1  skrll /* Append S to DS, resizing DS if necessary.  Returns 1 on success.
    308  1.1  skrll    On failure, if RETURN_ON_ALLOCATION_FAILURE, deletes DEST and
    309  1.1  skrll    returns 0.  */
    310  1.1  skrll 
    311  1.1  skrll int
    312  1.1  skrll dyn_string_append (dyn_string_t dest, dyn_string_t s)
    313  1.1  skrll {
    314  1.1  skrll   if (dyn_string_resize (dest, dest->length + s->length) == 0)
    315  1.1  skrll     return 0;
    316  1.1  skrll   strcpy (dest->s + dest->length, s->s);
    317  1.1  skrll   dest->length += s->length;
    318  1.1  skrll   return 1;
    319  1.1  skrll }
    320  1.1  skrll 
    321  1.1  skrll /* Append the NUL-terminated string S to DS, resizing DS if necessary.
    322  1.1  skrll    Returns 1 on success.  On failure, if RETURN_ON_ALLOCATION_FAILURE,
    323  1.1  skrll    deletes DEST and returns 0.  */
    324  1.1  skrll 
    325  1.1  skrll int
    326  1.1  skrll dyn_string_append_cstr (dyn_string_t dest, const char *s)
    327  1.1  skrll {
    328  1.1  skrll   int len = strlen (s);
    329  1.1  skrll 
    330  1.1  skrll   /* The new length is the old length plus the size of our string, plus
    331  1.1  skrll      one for the null at the end.  */
    332  1.1  skrll   if (dyn_string_resize (dest, dest->length + len) == NULL)
    333  1.1  skrll     return 0;
    334  1.1  skrll   strcpy (dest->s + dest->length, s);
    335  1.1  skrll   dest->length += len;
    336  1.1  skrll   return 1;
    337  1.1  skrll }
    338  1.1  skrll 
    339  1.1  skrll /* Appends C to the end of DEST.  Returns 1 on success.  On failiure,
    340  1.1  skrll    if RETURN_ON_ALLOCATION_FAILURE, deletes DEST and returns 0.  */
    341  1.1  skrll 
    342  1.1  skrll int
    343  1.1  skrll dyn_string_append_char (dyn_string_t dest, int c)
    344  1.1  skrll {
    345  1.1  skrll   /* Make room for the extra character.  */
    346  1.1  skrll   if (dyn_string_resize (dest, dest->length + 1) == NULL)
    347  1.1  skrll     return 0;
    348  1.1  skrll   /* Append the character; it will overwrite the old NUL.  */
    349  1.1  skrll   dest->s[dest->length] = c;
    350  1.1  skrll   /* Add a new NUL at the end.  */
    351  1.1  skrll   dest->s[dest->length + 1] = '\0';
    352  1.1  skrll   /* Update the length.  */
    353  1.1  skrll   ++(dest->length);
    354  1.1  skrll   return 1;
    355  1.1  skrll }
    356  1.1  skrll 
    357  1.1  skrll /* Sets the contents of DEST to the substring of SRC starting at START
    358  1.1  skrll    and ending before END.  START must be less than or equal to END,
    359  1.1  skrll    and both must be between zero and the length of SRC, inclusive.
    360  1.1  skrll    Returns 1 on success.  On failure, if RETURN_ON_ALLOCATION_FAILURE,
    361  1.1  skrll    deletes DEST and returns 0.  */
    362  1.1  skrll 
    363  1.1  skrll int
    364  1.1  skrll dyn_string_substring (dyn_string_t dest, dyn_string_t src,
    365  1.1  skrll                       int start, int end)
    366  1.1  skrll {
    367  1.1  skrll   int i;
    368  1.1  skrll   int length = end - start;
    369  1.1  skrll 
    370  1.1  skrll   if (start > end || start > src->length || end > src->length)
    371  1.1  skrll     abort ();
    372  1.1  skrll 
    373  1.1  skrll   /* Make room for the substring.  */
    374  1.1  skrll   if (dyn_string_resize (dest, length) == NULL)
    375  1.1  skrll     return 0;
    376  1.1  skrll   /* Copy the characters in the substring,  */
    377  1.1  skrll   for (i = length; --i >= 0; )
    378  1.1  skrll     dest->s[i] = src->s[start + i];
    379  1.1  skrll   /* NUL-terimate the result.  */
    380  1.1  skrll   dest->s[length] = '\0';
    381  1.1  skrll   /* Record the length of the substring.  */
    382  1.1  skrll   dest->length = length;
    383  1.1  skrll 
    384  1.1  skrll   return 1;
    385  1.1  skrll }
    386  1.1  skrll 
    387  1.1  skrll /* Returns non-zero if DS1 and DS2 have the same contents.  */
    388  1.1  skrll 
    389  1.1  skrll int
    390  1.1  skrll dyn_string_eq (dyn_string_t ds1, dyn_string_t ds2)
    391  1.1  skrll {
    392  1.1  skrll   /* If DS1 and DS2 have different lengths, they must not be the same.  */
    393  1.1  skrll   if (ds1->length != ds2->length)
    394  1.1  skrll     return 0;
    395  1.1  skrll   else
    396  1.1  skrll     return !strcmp (ds1->s, ds2->s);
    397  1.1  skrll }
    398