51c7a3959d8782428f055e1064ae977dd510386a
[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,false); }    
70         
71         public File(java.io.File file, boolean writable, boolean truncate) throws IOException {
72             String mode = writable ? "rw" : "r";
73             raf = truncate ? Platform.truncatedRandomAccessFile(file,mode) : new RandomAccessFile(file,mode);
74         }
75         
76         public int read(byte[] buf, int offset, int length) throws IOException { return raf.read(buf,offset,length); }
77         public int write(byte[] buf, int offset, int length) throws IOException { raf.write(buf,offset,length); return length; }
78         public void seek(int pos) throws IOException{ raf.seek(pos); }
79         public int pos()  throws IOException { return (int) raf.getFilePointer(); }
80         public int length() throws IOException { return (int)raf.length(); }
81         public void close() throws IOException { raf.close(); }
82     }
83     
84     public static class InputStream extends Seekable {
85         private byte[] buffer = new byte[4096];
86         private int bytesRead = 0;
87         private boolean eof = false;
88         private int pos;
89         private java.io.InputStream is;
90         
91         public InputStream(java.io.InputStream is) { this.is = is; }
92         
93         public int read(byte[] outbuf, int off, int len) throws IOException {
94             if(pos >= bytesRead && !eof) readTo(pos + 1);
95             len = Math.min(len,bytesRead-pos);
96             if(len <= 0) return -1;
97             System.arraycopy(buffer,pos,outbuf,off,len);
98             pos += len;
99             return len;
100         }
101         
102         private void readTo(int target) throws IOException {
103             if(target >= buffer.length) {
104                 byte[] buf2 = new byte[Math.max(buffer.length+Math.min(buffer.length,65536),target)];
105                 System.arraycopy(buffer,0,buf2,0,bytesRead);
106                 buffer = buf2;
107             }
108             while(bytesRead < target) {
109                 int n = is.read(buffer,bytesRead,buffer.length-bytesRead);
110                 if(n == -1) {
111                     eof = true;
112                     break;
113                 }
114                 bytesRead += n;
115             }
116         }
117         
118         public int length() throws IOException {
119             while(!eof) readTo(bytesRead+4096);
120             return bytesRead;
121         }
122         
123         public int write(byte[] buf, int off, int len) throws IOException { throw new IOException("read-only"); }
124         public void seek(int pos) { this.pos = pos; }
125         public int pos() { return pos; }
126         public void close() throws IOException { is.close(); }
127     }
128     
129 }