/*
* Copyright 2004 - 2008 Christian Sprajc, Dennis Waldherr. All rights reserved.
*
* This file is part of PowerFolder.
*
* PowerFolder is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation.
*
* PowerFolder 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 for more details.
*
* You should have received a copy of the GNU General Public License
* along with PowerFolder. If not, see <http://www.gnu.org/licenses/>.
*
* $Id$
*/
package de.dal33t.powerfolder.util;
import java.nio.BufferOverflowException;
import java.nio.BufferUnderflowException;
/**
* Implementation of a ringbuffer.
* This class represents a ringbuffer of bytes. It's not using a generic type due to
* performance reasons.
*
* @author Dennis "Dante" Waldherr
* @version $Revision: $
*/
public final class RingBuffer {
private final byte[] data;
private int rpos, wlen;
public RingBuffer(int size) {
data = new byte[size];
}
/**
* Writes the given byte to the buffer.
* @param b the value (only the byte part will be used)
*/
public void write(int b) {
if (wlen >= data.length) {
throw new BufferOverflowException();
}
data[(rpos + wlen) % data.length] = (byte) b;
wlen++;
}
/**
* Writes from the given array of bytes to the buffer.
* @param b the array
* @param ofs the offset in the array to start from
* @param len the number of bytes to write
*/
public void write(byte[] b, int ofs, int len) {
if (len + wlen > data.length) {
throw new BufferOverflowException();
}
while (len > 0) {
int wpos = (rpos + wlen) % data.length;
int rem = Math.min(data.length - wpos, len);
System.arraycopy(b, ofs, data, wpos, rem);
ofs += rem;
wlen += rem;
len -= rem;
}
}
/**
* Writes the values of the given array into the buffer.
* Same as write(b, 0, b.length);
* @param b
*/
public void write(byte[] b) {
write(b, 0, b.length);
}
/**
* Reads one byte from the buffer.
* @return
*/
public int read() {
if (wlen <= 0) {
throw new BufferUnderflowException();
}
final int val = data[rpos] & 0xff;
rpos = (rpos + 1) % data.length;
wlen--;
return val;
}
/**
* Skips the given amount of bytes
* @param n
*/
public void skip(int n) {
if (n > wlen) {
throw new BufferUnderflowException();
}
rpos = (rpos + n) % data.length;
wlen -= n;
}
/**
* Reads one byte from the buffer without removing it.
* @return
*/
public int peek() {
if (wlen <= 0) {
throw new BufferUnderflowException();
}
return data[rpos] & 0xff;
}
/**
* Reads values from the buffer into an array.
* @param target the array to store into
* @param ofs the start of the storge in the array
* @param len the number of bytes to read
*/
public void read(byte[] target, int ofs, int len) {
if (len > wlen) {
throw new BufferUnderflowException();
}
while (len > 0) {
int wpos = (rpos + wlen) % data.length;
int rem = Math.min(data.length - wpos, len);
System.arraycopy(data, wpos, target, ofs, rem);
ofs += rem;
wlen -= rem;
rpos = (rpos + rem) % data.length;
len -= rem;
}
}
/**
* Reads values from the buffer into an array, without removing them from the buffer.
* @param target
* @param ofs
* @param len
*/
public void peek(byte[] target, int ofs, int len) {
if (len > wlen) {
throw new BufferUnderflowException();
}
int wpos = rpos;
while (len > 0) {
int rem = Math.min(data.length - wpos, len);
System.arraycopy(data, wpos, target, ofs, rem);
ofs += rem;
len -= rem;
wpos = (wpos + rem) % data.length;
}
}
/**
* @return the number of bytes stored in the buffer.
*/
public int available() {
return wlen;
}
/**
* @return the remaining space in number of bytes.
*/
public int remaining() {
return data.length - wlen;
}
/**
* @return the size of the buffer.
*/
public int size() {
return data.length;
}
/**
* Resets the buffer.
* After this call, the buffer is empty and available() == 0.
*/
public void reset() {
rpos = 0;
wlen = 0;
}
}