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