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