package jdk.internal.org.jline.utils;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.io.Writer;
import java.nio.CharBuffer;
public class NonBlockingPumpReader extends NonBlockingReader {
private static final int DEFAULT_BUFFER_SIZE = 4096;
private final CharBuffer readBuffer;
private final CharBuffer writeBuffer;
private final Writer writer;
private boolean closed;
public NonBlockingPumpReader() {
this(DEFAULT_BUFFER_SIZE);
}
public NonBlockingPumpReader(int bufferSize) {
char[] buf = new char[bufferSize];
this.readBuffer = CharBuffer.wrap(buf);
this.writeBuffer = CharBuffer.wrap(buf);
this.writer = new NbpWriter();
readBuffer.limit(0);
}
public Writer getWriter() {
return this.writer;
}
private int wait(CharBuffer buffer, long timeout) throws InterruptedIOException {
boolean isInfinite = (timeout <= 0L);
long end = 0;
if (!isInfinite) {
end = System.currentTimeMillis() + timeout;
}
while (!closed && !buffer.hasRemaining() && (isInfinite || timeout > 0L)) {
notifyAll();
try {
wait(timeout);
} catch (InterruptedException e) {
throw new InterruptedIOException();
}
if (!isInfinite) {
timeout = end - System.currentTimeMillis();
}
}
return closed
? EOF
: buffer.hasRemaining()
? 0
: READ_EXPIRED;
}
private static boolean rewind(CharBuffer buffer, CharBuffer other) {
if (buffer.position() > other.position()) {
other.limit(buffer.position());
}
if (buffer.position() == buffer.capacity()) {
buffer.rewind();
buffer.limit(other.position());
return true;
} else {
return false;
}
}
@Override
public synchronized boolean ready() {
return readBuffer.hasRemaining();
}
public synchronized int available() {
int count = readBuffer.remaining();
if (writeBuffer.position() < readBuffer.position()) {
count += writeBuffer.position();
}
return count;
}
@Override
protected synchronized int read(long timeout, boolean isPeek) throws IOException {
int res = wait(readBuffer, timeout);
if (res >= 0) {
res = isPeek ? readBuffer.get(readBuffer.position()) : readBuffer.get();
}
rewind(readBuffer, writeBuffer);
return res;
}
synchronized void write(char[] cbuf, int off, int len) throws IOException {
while (len > 0) {
if (wait(writeBuffer, 0L) == EOF) {
throw new ClosedException();
}
int count = Math.min(len, writeBuffer.remaining());
writeBuffer.put(cbuf, off, count);
off += count;
len -= count;
rewind(writeBuffer, readBuffer);
}
}
synchronized void flush() {
if (readBuffer.hasRemaining()) {
notifyAll();
}
}
@Override
public synchronized void close() throws IOException {
this.closed = true;
notifyAll();
}
private class NbpWriter extends Writer {
@Override
public void write(char[] cbuf, int off, int len) throws IOException {
NonBlockingPumpReader.this.write(cbuf, off, len);
}
@Override
public void flush() throws IOException {
NonBlockingPumpReader.this.flush();
}
@Override
public void close() throws IOException {
NonBlockingPumpReader.this.close();
}
}
}