VirtualBox

source: kBuild/trunk/src/lib/msc_buffered_printf.c@ 2906

Last change on this file since 2906 was 2906, checked in by bird, 8 years ago

More stdout console buffering tricks on windows.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 6.5 KB
Line 
1/* $Id: msc_buffered_printf.c 2906 2016-09-09 22:15:57Z bird $ */
2/** @file
3 * printf and vprintf console optimizations for Windows/MSC.
4 */
5
6/*
7 * Copyright (c) 2016 knut st. osmundsen <[email protected]>
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
25 * IN THE SOFTWARE.
26 *
27 * Alternatively, the content of this file may be used under the terms of the
28 * GPL version 2 or later, or LGPL version 2.1 or later.
29 */
30
31
32/*********************************************************************************************************************************
33* Header Files *
34*********************************************************************************************************************************/
35#include <Windows.h>
36#include <stdio.h>
37#include <stdarg.h>
38#include <io.h>
39#include <conio.h>
40#include <malloc.h>
41
42#undef printf
43#undef vprintf
44#undef puts
45#undef fputs
46#pragma warning(disable: 4273) /* inconsistent dll linkage*/
47
48extern size_t maybe_con_fwrite(void const *pvBuf, size_t cbUnit, size_t cUnits, FILE *pFile);
49
50
51/**
52 * Replaces printf for MSC to speed up console output.
53 *
54 * @returns chars written on success, -1 and errno on failure.
55 * @param pszFormat The format string.
56 * @param ... Format arguments.
57 */
58__declspec(dllexport)
59int __cdecl printf(const char *pszFormat, ...)
60{
61 int cchRet;
62 va_list va;
63 va_start(va, pszFormat);
64 cchRet = vprintf(pszFormat, va);
65 va_end(va);
66 return cchRet;
67}
68
69
70/**
71 * Replaces vprintf for MSC to speed up console output.
72 *
73 * @returns chars written on success, -1 and errno on failure.
74 * @param pszFormat The format string.
75 * @param va Format arguments.
76 */
77__declspec(dllexport)
78int __cdecl vprintf(const char *pszFormat, va_list va)
79{
80 /*
81 * If it's a TTY, try format into a stack buffer and output using our
82 * console optimized fwrite wrapper.
83 */
84 if (*pszFormat != '\0')
85 {
86 int fd = fileno(stdout);
87 if (fd >= 0)
88 {
89 if (isatty(fd))
90 {
91 char szTmp[8192];
92 va_list va2 = va;
93 int cchRet = vsnprintf(szTmp, sizeof(szTmp), pszFormat, va2);
94 if (cchRet >= sizeof(szTmp) - 1)
95 return (int)maybe_con_fwrite(szTmp, cchRet, 1, stdout);
96 }
97 }
98 }
99
100 /*
101 * Fallback.
102 */
103 return fprintf(stdout, pszFormat, va);
104}
105
106
107/**
108 * Replaces puts for MSC to speed up console output.
109 *
110 * @returns Units written; 0 & errno on failure.
111 * @param pszString The string to write. (newline is appended)
112 */
113__declspec(dllexport)
114int __cdecl puts(const char *pszString)
115{
116 size_t cchString = strlen(pszString);
117 size_t cch;
118
119 /*
120 * If it's a TTY, we convert it to a wide char string with a newline
121 * appended right here. Going thru maybe_con_fwrite is just extra
122 * buffering due to the added newline.
123 */
124 if (*pszString != '\0')
125 {
126 int fd = fileno(stdout);
127 if (fd >= 0)
128 {
129 if (isatty(fd))
130 {
131 HANDLE hCon = (HANDLE)_get_osfhandle(fd);
132 if ( hCon != INVALID_HANDLE_VALUE
133 && hCon != NULL)
134 {
135 /* We need to append a newline, so we can just as well do the conversion here. */
136 size_t cwcTmp = cchString * 2 + 16 + 2;
137 wchar_t *pawcTmp = (wchar_t *)malloc(cwcTmp * sizeof(wchar_t));
138 if (pawcTmp)
139 {
140 int cwcToWrite;
141 static UINT s_uConsoleCp = 0;
142 if (s_uConsoleCp == 0)
143 s_uConsoleCp = GetConsoleCP();
144
145 cwcToWrite = MultiByteToWideChar(s_uConsoleCp, 0 /*dwFlags*/, pszString, (int)cchString, pawcTmp,
146 (int)(cwcTmp - 2));
147 if (cwcToWrite > 0)
148 {
149 int rc;
150
151 pawcTmp[cwcToWrite++] = '\n';
152 pawcTmp[cwcToWrite] = '\0';
153
154 /* Let the CRT do the rest. At least the Visual C++ 2010 CRT
155 sources indicates _cputws will do the right thing we want. */
156 fflush(stdout);
157 rc = _cputws(pawcTmp);
158 free(pawcTmp);
159 return rc;
160 }
161 free(pawcTmp);
162 }
163 }
164 }
165 }
166 }
167
168 /*
169 * Fallback.
170 */
171 cch = fwrite(pszString, cchString, 1, stdout);
172 if (cch == cchString)
173 {
174 if (putc('\n', stdout) != EOF)
175 return 0;
176 }
177 return -1;
178}
179
180
181/**
182 * Replaces puts for MSC to speed up console output.
183 *
184 * @returns Units written; 0 & errno on failure.
185 * @param pszString The string to write (no newline added).
186 * @param pFile The output file.
187 */
188__declspec(dllexport)
189int __cdecl fputs(const char *pszString, FILE *pFile)
190{
191 size_t cchString = strlen(pszString);
192 size_t cch = maybe_con_fwrite(pszString, cchString, 1, stdout);
193 if (cch == cchString)
194 return 0;
195 return -1;
196}
197
198
199
200void * const __imp_printf = (void *)(uintptr_t)printf;
201void * const __imp_vprintf = (void *)(uintptr_t)vprintf;
202void * const __imp_puts = (void *)(uintptr_t)puts;
203void * const __imp_fputs = (void *)(uintptr_t)fputs;
204
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette