Fix the case of product and company names.
[wine] / libs / unicode / string.c
1 /*
2  * Unicode string manipulation functions
3  *
4  * Copyright 2000 Alexandre Julliard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include <limits.h>
22 #include <stdio.h>
23
24 #include "wine/unicode.h"
25
26 int strcmpiW( const WCHAR *str1, const WCHAR *str2 )
27 {
28     for (;;)
29     {
30         int ret = toupperW(*str1) - toupperW(*str2);
31         if (ret || !*str1) return ret;
32         str1++;
33         str2++;
34     }
35 }
36
37 int strncmpiW( const WCHAR *str1, const WCHAR *str2, int n )
38 {
39     int ret = 0;
40     for ( ; n > 0; n--, str1++, str2++)
41         if ((ret = toupperW(*str1) - toupperW(*str2)) || !*str1) break;
42     return ret;
43 }
44
45 WCHAR *strstrW( const WCHAR *str, const WCHAR *sub )
46 {
47     while (*str)
48     {
49         const WCHAR *p1 = str, *p2 = sub;
50         while (*p1 && *p2 && *p1 == *p2) { p1++; p2++; }
51         if (!*p2) return (WCHAR *)str;
52         str++;
53     }
54     return NULL;
55 }
56
57 /* strtolW and strtoulW implementation based on the GNU C library code */
58 /* Copyright (C) 1991,92,94,95,96,97,98,99,2000,2001 Free Software Foundation, Inc. */
59
60 long int strtolW( const WCHAR *nptr, WCHAR **endptr, int base )
61 {
62   int negative;
63   register unsigned long int cutoff;
64   register unsigned int cutlim;
65   register unsigned long int i;
66   register const WCHAR *s;
67   register WCHAR c;
68   const WCHAR *save, *end;
69   int overflow;
70
71   if (base < 0 || base == 1 || base > 36) return 0;
72
73   save = s = nptr;
74
75   /* Skip white space.  */
76   while (isspaceW (*s))
77     ++s;
78   if (!*s) goto noconv;
79
80   /* Check for a sign.  */
81   negative = 0;
82   if (*s == '-')
83     {
84       negative = 1;
85       ++s;
86     }
87   else if (*s == '+')
88     ++s;
89
90   /* Recognize number prefix and if BASE is zero, figure it out ourselves.  */
91   if (*s == '0')
92     {
93       if ((base == 0 || base == 16) && toupperW(s[1]) == 'X')
94         {
95           s += 2;
96           base = 16;
97         }
98       else if (base == 0)
99         base = 8;
100     }
101   else if (base == 0)
102     base = 10;
103
104   /* Save the pointer so we can check later if anything happened.  */
105   save = s;
106   end = NULL;
107
108   cutoff = ULONG_MAX / (unsigned long int) base;
109   cutlim = ULONG_MAX % (unsigned long int) base;
110
111   overflow = 0;
112   i = 0;
113   c = *s;
114   for (;c != '\0'; c = *++s)
115   {
116       if (s == end)
117           break;
118       if (c >= '0' && c <= '9')
119           c -= '0';
120       else if (isalphaW (c))
121           c = toupperW (c) - 'A' + 10;
122       else
123           break;
124       if ((int) c >= base)
125           break;
126       /* Check for overflow.  */
127       if (i > cutoff || (i == cutoff && c > cutlim))
128           overflow = 1;
129       else
130       {
131           i *= (unsigned long int) base;
132           i += c;
133       }
134   }
135
136   /* Check if anything actually happened.  */
137   if (s == save)
138     goto noconv;
139
140   /* Store in ENDPTR the address of one character
141      past the last character we converted.  */
142   if (endptr != NULL)
143     *endptr = (WCHAR *)s;
144
145   /* Check for a value that is within the range of
146      `unsigned LONG int', but outside the range of `LONG int'.  */
147   if (overflow == 0
148       && i > (negative
149               ? -((unsigned long int) (LONG_MIN + 1)) + 1
150               : (unsigned long int) LONG_MAX))
151     overflow = 1;
152
153   if (overflow)
154     {
155       return negative ? LONG_MIN : LONG_MAX;
156     }
157
158   /* Return the result of the appropriate sign.  */
159   return negative ? -i : i;
160
161 noconv:
162   /* We must handle a special case here: the base is 0 or 16 and the
163      first two characters are '0' and 'x', but the rest are not
164      hexadecimal digits.  This is no error case.  We return 0 and
165      ENDPTR points to the `x`.  */
166   if (endptr != NULL)
167     {
168       if (save - nptr >= 2 && toupperW (save[-1]) == 'X'
169           && save[-2] == '0')
170         *endptr = (WCHAR *)&save[-1];
171       else
172         /*  There was no number to convert.  */
173         *endptr = (WCHAR *)nptr;
174     }
175
176   return 0L;
177 }
178
179
180 unsigned long int strtoulW( const WCHAR *nptr, WCHAR **endptr, int base )
181 {
182   int negative;
183   register unsigned long int cutoff;
184   register unsigned int cutlim;
185   register unsigned long int i;
186   register const WCHAR *s;
187   register WCHAR c;
188   const WCHAR *save, *end;
189   int overflow;
190
191   if (base < 0 || base == 1 || base > 36) return 0;
192
193   save = s = nptr;
194
195   /* Skip white space.  */
196   while (isspaceW (*s))
197     ++s;
198   if (!*s) goto noconv;
199
200   /* Check for a sign.  */
201   negative = 0;
202   if (*s == '-')
203     {
204       negative = 1;
205       ++s;
206     }
207   else if (*s == '+')
208     ++s;
209
210   /* Recognize number prefix and if BASE is zero, figure it out ourselves.  */
211   if (*s == '0')
212     {
213       if ((base == 0 || base == 16) && toupperW(s[1]) == 'X')
214         {
215           s += 2;
216           base = 16;
217         }
218       else if (base == 0)
219         base = 8;
220     }
221   else if (base == 0)
222     base = 10;
223
224   /* Save the pointer so we can check later if anything happened.  */
225   save = s;
226   end = NULL;
227
228   cutoff = ULONG_MAX / (unsigned long int) base;
229   cutlim = ULONG_MAX % (unsigned long int) base;
230
231   overflow = 0;
232   i = 0;
233   c = *s;
234   for (;c != '\0'; c = *++s)
235   {
236       if (s == end)
237           break;
238       if (c >= '0' && c <= '9')
239           c -= '0';
240       else if (isalphaW (c))
241           c = toupperW (c) - 'A' + 10;
242       else
243           break;
244       if ((int) c >= base)
245           break;
246       /* Check for overflow.  */
247       if (i > cutoff || (i == cutoff && c > cutlim))
248           overflow = 1;
249       else
250       {
251           i *= (unsigned long int) base;
252           i += c;
253       }
254   }
255
256   /* Check if anything actually happened.  */
257   if (s == save)
258     goto noconv;
259
260   /* Store in ENDPTR the address of one character
261      past the last character we converted.  */
262   if (endptr != NULL)
263     *endptr = (WCHAR *)s;
264
265   if (overflow)
266     {
267       return ULONG_MAX;
268     }
269
270   /* Return the result of the appropriate sign.  */
271   return negative ? -i : i;
272
273 noconv:
274   /* We must handle a special case here: the base is 0 or 16 and the
275      first two characters are '0' and 'x', but the rest are not
276      hexadecimal digits.  This is no error case.  We return 0 and
277      ENDPTR points to the `x`.  */
278   if (endptr != NULL)
279     {
280       if (save - nptr >= 2 && toupperW (save[-1]) == 'X'
281           && save[-2] == '0')
282         *endptr = (WCHAR *)&save[-1];
283       else
284         /*  There was no number to convert.  */
285         *endptr = (WCHAR *)nptr;
286     }
287
288   return 0L;
289 }
290
291
292 int vsnprintfW(WCHAR *str, size_t len, const WCHAR *format, va_list valist)
293 {
294     unsigned int written = 0;
295     const WCHAR *iter = format;
296     char bufa[256], fmtbufa[64], *fmta;
297
298     while (*iter)
299     {
300         while (*iter && *iter != '%')
301         {
302             if (written++ >= len)
303                 return -1;
304             *str++ = *iter++;
305         }
306         if (*iter == '%')
307         {
308             if (iter[1] == '%')
309             {
310                 if (written++ >= len)
311                     return -1;
312                 *str++ = '%'; /* "%%"->'%' */
313                 iter += 2;
314                 continue;
315             }
316
317             fmta = fmtbufa;
318             *fmta++ = *iter++;
319             while (*iter == '0' ||
320                    *iter == '+' ||
321                    *iter == '-' ||
322                    *iter == ' ' ||
323                    *iter == '0' ||
324                    *iter == '*' ||
325                    *iter == '#')
326             {
327                 if (*iter == '*')
328                 {
329                     char *buffiter = bufa;
330                     int fieldlen = va_arg(valist, int);
331                     sprintf(buffiter, "%d", fieldlen);
332                     while (*buffiter)
333                         *fmta++ = *buffiter++;
334                 }
335                 else
336                     *fmta++ = *iter;
337                 iter++;
338             }
339
340             while (isdigit(*iter))
341                 *fmta++ = *iter++;
342
343             if (*iter == '.')
344             {
345                 *fmta++ = *iter++;
346                 if (*iter == '*')
347                 {
348                     char *buffiter = bufa;
349                     int fieldlen = va_arg(valist, int);
350                     sprintf(buffiter, "%d", fieldlen);
351                     while (*buffiter)
352                         *fmta++ = *buffiter++;
353                 }
354                 else
355                     while (isdigit(*iter))
356                         *fmta++ = *iter++;
357             }
358             if (*iter == 'h' || *iter == 'l')
359                 *fmta++ = *iter++;
360
361             switch (*iter)
362             {
363             case 's':
364             {
365                 static const WCHAR none[] = { '(','n','u','l','l',')',0 };
366                 const WCHAR *wstr = va_arg(valist, const WCHAR *);
367                 const WCHAR *striter = wstr ? wstr : none;
368                 while (*striter)
369                 {
370                     if (written++ >= len)
371                         return -1;
372                     *str++ = *striter++;
373                 }
374                 iter++;
375                 break;
376             }
377
378             case 'c':
379                 if (written++ >= len)
380                     return -1;
381                 *str++ = (WCHAR)va_arg(valist, int);
382                 iter++;
383                 break;
384
385             default:
386             {
387                 /* For non wc types, use system sprintf and append to wide char output */
388                 /* FIXME: for unrecognised types, should ignore % when printing */
389                 char *bufaiter = bufa;
390                 if (*iter == 'p')
391                     sprintf(bufaiter, "%08lX", va_arg(valist, long));
392                 else
393                 {
394                     *fmta++ = *iter;
395                     *fmta = '\0';
396                     if (*iter == 'f')
397                         sprintf(bufaiter, fmtbufa, va_arg(valist, double));
398                     else
399                         sprintf(bufaiter, fmtbufa, va_arg(valist, void *));
400                 }
401                 while (*bufaiter)
402                 {
403                     if (written++ >= len)
404                         return -1;
405                     *str++ = *bufaiter++;
406                 }
407                 iter++;
408                 break;
409             }
410             }
411         }
412     }
413     if (written >= len)
414         return -1;
415     *str++ = 0;
416     return (int)written;
417 }
418
419 int vsprintfW( WCHAR *str, const WCHAR *format, va_list valist )
420 {
421     return vsnprintfW( str, INT_MAX, format, valist );
422 }
423
424 int snprintfW( WCHAR *str, size_t len, const WCHAR *format, ...)
425 {
426     int retval;
427     va_list valist;
428     va_start(valist, format);
429     retval = vsnprintfW(str, len, format, valist);
430     va_end(valist);
431     return retval;
432 }
433
434 int sprintfW( WCHAR *str, const WCHAR *format, ...)
435 {
436     int retval;
437     va_list valist;
438     va_start(valist, format);
439     retval = vsnprintfW(str, INT_MAX, format, valist);
440     va_end(valist);
441     return retval;
442 }