Avoid referencing stackframe.h from outside kernel32.
[wine/testsucceed.git] / dlls / ntdll / wcstring.c
blob93ba2b6eeb318d728e020ebb509b28352e248f45
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 "winbase.h"
34 #include "winreg.h"
35 #include "winternl.h"
36 #include "wine/unicode.h"
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
42 /*********************************************************************
43 * _wcsicmp (NTDLL.@)
45 INT __cdecl NTDLL__wcsicmp( LPCWSTR str1, LPCWSTR str2 )
47 return strcmpiW( str1, str2 );
51 /*********************************************************************
52 * _wcslwr (NTDLL.@)
54 LPWSTR __cdecl NTDLL__wcslwr( LPWSTR str )
56 return strlwrW( str );
60 /*********************************************************************
61 * _wcsnicmp (NTDLL.@)
63 INT __cdecl NTDLL__wcsnicmp( LPCWSTR str1, LPCWSTR str2, INT n )
65 return strncmpiW( str1, str2, n );
69 /*********************************************************************
70 * _wcsupr (NTDLL.@)
72 LPWSTR __cdecl NTDLL__wcsupr( LPWSTR str )
74 return struprW( str );
78 /*********************************************************************
79 * towlower (NTDLL.@)
81 WCHAR __cdecl NTDLL_towlower( WCHAR ch )
83 return tolowerW(ch);
87 /*********************************************************************
88 * towupper (NTDLL.@)
90 WCHAR __cdecl NTDLL_towupper( WCHAR ch )
92 return toupperW(ch);
96 /***********************************************************************
97 * wcscat (NTDLL.@)
99 LPWSTR __cdecl NTDLL_wcscat( LPWSTR dst, LPCWSTR src )
101 return strcatW( dst, src );
105 /*********************************************************************
106 * wcschr (NTDLL.@)
108 LPWSTR __cdecl NTDLL_wcschr( LPCWSTR str, WCHAR ch )
110 return strchrW( str, ch );
114 /*********************************************************************
115 * wcscmp (NTDLL.@)
117 INT __cdecl NTDLL_wcscmp( LPCWSTR str1, LPCWSTR str2 )
119 return strcmpW( str1, str2 );
123 /***********************************************************************
124 * wcscpy (NTDLL.@)
126 LPWSTR __cdecl NTDLL_wcscpy( LPWSTR dst, LPCWSTR src )
128 return strcpyW( dst, src );
132 /*********************************************************************
133 * wcscspn (NTDLL.@)
135 INT __cdecl NTDLL_wcscspn( LPCWSTR str, LPCWSTR reject )
137 LPCWSTR start = str;
138 while (*str)
140 LPCWSTR p = reject;
141 while (*p && (*p != *str)) p++;
142 if (*p) break;
143 str++;
145 return str - start;
149 /***********************************************************************
150 * wcslen (NTDLL.@)
152 INT __cdecl NTDLL_wcslen( LPCWSTR str )
154 return strlenW( str );
158 /*********************************************************************
159 * wcsncat (NTDLL.@)
161 LPWSTR __cdecl NTDLL_wcsncat( LPWSTR s1, LPCWSTR s2, INT n )
163 LPWSTR ret = s1;
164 while (*s1) s1++;
165 while (n-- > 0) if (!(*s1++ = *s2++)) return ret;
166 *s1 = 0;
167 return ret;
171 /*********************************************************************
172 * wcsncmp (NTDLL.@)
174 INT __cdecl NTDLL_wcsncmp( LPCWSTR str1, LPCWSTR str2, INT n )
176 return strncmpW( str1, str2, n );
180 /*********************************************************************
181 * wcsncpy (NTDLL.@)
183 LPWSTR __cdecl NTDLL_wcsncpy( LPWSTR s1, LPCWSTR s2, INT n )
185 WCHAR *ret = s1;
186 while (n-- > 0) if (!(*s1++ = *s2++)) break;
187 while (n-- > 0) *s1++ = 0;
188 return ret;
192 /*********************************************************************
193 * wcspbrk (NTDLL.@)
195 LPWSTR __cdecl NTDLL_wcspbrk( LPCWSTR str, LPCWSTR accept )
197 LPCWSTR p;
198 while (*str)
200 for (p = accept; *p; p++) if (*p == *str) return (LPWSTR)str;
201 str++;
203 return NULL;
207 /*********************************************************************
208 * wcsrchr (NTDLL.@)
210 LPWSTR __cdecl NTDLL_wcsrchr( LPWSTR str, WCHAR ch )
212 LPWSTR last = NULL;
213 while (*str)
215 if (*str == ch) last = str;
216 str++;
218 return last;
222 /*********************************************************************
223 * wcsspn (NTDLL.@)
225 INT __cdecl NTDLL_wcsspn( LPCWSTR str, LPCWSTR accept )
227 LPCWSTR start = str;
228 while (*str)
230 LPCWSTR p = accept;
231 while (*p && (*p != *str)) p++;
232 if (!*p) break;
233 str++;
235 return str - start;
239 /*********************************************************************
240 * wcsstr (NTDLL.@)
242 LPWSTR __cdecl NTDLL_wcsstr( LPCWSTR str, LPCWSTR sub )
244 return strstrW( str, sub );
248 /*********************************************************************
249 * wcstok (NTDLL.@)
251 LPWSTR __cdecl NTDLL_wcstok( LPWSTR str, LPCWSTR delim )
253 static LPWSTR next = NULL;
254 LPWSTR ret;
256 if (!str)
257 if (!(str = next)) return NULL;
259 while (*str && NTDLL_wcschr( delim, *str )) str++;
260 if (!*str) return NULL;
261 ret = str++;
262 while (*str && !NTDLL_wcschr( delim, *str )) str++;
263 if (*str) *str++ = 0;
264 next = str;
265 return ret;
269 /*********************************************************************
270 * wcstombs (NTDLL.@)
272 INT __cdecl NTDLL_wcstombs( LPSTR dst, LPCWSTR src, INT n )
274 DWORD len;
276 if (!dst)
278 RtlUnicodeToMultiByteSize( &len, src, strlenW(src)*sizeof(WCHAR) );
279 return len;
281 else
283 if (n <= 0) return 0;
284 RtlUnicodeToMultiByteN( dst, n, &len, src, strlenW(src)*sizeof(WCHAR) );
285 if (len < n) dst[len] = 0;
287 return len;
291 /*********************************************************************
292 * mbstowcs (NTDLL.@)
294 INT __cdecl NTDLL_mbstowcs( LPWSTR dst, LPCSTR src, INT n )
296 DWORD len;
298 if (!dst)
300 RtlMultiByteToUnicodeSize( &len, src, strlen(src) );
302 else
304 if (n <= 0) return 0;
305 RtlMultiByteToUnicodeN( dst, n*sizeof(WCHAR), &len, src, strlen(src) );
306 if (len / sizeof(WCHAR) < n) dst[len / sizeof(WCHAR)] = 0;
308 return len / sizeof(WCHAR);
312 /*********************************************************************
313 * wcstol (NTDLL.@)
315 long __cdecl NTDLL_wcstol(LPCWSTR s,LPWSTR *end,INT base)
317 return strtolW( s, end, base );
321 /*********************************************************************
322 * wcstoul (NTDLL.@)
324 unsigned long __cdecl NTDLL_wcstoul(LPCWSTR s,LPWSTR *end,INT base)
326 return strtoulW( s, end, base );
330 /*********************************************************************
331 * iswctype (NTDLL.@)
333 INT __cdecl NTDLL_iswctype( WCHAR wc, WCHAR wct )
335 return (get_char_typeW(wc) & 0xfff) & wct;
339 /*********************************************************************
340 * iswalpha (NTDLL.@)
342 * Checks if an unicode char wc is a letter
344 * RETURNS
345 * TRUE: The unicode char wc is a letter.
346 * FALSE: Otherwise
348 INT __cdecl NTDLL_iswalpha( WCHAR wc )
350 return isalphaW(wc);
354 /*********************************************************************
355 * iswdigit (NTDLL.@)
357 * Checks if an unicode char wc is a digit
359 * RETURNS
360 * TRUE: The unicode char wc is a digit.
361 * FALSE: Otherwise
363 INT __cdecl NTDLL_iswdigit( WCHAR wc )
365 return isdigitW(wc);
369 /*********************************************************************
370 * iswlower (NTDLL.@)
372 * Checks if an unicode char wc is a lower case letter
374 * RETURNS
375 * TRUE: The unicode char wc is a lower case letter.
376 * FALSE: Otherwise
378 INT __cdecl NTDLL_iswlower( WCHAR wc )
380 return islowerW(wc);
384 /*********************************************************************
385 * iswspace (NTDLL.@)
387 * Checks if an unicode char wc is a white space character
389 * RETURNS
390 * TRUE: The unicode char wc is a white space character.
391 * FALSE: Otherwise
393 INT __cdecl NTDLL_iswspace( WCHAR wc )
395 return isspaceW(wc);
399 /*********************************************************************
400 * iswxdigit (NTDLL.@)
402 * Checks if an unicode char wc is an extended digit
404 * RETURNS
405 * TRUE: The unicode char wc is an extended digit.
406 * FALSE: Otherwise
408 INT __cdecl NTDLL_iswxdigit( WCHAR wc )
410 return isxdigitW(wc);
414 /*********************************************************************
415 * _ultow (NTDLL.@)
417 * Converts an unsigned long integer to an unicode string.
419 * RETURNS
420 * Always returns str.
422 * NOTES
423 * Converts value to a '\0' terminated wstring which is copied to str.
424 * The maximum length of the copied str is 33 bytes.
425 * Does not check if radix is in the range of 2 to 36.
426 * If str is NULL it just returns NULL.
428 LPWSTR __cdecl _ultow(
429 unsigned long value, /* [I] Value to be converted */
430 LPWSTR str, /* [O] Destination for the converted value */
431 INT radix) /* [I] Number base for conversion */
433 WCHAR buffer[33];
434 PWCHAR pos;
435 WCHAR digit;
437 pos = &buffer[32];
438 *pos = '\0';
440 do {
441 digit = value % radix;
442 value = value / radix;
443 if (digit < 10) {
444 *--pos = '0' + digit;
445 } else {
446 *--pos = 'a' + digit - 10;
447 } /* if */
448 } while (value != 0L);
450 if (str != NULL) {
451 memcpy(str, pos, (&buffer[32] - pos + 1) * sizeof(WCHAR));
452 } /* if */
453 return str;
457 /*********************************************************************
458 * _ltow (NTDLL.@)
460 * Converts a long integer to an unicode string.
462 * RETURNS
463 * Always returns str.
465 * NOTES
466 * Converts value to a '\0' terminated wstring which is copied to str.
467 * The maximum length of the copied str is 33 bytes. If radix
468 * is 10 and value is negative, the value is converted with sign.
469 * Does not check if radix is in the range of 2 to 36.
470 * If str is NULL it just returns NULL.
472 LPWSTR __cdecl _ltow(
473 long value, /* [I] Value to be converted */
474 LPWSTR str, /* [O] Destination for the converted value */
475 INT radix) /* [I] Number base for conversion */
477 unsigned long val;
478 int negative;
479 WCHAR buffer[33];
480 PWCHAR pos;
481 WCHAR digit;
483 if (value < 0 && radix == 10) {
484 negative = 1;
485 val = -value;
486 } else {
487 negative = 0;
488 val = value;
489 } /* if */
491 pos = &buffer[32];
492 *pos = '\0';
494 do {
495 digit = val % radix;
496 val = val / radix;
497 if (digit < 10) {
498 *--pos = '0' + digit;
499 } else {
500 *--pos = 'a' + digit - 10;
501 } /* if */
502 } while (val != 0L);
504 if (negative) {
505 *--pos = '-';
506 } /* if */
508 if (str != NULL) {
509 memcpy(str, pos, (&buffer[32] - pos + 1) * sizeof(WCHAR));
510 } /* if */
511 return str;
515 /*********************************************************************
516 * _itow (NTDLL.@)
518 * Converts an integer to an unicode string.
520 * RETURNS
521 * Always returns str.
523 * NOTES
524 * Converts value to a '\0' terminated wstring which is copied to str.
525 * The maximum length of the copied str is 33 bytes. If radix
526 * is 10 and value is negative, the value is converted with sign.
527 * Does not check if radix is in the range of 2 to 36.
528 * If str is NULL it just returns NULL.
530 * DIFFERENCES
531 * - The native function crashes when the string is longer than 19 chars.
532 * This function does not have this bug.
534 LPWSTR __cdecl _itow(
535 int value, /* [I] Value to be converted */
536 LPWSTR str, /* [O] Destination for the converted value */
537 INT radix) /* [I] Number base for conversion */
539 return _ltow(value, str, radix);
543 /*********************************************************************
544 * _ui64tow (NTDLL.@)
546 * Converts a large unsigned integer to an unicode string.
548 * RETURNS
549 * Always returns str.
551 * NOTES
552 * Converts value to a '\0' terminated wstring which is copied to str.
553 * The maximum length of the copied str is 33 bytes.
554 * Does not check if radix is in the range of 2 to 36.
555 * If str is NULL it just returns NULL.
557 * DIFFERENCES
558 * - This function does not exist in the native DLL (but in msvcrt).
559 * But since the maintenance of all these functions is better done
560 * in one place we implement it here.
562 LPWSTR __cdecl _ui64tow(
563 ULONGLONG value, /* [I] Value to be converted */
564 LPWSTR str, /* [O] Destination for the converted value */
565 INT radix) /* [I] Number base for conversion */
567 WCHAR buffer[65];
568 PWCHAR pos;
569 WCHAR digit;
571 pos = &buffer[64];
572 *pos = '\0';
574 do {
575 digit = value % radix;
576 value = value / radix;
577 if (digit < 10) {
578 *--pos = '0' + digit;
579 } else {
580 *--pos = 'a' + digit - 10;
581 } /* if */
582 } while (value != 0L);
584 if (str != NULL) {
585 memcpy(str, pos, (&buffer[64] - pos + 1) * sizeof(WCHAR));
586 } /* if */
587 return str;
591 /*********************************************************************
592 * _i64tow (NTDLL.@)
594 * Converts a large integer to an unicode string.
596 * RETURNS
597 * Always returns str.
599 * NOTES
600 * Converts value to a '\0' terminated wstring which is copied to str.
601 * The maximum length of the copied str is 33 bytes. If radix
602 * is 10 and value is negative, the value is converted with sign.
603 * Does not check if radix is in the range of 2 to 36.
604 * If str is NULL it just returns NULL.
606 * DIFFERENCES
607 * - The native DLL converts negative values (for base 10) wrong:
608 * -1 is converted to -18446744073709551615
609 * -2 is converted to -18446744073709551614
610 * -9223372036854775807 is converted to -9223372036854775809
611 * -9223372036854775808 is converted to -9223372036854775808
612 * The native msvcrt _i64tow function and our ntdll function do
613 * not have this bug.
615 LPWSTR __cdecl _i64tow(
616 LONGLONG value, /* [I] Value to be converted */
617 LPWSTR str, /* [O] Destination for the converted value */
618 INT radix) /* [I] Number base for conversion */
620 ULONGLONG val;
621 int negative;
622 WCHAR buffer[65];
623 PWCHAR pos;
624 WCHAR digit;
626 if (value < 0 && radix == 10) {
627 negative = 1;
628 val = -value;
629 } else {
630 negative = 0;
631 val = value;
632 } /* if */
634 pos = &buffer[64];
635 *pos = '\0';
637 do {
638 digit = val % radix;
639 val = val / radix;
640 if (digit < 10) {
641 *--pos = '0' + digit;
642 } else {
643 *--pos = 'a' + digit - 10;
644 } /* if */
645 } while (val != 0L);
647 if (negative) {
648 *--pos = '-';
649 } /* if */
651 if (str != NULL) {
652 memcpy(str, pos, (&buffer[64] - pos + 1) * sizeof(WCHAR));
653 } /* if */
654 return str;
658 /*********************************************************************
659 * _wtol (NTDLL.@)
661 * Converts an unicode string to a long integer.
663 * PARAMS
664 * str [I] Wstring to be converted
666 * RETURNS
667 * On success it returns the integer value otherwise it returns 0.
669 * NOTES
670 * Accepts: {whitespace} [+|-] {digits}
671 * No check is made for value overflow, only the lower 32 bits are assigned.
672 * If str is NULL it crashes, as the native function does.
674 LONG __cdecl _wtol( LPCWSTR str )
676 ULONG RunningTotal = 0;
677 char bMinus = 0;
679 while (isspaceW(*str)) {
680 str++;
681 } /* while */
683 if (*str == '+') {
684 str++;
685 } else if (*str == '-') {
686 bMinus = 1;
687 str++;
688 } /* if */
690 while (*str >= '0' && *str <= '9') {
691 RunningTotal = RunningTotal * 10 + *str - '0';
692 str++;
693 } /* while */
695 return bMinus ? -RunningTotal : RunningTotal;
699 /*********************************************************************
700 * _wtoi (NTDLL.@)
702 * Converts an unicode string to an integer.
704 * PARAMS
705 * str [I] Wstring to be converted
707 * RETURNS
708 * On success it returns the integer value otherwise it returns 0.
710 * NOTES
711 * Accepts: {whitespace} [+|-] {digits}
712 * No check is made for value overflow, only the lower 32 bits are assigned.
713 * If str is NULL it crashes, as the native function does.
715 int __cdecl _wtoi( LPCWSTR str )
717 return _wtol(str);
721 /*********************************************************************
722 * _wtoi64 (NTDLL.@)
724 * Converts an unicode string to a large integer.
726 * PARAMS
727 * str [I] Wstring to be converted
729 * RETURNS
730 * On success it returns the integer value otherwise it returns 0.
732 * NOTES
733 * Accepts: {whitespace} [+|-] {digits}
734 * No check is made for value overflow, only the lower 64 bits are assigned.
735 * If str is NULL it crashes, as the native function does.
737 LONGLONG __cdecl _wtoi64( LPCWSTR str )
739 ULONGLONG RunningTotal = 0;
740 char bMinus = 0;
742 while (isspaceW(*str)) {
743 str++;
744 } /* while */
746 if (*str == '+') {
747 str++;
748 } else if (*str == '-') {
749 bMinus = 1;
750 str++;
751 } /* if */
753 while (*str >= '0' && *str <= '9') {
754 RunningTotal = RunningTotal * 10 + *str - '0';
755 str++;
756 } /* while */
758 return bMinus ? -RunningTotal : RunningTotal;
762 /***********************************************************************
763 * _snwprintf (NTDLL.@)
765 int __cdecl _snwprintf(WCHAR *str, unsigned int len, const WCHAR *format, ...)
767 int retval;
768 va_list valist;
769 va_start(valist, format);
770 retval = vsnprintfW(str, len, format, valist);
771 va_end(valist);
772 return retval;
776 /***********************************************************************
777 * swprintf (NTDLL.@)
779 int __cdecl NTDLL_swprintf(WCHAR *str, const WCHAR *format, ...)
781 int retval;
782 va_list valist;
783 va_start(valist, format);
784 retval = vsnprintfW(str, INT_MAX, format, valist);
785 va_end(valist);
786 return retval;