1 package SQLite;
2 
3 import java.io.*;
4 
5 /**
6  * Internal class implementing java.io.InputStream on
7  * SQLite 3.4.0 incremental blob I/O interface.
8  */
9 
10 class BlobR extends InputStream {
11 
12     /**
13      * Blob instance
14      */
15 
16     private Blob blob;
17 
18     /**
19      * Read position, file pointer.
20      */
21 
22     private int pos;
23 
24     /**
25      * Contruct InputStream from blob instance.
26      */
27 
BlobR(Blob blob)28     BlobR(Blob blob) {
29 	this.blob = blob;
30 	this.pos = 0;
31     }
32 
33     /**
34      * Return number of available bytes for reading.
35      * @return available input bytes
36      */
37 
available()38     public int available() throws IOException {
39 	int ret = blob.size - pos;
40 	return (ret < 0) ? 0 : ret;
41     }
42 
43     /**
44      * Mark method; dummy to satisfy InputStream class.
45      */
46 
mark(int limit)47     public void mark(int limit) {
48     }
49 
50     /**
51      * Reset method; dummy to satisfy InputStream class.
52      */
53 
reset()54     public void reset() throws IOException {
55     }
56 
57     /**
58      * Mark support; not for this class.
59      * @return always false
60      */
61 
markSupported()62     public boolean markSupported() {
63 	return false;
64     }
65 
66     /**
67      * Close this blob InputStream.
68      */
69 
close()70     public void close() throws IOException {
71         blob.close();
72 	blob = null;
73 	pos = 0;
74     }
75 
76     /**
77      * Skip over blob data.
78      */
79 
skip(long n)80     public long skip(long n) throws IOException {
81 	long ret = pos + n;
82 	if (ret < 0) {
83 	    ret = 0;
84 	    pos = 0;
85 	} else if (ret > blob.size) {
86 	    ret = blob.size;
87 	    pos = blob.size;
88 	} else {
89 	    pos = (int) ret;
90 	}
91 	return ret;
92     }
93 
94     /**
95      * Read single byte from blob.
96      * @return byte read
97      */
98 
read()99     public int read() throws IOException {
100 	byte b[] = new byte[1];
101 	int n = blob.read(b, 0, pos, b.length);
102 	if (n > 0) {
103 	    pos += n;
104 	    return b[0];
105 	}
106 	return -1;
107     }
108 
109     /**
110      * Read byte array from blob.
111      * @param b byte array to be filled
112      * @return number of bytes read
113      */
114 
read(byte b[])115     public int read(byte b[]) throws IOException {
116 	int n = blob.read(b, 0, pos, b.length);
117 	if (n > 0) {
118 	    pos += n;
119 	    return n;
120 	}
121 	return -1;
122     }
123 
124     /**
125      * Read slice of byte array from blob.
126      * @param b byte array to be filled
127      * @param off offset into byte array
128      * @param len length to be read
129      * @return number of bytes read
130      */
131 
read(byte b[], int off, int len)132     public int read(byte b[], int off, int len) throws IOException {
133 	if (off + len > b.length) {
134 	    len = b.length - off;
135 	}
136 	if (len < 0) {
137 	    return -1;
138 	}
139 	if (len == 0) {
140 	    return 0;
141 	}
142 	int n = blob.read(b, off, pos, len);
143 	if (n > 0) {
144 	    pos += n;
145 	    return n;
146 	}
147 	return -1;
148     }
149 }
150 
151 /**
152  * Internal class implementing java.io.OutputStream on
153  * SQLite 3.4.0 incremental blob I/O interface.
154  */
155 
156 class BlobW extends OutputStream {
157 
158     /**
159      * Blob instance
160      */
161 
162     private Blob blob;
163 
164     /**
165      * Read position, file pointer.
166      */
167 
168     private int pos;
169 
170     /**
171      * Contruct OutputStream from blob instance.
172      */
173 
BlobW(Blob blob)174     BlobW(Blob blob) {
175 	this.blob = blob;
176 	this.pos = 0;
177     }
178 
179     /**
180      * Flush blob; dummy to satisfy OutputStream class.
181      */
182 
flush()183     public void flush() throws IOException {
184     }
185 
186     /**
187      * Close this blob OutputStream.
188      */
189 
close()190     public void close() throws IOException {
191         blob.close();
192 	blob = null;
193 	pos = 0;
194     }
195 
196     /**
197      * Write blob data.
198      * @param v byte to be written at current position.
199      */
200 
write(int v)201     public void write(int v) throws IOException {
202 	byte b[] = new byte[1];
203 	b[0] = (byte) v;
204 	pos += blob.write(b, 0, pos, 1);
205     }
206 
207     /**
208      * Write blob data.
209      * @param b byte array to be written at current position.
210      */
211 
write(byte[] b)212     public void write(byte[] b) throws IOException {
213 	if (b != null && b.length > 0) {
214 	    pos += blob.write(b, 0, pos, b.length);
215 	}
216     }
217 
218     /**
219      * Write blob data.
220      * @param b byte array to be written.
221      * @param off offset within byte array
222      * @param len length of data to be written
223      */
224 
write(byte[] b, int off, int len)225     public void write(byte[] b, int off, int len) throws IOException {
226 	if (b != null) {
227 	    if (off + len > b.length) {
228 		len = b.length - off;
229 	    }
230 	    if (len <= 0) {
231 		return;
232 	    }
233 	    pos += blob.write(b, off, pos, len);
234 	}
235     }
236 }
237 
238 /**
239  * Class to represent SQLite3 3.4.0 incremental blob I/O interface.
240  *
241  * Note, that all native methods of this class are
242  * not synchronized, i.e. it is up to the caller
243  * to ensure that only one thread is in these
244  * methods at any one time.
245  */
246 
247 public class Blob {
248 
249     /**
250      * Internal handle for the SQLite3 blob.
251      */
252 
253     private long handle = 0;
254 
255     /**
256      * Cached size of blob, setup right after blob
257      * has been opened.
258      */
259 
260     protected int size = 0;
261 
262     /**
263      * Return InputStream for this blob
264      * @return InputStream
265      */
266 
getInputStream()267     public InputStream getInputStream() {
268 	return (InputStream) new BlobR(this);
269     }
270 
271     /**
272      * Return OutputStream for this blob
273      * @return OutputStream
274      */
275 
getOutputStream()276     public OutputStream getOutputStream() {
277 	return (OutputStream) new BlobW(this);
278     }
279 
280     /**
281      * Close blob.
282      */
283 
close()284     public native void close();
285 
286     /**
287      * Internal blob write method.
288      * @param b byte array to be written
289      * @param off offset into byte array
290      * @param pos offset into blob
291      * @param len length to be written
292      * @return number of bytes written to blob
293      */
294 
write(byte[] b, int off, int pos, int len)295     native int write(byte[] b, int off, int pos, int len) throws IOException;
296 
297     /**
298      * Internal blob read method.
299      * @param b byte array to be written
300      * @param off offset into byte array
301      * @param pos offset into blob
302      * @param len length to be written
303      * @return number of bytes written to blob
304      */
305 
read(byte[] b, int off, int pos, int len)306     native int read(byte[] b, int off, int pos, int len) throws IOException;
307 
308     /**
309      * Destructor for object.
310      */
311 
finalize()312     protected native void finalize();
313 
314     /**
315      * Internal native initializer.
316      */
317 
internal_init()318     private static native void internal_init();
319 
320     static {
internal_init()321 	internal_init();
322     }
323 }
324