comctl32/tests: Write-strings warnings fix.
[wine] / dlls / ntdll / wcstring.c
1 /*
2  * NTDLL wide-char functions
3  *
4  * Copyright 2000 Alexandre Julliard
5  * Copyright 2000 Jon Griffiths
6  * Copyright 2003 Thomas Mertes
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22
23 #include "config.h"
24
25 #include <ctype.h>
26 #include <limits.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <stdarg.h>
30 #include <stdio.h>
31
32 #include "windef.h"
33 #include "winternl.h"
34 #include "wine/unicode.h"
35 #include "wine/debug.h"
36
37 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
38
39
40 /*********************************************************************
41  *           _wcsicmp    (NTDLL.@)
42  */
43 INT __cdecl NTDLL__wcsicmp( LPCWSTR str1, LPCWSTR str2 )
44 {
45     return strcmpiW( str1, str2 );
46 }
47
48
49 /*********************************************************************
50  *           _wcslwr    (NTDLL.@)
51  */
52 LPWSTR __cdecl NTDLL__wcslwr( LPWSTR str )
53 {
54     return strlwrW( str );
55 }
56
57
58 /*********************************************************************
59  *           _wcsnicmp    (NTDLL.@)
60  */
61 INT __cdecl NTDLL__wcsnicmp( LPCWSTR str1, LPCWSTR str2, INT n )
62 {
63     return strncmpiW( str1, str2, n );
64 }
65
66
67 /*********************************************************************
68  *           _wcsupr    (NTDLL.@)
69  */
70 LPWSTR __cdecl NTDLL__wcsupr( LPWSTR str )
71 {
72     return struprW( str );
73 }
74
75
76 /*********************************************************************
77  *           towlower    (NTDLL.@)
78  */
79 WCHAR __cdecl NTDLL_towlower( WCHAR ch )
80 {
81     return tolowerW(ch);
82 }
83
84
85 /*********************************************************************
86  *           towupper    (NTDLL.@)
87  */
88 WCHAR __cdecl NTDLL_towupper( WCHAR ch )
89 {
90     return toupperW(ch);
91 }
92
93
94 /***********************************************************************
95  *           wcscat    (NTDLL.@)
96  */
97 LPWSTR __cdecl NTDLL_wcscat( LPWSTR dst, LPCWSTR src )
98 {
99     return strcatW( dst, src );
100 }
101
102
103 /*********************************************************************
104  *           wcschr    (NTDLL.@)
105  */
106 LPWSTR __cdecl NTDLL_wcschr( LPCWSTR str, WCHAR ch )
107 {
108     return strchrW( str, ch );
109 }
110
111
112 /*********************************************************************
113  *           wcscmp    (NTDLL.@)
114  */
115 INT __cdecl NTDLL_wcscmp( LPCWSTR str1, LPCWSTR str2 )
116 {
117     return strcmpW( str1, str2 );
118 }
119
120
121 /***********************************************************************
122  *           wcscpy    (NTDLL.@)
123  */
124 LPWSTR __cdecl NTDLL_wcscpy( LPWSTR dst, LPCWSTR src )
125 {
126     return strcpyW( dst, src );
127 }
128
129
130 /*********************************************************************
131  *           wcscspn    (NTDLL.@)
132  */
133 INT __cdecl NTDLL_wcscspn( LPCWSTR str, LPCWSTR reject )
134 {
135     return strcspnW( str, reject );
136 }
137
138
139 /***********************************************************************
140  *           wcslen    (NTDLL.@)
141  */
142 INT __cdecl NTDLL_wcslen( LPCWSTR str )
143 {
144     return strlenW( str );
145 }
146
147
148 /*********************************************************************
149  *           wcsncat    (NTDLL.@)
150  */
151 LPWSTR __cdecl NTDLL_wcsncat( LPWSTR s1, LPCWSTR s2, INT n )
152 {
153     LPWSTR ret = s1;
154     while (*s1) s1++;
155     while (n-- > 0) if (!(*s1++ = *s2++)) return ret;
156     *s1 = 0;
157     return ret;
158 }
159
160
161 /*********************************************************************
162  *           wcsncmp    (NTDLL.@)
163  */
164 INT __cdecl NTDLL_wcsncmp( LPCWSTR str1, LPCWSTR str2, INT n )
165 {
166     return strncmpW( str1, str2, n );
167 }
168
169
170 /*********************************************************************
171  *           wcsncpy    (NTDLL.@)
172  */
173 LPWSTR __cdecl NTDLL_wcsncpy( LPWSTR s1, LPCWSTR s2, INT n )
174 {
175     WCHAR *ret = s1;
176     while (n-- > 0) if (!(*s1++ = *s2++)) break;
177     while (n-- > 0) *s1++ = 0;
178     return ret;
179 }
180
181
182 /*********************************************************************
183  *           wcspbrk    (NTDLL.@)
184  */
185 LPWSTR __cdecl NTDLL_wcspbrk( LPCWSTR str, LPCWSTR accept )
186 {
187     return strpbrkW( str, accept );
188 }
189
190
191 /*********************************************************************
192  *           wcsrchr    (NTDLL.@)
193  */
194 LPWSTR __cdecl NTDLL_wcsrchr( LPWSTR str, WCHAR ch )
195 {
196     return strrchrW( str, ch );
197 }
198
199
200 /*********************************************************************
201  *           wcsspn    (NTDLL.@)
202  */
203 INT __cdecl NTDLL_wcsspn( LPCWSTR str, LPCWSTR accept )
204 {
205     return strspnW( str, accept );
206 }
207
208
209 /*********************************************************************
210  *           wcsstr    (NTDLL.@)
211  */
212 LPWSTR __cdecl NTDLL_wcsstr( LPCWSTR str, LPCWSTR sub )
213 {
214     return strstrW( str, sub );
215 }
216
217
218 /*********************************************************************
219  *           wcstok    (NTDLL.@)
220  */
221 LPWSTR __cdecl NTDLL_wcstok( LPWSTR str, LPCWSTR delim )
222 {
223     static LPWSTR next = NULL;
224     LPWSTR ret;
225
226     if (!str)
227         if (!(str = next)) return NULL;
228
229     while (*str && NTDLL_wcschr( delim, *str )) str++;
230     if (!*str) return NULL;
231     ret = str++;
232     while (*str && !NTDLL_wcschr( delim, *str )) str++;
233     if (*str) *str++ = 0;
234     next = str;
235     return ret;
236 }
237
238
239 /*********************************************************************
240  *           wcstombs    (NTDLL.@)
241  */
242 INT __cdecl NTDLL_wcstombs( LPSTR dst, LPCWSTR src, INT n )
243 {
244     DWORD len;
245
246     if (!dst)
247     {
248         RtlUnicodeToMultiByteSize( &len, src, strlenW(src)*sizeof(WCHAR) );
249         return len;
250     }
251     else
252     {
253         if (n <= 0) return 0;
254         RtlUnicodeToMultiByteN( dst, n, &len, src, strlenW(src)*sizeof(WCHAR) );
255         if (len < n) dst[len] = 0;
256     }
257     return len;
258 }
259
260
261 /*********************************************************************
262  *           mbstowcs    (NTDLL.@)
263  */
264 INT __cdecl NTDLL_mbstowcs( LPWSTR dst, LPCSTR src, INT n )
265 {
266     DWORD len;
267
268     if (!dst)
269     {
270         RtlMultiByteToUnicodeSize( &len, src, strlen(src) );
271     }
272     else
273     {
274         if (n <= 0) return 0;
275         RtlMultiByteToUnicodeN( dst, n*sizeof(WCHAR), &len, src, strlen(src) );
276         if (len / sizeof(WCHAR) < n) dst[len / sizeof(WCHAR)] = 0;
277     }
278     return len / sizeof(WCHAR);
279 }
280
281
282 /*********************************************************************
283  *                  wcstol  (NTDLL.@)
284  */
285 long __cdecl NTDLL_wcstol(LPCWSTR s,LPWSTR *end,INT base)
286 {
287     return strtolW( s, end, base );
288 }
289
290
291 /*********************************************************************
292  *                  wcstoul  (NTDLL.@)
293  */
294 unsigned long __cdecl NTDLL_wcstoul(LPCWSTR s,LPWSTR *end,INT base)
295 {
296     return strtoulW( s, end, base );
297 }
298
299
300 /*********************************************************************
301  *           iswctype    (NTDLL.@)
302  */
303 INT __cdecl NTDLL_iswctype( WCHAR wc, WCHAR wct )
304 {
305     return (get_char_typeW(wc) & 0xfff) & wct;
306 }
307
308
309 /*********************************************************************
310  *           iswalpha    (NTDLL.@)
311  *
312  * Checks if an unicode char wc is a letter
313  *
314  * RETURNS
315  *  TRUE: The unicode char wc is a letter.
316  *  FALSE: Otherwise
317  */
318 INT __cdecl NTDLL_iswalpha( WCHAR wc )
319 {
320     return isalphaW(wc);
321 }
322
323
324 /*********************************************************************
325  *              iswdigit (NTDLL.@)
326  *
327  * Checks if an unicode char wc is a digit
328  *
329  * RETURNS
330  *  TRUE: The unicode char wc is a digit.
331  *  FALSE: Otherwise
332  */
333 INT __cdecl NTDLL_iswdigit( WCHAR wc )
334 {
335     return isdigitW(wc);
336 }
337
338
339 /*********************************************************************
340  *              iswlower (NTDLL.@)
341  *
342  * Checks if an unicode char wc is a lower case letter
343  *
344  * RETURNS
345  *  TRUE: The unicode char wc is a lower case letter.
346  *  FALSE: Otherwise
347  */
348 INT __cdecl NTDLL_iswlower( WCHAR wc )
349 {
350     return islowerW(wc);
351 }
352
353
354 /*********************************************************************
355  *              iswspace (NTDLL.@)
356  *
357  * Checks if an unicode char wc is a white space character
358  *
359  * RETURNS
360  *  TRUE: The unicode char wc is a white space character.
361  *  FALSE: Otherwise
362  */
363 INT __cdecl NTDLL_iswspace( WCHAR wc )
364 {
365     return isspaceW(wc);
366 }
367
368
369 /*********************************************************************
370  *              iswxdigit (NTDLL.@)
371  *
372  * Checks if an unicode char wc is an extended digit
373  *
374  * RETURNS
375  *  TRUE: The unicode char wc is an extended digit.
376  *  FALSE: Otherwise
377  */
378 INT __cdecl NTDLL_iswxdigit( WCHAR wc )
379 {
380     return isxdigitW(wc);
381 }
382
383
384 /*********************************************************************
385  *      _ultow   (NTDLL.@)
386  *
387  * Converts an unsigned long integer to an unicode string.
388  *
389  * RETURNS
390  *  Always returns str.
391  *
392  * NOTES
393  *  Converts value to a '\0' terminated wstring which is copied to str.
394  *  The maximum length of the copied str is 33 bytes.
395  *  Does not check if radix is in the range of 2 to 36.
396  *  If str is NULL it just returns NULL.
397  */
398 LPWSTR __cdecl _ultow(
399     unsigned long value, /* [I] Value to be converted */
400     LPWSTR str,          /* [O] Destination for the converted value */
401     INT radix)           /* [I] Number base for conversion */
402 {
403     WCHAR buffer[33];
404     PWCHAR pos;
405     WCHAR digit;
406
407     pos = &buffer[32];
408     *pos = '\0';
409
410     do {
411         digit = value % radix;
412         value = value / radix;
413         if (digit < 10) {
414             *--pos = '0' + digit;
415         } else {
416             *--pos = 'a' + digit - 10;
417         } /* if */
418     } while (value != 0L);
419
420     if (str != NULL) {
421         memcpy(str, pos, (&buffer[32] - pos + 1) * sizeof(WCHAR));
422     } /* if */
423     return str;
424 }
425
426
427 /*********************************************************************
428  *      _ltow   (NTDLL.@)
429  *
430  * Converts a long integer to an unicode string.
431  *
432  * RETURNS
433  *  Always returns str.
434  *
435  * NOTES
436  *  Converts value to a '\0' terminated wstring which is copied to str.
437  *  The maximum length of the copied str is 33 bytes. If radix
438  *  is 10 and value is negative, the value is converted with sign.
439  *  Does not check if radix is in the range of 2 to 36.
440  *  If str is NULL it just returns NULL.
441  */
442 LPWSTR __cdecl _ltow(
443     long value, /* [I] Value to be converted */
444     LPWSTR str, /* [O] Destination for the converted value */
445     INT radix)  /* [I] Number base for conversion */
446 {
447     unsigned long val;
448     int negative;
449     WCHAR buffer[33];
450     PWCHAR pos;
451     WCHAR digit;
452
453     if (value < 0 && radix == 10) {
454         negative = 1;
455         val = -value;
456     } else {
457         negative = 0;
458         val = value;
459     } /* if */
460
461     pos = &buffer[32];
462     *pos = '\0';
463
464     do {
465         digit = val % radix;
466         val = val / radix;
467         if (digit < 10) {
468             *--pos = '0' + digit;
469         } else {
470             *--pos = 'a' + digit - 10;
471         } /* if */
472     } while (val != 0L);
473
474     if (negative) {
475         *--pos = '-';
476     } /* if */
477
478     if (str != NULL) {
479         memcpy(str, pos, (&buffer[32] - pos + 1) * sizeof(WCHAR));
480     } /* if */
481     return str;
482 }
483
484
485 /*********************************************************************
486  *      _itow    (NTDLL.@)
487  *
488  * Converts an integer to an unicode string.
489  *
490  * RETURNS
491  *  Always returns str.
492  *
493  * NOTES
494  *  Converts value to a '\0' terminated wstring which is copied to str.
495  *  The maximum length of the copied str is 33 bytes. If radix
496  *  is 10 and value is negative, the value is converted with sign.
497  *  Does not check if radix is in the range of 2 to 36.
498  *  If str is NULL it just returns NULL.
499  *
500  * DIFFERENCES
501  * - The native function crashes when the string is longer than 19 chars.
502  *   This function does not have this bug.
503  */
504 LPWSTR __cdecl _itow(
505     int value,  /* [I] Value to be converted */
506     LPWSTR str, /* [O] Destination for the converted value */
507     INT radix)  /* [I] Number base for conversion */
508 {
509     return _ltow(value, str, radix);
510 }
511
512
513 /*********************************************************************
514  *      _ui64tow   (NTDLL.@)
515  *
516  * Converts a large unsigned integer to an unicode string.
517  *
518  * RETURNS
519  *  Always returns str.
520  *
521  * NOTES
522  *  Converts value to a '\0' terminated wstring which is copied to str.
523  *  The maximum length of the copied str is 33 bytes.
524  *  Does not check if radix is in the range of 2 to 36.
525  *  If str is NULL it just returns NULL.
526  *
527  * DIFFERENCES
528  * - This function does not exist in the native DLL (but in msvcrt).
529  *   But since the maintenance of all these functions is better done
530  *   in one place we implement it here.
531  */
532 LPWSTR __cdecl _ui64tow(
533     ULONGLONG value, /* [I] Value to be converted */
534     LPWSTR str,      /* [O] Destination for the converted value */
535     INT radix)       /* [I] Number base for conversion */
536 {
537     WCHAR buffer[65];
538     PWCHAR pos;
539     WCHAR digit;
540
541     pos = &buffer[64];
542     *pos = '\0';
543
544     do {
545         digit = value % radix;
546         value = value / radix;
547         if (digit < 10) {
548             *--pos = '0' + digit;
549         } else {
550             *--pos = 'a' + digit - 10;
551         } /* if */
552     } while (value != 0L);
553
554     if (str != NULL) {
555         memcpy(str, pos, (&buffer[64] - pos + 1) * sizeof(WCHAR));
556     } /* if */
557     return str;
558 }
559
560
561 /*********************************************************************
562  *      _i64tow   (NTDLL.@)
563  *
564  * Converts a large integer to an unicode string.
565  *
566  * RETURNS
567  *  Always returns str.
568  *
569  * NOTES
570  *  Converts value to a '\0' terminated wstring which is copied to str.
571  *  The maximum length of the copied str is 33 bytes. If radix
572  *  is 10 and value is negative, the value is converted with sign.
573  *  Does not check if radix is in the range of 2 to 36.
574  *  If str is NULL it just returns NULL.
575  *
576  * DIFFERENCES
577  * - The native DLL converts negative values (for base 10) wrong:
578  *                     -1 is converted to -18446744073709551615
579  *                     -2 is converted to -18446744073709551614
580  *   -9223372036854775807 is converted to  -9223372036854775809
581  *   -9223372036854775808 is converted to  -9223372036854775808
582  *   The native msvcrt _i64tow function and our ntdll function do
583  *   not have this bug.
584  */
585 LPWSTR __cdecl _i64tow(
586     LONGLONG value, /* [I] Value to be converted */
587     LPWSTR str,     /* [O] Destination for the converted value */
588     INT radix)      /* [I] Number base for conversion */
589 {
590     ULONGLONG val;
591     int negative;
592     WCHAR buffer[65];
593     PWCHAR pos;
594     WCHAR digit;
595
596     if (value < 0 && radix == 10) {
597         negative = 1;
598         val = -value;
599     } else {
600         negative = 0;
601         val = value;
602     } /* if */
603
604     pos = &buffer[64];
605     *pos = '\0';
606
607     do {
608         digit = val % radix;
609         val = val / radix;
610         if (digit < 10) {
611             *--pos = '0' + digit;
612         } else {
613             *--pos = 'a' + digit - 10;
614         } /* if */
615     } while (val != 0L);
616
617     if (negative) {
618         *--pos = '-';
619     } /* if */
620
621     if (str != NULL) {
622         memcpy(str, pos, (&buffer[64] - pos + 1) * sizeof(WCHAR));
623     } /* if */
624     return str;
625 }
626
627
628 /*********************************************************************
629  *      _wtol    (NTDLL.@)
630  *
631  * Converts an unicode string to a long integer.
632  *
633  * PARAMS
634  *  str [I] Wstring to be converted
635  *
636  * RETURNS
637  *  On success it returns the integer value otherwise it returns 0.
638  *
639  * NOTES
640  *  Accepts: {whitespace} [+|-] {digits}
641  *  No check is made for value overflow, only the lower 32 bits are assigned.
642  *  If str is NULL it crashes, as the native function does.
643  */
644 LONG __cdecl _wtol( LPCWSTR str )
645 {
646     ULONG RunningTotal = 0;
647     char bMinus = 0;
648
649     while (isspaceW(*str)) {
650         str++;
651     } /* while */
652
653     if (*str == '+') {
654         str++;
655     } else if (*str == '-') {
656         bMinus = 1;
657         str++;
658     } /* if */
659
660     while (*str >= '0' && *str <= '9') {
661         RunningTotal = RunningTotal * 10 + *str - '0';
662         str++;
663     } /* while */
664
665     return bMinus ? -RunningTotal : RunningTotal;
666 }
667
668
669 /*********************************************************************
670  *      _wtoi    (NTDLL.@)
671  *
672  * Converts an unicode string to an integer.
673  *
674  * PARAMS
675  *  str [I] Wstring to be converted
676  *
677  * RETURNS
678  *  On success it returns the integer value otherwise it returns 0.
679  *
680  * NOTES
681  *  Accepts: {whitespace} [+|-] {digits}
682  *  No check is made for value overflow, only the lower 32 bits are assigned.
683  *  If str is NULL it crashes, as the native function does.
684  */
685 int __cdecl _wtoi( LPCWSTR str )
686 {
687     return _wtol(str);
688 }
689
690
691 /*********************************************************************
692  *      _wtoi64   (NTDLL.@)
693  *
694  * Converts an unicode string to a large integer.
695  *
696  * PARAMS
697  *  str [I] Wstring to be converted
698  *
699  * RETURNS
700  *  On success it returns the integer value otherwise it returns 0.
701  *
702  * NOTES
703  *  Accepts: {whitespace} [+|-] {digits}
704  *  No check is made for value overflow, only the lower 64 bits are assigned.
705  *  If str is NULL it crashes, as the native function does.
706  */
707 LONGLONG  __cdecl _wtoi64( LPCWSTR str )
708 {
709     ULONGLONG RunningTotal = 0;
710     char bMinus = 0;
711
712     while (isspaceW(*str)) {
713         str++;
714     } /* while */
715
716     if (*str == '+') {
717         str++;
718     } else if (*str == '-') {
719         bMinus = 1;
720         str++;
721     } /* if */
722
723     while (*str >= '0' && *str <= '9') {
724         RunningTotal = RunningTotal * 10 + *str - '0';
725         str++;
726     } /* while */
727
728     return bMinus ? -RunningTotal : RunningTotal;
729 }
730
731
732 /***********************************************************************
733  *        _snwprintf (NTDLL.@)
734  */
735 int __cdecl _snwprintf(WCHAR *str, unsigned int len, const WCHAR *format, ...)
736 {
737   int retval;
738   va_list valist;
739   va_start(valist, format);
740   retval = vsnprintfW(str, len, format, valist);
741   va_end(valist);
742   return retval;
743 }
744
745
746 /***********************************************************************
747  *        swprintf (NTDLL.@)
748  */
749 int __cdecl NTDLL_swprintf(WCHAR *str, const WCHAR *format, ...)
750 {
751   int retval;
752   va_list valist;
753   va_start(valist, format);
754   retval = vsnprintfW(str, INT_MAX, format, valist);
755   va_end(valist);
756   return retval;
757 }
758
759
760 /***********************************************************************
761  *        _vsnwprintf (NTDLL.@)
762  */
763 int __cdecl _vsnwprintf( WCHAR *str, unsigned int len, const WCHAR *format, va_list args )
764 {
765   return vsnprintfW( str, len, format, args );
766 }