d3d10/effect: Use case-insensitive comparison in GetMemberTypeBySemantic().
[wine.git] / dlls / msvcrt / wcs.c
blobaeab5527db44517a23e79bde164dbe8b7445afe5
1 /*
2 * msvcrt.dll wide-char functions
4 * Copyright 1999 Alexandre Julliard
5 * Copyright 2000 Jon Griffiths
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #define _NO_CRT_STDIO_INLINE
23 #include <limits.h>
24 #include <locale.h>
25 #include <math.h>
26 #include <assert.h>
27 #include <wchar.h>
28 #include <wctype.h>
29 #include "msvcrt.h"
30 #include "winnls.h"
31 #include "wtypes.h"
32 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
36 typedef struct
38 enum { LEN_DEFAULT, LEN_SHORT, LEN_LONG } IntegerLength;
39 BOOLEAN IntegerDouble, IntegerNative, LeftAlign, Alternate, PadZero;
40 BOOLEAN WideString, NaturalString;
41 int FieldLength, Precision;
42 char Sign, Format;
43 } pf_flags;
45 static BOOL n_format_enabled = TRUE;
47 #include "printf.h"
48 #define PRINTF_WIDE
49 #include "printf.h"
50 #undef PRINTF_WIDE
52 #if _MSVCR_VER>=80
54 /*********************************************************************
55 * _get_printf_count_output (MSVCR80.@)
57 int CDECL _get_printf_count_output( void )
59 return n_format_enabled ? 1 : 0;
62 /*********************************************************************
63 * _set_printf_count_output (MSVCR80.@)
65 int CDECL _set_printf_count_output( int enable )
67 BOOL old = n_format_enabled;
68 n_format_enabled = enable != 0;
69 return old ? 1 : 0;
72 #endif /* _MSVCR_VER>=80 */
74 /*********************************************************************
75 * _wcsdup (MSVCRT.@)
77 wchar_t* CDECL _wcsdup( const wchar_t* str )
79 wchar_t* ret = NULL;
80 if (str)
82 int size = (wcslen(str) + 1) * sizeof(wchar_t);
83 ret = malloc( size );
84 if (ret) memcpy( ret, str, size );
86 return ret;
89 /*********************************************************************
90 * _towlower_l (MSVCRT.@)
92 wint_t CDECL _towlower_l(wint_t c, _locale_t locale)
94 pthreadlocinfo locinfo;
95 wchar_t ret;
97 if(!locale)
98 locinfo = get_locinfo();
99 else
100 locinfo = locale->locinfo;
102 if(!locinfo->lc_handle[LC_CTYPE]) {
103 if(c >= 'A' && c <= 'Z')
104 return c + 'a' - 'A';
105 return c;
108 if(!LCMapStringW(locinfo->lc_handle[LC_CTYPE], LCMAP_LOWERCASE, &c, 1, &ret, 1))
109 return c;
110 return ret;
113 /*********************************************************************
114 * towlower (MSVCRT.@)
116 wint_t CDECL towlower(wint_t c)
118 return _towlower_l(c, NULL);
121 INT CDECL _wcsicmp_l(const wchar_t *str1, const wchar_t *str2, _locale_t locale)
123 _locale_tstruct tmp = {0};
124 wchar_t c1, c2;
126 if(!MSVCRT_CHECK_PMT(str1 != NULL) || !MSVCRT_CHECK_PMT(str2 != NULL))
127 return _NLSCMPERROR;
129 if(!locale)
130 locale = get_current_locale_noalloc(&tmp);
134 c1 = _towlower_l(*str1++, locale);
135 c2 = _towlower_l(*str2++, locale);
136 } while(c1 && (c1 == c2));
138 free_locale_noalloc(&tmp);
139 return c1 - c2;
142 /*********************************************************************
143 * towctrans (MSVCR120.@)
145 wint_t CDECL towctrans(wint_t c, wctrans_t category)
147 if(category == 1)
148 return _towupper_l(c, NULL);
149 return _towlower_l(c, NULL);
152 /*********************************************************************
153 * _wcsicmp (MSVCRT.@)
155 INT CDECL _wcsicmp( const wchar_t* str1, const wchar_t* str2 )
157 return _wcsicmp_l(str1, str2, NULL);
160 /*********************************************************************
161 * _wcsnicmp_l (MSVCRT.@)
163 INT CDECL _wcsnicmp_l(const wchar_t *str1, const wchar_t *str2,
164 size_t n, _locale_t locale)
166 _locale_tstruct tmp = {0};
167 wchar_t c1, c2;
169 if (!n)
170 return 0;
172 if(!MSVCRT_CHECK_PMT(str1 != NULL) || !MSVCRT_CHECK_PMT(str2 != NULL))
173 return _NLSCMPERROR;
175 if(!locale)
176 locale = get_current_locale_noalloc(&tmp);
180 c1 = _towlower_l(*str1++, locale);
181 c2 = _towlower_l(*str2++, locale);
182 } while(--n && c1 && (c1 == c2));
184 free_locale_noalloc(&tmp);
185 return c1 - c2;
188 /*********************************************************************
189 * _wcsnicmp (MSVCRT.@)
191 INT CDECL _wcsnicmp(const wchar_t *str1, const wchar_t *str2, size_t n)
193 return _wcsnicmp_l(str1, str2, n, NULL);
196 /*********************************************************************
197 * _wcsicoll_l (MSVCRT.@)
199 int CDECL _wcsicoll_l(const wchar_t* str1, const wchar_t* str2, _locale_t locale)
201 pthreadlocinfo locinfo;
203 if(!locale)
204 locinfo = get_locinfo();
205 else
206 locinfo = locale->locinfo;
208 if(!locinfo->lc_handle[LC_COLLATE])
210 wchar_t c1, c2;
214 c1 = *str1++;
215 if (c1 >= 'A' && c1 <= 'Z')
216 c1 += 'a' - 'A';
218 c2 = *str2++;
219 if (c2 >= 'A' && c2 <= 'Z')
220 c2 += 'a' - 'A';
221 } while(c1 && (c1 == c2));
222 return c1 - c2;
225 return CompareStringW(locinfo->lc_handle[LC_COLLATE], NORM_IGNORECASE,
226 str1, -1, str2, -1)-CSTR_EQUAL;
229 /*********************************************************************
230 * _wcsicoll (MSVCRT.@)
232 INT CDECL _wcsicoll( const wchar_t* str1, const wchar_t* str2 )
234 return _wcsicoll_l(str1, str2, NULL);
237 /*********************************************************************
238 * _wcsnicoll_l (MSVCRT.@)
240 int CDECL _wcsnicoll_l(const wchar_t* str1, const wchar_t* str2,
241 size_t count, _locale_t locale)
243 pthreadlocinfo locinfo;
245 if(!locale)
246 locinfo = get_locinfo();
247 else
248 locinfo = locale->locinfo;
250 if(!locinfo->lc_handle[LC_COLLATE])
252 wchar_t c1, c2;
254 if (!count)
255 return 0;
259 c1 = *str1++;
260 if (c1 >= 'A' && c1 <= 'Z')
261 c1 += 'a' - 'A';
263 c2 = *str2++;
264 if (c2 >= 'A' && c2 <= 'Z')
265 c2 += 'a' - 'A';
266 } while(--count && c1 && (c1 == c2));
267 return c1 - c2;
270 return CompareStringW(locinfo->lc_handle[LC_COLLATE], NORM_IGNORECASE,
271 str1, wcsnlen(str1, count),
272 str2, wcsnlen(str2, count))-CSTR_EQUAL;
275 /*********************************************************************
276 * _wcsnicoll (MSVCRT.@)
278 INT CDECL _wcsnicoll( const wchar_t* str1, const wchar_t* str2, size_t count )
280 return _wcsnicoll_l(str1, str2, count, NULL);
283 /*********************************************************************
284 * _wcsnset (MSVCRT.@)
286 wchar_t* CDECL _wcsnset( wchar_t* str, wchar_t c, size_t n )
288 wchar_t* ret = str;
289 while ((n-- > 0) && *str) *str++ = c;
290 return ret;
293 /*********************************************************************
294 * _wcsnset_s (MSVCRT.@)
296 int CDECL _wcsnset_s( wchar_t *str, size_t size, wchar_t c, size_t count )
298 size_t i;
300 if(!str && !size && !count) return 0;
301 if(!MSVCRT_CHECK_PMT(str != NULL)) return EINVAL;
302 if(!MSVCRT_CHECK_PMT(size > 0)) return EINVAL;
304 for(i=0; i<size-1 && i<count; i++) {
305 if(!str[i]) return 0;
306 str[i] = c;
308 for(; i<size; i++)
309 if(!str[i]) return 0;
311 str[0] = 0;
312 _invalid_parameter(NULL, NULL, NULL, 0, 0);
313 *_errno() = EINVAL;
314 return EINVAL;
317 /*********************************************************************
318 * _wcsrev (MSVCRT.@)
320 wchar_t* CDECL _wcsrev( wchar_t* str )
322 wchar_t* ret = str;
323 wchar_t* end = str + wcslen(str) - 1;
324 while (end > str)
326 wchar_t t = *end;
327 *end-- = *str;
328 *str++ = t;
330 return ret;
333 /*********************************************************************
334 * _wcsset_s (MSVCRT.@)
336 int CDECL _wcsset_s( wchar_t *str, size_t n, wchar_t c )
338 wchar_t *p = str;
340 if(!MSVCRT_CHECK_PMT(str != NULL)) return EINVAL;
341 if(!MSVCRT_CHECK_PMT(n)) return EINVAL;
343 while(*p && --n) *p++ = c;
344 if(!n) {
345 str[0] = 0;
346 _invalid_parameter(NULL, NULL, NULL, 0, 0);
347 *_errno() = EINVAL;
348 return EINVAL;
350 return 0;
353 /*********************************************************************
354 * _wcsset (MSVCRT.@)
356 wchar_t* CDECL _wcsset( wchar_t* str, wchar_t c )
358 wchar_t* ret = str;
359 while (*str) *str++ = c;
360 return ret;
363 /******************************************************************
364 * _wcsupr_s_l (MSVCRT.@)
366 int CDECL _wcsupr_s_l( wchar_t* str, size_t n, _locale_t locale )
368 _locale_tstruct tmp = {0};
369 wchar_t* ptr = str;
371 if (!str || !n)
373 if (str) *str = '\0';
374 *_errno() = EINVAL;
375 return EINVAL;
378 if(!locale)
379 locale = get_current_locale_noalloc(&tmp);
381 while (n--)
383 if (!*ptr)
385 free_locale_noalloc(&tmp);
386 return 0;
388 *ptr = _towupper_l(*ptr, locale);
389 ptr++;
392 free_locale_noalloc(&tmp);
394 /* MSDN claims that the function should return and set errno to
395 * ERANGE, which doesn't seem to be true based on the tests. */
396 *str = '\0';
397 *_errno() = EINVAL;
398 return EINVAL;
401 /******************************************************************
402 * _wcsupr_s (MSVCRT.@)
405 INT CDECL _wcsupr_s( wchar_t* str, size_t n )
407 return _wcsupr_s_l( str, n, NULL );
410 /******************************************************************
411 * _wcsupr_l (MSVCRT.@)
413 wchar_t* CDECL _wcsupr_l( wchar_t *str, _locale_t locale )
415 _wcsupr_s_l( str, -1, locale);
416 return str;
419 /******************************************************************
420 * _wcsupr (MSVCRT.@)
422 wchar_t* CDECL _wcsupr( wchar_t *str )
424 return _wcsupr_l(str, NULL);
427 /******************************************************************
428 * _wcslwr_s_l (MSVCRT.@)
430 int CDECL _wcslwr_s_l( wchar_t* str, size_t n, _locale_t locale )
432 _locale_tstruct tmp = {0};
433 wchar_t* ptr = str;
435 if (!str || !n)
437 if (str) *str = '\0';
438 *_errno() = EINVAL;
439 return EINVAL;
442 if(!locale)
443 locale = get_current_locale_noalloc(&tmp);
445 while (n--)
447 if (!*ptr)
449 free_locale_noalloc(&tmp);
450 return 0;
452 *ptr = _towlower_l(*ptr, locale);
453 ptr++;
456 free_locale_noalloc(&tmp);
458 /* MSDN claims that the function should return and set errno to
459 * ERANGE, which doesn't seem to be true based on the tests. */
460 *str = '\0';
461 *_errno() = EINVAL;
462 return EINVAL;
465 /******************************************************************
466 * _wcslwr_s (MSVCRT.@)
468 int CDECL _wcslwr_s( wchar_t* str, size_t n )
470 return _wcslwr_s_l(str, n, NULL);
473 /******************************************************************
474 * _wcslwr_l (MSVCRT.@)
476 wchar_t* CDECL _wcslwr_l( wchar_t* str, _locale_t locale )
478 _wcslwr_s_l(str, -1, locale);
479 return str;
482 /******************************************************************
483 * _wcslwr (MSVCRT.@)
485 wchar_t* CDECL _wcslwr( wchar_t* str )
487 _wcslwr_s_l(str, -1, NULL);
488 return str;
491 /*********************************************************************
492 * wcsncmp (MSVCRT.@)
494 int CDECL wcsncmp(const wchar_t *str1, const wchar_t *str2, size_t n)
496 if (!n)
497 return 0;
498 while(--n && *str1 && (*str1 == *str2))
500 str1++;
501 str2++;
503 return *str1 - *str2;
506 /*********************************************************************
507 * _wcsncoll_l (MSVCRT.@)
509 int CDECL _wcsncoll_l(const wchar_t* str1, const wchar_t* str2,
510 size_t count, _locale_t locale)
512 pthreadlocinfo locinfo;
514 if(!locale)
515 locinfo = get_locinfo();
516 else
517 locinfo = locale->locinfo;
519 if(!locinfo->lc_handle[LC_COLLATE])
520 return wcsncmp(str1, str2, count);
521 return CompareStringW(locinfo->lc_handle[LC_COLLATE], 0,
522 str1, wcsnlen(str1, count),
523 str2, wcsnlen(str2, count))-CSTR_EQUAL;
526 /*********************************************************************
527 * _wcsncoll (MSVCRT.@)
529 int CDECL _wcsncoll(const wchar_t* str1, const wchar_t* str2, size_t count)
531 return _wcsncoll_l(str1, str2, count, NULL);
534 static wchar_t strtod_wstr_get(void *ctx)
536 const wchar_t **p = ctx;
537 if (!**p) return WEOF;
538 return *(*p)++;
541 static void strtod_wstr_unget(void *ctx)
543 const wchar_t **p = ctx;
544 (*p)--;
547 /*********************************************************************
548 * _wcstod_l (MSVCRT.@)
550 double CDECL _wcstod_l(const wchar_t* str, wchar_t** end,
551 _locale_t locale)
553 pthreadlocinfo locinfo;
554 const wchar_t *beg, *p;
555 struct fpnum fp;
556 double ret;
557 int err;
559 if (!MSVCRT_CHECK_PMT(str != NULL)) {
560 if (end) *end = NULL;
561 return 0;
564 if (!locale)
565 locinfo = get_locinfo();
566 else
567 locinfo = locale->locinfo;
569 p = str;
570 while(_iswspace_l(*p, locale))
571 p++;
572 beg = p;
574 fp = fpnum_parse(strtod_wstr_get, strtod_wstr_unget, &p, locinfo, FALSE);
575 if (end) *end = (p == beg ? (wchar_t*)str : (wchar_t*)p);
577 err = fpnum_double(&fp, &ret);
578 if(err) *_errno() = err;
579 return ret;
582 /*********************************************************************
583 * wcsrtombs_l (INTERNAL)
585 static size_t wcsrtombs_l(char *mbstr, const wchar_t **wcstr,
586 size_t count, _locale_t locale)
588 pthreadlocinfo locinfo;
589 size_t tmp = 0;
590 BOOL used_default = FALSE;
591 BOOL *pused_default;
593 if(!locale)
594 locinfo = get_locinfo();
595 else
596 locinfo = locale->locinfo;
598 if(!locinfo->lc_codepage) {
599 size_t i;
601 if(!mbstr)
602 return wcslen(*wcstr);
604 for(i=0; i<count; i++) {
605 if((*wcstr)[i] > 255) {
606 *_errno() = EILSEQ;
607 return -1;
610 mbstr[i] = (*wcstr)[i];
611 if(!(*wcstr)[i]) break;
614 if(i < count) *wcstr = NULL;
615 else *wcstr += i;
616 return i;
619 pused_default = (locinfo->lc_codepage != CP_UTF8 ? &used_default : NULL);
621 if(!mbstr) {
622 tmp = WideCharToMultiByte(locinfo->lc_codepage, WC_NO_BEST_FIT_CHARS,
623 *wcstr, -1, NULL, 0, NULL, pused_default);
624 if(!tmp || used_default) {
625 *_errno() = EILSEQ;
626 return -1;
628 return tmp-1;
631 while(**wcstr) {
632 char buf[3];
633 size_t i, size;
635 size = WideCharToMultiByte(locinfo->lc_codepage, WC_NO_BEST_FIT_CHARS,
636 *wcstr, 1, buf, 3, NULL, pused_default);
637 if(!size || used_default) {
638 *_errno() = EILSEQ;
639 return -1;
641 if(tmp+size > count)
642 return tmp;
644 for(i=0; i<size; i++)
645 mbstr[tmp++] = buf[i];
646 (*wcstr)++;
649 if(tmp < count) {
650 mbstr[tmp] = '\0';
651 *wcstr = NULL;
653 return tmp;
656 /*********************************************************************
657 * _wcstombs_l (MSVCRT.@)
659 size_t CDECL _wcstombs_l(char *mbstr, const wchar_t *wcstr,
660 size_t count, _locale_t locale)
662 return wcsrtombs_l(mbstr, &wcstr, count, locale);
665 /*********************************************************************
666 * wcstombs (MSVCRT.@)
668 size_t CDECL wcstombs(char *mbstr, const wchar_t *wcstr,
669 size_t count)
671 return wcsrtombs_l(mbstr, &wcstr, count, NULL);
674 /*********************************************************************
675 * wcsrtombs (MSVCRT.@)
677 size_t CDECL wcsrtombs(char *mbstr, const wchar_t **wcstr,
678 size_t count, mbstate_t *mbstate)
680 if(mbstate)
681 *mbstate = 0;
683 return wcsrtombs_l(mbstr, wcstr, count, NULL);
686 /*********************************************************************
687 * wcsrtombs_s_l (INTERNAL)
689 static int wcsrtombs_s_l(size_t *ret, char *mbstr, size_t size,
690 const wchar_t **wcstr, size_t count, _locale_t locale)
692 size_t conv;
693 int err;
695 if(!mbstr && !size && wcstr) {
696 conv = wcsrtombs_l(NULL, wcstr, 0, locale);
697 if(ret)
698 *ret = conv+1;
699 if(conv == -1)
700 return *_errno();
701 return 0;
704 if (!MSVCRT_CHECK_PMT(mbstr != NULL)) return EINVAL;
705 if (size) mbstr[0] = '\0';
706 if (!MSVCRT_CHECK_PMT(wcstr != NULL)) return EINVAL;
707 if (!MSVCRT_CHECK_PMT(*wcstr != NULL)) return EINVAL;
709 if(count==_TRUNCATE || size<count)
710 conv = size;
711 else
712 conv = count;
714 err = 0;
715 conv = wcsrtombs_l(mbstr, wcstr, conv, locale);
716 if(conv == -1) {
717 conv = 0;
718 if(size)
719 mbstr[0] = '\0';
720 err = *_errno();
721 }else if(conv < size)
722 mbstr[conv++] = '\0';
723 else if(conv==size && (count==_TRUNCATE || mbstr[conv-1]=='\0')) {
724 mbstr[conv-1] = '\0';
725 if(count==_TRUNCATE)
726 err = STRUNCATE;
727 }else {
728 MSVCRT_INVALID_PMT("mbstr[size] is too small", ERANGE);
729 conv = 0;
730 if(size)
731 mbstr[0] = '\0';
732 err = ERANGE;
735 if(ret)
736 *ret = conv;
737 return err;
740 /*********************************************************************
741 * _wcstombs_s_l (MSVCRT.@)
743 int CDECL _wcstombs_s_l(size_t *ret, char *mbstr, size_t size,
744 const wchar_t *wcstr, size_t count, _locale_t locale)
746 return wcsrtombs_s_l(ret, mbstr, size, &wcstr,count, locale);
749 /*********************************************************************
750 * wcstombs_s (MSVCRT.@)
752 int CDECL wcstombs_s(size_t *ret, char *mbstr, size_t size,
753 const wchar_t *wcstr, size_t count)
755 return wcsrtombs_s_l(ret, mbstr, size, &wcstr, count, NULL);
758 /*********************************************************************
759 * wcsrtombs_s (MSVCRT.@)
761 int CDECL wcsrtombs_s(size_t *ret, char *mbstr, size_t size,
762 const wchar_t **wcstr, size_t count, mbstate_t *mbstate)
764 if(mbstate)
765 *mbstate = 0;
767 return wcsrtombs_s_l(ret, mbstr, size, wcstr, count, NULL);
770 /*********************************************************************
771 * wcstod (MSVCRT.@)
773 double CDECL wcstod(const wchar_t* lpszStr, wchar_t** end)
775 return _wcstod_l(lpszStr, end, NULL);
778 /*********************************************************************
779 * _wtof (MSVCRT.@)
781 double CDECL _wtof(const wchar_t *str)
783 return _wcstod_l(str, NULL, NULL);
786 /*********************************************************************
787 * _wtof_l (MSVCRT.@)
789 double CDECL _wtof_l(const wchar_t *str, _locale_t locale)
791 return _wcstod_l(str, NULL, locale);
794 #if _MSVCR_VER>=120
796 /*********************************************************************
797 * _wcstof_l (MSVCR120.@)
799 float CDECL _wcstof_l( const wchar_t *str, wchar_t **end, _locale_t locale )
801 double ret = _wcstod_l(str, end, locale);
802 if (ret && isfinite(ret)) {
803 float f = ret;
804 if (!f || !isfinite(f))
805 *_errno() = ERANGE;
807 return ret;
810 /*********************************************************************
811 * wcstof (MSVCR120.@)
813 float CDECL wcstof( const wchar_t *str, wchar_t **end )
815 return _wcstof_l(str, end, NULL);
818 #endif /* _MSVCR_VER>=120 */
820 /*********************************************************************
821 * arg_clbk_valist (INTERNAL)
823 printf_arg arg_clbk_valist(void *ctx, int arg_pos, int type, __ms_va_list *valist)
825 printf_arg ret;
827 if(type == VT_I8)
828 ret.get_longlong = va_arg(*valist, LONGLONG);
829 else if(type == VT_INT)
830 ret.get_int = va_arg(*valist, int);
831 else if(type == VT_R8)
832 ret.get_double = va_arg(*valist, double);
833 else if(type == VT_PTR)
834 ret.get_ptr = va_arg(*valist, void*);
835 else {
836 ERR("Incorrect type\n");
837 ret.get_int = 0;
840 return ret;
843 /*********************************************************************
844 * arg_clbk_positional (INTERNAL)
846 printf_arg arg_clbk_positional(void *ctx, int pos, int type, __ms_va_list *valist)
848 printf_arg *args = ctx;
849 return args[pos];
852 #if _MSVCR_VER < 140
854 /*********************************************************************
855 * _vsnprintf (MSVCRT.@)
857 int CDECL _vsnprintf( char *str, size_t len, const char *format, __ms_va_list valist )
859 static const char nullbyte = '\0';
860 struct _str_ctx_a ctx = {len, str};
861 int ret;
863 ret = pf_printf_a(puts_clbk_str_a, &ctx, format, NULL, 0,
864 arg_clbk_valist, NULL, &valist);
865 puts_clbk_str_a(&ctx, 1, &nullbyte);
866 return ret;
869 #else
871 static int puts_clbk_str_c99_a(void *ctx, int len, const char *str)
873 struct _str_ctx_a *out = ctx;
875 if(!out->buf)
876 return len;
878 if(out->len < len) {
879 memmove(out->buf, str, out->len);
880 out->buf += out->len;
881 out->len = 0;
882 return len;
885 memmove(out->buf, str, len);
886 out->buf += len;
887 out->len -= len;
888 return len;
891 /*********************************************************************
892 * __stdio_common_vsprintf (UCRTBASE.@)
894 int CDECL __stdio_common_vsprintf( unsigned __int64 options, char *str, size_t len, const char *format,
895 _locale_t locale, __ms_va_list valist )
897 static const char nullbyte = '\0';
898 struct _str_ctx_a ctx = {len, str};
899 int ret;
901 if (options & ~UCRTBASE_PRINTF_MASK)
902 FIXME("options %s not handled\n", wine_dbgstr_longlong(options));
903 ret = pf_printf_a(puts_clbk_str_c99_a,
904 &ctx, format, (_locale_t)locale, options & UCRTBASE_PRINTF_MASK, arg_clbk_valist, NULL, &valist);
905 puts_clbk_str_a(&ctx, 1, &nullbyte);
907 if(!str)
908 return ret;
909 if(options & _CRT_INTERNAL_PRINTF_LEGACY_VSPRINTF_NULL_TERMINATION)
910 return ret>len ? -1 : ret;
911 if(ret>=len) {
912 if(len) str[len-1] = 0;
913 if(options & _CRT_INTERNAL_PRINTF_STANDARD_SNPRINTF_BEHAVIOR)
914 return ret;
915 return len > 0 ? -2 : -1;
917 return ret;
920 #endif /* _MSVCR_VER>=140 */
922 /*********************************************************************
923 * _vsnprintf_l (MSVCRT.@)
925 int CDECL _vsnprintf_l( char *str, size_t len, const char *format,
926 _locale_t locale, __ms_va_list valist )
928 static const char nullbyte = '\0';
929 struct _str_ctx_a ctx = {len, str};
930 int ret;
932 ret = pf_printf_a(puts_clbk_str_a, &ctx, format, locale, 0,
933 arg_clbk_valist, NULL, &valist);
934 puts_clbk_str_a(&ctx, 1, &nullbyte);
935 return ret;
938 /*********************************************************************
939 * _vsprintf_l (MSVCRT.@)
941 int CDECL _vsprintf_l( char *str, const char *format,
942 _locale_t locale, __ms_va_list valist )
944 return _vsnprintf_l(str, INT_MAX, format, locale, valist);
947 /*********************************************************************
948 * _sprintf_l (MSVCRT.@)
950 int WINAPIV _sprintf_l(char *str, const char *format,
951 _locale_t locale, ...)
953 int retval;
954 __ms_va_list valist;
955 __ms_va_start(valist, locale);
956 retval = _vsnprintf_l(str, INT_MAX, format, locale, valist);
957 __ms_va_end(valist);
958 return retval;
961 static int CDECL vsnprintf_s_l_opt( char *str, size_t sizeOfBuffer,
962 size_t count, const char *format, DWORD options,
963 _locale_t locale, __ms_va_list valist )
965 static const char nullbyte = '\0';
966 struct _str_ctx_a ctx;
967 int len, ret;
969 if(sizeOfBuffer<count+1 || count==-1)
970 len = sizeOfBuffer;
971 else
972 len = count+1;
974 ctx.len = len;
975 ctx.buf = str;
976 ret = pf_printf_a(puts_clbk_str_a, &ctx, format, locale, MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER | options,
977 arg_clbk_valist, NULL, &valist);
978 puts_clbk_str_a(&ctx, 1, &nullbyte);
980 if(ret<0 || ret==len) {
981 if(count!=_TRUNCATE && count>sizeOfBuffer) {
982 MSVCRT_INVALID_PMT("str[sizeOfBuffer] is too small", ERANGE);
983 memset(str, 0, sizeOfBuffer);
984 } else
985 str[len-1] = '\0';
987 return -1;
990 return ret;
993 static int vsnwprintf_s_l_opt( wchar_t *str, size_t sizeOfBuffer,
994 size_t count, const wchar_t *format, DWORD options,
995 _locale_t locale, __ms_va_list valist)
997 struct _str_ctx_w ctx;
998 int len, ret;
1000 len = sizeOfBuffer;
1001 if(count!=-1 && len>count+1)
1002 len = count+1;
1004 ctx.len = len;
1005 ctx.buf = str;
1006 ret = pf_printf_w(puts_clbk_str_w, &ctx, format, locale, MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER | options,
1007 arg_clbk_valist, NULL, &valist);
1008 puts_clbk_str_w(&ctx, 1, L"");
1010 if(ret<0 || ret==len) {
1011 if(count!=_TRUNCATE && count>sizeOfBuffer) {
1012 MSVCRT_INVALID_PMT("str[sizeOfBuffer] is too small", ERANGE);
1013 memset(str, 0, sizeOfBuffer*sizeof(wchar_t));
1014 } else
1015 str[len-1] = '\0';
1017 return -1;
1020 return ret;
1023 /*********************************************************************
1024 * _vsnprintf_s_l (MSVCRT.@)
1026 int CDECL _vsnprintf_s_l( char *str, size_t sizeOfBuffer,
1027 size_t count, const char *format,
1028 _locale_t locale, __ms_va_list valist )
1030 return vsnprintf_s_l_opt(str, sizeOfBuffer, count, format, 0, locale, valist);
1033 /*********************************************************************
1034 * _vsprintf_s_l (MSVCRT.@)
1036 int CDECL _vsprintf_s_l( char *str, size_t count, const char *format,
1037 _locale_t locale, __ms_va_list valist )
1039 return _vsnprintf_s_l(str, INT_MAX, count, format, locale, valist);
1042 /*********************************************************************
1043 * _sprintf_s_l (MSVCRT.@)
1045 int WINAPIV _sprintf_s_l( char *str, size_t count, const char *format,
1046 _locale_t locale, ...)
1048 int retval;
1049 __ms_va_list valist;
1050 __ms_va_start(valist, locale);
1051 retval = _vsnprintf_s_l(str, INT_MAX, count, format, locale, valist);
1052 __ms_va_end(valist);
1053 return retval;
1056 /*********************************************************************
1057 * _vsnprintf_s (MSVCRT.@)
1059 int CDECL _vsnprintf_s( char *str, size_t sizeOfBuffer,
1060 size_t count, const char *format, __ms_va_list valist )
1062 return _vsnprintf_s_l(str,sizeOfBuffer, count, format, NULL, valist);
1065 /*********************************************************************
1066 * _vsnprintf_c_l (MSVCRT.@)
1068 int CDECL _vsnprintf_c_l(char *str, size_t len, const char *format,
1069 _locale_t locale, __ms_va_list valist)
1071 return vsnprintf_s_l_opt(str, len, len, format, 0, locale, valist);
1074 /*********************************************************************
1075 * _vsnprintf_c (MSVCRT.@)
1077 int CDECL _vsnprintf_c(char *str, size_t len,
1078 const char *format, __ms_va_list valist)
1080 return _vsnprintf_c_l(str, len, format, NULL, valist);
1083 #if _MSVCR_VER>=140
1085 /*********************************************************************
1086 * __stdio_common_vsnprintf_s (UCRTBASE.@)
1088 int CDECL __stdio_common_vsnprintf_s( unsigned __int64 options,
1089 char *str, size_t sizeOfBuffer, size_t count,
1090 const char *format, _locale_t locale, __ms_va_list valist )
1092 if (options & ~UCRTBASE_PRINTF_MASK)
1093 FIXME("options %s not handled\n", wine_dbgstr_longlong(options));
1094 return vsnprintf_s_l_opt(str, sizeOfBuffer, count, format, options & UCRTBASE_PRINTF_MASK, locale, valist);
1097 /*********************************************************************
1098 * __stdio_common_vsnwprintf_s (UCRTBASE.@)
1100 int CDECL __stdio_common_vsnwprintf_s( unsigned __int64 options,
1101 wchar_t *str, size_t sizeOfBuffer, size_t count,
1102 const wchar_t *format, _locale_t locale, __ms_va_list valist )
1104 if (options & ~UCRTBASE_PRINTF_MASK)
1105 FIXME("options %s not handled\n", wine_dbgstr_longlong(options));
1106 return vsnwprintf_s_l_opt(str, sizeOfBuffer, count, format, options & UCRTBASE_PRINTF_MASK, locale, valist);
1109 /*********************************************************************
1110 * __stdio_common_vswprintf_s (UCRTBASE.@)
1112 int CDECL __stdio_common_vswprintf_s( unsigned __int64 options,
1113 wchar_t *str, size_t count, const wchar_t *format,
1114 _locale_t locale, __ms_va_list valist )
1116 return __stdio_common_vsnwprintf_s(options, str, INT_MAX, count, format, locale, valist);
1119 /*********************************************************************
1120 * __stdio_common_vsprintf_s (UCRTBASE.@)
1122 int CDECL __stdio_common_vsprintf_s( unsigned __int64 options,
1123 char *str, size_t count, const char *format,
1124 _locale_t locale, __ms_va_list valist )
1126 if (options & ~UCRTBASE_PRINTF_MASK)
1127 FIXME("options %s not handled\n", wine_dbgstr_longlong(options));
1128 return vsnprintf_s_l_opt(str, INT_MAX, count, format, options & UCRTBASE_PRINTF_MASK, locale, valist);
1131 #endif /* _MSVCR_VER>=140 */
1133 /*********************************************************************
1134 * vsprintf (MSVCRT.@)
1136 int CDECL vsprintf( char *str, const char *format, __ms_va_list valist)
1138 return vsnprintf(str, INT_MAX, format, valist);
1141 /*********************************************************************
1142 * vsprintf_s (MSVCRT.@)
1144 int CDECL vsprintf_s( char *str, size_t num, const char *format, __ms_va_list valist)
1146 return vsnprintf(str, num, format, valist);
1149 /*********************************************************************
1150 * _vscprintf (MSVCRT.@)
1152 int CDECL _vscprintf( const char *format, __ms_va_list valist )
1154 return _vsnprintf_l( NULL, INT_MAX, format, NULL, valist );
1157 /*********************************************************************
1158 * _vscprintf_l (MSVCRT.@)
1160 int CDECL _vscprintf_l(const char *format,
1161 _locale_t locale, __ms_va_list valist)
1163 return _vsnprintf_l(NULL, INT_MAX, format, locale, valist);
1166 /*********************************************************************
1167 * _vscprintf_p_l (MSVCRT.@)
1169 int CDECL _vscprintf_p_l(const char *format,
1170 _locale_t locale, __ms_va_list args)
1172 printf_arg args_ctx[_ARGMAX+1];
1173 struct _str_ctx_a puts_ctx = {INT_MAX, NULL};
1174 int ret;
1176 memset(args_ctx, 0, sizeof(args_ctx));
1178 ret = create_positional_ctx_a(args_ctx, format, args);
1179 if(ret < 0) {
1180 _invalid_parameter(NULL, NULL, NULL, 0, 0);
1181 *_errno() = EINVAL;
1182 return ret;
1183 } else if(ret == 0) {
1184 ret = pf_printf_a(puts_clbk_str_a, &puts_ctx, format, locale,
1185 MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER,
1186 arg_clbk_valist, NULL, &args);
1187 } else {
1188 ret = pf_printf_a(puts_clbk_str_a, &puts_ctx, format, locale,
1189 MSVCRT_PRINTF_POSITIONAL_PARAMS | MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER,
1190 arg_clbk_positional, args_ctx, NULL);
1193 return ret;
1196 /*********************************************************************
1197 * _vscprintf_p (MSVCR80.@)
1199 int CDECL _vscprintf_p(const char *format, __ms_va_list argptr)
1201 return _vscprintf_p_l(format, NULL, argptr);
1204 /*********************************************************************
1205 * _snprintf (MSVCRT.@)
1207 int WINAPIV _snprintf(char *str, size_t len, const char *format, ...)
1209 int retval;
1210 __ms_va_list valist;
1211 __ms_va_start(valist, format);
1212 retval = vsnprintf(str, len, format, valist);
1213 __ms_va_end(valist);
1214 return retval;
1217 /*********************************************************************
1218 * _snprintf_l (MSVCRT.@)
1220 int WINAPIV _snprintf_l(char *str, size_t count, const char *format,
1221 _locale_t locale, ...)
1223 int retval;
1224 __ms_va_list valist;
1225 __ms_va_start(valist, locale);
1226 retval = _vsnprintf_l(str, count, format, locale, valist);
1227 __ms_va_end(valist);
1228 return retval;
1231 /*********************************************************************
1232 * _snprintf_c_l (MSVCRT.@)
1234 int WINAPIV _snprintf_c_l(char *str, size_t count, const char *format,
1235 _locale_t locale, ...)
1237 int retval;
1238 __ms_va_list valist;
1239 __ms_va_start(valist, locale);
1240 retval = _vsnprintf_c_l(str, count, format, locale, valist);
1241 __ms_va_end(valist);
1242 return retval;
1245 /*********************************************************************
1246 * _snprintf_c (MSVCRT.@)
1248 int WINAPIV _snprintf_c(char *str, size_t count, const char *format, ...)
1250 int retval;
1251 __ms_va_list valist;
1252 __ms_va_start(valist, format);
1253 retval = _vsnprintf_c(str, count, format, valist);
1254 __ms_va_end(valist);
1255 return retval;
1258 /*********************************************************************
1259 * _snprintf_s_l (MSVCRT.@)
1261 int WINAPIV _snprintf_s_l(char *str, size_t len, size_t count,
1262 const char *format, _locale_t locale, ...)
1264 int retval;
1265 __ms_va_list valist;
1266 __ms_va_start(valist, locale);
1267 retval = _vsnprintf_s_l(str, len, count, format, locale, valist);
1268 __ms_va_end(valist);
1269 return retval;
1272 /*********************************************************************
1273 * _snprintf_s (MSVCRT.@)
1275 int WINAPIV _snprintf_s(char *str, size_t len, size_t count,
1276 const char *format, ...)
1278 int retval;
1279 __ms_va_list valist;
1280 __ms_va_start(valist, format);
1281 retval = _vsnprintf_s_l(str, len, count, format, NULL, valist);
1282 __ms_va_end(valist);
1283 return retval;
1286 /*********************************************************************
1287 * _scprintf (MSVCRT.@)
1289 int WINAPIV _scprintf(const char *format, ...)
1291 int retval;
1292 __ms_va_list valist;
1293 __ms_va_start(valist, format);
1294 retval = _vscprintf(format, valist);
1295 __ms_va_end(valist);
1296 return retval;
1299 /*********************************************************************
1300 * _vsnwprintf (MSVCRT.@)
1302 int CDECL _vsnwprintf(wchar_t *str, size_t len,
1303 const wchar_t *format, __ms_va_list valist)
1305 struct _str_ctx_w ctx = {len, str};
1306 int ret;
1308 ret = pf_printf_w(puts_clbk_str_w, &ctx, format, NULL, 0,
1309 arg_clbk_valist, NULL, &valist);
1310 puts_clbk_str_w(&ctx, 1, L"");
1311 return ret;
1314 /*********************************************************************
1315 * _vsnwprintf_l (MSVCRT.@)
1317 int CDECL _vsnwprintf_l(wchar_t *str, size_t len, const wchar_t *format,
1318 _locale_t locale, __ms_va_list valist)
1320 struct _str_ctx_w ctx = {len, str};
1321 int ret;
1323 ret = pf_printf_w(puts_clbk_str_w, &ctx, format, locale, 0,
1324 arg_clbk_valist, NULL, &valist);
1325 puts_clbk_str_w(&ctx, 1, L"");
1326 return ret;
1329 /*********************************************************************
1330 * _vswprintf_c_l (MSVCRT.@)
1332 int CDECL _vswprintf_c_l(wchar_t *str, size_t len, const wchar_t *format,
1333 _locale_t locale, __ms_va_list valist)
1335 return vsnwprintf_s_l_opt(str, len, len, format, 0, locale, valist);
1338 /*********************************************************************
1339 * _vswprintf_c (MSVCRT.@)
1341 int CDECL _vswprintf_c(wchar_t *str, size_t len,
1342 const wchar_t *format, __ms_va_list valist)
1344 return _vswprintf_c_l(str, len, format, NULL, valist);
1347 static int vswprintf_p_l_opt(wchar_t *buffer, size_t length,
1348 const wchar_t *format, DWORD options, _locale_t locale, __ms_va_list args)
1350 printf_arg args_ctx[_ARGMAX+1];
1351 struct _str_ctx_w puts_ctx = {length, buffer};
1352 int ret;
1354 memset(args_ctx, 0, sizeof(args_ctx));
1356 ret = create_positional_ctx_w(args_ctx, format, args);
1357 if(ret < 0) {
1358 _invalid_parameter(NULL, NULL, NULL, 0, 0);
1359 *_errno() = EINVAL;
1360 return ret;
1361 } else if(ret == 0)
1362 ret = pf_printf_w(puts_clbk_str_w, &puts_ctx, format, locale, MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER | options,
1363 arg_clbk_valist, NULL, &args);
1364 else
1365 ret = pf_printf_w(puts_clbk_str_w, &puts_ctx, format, locale,
1366 MSVCRT_PRINTF_POSITIONAL_PARAMS | MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER | options,
1367 arg_clbk_positional, args_ctx, NULL);
1369 puts_clbk_str_w(&puts_ctx, 1, L"");
1370 return ret;
1373 /*********************************************************************
1374 * _vswprintf_p_l (MSVCRT.@)
1376 int CDECL _vswprintf_p_l(wchar_t *buffer, size_t length,
1377 const wchar_t *format, _locale_t locale, __ms_va_list args)
1379 return vswprintf_p_l_opt(buffer, length, format, 0, locale, args);
1382 #if _MSVCR_VER>=80
1383 /*********************************************************************
1384 * _vswprintf_p (MSVCR80.@)
1386 int CDECL _vswprintf_p(wchar_t *buffer, size_t length,
1387 const wchar_t *format, __ms_va_list args)
1389 return vswprintf_p_l_opt(buffer, length, format, 0, NULL, args);
1391 #endif
1393 #if _MSVCR_VER>=140
1394 /*********************************************************************
1395 * __stdio_common_vswprintf_p (UCRTBASE.@)
1397 int CDECL __stdio_common_vswprintf_p( unsigned __int64 options,
1398 wchar_t *str, size_t count, const wchar_t *format,
1399 _locale_t locale, __ms_va_list valist )
1401 if (options & ~UCRTBASE_PRINTF_MASK)
1402 FIXME("options %s not handled\n", wine_dbgstr_longlong(options));
1403 return vswprintf_p_l_opt(str, count, format, options & UCRTBASE_PRINTF_MASK, locale, valist);
1405 #endif
1407 /*********************************************************************
1408 * _vsnwprintf_s_l (MSVCRT.@)
1410 int CDECL _vsnwprintf_s_l( wchar_t *str, size_t sizeOfBuffer,
1411 size_t count, const wchar_t *format,
1412 _locale_t locale, __ms_va_list valist)
1414 return vsnwprintf_s_l_opt(str, sizeOfBuffer, count, format, 0, locale, valist);
1417 /*********************************************************************
1418 * _vsnwprintf_s (MSVCRT.@)
1420 int CDECL _vsnwprintf_s(wchar_t *str, size_t sizeOfBuffer,
1421 size_t count, const wchar_t *format, __ms_va_list valist)
1423 return _vsnwprintf_s_l(str, sizeOfBuffer, count,
1424 format, NULL, valist);
1427 /*********************************************************************
1428 * _snwprintf (MSVCRT.@)
1430 int WINAPIV _snwprintf( wchar_t *str, size_t len, const wchar_t *format, ...)
1432 int retval;
1433 __ms_va_list valist;
1434 __ms_va_start(valist, format);
1435 retval = _vsnwprintf(str, len, format, valist);
1436 __ms_va_end(valist);
1437 return retval;
1440 /*********************************************************************
1441 * _snwprintf_l (MSVCRT.@)
1443 int WINAPIV _snwprintf_l( wchar_t *str, size_t len, const wchar_t *format,
1444 _locale_t locale, ...)
1446 int retval;
1447 __ms_va_list valist;
1448 __ms_va_start(valist, locale);
1449 retval = _vsnwprintf_l(str, len, format, locale, valist);
1450 __ms_va_end(valist);
1451 return retval;
1454 /*********************************************************************
1455 * _snwprintf_s (MSVCRT.@)
1457 int WINAPIV _snwprintf_s( wchar_t *str, size_t len, size_t count,
1458 const wchar_t *format, ...)
1460 int retval;
1461 __ms_va_list valist;
1462 __ms_va_start(valist, format);
1463 retval = _vsnwprintf_s_l(str, len, count, format, NULL, valist);
1464 __ms_va_end(valist);
1465 return retval;
1468 /*********************************************************************
1469 * _snwprintf_s_l (MSVCRT.@)
1471 int WINAPIV _snwprintf_s_l( wchar_t *str, size_t len, size_t count,
1472 const wchar_t *format, _locale_t locale, ... )
1474 int retval;
1475 __ms_va_list valist;
1476 __ms_va_start(valist, locale);
1477 retval = _vsnwprintf_s_l(str, len, count, format, locale, valist);
1478 __ms_va_end(valist);
1479 return retval;
1482 #if _MSVCR_VER>=140
1484 static int puts_clbk_str_c99_w(void *ctx, int len, const wchar_t *str)
1486 struct _str_ctx_w *out = ctx;
1488 if(!out->buf)
1489 return len;
1491 if(out->len < len) {
1492 memcpy(out->buf, str, out->len*sizeof(wchar_t));
1493 out->buf += out->len;
1494 out->len = 0;
1495 return len;
1498 memcpy(out->buf, str, len*sizeof(wchar_t));
1499 out->buf += len;
1500 out->len -= len;
1501 return len;
1504 /*********************************************************************
1505 * __stdio_common_vswprintf (UCRTBASE.@)
1507 int CDECL __stdio_common_vswprintf( unsigned __int64 options,
1508 wchar_t *str, size_t len, const wchar_t *format,
1509 _locale_t locale, __ms_va_list valist )
1511 struct _str_ctx_w ctx = {len, str};
1512 int ret;
1514 if (options & ~UCRTBASE_PRINTF_MASK)
1515 FIXME("options %s not handled\n", wine_dbgstr_longlong(options));
1516 ret = pf_printf_w(puts_clbk_str_c99_w,
1517 &ctx, format, locale, options & UCRTBASE_PRINTF_MASK, arg_clbk_valist, NULL, &valist);
1518 puts_clbk_str_w(&ctx, 1, L"");
1520 if(!str)
1521 return ret;
1522 if(options & _CRT_INTERNAL_PRINTF_LEGACY_VSPRINTF_NULL_TERMINATION)
1523 return ret>len ? -1 : ret;
1524 if(ret>=len) {
1525 if(len) str[len-1] = 0;
1526 if(options & _CRT_INTERNAL_PRINTF_STANDARD_SNPRINTF_BEHAVIOR)
1527 return ret;
1528 return len > 0 ? -2 : -1;
1530 return ret;
1533 #endif /* _MSVCR_VER>=140 */
1535 /*********************************************************************
1536 * sprintf (MSVCRT.@)
1538 int WINAPIV sprintf( char *str, const char *format, ... )
1540 __ms_va_list ap;
1541 int r;
1543 __ms_va_start( ap, format );
1544 r = vsnprintf( str, INT_MAX, format, ap );
1545 __ms_va_end( ap );
1546 return r;
1549 /*********************************************************************
1550 * sprintf_s (MSVCRT.@)
1552 int WINAPIV sprintf_s( char *str, size_t num, const char *format, ... )
1554 __ms_va_list ap;
1555 int r;
1557 __ms_va_start( ap, format );
1558 r = vsnprintf( str, num, format, ap );
1559 __ms_va_end( ap );
1560 return r;
1563 /*********************************************************************
1564 * _scwprintf (MSVCRT.@)
1566 int WINAPIV _scwprintf( const wchar_t *format, ... )
1568 __ms_va_list ap;
1569 int r;
1571 __ms_va_start( ap, format );
1572 r = _vsnwprintf( NULL, INT_MAX, format, ap );
1573 __ms_va_end( ap );
1574 return r;
1577 /*********************************************************************
1578 * swprintf (MSVCRT.@)
1580 int WINAPIV _swprintf( wchar_t *str, const wchar_t *format, ... )
1582 __ms_va_list ap;
1583 int r;
1585 __ms_va_start( ap, format );
1586 r = _vsnwprintf( str, INT_MAX, format, ap );
1587 __ms_va_end( ap );
1588 return r;
1591 /*********************************************************************
1592 * swprintf_s (MSVCRT.@)
1594 int WINAPIV swprintf_s(wchar_t *str, size_t numberOfElements,
1595 const wchar_t *format, ... )
1597 __ms_va_list ap;
1598 int r;
1600 __ms_va_start(ap, format);
1601 r = _vsnwprintf_s(str, numberOfElements, INT_MAX, format, ap);
1602 __ms_va_end(ap);
1604 return r;
1607 /*********************************************************************
1608 * _swprintf_s_l (MSVCRT.@)
1610 int WINAPIV _swprintf_s_l(wchar_t *str, size_t numberOfElements,
1611 const wchar_t *format, _locale_t locale, ... )
1613 __ms_va_list ap;
1614 int r;
1616 __ms_va_start(ap, locale);
1617 r = _vsnwprintf_s_l(str, numberOfElements, INT_MAX, format, locale, ap);
1618 __ms_va_end(ap);
1620 return r;
1623 /*********************************************************************
1624 * _swprintf_c_l (MSVCRT.@)
1626 int WINAPIV _swprintf_c_l(wchar_t *str, size_t len,
1627 const wchar_t *format, _locale_t locale, ... )
1629 __ms_va_list ap;
1630 int r;
1632 __ms_va_start(ap, locale);
1633 r = _vswprintf_c_l(str, len, format, locale, ap);
1634 __ms_va_end(ap);
1636 return r;
1639 /*********************************************************************
1640 * _swprintf_c (MSVCRT.@)
1642 int WINAPIV _swprintf_c(wchar_t *str, size_t len,
1643 const wchar_t *format, ... )
1645 __ms_va_list ap;
1646 int r;
1648 __ms_va_start(ap, format);
1649 r = _vswprintf_c(str, len, format, ap);
1650 __ms_va_end(ap);
1652 return r;
1655 /*********************************************************************
1656 * _vswprintf (MSVCRT.@)
1658 int CDECL _vswprintf( wchar_t* str, const wchar_t* format, __ms_va_list args )
1660 return _vsnwprintf( str, INT_MAX, format, args );
1663 /*********************************************************************
1664 * _vswprintf (MSVCRT.@)
1666 int CDECL _vswprintf_l( wchar_t* str, const wchar_t* format,
1667 _locale_t locale, __ms_va_list args )
1669 return _vsnwprintf_l( str, INT_MAX, format, locale, args );
1672 /*********************************************************************
1673 * _vscwprintf (MSVCRT.@)
1675 int CDECL _vscwprintf( const wchar_t *format, __ms_va_list args )
1677 return _vsnwprintf( NULL, INT_MAX, format, args );
1680 /*********************************************************************
1681 * _vscwprintf_l (MSVCRT.@)
1683 int CDECL _vscwprintf_l( const wchar_t *format, _locale_t locale, __ms_va_list args )
1685 return _vsnwprintf_l( NULL, INT_MAX, format, locale, args );
1688 /*********************************************************************
1689 * _vscwprintf_p_l (MSVCRT.@)
1691 int CDECL _vscwprintf_p_l( const wchar_t *format, _locale_t locale, __ms_va_list args )
1693 return vswprintf_p_l_opt( NULL, INT_MAX, format, 0, locale, args );
1696 #if _MSVCR_VER>=80
1697 /*********************************************************************
1698 * _vscwprintf_p (MSVCR80.@)
1700 int CDECL _vscwprintf_p(const wchar_t *format, __ms_va_list args)
1702 return vswprintf_p_l_opt(NULL, INT_MAX, format, 0, NULL, args);
1704 #endif
1706 /*********************************************************************
1707 * vswprintf_s (MSVCRT.@)
1709 int CDECL vswprintf_s(wchar_t* str, size_t numberOfElements,
1710 const wchar_t* format, __ms_va_list args)
1712 return _vsnwprintf_s(str, numberOfElements, INT_MAX, format, args );
1715 /*********************************************************************
1716 * _vswprintf_s_l (MSVCRT.@)
1718 int CDECL _vswprintf_s_l(wchar_t* str, size_t numberOfElements,
1719 const wchar_t* format, _locale_t locale, __ms_va_list args)
1721 return _vsnwprintf_s_l(str, numberOfElements, INT_MAX,
1722 format, locale, args );
1725 static int vsprintf_p_l_opt(char *buffer, size_t length, const char *format,
1726 DWORD options, _locale_t locale, __ms_va_list args)
1728 static const char nullbyte = '\0';
1729 printf_arg args_ctx[_ARGMAX+1];
1730 struct _str_ctx_a puts_ctx = {length, buffer};
1731 int ret;
1733 memset(args_ctx, 0, sizeof(args_ctx));
1735 ret = create_positional_ctx_a(args_ctx, format, args);
1736 if(ret < 0) {
1737 _invalid_parameter(NULL, NULL, NULL, 0, 0);
1738 *_errno() = EINVAL;
1739 return ret;
1740 } else if(ret == 0)
1741 ret = pf_printf_a(puts_clbk_str_a, &puts_ctx, format, locale,
1742 MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER | options, arg_clbk_valist, NULL, &args);
1743 else
1744 ret = pf_printf_a(puts_clbk_str_a, &puts_ctx, format, locale,
1745 MSVCRT_PRINTF_POSITIONAL_PARAMS | MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER | options,
1746 arg_clbk_positional, args_ctx, NULL);
1748 puts_clbk_str_a(&puts_ctx, 1, &nullbyte);
1749 return ret;
1752 /*********************************************************************
1753 * _vsprintf_p_l (MSVCRT.@)
1755 int CDECL _vsprintf_p_l(char *buffer, size_t length, const char *format,
1756 _locale_t locale, __ms_va_list args)
1758 return vsprintf_p_l_opt(buffer, length, format, 0, locale, args);
1761 /*********************************************************************
1762 * _vsprintf_p (MSVCRT.@)
1764 int CDECL _vsprintf_p(char *buffer, size_t length,
1765 const char *format, __ms_va_list args)
1767 return _vsprintf_p_l(buffer, length, format, NULL, args);
1770 #if _MSVCR_VER>=140
1771 /*********************************************************************
1772 * __stdio_common_vsprintf_p (UCRTBASE.@)
1774 int CDECL __stdio_common_vsprintf_p(unsigned __int64 options, char *buffer, size_t length,
1775 const char *format, _locale_t locale, __ms_va_list args)
1777 if (options & ~UCRTBASE_PRINTF_MASK)
1778 FIXME("options %s not handled\n", wine_dbgstr_longlong(options));
1779 return vsprintf_p_l_opt(buffer, length, format, options & UCRTBASE_PRINTF_MASK, locale, args);
1781 #endif
1783 /*********************************************************************
1784 * _sprintf_p_l (MSVCRT.@)
1786 int WINAPIV _sprintf_p_l(char *buffer, size_t length,
1787 const char *format, _locale_t locale, ...)
1789 __ms_va_list valist;
1790 int r;
1792 __ms_va_start(valist, locale);
1793 r = _vsprintf_p_l(buffer, length, format, locale, valist);
1794 __ms_va_end(valist);
1796 return r;
1799 /*********************************************************************
1800 * __swprintf_l (MSVCRT.@)
1802 int WINAPIV __swprintf_l( wchar_t *str, const wchar_t *format,
1803 _locale_t locale, ...)
1805 int retval;
1806 __ms_va_list valist;
1807 __ms_va_start(valist, locale);
1808 retval = _vswprintf_l(str, format, locale, valist);
1809 __ms_va_end(valist);
1810 return retval;
1813 #if _MSVCR_VER>=80
1814 /*********************************************************************
1815 * _sprintf_p (MSVCR80.@)
1817 int WINAPIV _sprintf_p(char *buffer, size_t length, const char *format, ...)
1819 __ms_va_list valist;
1820 int r;
1822 __ms_va_start(valist, format);
1823 r = _vsprintf_p_l(buffer, length, format, NULL, valist);
1824 __ms_va_end(valist);
1826 return r;
1828 #endif
1830 /*********************************************************************
1831 * _swprintf_p_l (MSVCRT.@)
1833 int WINAPIV _swprintf_p_l(wchar_t *buffer, size_t length,
1834 const wchar_t *format, _locale_t locale, ...)
1836 __ms_va_list valist;
1837 int r;
1839 __ms_va_start(valist, locale);
1840 r = vswprintf_p_l_opt(buffer, length, format, 0, locale, valist);
1841 __ms_va_end(valist);
1843 return r;
1846 /*********************************************************************
1847 * wcscmp (MSVCRT.@)
1849 int CDECL wcscmp(const wchar_t *str1, const wchar_t *str2)
1851 while (*str1 && (*str1 == *str2))
1853 str1++;
1854 str2++;
1857 if (*str1 < *str2)
1858 return -1;
1859 if (*str1 > *str2)
1860 return 1;
1861 return 0;
1864 /*********************************************************************
1865 * _wcscoll_l (MSVCRT.@)
1867 int CDECL _wcscoll_l(const wchar_t* str1, const wchar_t* str2, _locale_t locale)
1869 pthreadlocinfo locinfo;
1871 if(!locale)
1872 locinfo = get_locinfo();
1873 else
1874 locinfo = locale->locinfo;
1876 if(!locinfo->lc_handle[LC_COLLATE])
1877 return wcscmp(str1, str2);
1878 return CompareStringW(locinfo->lc_handle[LC_COLLATE], 0, str1, -1, str2, -1)-CSTR_EQUAL;
1881 /*********************************************************************
1882 * wcscoll (MSVCRT.@)
1884 int CDECL wcscoll( const wchar_t* str1, const wchar_t* str2 )
1886 return _wcscoll_l(str1, str2, NULL);
1889 /*********************************************************************
1890 * wcspbrk (MSVCRT.@)
1892 wchar_t* CDECL wcspbrk( const wchar_t* str, const wchar_t* accept )
1894 const wchar_t* p;
1896 while (*str)
1898 for (p = accept; *p; p++) if (*p == *str) return (wchar_t*)str;
1899 str++;
1901 return NULL;
1904 /*********************************************************************
1905 * wcstok_s (MSVCRT.@)
1907 wchar_t * CDECL wcstok_s( wchar_t *str, const wchar_t *delim,
1908 wchar_t **next_token )
1910 wchar_t *ret;
1912 if (!MSVCRT_CHECK_PMT(delim != NULL)) return NULL;
1913 if (!MSVCRT_CHECK_PMT(next_token != NULL)) return NULL;
1914 if (!MSVCRT_CHECK_PMT(str != NULL || *next_token != NULL)) return NULL;
1916 if (!str) str = *next_token;
1918 while (*str && wcschr( delim, *str )) str++;
1919 if (!*str) ret = NULL;
1920 else
1922 ret = str++;
1923 while (*str && !wcschr( delim, *str )) str++;
1924 if (*str) *str++ = 0;
1926 *next_token = str;
1927 return ret;
1930 /*********************************************************************
1931 * wcstok (MSVCRT.@)
1933 #if _MSVCR_VER>=140
1934 wchar_t * CDECL wcstok( wchar_t *str, const wchar_t *delim, wchar_t **ctx )
1936 if (!ctx)
1937 ctx = &msvcrt_get_thread_data()->wcstok_next;
1938 return wcstok_s(str, delim, ctx);
1940 #else
1941 wchar_t * CDECL wcstok( wchar_t *str, const wchar_t *delim )
1943 return wcstok_s(str, delim, &msvcrt_get_thread_data()->wcstok_next);
1945 #endif
1947 /*********************************************************************
1948 * _wctomb_s_l (MSVCRT.@)
1950 int CDECL _wctomb_s_l(int *len, char *mbchar, size_t size,
1951 wchar_t wch, _locale_t locale)
1953 pthreadlocinfo locinfo;
1954 BOOL error = FALSE;
1955 BOOL *perror;
1956 int mblen;
1958 if(!mbchar && size>0) {
1959 if(len)
1960 *len = 0;
1961 return 0;
1964 if(len)
1965 *len = -1;
1967 if(!MSVCRT_CHECK_PMT(size <= INT_MAX))
1968 return EINVAL;
1970 if(!locale)
1971 locinfo = get_locinfo();
1972 else
1973 locinfo = locale->locinfo;
1975 if(!locinfo->lc_codepage) {
1976 if(wch > 0xff) {
1977 if(mbchar && size>0)
1978 memset(mbchar, 0, size);
1979 *_errno() = EILSEQ;
1980 return EILSEQ;
1983 if(!MSVCRT_CHECK_PMT_ERR(size >= 1, ERANGE))
1984 return ERANGE;
1986 *mbchar = wch;
1987 if(len)
1988 *len = 1;
1989 return 0;
1992 perror = (locinfo->lc_codepage != CP_UTF8 ? &error : NULL);
1993 mblen = WideCharToMultiByte(locinfo->lc_codepage, 0, &wch, 1, mbchar, size, NULL, perror);
1994 if(!mblen || error) {
1995 if(!mblen && GetLastError()==ERROR_INSUFFICIENT_BUFFER) {
1996 if(mbchar && size>0)
1997 memset(mbchar, 0, size);
1999 MSVCRT_INVALID_PMT("insufficient buffer size", ERANGE);
2000 return ERANGE;
2003 *_errno() = EILSEQ;
2004 return EILSEQ;
2007 if(len)
2008 *len = mblen;
2009 return 0;
2012 /*********************************************************************
2013 * wctomb_s (MSVCRT.@)
2015 int CDECL wctomb_s(int *len, char *mbchar, size_t size, wchar_t wch)
2017 return _wctomb_s_l(len, mbchar, size, wch, NULL);
2020 /*********************************************************************
2021 * _wctomb_l (MSVCRT.@)
2023 int CDECL _wctomb_l(char *dst, wchar_t ch, _locale_t locale)
2025 int len;
2027 _wctomb_s_l(&len, dst, dst ? MB_LEN_MAX : 0, ch, locale);
2028 return len;
2031 /*********************************************************************
2032 * wctomb (MSVCRT.@)
2034 INT CDECL wctomb( char *dst, wchar_t ch )
2036 return _wctomb_l(dst, ch, NULL);
2039 /*********************************************************************
2040 * wctob (MSVCRT.@)
2042 INT CDECL wctob( wint_t wchar )
2044 char out;
2045 BOOL error = FALSE;
2046 BOOL *perror;
2047 UINT codepage = get_locinfo()->lc_codepage;
2049 perror = (codepage != CP_UTF8 ? &error : NULL);
2051 if(!codepage) {
2052 if (wchar < 0xff)
2053 return (signed char)wchar;
2054 else
2055 return EOF;
2056 } else if(WideCharToMultiByte( codepage, 0, &wchar, 1, &out, 1, NULL, perror ) && !error)
2057 return (INT)out;
2058 return EOF;
2061 /*********************************************************************
2062 * wcrtomb_s (MSVCRT.@)
2064 INT CDECL wcrtomb_s(size_t *len, char *mbchar,
2065 size_t size, wchar_t wch, mbstate_t *s)
2067 int ilen, ret;
2069 if (s) *s = 0;
2070 ret = wctomb_s(&ilen, mbchar, size, wch);
2071 if (len) *len = ilen;
2072 return ret;
2075 /*********************************************************************
2076 * wcrtomb (MSVCRT.@)
2078 size_t CDECL wcrtomb( char *dst, wchar_t ch, mbstate_t *s)
2080 if(s)
2081 *s = 0;
2082 return wctomb(dst, ch);
2085 /*********************************************************************
2086 * _iswctype_l (MSVCRT.@)
2088 INT CDECL _iswctype_l( wchar_t wc, wctype_t type, _locale_t locale )
2090 WORD ct;
2092 if (wc == WEOF) return 0;
2093 if (wc < 256) return MSVCRT__pwctype[wc] & type;
2095 if (!GetStringTypeW(CT_CTYPE1, &wc, 1, &ct))
2097 ERR("GetStringTypeW failed for %x\n", wc);
2098 return 0;
2100 return ct & type;
2103 /*********************************************************************
2104 * iswctype (MSVCRT.@)
2106 INT CDECL iswctype( wchar_t wc, wctype_t type )
2108 return _iswctype_l( wc, type, NULL );
2111 /*********************************************************************
2112 * _iswalnum_l (MSVCRT.@)
2114 int CDECL _iswalnum_l( wchar_t wc, _locale_t locale )
2116 return _iswctype_l( wc, _ALPHA | _DIGIT, locale );
2119 /*********************************************************************
2120 * iswalnum (MSVCRT.@)
2122 INT CDECL iswalnum( wchar_t wc )
2124 return _iswalnum_l( wc, NULL );
2127 /*********************************************************************
2128 * iswalpha_l (MSVCRT.@)
2130 INT CDECL _iswalpha_l( wchar_t wc, _locale_t locale )
2132 return _iswctype_l( wc, _ALPHA, locale );
2135 /*********************************************************************
2136 * iswalpha (MSVCRT.@)
2138 INT CDECL iswalpha( wchar_t wc )
2140 return _iswalpha_l( wc, NULL );
2143 /*********************************************************************
2144 * _iswcntrl_l (MSVCRT.@)
2146 int CDECL _iswcntrl_l( wchar_t wc, _locale_t locale )
2148 return _iswctype_l( wc, _CONTROL, locale );
2151 /*********************************************************************
2152 * iswcntrl (MSVCRT.@)
2154 INT CDECL iswcntrl( wchar_t wc )
2156 return _iswcntrl_l( wc, NULL );
2159 /*********************************************************************
2160 * _iswdigit_l (MSVCRT.@)
2162 INT CDECL _iswdigit_l( wchar_t wc, _locale_t locale )
2164 return _iswctype_l( wc, _DIGIT, locale );
2167 /*********************************************************************
2168 * iswdigit (MSVCRT.@)
2170 INT CDECL iswdigit( wchar_t wc )
2172 return _iswdigit_l( wc, NULL );
2175 /*********************************************************************
2176 * _iswgraph_l (MSVCRT.@)
2178 int CDECL _iswgraph_l( wchar_t wc, _locale_t locale )
2180 return _iswctype_l( wc, _ALPHA | _DIGIT | _PUNCT, locale );
2183 /*********************************************************************
2184 * iswgraph (MSVCRT.@)
2186 INT CDECL iswgraph( wchar_t wc )
2188 return _iswgraph_l( wc, NULL );
2191 /*********************************************************************
2192 * _iswlower_l (MSVCRT.@)
2194 int CDECL _iswlower_l( wchar_t wc, _locale_t locale )
2196 return _iswctype_l( wc, _LOWER, locale );
2199 /*********************************************************************
2200 * iswlower (MSVCRT.@)
2202 INT CDECL iswlower( wchar_t wc )
2204 return _iswlower_l( wc, NULL );
2207 /*********************************************************************
2208 * _iswprint_l (MSVCRT.@)
2210 int CDECL _iswprint_l( wchar_t wc, _locale_t locale )
2212 return _iswctype_l( wc, _ALPHA | _BLANK | _DIGIT | _PUNCT, locale );
2215 /*********************************************************************
2216 * iswprint (MSVCRT.@)
2218 INT CDECL iswprint( wchar_t wc )
2220 return _iswprint_l( wc, NULL );
2223 /*********************************************************************
2224 * _iswpunct_l (MSVCRT.@)
2226 INT CDECL _iswpunct_l( wchar_t wc, _locale_t locale )
2228 return _iswctype_l( wc, _PUNCT, locale );
2231 /*********************************************************************
2232 * iswpunct (MSVCRT.@)
2234 INT CDECL iswpunct( wchar_t wc )
2236 return _iswpunct_l( wc, NULL );
2239 /*********************************************************************
2240 * _iswspace_l (MSVCRT.@)
2242 INT CDECL _iswspace_l( wchar_t wc, _locale_t locale )
2244 return _iswctype_l( wc, _SPACE, locale );
2247 /*********************************************************************
2248 * iswspace (MSVCRT.@)
2250 INT CDECL iswspace( wchar_t wc )
2252 return _iswspace_l( wc, NULL );
2255 /*********************************************************************
2256 * _iswupper_l (MSVCRT.@)
2258 int CDECL _iswupper_l( wchar_t wc, _locale_t locale )
2260 return _iswctype_l( wc, _UPPER, locale );
2263 /*********************************************************************
2264 * iswupper (MSVCRT.@)
2266 INT CDECL iswupper( wchar_t wc )
2268 return _iswupper_l( wc, NULL );
2271 /*********************************************************************
2272 * _iswxdigit_l (MSVCRT.@)
2274 int CDECL _iswxdigit_l( wchar_t wc, _locale_t locale )
2276 return _iswctype_l( wc, _HEX, locale );
2279 /*********************************************************************
2280 * iswxdigit (MSVCRT.@)
2282 INT CDECL iswxdigit( wchar_t wc )
2284 return _iswxdigit_l( wc, NULL );
2287 /*********************************************************************
2288 * _iswblank_l (MSVCRT.@)
2290 INT CDECL _iswblank_l( wchar_t wc, _locale_t locale )
2292 return wc == '\t' || _iswctype_l( wc, _BLANK, locale );
2295 /*********************************************************************
2296 * iswblank (MSVCRT.@)
2298 INT CDECL iswblank( wchar_t wc )
2300 return wc == '\t' || _iswctype_l( wc, _BLANK, NULL );
2303 /*********************************************************************
2304 * wcscpy_s (MSVCRT.@)
2306 INT CDECL wcscpy_s( wchar_t* wcDest, size_t numElement, const wchar_t *wcSrc)
2308 size_t size = 0;
2310 if(!MSVCRT_CHECK_PMT(wcDest)) return EINVAL;
2311 if(!MSVCRT_CHECK_PMT(numElement)) return EINVAL;
2313 if(!MSVCRT_CHECK_PMT(wcSrc))
2315 wcDest[0] = 0;
2316 return EINVAL;
2319 size = wcslen(wcSrc) + 1;
2321 if(!MSVCRT_CHECK_PMT_ERR(size <= numElement, ERANGE))
2323 wcDest[0] = 0;
2324 return ERANGE;
2327 memmove( wcDest, wcSrc, size*sizeof(WCHAR) );
2329 return 0;
2332 /***********************************************************************
2333 * wcscpy (MSVCRT.@)
2335 wchar_t* __cdecl wcscpy( wchar_t *dst, const wchar_t *src )
2337 WCHAR *p = dst;
2338 while ((*p++ = *src++));
2339 return dst;
2342 /******************************************************************
2343 * wcsncpy (MSVCRT.@)
2345 wchar_t* __cdecl wcsncpy( wchar_t* s1, const wchar_t *s2, size_t n )
2347 size_t i;
2349 for(i=0; i<n; i++)
2350 if(!(s1[i] = s2[i])) break;
2351 for(; i<n; i++)
2352 s1[i] = 0;
2353 return s1;
2356 /******************************************************************
2357 * wcsncpy_s (MSVCRT.@)
2359 INT CDECL wcsncpy_s( wchar_t* wcDest, size_t numElement, const wchar_t *wcSrc,
2360 size_t count )
2362 WCHAR *p = wcDest;
2363 BOOL truncate = (count == _TRUNCATE);
2365 if(!wcDest && !numElement && !count)
2366 return 0;
2368 if (!wcDest || !numElement)
2369 return EINVAL;
2371 if (!wcSrc)
2373 *wcDest = 0;
2374 return count ? EINVAL : 0;
2377 while (numElement && count && *wcSrc)
2379 *p++ = *wcSrc++;
2380 numElement--;
2381 count--;
2383 if (!numElement && truncate)
2385 *(p-1) = 0;
2386 return STRUNCATE;
2388 else if (!numElement)
2390 *wcDest = 0;
2391 return ERANGE;
2394 *p = 0;
2395 return 0;
2398 /******************************************************************
2399 * wcscat_s (MSVCRT.@)
2402 INT CDECL wcscat_s(wchar_t* dst, size_t elem, const wchar_t* src)
2404 wchar_t* ptr = dst;
2406 if (!dst || elem == 0) return EINVAL;
2407 if (!src)
2409 dst[0] = '\0';
2410 return EINVAL;
2413 /* seek to end of dst string (or elem if no end of string is found */
2414 while (ptr < dst + elem && *ptr != '\0') ptr++;
2415 while (ptr < dst + elem)
2417 if ((*ptr++ = *src++) == '\0') return 0;
2419 /* not enough space */
2420 dst[0] = '\0';
2421 return ERANGE;
2424 /***********************************************************************
2425 * wcscat (MSVCRT.@)
2427 wchar_t* __cdecl wcscat( wchar_t *dst, const wchar_t *src )
2429 wcscpy( dst + wcslen(dst), src );
2430 return dst;
2433 /*********************************************************************
2434 * wcsncat_s (MSVCRT.@)
2437 INT CDECL wcsncat_s(wchar_t *dst, size_t elem,
2438 const wchar_t *src, size_t count)
2440 size_t srclen;
2441 wchar_t dststart;
2442 INT ret = 0;
2444 if (!MSVCRT_CHECK_PMT(dst != NULL)) return EINVAL;
2445 if (!MSVCRT_CHECK_PMT(elem > 0)) return EINVAL;
2446 if (!MSVCRT_CHECK_PMT(src != NULL || count == 0)) return EINVAL;
2448 if (count == 0)
2449 return 0;
2451 for (dststart = 0; dststart < elem; dststart++)
2453 if (dst[dststart] == '\0')
2454 break;
2456 if (dststart == elem)
2458 MSVCRT_INVALID_PMT("dst[elem] is not NULL terminated\n", EINVAL);
2459 return EINVAL;
2462 if (count == _TRUNCATE)
2464 srclen = wcslen(src);
2465 if (srclen >= (elem - dststart))
2467 srclen = elem - dststart - 1;
2468 ret = STRUNCATE;
2471 else
2472 srclen = min(wcslen(src), count);
2473 if (srclen < (elem - dststart))
2475 memcpy(&dst[dststart], src, srclen*sizeof(wchar_t));
2476 dst[dststart+srclen] = '\0';
2477 return ret;
2479 MSVCRT_INVALID_PMT("dst[elem] is too small", ERANGE);
2480 dst[0] = '\0';
2481 return ERANGE;
2484 /*********************************************************************
2485 * wctoint (INTERNAL)
2487 static int wctoint(WCHAR c, int base)
2489 int v = -1;
2490 if ('0' <= c && c <= '9')
2491 v = c - '0';
2492 else if ('A' <= c && c <= 'Z')
2493 v = c - 'A' + 10;
2494 else if ('a' <= c && c <= 'z')
2495 v = c - 'a' + 10;
2496 else {
2497 /* NOTE: wine_fold_string(MAP_FOLDDIGITS) supports too many things. */
2498 /* Unicode points that contain digits 0-9; keep this sorted! */
2499 static const WCHAR zeros[] = {
2500 0x660, 0x6f0, 0x966, 0x9e6, 0xa66, 0xae6, 0xb66, 0xc66, 0xce6,
2501 0xd66, 0xe50, 0xed0, 0xf20, 0x1040, 0x17e0, 0x1810, 0xff10
2503 int i;
2504 for (i = 0; i < ARRAY_SIZE(zeros) && c >= zeros[i]; ++i) {
2505 if (zeros[i] <= c && c <= zeros[i] + 9) {
2506 v = c - zeros[i];
2507 break;
2511 return v < base ? v : -1;
2514 /*********************************************************************
2515 * _wcstoi64_l (MSVCRT.@)
2517 __int64 CDECL _wcstoi64_l(const wchar_t *nptr,
2518 wchar_t **endptr, int base, _locale_t locale)
2520 BOOL negative = FALSE, empty = TRUE;
2521 __int64 ret = 0;
2523 TRACE("(%s %p %d %p)\n", debugstr_w(nptr), endptr, base, locale);
2525 if (!MSVCRT_CHECK_PMT(nptr != NULL)) return 0;
2526 if (!MSVCRT_CHECK_PMT(base == 0 || base >= 2)) return 0;
2527 if (!MSVCRT_CHECK_PMT(base <= 36)) return 0;
2529 if(endptr)
2530 *endptr = (wchar_t*)nptr;
2532 while(_iswspace_l(*nptr, locale)) nptr++;
2534 if(*nptr == '-') {
2535 negative = TRUE;
2536 nptr++;
2537 } else if(*nptr == '+')
2538 nptr++;
2540 if((base==0 || base==16) && wctoint(*nptr, 1)==0 && (nptr[1]=='x' || nptr[1]=='X')) {
2541 base = 16;
2542 nptr += 2;
2545 if(base == 0) {
2546 if(wctoint(*nptr, 1)==0)
2547 base = 8;
2548 else
2549 base = 10;
2552 while(*nptr) {
2553 int v = wctoint(*nptr, base);
2554 if(v<0)
2555 break;
2557 if(negative)
2558 v = -v;
2560 nptr++;
2561 empty = FALSE;
2563 if(!negative && (ret>I64_MAX/base || ret*base>I64_MAX-v)) {
2564 ret = I64_MAX;
2565 *_errno() = ERANGE;
2566 } else if(negative && (ret<I64_MIN/base || ret*base<I64_MIN-v)) {
2567 ret = I64_MIN;
2568 *_errno() = ERANGE;
2569 } else
2570 ret = ret*base + v;
2573 if(endptr && !empty)
2574 *endptr = (wchar_t*)nptr;
2576 return ret;
2579 /*********************************************************************
2580 * _wcstoi64 (MSVCRT.@)
2582 __int64 CDECL _wcstoi64(const wchar_t *nptr,
2583 wchar_t **endptr, int base)
2585 return _wcstoi64_l(nptr, endptr, base, NULL);
2588 /*********************************************************************
2589 * _wcstol_l (MSVCRT.@)
2591 __msvcrt_long CDECL _wcstol_l(const wchar_t *s,
2592 wchar_t **end, int base, _locale_t locale)
2594 __int64 ret = _wcstoi64_l(s, end, base, locale);
2596 if(ret > LONG_MAX) {
2597 ret = LONG_MAX;
2598 *_errno() = ERANGE;
2599 }else if(ret < LONG_MIN) {
2600 ret = LONG_MIN;
2601 *_errno() = ERANGE;
2603 return ret;
2606 /*********************************************************************
2607 * wcstol (MSVCRT.@)
2609 __msvcrt_long CDECL wcstol(const wchar_t *s,
2610 wchar_t **end, int base)
2612 return _wcstol_l(s, end, base, NULL);
2615 /*********************************************************************
2616 * _wtoi_l (MSVCRT.@)
2618 int __cdecl _wtoi_l(const wchar_t *str, _locale_t locale)
2620 __int64 ret = _wcstoi64_l(str, NULL, 10, locale);
2622 if(ret > INT_MAX) {
2623 ret = INT_MAX;
2624 *_errno() = ERANGE;
2625 } else if(ret < INT_MIN) {
2626 ret = INT_MIN;
2627 *_errno() = ERANGE;
2629 return ret;
2632 /*********************************************************************
2633 * _wtoi (MSVCRT.@)
2635 int __cdecl _wtoi(const wchar_t *str)
2637 return _wtoi_l(str, NULL);
2640 /*********************************************************************
2641 * _wtol_l (MSVCRT.@)
2643 __msvcrt_long __cdecl _wtol_l(const wchar_t *str, _locale_t locale)
2645 __int64 ret = _wcstoi64_l(str, NULL, 10, locale);
2647 if(ret > LONG_MAX) {
2648 ret = LONG_MAX;
2649 *_errno() = ERANGE;
2650 } else if(ret < LONG_MIN) {
2651 ret = LONG_MIN;
2652 *_errno() = ERANGE;
2654 return ret;
2657 /*********************************************************************
2658 * _wtol (MSVCRT.@)
2660 __msvcrt_long __cdecl _wtol(const wchar_t *str)
2662 return _wtol_l(str, NULL);
2665 #if _MSVCR_VER>=120
2667 /*********************************************************************
2668 * _wtoll_l (MSVCR120.@)
2670 __int64 __cdecl _wtoll_l(const wchar_t *str, _locale_t locale)
2672 return _wcstoi64_l(str, NULL, 10, locale);
2675 /*********************************************************************
2676 * _wtoll (MSVCR120.@)
2678 __int64 __cdecl _wtoll(const wchar_t *str)
2680 return _wtoll_l(str, NULL);
2683 #endif /* _MSVCR_VER>=120 */
2685 /*********************************************************************
2686 * _wcstoui64_l (MSVCRT.@)
2688 unsigned __int64 CDECL _wcstoui64_l(const wchar_t *nptr,
2689 wchar_t **endptr, int base, _locale_t locale)
2691 BOOL negative = FALSE, empty = TRUE;
2692 unsigned __int64 ret = 0;
2694 TRACE("(%s %p %d %p)\n", debugstr_w(nptr), endptr, base, locale);
2696 if (!MSVCRT_CHECK_PMT(nptr != NULL)) return 0;
2697 if (!MSVCRT_CHECK_PMT(base == 0 || base >= 2)) return 0;
2698 if (!MSVCRT_CHECK_PMT(base <= 36)) return 0;
2700 if(endptr)
2701 *endptr = (wchar_t*)nptr;
2703 while(_iswspace_l(*nptr, locale)) nptr++;
2705 if(*nptr == '-') {
2706 negative = TRUE;
2707 nptr++;
2708 } else if(*nptr == '+')
2709 nptr++;
2711 if((base==0 || base==16) && wctoint(*nptr, 1)==0 && (nptr[1]=='x' || nptr[1]=='X')) {
2712 base = 16;
2713 nptr += 2;
2716 if(base == 0) {
2717 if(wctoint(*nptr, 1)==0)
2718 base = 8;
2719 else
2720 base = 10;
2723 while(*nptr) {
2724 int v = wctoint(*nptr, base);
2725 if(v<0)
2726 break;
2728 nptr++;
2729 empty = FALSE;
2731 if(ret>UI64_MAX/base || ret*base>UI64_MAX-v) {
2732 ret = UI64_MAX;
2733 *_errno() = ERANGE;
2734 } else
2735 ret = ret*base + v;
2738 if(endptr && !empty)
2739 *endptr = (wchar_t*)nptr;
2741 return negative ? -ret : ret;
2744 /*********************************************************************
2745 * _wcstoui64 (MSVCRT.@)
2747 unsigned __int64 CDECL _wcstoui64(const wchar_t *nptr,
2748 wchar_t **endptr, int base)
2750 return _wcstoui64_l(nptr, endptr, base, NULL);
2753 /*********************************************************************
2754 * _wcstoul_l (MSVCRT.@)
2756 __msvcrt_ulong __cdecl _wcstoul_l(const wchar_t *s,
2757 wchar_t **end, int base, _locale_t locale)
2759 __int64 ret = _wcstoi64_l(s, end, base, locale);
2761 if(ret > ULONG_MAX) {
2762 ret = ULONG_MAX;
2763 *_errno() = ERANGE;
2764 }else if(ret < -(__int64)ULONG_MAX) {
2765 ret = 1;
2766 *_errno() = ERANGE;
2768 return ret;
2771 /*********************************************************************
2772 * wcstoul (MSVCRT.@)
2774 __msvcrt_ulong __cdecl wcstoul(const wchar_t *s, wchar_t **end, int base)
2776 return _wcstoul_l(s, end, base, NULL);
2779 /******************************************************************
2780 * wcsnlen (MSVCRT.@)
2782 size_t CDECL wcsnlen(const wchar_t *s, size_t maxlen)
2784 size_t i;
2786 for (i = 0; i < maxlen; i++)
2787 if (!s[i]) break;
2788 return i;
2791 /*********************************************************************
2792 * _towupper_l (MSVCRT.@)
2794 wint_t CDECL _towupper_l(wint_t c, _locale_t locale)
2796 pthreadlocinfo locinfo;
2797 wchar_t ret;
2799 if(!locale)
2800 locinfo = get_locinfo();
2801 else
2802 locinfo = locale->locinfo;
2804 if(!locinfo->lc_handle[LC_CTYPE]) {
2805 if(c >= 'a' && c <= 'z')
2806 return c + 'A' - 'a';
2807 return c;
2810 if(!LCMapStringW(locinfo->lc_handle[LC_CTYPE], LCMAP_UPPERCASE, &c, 1, &ret, 1))
2811 return c;
2812 return ret;
2815 /*********************************************************************
2816 * towupper (MSVCRT.@)
2818 wint_t CDECL towupper(wint_t c)
2820 return _towupper_l(c, NULL);
2823 /*********************************************************************
2824 * wcschr (MSVCRT.@)
2826 wchar_t* CDECL wcschr(const wchar_t *str, wchar_t ch)
2828 do { if (*str == ch) return (WCHAR *)(ULONG_PTR)str; } while (*str++);
2829 return NULL;
2832 /*********************************************************************
2833 * wcsrchr (MSVCRT.@)
2835 wchar_t* CDECL wcsrchr(const wchar_t *str, wchar_t ch)
2837 WCHAR *ret = NULL;
2838 do { if (*str == ch) ret = (WCHAR *)(ULONG_PTR)str; } while (*str++);
2839 return ret;
2842 /***********************************************************************
2843 * wcslen (MSVCRT.@)
2845 size_t CDECL wcslen(const wchar_t *str)
2847 const wchar_t *s = str;
2848 while (*s) s++;
2849 return s - str;
2852 /*********************************************************************
2853 * wcsstr (MSVCRT.@)
2855 wchar_t* CDECL wcsstr(const wchar_t *str, const wchar_t *sub)
2857 while(*str)
2859 const wchar_t *p1 = str, *p2 = sub;
2860 while(*p1 && *p2 && *p1 == *p2)
2862 p1++;
2863 p2++;
2865 if(!*p2)
2866 return (wchar_t*)str;
2867 str++;
2869 return NULL;
2872 /*********************************************************************
2873 * _wtoi64_l (MSVCRT.@)
2875 __int64 CDECL _wtoi64_l(const wchar_t *str, _locale_t locale)
2877 ULONGLONG RunningTotal = 0;
2878 BOOL bMinus = FALSE;
2880 while (_iswspace_l(*str, locale)) {
2881 str++;
2882 } /* while */
2884 if (*str == '+') {
2885 str++;
2886 } else if (*str == '-') {
2887 bMinus = TRUE;
2888 str++;
2889 } /* if */
2891 while (*str >= '0' && *str <= '9') {
2892 RunningTotal = RunningTotal * 10 + *str - '0';
2893 str++;
2894 } /* while */
2896 return bMinus ? -RunningTotal : RunningTotal;
2899 /*********************************************************************
2900 * _wtoi64 (MSVCRT.@)
2902 __int64 CDECL _wtoi64(const wchar_t *str)
2904 return _wtoi64_l(str, NULL);
2907 /*********************************************************************
2908 * _wcsxfrm_l (MSVCRT.@)
2910 size_t CDECL _wcsxfrm_l(wchar_t *dest, const wchar_t *src,
2911 size_t len, _locale_t locale)
2913 pthreadlocinfo locinfo;
2914 int i, ret;
2916 if(!MSVCRT_CHECK_PMT(src)) return INT_MAX;
2917 if(!MSVCRT_CHECK_PMT(dest || !len)) return INT_MAX;
2919 if(len > INT_MAX) {
2920 FIXME("len > INT_MAX not supported\n");
2921 len = INT_MAX;
2924 if(!locale)
2925 locinfo = get_locinfo();
2926 else
2927 locinfo = locale->locinfo;
2929 if(!locinfo->lc_handle[LC_COLLATE]) {
2930 wcsncpy(dest, src, len);
2931 return wcslen(src);
2934 ret = LCMapStringW(locinfo->lc_handle[LC_COLLATE],
2935 LCMAP_SORTKEY, src, -1, NULL, 0);
2936 if(!ret) {
2937 if(len) dest[0] = 0;
2938 *_errno() = EILSEQ;
2939 return INT_MAX;
2941 if(!len) return ret-1;
2943 if(ret > len) {
2944 dest[0] = 0;
2945 *_errno() = ERANGE;
2946 return ret-1;
2949 ret = LCMapStringW(locinfo->lc_handle[LC_COLLATE],
2950 LCMAP_SORTKEY, src, -1, dest, len) - 1;
2951 for(i=ret; i>=0; i--)
2952 dest[i] = ((unsigned char*)dest)[i];
2953 return ret;
2956 /*********************************************************************
2957 * wcsxfrm (MSVCRT.@)
2959 size_t CDECL wcsxfrm(wchar_t *dest, const wchar_t *src, size_t len)
2961 return _wcsxfrm_l(dest, src, len, NULL);