comparison tango/tango/io/Print.d @ 132:1700239cab2e trunk

[svn r136] MAJOR UNSTABLE UPDATE!!! Initial commit after moving to Tango instead of Phobos. Lots of bugfixes... This build is not suitable for most things.
author lindquist
date Fri, 11 Jan 2008 17:57:40 +0100
parents
children
comparison
equal deleted inserted replaced
131:5825d48b27d1 132:1700239cab2e
1 /*******************************************************************************
2
3 copyright: Copyright (c) 2007 Kris Bell. All rights reserved
4
5 license: BSD style: $(LICENSE)
6
7 version: Feb 2007: Separated from Stdout
8
9 author: Kris
10
11 *******************************************************************************/
12
13 module tango.io.Print;
14
15 private import tango.io.model.IBuffer,
16 tango.io.model.IConduit;
17
18 private import tango.text.convert.Layout;
19
20 /*******************************************************************************
21
22 A bridge between a Layout instance and a Buffer. This is used for
23 the Stdout & Stderr globals, but can be used for general purpose
24 buffer-formatting as desired. The Template type 'T' dictates the
25 text arrangement within the target buffer ~ one of char, wchar or
26 dchar (utf8, utf16, or utf32).
27
28 Print exposes this style of usage:
29 ---
30 auto print = new Print!(char) (...);
31
32 print ("hello"); => hello
33 print (1); => 1
34 print (3.14); => 3.14
35 print ('b'); => b
36 print (1, 2, 3); => 1, 2, 3
37 print ("abc", 1, 2, 3); => abc, 1, 2, 3
38 print ("abc", 1, 2) ("foo"); => abc, 1, 2foo
39 print ("abc") ("def") (3.14); => abcdef3.14
40
41 print.format ("abc {}", 1); => abc 1
42 print.format ("abc {}:{}", 1, 2); => abc 1:2
43 print.format ("abc {1}:{0}", 1, 2); => abc 2:1
44 print.format ("abc ", 1); => abc
45 ---
46
47 Note that the last example does not throw an exception. There
48 are several use-cases where dropping an argument is legitimate,
49 so we're currently not enforcing any particular trap mechanism.
50
51 Flushing the output is achieved through the flush() method, or
52 via an empty pair of parens:
53 ---
54 print ("hello world") ();
55 print ("hello world").flush;
56
57 print.format ("hello {}", "world") ();
58 print.format ("hello {}", "world").flush;
59 ---
60
61 Special character sequences, such as "\n", are written directly to
62 the output without any translation (though an output-filter could
63 be inserted to perform translation as required). Platform-specific
64 newlines are generated instead via the newline() method, which also
65 flushes the output when configured to do so:
66 ---
67 print ("hello ") ("world").newline;
68 print.format ("hello {}", "world").newline;
69 print.formatln ("hello {}", "world");
70 ---
71
72 The format() method supports the range of formatting options
73 exposed by tango.text.convert.Layout and extensions thereof;
74 including the full I18N extensions where configured in that
75 manner. To create a French instance of Print:
76 ---
77 import tango.text.locale.Locale;
78
79 auto locale = new Locale (Culture.getCulture ("fr-FR"));
80 auto print = new Print!(char) (locale, ...);
81 ---
82
83 Note that Print is *not* intended to be thread-safe. Use either
84 tango.util.log.Trace or the standard logging facilities in order
85 to enable atomic console I/O
86
87 *******************************************************************************/
88
89 class Print(T) : OutputStream
90 {
91 private T[] eol;
92 private OutputStream output;
93 private Layout!(T) convert;
94 private bool flushLines;
95
96 public alias print opCall;
97
98 version (Win32)
99 private const T[] Eol = "\r\n";
100 else
101 private const T[] Eol = "\n";
102
103 /**********************************************************************
104
105 Construct a Print instance, tying the provided stream
106 to a layout formatter
107
108 **********************************************************************/
109
110 this (Layout!(T) convert, OutputStream output, T[] eol = Eol)
111 {
112 assert (convert);
113 assert (output);
114
115 this.eol = eol;
116 this.output = output;
117 this.convert = convert;
118 }
119
120 /**********************************************************************
121
122 Layout using the provided formatting specification
123
124 **********************************************************************/
125
126 final Print format (T[] fmt, ...)
127 {
128 convert (&sink, _arguments, _argptr, fmt);
129 return this;
130 }
131
132 /**********************************************************************
133
134 Layout using the provided formatting specification
135
136 **********************************************************************/
137
138 final Print formatln (T[] fmt, ...)
139 {
140 convert (&sink, _arguments, _argptr, fmt);
141 return newline;
142 }
143
144 /**********************************************************************
145
146 Unformatted layout, with commas inserted between args.
147 Currently supports a maximum of 24 arguments
148
149 **********************************************************************/
150
151 final Print print (...)
152 {
153 static T[] slice = "{}, {}, {}, {}, {}, {}, {}, {}, "
154 "{}, {}, {}, {}, {}, {}, {}, {}, "
155 "{}, {}, {}, {}, {}, {}, {}, {}, ";
156
157 assert (_arguments.length <= slice.length/4, "Print :: too many arguments");
158
159 if (_arguments.length is 0)
160 output.flush;
161 else
162 convert (&sink, _arguments, _argptr, slice[0 .. _arguments.length * 4 - 2]);
163
164 return this;
165 }
166
167 /***********************************************************************
168
169 Output a newline and optionally flush
170
171 ***********************************************************************/
172
173 final Print newline ()
174 {
175 output.write (eol);
176 if (flushLines)
177 output.flush;
178 return this;
179 }
180
181 /**********************************************************************
182
183 Control implicit flushing of newline(), where true enables
184 flushing. An explicit flush() will always flush the output.
185
186 **********************************************************************/
187
188 final Print flush (bool yes)
189 {
190 flushLines = yes;
191 return this;
192 }
193
194 /**********************************************************************
195
196 Return the associated output stream
197
198 **********************************************************************/
199
200 final OutputStream stream ()
201 {
202 return output;
203 }
204
205 /**********************************************************************
206
207 Set the associated output stream
208
209 **********************************************************************/
210
211 final Print stream (OutputStream output)
212 {
213 this.output = output;
214 return this;
215 }
216
217 /**********************************************************************
218
219 Return the associated Layout
220
221 **********************************************************************/
222
223 final Layout!(T) layout ()
224 {
225 return convert;
226 }
227
228 /**********************************************************************
229
230 Set the associated Layout
231
232 **********************************************************************/
233
234 final Print layout (Layout!(T) layout)
235 {
236 convert = layout;
237 return this;
238 }
239
240 /**********************************************************************
241
242 Sink for passing to the formatter
243
244 **********************************************************************/
245
246 private final uint sink (T[] s)
247 {
248 return output.write (s);
249 }
250
251 /**********************************************************************/
252 /********************* OutputStream Interface *************************/
253 /**********************************************************************/
254
255
256 /***********************************************************************
257
258 Return the host conduit
259
260 ***********************************************************************/
261
262 IConduit conduit ()
263 {
264 return output.conduit;
265 }
266
267 /***********************************************************************
268
269 Write to conduit from a source array. The provided src
270 content will be written to the conduit.
271
272 Returns the number of bytes written from src, which may
273 be less than the quantity provided
274
275 ***********************************************************************/
276
277 uint write (void[] src)
278 {
279 return output.write (src);
280 }
281
282 /**********************************************************************
283
284 Flush the output stream
285
286 **********************************************************************/
287
288 final OutputStream flush ()
289 {
290 output.flush;
291 return this;
292 }
293
294 /***********************************************************************
295
296 Transfer the content of another conduit to this one. Returns
297 a reference to this class, and throws IOException on failure.
298
299 ***********************************************************************/
300
301 OutputStream copy (InputStream src)
302 {
303 output.copy (src);
304 return this;
305 }
306
307 /***********************************************************************
308
309 Close the output
310
311 ***********************************************************************/
312
313 void close ()
314 {
315 output.close;
316 }
317 }
318
319
320 debug (Print)
321 {
322 import tango.io.GrowBuffer;
323 import tango.text.convert.Layout;
324
325 void main()
326 {
327 auto print = new Print!(char) (new Layout!(char), new GrowBuffer);
328
329 for (int i=0;i < 1000; i++)
330 print(i).newline;
331 }
332 }