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