1 /*******************************************************************************
2 3 Copyright:
4 Copyright (c) 2007 Kris Bell.
5 Some parts copyright (c) 2009-2016 dunnhumby Germany GmbH.
6 All rights reserved.
7 8 License:
9 Tango Dual License: 3-Clause BSD License / Academic Free License v3.0.
10 See LICENSE_TANGO.txt for details.
11 12 Version: Initial release: Oct 2007
13 14 Authors: Kris
15 16 *******************************************************************************/17 18 moduleocean.io.stream.Format;
19 20 importocean.meta.types.Qualifiers;
21 22 importocean.core.Verify;
23 24 importocean.io.device.Conduit;
25 26 importocean.text.convert.Formatter;
27 28 29 /*******************************************************************************
30 31 A bridge between a Layout instance and a stream. This is used for
32 the Stdout & Stderr globals, but can be used for general purpose
33 buffer-formatting as desired.
34 35 FormatOutput exposes this style of usage:
36 ---
37 auto print = new FormatOutput(...);
38 39 print.format ("abc {}", 1); // => abc 1
40 print.format ("abc {}:{}", 1, 2); // => abc 1:2
41 print.format ("abc {1}:{0}", 1, 2); // => abc 2:1
42 print.format ("abc ", 1); // => abc
43 ---
44 45 Note that the last example does not throw an exception. There
46 are several use-cases where dropping an argument is legitimate,
47 so we're currently not enforcing any particular trap mechanism.
48 49 Flushing the output is achieved through the flush() method:
50 ---
51 print.format ("hello {}", "world").flush;
52 ---
53 54 Special character sequences, such as "\n", are written directly to
55 the output without any translation (though an output-filter could
56 be inserted to perform translation as required). Platform-specific
57 newlines are generated instead via the newline() method, which also
58 flushes the output when configured to do so:
59 ---
60 print.format ("hello {}", "world").newline;
61 print.formatln ("hello {}", "world");
62 ---
63 64 Note that FormatOutput is *not* intended to be thread-safe.
65 66 *******************************************************************************/67 68 classFormatOutput : OutputFilter69 {
70 publicaliasOutputFilter.flushflush;
71 72 privatecstringeol;
73 privateboolflushLines;
74 75 publicaliasnewlinenl; /// nl -> newline76 77 protectedstaticimmutableEol = "\n";
78 79 /**********************************************************************
80 81 Construct a FormatOutput instance, tying the provided stream
82 to a layout formatter.
83 84 **********************************************************************/85 86 this (OutputStreamoutput, cstringeol = Eol)
87 {
88 this.eol = eol;
89 super (output);
90 91 }
92 93 /**********************************************************************
94 95 Format the provided arguments to the stream according to the format
96 string
97 98 Params:
99 Args = Variadic template arguments
100 fmt = Format string to use (see `ocean.text.convert.Formatter`
101 args = Arguments to format
102 103 Returns:
104 `this`, for easy chaining
105 106 **********************************************************************/107 108 publictypeof(this) format (Args...) (cstringfmt, Argsargs)
109 {
110 sformat(&this.emit, fmt, args);
111 returnthis;
112 }
113 114 /**********************************************************************
115 116 Format the provided arguments to the stream according to the format
117 string, and append a newline to the output.
118 119 Params:
120 Args = Variadic template arguments
121 fmt = Format string to use (see `ocean.text.convert.Formatter`
122 args = Arguments to format
123 124 Returns:
125 `this`, for easy chaining
126 127 **********************************************************************/128 129 publictypeof(this) formatln (Args...) (cstringfmt, Argsargs)
130 {
131 sformat(&this.emit, fmt, args);
132 this.newline;
133 returnthis;
134 }
135 136 /***********************************************************************
137 138 Output a newline and optionally flush.
139 140 ***********************************************************************/141 142 finalFormatOutputnewline ()
143 {
144 sink.write (eol);
145 if (flushLines)
146 sink.flush;
147 returnthis;
148 }
149 150 /**********************************************************************
151 152 Control implicit flushing of newline(), where true enables
153 flushing. An explicit flush() will always flush the output.
154 155 **********************************************************************/156 157 finalFormatOutputflush (boolyes)
158 {
159 flushLines = yes;
160 returnthis;
161 }
162 163 /**********************************************************************
164 165 Return the associated output stream.
166 167 **********************************************************************/168 169 finalOutputStreamstream ()
170 {
171 returnsink;
172 }
173 174 /**********************************************************************
175 176 Set the associated output stream.
177 178 **********************************************************************/179 180 finalFormatOutputstream (OutputStreamoutput)
181 {
182 sink = output;
183 returnthis;
184 }
185 186 /**********************************************************************
187 188 Sink for passing to the formatter.
189 190 **********************************************************************/191 192 protectedvoidemit (cstrings)
193 {
194 autocount = sink.write (s);
195 if (countisEof)
196 conduit.error ("FormatOutput :: unexpected Eof");
197 }
198 }