Reactos
at master 146 lines 3.9 kB view raw
1// 2// fputwc.cpp 3// 4// Copyright (c) Microsoft Corporation. All rights reserved. 5// 6// Defines the fputc() family of functions, which write a character to a stream. 7// 8#include <corecrt_internal_stdio.h> 9#include <corecrt_internal_mbstring.h> 10#include <corecrt_internal_ptd_propagation.h> 11 12 13 14static wint_t __cdecl fputwc_binary_nolock(wchar_t const c, __crt_stdio_stream const stream, __crt_cached_ptd_host& ptd) throw() 15{ 16 stream->_cnt -= sizeof(wchar_t); 17 18 // If there is no room for the character in the buffer, flush the buffer and 19 // write the character: 20 if (stream->_cnt < 0) 21 { 22 return static_cast<wint_t>(__acrt_stdio_flush_and_write_wide_nolock(c, stream.public_stream(), ptd)); 23 } 24 25 // Otherwise, there is sufficient room, so we can write directly to the buffer: 26 wchar_t*& wide_stream_ptr = reinterpret_cast<wchar_t*&>(stream->_ptr); 27 *wide_stream_ptr++ = c; 28 29 return c; 30} 31 32 33 34extern "C" wint_t __cdecl _fputwc_nolock_internal(wchar_t const c, FILE* const public_stream, __crt_cached_ptd_host& ptd) 35{ 36 __crt_stdio_stream const stream(public_stream); 37 38 // If this stream is not file-backed, we can write the character directly: 39 if (stream.is_string_backed()) 40 { 41 return fputwc_binary_nolock(c, stream, ptd); 42 } 43 44 __crt_lowio_text_mode const text_mode = _textmode_safe(_fileno(stream.public_stream())); 45 46 // If the file is open in a Unicode text mode, we can write the character 47 // directly to the stream: 48 if (text_mode == __crt_lowio_text_mode::utf16le || text_mode == __crt_lowio_text_mode::utf8) 49 { 50 return fputwc_binary_nolock(c, stream, ptd); 51 } 52 53 // If the file is open in binary mode, we can write the character directly 54 // to the stream: 55 if ((_osfile_safe(_fileno(stream.public_stream())) & FTEXT) == 0) 56 { 57 return fputwc_binary_nolock(c, stream, ptd); 58 } 59 60 // Otherwise, the file is open in ANSI text mode, and we need to translate 61 // the wide character to multibyte before we can write it: 62 char mbc[MB_LEN_MAX]; 63 64 int size; 65 if (_wctomb_internal(&size, mbc, MB_LEN_MAX, c, ptd) != 0) 66 { 67 // If conversion failed, errno is set by wctomb_s and we return WEOF: 68 return WEOF; 69 } 70 71 // Write the character, byte-by-byte: 72 for (int i = 0; i < size; ++i) 73 { 74 if (_fputc_nolock_internal(mbc[i], stream.public_stream(), ptd) == EOF) 75 { 76 return WEOF; 77 } 78 } 79 80 return c; 81} 82 83extern "C" wint_t __cdecl _fputwc_nolock(wchar_t const c, FILE* const public_stream) 84{ 85 __crt_cached_ptd_host ptd; 86 return _fputwc_nolock_internal(c, public_stream, ptd); 87} 88 89extern "C" wint_t __cdecl _putwc_nolock(wchar_t const c, FILE* const stream) 90{ 91 return _fputwc_nolock(c, stream); 92} 93 94 95 96// Writes a wide character to a stream. Returns the wide character on success; 97// WEOF on failure. 98static wint_t __cdecl _fputwc_internal(wchar_t const c, FILE* const stream, __crt_cached_ptd_host& ptd) 99{ 100 _UCRT_VALIDATE_RETURN(ptd, stream != nullptr, EINVAL, WEOF); 101 102 wint_t return_value = WEOF; 103 104 _lock_file(stream); 105 __try 106 { 107 return_value = _fputwc_nolock_internal(c, stream, ptd); 108 } 109 __finally 110 { 111 _unlock_file(stream); 112 } 113 __endtry 114 115 return return_value; 116} 117 118extern "C" wint_t __cdecl fputwc(wchar_t const c, FILE* const stream) 119{ 120 __crt_cached_ptd_host ptd; 121 return _fputwc_internal(c, stream, ptd); 122} 123 124 125 126// Writes a wide character to a stream. See fputwc() for details. 127extern "C" wint_t __cdecl putwc(wchar_t const c, FILE* const stream) 128{ 129 return fputwc(c, stream); 130} 131 132 133 134// Writes a wide character to stdout. See fputwc() for details. 135extern "C" wint_t __cdecl _fputwchar(wchar_t const c) 136{ 137 return fputwc(c, stdout); 138} 139 140 141 142// Writes a wide character to stdout. See fputwc() for details. 143extern "C" wint_t __cdecl putwchar(wchar_t const c) 144{ 145 return _fputwchar(c); 146}