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