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