1 // 2 // fgetwc.cpp 3 // 4 // Copyright (c) Microsoft Corporation. All rights reserved. 5 // 6 // Functions that read the next wide character from a stream and return it. If 7 // the read causes the stream to reach EOF, WEOF is returned and the EOF bit is 8 // set on the stream. 9 // 10 #include <corecrt_internal_stdio.h> 11 12 13 _fgetwc_nolock(FILE * const public_stream)14extern "C" wint_t __cdecl _fgetwc_nolock(FILE* const public_stream) 15 { 16 __crt_stdio_stream const stream(public_stream); 17 18 // If the stream is backed by a real file and is open in a Unicode text mode, 19 // we need to read two bytes (note that we read two bytes for both UTF-8 and 20 // UTF-16 backed streams, since lowio translates UTF-8 to UTF-16 when we read. 21 if (!stream.is_string_backed() && 22 _textmode_safe(_fileno(stream.public_stream())) != __crt_lowio_text_mode::ansi) 23 { 24 wchar_t wc; 25 26 // Compose the wide character by reading byte-by-byte from the stream: 27 char* const wc_first = reinterpret_cast<char*>(&wc); 28 char* const wc_last = wc_first + sizeof(wc); 29 30 for (char* it = wc_first; it != wc_last; ++it) 31 { 32 int const c = _getc_nolock(stream.public_stream()); 33 if (c == EOF) 34 return WEOF; 35 36 *it = static_cast<char>(c); 37 } 38 39 return wc; 40 } 41 42 if (!stream.is_string_backed() && 43 (_osfile_safe(_fileno(stream.public_stream())) & FTEXT)) 44 { 45 int size = 1; 46 int ch; 47 char mbc[4]; 48 wchar_t wch; 49 50 /* text (multi-byte) mode */ 51 if ((ch = _getc_nolock(stream.public_stream())) == EOF) 52 return WEOF; 53 54 mbc[0] = static_cast<char>(ch); 55 56 if (isleadbyte(static_cast<unsigned char>(mbc[0]))) 57 { 58 if ((ch = _getc_nolock(stream.public_stream())) == EOF) 59 { 60 ungetc(mbc[0], stream.public_stream()); 61 return WEOF; 62 } 63 mbc[1] = static_cast<char>(ch); 64 size = 2; 65 } 66 67 if (mbtowc(&wch, mbc, size) == -1) 68 { 69 // Conversion failed! Set errno and return failure: 70 errno = EILSEQ; 71 return WEOF; 72 } 73 74 return wch; 75 } 76 77 // binary (Unicode) mode 78 if (stream->_cnt >= static_cast<int>(sizeof(wchar_t))) 79 { 80 stream->_cnt -= static_cast<int>(sizeof(wchar_t)); 81 return *reinterpret_cast<wchar_t*&>(stream->_ptr)++; 82 } 83 else 84 { 85 return static_cast<wint_t>(__acrt_stdio_refill_and_read_wide_nolock(stream.public_stream())); 86 } 87 } 88 89 90 _getwc_nolock(FILE * const stream)91extern "C" wint_t __cdecl _getwc_nolock(FILE* const stream) 92 { 93 return _fgetwc_nolock(stream); 94 } 95 96 97 fgetwc(FILE * const stream)98extern "C" wint_t __cdecl fgetwc(FILE* const stream) 99 { 100 _VALIDATE_RETURN(stream != nullptr, EINVAL, WEOF); 101 102 wint_t return_value = 0; 103 104 _lock_file(stream); 105 __try 106 { 107 return_value = _fgetwc_nolock(stream); 108 } 109 __finally 110 { 111 _unlock_file(stream); 112 } 113 __endtry 114 115 return return_value; 116 } 117 118 119 getwc(FILE * const stream)120extern "C" wint_t __cdecl getwc(FILE* const stream) 121 { 122 return fgetwc(stream); 123 } 124 125 126 _fgetwchar()127extern "C" wint_t __cdecl _fgetwchar() 128 { 129 return fgetwc(stdin); 130 } 131 132 133 getwchar()134extern "C" wint_t __cdecl getwchar() 135 { 136 return _fgetwchar(); 137 } 138