move some upstream materials from brianweb.net to nestedvm.org
[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 void sync() throws IOException {
18         throw new IOException("sync not implemented for " + getClass());
19     }
20     public void resize(long length) throws IOException {
21         throw new IOException("resize not implemented for " + getClass());
22     }
23     /** If pos == 0 and size == 0 lock covers whole file. */
24     public Lock lock(long pos, long size, boolean shared) throws IOException {
25         throw new IOException("lock not implemented for " + getClass());
26     }
27     
28     public int read() throws IOException {
29         byte[] buf = new byte[1];
30         int n = read(buf,0,1);
31         return n == -1 ? -1 : buf[0]&0xff;
32     }
33     
34     public int tryReadFully(byte[] buf, int off, int len) throws IOException {
35         int total = 0;
36         while(len > 0) {
37                 int n = read(buf,off,len);
38                 if(n == -1) break;
39                 off += n;
40                 len -= n;
41             total += n;
42         }
43         return total == 0 ? -1 : total;
44     }
45     
46     public static class ByteArray extends Seekable {
47         protected byte[] data;
48         protected int pos;
49         private final boolean writable;
50         
51         public ByteArray(byte[] data, boolean writable) {
52             this.data = data;
53             this.pos = 0;
54             this.writable = writable;
55         }
56         
57         public int read(byte[] buf, int off, int len) {
58             len = Math.min(len,data.length-pos);
59             if(len <= 0) return -1;
60             System.arraycopy(data,pos,buf,off,len);
61             pos += len;
62             return len;
63         }
64                 
65         public int write(byte[] buf, int off, int len) throws IOException {
66             if(!writable) throw new IOException("read-only data");
67             len = Math.min(len,data.length-pos);
68             if(len <= 0) throw new IOException("no space");
69             System.arraycopy(buf,off,data,pos,len);        
70             pos += len;
71             return len;
72         }
73         
74         public int length() { return data.length; }
75         public int pos() { return pos; }
76         public void seek(int pos) { this.pos = pos; }
77         public void close() { /*noop*/ }
78     }
79     
80     public static class File extends Seekable {
81         private final java.io.File file;
82         private final RandomAccessFile raf;
83         
84         public File(String fileName) throws IOException { this(fileName,false); }
85         public File(String fileName, boolean writable) throws IOException { this(new java.io.File(fileName),writable,false); }    
86         
87         public File(java.io.File file, boolean writable, boolean truncate) throws IOException {
88             this.file = file;
89             String mode = writable ? "rw" : "r";
90             raf = new RandomAccessFile(file,mode);
91             if (truncate) Platform.setFileLength(raf, 0);
92         }
93         
94         public int read(byte[] buf, int offset, int length) throws IOException { return raf.read(buf,offset,length); }
95         public int write(byte[] buf, int offset, int length) throws IOException { raf.write(buf,offset,length); return length; }
96         public void sync() throws IOException { raf.getFD().sync(); }
97         public void seek(int pos) throws IOException{ raf.seek(pos); }
98         public int pos()  throws IOException { return (int) raf.getFilePointer(); }
99         public int length() throws IOException { return (int)raf.length(); }
100         public void close() throws IOException { raf.close(); }
101         public void resize(long length) throws IOException { Platform.setFileLength(raf, (int)length); }
102         public boolean equals(Object o) {
103             return o != null && o instanceof File
104                    && file.equals(((File)o).file);
105         }
106         public Lock lock(long pos, long size, boolean shared)
107                 throws IOException {
108             return Platform.lockFile(this, raf, pos, size, shared);
109         }
110     }
111     
112     public static class InputStream extends Seekable {
113         private byte[] buffer = new byte[4096];
114         private int bytesRead = 0;
115         private boolean eof = false;
116         private int pos;
117         private java.io.InputStream is;
118         
119         public InputStream(java.io.InputStream is) { this.is = is; }
120         
121         public int read(byte[] outbuf, int off, int len) throws IOException {
122             if(pos >= bytesRead && !eof) readTo(pos + 1);
123             len = Math.min(len,bytesRead-pos);
124             if(len <= 0) return -1;
125             System.arraycopy(buffer,pos,outbuf,off,len);
126             pos += len;
127             return len;
128         }
129         
130         private void readTo(int target) throws IOException {
131             if(target >= buffer.length) {
132                 byte[] buf2 = new byte[Math.max(buffer.length+Math.min(buffer.length,65536),target)];
133                 System.arraycopy(buffer,0,buf2,0,bytesRead);
134                 buffer = buf2;
135             }
136             while(bytesRead < target) {
137                 int n = is.read(buffer,bytesRead,buffer.length-bytesRead);
138                 if(n == -1) {
139                     eof = true;
140                     break;
141                 }
142                 bytesRead += n;
143             }
144         }
145         
146         public int length() throws IOException {
147             while(!eof) readTo(bytesRead+4096);
148             return bytesRead;
149         }
150         
151         public int write(byte[] buf, int off, int len) throws IOException { throw new IOException("read-only"); }
152         public void seek(int pos) { this.pos = pos; }
153         public int pos() { return pos; }
154         public void close() throws IOException { is.close(); }
155     }
156     
157     public abstract static class Lock {
158         private Object owner = null;
159
160         public abstract Seekable seekable();
161         public abstract boolean isShared();
162         public abstract boolean isValid();
163         public abstract void release() throws IOException;
164         public abstract long position();
165         public abstract long size();
166
167         public void setOwner(Object o) { owner = o; }
168         public Object getOwner() { return owner; }
169
170         public final boolean contains(int start, int len) {
171             return start >= position() &&  position() + size() >= start + len;
172         }
173
174         public final boolean contained(int start, int len) {
175             return start < position() && position() + size() < start + len;
176         }
177
178         public final boolean overlaps(int start, int len) {
179             return contains(start, len) || contained(start, len);
180         }
181     }
182 }