1 /* tmbstr.c -- Tidy string utility functions
2
3 (c) 1998-2004 (W3C) MIT, ERCIM, Keio University
4 See tidy.h for the copyright notice.
5
6 CVS Info :
7
8 $Author: terry_teague $
9 $Date: 2004/08/02 02:32:09 $
10 $Revision: 1.10 $
11
12 */
13
14 #include "tmbstr.h"
15 #include "lexer.h"
16
17 /* like strdup but using MemAlloc */
tmbstrdup(ctmbstr str)18 tmbstr tmbstrdup( ctmbstr str )
19 {
20 tmbstr s = NULL;
21 if ( str )
22 {
23 uint len = tmbstrlen( str );
24 tmbstr cp = s = (tmbstr) MemAlloc( 1+len );
25 while ( 0 != (*cp++ = *str++) )
26 /**/;
27 }
28 return s;
29 }
30
31 /* like strndup but using MemAlloc */
tmbstrndup(ctmbstr str,uint len)32 tmbstr tmbstrndup( ctmbstr str, uint len )
33 {
34 tmbstr s = NULL;
35 if ( str && len > 0 )
36 {
37 tmbstr cp = s = (tmbstr) MemAlloc( 1+len );
38 while ( len-- > 0 && (*cp++ = *str++) )
39 /**/;
40 *cp = 0;
41 }
42 return s;
43 }
44
45 /* exactly same as strncpy */
tmbstrncpy(tmbstr s1,ctmbstr s2,uint size)46 uint tmbstrncpy( tmbstr s1, ctmbstr s2, uint size )
47 {
48 if ( s1 != NULL && s2 != NULL )
49 {
50 tmbstr cp = s1;
51 while ( *s2 && --size ) /* Predecrement: reserve byte */
52 *cp++ = *s2++; /* for NULL terminator. */
53 *cp = 0;
54 }
55 return size;
56 }
57
58 /* Allows expressions like: cp += tmbstrcpy( cp, "joebob" );
59 */
tmbstrcpy(tmbstr s1,ctmbstr s2)60 uint tmbstrcpy( tmbstr s1, ctmbstr s2 )
61 {
62 uint ncpy = 0;
63 while (0 != (*s1++ = *s2++) )
64 ++ncpy;
65 return ncpy;
66 }
67
68 /* Allows expressions like: cp += tmbstrcat( cp, "joebob" );
69 */
tmbstrcat(tmbstr s1,ctmbstr s2)70 uint tmbstrcat( tmbstr s1, ctmbstr s2 )
71 {
72 uint ncpy = 0;
73 while ( *s1 )
74 ++s1;
75
76 while (0 != (*s1++ = *s2++) )
77 ++ncpy;
78 return ncpy;
79 }
80
81 /* exactly same as strcmp */
tmbstrcmp(ctmbstr s1,ctmbstr s2)82 int tmbstrcmp( ctmbstr s1, ctmbstr s2 )
83 {
84 int c;
85 while ((c = *s1) == *s2)
86 {
87 if (c == '\0')
88 return 0;
89
90 ++s1;
91 ++s2;
92 }
93
94 return (*s1 > *s2 ? 1 : -1);
95 }
96
97 /* returns byte count, not char count */
tmbstrlen(ctmbstr str)98 uint tmbstrlen( ctmbstr str )
99 {
100 uint len = 0;
101 if ( str )
102 {
103 while ( *str++ )
104 ++len;
105 }
106 return len;
107 }
108
109 /*
110 MS C 4.2 doesn't include strcasecmp.
111 Note that tolower and toupper won't
112 work on chars > 127.
113
114 Neither does ToLower()!
115 */
tmbstrcasecmp(ctmbstr s1,ctmbstr s2)116 int tmbstrcasecmp( ctmbstr s1, ctmbstr s2 )
117 {
118 uint c;
119
120 while (c = (uint)(*s1), ToLower(c) == ToLower((uint)(*s2)))
121 {
122 if (c == '\0')
123 return 0;
124
125 ++s1;
126 ++s2;
127 }
128
129 return (*s1 > *s2 ? 1 : -1);
130 }
131
tmbstrncmp(ctmbstr s1,ctmbstr s2,uint n)132 int tmbstrncmp( ctmbstr s1, ctmbstr s2, uint n )
133 {
134 uint c;
135
136 while ((c = (byte)*s1) == (byte)*s2)
137 {
138 if (c == '\0')
139 return 0;
140
141 if (n == 0)
142 return 0;
143
144 ++s1;
145 ++s2;
146 --n;
147 }
148
149 if (n == 0)
150 return 0;
151
152 return (*s1 > *s2 ? 1 : -1);
153 }
154
tmbstrncasecmp(ctmbstr s1,ctmbstr s2,uint n)155 int tmbstrncasecmp( ctmbstr s1, ctmbstr s2, uint n )
156 {
157 uint c;
158
159 while (c = (uint)(*s1), ToLower(c) == ToLower((uint)(*s2)))
160 {
161 if (c == '\0')
162 return 0;
163
164 if (n == 0)
165 return 0;
166
167 ++s1;
168 ++s2;
169 --n;
170 }
171
172 if (n == 0)
173 return 0;
174
175 return (*s1 > *s2 ? 1 : -1);
176 }
177
178 /* return offset of cc from beginning of s1,
179 ** -1 if not found.
180 */
tmbstrnchr(ctmbstr s1,uint maxlen,tmbchar cc)181 int tmbstrnchr( ctmbstr s1, uint maxlen, tmbchar cc )
182 {
183 int i;
184 ctmbstr cp = s1;
185
186 for ( i = 0; (uint)i < maxlen; ++i, ++cp )
187 {
188 if ( *cp == cc )
189 return i;
190 }
191
192 return -1;
193 }
194
tmbsubstrn(ctmbstr s1,uint len1,ctmbstr s2)195 ctmbstr tmbsubstrn( ctmbstr s1, uint len1, ctmbstr s2 )
196 {
197 uint len2 = tmbstrlen(s2);
198 int ix, diff = len1 - len2;
199
200 for ( ix = 0; ix <= diff; ++ix )
201 {
202 if ( tmbstrncmp(s1+ix, s2, len2) == 0 )
203 return (ctmbstr) s1+ix;
204 }
205 return NULL;
206 }
207
tmbsubstrncase(ctmbstr s1,uint len1,ctmbstr s2)208 ctmbstr tmbsubstrncase( ctmbstr s1, uint len1, ctmbstr s2 )
209 {
210 uint len2 = tmbstrlen(s2);
211 int ix, diff = len1 - len2;
212
213 for ( ix = 0; ix <= diff; ++ix )
214 {
215 if ( tmbstrncasecmp(s1+ix, s2, len2) == 0 )
216 return (ctmbstr) s1+ix;
217 }
218 return NULL;
219 }
220
tmbsubstr(ctmbstr s1,ctmbstr s2)221 ctmbstr tmbsubstr( ctmbstr s1, ctmbstr s2 )
222 {
223 uint len1 = tmbstrlen(s1), len2 = tmbstrlen(s2);
224 int ix, diff = len1 - len2;
225
226 for ( ix = 0; ix <= diff; ++ix )
227 {
228 if ( tmbstrncasecmp(s1+ix, s2, len2) == 0 )
229 return (ctmbstr) s1+ix;
230 }
231 return NULL;
232 }
233
234 /* Transform ASCII chars in string to lower case */
tmbstrtolower(tmbstr s)235 tmbstr tmbstrtolower( tmbstr s )
236 {
237 tmbstr cp;
238 for ( cp=s; *cp; ++cp )
239 *cp = (tmbchar) ToLower( *cp );
240 return s;
241 }
242
243 /* Transform ASCII chars in string to upper case */
tmbstrtoupper(tmbstr s)244 tmbstr tmbstrtoupper(tmbstr s)
245 {
246 tmbstr cp;
247
248 for (cp = s; *cp; ++cp)
249 *cp = (tmbchar)ToUpper(*cp);
250
251 return s;
252 }
253
tmbsamefile(ctmbstr filename1,ctmbstr filename2)254 Bool tmbsamefile( ctmbstr filename1, ctmbstr filename2 )
255 {
256 #if FILENAMES_CASE_SENSITIVE
257 return ( tmbstrcmp( filename1, filename2 ) == 0 );
258 #else
259 return ( tmbstrcasecmp( filename1, filename2 ) == 0 );
260 #endif
261 }
262
tmbvsnprintf(tmbstr buffer,size_t count,ctmbstr format,va_list args)263 int tmbvsnprintf(tmbstr buffer, size_t count, ctmbstr format, va_list args)
264 {
265 int retval;
266 #if HAS_VSNPRINTF
267 retval = vsnprintf(buffer, count - 1, format, args);
268 /* todo: conditionally null-terminate the string? */
269 buffer[count - 1] = 0;
270 #else
271 retval = vsprintf(buffer, format, args);
272 #endif /* HAS_VSNPRINTF */
273 return retval;
274 }
275
tmbsnprintf(tmbstr buffer,size_t count,ctmbstr format,...)276 int tmbsnprintf(tmbstr buffer, size_t count, ctmbstr format, ...)
277 {
278 int retval;
279 va_list args;
280 va_start(args, format);
281 #if HAS_VSNPRINTF
282 retval = vsnprintf(buffer, count - 1, format, args);
283 /* todo: conditionally null-terminate the string? */
284 buffer[count - 1] = 0;
285 #else
286 retval = vsprintf(buffer, format, args);
287 #endif /* HAS_VSNPRINTF */
288 va_end(args);
289 return retval;
290 }
291