xref: /Universal-ctags/main/vstring.c (revision 5b7dabdafafb78b5994c6dbab21b4d859d2c8202)
1 /*
2 *   Copyright (c) 1998-2002, Darren Hiebert
3 *
4 *   This source code is released for free distribution under the terms of the
5 *   GNU General Public License version 2 or (at your option) any later version.
6 *
7 *   This module contains functions supporting resizeable strings.
8 */
9 
10 /*
11 *   INCLUDE FILES
12 */
13 #include "general.h"  /* must always come first */
14 
15 #include <limits.h>  /* to define INT_MAX */
16 #include <string.h>
17 #include <ctype.h>
18 
19 #include "debug.h"
20 #include "routines.h"
21 #include "vstring.h"
22 #include "trashbox.h"
23 
24 /*
25 *   DATA DEFINITIONS
26 */
27 static const size_t vStringInitialSize = 32;
28 
29 /*
30 *   FUNCTION DEFINITIONS
31 */
32 
33 /*
34 *   External interface
35 */
36 
vStringResize(vString * const string,const size_t newSize)37 extern void vStringResize (vString *const string, const size_t newSize)
38 {
39 	size_t size = vStringInitialSize;
40 
41 	while (size < newSize)
42 		size *= 2;
43 
44 	if (size > string->size)
45 	{
46 		string->size = size;
47 		string->buffer = xRealloc (string->buffer, size, char);
48 	}
49 }
50 
vStringTruncate(vString * const string,const size_t length)51 extern void vStringTruncate (vString *const string, const size_t length)
52 {
53 	Assert (length <= string->length);
54 	string->length = length;
55 	string->buffer[string->length] = '\0';
56 	DebugStatement ( memset (string->buffer + string->length, 0,
57 	                         string->size - string->length); )
58 }
59 
vStringDelete(vString * const string)60 extern void vStringDelete (vString *const string)
61 {
62 	if (string != NULL)
63 	{
64 		if (string->buffer != NULL)
65 			eFree (string->buffer);
66 		eFree (string);
67 	}
68 }
69 
vStringNew(void)70 extern vString *vStringNew (void)
71 {
72 	vString *const string = xMalloc (1, vString);
73 
74 	string->length = 0;
75 	string->size   = vStringInitialSize;
76 	string->buffer = xMalloc (string->size, char);
77 
78 	vStringClear (string);
79 
80 	return string;
81 }
82 
vStringNewCopy(const vString * const string)83 extern vString *vStringNewCopy (const vString *const string)
84 {
85 	vString *vs = vStringNew ();
86 	vStringCatS (vs, string->buffer);
87 	return vs;
88 }
89 
vStringNewInit(const char * const s)90 extern vString *vStringNewInit (const char *const s)
91 {
92 	vString *vs = vStringNew ();
93 	vStringCatS (vs, s);
94 	return vs;
95 }
96 
vStringNewNInit(const char * const s,const size_t length)97 extern vString *vStringNewNInit (const char *const s, const size_t length)
98 {
99 	vString *vs = vStringNew ();
100 	vStringNCatS (vs, s, length);
101 	return vs;
102 }
103 
stringCat(vString * const string,const char * const s,const size_t length)104 static void stringCat (
105 		vString *const string, const char *const s, const size_t length)
106 {
107 	if (string->length + length + 1 > string->size)
108 		vStringResize (string, string->length + length + 1);
109 
110 	memcpy (string->buffer + string->length, s, length);
111 	string->length += length;
112 	vStringPut (string, '\0');
113 }
114 
vStringNCat(vString * const string,const vString * const s,const size_t length)115 extern void vStringNCat (
116 		vString *const string, const vString *const s, const size_t length)
117 {
118 	size_t len = vStringLength (s);
119 
120 	len = len < length ? len: length;
121 	stringCat (string, s->buffer, len);
122 }
123 
vStringNCatS(vString * const string,const char * const s,const size_t length)124 extern void vStringNCatS (
125 		vString *const string, const char *const s, const size_t length)
126 {
127 	size_t len = strlen (s);
128 
129 	len = len < length ? len : length;
130 	stringCat (string, s, len);
131 }
132 
vStringNCatSUnsafe(vString * const string,const char * const s,const size_t length)133 extern void vStringNCatSUnsafe (
134 		vString *const string, const char *const s, const size_t length)
135 {
136 	stringCat (string, s, length);
137 }
138 
vStringCat(vString * const string,const vString * const s)139 extern void vStringCat (vString *const string, const vString *const s)
140 {
141 	size_t len = vStringLength (s);
142 
143 	stringCat (string, s->buffer, len);
144 }
145 
vStringCatS(vString * const string,const char * const s)146 extern void vStringCatS (vString *const string, const char *const s)
147 {
148 	size_t len = strlen (s);
149 
150 	stringCat (string, s, len);
151 }
152 
153 /*  Strip trailing newline from string.
154  */
vStringStripNewline(vString * const string)155 extern bool vStringStripNewline (vString *const string)
156 {
157 	const size_t final = string->length - 1;
158 
159 	if (string->length == 0)
160 		return false;
161 
162 	if (string->buffer [final] == '\n')
163 	{
164 		string->buffer [final] = '\0';
165 		string->length--;
166 		return true;
167 	}
168 
169 	return false;
170 }
171 
172 /*  Strip leading white space from string.
173  */
vStringStripLeading(vString * const string)174 extern void vStringStripLeading (vString *const string)
175 {
176 	size_t n = 0;
177 
178 	while (n < string->length && isspace ((int) string->buffer [n]))
179 		n++;
180 	if (n > 0)
181 	{
182 		memmove (string->buffer, string->buffer + n, string->length - n);
183 		vStringTruncate (string, string->length - n);
184 	}
185 }
186 
187 /*  Strip trailing white space from string.
188  */
vStringStripTrailing(vString * const string)189 extern void vStringStripTrailing (vString *const string)
190 {
191 	while (string->length > 0 &&
192 		   isspace ((int) string->buffer [string->length - 1]))
193 	{
194 		string->length--;
195 		string->buffer [string->length] = '\0';
196 	}
197 }
198 
199 /*  Chop last character from string.
200  */
vStringChop(vString * const string)201 extern void vStringChop (vString *const string)
202 {
203 	if (string->length > 0)
204 	{
205 		--string->length;
206 		string->buffer [string->length] = '\0';
207 	}
208 }
209 
vStringCopy(vString * const string,const vString * const s)210 extern void vStringCopy (vString *const string, const vString *const s)
211 {
212 	vStringClear (string);
213 	vStringCat (string, s);
214 }
215 
vStringCopyS(vString * const string,const char * const s)216 extern void vStringCopyS (vString *const string, const char *const s)
217 {
218 	vStringClear (string);
219 	vStringCatS (string, s);
220 }
221 
vStringNCopy(vString * const string,const vString * const s,const size_t length)222 extern void vStringNCopy (
223 		vString *const string, const vString *const s, const size_t length)
224 {
225 	vStringClear (string);
226 	vStringNCat (string, s, length);
227 }
228 
vStringNCopyS(vString * const string,const char * const s,const size_t length)229 extern void vStringNCopyS (
230 		vString *const string, const char *const s, const size_t length)
231 {
232 	vStringClear (string);
233 	vStringNCatS (string, s, length);
234 }
235 
vStringCopyToLower(vString * const dest,const vString * const src)236 extern void vStringCopyToLower (vString *const dest, const vString *const src)
237 {
238 	const size_t length = src->length;
239 	const char *s = src->buffer;
240 	char *d;
241 	size_t i;
242 
243 	if (dest->size < src->size)
244 		vStringResize (dest, src->size);
245 	d = dest->buffer;
246 	for (i = 0  ;  i < length  ;  ++i)
247 	{
248 		int c = s [i];
249 
250 		d [i] = tolower (c);
251 	}
252 	d [i] = '\0';
253 }
254 
vStringSetLength(vString * const string)255 extern void vStringSetLength (vString *const string)
256 {
257 	string->length = strlen (string->buffer);
258 }
259 
vStringNewOwn(char * s)260 extern vString *vStringNewOwn (char *s)
261 {
262 	vString *r;
263 
264 	r = vStringNewInit (s);
265 	eFree (s);
266 
267 	return r;
268 }
269 
vStringDeleteUnwrap(vString * const string)270 extern char    *vStringDeleteUnwrap       (vString *const string)
271 {
272 	char *buffer = NULL;
273 
274 
275 	if (string != NULL)
276 	{
277 		buffer = string->buffer;
278 		string->buffer = NULL;
279 
280 		string->size = 0;
281 		string->length = 0;
282 
283 		eFree (string);
284 	}
285 
286 	return buffer;
287 }
288 
vStringStrdup(const vString * const string)289 extern char    *vStringStrdup (const vString *const string)
290 {
291 	char *str = xMalloc (vStringLength(string) + 1, char);
292 	str[vStringLength(string)] = '\0';
293 	memcpy (str, string->buffer, vStringLength(string));
294 	return str;
295 }
296 
valueToXDigit(int v)297 static char valueToXDigit (int v)
298 {
299 	Assert (v >= 0 && v <= 0xF);
300 
301 	if (v >= 0xA)
302 		return 'A' + (v - 0xA);
303 	else
304 		return '0' + v;
305 }
306 
vStringCatSWithEscaping(vString * b,const char * s)307 extern void vStringCatSWithEscaping (vString* b, const char *s)
308 {
309 	for(; *s; s++)
310 	{
311 		int c = *s;
312 
313 		/* escape control characters (incl. \t) */
314 		if ((c > 0x00 && c <= 0x1F) || c == 0x7F || c == '\\')
315 		{
316 			vStringPut (b, '\\');
317 
318 			switch (c)
319 			{
320 				/* use a short form for known escapes */
321 			case '\a':
322 				c = 'a'; break;
323 			case '\b':
324 				c = 'b'; break;
325 			case '\t':
326 				c = 't'; break;
327 			case '\n':
328 				c = 'n'; break;
329 			case '\v':
330 				c = 'v'; break;
331 			case '\f':
332 				c = 'f'; break;
333 			case '\r':
334 				c = 'r'; break;
335 			case '\\':
336 				c = '\\'; break;
337 			default:
338 				vStringPut (b, 'x');
339 				vStringPut (b, valueToXDigit ((c & 0xF0) >> 4));
340 				vStringPut (b, valueToXDigit (c & 0x0F));
341 				continue;
342 			}
343 		}
344 		vStringPut (b, c);
345 	}
346 }
347 
vStringCatSWithEscapingAsPattern(vString * output,const char * input)348 extern void vStringCatSWithEscapingAsPattern (vString *output, const char* input)
349 {
350 	while (*input)
351 	{
352 		switch (*input)
353 		{
354 		case '\\':
355 			vStringPut(output, '\\');
356 			vStringPut(output, '\\');
357 			break;
358 		case '/':
359 			vStringPut(output, '\\');
360 			vStringPut(output, '/');
361 			break;
362 		default:
363 			vStringPut(output, *input);
364 			break;
365 
366 		}
367 		input++;
368 	}
369 }
370 
vStringNewOrClear(vString * const string)371 extern vString *vStringNewOrClear (vString *const string)
372 {
373 	if (string)
374 	{
375 		vStringClear (string);
376 		return string;
377 	}
378 	else
379 		return vStringNew ();
380 }
381 
vStringNewOrClearWithAutoRelease(vString * const string)382 extern vString *vStringNewOrClearWithAutoRelease (vString *const string)
383 {
384 	vString *r;
385 
386 	bool autoRelease = false;
387 	if (!string)
388 		autoRelease = true;
389 
390 	r = vStringNewOrClear(string);
391 	if (autoRelease)
392 		DEFAULT_TRASH_BOX(r, vStringDelete);
393 
394 	return r;
395 }
396 
vStringTranslate(vString * const string,char fromC,char toC)397 extern void vStringTranslate(vString *const string, char fromC, char toC)
398 {
399 	for (unsigned int i = 0; i < vStringLength(string); i++)
400 	{
401 		if (string->buffer[i] == fromC)
402 			string->buffer[i] = toC;
403 	}
404 }
405