summaryrefslogtreecommitdiffstats
path: root/private/crt32/convert/mbstowcs.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/crt32/convert/mbstowcs.c')
-rw-r--r--private/crt32/convert/mbstowcs.c197
1 files changed, 197 insertions, 0 deletions
diff --git a/private/crt32/convert/mbstowcs.c b/private/crt32/convert/mbstowcs.c
new file mode 100644
index 000000000..739b91c5e
--- /dev/null
+++ b/private/crt32/convert/mbstowcs.c
@@ -0,0 +1,197 @@
+/***
+*mbstowcs.c - Convert multibyte char string to wide char string.
+*
+* Copyright (c) 1990-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Convert a multibyte char string into the equivalent wide char string.
+*
+*Revision History:
+* 08-24-90 KRS Module created.
+* 03-20-91 KRS Ported from 16-bit tree.
+* 10-16-91 ETC Locale support under _INTL switch.
+* 12-09-91 ETC Updated nlsapi; added multithread.
+* 08-20-92 KRS Activated NLSAPI support.
+* 08-31-92 SRW Allow INTL definition to be conditional for building ntcrt.lib
+* 09-02-92 SRW Get _INTL definition via ..\crt32.def
+* 02-09-93 CFW Always stuff WC 0 at end of output string of room (non _INTL).
+* 04-06-93 SKS Replace _CRTAPI* with _cdecl
+* 05-03-93 CFW Return pointer == NULL, return size, plus massive cleanup.
+* 06-02-93 SRW ignore _INTL if _NTSUBSET_ defined.
+* 09-27-93 CFW Avoid cast bug.
+* 10-26-93 CFW Test for invalid MB chars using global preset flag.
+* 01-14-94 SRW if _NTSUBSET_ defined call Rtl functions
+* 07-06-94 SRW Call mblen instead of _mbstrlen for input to Rtl function
+* 07-07-94 MMS/IJH Undo previous change, Call _mbstrlen
+*
+*******************************************************************************/
+
+#ifdef _NTSUBSET_
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#endif
+#include <cruntime.h>
+#include <internal.h>
+#include <stdlib.h>
+#include <os2dll.h>
+#include <locale.h>
+#include <setlocal.h>
+#include <errno.h>
+#include <assert.h>
+
+/***
+*size_t mbstowcs() - Convert multibyte char string to wide char string.
+*
+*Purpose:
+* Convert a multi-byte char string into the equivalent wide char string,
+* according to the LC_CTYPE category of the current locale.
+* [ANSI].
+*
+* NOTE: Currently, the C libraries support the "C" locale only.
+* Non-C locale support now available under _INTL switch.
+*Entry:
+* wchar_t *pwcs = pointer to destination wide character string buffer
+* const char *s = pointer to source multibyte character string
+* size_t n = maximum number of wide characters to store
+*
+*Exit:
+* If s != NULL, returns: number of words modified (<=n)
+* (size_t)-1 (if invalid mbcs)
+*
+*Exceptions:
+* Returns (size_t)-1 if s is NULL or invalid mbcs character encountered
+*
+*******************************************************************************/
+
+#ifdef MTHREAD
+size_t _CRTAPI1 mbstowcs
+ (
+ wchar_t *pwcs,
+ const char *s,
+ size_t n
+ )
+{
+ size_t retval;
+
+ _mlock (_LC_CTYPE_LOCK);
+ retval = _mbstowcs_lk(pwcs, s, n);
+ _munlock (_LC_CTYPE_LOCK);
+ return retval;
+}
+#endif /* MTHREAD */
+
+#ifdef MTHREAD
+size_t _CRTAPI1 _mbstowcs_lk
+#else
+size_t _CRTAPI1 mbstowcs
+#endif
+ (
+ wchar_t *pwcs,
+ const char *s,
+ size_t n
+ )
+{
+ int retval = 0;
+ size_t count = 0;
+
+ if (pwcs && n == 0)
+ return (size_t) 0;
+
+ assert(s != NULL);
+
+ /* if destination string exists, fill it in */
+ if (pwcs)
+ {
+#if defined(_INTL) && !defined(_NTSUBSET_)
+ if (_lc_handle[LC_CTYPE] == _CLOCALEHANDLE &&
+ _lc_codepage == _CLOCALECP)
+ {
+#endif /* _INTL */
+#ifdef _NTSUBSET_
+ {
+ NTSTATUS Status;
+ int size;
+
+ size = _mbstrlen(s);
+ Status = RtlMultiByteToUnicodeN(pwcs, n * sizeof( *pwcs ), (PULONG)&size, s, size+1 );
+ if (!NT_SUCCESS(Status))
+ {
+ errno = EILSEQ;
+ size = -1;
+ } else {
+ size = size / sizeof( *pwcs );
+ if (pwcs[size-1] == L'\0') {
+ size -= 1;
+ }
+ }
+
+ return size;
+ }
+#else
+ /* C locale: easy and fast */
+ while (count < n)
+ {
+ *pwcs = (wchar_t) ((unsigned char)s[count]);
+ if (!s[count])
+ return count;
+ count++;
+ pwcs++;
+ }
+#endif
+ return count;
+#if defined(_INTL) && !defined(_NTSUBSET_)
+ } else {
+ /* Assume that usually the buffer is large enough */
+ if ((count=MultiByteToWideChar(_lc_codepage, MB_PRECOMPOSED|__invalid_mb_chars,
+ s, -1, pwcs, n)) != 0)
+ return count - 1;
+
+ if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
+ {
+ errno = EILSEQ;
+ return (size_t)-1;
+ }
+
+ /* buffer not large enough, must do char by char */
+ while (count < n)
+ {
+ if ((retval = MultiByteToWideChar (_lc_codepage, MB_PRECOMPOSED,
+ s, MB_CUR_MAX, pwcs, 1)) == 0)
+ {
+ errno = EILSEQ;
+ return (size_t)-1;
+ }
+ if (!*s)
+ return count;
+ if (isleadbyte((unsigned char)*s))
+ s++;
+ s++;
+ count++;
+ pwcs++;
+ }
+ return count;
+ }
+#endif /* _INTL */
+ }
+ else { /* pwcs == NULL, get size only, s must be NUL-terminated */
+#if defined(_INTL) && !defined(_NTSUBSET_)
+ if (_lc_handle[LC_CTYPE] == _CLOCALEHANDLE &&
+ _lc_codepage == _CLOCALECP)
+#endif /* _INTL */
+ return strlen(s);
+
+#if defined(_INTL) && !defined(_NTSUBSET_)
+ else {
+ if ((count=MultiByteToWideChar(_lc_codepage, MB_PRECOMPOSED|__invalid_mb_chars,
+ s, -1, NULL, 0)) == 0)
+ {
+ errno = EILSEQ;
+ return (size_t)-1;
+ }
+
+ return count - 1;
+ }
+#endif /* _INTL */
+ }
+}