ReactOS 0.4.16-dev-853-g88d9285
_sftbuf.cpp
Go to the documentation of this file.
1//
2// _sftbuf.cpp
3//
4// Copyright (c) Microsoft Corporation. All rights reserved.
5//
6// Defines functions that enable and disable temporary buffering and flushing
7// for stdout and stderr. When __acrt_stdio_begin_temporary_buffering_nolock()
8// is called for one of these streams, it tests whether the stream is buffered.
9// If the stream is not buffered, it gives it a temporary buffer, so that we can
10// avoid making sequences of one-character writes.
11//
12// __acrt_stdio_end_temporary_buffering_nolock() must be called to disable
13// temporary buffering when it is no longer needed. This function flushes the
14// stream before tearing down the buffer.
15//
16// Note that these functions are only to be used for output streams--note that
17// __acrt_stdio_begin_temporary_buffering_nolock() sets the _IOWRITE flag. These
18// functions are intended for internal library use only.
19//
22
23
24
25// Buffer pointers for stdout and stderr
26extern "C" { void* __acrt_stdout_buffer = nullptr; }
27extern "C" { void* __acrt_stderr_buffer = nullptr; }
28
29// The temporary buffer has the data of one stdio call. Stderr and Stdout use a
30// temporary buffer for the duration of stdio output calls instead of having a
31// full buffer and write after flush. The temporary buffer prevents the stdio
32// functions from writing to the disk more than once per call when the stream is
33// unbuffered (except when _IONBF is specified).
35{
36 if (stream == stderr)
37 {
38 return true;
39 }
40
42 {
43 return true;
44 }
45
46 return false;
47}
48
49
50// Sets a temporary buffer if necessary (see __acrt_should_use_temporary_buffer).
51// On success, the buffer is initialized for the stream and 1 is returned. On
52// failure, 0 is returned. The temporary buffer ensures that only one write to
53// the disk occurs per stdio output call.
55 FILE* const public_stream
56 )
57{
58 _ASSERTE(public_stream != nullptr);
59
60 __crt_stdio_stream const stream(public_stream);
61
62 if (!__acrt_should_use_temporary_buffer(stream.public_stream()))
63 {
64 return false;
65 }
66
67 void** buffer;
68 if (stream.public_stream() == stdout)
69 {
71 }
72 else if (stream.public_stream() == stderr)
73 {
75 }
76 else
77 {
78 return false;
79 }
80
81 #ifndef CRTDLL
82 _cflush++; // Force library pre-termination procedure to run
83 #endif
84
85 // Make sure the stream is not already buffered:
86 if (stream.has_any_buffer())
87 {
88 return false;
89 }
90
92 if (*buffer == nullptr)
93 {
94 *buffer = _malloc_crt_t(char, _INTERNAL_BUFSIZ).detach();
95 }
96
97 if (*buffer == nullptr)
98 {
99 // If we failed to allocate a buffer, use the small character buffer:
100 stream->_base = reinterpret_cast<char*>(&stream->_charbuf);
101 stream->_ptr = reinterpret_cast<char*>(&stream->_charbuf);
102 stream->_cnt = 2;
103 stream->_bufsiz = 2;
104 return true;
105 }
106
107 // Otherwise, we have a new buffer, so set it up for use:
108 stream->_base = reinterpret_cast<char*>(*buffer);
109 stream->_ptr = reinterpret_cast<char*>(*buffer);
110 stream->_cnt = _INTERNAL_BUFSIZ;
111 stream->_bufsiz = _INTERNAL_BUFSIZ;
112 return true;
113}
114
115
116
117// If the stream currently has a temporary buffer that was set via a call to
118// __acrt_stdio_begin_temporary_buffering_nolock(), and if the flag value is
119// 1, this function flushes the stream and disables buffering of the stream.
121 bool const flag,
122 FILE* const public_stream,
123 __crt_cached_ptd_host& ptd
124 )
125{
126 __crt_stdio_stream const stream(public_stream);
127
128 if (!flag)
129 return;
130
131 if (stream.has_temporary_buffer())
132 {
133 // Flush the stream and tear down temporary buffering:
134 __acrt_stdio_flush_nolock(stream.public_stream(), ptd);
136 stream->_bufsiz = 0;
137 stream->_base = nullptr;
138 stream->_ptr = nullptr;
139 }
140
141 // Note: If we expand the functionality of the _IOBUFFER_STBUF bit to
142 // include other streams, we may want to clear that bit here under an
143 // 'else' clause (i.e., clear bit in the case that we leave the buffer
144 // permanently assigned. Given our current use of the bit, the extra
145 // code is not needed.
146}
int _cflush
Definition: _file.cpp:53
bool __acrt_should_use_temporary_buffer(FILE *const stream)
Definition: _sftbuf.cpp:34
void * __acrt_stdout_buffer
Definition: _sftbuf.cpp:26
void * __acrt_stderr_buffer
Definition: _sftbuf.cpp:27
bool __cdecl __acrt_stdio_begin_temporary_buffering_nolock(FILE *const public_stream)
Definition: _sftbuf.cpp:54
void __cdecl __acrt_stdio_end_temporary_buffering_nolock(bool const flag, FILE *const public_stream, __crt_cached_ptd_host &ptd)
Definition: _sftbuf.cpp:120
#define __cdecl
Definition: accygwin.h:79
#define _INTERNAL_BUFSIZ
@ _IOBUFFER_USER
@ _IOBUFFER_STBUF
#define _ASSERTE(expr)
Definition: crtdbg.h:114
_In_ size_t const _In_ int _In_ bool const _In_ unsigned const _In_ __acrt_rounding_mode const _Inout_ __crt_cached_ptd_host & ptd
Definition: cvt.cpp:355
int __cdecl __acrt_stdio_flush_nolock(FILE *const public_stream, __crt_cached_ptd_host &ptd)
Definition: fflush.cpp:222
GLuint buffer
Definition: glext.h:5915
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean flag
Definition: glfuncs.h:52
#define stdout
Definition: stdio.h:99
_Check_return_ _CRTIMP int __cdecl _fileno(_In_ FILE *_File)
#define stderr
Definition: stdio.h:100
_Check_return_ _CRTIMP int __cdecl _isatty(_In_ int _FileHandle)
Definition: parse.h:23