diff graal/com.oracle.jvmci.debug/src/com/oracle/jvmci/debug/LogStream.java @ 21554:b1530a6cce8c

renamed com.oracle.graal.[debug|options|hotspotvmconfig]* modules to com.oracle.jvmci.[debug|options|hotspotvmconfig]* modules (JBS:GRAAL-53)
author Doug Simon <doug.simon@oracle.com>
date Tue, 26 May 2015 23:21:15 +0200
parents graal/com.oracle.graal.debug/src/com/oracle/graal/debug/LogStream.java@1cde96b96673
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.jvmci.debug/src/com/oracle/jvmci/debug/LogStream.java	Tue May 26 23:21:15 2015 +0200
@@ -0,0 +1,477 @@
+/*
+ * Copyright (c) 2009, 2011, 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 com.oracle.jvmci.debug;
+
+import java.io.*;
+
+/**
+ * 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.
+     */
+    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.
+     */
+    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.
+     */
+    public static final String LINE_SEPARATOR = System.getProperty("line.separator");
+
+    /**
+     * 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 {@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 {@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.
+     */
+    public void flush() {
+        if (ps != null) {
+            if (lineBuffer.length() != 0) {
+                flushLine(false);
+            }
+            ps.flush();
+        }
+    }
+
+    /**
+     * 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.
+     *
+     * @return the current indentation level for this log stream.
+     */
+    public int indentationLevel() {
+        return indentationLevel;
+    }
+
+    /**
+     * 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.
+     */
+    public char indentation() {
+        return indentation;
+    }
+
+    public void disableIndentation() {
+        indentationDisabled = true;
+    }
+
+    public void enableIndentation() {
+        indentationDisabled = false;
+    }
+
+    /**
+     * Sets the character used for indentation.
+     */
+    public void setIndentation(char c) {
+        indentation = c;
+    }
+
+    /**
+     * 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 {@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 {@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.
+     *
+     * @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 {@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.
+     *
+     * @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 {@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.
+     *
+     * @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 {@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.
+     *
+     * @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 {@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.
+     *
+     * @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 {@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 {@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) {
+                    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 {@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.
+     *
+     * @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 {@linkplain #LINE_SEPARATOR line separator} to this stream.
+     *
+     * @return this {@code LogStream} instance
+     */
+    public LogStream println() {
+        if (ps != null) {
+            indent();
+            flushLine(true);
+        }
+        return this;
+    }
+}