123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398 |
- /* An abstract string datatype.
- Copyright (C) 1998, 1999, 2000, 2002, 2004 Free Software Foundation, Inc.
- Contributed by Mark Mitchell (mark@markmitchell.com).
- This file is part of GNU CC.
-
- GNU CC is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
- In addition to the permissions in the GNU General Public License, the
- Free Software Foundation gives you unlimited permission to link the
- compiled version of this file into combinations with other programs,
- and to distribute those combinations without any restriction coming
- from the use of this file. (The General Public License restrictions
- do apply in other respects; for example, they cover modification of
- the file, and distribution when not linked into a combined
- executable.)
- GNU CC is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with GNU CC; see the file COPYING. If not, write to
- the Free Software Foundation, 51 Franklin Street - Fifth Floor,
- Boston, MA 02110-1301, USA. */
- #ifdef HAVE_CONFIG_H
- #include "config.h"
- #endif
- #include <stdio.h>
- #ifdef HAVE_STRING_H
- #include <string.h>
- #endif
- #ifdef HAVE_STDLIB_H
- #include <stdlib.h>
- #endif
- #include "libiberty.h"
- #include "dyn-string.h"
- /* Performs in-place initialization of a dyn_string struct. This
- function can be used with a dyn_string struct on the stack or
- embedded in another object. The contents of of the string itself
- are still dynamically allocated. The string initially is capable
- of holding at least SPACE characeters, including the terminating
- NUL. If SPACE is 0, it will silently be increated to 1.
- If RETURN_ON_ALLOCATION_FAILURE is defined and memory allocation
- fails, returns 0. Otherwise returns 1. */
- int
- dyn_string_init (struct dyn_string *ds_struct_ptr, int space)
- {
- /* We need at least one byte in which to store the terminating NUL. */
- if (space == 0)
- space = 1;
- #ifdef RETURN_ON_ALLOCATION_FAILURE
- ds_struct_ptr->s = (char *) malloc (space);
- if (ds_struct_ptr->s == NULL)
- return 0;
- #else
- ds_struct_ptr->s = XNEWVEC (char, space);
- #endif
- ds_struct_ptr->allocated = space;
- ds_struct_ptr->length = 0;
- ds_struct_ptr->s[0] = '\0';
- return 1;
- }
- /* Create a new dynamic string capable of holding at least SPACE
- characters, including the terminating NUL. If SPACE is 0, it will
- be silently increased to 1. If RETURN_ON_ALLOCATION_FAILURE is
- defined and memory allocation fails, returns NULL. Otherwise
- returns the newly allocated string. */
- dyn_string_t
- dyn_string_new (int space)
- {
- dyn_string_t result;
- #ifdef RETURN_ON_ALLOCATION_FAILURE
- result = (dyn_string_t) malloc (sizeof (struct dyn_string));
- if (result == NULL)
- return NULL;
- if (!dyn_string_init (result, space))
- {
- free (result);
- return NULL;
- }
- #else
- result = XNEW (struct dyn_string);
- dyn_string_init (result, space);
- #endif
- return result;
- }
- /* Free the memory used by DS. */
- void
- dyn_string_delete (dyn_string_t ds)
- {
- free (ds->s);
- free (ds);
- }
- /* Returns the contents of DS in a buffer allocated with malloc. It
- is the caller's responsibility to deallocate the buffer using free.
- DS is then set to the empty string. Deletes DS itself. */
- char*
- dyn_string_release (dyn_string_t ds)
- {
- /* Store the old buffer. */
- char* result = ds->s;
- /* The buffer is no longer owned by DS. */
- ds->s = NULL;
- /* Delete DS. */
- free (ds);
- /* Return the old buffer. */
- return result;
- }
- /* Increase the capacity of DS so it can hold at least SPACE
- characters, plus the terminating NUL. This function will not (at
- present) reduce the capacity of DS. Returns DS on success.
- If RETURN_ON_ALLOCATION_FAILURE is defined and a memory allocation
- operation fails, deletes DS and returns NULL. */
- dyn_string_t
- dyn_string_resize (dyn_string_t ds, int space)
- {
- int new_allocated = ds->allocated;
- /* Increase SPACE to hold the NUL termination. */
- ++space;
- /* Increase allocation by factors of two. */
- while (space > new_allocated)
- new_allocated *= 2;
-
- if (new_allocated != ds->allocated)
- {
- ds->allocated = new_allocated;
- /* We actually need more space. */
- #ifdef RETURN_ON_ALLOCATION_FAILURE
- ds->s = (char *) realloc (ds->s, ds->allocated);
- if (ds->s == NULL)
- {
- free (ds);
- return NULL;
- }
- #else
- ds->s = XRESIZEVEC (char, ds->s, ds->allocated);
- #endif
- }
- return ds;
- }
- /* Sets the contents of DS to the empty string. */
- void
- dyn_string_clear (dyn_string_t ds)
- {
- /* A dyn_string always has room for at least the NUL terminator. */
- ds->s[0] = '\0';
- ds->length = 0;
- }
- /* Makes the contents of DEST the same as the contents of SRC. DEST
- and SRC must be distinct. Returns 1 on success. On failure, if
- RETURN_ON_ALLOCATION_FAILURE, deletes DEST and returns 0. */
- int
- dyn_string_copy (dyn_string_t dest, dyn_string_t src)
- {
- if (dest == src)
- abort ();
- /* Make room in DEST. */
- if (dyn_string_resize (dest, src->length) == NULL)
- return 0;
- /* Copy DEST into SRC. */
- strcpy (dest->s, src->s);
- /* Update the size of DEST. */
- dest->length = src->length;
- return 1;
- }
- /* Copies SRC, a NUL-terminated string, into DEST. Returns 1 on
- success. On failure, if RETURN_ON_ALLOCATION_FAILURE, deletes DEST
- and returns 0. */
- int
- dyn_string_copy_cstr (dyn_string_t dest, const char *src)
- {
- int length = strlen (src);
- /* Make room in DEST. */
- if (dyn_string_resize (dest, length) == NULL)
- return 0;
- /* Copy DEST into SRC. */
- strcpy (dest->s, src);
- /* Update the size of DEST. */
- dest->length = length;
- return 1;
- }
- /* Inserts SRC at the beginning of DEST. DEST is expanded as
- necessary. SRC and DEST must be distinct. Returns 1 on success.
- On failure, if RETURN_ON_ALLOCATION_FAILURE, deletes DEST and
- returns 0. */
- int
- dyn_string_prepend (dyn_string_t dest, dyn_string_t src)
- {
- return dyn_string_insert (dest, 0, src);
- }
- /* Inserts SRC, a NUL-terminated string, at the beginning of DEST.
- DEST is expanded as necessary. Returns 1 on success. On failure,
- if RETURN_ON_ALLOCATION_FAILURE, deletes DEST and returns 0. */
- int
- dyn_string_prepend_cstr (dyn_string_t dest, const char *src)
- {
- return dyn_string_insert_cstr (dest, 0, src);
- }
- /* Inserts SRC into DEST starting at position POS. DEST is expanded
- as necessary. SRC and DEST must be distinct. Returns 1 on
- success. On failure, if RETURN_ON_ALLOCATION_FAILURE, deletes DEST
- and returns 0. */
- int
- dyn_string_insert (dyn_string_t dest, int pos, dyn_string_t src)
- {
- int i;
- if (src == dest)
- abort ();
- if (dyn_string_resize (dest, dest->length + src->length) == NULL)
- return 0;
- /* Make room for the insertion. Be sure to copy the NUL. */
- for (i = dest->length; i >= pos; --i)
- dest->s[i + src->length] = dest->s[i];
- /* Splice in the new stuff. */
- strncpy (dest->s + pos, src->s, src->length);
- /* Compute the new length. */
- dest->length += src->length;
- return 1;
- }
- /* Inserts SRC, a NUL-terminated string, into DEST starting at
- position POS. DEST is expanded as necessary. Returns 1 on
- success. On failure, RETURN_ON_ALLOCATION_FAILURE, deletes DEST
- and returns 0. */
- int
- dyn_string_insert_cstr (dyn_string_t dest, int pos, const char *src)
- {
- int i;
- int length = strlen (src);
- if (dyn_string_resize (dest, dest->length + length) == NULL)
- return 0;
- /* Make room for the insertion. Be sure to copy the NUL. */
- for (i = dest->length; i >= pos; --i)
- dest->s[i + length] = dest->s[i];
- /* Splice in the new stuff. */
- strncpy (dest->s + pos, src, length);
- /* Compute the new length. */
- dest->length += length;
- return 1;
- }
- /* Inserts character C into DEST starting at position POS. DEST is
- expanded as necessary. Returns 1 on success. On failure,
- RETURN_ON_ALLOCATION_FAILURE, deletes DEST and returns 0. */
- int
- dyn_string_insert_char (dyn_string_t dest, int pos, int c)
- {
- int i;
- if (dyn_string_resize (dest, dest->length + 1) == NULL)
- return 0;
- /* Make room for the insertion. Be sure to copy the NUL. */
- for (i = dest->length; i >= pos; --i)
- dest->s[i + 1] = dest->s[i];
- /* Add the new character. */
- dest->s[pos] = c;
- /* Compute the new length. */
- ++dest->length;
- return 1;
- }
-
- /* Append S to DS, resizing DS if necessary. Returns 1 on success.
- On failure, if RETURN_ON_ALLOCATION_FAILURE, deletes DEST and
- returns 0. */
- int
- dyn_string_append (dyn_string_t dest, dyn_string_t s)
- {
- if (dyn_string_resize (dest, dest->length + s->length) == 0)
- return 0;
- strcpy (dest->s + dest->length, s->s);
- dest->length += s->length;
- return 1;
- }
- /* Append the NUL-terminated string S to DS, resizing DS if necessary.
- Returns 1 on success. On failure, if RETURN_ON_ALLOCATION_FAILURE,
- deletes DEST and returns 0. */
- int
- dyn_string_append_cstr (dyn_string_t dest, const char *s)
- {
- int len = strlen (s);
- /* The new length is the old length plus the size of our string, plus
- one for the null at the end. */
- if (dyn_string_resize (dest, dest->length + len) == NULL)
- return 0;
- strcpy (dest->s + dest->length, s);
- dest->length += len;
- return 1;
- }
- /* Appends C to the end of DEST. Returns 1 on success. On failure,
- if RETURN_ON_ALLOCATION_FAILURE, deletes DEST and returns 0. */
- int
- dyn_string_append_char (dyn_string_t dest, int c)
- {
- /* Make room for the extra character. */
- if (dyn_string_resize (dest, dest->length + 1) == NULL)
- return 0;
- /* Append the character; it will overwrite the old NUL. */
- dest->s[dest->length] = c;
- /* Add a new NUL at the end. */
- dest->s[dest->length + 1] = '\0';
- /* Update the length. */
- ++(dest->length);
- return 1;
- }
- /* Sets the contents of DEST to the substring of SRC starting at START
- and ending before END. START must be less than or equal to END,
- and both must be between zero and the length of SRC, inclusive.
- Returns 1 on success. On failure, if RETURN_ON_ALLOCATION_FAILURE,
- deletes DEST and returns 0. */
- int
- dyn_string_substring (dyn_string_t dest, dyn_string_t src,
- int start, int end)
- {
- int i;
- int length = end - start;
- if (start > end || start > src->length || end > src->length)
- abort ();
- /* Make room for the substring. */
- if (dyn_string_resize (dest, length) == NULL)
- return 0;
- /* Copy the characters in the substring, */
- for (i = length; --i >= 0; )
- dest->s[i] = src->s[start + i];
- /* NUL-terimate the result. */
- dest->s[length] = '\0';
- /* Record the length of the substring. */
- dest->length = length;
- return 1;
- }
- /* Returns non-zero if DS1 and DS2 have the same contents. */
- int
- dyn_string_eq (dyn_string_t ds1, dyn_string_t ds2)
- {
- /* If DS1 and DS2 have different lengths, they must not be the same. */
- if (ds1->length != ds2->length)
- return 0;
- else
- return !strcmp (ds1->s, ds2->s);
- }
|