/*
* Copyright (C) 2007 Steve Ratcliffe
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*
* Author: Steve Ratcliffe
* Create date: 23-Sep-2007
*/
package uk.me.parabola.io;
import java.io.IOException;
import java.io.InputStream;
/**
* An input stream used to make reading little endian integers and strings from
* the tdb file.
*
* @author Steve Ratcliffe
*/
public class StructuredInputStream extends InputStream {
private final InputStream in;
private boolean eof;
public StructuredInputStream(InputStream in) {
this.in = in;
}
/**
* Implementation of read that delegates to the underlying stream. It however
* also keeps track of the end of file status.
*
* @return The next byte, or -1 on eof.
* @throws IOException For problems reading.
*/
public int read() throws IOException {
int r = in.read();
if (r == -1)
eof = true;
return r;
}
/**
* Read a 2 byte little endian integer.
*
* @return The integer.
* @throws IOException If the stream could not be read.
*/
public int read2() throws IOException {
int a = read() & 0xff;
int b = read() & 0xff;
if (isEof())
throw new EndOfFileException();
return (b << 8) + a;
}
/**
* Read a 4 byte integer quantity. As always this is little endian.
*
* @return The integer.
* @throws IOException If the stream could not be read.
*/
public int read4() throws IOException {
int a = read() & 0xff;
int b = read() & 0xff;
int c = read() & 0xff;
int d = read() & 0xff;
return (d << 24) | (c << 16) | (b << 8) | a;
}
/**
* Read a nul terminated string from the input stream.
*
* @return A string, without the null terminator.
* @throws IOException If the stream cannot be read.
*/
public String readString() throws IOException {
StringBuffer name = new StringBuffer();
int b;
while ((b = read()) != '\0' && b != -1) {
name.append((char) (b & 0xff));
}
return name.toString();
}
boolean isEof() {
return eof;
}
/**
* Test if we are at the end of the file by marking the position and trying
* to read the next byte. If not at the end then the stream position is
* reset and all is as before.
*
* @return True if we are at the end of the stream.
*/
public boolean testEof() {
assert in.markSupported();
in.mark(1);
try {
int b = in.read();
if (b == -1) {
eof = true;
} else {
in.reset();
}
return isEof();
} catch (IOException e) {
return true;
}
}
}