|
|
/***
*xwctomb.c - Convert wide character to multibyte character, with locale. * * Copyright (c) 1995-2001, Microsoft Corporation. All rights reserved. * *Purpose: * Convert a wide character into the equivalent multibyte character. * *Revision History: * 12-XX-95 PJP Created from wctomb.c December 1995 by P.J. Plauger * 04-18-96 GJF Updated for current locale locking. Also, reformatted * and made several cosmetic changes. * 09-26-96 GJF Made _Getcvt() and wcsrtombs() multithread safe. * *******************************************************************************/
#include <cruntime.h>
#include <stdlib.h>
#include <mtdll.h>
#include <errno.h>
#include <limits.h> /* for MB_LEN_MAX */
#include <string.h> /* for memcpy */
#include <stdio.h> /* for EOF */
#include <xlocinfo.h> /* for _Cvtvec, _Wcrtomb */
#ifdef _WIN32
#include <locale.h>
#include <setlocal.h>
#endif /* _WIN32 */
#ifndef _MT
#define __Wcrtomb_lk _Wcrtomb
#endif
/***
*int _Wcrtomb() - Convert wide character to multibyte character. * *Purpose: * Convert a wide character into the equivalent multi-byte 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: * char *s = pointer to multibyte character * wchar_t wchar = source wide character * mbstate_t *pst = pointer to state (not used) * const _Cvtvec *ploc = pointer to locale info * *Exit: * Returns: * -1 (if error) or number of bytes comprising converted mbc * *Exceptions: * *******************************************************************************/
#ifdef _MT
_CRTIMP2 int __cdecl __Wcrtomb_lk ( char *s, wchar_t wchar, mbstate_t *, const _Cvtvec *ploc );
_CRTIMP2 int __cdecl _Wcrtomb ( char *s, wchar_t wchar, mbstate_t *pst, const _Cvtvec *ploc ) { int retval; int local_lock_flag;
_lock_locale( local_lock_flag ) retval = __Wcrtomb_lk(s, wchar, 0, ploc); _unlock_locale( local_lock_flag ) return retval; } #endif /* _MT */
#ifdef _MT
_CRTIMP2 int __cdecl __Wcrtomb_lk #else /* _MT */
_CRTIMP2 int __cdecl _Wcrtomb #endif /* _MT */
( char *s, wchar_t wchar, mbstate_t *pst, const _Cvtvec *ploc ) { #ifdef _WIN32
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 ( wchar > 255 ) /* validate high byte */ { errno = EILSEQ; return -1; }
*s = (char) wchar; return sizeof(char); } else { int size; BOOL defused = 0;
if ( ((size = WideCharToMultiByte(codepage, WC_COMPOSITECHECK | WC_SEPCHARS, &wchar, 1, s, MB_CUR_MAX, NULL, &defused)) == 0) || (defused) ) { errno = EILSEQ; return -1; }
return size; }
#else /* _WIN32 */
if ( wchar > 255 ) /* validate high byte */ { errno = EILSEQ; return -1; }
*s = (char) wchar; return sizeof(char);
#endif /* _WIN32 */
}
/***
*_Cvtvec _Getcvt() - get conversion info for current locale * *Purpose: * *Entry: * *Exit: * *Exceptions: * *******************************************************************************/
_CRTIMP2 _Cvtvec __cdecl _Getcvt() { _Cvtvec cvt; #ifdef _MT
int local_lock_flag; #endif
_lock_locale( local_lock_flag ) cvt._Hand = __lc_handle[LC_CTYPE]; cvt._Page = __lc_codepage; _unlock_locale( local_lock_flag )
return (cvt); }
/***
*size_t wcrtomb(s, wchar, pst) - translate wchar_t to multibyte, restartably * *Purpose: * *Entry: * *Exit: * *Exceptions: * *******************************************************************************/
_CRTIMP2 size_t __cdecl wcrtomb( char *s, wchar_t wchar, mbstate_t *pst ) { return (s == 0 ? 1 : _Wcrtomb(s, wchar, 0, 0)); }
/***
*size_t wcsrtombs(s, pwcs, n, pst) - translate wide char string to multibyte * string * *Purpose: * *Entry: * *Exit: * *Exceptions: * *******************************************************************************/
_CRTIMP2 size_t __cdecl wcsrtombs( char *s, const wchar_t **pwcs, size_t n, mbstate_t *pst ) { char buf[MB_LEN_MAX]; int i; size_t nc = 0; const wchar_t *wcs = *pwcs; #ifdef _MT
int local_lock_flag; #endif
_lock_locale( local_lock_flag )
if (s == 0) for (; ; nc += i, ++wcs) { /* translate but don't store */ if ((i = __Wcrtomb_lk(buf, *wcs, 0, 0)) <= 0) { _unlock_locale( local_lock_flag ) return ((size_t)-1); } else if (buf[i - 1] == '\0') { _unlock_locale( local_lock_flag ) return (nc + i - 1); } }
for (; 0 < n; nc += i, ++wcs, s += i, n -= i) { /* translate and store */ char *t;
if (n < MB_CUR_MAX) t = buf; else t = s;
if ((i = __Wcrtomb_lk(t, *wcs, 0, 0)) <= 0) { /* encountered invalid sequence */ nc = (size_t)-1; break; }
if (s == t) ; else if (n < i) break; /* won't all fit */ else memcpy(s, buf, i);
if (s[i - 1] == '\0') { /* encountered terminating null */ *pwcs = 0; _unlock_locale( local_lock_flag ) return (nc + i - 1); } }
_unlock_locale( local_lock_flag )
*pwcs = wcs; return (nc); }
/***
*int wctob(wchar) - translate wint_t to one-byte multibyte * *Purpose: * *Entry: * *Exit: * *Exceptions: * *******************************************************************************/
_CRTIMP2 int __cdecl wctob( wint_t wchar ) { if (wchar == WEOF) return (EOF); else { /* check for one-byte translation */ char buf[MB_LEN_MAX]; return (_Wcrtomb(buf, wchar, 0, 0) == 1 ? buf[0] : EOF); } }
|