home *** CD-ROM | disk | FTP | other *** search
- /***
- *xmbtowc.c - Convert multibyte char to wide char.
- *
- * Copyright (c) 1995-1996, Microsoft Corporation. All rights reserved.
- *
- *Purpose:
- * Convert a multibyte character into the equivalent wide character.
- *
- *Revison History:
- * 12-XX-95 PJP Created from mbtowc.c December 1995 by P.J. Plauger
- * 04-17-96 GJF Updated for current locale locking. Also, reformatted
- * and made several cosmetic changes.
- * 09-25-96 GJF Made mbrlen, mbrtowc and mbsrtowcs multithread safe.
- * 09-17-97 JWM Added "return MB_CUR_MAX" to "if (*pst != 0)" branch.
- *
- *******************************************************************************/
-
- #include <cruntime.h>
- #include <stdlib.h>
- #include <mtdll.h>
- #include <errno.h>
- #include <dbgint.h>
- #include <ctype.h>
- #include <limits.h> /* for INT_MAX */
- #include <stdio.h> /* for EOF */
- #include <xlocinfo.h> /* for _Cvtvec, _Mbrtowc */
- #ifdef _WIN32
- #include <internal.h>
- #include <locale.h>
- #include <setlocal.h>
- #endif /* _WIN32 */
-
- #ifndef _MT
- #define _Mbrtowc_lk _Mbrtowc
- #endif
-
- /***
- *int _Mbrtowc() - Convert multibyte char to wide character.
- *
- *Purpose:
- * Convert a multi-byte character into the equivalent wide character,
- * according to the specified LC_CTYPE category, or 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 *pwc = pointer to destination wide character
- * const char *s = pointer to multibyte character
- * size_t n = maximum length of multibyte character to consider
- * mbstate_t *pst = pointer to state
- * const _Cvtvec * = pointer to locale info
- *
- *Exit:
- * If s = NULL, returns 0, indicating we only use state-independent
- * character encodings.
- * If s != NULL, returns: 0 (if *s = null char)
- * -1 (if the next n or fewer bytes not valid mbc)
- * number of bytes comprising converted mbc
- *
- *Exceptions:
- *
- *******************************************************************************/
-
- #ifdef _MT
- static int __cdecl _Mbrtowc_lk
- (
- wchar_t *pwc,
- const char *s,
- size_t n,
- mbstate_t *pst,
- const _Cvtvec *ploc
- );
-
- int _CRTIMP2 __cdecl _Mbrtowc(
- wchar_t *pwc,
- const char *s,
- size_t n,
- mbstate_t *pst,
- const _Cvtvec *ploc
- )
- {
- int retval;
- #ifdef _MT
- int local_lock_flag;
- #endif
-
- _lock_locale( local_lock_flag )
- retval = _Mbrtowc_lk(pwc, s, n, pst, ploc);
- _unlock_locale( local_lock_flag )
- return retval;
- }
- #endif /* _MT */
- #ifdef _MT
- static int __cdecl _Mbrtowc_lk
- #else /* _MT */
- int _CRTIMP2 __cdecl _Mbrtowc
- #endif /* _MT */
- (
- wchar_t *pwc,
- const char *s,
- size_t n,
- mbstate_t *pst,
- const _Cvtvec *ploc
- )
- {
- _ASSERTE (MB_CUR_MAX == 1 || MB_CUR_MAX == 2);
-
- if ( !s || n == 0 )
- /* indicate do not have state-dependent encodings,
- handle zero length string */
- return 0;
-
- if ( !*s )
- {
- /* handle NULL char */
- if (pwc)
- *pwc = 0;
- return 0;
- }
-
- #ifdef _WIN32
-
- { /* perform locale-dependent parse */
- LCID handle;
- UINT codepage;
-
- if (ploc == 0)
- {
- handle = __lc_handle[LC_CTYPE];
- codepage = __lc_codepage;
- }
- else
- {
- handle = ploc->_Hand;
- codepage = ploc->_Page;
- }
-
- if ( handle == _CLOCALEHANDLE )
- {
- if (pwc)
- *pwc = (wchar_t)(unsigned char)*s;
- return sizeof(char);
- }
-
- if (*pst != 0)
- { /* complete two-byte multibyte character */
- ((char *)pst)[1] = *s;
- if (MB_CUR_MAX <= 1 || (MultiByteToWideChar(codepage,
- MB_PRECOMPOSED|MB_ERR_INVALID_CHARS,
- (char *)pst, 2, pwc, (pwc) ? 1 : 0) == 0))
- { /* translation failed */
- *pst = 0;
- errno = EILSEQ;
- return -1;
- }
- *pst = 0;
- return MB_CUR_MAX;
- }
- else if ( isleadbyte((unsigned char)*s) )
- {
- /* multi-byte char */
- if (n < MB_CUR_MAX)
- { /* save partial multibyte character */
- ((char *)pst)[0] = *s;
- return (-2);
- }
- else if ( MB_CUR_MAX <= 1 ||
- (MultiByteToWideChar( codepage,
- MB_PRECOMPOSED |
- MB_ERR_INVALID_CHARS,
- s,
- MB_CUR_MAX,
- pwc,
- (pwc) ? 1 : 0) == 0) )
- {
- /* validate high byte of mbcs char */
- if (!*(s+1))
- {
- *pst = 0;
- errno = EILSEQ;
- return -1;
- }
- /* else translation failed with no complaint? [pjp] */
- }
- return MB_CUR_MAX;
- }
- else {
- /* single byte char */
-
- if ( MultiByteToWideChar( codepage,
- MB_PRECOMPOSED|MB_ERR_INVALID_CHARS,
- s,
- 1,
- pwc,
- (pwc) ? 1 : 0) == 0 )
- {
- errno = EILSEQ;
- return -1;
- }
-
- return sizeof(char);
- }
- }
-
- #else /* _WIN32 */
-
- /* stuck the "C" locale again */
- if (pwc)
- *pwc = (wchar_t)(unsigned char)*s;
- return sizeof(char);
-
- #endif /* _WIN32 */
- }
-
-
- /***
- *wint_t btowc(c) - translate single byte to wide char
- *
- *Purpose:
- *
- *Entry:
- *
- *Exit:
- *
- *Exceptions:
- *
- *******************************************************************************/
-
- wint_t _CRTIMP2 __cdecl btowc (
- int c
- )
- {
- if (c == EOF)
- return (WEOF);
- else
- { /* convert as one-byte string */
- char ch = (char)c;
- mbstate_t mbst = 0;
- wchar_t wc;
- return (_Mbrtowc(&wc, &ch, 1, &mbst, 0) < 0 ? WEOF : wc);
- }
- }
-
-
- /***
- *size_t mbrlen(s, n, pst) - determine next multibyte code, restartably
- *
- *Purpose:
- *
- *Entry:
- *
- *Exit:
- *
- *Exceptions:
- *
- *******************************************************************************/
-
- size_t _CRTIMP2 __cdecl mbrlen (
- const char *s,
- size_t n,
- mbstate_t *pst
- )
- {
- #ifdef _MT
- int local_lock_flag;
- #endif
- size_t retval;
-
- static mbstate_t mbst = {0};
-
- _lock_locale( local_lock_flag )
- retval = _Mbrtowc_lk(0, s != 0 ? s : 0, n, pst ? pst : &mbst, 0);
- _unlock_locale( local_lock_flag )
-
- return retval;
- }
-
-
- /***
- *size_t mbrtowc(pwc, s, n, pst) - translate multibyte to wchar_t, restartably
- *
- *Purpose:
- *
- *Entry:
- *
- *Exit:
- *
- *Exceptions:
- *
- *******************************************************************************/
-
- size_t _CRTIMP2 __cdecl mbrtowc (
- wchar_t *pwc,
- const char *s,
- size_t n,
- mbstate_t *pst
- )
- {
- #ifdef _MT
- int local_lock_flag;
- #endif
- size_t retval;
-
- static mbstate_t mbst = {0};
-
- _lock_locale( local_lock_flag )
- retval = (s != 0) ? _Mbrtowc_lk(pwc, s, n, pst ? pst : &mbst, 0)
- : _Mbrtowc_lk(0, "", n, pst ? pst : &mbst, 0);
- _unlock_locale( local_lock_flag )
-
- return retval;
- }
-
-
- /***
- *size_t mbsrtowcs(wcs, ps, n, pst) - translate multibyte string to wide,
- * restartably
- *
- *Purpose:
- *
- *Entry:
- *
- *Exit:
- *
- *Exceptions:
- *
- *******************************************************************************/
-
- size_t _CRTIMP2 __cdecl mbsrtowcs (
- wchar_t *wcs,
- const char **ps,
- size_t n,
- mbstate_t *pst
- )
- {
- const char *s = *ps;
- int i;
- size_t nwc = 0;
- #ifdef _MT
- int local_lock_flag;
- #endif
- static mbstate_t mbst = {0};
-
- if (pst == 0)
- pst = &mbst;
-
- _lock_locale( local_lock_flag )
-
- if (wcs == 0)
- for (; ; ++nwc, s += i)
- { /* translate but don't store */
- wchar_t wc;
- if ((i = _Mbrtowc_lk(&wc, s, INT_MAX, pst, 0)) < 0) {
- _unlock_locale( local_lock_flag )
- return ((size_t)-1);
- }
- else if (i == 0) {
- _unlock_locale( local_lock_flag )
- return (nwc);
- }
- }
-
- for (; 0 < n; ++nwc, s += i, ++wcs, --n)
- { /* translate and store */
- if ((i = _Mbrtowc_lk(wcs, s, INT_MAX, pst, 0)) < 0)
- { /* encountered invalid sequence */
- nwc = (size_t)-1;
- break;
- }
- else if (i == 0)
- { /* encountered terminating null */
- s = 0;
- break;
- }
- }
-
- *ps = s;
-
- _unlock_locale( local_lock_flag )
-
- return (nwc);
- }
-