Download Reference Manual
The Developer's Library for D
About Wiki Forums Source Search Contact

Ticket #353: RawCoutFilter.d

File RawCoutFilter.d, 2.1 kB (added by Deewiant, 1 year ago)
Line 
1 import tango.core.Exception : IOException;
2 import tango.io.Conduit     : OutputFilter;
3 import tango.io.Console     : Cout, Cerr;
4 import tango.math.Math      : min;
5 import tango.sys.Common;
6
7 // a capturing filter on Stdout and Stderr to disable Unicode translation on console output
8 // Win32 code from Tango's (0.98 RC2) Console.Conduit, changed to to use WriteConsoleA
9 // Posix code from DeviceConduit
10
11 class RawCoutFilter(bool stderr) : OutputFilter {
12
13     private void error() {
14         throw new IOException("RawCoutFilter error: " ~ SysError.lastMsg);
15     }
16
17     private typeof(Cout.stream()) superArgs() {
18         return stderr ? Cerr.stream : Cout.stream;
19     }
20
21     version (Win32) {
22         private HANDLE handle;
23         private bool redirected;
24
25         public this() {
26             reopen();
27
28             super(superArgs());
29         }
30
31         private void reopen() {
32             handle = GetStdHandle(stderr ? cast(DWORD)-12 : cast(DWORD)-11);
33
34             if (handle is null) {
35                 handle = CreateFileA(
36                     "CONOUT$",
37                     GENERIC_READ    | GENERIC_WRITE,
38                     FILE_SHARE_READ | FILE_SHARE_WRITE,
39                     null,
40                     OPEN_EXISTING,
41                     0,
42                     null
43                 );
44
45                 if (handle is null)
46                     error();
47             }
48
49             DWORD dummy;
50             redirected = !GetConsoleMode(handle, &dummy);
51         }
52
53         public override size_t write(void[] src) {
54             if (redirected) {
55                 DWORD written;
56
57                             if (!WriteFile(handle, src.ptr, src.length, &written, null))
58                                     error();
59
60                             return written;
61             } else {
62                 DWORD i = src.length;
63
64                 if (i == 0)
65                     return 0;
66
67                 for (auto p = src.ptr, end = src.ptr + i; p < end; p += i)
68                     // avoid console buffer size limitations, write in smaller chunks
69                     if (!WriteConsoleA(handle, p, min(end - p, 16 * 1024), &i, null))
70                         error();
71
72                 return src.length;
73             }
74         }
75     } else { // Posix
76
77         // stdout is 1, stderr is 2
78         private const int handle = cast(int)stderr + 1;
79
80         public this() { super(superArgs()); }
81
82         public override size_t write(void[] src) {
83             ptrdiff_t written = posix.write(handle, src.ptr, src.length);
84             if (written < 0)
85                 error();
86             return written;
87         }
88     }
89 }