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

Ticket #353: RawCoutFilter.2.d

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