iostream.cpp
4.42 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
// Copyright (c) 2012 Artyom Beilis (Tonkikh)
// Copyright (c) 2020-2021 Alexander Grund
//
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#define BOOST_NOWIDE_SOURCE
#include <boost/nowide/iostream.hpp>
#ifndef BOOST_WINDOWS
namespace boost {
namespace nowide {
// LCOV_EXCL_START
/// Avoid empty compilation unit warnings
/// \internal
BOOST_NOWIDE_DECL void dummy_exported_function()
{}
// LCOV_EXCL_STOP
} // namespace nowide
} // namespace boost
#else
#include "console_buffer.hpp"
#include <cassert>
#include <iostream>
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <windows.h>
namespace boost {
namespace nowide {
namespace detail {
namespace {
bool is_atty_handle(HANDLE h)
{
DWORD dummy;
return h && GetConsoleMode(h, &dummy) != FALSE;
}
} // namespace
class console_output_buffer final : public console_output_buffer_base
{
HANDLE handle_;
public:
explicit console_output_buffer(HANDLE handle) : handle_(handle)
{}
protected:
bool
do_write(const wchar_t* buffer, std::size_t num_chars_to_write, std::size_t& num_chars_written) override
{
DWORD size = 0;
const bool result =
WriteConsoleW(handle_, buffer, static_cast<DWORD>(num_chars_to_write), &size, 0) != 0;
num_chars_written = size;
return result;
}
};
class console_input_buffer final : public console_input_buffer_base
{
HANDLE handle_;
public:
explicit console_input_buffer(HANDLE handle) : handle_(handle)
{}
protected:
bool do_read(wchar_t* buffer, std::size_t num_chars_to_read, std::size_t& num_chars_read) override
{
DWORD size = 0;
const auto to_read_size = static_cast<DWORD>(num_chars_to_read);
const bool result = ReadConsoleW(handle_, buffer, to_read_size, &size, 0) != 0;
num_chars_read = size;
return result;
}
};
winconsole_ostream::winconsole_ostream(const bool isBuffered, winconsole_ostream* tieStream) : std::ostream(0)
{
HANDLE h;
if(isBuffered)
h = GetStdHandle(STD_OUTPUT_HANDLE);
else
h = GetStdHandle(STD_ERROR_HANDLE);
if(is_atty_handle(h))
{
d.reset(new console_output_buffer(h));
std::ostream::rdbuf(d.get());
} else
{
std::ostream::rdbuf(isBuffered ? std::cout.rdbuf() : std::cerr.rdbuf());
assert(rdbuf());
}
if(tieStream)
{
tie(tieStream);
setf(ios_base::unitbuf); // If tieStream is set, this is cerr -> set unbuffered
}
}
winconsole_ostream::~winconsole_ostream()
{
try
{
flush();
} catch(...)
{} // LCOV_EXCL_LINE
}
winconsole_istream::winconsole_istream(winconsole_ostream* tieStream) : std::istream(0)
{
HANDLE h = GetStdHandle(STD_INPUT_HANDLE);
if(is_atty_handle(h))
{
d.reset(new console_input_buffer(h));
std::istream::rdbuf(d.get());
} else
{
std::istream::rdbuf(std::cin.rdbuf());
assert(rdbuf());
}
if(tieStream)
tie(tieStream);
}
winconsole_istream::~winconsole_istream()
{}
} // namespace detail
// Make sure those are initialized as early as possible
#ifdef BOOST_MSVC
#pragma warning(disable : 4073)
#pragma init_seg(lib)
#endif
#ifdef BOOST_NOWIDE_HAS_INIT_PRIORITY
#define BOOST_NOWIDE_INIT_PRIORITY __attribute__((init_priority(101)))
#else
#define BOOST_NOWIDE_INIT_PRIORITY
#endif
detail::winconsole_ostream cout BOOST_NOWIDE_INIT_PRIORITY(true, nullptr);
detail::winconsole_istream cin BOOST_NOWIDE_INIT_PRIORITY(&cout);
detail::winconsole_ostream cerr BOOST_NOWIDE_INIT_PRIORITY(false, &cout);
detail::winconsole_ostream clog BOOST_NOWIDE_INIT_PRIORITY(false, nullptr);
} // namespace nowide
} // namespace boost
#endif