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