package freenet.support.io;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.util.Arrays;
import freenet.client.async.ClientContext;
import freenet.support.api.LockableRandomAccessBuffer;
public class ByteArrayRandomAccessBuffer implements LockableRandomAccessBuffer, Serializable {
private static final long serialVersionUID = 1L;
private final byte[] data;
private boolean readOnly;
private boolean closed;
public ByteArrayRandomAccessBuffer(byte[] padded) {
this.data = padded;
}
public ByteArrayRandomAccessBuffer(int size) {
this.data = new byte[size];
}
public ByteArrayRandomAccessBuffer(byte[] initialContents, int offset, int size, boolean readOnly) {
data = Arrays.copyOfRange(initialContents, offset, offset+size);
this.readOnly = readOnly;
}
protected ByteArrayRandomAccessBuffer() {
// For serialization.
data = null;
}
@Override
public void close() {
closed = true;
}
@Override
public synchronized void pread(long fileOffset, byte[] buf, int bufOffset, int length)
throws IOException {
if(closed) throw new IOException("Closed");
if(fileOffset < 0) throw new IllegalArgumentException("Cannot read before zero");
if(fileOffset + length > data.length) throw new IOException("Cannot read after end: trying to read from "+fileOffset+" to "+(fileOffset+length)+" on block length "+data.length);
System.arraycopy(data, (int)fileOffset, buf, bufOffset, length);
}
@Override
public synchronized void pwrite(long fileOffset, byte[] buf, int bufOffset, int length)
throws IOException {
if(closed) throw new IOException("Closed");
if(fileOffset < 0) throw new IllegalArgumentException("Cannot write before zero");
if(fileOffset + length > data.length) throw new IOException("Cannot write after end: trying to write from "+fileOffset+" to "+(fileOffset+length)+" on block length "+data.length);
if(readOnly) throw new IOException("Read-only");
System.arraycopy(buf, bufOffset, data, (int)fileOffset, length);
}
@Override
public long size() {
return data.length;
}
public synchronized void setReadOnly() {
readOnly = true;
}
public synchronized boolean isReadOnly() {
return readOnly;
}
@Override
public RAFLock lockOpen() {
return new RAFLock() {
@Override
protected void innerUnlock() {
// Do nothing. Always open.
}
};
}
@Override
public void free() {
// Do nothing.
}
/** Package-local! */
byte[] getBuffer() {
return data;
}
@Override
public void onResume(ClientContext context) {
// Do nothing.
}
@Override
public void storeTo(DataOutputStream dos) {
throw new UnsupportedOperationException();
}
// Default hashCode() and equals() are correct for this type.
}