mirror of
https://github.com/Chuyu-Team/VC-LTL5.git
synced 2026-10-18 22:00:51 +08:00
115 lines
3.9 KiB
C++
115 lines
3.9 KiB
C++
//
|
|
// _sftbuf.cpp
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//
|
|
// Defines functions that enable and disable temporary buffering and flushing
|
|
// for stdout and stderr. When __acrt_stdio_begin_temporary_buffering_nolock()
|
|
// is called for one of these streams, it tests whether the stream is buffered.
|
|
// If the stream is not buffered, it gives it a temporary buffer, so that we can
|
|
// avoid making sequences of one-character writes.
|
|
//
|
|
// __acrt_stdio_end_temporary_buffering_nolock() must be called to disable
|
|
// temporary buffering when it is no longer needed. This function flushes the
|
|
// stream before tearing down the buffer.
|
|
//
|
|
// Note that these functions are only to be used for output streams--note that
|
|
// __acrt_stdio_begin_temporary_buffering_nolock() sets the _IOWRITE flag. These
|
|
// functions are intended for internal library use only.
|
|
//
|
|
#include <corecrt_internal_stdio.h>
|
|
|
|
|
|
|
|
// Buffer pointers for stdout and stderr
|
|
extern "C" void* __acrt_stdout_buffer = nullptr;
|
|
extern "C" void* __acrt_stderr_buffer = nullptr;
|
|
|
|
|
|
|
|
// If the stream is stdout or stderr and the stream is not buffered, this function
|
|
// creates and initializes a temporary buffer for the stream. On success, the
|
|
// buffer is initialized for the stream and 1 is returned. On failure, 0 is
|
|
// returned.
|
|
extern "C" bool __cdecl __acrt_stdio_begin_temporary_buffering_nolock(
|
|
FILE* const public_stream
|
|
)
|
|
{
|
|
_ASSERTE(public_stream != nullptr);
|
|
|
|
__crt_stdio_stream const stream(public_stream);
|
|
|
|
// Do nothing if the stream is not backed by a TTY device
|
|
if (!_isatty(_fileno(stream.public_stream())))
|
|
return false;
|
|
|
|
void** buffer;
|
|
if (stream.public_stream() == stdout)
|
|
buffer = &__acrt_stdout_buffer;
|
|
else if (stream.public_stream() == stderr)
|
|
buffer = &__acrt_stderr_buffer;
|
|
else
|
|
return false;
|
|
|
|
#ifndef CRTDLL
|
|
_cflush++; // Force library pre-termination procedure to run
|
|
#endif
|
|
|
|
// Make sure the stream is not already buffered:
|
|
if (stream.has_any_buffer())
|
|
return false;
|
|
|
|
stream.set_flags(_IOWRITE | _IOBUFFER_USER | _IOBUFFER_STBUF);
|
|
if (*buffer == nullptr)
|
|
*buffer = _malloc_crt_t(char, _INTERNAL_BUFSIZ).detach();
|
|
|
|
if (*buffer == nullptr)
|
|
{
|
|
// If we failed to allocate a buffer, use the small character buffer:
|
|
stream->_base = reinterpret_cast<char*>(&stream->_charbuf);
|
|
stream->_ptr = reinterpret_cast<char*>(&stream->_charbuf);
|
|
stream->_cnt = 2;
|
|
stream->_bufsiz = 2;
|
|
return true;
|
|
}
|
|
|
|
// Otherwise, we have a new buffer, so set it up for use:
|
|
stream->_base = reinterpret_cast<char*>(*buffer);
|
|
stream->_ptr = reinterpret_cast<char*>(*buffer);
|
|
stream->_cnt = _INTERNAL_BUFSIZ;
|
|
stream->_bufsiz = _INTERNAL_BUFSIZ;
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
// If the stream currently has a temporary buffer that was set via a call to
|
|
// __acrt_stdio_begin_temporary_buffering_nolock(), and if the flag value is
|
|
// 1, this function flushes the stream and disables buffering of the stream.
|
|
extern "C" void __cdecl __acrt_stdio_end_temporary_buffering_nolock(
|
|
bool const flag,
|
|
FILE* const public_stream
|
|
)
|
|
{
|
|
__crt_stdio_stream const stream(public_stream);
|
|
|
|
if (!flag)
|
|
return;
|
|
|
|
if (stream.has_temporary_buffer())
|
|
{
|
|
// Flush the stream and tear down temporary buffering:
|
|
__acrt_stdio_flush_nolock(stream.public_stream());
|
|
stream.unset_flags(_IOBUFFER_USER | _IOBUFFER_STBUF);
|
|
stream->_bufsiz = 0;
|
|
stream->_base = nullptr;
|
|
stream->_ptr = nullptr;
|
|
}
|
|
|
|
// Note: If we expand the functionality of the _IOBUFFER_STBUF bit to
|
|
// include other streams, we may want to clear that bit here under an
|
|
// 'else' clause (i.e., clear bit in the case that we leave the buffer
|
|
// permanently assigned. Given our current use of the bit, the extra
|
|
// code is not needed.
|
|
}
|