org.xwt.mips -> org.ibex.nestedvm
[nestedvm.git] / src / org / ibex / nestedvm / util / Seekable.java
diff --git a/src/org/ibex/nestedvm/util/Seekable.java b/src/org/ibex/nestedvm/util/Seekable.java
new file mode 100644 (file)
index 0000000..85a48cc
--- /dev/null
@@ -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(); }
+    }
+    
+}