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