package SQLite;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
* Internal class implementing java.io.InputStream on
* SQLite 3.4.0 incremental blob I/O interface.
*/
class BlobR extends InputStream {
/**
* Blob instance
*/
private Blob blob;
/**
* Read position, file pointer.
*/
private int pos;
/**
* Contruct InputStream from blob instance.
*
* @param blob blob to make input stream from
*/
BlobR(Blob blob) {
this.blob = blob;
this.pos = 0;
}
/**
* Return number of available bytes for reading.
*
* @return available input bytes
* @throws IOException on I/O error
*/
public int available() throws IOException {
int ret = blob.size - pos;
return (ret < 0) ? 0 : ret;
}
/**
* Mark method; dummy to satisfy InputStream class.
*/
public void mark(int limit) {
}
/**
* Reset method; dummy to satisfy InputStream class.
*
* @throws IOException on I/O error
*/
public void reset() throws IOException {
}
/**
* Mark support; not for this class.
*
* @return always false
*/
public boolean markSupported() {
return false;
}
/**
* Close this blob InputStream.
*
* @throws IOException on I/O error
*/
public void close() throws IOException {
blob.close();
blob = null;
pos = 0;
}
/**
* Skip over blob data.
*
* @param n number of bytes to skip
* @throws IOException on I/O error
*/
public long skip(long n) throws IOException {
long ret = pos + n;
if (ret < 0) {
ret = 0;
pos = 0;
} else if (ret > blob.size) {
ret = blob.size;
pos = blob.size;
} else {
pos = (int) ret;
}
return ret;
}
/**
* Read single byte from blob.
*
* @return byte read
* @throws IOException on I/O error
*/
public int read() throws IOException {
byte b[] = new byte[1];
int n = blob.read(b, 0, pos, b.length);
if (n > 0) {
pos += n;
return b[0];
}
return -1;
}
/**
* Read byte array from blob.
*
* @param b byte array to be filled
* @return number of bytes read
* @throws IOException on I/O error
*/
public int read(byte b[]) throws IOException {
int n = blob.read(b, 0, pos, b.length);
if (n > 0) {
pos += n;
return n;
}
return -1;
}
/**
* Read slice of byte array from blob.
*
* @param b byte array to be filled
* @param off offset into byte array
* @param len length to be read
* @return number of bytes read
* @throws IOException on I/O error
*/
public int read(byte b[], int off, int len) throws IOException {
if (off + len > b.length) {
len = b.length - off;
}
if (len < 0) {
return -1;
}
if (len == 0) {
return 0;
}
int n = blob.read(b, off, pos, len);
if (n > 0) {
pos += n;
return n;
}
return -1;
}
}
/**
* Internal class implementing java.io.OutputStream on
* SQLite 3.4.0 incremental blob I/O interface.
*/
class BlobW extends OutputStream {
/**
* Blob instance
*/
private Blob blob;
/**
* Read position, file pointer.
*/
private int pos;
/**
* Contruct OutputStream from blob instance.
*
* @param blob blob to make output stream from
*/
BlobW(Blob blob) {
this.blob = blob;
this.pos = 0;
}
/**
* Flush blob; dummy to satisfy OutputStream class.
*
* @throws IOException on I/O error
*/
public void flush() throws IOException {
}
/**
* Close this blob OutputStream.
*
* @throws IOException on I/O error
*/
public void close() throws IOException {
blob.close();
blob = null;
pos = 0;
}
/**
* Write blob data.
*
* @param v byte to be written at current position.
* @throws IOException on I/O error
*/
public void write(int v) throws IOException {
byte b[] = new byte[1];
b[0] = (byte) v;
pos += blob.write(b, 0, pos, 1);
}
/**
* Write blob data.
*
* @param b byte array to be written at current position.
* @throws IOException on I/O error
*/
public void write(byte[] b) throws IOException {
if (b != null && b.length > 0) {
pos += blob.write(b, 0, pos, b.length);
}
}
/**
* Write blob data.
*
* @param b byte array to be written.
* @param off offset within byte array
* @param len length of data to be written
* @throws IOException on I/O error
*/
public void write(byte[] b, int off, int len) throws IOException {
if (b != null) {
if (off + len > b.length) {
len = b.length - off;
}
if (len <= 0) {
return;
}
pos += blob.write(b, off, pos, len);
}
}
}
/**
* Class to represent SQLite3 3.4.0 incremental blob I/O interface.
*
* Note, that all native methods of this class are
* not synchronized, i.e. it is up to the caller
* to ensure that only one thread is in these
* methods at any one time.
*/
public class Blob {
/**
* Internal handle for the SQLite3 blob.
*/
private long handle = 0;
/**
* Cached size of blob, setup right after blob
* has been opened.
*/
protected int size = 0;
/**
* Return InputStream for this blob
*
* @return InputStream
*/
public InputStream getInputStream() {
return new BlobR(this);
}
/**
* Return OutputStream for this blob
*
* @return OutputStream
*/
public OutputStream getOutputStream() {
return new BlobW(this);
}
/**
* Close blob.
*/
public native void close();
/**
* Internal blob write method.
*
* @param b byte array to be written
* @param off offset into byte array
* @param pos offset into blob
* @param len length to be written
* @return number of bytes written to blob
* @throws IOException on I/O error
*/
native int write(byte[] b, int off, int pos, int len) throws IOException;
/**
* Internal blob read method.
*
* @param b byte array to be written
* @param off offset into byte array
* @param pos offset into blob
* @param len length to be written
* @return number of bytes written to blob
* @throws IOException on I/O error
*/
native int read(byte[] b, int off, int pos, int len) throws IOException;
/**
* Destructor for object.
*/
protected native void finalize();
/**
* Internal native initializer.
*/
private static native void internal_init();
static {
internal_init();
}
}