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