comparison graal/com.oracle.max.criutils/src/com/oracle/max/criutils/LogStream.java @ 3733:e233f5660da4

Added Java files from Maxine project.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Sat, 17 Dec 2011 19:59:18 +0100
parents
children
comparison
equal deleted inserted replaced
3732:3e2e8b8abdaf 3733:e233f5660da4
1 /*
2 * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23 package com.oracle.max.criutils;
24
25 import java.io.*;
26
27 /**
28 * A utility for printing compiler debug and informational output to an output stream.
29 *
30 * A {@link LogStream} instance maintains an internal buffer that is flushed to the underlying
31 * output stream every time one of the {@code println} methods is invoked, or a newline character
32 * ({@code '\n'}) is written.
33 *
34 * All of the {@code print} and {@code println} methods return the {code LogStream} instance
35 * on which they were invoked. This allows chaining of these calls to mitigate use of String
36 * concatenation by the caller.
37 *
38 * A {@code LogStream} maintains a current {@linkplain #indentationLevel() indentation} level.
39 * Each line of output written to this stream has {@code n} spaces prefixed to it where
40 * {@code n} is the value that would be returned by {@link #indentationLevel()} when the first
41 * character of a new line is written.
42 *
43 * A {@code LogStream} maintains a current {@linkplain #position() position} for the current
44 * line being written. This position can be advanced to a specified position by
45 * {@linkplain #fillTo(int, char) filling} this stream with a given character.
46 */
47 public class LogStream {
48
49 /**
50 * Null output stream that simply swallows any output sent to it.
51 */
52 public static final LogStream SINK = new LogStream();
53
54 private static final PrintStream SINK_PS = new PrintStream(new OutputStream() {
55 @Override
56 public void write(int b) throws IOException { }
57 });
58
59 private LogStream() {
60 this.ps = null;
61 this.lineBuffer = null;
62 }
63
64 /**
65 * The output stream to which this log stream writes.
66 */
67 private final PrintStream ps;
68
69 private final StringBuilder lineBuffer;
70 private int indentationLevel;
71 private char indentation = ' ';
72 private boolean indentationDisabled;
73
74 public final PrintStream out() {
75 if (ps == null) {
76 return SINK_PS;
77 }
78 return ps;
79 }
80
81 /**
82 * The system dependent line separator.
83 */
84 public static final String LINE_SEPARATOR = System.getProperty("line.separator");
85
86 /**
87 * Creates a new log stream.
88 *
89 * @param os the underlying output stream to which prints are sent
90 */
91 public LogStream(OutputStream os) {
92 ps = os instanceof PrintStream ? (PrintStream) os : new PrintStream(os);
93 lineBuffer = new StringBuilder(100);
94 }
95
96 /**
97 * Creates a new log stream that shares the same {@linkplain #ps output stream} as a given {@link LogStream}.
98 *
99 * @param log a LogStream whose output stream is shared with this one
100 */
101 public LogStream(LogStream log) {
102 ps = log.ps;
103 lineBuffer = new StringBuilder(100);
104 }
105
106 /**
107 * Prepends {@link #indentation} to the current output line until its write position is equal to the
108 * current {@linkplain #indentationLevel()} level.
109 */
110 private void indent() {
111 if (ps != null) {
112 if (!indentationDisabled && indentationLevel != 0) {
113 while (lineBuffer.length() < indentationLevel) {
114 lineBuffer.append(indentation);
115 }
116 }
117 }
118 }
119
120 private LogStream flushLine(boolean withNewline) {
121 if (ps != null) {
122 if (withNewline) {
123 lineBuffer.append(LINE_SEPARATOR);
124 }
125 ps.print(lineBuffer.toString());
126 ps.flush();
127 lineBuffer.setLength(0);
128 }
129 return this;
130 }
131
132 /**
133 * Flushes the stream. This is done by terminating the current line if it is not at position 0
134 * and then flushing the underlying output stream.
135 */
136 public void flush() {
137 if (ps != null) {
138 if (lineBuffer.length() != 0) {
139 flushLine(false);
140 }
141 ps.flush();
142 }
143 }
144
145 /**
146 * Gets the current column position of this log stream.
147 *
148 * @return the current column position of this log stream
149 */
150 public int position() {
151 return lineBuffer == null ? 0 : lineBuffer.length();
152
153 }
154
155 /**
156 * Gets the current indentation level for this log stream.
157 *
158 * @return the current indentation level for this log stream.
159 */
160 public int indentationLevel() {
161 return indentationLevel;
162 }
163
164 /**
165 * Adjusts the current indentation level of this log stream.
166 *
167 * @param delta
168 */
169 public void adjustIndentation(int delta) {
170 if (delta < 0) {
171 indentationLevel = Math.max(0, indentationLevel + delta);
172 } else {
173 indentationLevel += delta;
174 }
175 }
176
177 /**
178 * Gets the current indentation character of this log stream.
179 */
180 public char indentation() {
181 return indentation;
182 }
183
184 public void disableIndentation() {
185 indentationDisabled = true;
186 }
187
188 public void enableIndentation() {
189 indentationDisabled = false;
190 }
191
192 /**
193 * Sets the character used for indentation.
194 */
195 public void setIndentation(char c) {
196 indentation = c;
197 }
198
199 /**
200 * Advances this stream's {@linkplain #position() position} to a given position by
201 * repeatedly appending a given character as necessary.
202 *
203 * @param position the position to which this stream's position will be advanced
204 * @param filler the character used to pad the stream
205 */
206 public LogStream fillTo(int position, char filler) {
207 if (ps != null) {
208 indent();
209 while (lineBuffer.length() < position) {
210 lineBuffer.append(filler);
211 }
212 }
213 return this;
214 }
215
216 /**
217 * Writes a boolean value to this stream as {@code "true"} or {@code "false"}.
218 *
219 * @param b the value to be printed
220 * @return this {@link LogStream} instance
221 */
222 public LogStream print(boolean b) {
223 if (ps != null) {
224 indent();
225 lineBuffer.append(b);
226 }
227 return this;
228 }
229
230 /**
231 * Writes a boolean value to this stream followed by a {@linkplain #LINE_SEPARATOR line separator}.
232 *
233 * @param b the value to be printed
234 * @return this {@link LogStream} instance
235 */
236 public LogStream println(boolean b) {
237 if (ps != null) {
238 indent();
239 lineBuffer.append(b);
240 return flushLine(true);
241 }
242 return this;
243 }
244
245 /**
246 * Writes a character value to this stream.
247 *
248 * @param c the value to be printed
249 * @return this {@link LogStream} instance
250 */
251 public LogStream print(char c) {
252 if (ps != null) {
253 indent();
254 lineBuffer.append(c);
255 if (c == '\n') {
256 if (lineBuffer.indexOf(LINE_SEPARATOR, lineBuffer.length() - LINE_SEPARATOR.length()) != -1) {
257 flushLine(false);
258 }
259 }
260 }
261 return this;
262 }
263
264 /**
265 * Writes a character value to this stream followed by a {@linkplain #LINE_SEPARATOR line separator}.
266 *
267 * @param c the value to be printed
268 * @return this {@link LogStream} instance
269 */
270 public LogStream println(char c) {
271 if (ps != null) {
272 indent();
273 lineBuffer.append(c);
274 flushLine(true);
275 }
276 return this;
277 }
278
279 /**
280 * Prints an int value.
281 *
282 * @param i the value to be printed
283 * @return this {@link LogStream} instance
284 */
285 public LogStream print(int i) {
286 if (ps != null) {
287 indent();
288 lineBuffer.append(i);
289 }
290 return this;
291 }
292
293 /**
294 * Writes an int value to this stream followed by a {@linkplain #LINE_SEPARATOR line separator}.
295 *
296 * @param i the value to be printed
297 * @return this {@link LogStream} instance
298 */
299 public LogStream println(int i) {
300 if (ps != null) {
301 indent();
302 lineBuffer.append(i);
303 return flushLine(true);
304 }
305 return this;
306 }
307
308 /**
309 * Writes a float value to this stream.
310 *
311 * @param f the value to be printed
312 * @return this {@link LogStream} instance
313 */
314 public LogStream print(float f) {
315 if (ps != null) {
316 indent();
317 lineBuffer.append(f);
318 }
319 return this;
320 }
321
322 /**
323 * Writes a float value to this stream followed by a {@linkplain #LINE_SEPARATOR line separator}.
324 *
325 * @param f the value to be printed
326 * @return this {@link LogStream} instance
327 */
328 public LogStream println(float f) {
329 if (ps != null) {
330 indent();
331 lineBuffer.append(f);
332 return flushLine(true);
333 }
334 return this;
335 }
336
337 /**
338 * Writes a long value to this stream.
339 *
340 * @param l the value to be printed
341 * @return this {@link LogStream} instance
342 */
343 public LogStream print(long l) {
344 if (ps != null) {
345 indent();
346 lineBuffer.append(l);
347 }
348 return this;
349 }
350
351 /**
352 * Writes a long value to this stream followed by a {@linkplain #LINE_SEPARATOR line separator}.
353 *
354 * @param l the value to be printed
355 * @return this {@link LogStream} instance
356 */
357 public LogStream println(long l) {
358 if (ps != null) {
359 indent();
360 lineBuffer.append(l);
361 return flushLine(true);
362 }
363 return this;
364 }
365
366 /**
367 * Writes a double value to this stream.
368 *
369 * @param d the value to be printed
370 * @return this {@link LogStream} instance
371 */
372 public LogStream print(double d) {
373 if (ps != null) {
374 indent();
375 lineBuffer.append(d);
376 }
377 return this;
378 }
379
380 /**
381 * Writes a double value to this stream followed by a {@linkplain #LINE_SEPARATOR line separator}.
382 *
383 * @param d the value to be printed
384 * @return this {@link LogStream} instance
385 */
386 public LogStream println(double d) {
387 if (ps != null) {
388 indent();
389 lineBuffer.append(d);
390 return flushLine(true);
391 }
392 return this;
393 }
394
395 /**
396 * Writes a {@code String} value to this stream. This method ensures that the {@linkplain #position() position}
397 * of this stream is updated correctly with respect to any {@linkplain #LINE_SEPARATOR line separators}
398 * present in {@code s}.
399 *
400 * @param s the value to be printed
401 * @return this {@link LogStream} instance
402 */
403 public LogStream print(String s) {
404 if (ps != null) {
405 if (s == null) {
406 indent();
407 lineBuffer.append(s);
408 return this;
409 }
410
411 int index = 0;
412 int next = s.indexOf(LINE_SEPARATOR, index);
413 while (index < s.length()) {
414 indent();
415 if (next > index) {
416 lineBuffer.append(s.substring(index, next));
417 flushLine(true);
418 index = next + LINE_SEPARATOR.length();
419 next = s.indexOf(LINE_SEPARATOR, index);
420 } else {
421 lineBuffer.append(s.substring(index));
422 break;
423 }
424 }
425 }
426 return this;
427 }
428
429 /**
430 * Writes a {@code String} value to this stream followed by a {@linkplain #LINE_SEPARATOR line separator}.
431 *
432 * @param s the value to be printed
433 * @return this {@link LogStream} instance
434 */
435 public LogStream println(String s) {
436 if (ps != null) {
437 print(s);
438 flushLine(true);
439 }
440 return this;
441 }
442
443 /**
444 * Writes a formatted string to this stream.
445 *
446 * @param format a format string as described in {@link String#format(String, Object...)}
447 * @param args the arguments to be formatted
448 * @return this {@link LogStream} instance
449 */
450 public LogStream printf(String format, Object... args) {
451 if (ps != null) {
452 print(String.format(format, args));
453 }
454 return this;
455 }
456
457 /**
458 * Writes a {@linkplain #LINE_SEPARATOR line separator} to this stream.
459 *
460 * @return this {@code LogStream} instance
461 */
462 public LogStream println() {
463 if (ps != null) {
464 indent();
465 flushLine(true);
466 }
467 return this;
468 }
469 }