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