98f2c8e413dc0bebf6eeb53f9db205d2d4135472
[nestedvm.git] / src / org / ibex / nestedvm / util / Seekable.java
1 package org.ibex.nestedvm.util;
2
3 import java.io.*;
4
5 public abstract class Seekable { 
6     public abstract int read(byte[] buf, int offset, int length) throws IOException;
7     public abstract int write(byte[] buf, int offset, int length) throws IOException;
8     public abstract int length() throws IOException;
9     public abstract void seek(int pos) throws IOException;
10     public abstract void close() throws IOException;
11     public abstract int pos() throws IOException;
12     
13     public int read() throws IOException {
14         byte[] buf = new byte[1];
15         int n = read(buf,0,1);
16         return n == -1 ? -1 : buf[0]&0xff;
17     }
18     
19     public static class ByteArray extends Seekable {
20         protected byte[] data;
21         protected int pos;
22         private final boolean writable;
23         
24         public ByteArray(byte[] data, boolean writable) {
25             this.data = data;
26             this.pos = 0;
27             this.writable = writable;
28         }
29         
30         public int read(byte[] buf, int off, int len) {
31             len = Math.min(len,data.length-pos);
32             if(len <= 0) return -1;
33             System.arraycopy(data,pos,buf,off,len);
34             pos += len;
35             return len;
36         }
37                 
38         public int write(byte[] buf, int off, int len) throws IOException {
39             if(!writable) throw new IOException("read-only data");
40             len = Math.min(len,data.length-pos);
41             if(len <= 0) throw new IOException("no space");
42             System.arraycopy(buf,off,data,pos,len);        
43             pos += len;
44             return len;
45         }
46         
47         public int length() { return data.length; }
48         public int pos() { return pos; }
49         public void seek(int pos) { this.pos = pos; }
50         public void close() { /*noop*/ }
51     }
52     
53     public static class File extends Seekable {
54         private final RandomAccessFile raf;
55         
56         public File(String fileName) throws IOException { this(fileName,false); }
57         public File(String fileName, boolean writable) throws IOException { this(new java.io.File(fileName),writable); }    
58         
59         public File(java.io.File file, boolean writable) throws IOException {
60             raf = new RandomAccessFile(file,writable ? "rw" : "r");
61         }
62         
63         // NOTE: RandomAccessFile.setLength() is a Java2 function
64         public void setLength(int n) throws IOException { raf.setLength(n); }
65         
66         public int read(byte[] buf, int offset, int length) throws IOException { return raf.read(buf,offset,length); }
67         public int write(byte[] buf, int offset, int length) throws IOException { raf.write(buf,offset,length); return length; }
68         public void seek(int pos) throws IOException{ raf.seek(pos); }
69         public int pos()  throws IOException { return (int) raf.getFilePointer(); }
70         public int length() throws IOException { return (int)raf.length(); }
71         public void close() throws IOException { raf.close(); }
72     }
73     
74     public static class InputStream extends Seekable {
75         private byte[] buffer = new byte[4096];
76         private int bytesRead = 0;
77         private boolean eof = false;
78         private int pos;
79         private java.io.InputStream is;
80         
81         public InputStream(java.io.InputStream is) { this.is = is; }
82         
83         public int read(byte[] outbuf, int off, int len) throws IOException {
84             if(pos >= bytesRead && !eof) readTo(pos + 1);
85             len = Math.min(len,bytesRead-pos);
86             if(len <= 0) return -1;
87             System.arraycopy(buffer,pos,outbuf,off,len);
88             pos += len;
89             return len;
90         }
91         
92         private void readTo(int target) throws IOException {
93             if(target >= buffer.length) {
94                 byte[] buf2 = new byte[Math.max(buffer.length+Math.min(buffer.length,65536),target)];
95                 System.arraycopy(buffer,0,buf2,0,bytesRead);
96                 buffer = buf2;
97             }
98             while(bytesRead < target) {
99                 int n = is.read(buffer,bytesRead,buffer.length-bytesRead);
100                 if(n == -1) {
101                     eof = true;
102                     break;
103                 }
104                 bytesRead += n;
105             }
106         }
107         
108         public int length() throws IOException {
109             while(!eof) readTo(bytesRead+4096);
110             return bytesRead;
111         }
112         
113         public int write(byte[] buf, int off, int len) throws IOException { throw new IOException("read-only"); }
114         public void seek(int pos) { this.pos = pos; }
115         public int pos() { return pos; }
116         public void close() throws IOException { is.close(); }
117     }
118     
119 }