/*
 * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */


package org.graalvm.compiler.debug;

import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;

A utility for printing compiler debug and informational output to an output stream. A LogStream instance maintains an internal buffer that is flushed to the underlying output stream every time one of the println methods is invoked, or a newline character ( '\n') is written. All of the print and println methods return the {code LogStream} instance on which they were invoked. This allows chaining of these calls to mitigate use of String concatenation by the caller. A LogStream maintains a current indentation level. Each line of output written to this stream has n spaces prefixed to it where n is the value that would be returned by indentationLevel() when the first character of a new line is written. A LogStream maintains a current position for the current line being written. This position can be advanced to a specified position by filling this stream with a given character.
/** * A utility for printing compiler debug and informational output to an output stream. * * A {@link LogStream} instance maintains an internal buffer that is flushed to the underlying * output stream every time one of the {@code println} methods is invoked, or a newline character ( * {@code '\n'}) is written. * * All of the {@code print} and {@code println} methods return the {code LogStream} instance on * which they were invoked. This allows chaining of these calls to mitigate use of String * concatenation by the caller. * * A {@code LogStream} maintains a current {@linkplain #indentationLevel() indentation} level. Each * line of output written to this stream has {@code n} spaces prefixed to it where {@code n} is the * value that would be returned by {@link #indentationLevel()} when the first character of a new * line is written. * * A {@code LogStream} maintains a current {@linkplain #position() position} for the current line * being written. This position can be advanced to a specified position by * {@linkplain #fillTo(int, char) filling} this stream with a given character. */
public class LogStream {
Null output stream that simply swallows any output sent to it.
/** * Null output stream that simply swallows any output sent to it. */
public static final LogStream SINK = new LogStream(); private static final PrintStream SINK_PS = new PrintStream(new OutputStream() { @Override public void write(int b) throws IOException { } }); private LogStream() { this.ps = null; this.lineBuffer = null; }
The output stream to which this log stream writes.
/** * The output stream to which this log stream writes. */
private final PrintStream ps; private final StringBuilder lineBuffer; private int indentationLevel; private char indentation = ' '; private boolean indentationDisabled; public final PrintStream out() { if (ps == null) { return SINK_PS; } return ps; }
The system dependent line separator.
/** * The system dependent line separator. */
public static final String LINE_SEPARATOR = System.getProperty("line.separator");
Creates a new log stream.
Params:
  • os – the underlying output stream to which prints are sent
/** * Creates a new log stream. * * @param os the underlying output stream to which prints are sent */
public LogStream(OutputStream os) { ps = os instanceof PrintStream ? (PrintStream) os : new PrintStream(os); lineBuffer = new StringBuilder(100); }
Creates a new log stream that shares the same output stream as a given LogStream.
Params:
  • log – a LogStream whose output stream is shared with this one
/** * Creates a new log stream that shares the same {@linkplain #ps output stream} as a given * {@link LogStream}. * * @param log a LogStream whose output stream is shared with this one */
public LogStream(LogStream log) { ps = log.ps; lineBuffer = new StringBuilder(100); }
Prepends indentation to the current output line until its write position is equal to the current indentationLevel() level.
/** * Prepends {@link #indentation} to the current output line until its write position is equal to * the current {@linkplain #indentationLevel()} level. */
private void indent() { if (ps != null) { if (!indentationDisabled && indentationLevel != 0) { while (lineBuffer.length() < indentationLevel) { lineBuffer.append(indentation); } } } } private LogStream flushLine(boolean withNewline) { if (ps != null) { if (withNewline) { lineBuffer.append(LINE_SEPARATOR); } ps.print(lineBuffer.toString()); ps.flush(); lineBuffer.setLength(0); } return this; }
Flushes the stream. This is done by terminating the current line if it is not at position 0 and then flushing the underlying output stream.
/** * Flushes the stream. This is done by terminating the current line if it is not at position 0 * and then flushing the underlying output stream. */
public void flush() { if (ps != null) { if (lineBuffer.length() != 0) { flushLine(false); } ps.flush(); } }
Gets the current column position of this log stream.
Returns:the current column position of this log stream
/** * Gets the current column position of this log stream. * * @return the current column position of this log stream */
public int position() { return lineBuffer == null ? 0 : lineBuffer.length(); }
Gets the current indentation level for this log stream.
Returns:the current indentation level for this log stream.
/** * Gets the current indentation level for this log stream. * * @return the current indentation level for this log stream. */
public int indentationLevel() { return indentationLevel; }
Adjusts the current indentation level of this log stream.
Params:
  • delta –
/** * Adjusts the current indentation level of this log stream. * * @param delta */
public void adjustIndentation(int delta) { if (delta < 0) { indentationLevel = Math.max(0, indentationLevel + delta); } else { indentationLevel += delta; } }
Gets the current indentation character of this log stream.
/** * Gets the current indentation character of this log stream. */
public char indentation() { return indentation; } public void disableIndentation() { indentationDisabled = true; } public void enableIndentation() { indentationDisabled = false; }
Sets the character used for indentation.
/** * Sets the character used for indentation. */
public void setIndentation(char c) { indentation = c; }
Advances this stream's position to a given position by repeatedly appending a given character as necessary.
Params:
  • position – the position to which this stream's position will be advanced
  • filler – the character used to pad the stream
/** * Advances this stream's {@linkplain #position() position} to a given position by repeatedly * appending a given character as necessary. * * @param position the position to which this stream's position will be advanced * @param filler the character used to pad the stream */
public LogStream fillTo(int position, char filler) { if (ps != null) { indent(); while (lineBuffer.length() < position) { lineBuffer.append(filler); } } return this; }
Writes a boolean value to this stream as "true" or "false".
Params:
  • b – the value to be printed
Returns:this LogStream instance
/** * Writes a boolean value to this stream as {@code "true"} or {@code "false"}. * * @param b the value to be printed * @return this {@link LogStream} instance */
public LogStream print(boolean b) { if (ps != null) { indent(); lineBuffer.append(b); } return this; }
Writes a boolean value to this stream followed by a line separator.
Params:
  • b – the value to be printed
Returns:this LogStream instance
/** * Writes a boolean value to this stream followed by a {@linkplain #LINE_SEPARATOR line * separator}. * * @param b the value to be printed * @return this {@link LogStream} instance */
public LogStream println(boolean b) { if (ps != null) { indent(); lineBuffer.append(b); return flushLine(true); } return this; }
Writes a character value to this stream.
Params:
  • c – the value to be printed
Returns:this LogStream instance
/** * Writes a character value to this stream. * * @param c the value to be printed * @return this {@link LogStream} instance */
public LogStream print(char c) { if (ps != null) { indent(); lineBuffer.append(c); if (c == '\n') { if (lineBuffer.indexOf(LINE_SEPARATOR, lineBuffer.length() - LINE_SEPARATOR.length()) != -1) { flushLine(false); } } } return this; }
Writes a character value to this stream followed by a line separator.
Params:
  • c – the value to be printed
Returns:this LogStream instance
/** * Writes a character value to this stream followed by a {@linkplain #LINE_SEPARATOR line * separator}. * * @param c the value to be printed * @return this {@link LogStream} instance */
public LogStream println(char c) { if (ps != null) { indent(); lineBuffer.append(c); flushLine(true); } return this; }
Prints an int value.
Params:
  • i – the value to be printed
Returns:this LogStream instance
/** * Prints an int value. * * @param i the value to be printed * @return this {@link LogStream} instance */
public LogStream print(int i) { if (ps != null) { indent(); lineBuffer.append(i); } return this; }
Writes an int value to this stream followed by a line separator.
Params:
  • i – the value to be printed
Returns:this LogStream instance
/** * Writes an int value to this stream followed by a {@linkplain #LINE_SEPARATOR line separator}. * * @param i the value to be printed * @return this {@link LogStream} instance */
public LogStream println(int i) { if (ps != null) { indent(); lineBuffer.append(i); return flushLine(true); } return this; }
Writes a float value to this stream.
Params:
  • f – the value to be printed
Returns:this LogStream instance
/** * Writes a float value to this stream. * * @param f the value to be printed * @return this {@link LogStream} instance */
public LogStream print(float f) { if (ps != null) { indent(); lineBuffer.append(f); } return this; }
Writes a float value to this stream followed by a line separator .
Params:
  • f – the value to be printed
Returns:this LogStream instance
/** * Writes a float value to this stream followed by a {@linkplain #LINE_SEPARATOR line separator} * . * * @param f the value to be printed * @return this {@link LogStream} instance */
public LogStream println(float f) { if (ps != null) { indent(); lineBuffer.append(f); return flushLine(true); } return this; }
Writes a long value to this stream.
Params:
  • l – the value to be printed
Returns:this LogStream instance
/** * Writes a long value to this stream. * * @param l the value to be printed * @return this {@link LogStream} instance */
public LogStream print(long l) { if (ps != null) { indent(); lineBuffer.append(l); } return this; }
Writes a long value to this stream followed by a line separator.
Params:
  • l – the value to be printed
Returns:this LogStream instance
/** * Writes a long value to this stream followed by a {@linkplain #LINE_SEPARATOR line separator}. * * @param l the value to be printed * @return this {@link LogStream} instance */
public LogStream println(long l) { if (ps != null) { indent(); lineBuffer.append(l); return flushLine(true); } return this; }
Writes a double value to this stream.
Params:
  • d – the value to be printed
Returns:this LogStream instance
/** * Writes a double value to this stream. * * @param d the value to be printed * @return this {@link LogStream} instance */
public LogStream print(double d) { if (ps != null) { indent(); lineBuffer.append(d); } return this; }
Writes a double value to this stream followed by a line separator.
Params:
  • d – the value to be printed
Returns:this LogStream instance
/** * Writes a double value to this stream followed by a {@linkplain #LINE_SEPARATOR line * separator}. * * @param d the value to be printed * @return this {@link LogStream} instance */
public LogStream println(double d) { if (ps != null) { indent(); lineBuffer.append(d); return flushLine(true); } return this; }
Writes a String value to this stream. This method ensures that the position of this stream is updated correctly with respect to any line separators present in s.
Params:
  • s – the value to be printed
Returns:this LogStream instance
/** * Writes a {@code String} value to this stream. This method ensures that the * {@linkplain #position() position} of this stream is updated correctly with respect to any * {@linkplain #LINE_SEPARATOR line separators} present in {@code s}. * * @param s the value to be printed * @return this {@link LogStream} instance */
public LogStream print(String s) { if (ps != null) { if (s == null) { indent(); lineBuffer.append(s); return this; } int index = 0; int next = s.indexOf(LINE_SEPARATOR, index); while (index < s.length()) { indent(); if (next > index || next == 0) { lineBuffer.append(s.substring(index, next)); flushLine(true); index = next + LINE_SEPARATOR.length(); next = s.indexOf(LINE_SEPARATOR, index); } else { lineBuffer.append(s.substring(index)); break; } } } return this; }
Writes a String value to this stream followed by a line separator.
Params:
  • s – the value to be printed
Returns:this LogStream instance
/** * Writes a {@code String} value to this stream followed by a {@linkplain #LINE_SEPARATOR line * separator}. * * @param s the value to be printed * @return this {@link LogStream} instance */
public LogStream println(String s) { if (ps != null) { print(s); flushLine(true); } return this; }
Writes a formatted string to this stream.
Params:
Returns:this LogStream instance
/** * Writes a formatted string to this stream. * * @param format a format string as described in {@link String#format(String, Object...)} * @param args the arguments to be formatted * @return this {@link LogStream} instance */
public LogStream printf(String format, Object... args) { if (ps != null) { print(String.format(format, args)); } return this; }
Writes a line separator to this stream.
Returns:this LogStream instance
/** * Writes a {@linkplain #LINE_SEPARATOR line separator} to this stream. * * @return this {@code LogStream} instance */
public LogStream println() { if (ps != null) { indent(); flushLine(true); } return this; } }