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