dyn-string.c revision 104834
139287Ssos/* An abstract string datatype.
239643Syokota   Copyright (C) 1998, 1999, 2000, 2002 Free Software Foundation, Inc.
339287Ssos   Contributed by Mark Mitchell (mark@markmitchell.com).
439287Ssos
539287SsosThis file is part of GNU CC.
639287Ssos
739287SsosGNU CC is free software; you can redistribute it and/or modify
839287Ssosit under the terms of the GNU General Public License as published by
939643Syokotathe Free Software Foundation; either version 2, or (at your option)
1039643Syokotaany later version.
1139287Ssos
1239287SsosIn addition to the permissions in the GNU General Public License, the
1339287SsosFree Software Foundation gives you unlimited permission to link the
1439287Ssoscompiled version of this file into combinations with other programs,
1539643Syokotaand to distribute those combinations without any restriction coming
1639643Syokotafrom the use of this file.  (The General Public License restrictions
1739643Syokotado apply in other respects; for example, they cover modification of
1839643Syokotathe file, and distribution when not linked into a combined
1939643Syokotaexecutable.)
2039643Syokota
2139643SyokotaGNU CC is distributed in the hope that it will be useful,
2239643Syokotabut WITHOUT ANY WARRANTY; without even the implied warranty of
2339643SyokotaMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
2439643SyokotaGNU General Public License for more details.
2539287Ssos
2639287SsosYou should have received a copy of the GNU General Public License
27115703Sobrienalong with GNU CC; see the file COPYING.  If not, write to
28115703Sobrienthe Free Software Foundation, 59 Temple Place - Suite 330,
29115703SobrienBoston, MA 02111-1307, USA.  */
3042504Syokota
3166710Sjhb#ifdef HAVE_CONFIG_H
3239287Ssos#include "config.h"
3356836Speter#endif
3439287Ssos
3539287Ssos#include <stdio.h>
3639287Ssos
3739287Ssos#ifdef HAVE_STRING_H
3842179Syokota#include <string.h>
3939287Ssos#endif
4048104Syokota
4148104Syokota#ifdef HAVE_STDLIB_H
4239287Ssos#include <stdlib.h>
4348104Syokota#endif
4448104Syokota
45130312Sjhb#include "libiberty.h"
4639287Ssos#include "dyn-string.h"
4739287Ssos
4839287Ssos/* If this file is being compiled for inclusion in the C++ runtime
4939287Ssos   library, as part of the demangler implementation, we don't want to
5039287Ssos   abort if an allocation fails.  Instead, percolate an error code up
5139287Ssos   through the call chain.  */
5239287Ssos
5342504Syokota#if defined(IN_LIBGCC2) || defined(IN_GLIBCPP_V3)
5442504Syokota#define RETURN_ON_ALLOCATION_FAILURE
5539287Ssos#endif
5642504Syokota
5742504Syokota/* Performs in-place initialization of a dyn_string struct.  This
5842504Syokota   function can be used with a dyn_string struct on the stack or
5942504Syokota   embedded in another object.  The contents of of the string itself
6042504Syokota   are still dynamically allocated.  The string initially is capable
6142504Syokota   of holding at least SPACE characeters, including the terminating
62117710Srobert   NUL.  If SPACE is 0, it will silently be increated to 1.
63117710Srobert
6442504Syokota   If RETURN_ON_ALLOCATION_FAILURE is defined and memory allocation
6542611Syokota   fails, returns 0.  Otherwise returns 1.  */
6642504Syokota
6742504Syokotaint
6839287Ssosdyn_string_init (ds_struct_ptr, space)
6939287Ssos     struct dyn_string *ds_struct_ptr;
7039287Ssos     int space;
7139287Ssos{
7239287Ssos  /* We need at least one byte in which to store the terminating NUL.  */
7339287Ssos  if (space == 0)
7439287Ssos    space = 1;
7539287Ssos
7639287Ssos#ifdef RETURN_ON_ALLOCATION_FAILURE
7739287Ssos  ds_struct_ptr->s = (char *) malloc (space);
7839287Ssos  if (ds_struct_ptr->s == NULL)
7939287Ssos    return 0;
8039287Ssos#else
8148399Speter  ds_struct_ptr->s = (char *) xmalloc (space);
8242504Syokota#endif
8348399Speter  ds_struct_ptr->allocated = space;
8448104Syokota  ds_struct_ptr->length = 0;
8542504Syokota  ds_struct_ptr->s[0] = '\0';
8639287Ssos
8739287Ssos  return 1;
8839287Ssos}
8939287Ssos
9039287Ssos/* Create a new dynamic string capable of holding at least SPACE
9139287Ssos   characters, including the terminating NUL.  If SPACE is 0, it will
9239287Ssos   be silently increased to 1.  If RETURN_ON_ALLOCATION_FAILURE is
9339287Ssos   defined and memory allocation fails, returns NULL.  Otherwise
9439287Ssos   returns the newly allocated string.  */
9539287Ssos
9639287Ssosdyn_string_t
9739287Ssosdyn_string_new (space)
9839287Ssos     int space;
9939287Ssos{
10039287Ssos  dyn_string_t result;
10142504Syokota#ifdef RETURN_ON_ALLOCATION_FAILURE
10248104Syokota  result = (dyn_string_t) malloc (sizeof (struct dyn_string));
10342504Syokota  if (result == NULL)
10448104Syokota    return NULL;
10548104Syokota  if (!dyn_string_init (result, space))
10648104Syokota    {
10748104Syokota      free (result);
10839287Ssos      return NULL;
10948104Syokota    }
11044846Sjlemon#else
11139287Ssos  result = (dyn_string_t) xmalloc (sizeof (struct dyn_string));
11242504Syokota  dyn_string_init (result, space);
11342504Syokota#endif
11442504Syokota  return result;
11542504Syokota}
11642504Syokota
11742504Syokota/* Free the memory used by DS.  */
11842504Syokota
11942504Syokotavoid
12042504Syokotadyn_string_delete (ds)
12142504Syokota     dyn_string_t ds;
12242504Syokota{
12342504Syokota  free (ds->s);
12442504Syokota  free (ds);
12542504Syokota}
12642504Syokota
12742504Syokota/* Returns the contents of DS in a buffer allocated with malloc.  It
12842504Syokota   is the caller's responsibility to deallocate the buffer using free.
12942504Syokota   DS is then set to the empty string.  Deletes DS itself.  */
13048104Syokota
13142504Syokotachar*
13248104Syokotadyn_string_release (ds)
13348104Syokota     dyn_string_t ds;
13448104Syokota{
13548104Syokota  /* Store the old buffer.  */
13648104Syokota  char* result = ds->s;
13748104Syokota  /* The buffer is no longer owned by DS.  */
13839287Ssos  ds->s = NULL;
13939287Ssos  /* Delete DS.  */
14039287Ssos  free (ds);
14142504Syokota  /* Return the old buffer.  */
14239287Ssos  return result;
14339287Ssos}
14439287Ssos
14539287Ssos/* Increase the capacity of DS so it can hold at least SPACE
14639287Ssos   characters, plus the terminating NUL.  This function will not (at
14739287Ssos   present) reduce the capacity of DS.  Returns DS on success.
14848104Syokota
14939287Ssos   If RETURN_ON_ALLOCATION_FAILURE is defined and a memory allocation
15048104Syokota   operation fails, deletes DS and returns NULL.  */
15148104Syokota
15248104Syokotadyn_string_t
15348104Syokotadyn_string_resize (ds, space)
15439287Ssos     dyn_string_t ds;
15539287Ssos     int space;
15639287Ssos{
15739287Ssos  int new_allocated = ds->allocated;
15839858Syokota
15939858Syokota  /* Increase SPACE to hold the NUL termination.  */
16039858Syokota  ++space;
16139858Syokota
16239287Ssos  /* Increase allocation by factors of two.  */
16339287Ssos  while (space > new_allocated)
16439287Ssos    new_allocated *= 2;
16539287Ssos
16642504Syokota  if (new_allocated != ds->allocated)
16739287Ssos    {
16839287Ssos      ds->allocated = new_allocated;
16945117Syokota      /* We actually need more space.  */
17039287Ssos#ifdef RETURN_ON_ALLOCATION_FAILURE
17142729Syokota      ds->s = (char *) realloc (ds->s, ds->allocated);
17242729Syokota      if (ds->s == NULL)
17348104Syokota	{
17448104Syokota	  free (ds);
17542729Syokota	  return NULL;
17642729Syokota	}
17748399Speter#else
17848104Syokota      ds->s = (char *) xrealloc (ds->s, ds->allocated);
17948104Syokota#endif
18048399Speter    }
18139287Ssos
18239287Ssos  return ds;
18339287Ssos}
18439287Ssos
18539287Ssos/* Sets the contents of DS to the empty string.  */
18639287Ssos
18739287Ssosvoid
18839287Ssosdyn_string_clear (ds)
18939287Ssos     dyn_string_t ds;
190142830Siedowse{
19139287Ssos  /* A dyn_string always has room for at least the NUL terminator.  */
19239287Ssos  ds->s[0] = '\0';
19343664Syokota  ds->length = 0;
19450446Syokota}
19548399Speter
19648104Syokota/* Makes the contents of DEST the same as the contents of SRC.  DEST
19748399Speter   and SRC must be distinct.  Returns 1 on success.  On failure, if
19848104Syokota   RETURN_ON_ALLOCATION_FAILURE, deletes DEST and returns 0.  */
19939591Syokota
20039591Syokotaint
20148104Syokotadyn_string_copy (dest, src)
20239858Syokota     dyn_string_t dest;
20339858Syokota     dyn_string_t src;
20439287Ssos{
20539591Syokota  if (dest == src)
20648104Syokota    abort ();
20748104Syokota
20839287Ssos  /* Make room in DEST.  */
20948399Speter  if (dyn_string_resize (dest, src->length) == NULL)
21048104Syokota    return 0;
21148399Speter  /* Copy DEST into SRC.  */
21248104Syokota  strcpy (dest->s, src->s);
21339287Ssos  /* Update the size of DEST.  */
21439287Ssos  dest->length = src->length;
21539287Ssos  return 1;
21639287Ssos}
21739287Ssos
21839287Ssos/* Copies SRC, a NUL-terminated string, into DEST.  Returns 1 on
21939287Ssos   success.  On failure, if RETURN_ON_ALLOCATION_FAILURE, deletes DEST
22039287Ssos   and returns 0.  */
22139287Ssos
22239287Ssosint
22339287Ssosdyn_string_copy_cstr (dest, src)
22439287Ssos     dyn_string_t dest;
22542504Syokota     const char *src;
22642504Syokota{
22742504Syokota  int length = strlen (src);
22842504Syokota  /* Make room in DEST.  */
22942504Syokota  if (dyn_string_resize (dest, length) == NULL)
23042504Syokota    return 0;
23142504Syokota  /* Copy DEST into SRC.  */
23242504Syokota  strcpy (dest->s, src);
23342504Syokota  /* Update the size of DEST.  */
23442504Syokota  dest->length = length;
23542504Syokota  return 1;
23642504Syokota}
23739287Ssos
23839287Ssos/* Inserts SRC at the beginning of DEST.  DEST is expanded as
23939287Ssos   necessary.  SRC and DEST must be distinct.  Returns 1 on success.
24039287Ssos   On failure, if RETURN_ON_ALLOCATION_FAILURE, deletes DEST and
24139287Ssos   returns 0.  */
24244846Sjlemon
24339287Ssosint
24439287Ssosdyn_string_prepend (dest, src)
24539287Ssos     dyn_string_t dest;
24639287Ssos     dyn_string_t src;
24739287Ssos{
24844846Sjlemon  return dyn_string_insert (dest, 0, src);
24944866Sjlemon}
25044846Sjlemon
25144846Sjlemon/* Inserts SRC, a NUL-terminated string, at the beginning of DEST.
25250445Syokota   DEST is expanded as necessary.  Returns 1 on success.  On failure,
25339287Ssos   if RETURN_ON_ALLOCATION_FAILURE, deletes DEST and returns 0. */
25439287Ssos
25539287Ssosint
25639287Ssosdyn_string_prepend_cstr (dest, src)
25739287Ssos     dyn_string_t dest;
25839287Ssos     const char *src;
25939287Ssos{
26039287Ssos  return dyn_string_insert_cstr (dest, 0, src);
26139287Ssos}
26239287Ssos
26339287Ssos/* Inserts SRC into DEST starting at position POS.  DEST is expanded
26439287Ssos   as necessary.  SRC and DEST must be distinct.  Returns 1 on
26539287Ssos   success.  On failure, if RETURN_ON_ALLOCATION_FAILURE, deletes DEST
26639287Ssos   and returns 0.  */
26739287Ssos
26850445Syokotaint
26939287Ssosdyn_string_insert (dest, pos, src)
27039287Ssos     dyn_string_t dest;
27139287Ssos     int pos;
27245117Syokota     dyn_string_t src;
27345117Syokota{
27445117Syokota  int i;
27545117Syokota
27645117Syokota  if (src == dest)
27745117Syokota    abort ();
27845117Syokota
27945117Syokota  if (dyn_string_resize (dest, dest->length + src->length) == NULL)
28045117Syokota    return 0;
28150445Syokota  /* Make room for the insertion.  Be sure to copy the NUL.  */
28245117Syokota  for (i = dest->length; i >= pos; --i)
28345117Syokota    dest->s[i + src->length] = dest->s[i];
28445117Syokota  /* Splice in the new stuff.  */
28545117Syokota  strncpy (dest->s + pos, src->s, src->length);
28645117Syokota  /* Compute the new length.  */
28739287Ssos  dest->length += src->length;
28839287Ssos  return 1;
28939287Ssos}
29039287Ssos
29139287Ssos/* Inserts SRC, a NUL-terminated string, into DEST starting at
29239287Ssos   position POS.  DEST is expanded as necessary.  Returns 1 on
29339287Ssos   success.  On failure, RETURN_ON_ALLOCATION_FAILURE, deletes DEST
29439287Ssos   and returns 0.  */
29539287Ssos
29650445Syokotaint
29742729Syokotadyn_string_insert_cstr (dest, pos, src)
29842729Syokota     dyn_string_t dest;
29939287Ssos     int pos;
30039287Ssos     const char *src;
30139287Ssos{
30242729Syokota  int i;
30339287Ssos  int length = strlen (src);
30439287Ssos
30539287Ssos  if (dyn_string_resize (dest, dest->length + length) == NULL)
30639287Ssos    return 0;
30739287Ssos  /* Make room for the insertion.  Be sure to copy the NUL.  */
30839287Ssos  for (i = dest->length; i >= pos; --i)
30939287Ssos    dest->s[i + length] = dest->s[i];
31039287Ssos  /* Splice in the new stuff.  */
31139287Ssos  strncpy (dest->s + pos, src, length);
31239287Ssos  /* Compute the new length.  */
31339287Ssos  dest->length += length;
31444846Sjlemon  return 1;
31544866Sjlemon}
31644846Sjlemon
31744846Sjlemon/* Inserts character C into DEST starting at position POS.  DEST is
31850445Syokota   expanded as necessary.  Returns 1 on success.  On failure,
31939287Ssos   RETURN_ON_ALLOCATION_FAILURE, deletes DEST and returns 0.  */
32039287Ssos
32142729Syokotaint
32239287Ssosdyn_string_insert_char (dest, pos, c)
32342729Syokota     dyn_string_t dest;
32442729Syokota     int pos;
32542729Syokota     int c;
32639287Ssos{
32739287Ssos  int i;
32839287Ssos
32939287Ssos  if (dyn_string_resize (dest, dest->length + 1) == NULL)
33039287Ssos    return 0;
33148104Syokota  /* Make room for the insertion.  Be sure to copy the NUL.  */
33248104Syokota  for (i = dest->length; i >= pos; --i)
33348104Syokota    dest->s[i + 1] = dest->s[i];
33448104Syokota  /* Add the new character.  */
33548104Syokota  dest->s[pos] = c;
33648104Syokota  /* Compute the new length.  */
33748104Syokota  ++dest->length;
33848104Syokota  return 1;
33948104Syokota}
34048104Syokota
34148104Syokota/* Append S to DS, resizing DS if necessary.  Returns 1 on success.
34248104Syokota   On failure, if RETURN_ON_ALLOCATION_FAILURE, deletes DEST and
34348104Syokota   returns 0.  */
34448104Syokota
34548104Syokotaint
34648104Syokotadyn_string_append (dest, s)
34748104Syokota     dyn_string_t dest;
34850445Syokota     dyn_string_t s;
34948104Syokota{
35048104Syokota  if (dyn_string_resize (dest, dest->length + s->length) == 0)
35148104Syokota    return 0;
35248104Syokota  strcpy (dest->s + dest->length, s->s);
35348104Syokota  dest->length += s->length;
35448104Syokota  return 1;
35548104Syokota}
35648104Syokota
35748104Syokota/* Append the NUL-terminated string S to DS, resizing DS if necessary.
35848104Syokota   Returns 1 on success.  On failure, if RETURN_ON_ALLOCATION_FAILURE,
35948104Syokota   deletes DEST and returns 0.  */
36048104Syokota
36142729Syokotaint
36239287Ssosdyn_string_append_cstr (dest, s)
36339287Ssos     dyn_string_t dest;
36439287Ssos     const char *s;
36539287Ssos{
36639287Ssos  int len = strlen (s);
36739287Ssos
36844846Sjlemon  /* The new length is the old length plus the size of our string, plus
36942729Syokota     one for the null at the end.  */
37039287Ssos  if (dyn_string_resize (dest, dest->length + len) == NULL)
37142729Syokota    return 0;
37242729Syokota  strcpy (dest->s + dest->length, s);
37342729Syokota  dest->length += len;
37442729Syokota  return 1;
37539287Ssos}
37639287Ssos
37739287Ssos/* Appends C to the end of DEST.  Returns 1 on success.  On failiure,
37839287Ssos   if RETURN_ON_ALLOCATION_FAILURE, deletes DEST and returns 0.  */
37939287Ssos
38039287Ssosint
38139287Ssosdyn_string_append_char (dest, c)
38244866Sjlemon     dyn_string_t dest;
38344846Sjlemon     int c;
38444846Sjlemon{
38550445Syokota  /* Make room for the extra character.  */
38639287Ssos  if (dyn_string_resize (dest, dest->length + 1) == NULL)
38739287Ssos    return 0;
38848399Speter  /* Append the character; it will overwrite the old NUL.  */
38939287Ssos  dest->s[dest->length] = c;
39048104Syokota  /* Add a new NUL at the end.  */
39148104Syokota  dest->s[dest->length + 1] = '\0';
39248104Syokota  /* Update the length.  */
39348104Syokota  ++(dest->length);
39448104Syokota  return 1;
39548104Syokota}
39648104Syokota
39748104Syokota/* Sets the contents of DEST to the substring of SRC starting at START
39848104Syokota   and ending before END.  START must be less than or equal to END,
39948104Syokota   and both must be between zero and the length of SRC, inclusive.
40048104Syokota   Returns 1 on success.  On failure, if RETURN_ON_ALLOCATION_FAILURE,
40148104Syokota   deletes DEST and returns 0.  */
40248104Syokota
40348104Syokotaint
40448104Syokotadyn_string_substring (dest, src, start, end)
40548104Syokota     dyn_string_t dest;
40648104Syokota     dyn_string_t src;
40748104Syokota     int start;
40848104Syokota     int end;
40948104Syokota{
41048104Syokota  int i;
41148104Syokota  int length = end - start;
41248104Syokota
41348104Syokota  if (start > end || start > src->length || end > src->length)
41448104Syokota    abort ();
41550445Syokota
41648104Syokota  /* Make room for the substring.  */
41748399Speter  if (dyn_string_resize (dest, length) == NULL)
41848104Syokota    return 0;
41948104Syokota  /* Copy the characters in the substring,  */
42039287Ssos  for (i = length; --i >= 0; )
42139287Ssos    dest->s[i] = src->s[start + i];
42239287Ssos  /* NUL-terimate the result.  */
42339287Ssos  dest->s[length] = '\0';
42439287Ssos  /* Record the length of the substring.  */
42539287Ssos  dest->length = length;
42639287Ssos
427142830Siedowse  return 1;
42839287Ssos}
42939287Ssos
43050445Syokota/* Returns non-zero if DS1 and DS2 have the same contents.  */
43139287Ssos
43250445Syokotaint
43339287Ssosdyn_string_eq (ds1, ds2)
43439287Ssos     dyn_string_t ds1;
43539287Ssos     dyn_string_t ds2;
43639287Ssos{
43739287Ssos  /* If DS1 and DS2 have different lengths, they must not be the same.  */
43839287Ssos  if (ds1->length != ds2->length)
43944846Sjlemon    return 0;
44039287Ssos  else
44139287Ssos    return !strcmp (ds1->s, ds2->s);
442142830Siedowse}
443142830Siedowse