/*** *wcstombs.c - Convert wide char string to multibyte char string. * * Copyright (c) 1990-1997, Microsoft Corporation. All rights reserved. * *Purpose: * Convert a wide char string into the equivalent multibyte char string. * *******************************************************************************/ #include #include #include #include #include #include #include #ifndef _MAC #include #include #endif /* _MAC */ /*** *int __cdecl wcsncnt - count wide characters in a string, up to n. * *Purpose: * Internal local support function. Counts characters in string including NULL. * If NULL not found in n chars, then return n. * *Entry: * const wchar_t *string - start of string * int n - character count * *Exit: * returns number of wide characters from start of string to * NULL (inclusive), up to n. * *Exceptions: * *******************************************************************************/ static int __cdecl wcsncnt ( const wchar_t *string, int cnt ) { int n = cnt+1; wchar_t *cp = (wchar_t *)string; while (--n && *cp) cp++; if (n && !*cp) return cp - string + 1; return cnt; } /*** *size_t wcstombs() - Convert wide char string to multibyte char string. * *Purpose: * Convert a wide char string into the equivalent multibyte 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: * char *s = pointer to destination multibyte char string * const wchar_t *pwc = pointer to source wide character string * size_t n = maximum number of bytes to store in s * *Exit: * If s != NULL, returns (size_t)-1 (if a wchar cannot be converted) * Otherwise: Number of bytes modified (<=n), not including * the terminating NUL, if any. * *Exceptions: * Returns (size_t)-1 if s is NULL or invalid mb character encountered. * *******************************************************************************/ #ifdef _MT size_t __cdecl wcstombs ( char * s, const wchar_t * pwcs, size_t n ) { int retval; int local_lock_flag; _lock_locale( local_lock_flag ) retval = _wcstombs_lk(s, pwcs, n); _unlock_locale( local_lock_flag ); return retval; } #endif /* _MT */ #ifdef _MT size_t __cdecl _wcstombs_lk #else /* _MT */ size_t __cdecl wcstombs #endif /* _MT */ ( char * s, const wchar_t * pwcs, size_t n ) { size_t count = 0; #ifndef _MAC int i, retval; char buffer[MB_LEN_MAX]; BOOL defused = 0; #endif /* _MAC */ if (s && n == 0) /* dest string exists, but 0 bytes converted */ return (size_t) 0; _ASSERTE(pwcs != NULL); #ifndef _MAC /* if destination string exists, fill it in */ if (s) { if (__lc_handle[LC_CTYPE] == _CLOCALEHANDLE) { /* C locale: easy and fast */ while(count < n) { if (*pwcs > 255) /* validate high byte */ { errno = EILSEQ; return (size_t)-1; /* error */ } s[count] = (char) *pwcs; if (*pwcs++ == L'\0') return count; count++; } return count; } else { if (1 == MB_CUR_MAX) { /* If SBCS, one wchar_t maps to one char */ /* WideCharToMultiByte will compare past NULL - reset n */ if (n > 0) n = wcsncnt(pwcs, n); if ( ((count = WideCharToMultiByte( __lc_codepage, WC_COMPOSITECHECK | WC_SEPCHARS, pwcs, n, s, n, NULL, &defused )) != 0) && (!defused) ) { if (*(s + count - 1) == '\0') count--; /* don't count NUL */ return count; } errno = EILSEQ; return (size_t)-1; } else { /* If MBCS, wchar_t to char mapping unknown */ /* Assume that usually the buffer is large enough */ if ( ((count = WideCharToMultiByte( __lc_codepage, WC_COMPOSITECHECK | WC_SEPCHARS, pwcs, -1, s, n, NULL, &defused )) != 0) && (!defused) ) { return count - 1; /* don't count NUL */ } if (defused || GetLastError() != ERROR_INSUFFICIENT_BUFFER) { errno = EILSEQ; return (size_t)-1; } /* buffer not large enough, must do char by char */ while (count < n) { if ( ((retval = WideCharToMultiByte( __lc_codepage, 0, pwcs, 1, buffer, MB_CUR_MAX, NULL, &defused )) == 0) || defused ) { errno = EILSEQ; return (size_t)-1; } if (count + retval > n) return count; for (i = 0; i < retval; i++, count++) /* store character */ if((s[count] = buffer[i])=='\0') return count; pwcs++; } return count; } } } else { /* s == NULL, get size only, pwcs must be NUL-terminated */ if (__lc_handle[LC_CTYPE] == _CLOCALEHANDLE) return wcslen(pwcs); else { if (((count=WideCharToMultiByte(__lc_codepage, WC_COMPOSITECHECK | WC_SEPCHARS, pwcs, -1, NULL, 0, NULL, &defused)) == 0) || (defused)) { errno = EILSEQ; return (size_t)-1; } return count - 1; } } #else /* _MAC */ /* if destination string exists, fill it in */ if (s) { /* C locale: easy and fast */ while(count < n) { if (*pwcs > 255) /* validate high byte */ { errno = EILSEQ; return (size_t)-1; /* error */ } s[count] = (char) *pwcs; if (*pwcs++ == L'\0') return count; count++; } return count; } else { /* s == NULL, get size only, pwcs must be NUL-terminated */ const wchar_t *eos = pwcs; while( *eos++ ) ; return( (size_t)(eos - pwcs - 1) ); } #endif /* _MAC */ }