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: iccir $
9    $Date: 2007/01/30 23:46:52 $
10    $Revision: 1.3 $
11
12*/
13
14#include "forward.h"
15#include "tmbstr.h"
16#include "lexer.h"
17
18/* like strdup but using MemAlloc */
19tmbstr TY_(tmbstrdup)( ctmbstr str )
20{
21    tmbstr s = NULL;
22    if ( str )
23    {
24        uint len = TY_(tmbstrlen)( str );
25        tmbstr cp = s = (tmbstr) MemAlloc( 1+len );
26        while ( 0 != (*cp++ = *str++) )
27            /**/;
28    }
29    return s;
30}
31
32/* like strndup but using MemAlloc */
33tmbstr TY_(tmbstrndup)( ctmbstr str, uint len )
34{
35    tmbstr s = NULL;
36    if ( str && len > 0 )
37    {
38        tmbstr cp = s = (tmbstr) MemAlloc( 1+len );
39        while ( len-- > 0 &&  (*cp++ = *str++) )
40          /**/;
41        *cp = 0;
42    }
43    return s;
44}
45
46/* exactly same as strncpy */
47uint 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*/
61uint 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*/
71uint 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 */
83int 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 */
99uint 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*/
117int 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
133int 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
156int 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*/
183int 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
198ctmbstr 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
212ctmbstr 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
226ctmbstr 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 */
240tmbstr 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 */
249tmbstr 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
260Bool 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
270int 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
283int 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