diff --git a/platform/util/src/com/intellij/util/io/BaseOutputReader.java b/platform/util/src/com/intellij/util/io/BaseOutputReader.java index d6684414110c..47f7b7bf73e0 100644 --- a/platform/util/src/com/intellij/util/io/BaseOutputReader.java +++ b/platform/util/src/com/intellij/util/io/BaseOutputReader.java @@ -40,12 +40,38 @@ public abstract class BaseOutputReader extends BaseDataReader { myReader = reader; } + private void processLine(char[] buffer, StringBuilder token, int n) { + for (int i = 0; i < n; i++) { + char c = buffer[i]; + if (skipLF && c != '\n') { + token.append('\r'); + } + + if (c == '\r') { + skipLF = true; + } + else { + skipLF = false; + token.append(c); + } + + if (c == '\n') { + onTextAvailable(token.toString()); + token.setLength(0); + } + } + } + + /** * Reads as much data as possible without blocking. + * Relies on InputStream.ready method. + * In case of doubts look at #readAvailableBlocking + * * @return true if non-zero amount of data has been read * @exception IOException If an I/O error occurs */ - protected final boolean readAvailable() throws IOException { + protected final boolean readAvailableNonBlocking() throws IOException { char[] buffer = myBuffer; StringBuilder token = myTextBuffer; token.setLength(0); @@ -56,25 +82,36 @@ public abstract class BaseOutputReader extends BaseDataReader { if (n <= 0) break; read = true; - for (int i = 0; i < n; i++) { - char c = buffer[i]; - if (skipLF && c != '\n') { - token.append('\r'); - } + processLine(buffer, token, n); + } - if (c == '\r') { - skipLF = true; - } - else { - skipLF = false; - token.append(c); - } + if (token.length() != 0) { + onTextAvailable(token.toString()); + token.setLength(0); + } + return read; + } - if (c == '\n') { - onTextAvailable(token.toString()); - token.setLength(0); - } - } + /** + * Reads data with blocking. + * Should be used in case when ready method always returns false for your input stream. + * Should be used if we want to to make our reader exit when end of stream reached. + * Could be used if we prefer IO-blocking over CPU sleeping. + * + * @return true if non-zero amount of data has been read, false if end of the stream is reached + * @exception IOException If an I/O error occurs + */ + protected final boolean readAvailableBlocking() throws IOException { + char[] buffer = myBuffer; + StringBuilder token = myTextBuffer; + token.setLength(0); + + boolean read = false; + int n; + while ((n = myReader.read(buffer)) > 0) { + read = true; + + processLine(buffer, token, n); } if (token.length() != 0) { @@ -84,6 +121,11 @@ public abstract class BaseOutputReader extends BaseDataReader { return read; } + @Override + protected boolean readAvailable() throws IOException { + return readAvailableNonBlocking(); + } + @Override protected void close() throws IOException { myReader.close();