dbghelp: StackWalk (32 and 64 bit version).
[wine/multimedia.git] / dlls / ntdll / wcstring.c
blobd42f4925dd34f372d9e80bca8c1fb8d18580b73c
1 /*
2 * NTDLL wide-char functions
4 * Copyright 2000 Alexandre Julliard
5 * Copyright 2000 Jon Griffiths
6 * Copyright 2003 Thomas Mertes
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.
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.
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
23 #include "config.h"
25 #include <ctype.h>
26 #include <limits.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <stdarg.h>
30 #include <stdio.h>
32 #include "windef.h"
33 #include "winternl.h"
34 #include "wine/unicode.h"
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
40 /*********************************************************************
41 * _wcsicmp (NTDLL.@)
43 INT __cdecl NTDLL__wcsicmp( LPCWSTR str1, LPCWSTR str2 )
45 return strcmpiW( str1, str2 );
49 /*********************************************************************
50 * _wcslwr (NTDLL.@)
52 LPWSTR __cdecl NTDLL__wcslwr( LPWSTR str )
54 return strlwrW( str );
58 /*********************************************************************
59 * _wcsnicmp (NTDLL.@)
61 INT __cdecl NTDLL__wcsnicmp( LPCWSTR str1, LPCWSTR str2, INT n )
63 return strncmpiW( str1, str2, n );
67 /*********************************************************************
68 * _wcsupr (NTDLL.@)
70 LPWSTR __cdecl NTDLL__wcsupr( LPWSTR str )
72 return struprW( str );
76 /*********************************************************************
77 * towlower (NTDLL.@)
79 WCHAR __cdecl NTDLL_towlower( WCHAR ch )
81 return tolowerW(ch);
85 /*********************************************************************
86 * towupper (NTDLL.@)
88 WCHAR __cdecl NTDLL_towupper( WCHAR ch )
90 return toupperW(ch);
94 /***********************************************************************
95 * wcscat (NTDLL.@)
97 LPWSTR __cdecl NTDLL_wcscat( LPWSTR dst, LPCWSTR src )
99 return strcatW( dst, src );
103 /*********************************************************************
104 * wcschr (NTDLL.@)
106 LPWSTR __cdecl NTDLL_wcschr( LPCWSTR str, WCHAR ch )
108 return strchrW( str, ch );
112 /*********************************************************************
113 * wcscmp (NTDLL.@)
115 INT __cdecl NTDLL_wcscmp( LPCWSTR str1, LPCWSTR str2 )
117 return strcmpW( str1, str2 );
121 /***********************************************************************
122 * wcscpy (NTDLL.@)
124 LPWSTR __cdecl NTDLL_wcscpy( LPWSTR dst, LPCWSTR src )
126 return strcpyW( dst, src );
130 /*********************************************************************
131 * wcscspn (NTDLL.@)
133 INT __cdecl NTDLL_wcscspn( LPCWSTR str, LPCWSTR reject )
135 return strcspnW( str, reject );
139 /***********************************************************************
140 * wcslen (NTDLL.@)
142 INT __cdecl NTDLL_wcslen( LPCWSTR str )
144 return strlenW( str );
148 /*********************************************************************
149 * wcsncat (NTDLL.@)
151 LPWSTR __cdecl NTDLL_wcsncat( LPWSTR s1, LPCWSTR s2, INT n )
153 LPWSTR ret = s1;
154 while (*s1) s1++;
155 while (n-- > 0) if (!(*s1++ = *s2++)) return ret;
156 *s1 = 0;
157 return ret;
161 /*********************************************************************
162 * wcsncmp (NTDLL.@)
164 INT __cdecl NTDLL_wcsncmp( LPCWSTR str1, LPCWSTR str2, INT n )
166 return strncmpW( str1, str2, n );
170 /*********************************************************************
171 * wcsncpy (NTDLL.@)
173 LPWSTR __cdecl NTDLL_wcsncpy( LPWSTR s1, LPCWSTR s2, INT n )
175 WCHAR *ret = s1;
176 while (n-- > 0) if (!(*s1++ = *s2++)) break;
177 while (n-- > 0) *s1++ = 0;
178 return ret;
182 /*********************************************************************
183 * wcspbrk (NTDLL.@)
185 LPWSTR __cdecl NTDLL_wcspbrk( LPCWSTR str, LPCWSTR accept )
187 return strpbrkW( str, accept );
191 /*********************************************************************
192 * wcsrchr (NTDLL.@)
194 LPWSTR __cdecl NTDLL_wcsrchr( LPWSTR str, WCHAR ch )
196 return strrchrW( str, ch );
200 /*********************************************************************
201 * wcsspn (NTDLL.@)
203 INT __cdecl NTDLL_wcsspn( LPCWSTR str, LPCWSTR accept )
205 return strspnW( str, accept );
209 /*********************************************************************
210 * wcsstr (NTDLL.@)
212 LPWSTR __cdecl NTDLL_wcsstr( LPCWSTR str, LPCWSTR sub )
214 return strstrW( str, sub );
218 /*********************************************************************
219 * wcstok (NTDLL.@)
221 LPWSTR __cdecl NTDLL_wcstok( LPWSTR str, LPCWSTR delim )
223 static LPWSTR next = NULL;
224 LPWSTR ret;
226 if (!str)
227 if (!(str = next)) return NULL;
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;
239 /*********************************************************************
240 * wcstombs (NTDLL.@)
242 INT __cdecl NTDLL_wcstombs( LPSTR dst, LPCWSTR src, INT n )
244 DWORD len;
246 if (!dst)
248 RtlUnicodeToMultiByteSize( &len, src, strlenW(src)*sizeof(WCHAR) );
249 return len;
251 else
253 if (n <= 0) return 0;
254 RtlUnicodeToMultiByteN( dst, n, &len, src, strlenW(src)*sizeof(WCHAR) );
255 if (len < n) dst[len] = 0;
257 return len;
261 /*********************************************************************
262 * mbstowcs (NTDLL.@)
264 INT __cdecl NTDLL_mbstowcs( LPWSTR dst, LPCSTR src, INT n )
266 DWORD len;
268 if (!dst)
270 RtlMultiByteToUnicodeSize( &len, src, strlen(src) );
272 else
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;
278 return len / sizeof(WCHAR);
282 /*********************************************************************
283 * wcstol (NTDLL.@)
285 long __cdecl NTDLL_wcstol(LPCWSTR s,LPWSTR *end,INT base)
287 return strtolW( s, end, base );
291 /*********************************************************************
292 * wcstoul (NTDLL.@)
294 unsigned long __cdecl NTDLL_wcstoul(LPCWSTR s,LPWSTR *end,INT base)
296 return strtoulW( s, end, base );
300 /*********************************************************************
301 * iswctype (NTDLL.@)
303 INT __cdecl NTDLL_iswctype( WCHAR wc, WCHAR wct )
305 return (get_char_typeW(wc) & 0xfff) & wct;
309 /*********************************************************************
310 * iswalpha (NTDLL.@)
312 * Checks if an unicode char wc is a letter
314 * RETURNS
315 * TRUE: The unicode char wc is a letter.
316 * FALSE: Otherwise
318 INT __cdecl NTDLL_iswalpha( WCHAR wc )
320 return isalphaW(wc);
324 /*********************************************************************
325 * iswdigit (NTDLL.@)
327 * Checks if an unicode char wc is a digit
329 * RETURNS
330 * TRUE: The unicode char wc is a digit.
331 * FALSE: Otherwise
333 INT __cdecl NTDLL_iswdigit( WCHAR wc )
335 return isdigitW(wc);
339 /*********************************************************************
340 * iswlower (NTDLL.@)
342 * Checks if an unicode char wc is a lower case letter
344 * RETURNS
345 * TRUE: The unicode char wc is a lower case letter.
346 * FALSE: Otherwise
348 INT __cdecl NTDLL_iswlower( WCHAR wc )
350 return islowerW(wc);
354 /*********************************************************************
355 * iswspace (NTDLL.@)
357 * Checks if an unicode char wc is a white space character
359 * RETURNS
360 * TRUE: The unicode char wc is a white space character.
361 * FALSE: Otherwise
363 INT __cdecl NTDLL_iswspace( WCHAR wc )
365 return isspaceW(wc);
369 /*********************************************************************
370 * iswxdigit (NTDLL.@)
372 * Checks if an unicode char wc is an extended digit
374 * RETURNS
375 * TRUE: The unicode char wc is an extended digit.
376 * FALSE: Otherwise
378 INT __cdecl NTDLL_iswxdigit( WCHAR wc )
380 return isxdigitW(wc);
384 /*********************************************************************
385 * _ultow (NTDLL.@)
387 * Converts an unsigned long integer to an unicode string.
389 * RETURNS
390 * Always returns str.
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.
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 */
403 WCHAR buffer[33];
404 PWCHAR pos;
405 WCHAR digit;
407 pos = &buffer[32];
408 *pos = '\0';
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);
420 if (str != NULL) {
421 memcpy(str, pos, (&buffer[32] - pos + 1) * sizeof(WCHAR));
422 } /* if */
423 return str;
427 /*********************************************************************
428 * _ltow (NTDLL.@)
430 * Converts a long integer to an unicode string.
432 * RETURNS
433 * Always returns str.
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.
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 */
447 unsigned long val;
448 int negative;
449 WCHAR buffer[33];
450 PWCHAR pos;
451 WCHAR digit;
453 if (value < 0 && radix == 10) {
454 negative = 1;
455 val = -value;
456 } else {
457 negative = 0;
458 val = value;
459 } /* if */
461 pos = &buffer[32];
462 *pos = '\0';
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);
474 if (negative) {
475 *--pos = '-';
476 } /* if */
478 if (str != NULL) {
479 memcpy(str, pos, (&buffer[32] - pos + 1) * sizeof(WCHAR));
480 } /* if */
481 return str;
485 /*********************************************************************
486 * _itow (NTDLL.@)
488 * Converts an integer to an unicode string.
490 * RETURNS
491 * Always returns str.
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.
500 * DIFFERENCES
501 * - The native function crashes when the string is longer than 19 chars.
502 * This function does not have this bug.
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 */
509 return _ltow(value, str, radix);
513 /*********************************************************************
514 * _ui64tow (NTDLL.@)
516 * Converts a large unsigned integer to an unicode string.
518 * RETURNS
519 * Always returns str.
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.
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.
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 */
537 WCHAR buffer[65];
538 PWCHAR pos;
539 WCHAR digit;
541 pos = &buffer[64];
542 *pos = '\0';
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);
554 if (str != NULL) {
555 memcpy(str, pos, (&buffer[64] - pos + 1) * sizeof(WCHAR));
556 } /* if */
557 return str;
561 /*********************************************************************
562 * _i64tow (NTDLL.@)
564 * Converts a large integer to an unicode string.
566 * RETURNS
567 * Always returns str.
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.
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.
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 */
590 ULONGLONG val;
591 int negative;
592 WCHAR buffer[65];
593 PWCHAR pos;
594 WCHAR digit;
596 if (value < 0 && radix == 10) {
597 negative = 1;
598 val = -value;
599 } else {
600 negative = 0;
601 val = value;
602 } /* if */
604 pos = &buffer[64];
605 *pos = '\0';
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);
617 if (negative) {
618 *--pos = '-';
619 } /* if */
621 if (str != NULL) {
622 memcpy(str, pos, (&buffer[64] - pos + 1) * sizeof(WCHAR));
623 } /* if */
624 return str;
628 /*********************************************************************
629 * _wtol (NTDLL.@)
631 * Converts an unicode string to a long integer.
633 * PARAMS
634 * str [I] Wstring to be converted
636 * RETURNS
637 * On success it returns the integer value otherwise it returns 0.
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.
644 LONG __cdecl _wtol( LPCWSTR str )
646 ULONG RunningTotal = 0;
647 char bMinus = 0;
649 while (isspaceW(*str)) {
650 str++;
651 } /* while */
653 if (*str == '+') {
654 str++;
655 } else if (*str == '-') {
656 bMinus = 1;
657 str++;
658 } /* if */
660 while (*str >= '0' && *str <= '9') {
661 RunningTotal = RunningTotal * 10 + *str - '0';
662 str++;
663 } /* while */
665 return bMinus ? -RunningTotal : RunningTotal;
669 /*********************************************************************
670 * _wtoi (NTDLL.@)
672 * Converts an unicode string to an integer.
674 * PARAMS
675 * str [I] Wstring to be converted
677 * RETURNS
678 * On success it returns the integer value otherwise it returns 0.
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.
685 int __cdecl _wtoi( LPCWSTR str )
687 return _wtol(str);
691 /*********************************************************************
692 * _wtoi64 (NTDLL.@)
694 * Converts an unicode string to a large integer.
696 * PARAMS
697 * str [I] Wstring to be converted
699 * RETURNS
700 * On success it returns the integer value otherwise it returns 0.
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.
707 LONGLONG __cdecl _wtoi64( LPCWSTR str )
709 ULONGLONG RunningTotal = 0;
710 char bMinus = 0;
712 while (isspaceW(*str)) {
713 str++;
714 } /* while */
716 if (*str == '+') {
717 str++;
718 } else if (*str == '-') {
719 bMinus = 1;
720 str++;
721 } /* if */
723 while (*str >= '0' && *str <= '9') {
724 RunningTotal = RunningTotal * 10 + *str - '0';
725 str++;
726 } /* while */
728 return bMinus ? -RunningTotal : RunningTotal;
732 /***********************************************************************
733 * _snwprintf (NTDLL.@)
735 int __cdecl _snwprintf(WCHAR *str, unsigned int len, const WCHAR *format, ...)
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;
746 /***********************************************************************
747 * swprintf (NTDLL.@)
749 int __cdecl NTDLL_swprintf(WCHAR *str, const WCHAR *format, ...)
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;