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