1 /*
2 *   $Id: vstring.c 558 2007-06-15 19:17:02Z elliotth $
3 *
4 *   Copyright (c) 1998-2002, Darren Hiebert
5 *
6 *   This source code is released for free distribution under the terms of the
7 *   GNU General Public License.
8 *
9 *   This module contains functions supporting resizeable strings.
10 */
11 
12 /*
13 *   INCLUDE FILES
14 */
15 #include "general.h"  /* must always come first */
16 
17 #include <limits.h>  /* to define INT_MAX */
18 #include <string.h>
19 #include <ctype.h>
20 
21 #include "debug.h"
22 #include "routines.h"
23 #include "vstring.h"
24 
25 /*
26 *   DATA DEFINITIONS
27 */
28 static const size_t vStringInitialSize = 32;
29 
30 /*
31 *   FUNCTION DEFINITIONS
32 */
33 
vStringResize(vString * const string,const size_t newSize)34 static void vStringResize (vString *const string, const size_t newSize)
35 {
36 	char *const newBuffer = xRealloc (string->buffer, newSize, char);
37 
38 	string->size = newSize;
39 	string->buffer = newBuffer;
40 }
41 
42 /*
43 *   External interface
44 */
45 
vStringAutoResize(vString * const string)46 extern boolean vStringAutoResize (vString *const string)
47 {
48 	boolean ok = TRUE;
49 
50 	if (string->size <= INT_MAX / 2)
51 	{
52 		const size_t newSize = string->size * 2;
53 
54 		vStringResize (string, newSize);
55 	}
56 	return ok;
57 }
58 
vStringClear(vString * const string)59 extern void vStringClear (vString *const string)
60 {
61 	string->length = 0;
62 	string->buffer [0] = '\0';
63 	DebugStatement ( memset (string->buffer, 0, string->size); )
64 }
65 
vStringDelete(vString * const string)66 extern void vStringDelete (vString *const string)
67 {
68 	if (string != NULL)
69 	{
70 		if (string->buffer != NULL)
71 			eFree (string->buffer);
72 		eFree (string);
73 	}
74 }
75 
vStringNew(void)76 extern vString *vStringNew (void)
77 {
78 	vString *const string = xMalloc (1, vString);
79 
80 	string->length = 0;
81 	string->size   = vStringInitialSize;
82 	string->buffer = xMalloc (string->size, char);
83 
84 	vStringClear (string);
85 
86 	return string;
87 }
88 
89 #ifndef VSTRING_PUTC_MACRO
vStringPut(vString * const string,const int c)90 extern void vStringPut (vString *const string, const int c)
91 {
92 	if (string->length + 1 == string->size)  /*  check for buffer overflow */
93 		vStringAutoResize (string);
94 
95 	string->buffer [string->length] = c;
96 	if (c != '\0')
97 		string->buffer [++string->length] = '\0';
98 }
99 #endif
100 
vStringCatS(vString * const string,const char * const s)101 extern void vStringCatS (vString *const string, const char *const s)
102 {
103 #if 1
104 	const size_t len = strlen (s);
105 	while (string->length + len + 1 >= string->size)/*  check for buffer overflow */
106 		vStringAutoResize (string);
107 	strcpy (string->buffer + string->length, s);
108 	string->length += len;
109 #else
110 	const char *p = s;
111 	do
112 		vStringPut (string, *p);
113 	while (*p++ != '\0');
114 #endif
115 }
116 
vStringNewCopy(const vString * const string)117 extern vString *vStringNewCopy (const vString *const string)
118 {
119 	vString *vs = vStringNew ();
120 	vStringCatS (vs, string->buffer);
121 	return vs;
122 }
123 
vStringNewInit(const char * const s)124 extern vString *vStringNewInit (const char *const s)
125 {
126 	vString *vs = vStringNew ();
127 	vStringCatS (vs, s);
128 	return vs;
129 }
130 
vStringNCatS(vString * const string,const char * const s,const size_t length)131 extern void vStringNCatS (
132 		vString *const string, const char *const s, const size_t length)
133 {
134 	const char *p = s;
135 	size_t remain = length;
136 
137 	while (*p != '\0'  &&  remain > 0)
138 	{
139 		vStringPut (string, *p);
140 		--remain;
141 		++p;
142 	}
143 	vStringTerminate (string);
144 }
145 
146 /*  Strip trailing newline from string.
147  */
vStringStripNewline(vString * const string)148 extern void vStringStripNewline (vString *const string)
149 {
150 	const size_t final = string->length - 1;
151 	if (string->buffer [final] == '\n')
152 	{
153 		string->buffer [final] = '\0';
154 		string->length--;
155 	}
156 }
157 
158 /*  Strip leading white space from string.
159  */
vStringStripLeading(vString * const string)160 extern void vStringStripLeading (vString *const string)
161 {
162 	while (isspace ((int) string->buffer [0]) && string->length > 0)
163 	{
164 		size_t i;
165 		for (i = 1  ;  i < string->length  ;  ++i)
166 			string->buffer [i - 1] = string->buffer [i];
167 		--string->length;
168 		string->buffer [string->length] = '\0';
169 	}
170 }
171 
172 /*  Strip trailing white space from string.
173  */
vStringStripTrailing(vString * const string)174 extern void vStringStripTrailing (vString *const string)
175 {
176 	while (isspace ((int) string->buffer [string->length - 1]) &&
177 		   string->length > 0)
178 	{
179 		string->length--;
180 		string->buffer [string->length] = '\0';
181 	}
182 }
183 
184 /*  Chop last character from string.
185  */
vStringChop(vString * const string)186 extern void vStringChop (vString *const string)
187 {
188 	if (string->length > 0)
189 	{
190 		--string->length;
191 		string->buffer [string->length] = '\0';
192 	}
193 }
194 
vStringCopyS(vString * const string,const char * const s)195 extern void vStringCopyS (vString *const string, const char *const s)
196 {
197 	vStringClear (string);
198 	vStringCatS (string, s);
199 }
200 
vStringNCopyS(vString * const string,const char * const s,const size_t length)201 extern void vStringNCopyS (
202 		vString *const string, const char *const s, const size_t length)
203 {
204 	vStringClear (string);
205 	vStringNCatS (string, s, length);
206 }
207 
vStringCopyToLower(vString * const dest,const vString * const src)208 extern void vStringCopyToLower (vString *const dest, const vString *const src)
209 {
210 	const size_t length = src->length;
211 	const char *s = src->buffer;
212 	char *d;
213 	size_t i;
214 
215 	if (dest->size < src->size)
216 		vStringResize (dest, src->size);
217 	d = dest->buffer;
218 	for (i = 0  ;  i < length  ;  ++i)
219 	{
220 		int c = s [i];
221 
222 		d [i] = tolower (c);
223 	}
224 	d [i] = '\0';
225 }
226 
vStringSetLength(vString * const string)227 extern void vStringSetLength (vString *const string)
228 {
229 	string->length = strlen (string->buffer);
230 }
231 
232 /* vi:set tabstop=4 shiftwidth=4: */
233