/*** *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 #include #include #include #include /* for MB_LEN_MAX */ #include /* for memcpy */ #include /* for EOF */ #include /* for _Cvtvec, _Wcrtomb */ #ifdef _WIN32 #include #include #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); } }