Browse code

Add iostream.cpp

Steffen Neumann authored on 18/01/2022 11:59:27
Showing1 changed files

1 1
new file mode 100644
... ...
@@ -0,0 +1,261 @@
1
+//
2
+//  Copyright (c) 2012 Artyom Beilis (Tonkikh)
3
+//
4
+//  Distributed under the Boost Software License, Version 1.0. (See
5
+//  accompanying file LICENSE_1_0.txt or copy at
6
+//  http://www.boost.org/LICENSE_1_0.txt)
7
+//
8
+#define BOOST_NOWIDE_SOURCE
9
+#include <boost/nowide/iostream.hpp>
10
+#include <boost/nowide/convert.hpp>
11
+#include <stdio.h>
12
+#include <vector>
13
+
14
+#ifdef BOOST_WINDOWS
15
+
16
+#ifndef NOMINMAX
17
+# define NOMINMAX
18
+#endif
19
+
20
+
21
+#include <windows.h>
22
+
23
+namespace boost {
24
+namespace nowide {
25
+namespace details {
26
+    class console_output_buffer : public std::streambuf {
27
+    public:
28
+        console_output_buffer(HANDLE h) :
29
+            handle_(h),
30
+            isatty_(false)
31
+        {
32
+            if(handle_) {
33
+                DWORD dummy;
34
+                isatty_ = GetConsoleMode(handle_,&dummy) == TRUE;
35
+            }
36
+        }
37
+    protected:
38
+        int sync()
39
+        {
40
+            return overflow(EOF);
41
+        }
42
+        int overflow(int c)
43
+        {
44
+            if(!handle_)
45
+                return -1;
46
+            int n = pptr() - pbase();
47
+            int r = 0;
48
+            
49
+            if(n > 0 && (r=write(pbase(),n)) < 0)
50
+                    return -1;
51
+            if(r < n) {
52
+                memmove(pbase(),pbase() + r,n-r);
53
+            }
54
+            setp(buffer_, buffer_ + buffer_size);
55
+            pbump(n-r);
56
+            if(c!=EOF)
57
+                sputc(c);
58
+            return 0;
59
+        }
60
+    private:
61
+        
62
+        int write(char const *p,int n)
63
+        {
64
+            namespace uf = boost::locale::utf;
65
+            char const *b = p;
66
+            char const *e = p+n;
67
+            if(!isatty_) {
68
+                DWORD size=0;
69
+                if(!WriteFile(handle_,p,n,&size,0) || static_cast<int>(size) != n)
70
+                    return -1;
71
+                return n;
72
+            }
73
+            if(n > buffer_size)
74
+                return -1;
75
+            wchar_t *out = wbuffer_;
76
+            uf::code_point c;
77
+            size_t decoded = 0;
78
+            while(p < e && (c = uf::utf_traits<char>::decode(p,e))!=uf::illegal && c!=uf::incomplete) {
79
+                out = uf::utf_traits<wchar_t>::encode(c,out);
80
+                decoded = p-b;
81
+            }
82
+            if(c==uf::illegal)
83
+                return -1;
84
+            if(!WriteConsoleW(handle_,wbuffer_,out - wbuffer_,0,0))
85
+                return -1;
86
+            return decoded;
87
+        }
88
+        
89
+        static const int buffer_size = 1024;
90
+        char buffer_[buffer_size];
91
+        wchar_t wbuffer_[buffer_size]; // for null
92
+        HANDLE handle_;
93
+        bool isatty_;
94
+    };
95
+    
96
+    class console_input_buffer: public std::streambuf {
97
+    public:
98
+        console_input_buffer(HANDLE h) :
99
+            handle_(h),
100
+            isatty_(false),
101
+            wsize_(0)
102
+        {
103
+            if(handle_) {
104
+                DWORD dummy;
105
+                isatty_ = GetConsoleMode(handle_,&dummy) == TRUE;
106
+            }
107
+        } 
108
+        
109
+    protected:
110
+        int pbackfail(int c)
111
+        {
112
+            if(c==EOF)
113
+                return EOF;
114
+            
115
+            if(gptr()!=eback()) {
116
+                gbump(-1);
117
+                *gptr() = c;
118
+                return 0;
119
+            }
120
+            
121
+            if(pback_buffer_.empty()) {
122
+                pback_buffer_.resize(4);
123
+                char *b = &pback_buffer_[0];
124
+                char *e = b + pback_buffer_.size();
125
+                setg(b,e-1,e);
126
+                *gptr() = c;
127
+            }
128
+            else {
129
+                size_t n = pback_buffer_.size();
130
+                std::vector<char> tmp;
131
+                tmp.resize(n*2);
132
+                memcpy(&tmp[n],&pback_buffer_[0],n);
133
+                tmp.swap(pback_buffer_);
134
+                char *b = &pback_buffer_[0];
135
+                char *e = b + n * 2;
136
+                char *p = b+n-1;
137
+                *p = c;
138
+                setg(b,p,e);
139
+            }
140
+          
141
+            return 0;
142
+        }
143
+
144
+        int underflow()
145
+        {
146
+            if(!handle_)
147
+                return -1;
148
+            if(!pback_buffer_.empty())
149
+                pback_buffer_.clear();
150
+            
151
+            size_t n = read();
152
+            setg(buffer_,buffer_,buffer_+n);
153
+            if(n == 0)
154
+                return EOF;
155
+            return std::char_traits<char>::to_int_type(*gptr());
156
+        }
157
+        
158
+    private:
159
+        
160
+        size_t read()
161
+        {
162
+            namespace uf = boost::locale::utf;
163
+            if(!isatty_) {
164
+                DWORD read_bytes = 0;
165
+                if(!ReadFile(handle_,buffer_,buffer_size,&read_bytes,0))
166
+                    return 0;
167
+                return read_bytes;
168
+            }
169
+            DWORD read_wchars = 0;
170
+            size_t n = wbuffer_size - wsize_;
171
+            if(!ReadConsoleW(handle_,wbuffer_,n,&read_wchars,0))
172
+                return 0;
173
+            wsize_ += read_wchars;
174
+            char *out = buffer_;
175
+            wchar_t *b = wbuffer_;
176
+            wchar_t *e = b + wsize_;
177
+            wchar_t *p = b;
178
+            uf::code_point c;
179
+            wsize_ = e-p;
180
+            while(p < e && (c = uf::utf_traits<wchar_t>::decode(p,e))!=uf::illegal && c!=uf::incomplete) {
181
+                out = uf::utf_traits<char>::encode(c,out);
182
+                wsize_ = e-p;
183
+            }
184
+            
185
+            if(c==uf::illegal)
186
+                return -1;
187
+            
188
+            
189
+            if(c==uf::incomplete) {
190
+                memmove(b,e-wsize_,sizeof(wchar_t)*wsize_);
191
+            }
192
+            
193
+            return out - buffer_;
194
+        }
195
+        
196
+        static const size_t buffer_size = 1024 * 3;
197
+        static const size_t wbuffer_size = 1024;
198
+        char buffer_[buffer_size];
199
+        wchar_t wbuffer_[buffer_size]; // for null
200
+        HANDLE handle_;
201
+        bool isatty_;
202
+        int wsize_;
203
+        std::vector<char> pback_buffer_;
204
+    };
205
+
206
+    winconsole_ostream::winconsole_ostream(int fd) : std::ostream(0)
207
+    {
208
+        HANDLE h = 0;
209
+        switch(fd) {
210
+        case 1:
211
+            h = GetStdHandle(STD_OUTPUT_HANDLE);
212
+            break;
213
+        case 2:
214
+            h = GetStdHandle(STD_ERROR_HANDLE);
215
+            break;
216
+        }
217
+        d.reset(new console_output_buffer(h));
218
+        std::ostream::rdbuf(d.get());
219
+    }
220
+    
221
+    winconsole_ostream::~winconsole_ostream()
222
+    {
223
+    }
224
+
225
+    winconsole_istream::winconsole_istream() : std::istream(0)
226
+    {
227
+        HANDLE h = GetStdHandle(STD_INPUT_HANDLE);
228
+        d.reset(new console_input_buffer(h));
229
+        std::istream::rdbuf(d.get());
230
+    }
231
+    
232
+    winconsole_istream::~winconsole_istream()
233
+    {
234
+    }
235
+    
236
+} // details
237
+    
238
+BOOST_NOWIDE_DECL details::winconsole_istream cin;
239
+BOOST_NOWIDE_DECL details::winconsole_ostream cout(1);
240
+BOOST_NOWIDE_DECL details::winconsole_ostream cerr(2);
241
+BOOST_NOWIDE_DECL details::winconsole_ostream clog(2);
242
+    
243
+namespace {
244
+    struct initialize {
245
+        initialize()
246
+        {
247
+            boost::nowide::cin.tie(&boost::nowide::cout);
248
+            boost::nowide::cerr.tie(&boost::nowide::cout);
249
+            boost::nowide::clog.tie(&boost::nowide::cout);
250
+        }
251
+    } inst;
252
+}
253
+
254
+
255
+    
256
+} // nowide
257
+} // namespace boost
258
+
259
+#endif
260
+///
261
+// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4