Reactos
at master 153 lines 4.5 kB view raw
1/*** 2*mbtowc.c - Convert multibyte char to wide char. 3* 4* Copyright (c) Microsoft Corporation. All rights reserved. 5* 6*Purpose: 7* Convert a multibyte character into the equivalent wide character. 8* 9*******************************************************************************/ 10#include <corecrt_internal_mbstring.h> 11#include <corecrt_internal_ptd_propagation.h> 12#include <locale.h> 13#include <stdlib.h> 14#include <wchar.h> 15 16using namespace __crt_mbstring; 17 18/*** 19*int mbtowc() - Convert multibyte char to wide character. 20* 21*Purpose: 22* Convert a multi-byte character into the equivalent wide character, 23* according to the LC_CTYPE category of the current locale. 24* [ANSI]. 25* 26* NOTE: Currently, the C libraries support the "C" locale only. 27* Non-C locale support now available under _INTL switch. 28*Entry: 29* wchar_t *pwc = pointer to destination wide character 30* const char *s = pointer to multibyte character 31* size_t n = maximum length of multibyte character to consider 32* 33*Exit: 34* If s = nullptr, returns 0, indicating we only use state-independent 35* character encodings. 36* If s != nullptr, returns: 0 (if *s = null char) 37* -1 (if the next n or fewer bytes not valid mbc) 38* number of bytes comprising converted mbc 39* 40*Exceptions: 41* If errors are encountered, -1 is returned and errno is set to EILSEQ. 42* 43*******************************************************************************/ 44 45extern "C" int __cdecl _mbtowc_internal( 46 wchar_t * pwc, 47 const char * s, 48 size_t n, 49 __crt_cached_ptd_host& ptd 50 ) 51{ 52 static mbstate_t internal_state{}; 53 if (!s || n == 0) 54 { 55 /* indicate do not have state-dependent encodings, 56 handle zero length string */ 57 internal_state = {}; 58 return 0; 59 } 60 61 if (!*s) 62 { 63 /* handle NULL char */ 64 if (pwc) 65 { 66 *pwc = 0; 67 } 68 return 0; 69 } 70 71 const _locale_t locale = ptd.get_locale(); 72 73 if (locale->locinfo->_public._locale_lc_codepage == CP_UTF8) 74 { 75 int result = static_cast<int>(__mbrtowc_utf8(pwc, s, n, &internal_state, ptd)); 76 if (result < 0) 77 result = -1; 78 return result; 79 } 80 81 _ASSERTE(locale->locinfo->_public._locale_mb_cur_max == 1 || 82 locale->locinfo->_public._locale_mb_cur_max == 2); 83 84 if (locale->locinfo->locale_name[LC_CTYPE] == nullptr) 85 { 86 if (pwc) 87 { 88 *pwc = (wchar_t) (unsigned char) *s; 89 } 90 return sizeof(char); 91 } 92 93 if (_isleadbyte_fast_internal((unsigned char) *s, locale)) 94 { 95 _ASSERTE(locale->locinfo->_public._locale_lc_codepage != CP_UTF8 && L"UTF-8 isn't supported in this _mbtowc_l function yet!!!"); 96 97 /* multi-byte char */ 98 // If this is a lead byte, then the codepage better be a multibyte codepage 99 _ASSERTE(locale->locinfo->_public._locale_mb_cur_max > 1); 100 101 if ((locale->locinfo->_public._locale_mb_cur_max <= 1) || ((int) n < locale->locinfo->_public._locale_mb_cur_max) || 102 (__acrt_MultiByteToWideChar(locale->locinfo->_public._locale_lc_codepage, 103 MB_PRECOMPOSED | MB_ERR_INVALID_CHARS, 104 s, 105 locale->locinfo->_public._locale_mb_cur_max, 106 pwc, 107 (pwc) ? 1 : 0) == 0)) 108 { 109 /* validate high byte of mbcs char */ 110 if ((n < (size_t) locale->locinfo->_public._locale_mb_cur_max) || (!*(s + 1))) 111 { 112 ptd.get_errno().set(EILSEQ); 113 return -1; 114 } 115 } 116 return locale->locinfo->_public._locale_mb_cur_max; 117 } 118 else { 119 /* single byte char */ 120 if (__acrt_MultiByteToWideChar(locale->locinfo->_public._locale_lc_codepage, 121 MB_PRECOMPOSED | MB_ERR_INVALID_CHARS, 122 s, 123 1, 124 pwc, 125 (pwc) ? 1 : 0) == 0) 126 { 127 ptd.get_errno().set(EILSEQ); 128 return -1; 129 } 130 return sizeof(char); 131 } 132} 133 134extern "C" int __cdecl _mbtowc_l( 135 wchar_t *pwc, 136 const char *s, 137 size_t n, 138 _locale_t plocinfo 139 ) 140{ 141 __crt_cached_ptd_host ptd(plocinfo); 142 return _mbtowc_internal(pwc, s, n, ptd); 143} 144 145extern "C" int __cdecl mbtowc( 146 wchar_t *pwc, 147 const char *s, 148 size_t n 149 ) 150{ 151 __crt_cached_ptd_host ptd; 152 return _mbtowc_internal(pwc, s, n, ptd); 153}