X-Git-Url: http://git.megacz.com/?p=nestedvm.git;a=blobdiff_plain;f=src%2Forg%2Fibex%2Fnestedvm%2Futil%2FSeekable.java;fp=src%2Forg%2Fibex%2Fnestedvm%2Futil%2FSeekable.java;h=85a48cc0d4cac58bcd2bc86e739c8473ed0bd00c;hp=0000000000000000000000000000000000000000;hb=c2b2704764af1ade923ba8f15d517b87f9d16189;hpb=90f1aff73ed698ab5992fbd7eb53c1ba7329b1a5 diff --git a/src/org/ibex/nestedvm/util/Seekable.java b/src/org/ibex/nestedvm/util/Seekable.java new file mode 100644 index 0000000..85a48cc --- /dev/null +++ b/src/org/ibex/nestedvm/util/Seekable.java @@ -0,0 +1,113 @@ +package org.ibex.nestedvm.util; + +import java.io.*; + +public interface Seekable { + public int read(byte[] buf, int offset, int length) throws IOException; + public int write(byte[] buf, int offset, int length) throws IOException; + public int length() throws IOException; + public void seek(int pos) throws IOException; + public void close() throws IOException; + public int pos() throws IOException; + + public class ByteArray implements Seekable { + protected byte[] data; + protected int pos; + private final boolean writable; + + public ByteArray(byte[] data, boolean writable) { + this.data = data; + this.pos = 0; + this.writable = writable; + } + + public int read(byte[] buf, int off, int len) { + len = Math.min(len,data.length-pos); + if(len <= 0) return -1; + System.arraycopy(data,pos,buf,off,len); + pos += len; + return len; + } + + public int write(byte[] buf, int off, int len) throws IOException { + if(!writable) throw new IOException("read-only data"); + len = Math.min(len,data.length-pos); + if(len <= 0) throw new IOException("no space"); + System.arraycopy(buf,off,data,pos,len); + pos += len; + return len; + } + + public int length() { return data.length; } + public int pos() { return pos; } + public void seek(int pos) { this.pos = pos; } + public void close() { /*noop*/ } + } + + public class File implements Seekable { + private final RandomAccessFile raf; + + public File(String fileName) throws IOException { this(fileName,false); } + public File(String fileName, boolean writable) throws IOException { this(new java.io.File(fileName),writable); } + + public File(java.io.File file, boolean writable) throws IOException { + raf = new RandomAccessFile(file,writable ? "rw" : "r"); + } + + // NOTE: RandomAccessFile.setLength() is a Java2 function + public void setLength(int n) throws IOException { raf.setLength(n); } + + public int read(byte[] buf, int offset, int length) throws IOException { return raf.read(buf,offset,length); } + public int write(byte[] buf, int offset, int length) throws IOException { raf.write(buf,offset,length); return length; } + public void seek(int pos) throws IOException{ raf.seek(pos); } + public int pos() throws IOException { return (int) raf.getFilePointer(); } + public int length() throws IOException { return (int)raf.length(); } + public void close() throws IOException { raf.close(); } + } + + public class InputStream implements Seekable { + private byte[] buffer = new byte[4096]; + private int bytesRead = 0; + private boolean eof = false; + private int pos; + private java.io.InputStream is; + + public InputStream(java.io.InputStream is) { this.is = is; } + + public int read(byte[] outbuf, int off, int len) throws IOException { + if(pos >= bytesRead && !eof) readTo(pos + 1); + len = Math.min(len,bytesRead-pos); + if(len <= 0) return -1; + System.arraycopy(buffer,pos,outbuf,off,len); + pos += len; + return len; + } + + private void readTo(int target) throws IOException { + if(target >= buffer.length) { + byte[] buf2 = new byte[Math.max(buffer.length+Math.min(buffer.length,65536),target)]; + System.arraycopy(buffer,0,buf2,0,bytesRead); + buffer = buf2; + } + while(bytesRead < target) { + int n = is.read(buffer,bytesRead,buffer.length-bytesRead); + if(n == -1) { + eof = true; + break; + } + bytesRead += n; + } + } + + public int length() throws IOException { + while(!eof) readTo(bytesRead+4096); + return bytesRead; + } + + public int write(byte[] buf, int off, int len) throws IOException { throw new IOException("read-only"); } + public void seek(int pos) { this.pos = pos; } + public int pos() { return pos; } + public void close() throws IOException { is.close(); } + } + +}