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