private void append(byte[] buf, int pos, int len) { if (len == 0) { return; } if (len < 0) { throw new AssertionError(); } int p = clip(rBufPos + rBufUsed); System.arraycopy(buf, pos, rBuf, p, len); rBufUsed += len; }
/** * Resizes the ring buffer by preserving it's data. * * <p> * If the new size is not enough to keep all used data in the ring buffer, * the excess old data is discarded. */ public void resize(int newSize) { if (newSize <= 0) { throw new IllegalArgumentException(); } if (newSize < rBufUsed) { // if new buffer is too small to contain all data discard(rBufUsed - newSize); } // discard oldest data byte[] newBuf = new byte[newSize]; int newBufUsed = get(newBuf, 0, newSize); // transfer data to new buffer rBuf = newBuf; rBufSize = newSize; rBufPos = 0; rBufUsed = newBufUsed; }
@Override public int available() throws IOException { lock.lock(); try { return buffer.getUsed(); } finally { lock.unlock(); } }
@Override public int read(byte[] bytes, int offset, int length) throws IOException { lock.lock(); try { // are there any bytes available? while (buffer.getUsed() <= 0) { // was the output closed? if (outputClosed.get()) { // return EOF return -1; } //log.debug("waiting for write so up to {} bytes can be read", length); writeSignal.await(); } int getLength = Math.min(buffer.getUsed(), length); //log.debug("trying to get {} bytes ({} available)", getLength, buffer.getUsed()); buffer.get(bytes, offset, getLength); //log.debug("get {} bytes into buffer ({} available)", getLength, buffer.getUsed()); // signal data read readSignal.signal(); return getLength; } catch (InterruptedException e) { throw new IOException("Interrupted while waiting for signal", e); } finally { lock.unlock(); } }
/** * Gets data from the ring buffer. * * <p> * Convenience method for: <code>read(buf, 0, buf.length)</code> */ public int get(byte[] buf) { return get(buf, 0, buf.length); }
/** * Puts data to the ring buffer. * * <p> * Convenience method for: <code>write(buf, 0, buf.length)</code> * @param buf * @return */ public int put(byte[] buf) { return put(buf, 0, buf.length); }
public BytePipe(int bufferSize) { if (bufferSize <= 0) { throw new IllegalArgumentException("bufferSize must be > 0"); } this.lock = new ReentrantLock(); this.writeSignal = this.lock.newCondition(); this.readSignal = this.lock.newCondition(); this.buffer = new ByteRingBuffer(bufferSize); this.outputClosed = new AtomicBoolean(false); this.inputClosed = new AtomicBoolean(false); this.output = new BytePipeOutputStream(); this.input = new BytePipeInputStream(); }
/** * Gets data from the ring buffer. * * @return The number of bytes read. This is guaranteed to be * <code>min(len, getUsed())</code>. */ public int get(byte[] buf, int pos, int len) { if (len < 0) { throw new IllegalArgumentException(); } int trLen1 = Math.min(len, Math.min(rBufUsed, rBufSize - rBufPos)); remove(buf, pos, trLen1); int trLen2 = Math.min(len - trLen1, rBufUsed); remove(buf, pos + trLen1, trLen2); return trLen1 + trLen2; }
/** * Puts data to the ring buffer. * * @param buf * @param pos * @param len * @return The number of bytes written. This is guaranteed to be * <code>min(len, getFree())</code>. */ public int put(byte[] buf, int pos, int len) { if (len < 0) { throw new IllegalArgumentException(); } if (rBufUsed == 0) { rBufPos = 0; } // (speed optimization) int p1 = rBufPos + rBufUsed; if (p1 < rBufSize) { // free space in two pieces int trLen1 = Math.min(len, rBufSize - p1); append(buf, pos, trLen1); int trLen2 = Math.min(len - trLen1, rBufPos); append(buf, pos + trLen1, trLen2); return trLen1 + trLen2; } else { // free space in one piece int trLen = Math.min(len, rBufSize - rBufUsed); append(buf, pos, trLen); return trLen; } }
@Override public int read(byte[] bytes, int offset, int length) throws IOException { lock.lock(); try { // are there any bytes available? while (buffer.getUsed() <= 0) { // was the output closed? if (outputClosed.get()) { // return EOF return -1; } //log.debug("waiting for write so up to {} bytes can be read", length); writeSignal.await(); } int getLength = Math.min(buffer.getUsed(), length); //log.debug("trying to get {} bytes ({} available)", getLength, buffer.getUsed()); buffer.get(bytes, offset, getLength); //log.debug("get {} bytes into buffer ({} available)", getLength, buffer.getUsed()); // signal data read readSignal.signal(); return getLength; } catch (InterruptedException e) { throw new IOException("Interrupted while waiting for signal", e); } finally { lock.unlock(); } }
/** * Gets data from the ring buffer. * * <p> * Convenience method for: <code>read(buf, 0, buf.length)</code> */ public int get(byte[] buf) { return get(buf, 0, buf.length); }
/** * Puts data to the ring buffer. * * <p> * Convenience method for: <code>write(buf, 0, buf.length)</code> * @param buf * @return */ public int put(byte[] buf) { return put(buf, 0, buf.length); }
public BytePipe(int bufferSize) { if (bufferSize <= 0) { throw new IllegalArgumentException("bufferSize must be > 0"); } this.lock = new ReentrantLock(); this.writeSignal = this.lock.newCondition(); this.readSignal = this.lock.newCondition(); this.buffer = new ByteRingBuffer(bufferSize); this.outputClosed = new AtomicBoolean(false); this.inputClosed = new AtomicBoolean(false); this.output = new BytePipeOutputStream(); this.input = new BytePipeInputStream(); }
/** * Gets data from the ring buffer. * * @return The number of bytes read. This is guaranteed to be * <code>min(len, getUsed())</code>. */ public int get(byte[] buf, int pos, int len) { if (len < 0) { throw new IllegalArgumentException(); } int trLen1 = Math.min(len, Math.min(rBufUsed, rBufSize - rBufPos)); remove(buf, pos, trLen1); int trLen2 = Math.min(len - trLen1, rBufUsed); remove(buf, pos + trLen1, trLen2); return trLen1 + trLen2; }
/** * Puts data to the ring buffer. * * @param buf * @param pos * @param len * @return The number of bytes written. This is guaranteed to be * <code>min(len, getFree())</code>. */ public int put(byte[] buf, int pos, int len) { if (len < 0) { throw new IllegalArgumentException(); } if (rBufUsed == 0) { rBufPos = 0; } // (speed optimization) int p1 = rBufPos + rBufUsed; if (p1 < rBufSize) { // free space in two pieces int trLen1 = Math.min(len, rBufSize - p1); append(buf, pos, trLen1); int trLen2 = Math.min(len - trLen1, rBufPos); append(buf, pos + trLen1, trLen2); return trLen1 + trLen2; } else { // free space in one piece int trLen = Math.min(len, rBufSize - rBufUsed); append(buf, pos, trLen); return trLen; } }
/** * Resizes the ring buffer by preserving it's data. * * <p> * If the new size is not enough to keep all used data in the ring buffer, * the excess old data is discarded. */ public void resize(int newSize) { if (newSize <= 0) { throw new IllegalArgumentException(); } if (newSize < rBufUsed) { // if new buffer is too small to contain all data discard(rBufUsed - newSize); } // discard oldest data byte[] newBuf = new byte[newSize]; int newBufUsed = get(newBuf, 0, newSize); // transfer data to new buffer rBuf = newBuf; rBufSize = newSize; rBufPos = 0; rBufUsed = newBufUsed; }
private void remove(byte[] buf, int pos, int len) { if (len == 0) { return; } if (len < 0) { throw new AssertionError(); } System.arraycopy(rBuf, rBufPos, buf, pos, len); rBufPos = clip(rBufPos + len); rBufUsed -= len; }
@Override public int available() throws IOException { lock.lock(); try { return buffer.getUsed(); } finally { lock.unlock(); } }