libwine_unicode: Define all functions in the library even if they can be inlined.
[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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include <limits.h>
22 #include <stdio.h>
23
24 #include "wine/unicode.h"
25
26 extern const WCHAR wine_casemap_lower[];
27 extern const WCHAR wine_casemap_upper[];
28 extern const unsigned short wine_wctype_table[];
29
30 int is_dbcs_leadbyte( const union cptable *table, unsigned char ch )
31 {
32     return (table->info.char_size == 2) && (table->dbcs.cp2uni_leadbytes[ch]);
33 }
34
35 WCHAR tolowerW( WCHAR ch )
36 {
37     return ch + wine_casemap_lower[wine_casemap_lower[ch >> 8] + (ch & 0xff)];
38 }
39
40 WCHAR toupperW( WCHAR ch )
41 {
42     return ch + wine_casemap_upper[wine_casemap_upper[ch >> 8] + (ch & 0xff)];
43 }
44
45 /* the character type contains the C1_* flags in the low 12 bits */
46 /* and the C2_* type in the high 4 bits */
47 unsigned short get_char_typeW( WCHAR ch )
48 {
49     return wine_wctype_table[wine_wctype_table[ch >> 8] + (ch & 0xff)];
50 }
51
52 int iscntrlW( WCHAR wc )
53 {
54     return get_char_typeW(wc) & C1_CNTRL;
55 }
56
57 int ispunctW( WCHAR wc )
58 {
59     return get_char_typeW(wc) & C1_PUNCT;
60 }
61
62 int isspaceW( WCHAR wc )
63 {
64     return get_char_typeW(wc) & C1_SPACE;
65 }
66
67 int isdigitW( WCHAR wc )
68 {
69     return get_char_typeW(wc) & C1_DIGIT;
70 }
71
72 int isxdigitW( WCHAR wc )
73 {
74     return get_char_typeW(wc) & C1_XDIGIT;
75 }
76
77 int islowerW( WCHAR wc )
78 {
79     return get_char_typeW(wc) & C1_LOWER;
80 }
81
82 int isupperW( WCHAR wc )
83 {
84     return get_char_typeW(wc) & C1_UPPER;
85 }
86
87 int isalnumW( WCHAR wc )
88 {
89     return get_char_typeW(wc) & (C1_ALPHA|C1_DIGIT|C1_LOWER|C1_UPPER);
90 }
91
92 int isalphaW( WCHAR wc )
93 {
94     return get_char_typeW(wc) & (C1_ALPHA|C1_LOWER|C1_UPPER);
95 }
96
97 int isgraphW( WCHAR wc )
98 {
99     return get_char_typeW(wc) & (C1_ALPHA|C1_PUNCT|C1_DIGIT|C1_LOWER|C1_UPPER);
100 }
101
102 int isprintW( WCHAR wc )
103 {
104     return get_char_typeW(wc) & (C1_ALPHA|C1_BLANK|C1_PUNCT|C1_DIGIT|C1_LOWER|C1_UPPER);
105 }
106
107 unsigned int strlenW( const WCHAR *str )
108 {
109     const WCHAR *s = str;
110     while (*s) s++;
111     return s - str;
112 }
113
114 WCHAR *strcpyW( WCHAR *dst, const WCHAR *src )
115 {
116     WCHAR *p = dst;
117     while ((*p++ = *src++));
118     return dst;
119 }
120
121 int strcmpW( const WCHAR *str1, const WCHAR *str2 )
122 {
123     while (*str1 && (*str1 == *str2)) { str1++; str2++; }
124     return *str1 - *str2;
125 }
126
127 int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
128 {
129     if (n <= 0) return 0;
130     while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
131     return *str1 - *str2;
132 }
133
134 WCHAR *strcatW( WCHAR *dst, const WCHAR *src )
135 {
136     strcpyW( dst + strlenW(dst), src );
137     return dst;
138 }
139
140 WCHAR *strchrW( const WCHAR *str, WCHAR ch )
141 {
142     do { if (*str == ch) return (WCHAR *)str; } while (*str++);
143     return NULL;
144 }
145
146 WCHAR *strrchrW( const WCHAR *str, WCHAR ch )
147 {
148     WCHAR *ret = NULL;
149     do { if (*str == ch) ret = (WCHAR *)str; } while (*str++);
150     return ret;
151 }
152
153 WCHAR *strpbrkW( const WCHAR *str, const WCHAR *accept )
154 {
155     for ( ; *str; str++) if (strchrW( accept, *str )) return (WCHAR *)str;
156     return NULL;
157 }
158
159 size_t strspnW( const WCHAR *str, const WCHAR *accept )
160 {
161     const WCHAR *ptr;
162     for (ptr = str; *ptr; ptr++) if (!strchrW( accept, *ptr )) break;
163     return ptr - str;
164 }
165
166 size_t strcspnW( const WCHAR *str, const WCHAR *reject )
167 {
168     const WCHAR *ptr;
169     for (ptr = str; *ptr; ptr++) if (strchrW( reject, *ptr )) break;
170     return ptr - str;
171 }
172
173 WCHAR *strlwrW( WCHAR *str )
174 {
175     WCHAR *ret = str;
176     while ((*str = tolowerW(*str))) str++;
177     return ret;
178 }
179
180 WCHAR *struprW( WCHAR *str )
181 {
182     WCHAR *ret = str;
183     while ((*str = toupperW(*str))) str++;
184     return ret;
185 }
186
187 WCHAR *memchrW( const WCHAR *ptr, WCHAR ch, size_t n )
188 {
189     const WCHAR *end;
190     for (end = ptr + n; ptr < end; ptr++) if (*ptr == ch) return (WCHAR *)ptr;
191     return NULL;
192 }
193
194 WCHAR *memrchrW( const WCHAR *ptr, WCHAR ch, size_t n )
195 {
196     const WCHAR *end, *ret = NULL;
197     for (end = ptr + n; ptr < end; ptr++) if (*ptr == ch) ret = ptr;
198     return (WCHAR *)ret;
199 }
200
201 long int atolW( const WCHAR *str )
202 {
203     return strtolW( str, (WCHAR **)0, 10 );
204 }
205
206 int atoiW( const WCHAR *str )
207 {
208     return (int)atolW( str );
209 }
210
211 int strcmpiW( const WCHAR *str1, const WCHAR *str2 )
212 {
213     for (;;)
214     {
215         int ret = tolowerW(*str1) - tolowerW(*str2);
216         if (ret || !*str1) return ret;
217         str1++;
218         str2++;
219     }
220 }
221
222 int strncmpiW( const WCHAR *str1, const WCHAR *str2, int n )
223 {
224     int ret = 0;
225     for ( ; n > 0; n--, str1++, str2++)
226         if ((ret = tolowerW(*str1) - tolowerW(*str2)) || !*str1) break;
227     return ret;
228 }
229
230 int memicmpW( const WCHAR *str1, const WCHAR *str2, int n )
231 {
232     int ret = 0;
233     for ( ; n > 0; n--, str1++, str2++)
234         if ((ret = tolowerW(*str1) - tolowerW(*str2))) break;
235     return ret;
236 }
237
238 WCHAR *strstrW( const WCHAR *str, const WCHAR *sub )
239 {
240     while (*str)
241     {
242         const WCHAR *p1 = str, *p2 = sub;
243         while (*p1 && *p2 && *p1 == *p2) { p1++; p2++; }
244         if (!*p2) return (WCHAR *)str;
245         str++;
246     }
247     return NULL;
248 }
249
250 /* strtolW and strtoulW implementation based on the GNU C library code */
251 /* Copyright (C) 1991,92,94,95,96,97,98,99,2000,2001 Free Software Foundation, Inc. */
252
253 long int strtolW( const WCHAR *nptr, WCHAR **endptr, int base )
254 {
255   int negative;
256   register unsigned long int cutoff;
257   register unsigned int cutlim;
258   register unsigned long int i;
259   register const WCHAR *s;
260   register WCHAR c;
261   const WCHAR *save, *end;
262   int overflow;
263
264   if (base < 0 || base == 1 || base > 36) return 0;
265
266   save = s = nptr;
267
268   /* Skip white space.  */
269   while (isspaceW (*s))
270     ++s;
271   if (!*s) goto noconv;
272
273   /* Check for a sign.  */
274   negative = 0;
275   if (*s == '-')
276     {
277       negative = 1;
278       ++s;
279     }
280   else if (*s == '+')
281     ++s;
282
283   /* Recognize number prefix and if BASE is zero, figure it out ourselves.  */
284   if (*s == '0')
285     {
286       if ((base == 0 || base == 16) && toupperW(s[1]) == 'X')
287         {
288           s += 2;
289           base = 16;
290         }
291       else if (base == 0)
292         base = 8;
293     }
294   else if (base == 0)
295     base = 10;
296
297   /* Save the pointer so we can check later if anything happened.  */
298   save = s;
299   end = NULL;
300
301   cutoff = ULONG_MAX / (unsigned long int) base;
302   cutlim = ULONG_MAX % (unsigned long int) base;
303
304   overflow = 0;
305   i = 0;
306   c = *s;
307   for (;c != '\0'; c = *++s)
308   {
309       if (s == end)
310           break;
311       if (c >= '0' && c <= '9')
312           c -= '0';
313       else if (isalphaW (c))
314           c = toupperW (c) - 'A' + 10;
315       else
316           break;
317       if ((int) c >= base)
318           break;
319       /* Check for overflow.  */
320       if (i > cutoff || (i == cutoff && c > cutlim))
321           overflow = 1;
322       else
323       {
324           i *= (unsigned long int) base;
325           i += c;
326       }
327   }
328
329   /* Check if anything actually happened.  */
330   if (s == save)
331     goto noconv;
332
333   /* Store in ENDPTR the address of one character
334      past the last character we converted.  */
335   if (endptr != NULL)
336     *endptr = (WCHAR *)s;
337
338   /* Check for a value that is within the range of
339      `unsigned LONG int', but outside the range of `LONG int'.  */
340   if (overflow == 0
341       && i > (negative
342               ? -((unsigned long int) (LONG_MIN + 1)) + 1
343               : (unsigned long int) LONG_MAX))
344     overflow = 1;
345
346   if (overflow)
347     {
348       return negative ? LONG_MIN : LONG_MAX;
349     }
350
351   /* Return the result of the appropriate sign.  */
352   return negative ? -i : i;
353
354 noconv:
355   /* We must handle a special case here: the base is 0 or 16 and the
356      first two characters are '0' and 'x', but the rest are not
357      hexadecimal digits.  This is no error case.  We return 0 and
358      ENDPTR points to the `x`.  */
359   if (endptr != NULL)
360     {
361       if (save - nptr >= 2 && toupperW (save[-1]) == 'X'
362           && save[-2] == '0')
363         *endptr = (WCHAR *)&save[-1];
364       else
365         /*  There was no number to convert.  */
366         *endptr = (WCHAR *)nptr;
367     }
368
369   return 0L;
370 }
371
372
373 unsigned long int strtoulW( const WCHAR *nptr, WCHAR **endptr, int base )
374 {
375   int negative;
376   register unsigned long int cutoff;
377   register unsigned int cutlim;
378   register unsigned long int i;
379   register const WCHAR *s;
380   register WCHAR c;
381   const WCHAR *save, *end;
382   int overflow;
383
384   if (base < 0 || base == 1 || base > 36) return 0;
385
386   save = s = nptr;
387
388   /* Skip white space.  */
389   while (isspaceW (*s))
390     ++s;
391   if (!*s) goto noconv;
392
393   /* Check for a sign.  */
394   negative = 0;
395   if (*s == '-')
396     {
397       negative = 1;
398       ++s;
399     }
400   else if (*s == '+')
401     ++s;
402
403   /* Recognize number prefix and if BASE is zero, figure it out ourselves.  */
404   if (*s == '0')
405     {
406       if ((base == 0 || base == 16) && toupperW(s[1]) == 'X')
407         {
408           s += 2;
409           base = 16;
410         }
411       else if (base == 0)
412         base = 8;
413     }
414   else if (base == 0)
415     base = 10;
416
417   /* Save the pointer so we can check later if anything happened.  */
418   save = s;
419   end = NULL;
420
421   cutoff = ULONG_MAX / (unsigned long int) base;
422   cutlim = ULONG_MAX % (unsigned long int) base;
423
424   overflow = 0;
425   i = 0;
426   c = *s;
427   for (;c != '\0'; c = *++s)
428   {
429       if (s == end)
430           break;
431       if (c >= '0' && c <= '9')
432           c -= '0';
433       else if (isalphaW (c))
434           c = toupperW (c) - 'A' + 10;
435       else
436           break;
437       if ((int) c >= base)
438           break;
439       /* Check for overflow.  */
440       if (i > cutoff || (i == cutoff && c > cutlim))
441           overflow = 1;
442       else
443       {
444           i *= (unsigned long int) base;
445           i += c;
446       }
447   }
448
449   /* Check if anything actually happened.  */
450   if (s == save)
451     goto noconv;
452
453   /* Store in ENDPTR the address of one character
454      past the last character we converted.  */
455   if (endptr != NULL)
456     *endptr = (WCHAR *)s;
457
458   if (overflow)
459     {
460       return ULONG_MAX;
461     }
462
463   /* Return the result of the appropriate sign.  */
464   return negative ? -i : i;
465
466 noconv:
467   /* We must handle a special case here: the base is 0 or 16 and the
468      first two characters are '0' and 'x', but the rest are not
469      hexadecimal digits.  This is no error case.  We return 0 and
470      ENDPTR points to the `x`.  */
471   if (endptr != NULL)
472     {
473       if (save - nptr >= 2 && toupperW (save[-1]) == 'X'
474           && save[-2] == '0')
475         *endptr = (WCHAR *)&save[-1];
476       else
477         /*  There was no number to convert.  */
478         *endptr = (WCHAR *)nptr;
479     }
480
481   return 0L;
482 }
483
484
485 int vsnprintfW(WCHAR *str, size_t len, const WCHAR *format, va_list valist)
486 {
487     unsigned int written = 0;
488     const WCHAR *iter = format;
489     char bufa[256], fmtbufa[64], *fmta;
490
491     while (*iter)
492     {
493         while (*iter && *iter != '%')
494         {
495             if (written++ >= len)
496                 return -1;
497             *str++ = *iter++;
498         }
499         if (*iter == '%')
500         {
501             if (iter[1] == '%')
502             {
503                 if (written++ >= len)
504                     return -1;
505                 *str++ = '%'; /* "%%"->'%' */
506                 iter += 2;
507                 continue;
508             }
509
510             fmta = fmtbufa;
511             *fmta++ = *iter++;
512             while (*iter == '0' ||
513                    *iter == '+' ||
514                    *iter == '-' ||
515                    *iter == ' ' ||
516                    *iter == '*' ||
517                    *iter == '#')
518             {
519                 if (*iter == '*')
520                 {
521                     char *buffiter = bufa;
522                     int fieldlen = va_arg(valist, int);
523                     sprintf(buffiter, "%d", fieldlen);
524                     while (*buffiter)
525                         *fmta++ = *buffiter++;
526                 }
527                 else
528                     *fmta++ = *iter;
529                 iter++;
530             }
531
532             while (isdigit(*iter))
533                 *fmta++ = *iter++;
534
535             if (*iter == '.')
536             {
537                 *fmta++ = *iter++;
538                 if (*iter == '*')
539                 {
540                     char *buffiter = bufa;
541                     int fieldlen = va_arg(valist, int);
542                     sprintf(buffiter, "%d", fieldlen);
543                     while (*buffiter)
544                         *fmta++ = *buffiter++;
545                 }
546                 else
547                     while (isdigit(*iter))
548                         *fmta++ = *iter++;
549             }
550             if (*iter == 'h' || *iter == 'l')
551                 *fmta++ = *iter++;
552
553             switch (*iter)
554             {
555             case 's':
556             {
557                 static const WCHAR none[] = { '(','n','u','l','l',')',0 };
558                 const WCHAR *wstr = va_arg(valist, const WCHAR *);
559                 const WCHAR *striter = wstr ? wstr : none;
560                 while (*striter)
561                 {
562                     if (written++ >= len)
563                         return -1;
564                     *str++ = *striter++;
565                 }
566                 iter++;
567                 break;
568             }
569
570             case 'c':
571                 if (written++ >= len)
572                     return -1;
573                 *str++ = (WCHAR)va_arg(valist, int);
574                 iter++;
575                 break;
576
577             default:
578             {
579                 /* For non wc types, use system sprintf and append to wide char output */
580                 /* FIXME: for unrecognised types, should ignore % when printing */
581                 char *bufaiter = bufa;
582                 if (*iter == 'p')
583                     sprintf(bufaiter, "%08lX", va_arg(valist, long));
584                 else
585                 {
586                     *fmta++ = *iter;
587                     *fmta = '\0';
588                     if (*iter == 'a' || *iter == 'A' ||
589                         *iter == 'e' || *iter == 'E' ||
590                         *iter == 'f' || *iter == 'F' || 
591                         *iter == 'g' || *iter == 'G')
592                         sprintf(bufaiter, fmtbufa, va_arg(valist, double));
593                     else
594                     {
595                         /* FIXME: On 32 bit systems this doesn't handle int 64's.
596                          *        on 64 bit systems this doesn't work for 32 bit types
597                          */
598                         sprintf(bufaiter, fmtbufa, va_arg(valist, void *));
599                     }
600                 }
601                 while (*bufaiter)
602                 {
603                     if (written++ >= len)
604                         return -1;
605                     *str++ = *bufaiter++;
606                 }
607                 iter++;
608                 break;
609             }
610             }
611         }
612     }
613     if (written >= len)
614         return -1;
615     *str++ = 0;
616     return (int)written;
617 }
618
619 int vsprintfW( WCHAR *str, const WCHAR *format, va_list valist )
620 {
621     return vsnprintfW( str, INT_MAX, format, valist );
622 }
623
624 int snprintfW( WCHAR *str, size_t len, const WCHAR *format, ...)
625 {
626     int retval;
627     va_list valist;
628     va_start(valist, format);
629     retval = vsnprintfW(str, len, format, valist);
630     va_end(valist);
631     return retval;
632 }
633
634 int sprintfW( WCHAR *str, const WCHAR *format, ...)
635 {
636     int retval;
637     va_list valist;
638     va_start(valist, format);
639     retval = vsnprintfW(str, INT_MAX, format, valist);
640     va_end(valist);
641     return retval;
642 }