// This file is part of PleoCommand: // Interactively control Pleo with psychobiological parameters // // Copyright (C) 2010 Oliver Hoffmann - Hoffmann_Oliver@gmx.de // // This program 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; either version 2 // of the License, or (at your option) any later version. // // This program 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 this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Boston, USA. package pleocmd.itfc.gui.dse; import java.io.DataInput; import java.io.DataInputStream; import java.io.DataOutput; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; public final class RandomAccessArray implements RandomAccess { private byte[] ba; private int pos; private int length; private final DataInput dataIn; private final DataOutput dataOut; public RandomAccessArray(final InputStream in, final long length) throws IOException { if (length < 0 || length > Integer.MAX_VALUE) throw new IOException("Invalid length: " + length); this.length = (int) length; ba = new byte[this.length]; if (this.length > 0 && in.read(ba) != this.length) throw new IOException("Failed to read from InputStream"); dataIn = new DataInputStream(new InputStream() { @Override public int read() throws IOException { return RandomAccessArray.this.read(); } }); dataOut = new DataOutputStream(new OutputStream() { @Override public void write(final int b) throws IOException { RandomAccessArray.this.write(b); } }); } @Override public long length() { return length; } @Override public long getFilePointer() { return pos; } @Override public void seek(final long newPos) throws IOException { if (newPos < 0 || newPos > Integer.MAX_VALUE) throw new IOException("Invalid position: " + newPos); pos = (int) newPos; } @Override public void close() { // do nothing } @Override public int read() throws IOException { if (pos < 0 || pos >= length) throw new IOException("Invalid position: " + pos); return ba[pos++] & 0xFF; } @Override public void write(final int b) throws IOException { if (pos < 0) throw new IOException("Invalid position: " + pos); if (pos < length) ba[pos++] = (byte) b; else { if (pos >= ba.length) { // make about 33% larger than needed // but at least 100 bytes on small arrays final int cap = (int) ((pos + 100) * 1.333); final byte[] newba = new byte[cap]; // we only need to keep the valid bytes System.arraycopy(ba, 0, newba, 0, length); ba = newba; } // fill the grown area with zeroes for (int i = length; i < pos; ++i) ba[i] = 0; // finally set the new byte and length of file ba[pos++] = (byte) b; length = pos; } } @Override public DataInput getDataInput() { return dataIn; } @Override public DataOutput getDataOutput() { return dataOut; } }