-
Sven Gestegård Robertz authoredSven Gestegård Robertz authored
DecoderChannel.java 6.45 KiB
package se.lth.control.labcomm2014;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.EOFException;
public class DecoderChannel implements Decoder {
private DataInputStream in;
private DecoderRegistry def_registry = new DecoderRegistry();
private DecoderRegistry ref_registry = new DecoderRegistry();
public DecoderChannel(InputStream in) throws IOException {
this.in = new DataInputStream(in);
}
private byte[] decodeBytes() throws IOException {
int len = decodePacked32();
byte result[] = new byte[len];
for(int i=0; i<len; i++) {
result[i] = decodeByte();
}
return result;
}
private String decodeIntentions() throws IOException {
int numIntentions = decodePacked32();
String name = "";
for(int i = 0; i<numIntentions; i++) {
byte key[] = decodeBytes();
byte val[] = decodeBytes();
if(key.length == 0) {
name = new String(val);
}
}
return name;
}
private void processSampleDef() throws IOException {
int index = decodePacked32();
String name = decodeIntentions();
int signature_length = decodePacked32();
byte[] signature = new byte[signature_length];
ReadBytes(signature, signature_length);
def_registry.add(index, name, signature);
}
private void processSampleRef() throws IOException {
int index = decodePacked32();
String name = decodeIntentions();
int signature_length = decodePacked32();
byte[] signature = new byte[signature_length];
ReadBytes(signature, signature_length);
ref_registry.add(index, name, signature);
}
private void processTypeDef(int len) throws IOException {
try {
processSample(Constant.TYPE_DEF);
} catch(Exception ex) {
int idx = decodePacked32();
String name = decodeIntentions();
int siglen = decodePacked32();
for(int i=0; i<siglen; i++) {
byte b = decodeByte();
}
}
}
private void processTypeBinding(int len) throws IOException {
try {
processSample(Constant.TYPE_BINDING);
} catch(Exception ex) {
for(int i=0; i<len; i++) {
decodeByte();
}
}
}
private void processPragma(int len) throws IOException {
for(int i=0; i<len; i++) {
decodeByte();
}
}
private void processSample(int tag) throws IOException {
DecoderRegistry.Entry e = def_registry.get(tag);
if (e == null) {
throw new IOException("Unhandled tag " + tag);
}
SampleDispatcher d = e.getDispatcher();
if (d == null) {
throw new IOException("No dispatcher for '" + e.getName() + "'");
}
SampleHandler h = e.getHandler();
if (h == null) {
throw new IOException("No handler for '" + e.getName() +"'");
}
try {
//XXX why does decodeAndHandle throw Exception and not IOException?
d.decodeAndHandle(this, h);
} catch (IOException ex) {
throw ex;
} catch (Exception ex) {
ex.printStackTrace();
}
}
public void runOne() throws Exception {
boolean done = false;
while (!done) {
int tag = decodePacked32();
int length = decodePacked32();
switch (tag) {
case Constant.VERSION: {
String version = decodeString();
if (! version.equals(Constant.CURRENT_VERSION)) {
throw new IOException("LabComm version mismatch " +
version + " != " + Constant.CURRENT_VERSION);
}
} break;
case Constant.SAMPLE_DEF: {
processSampleDef();
} break;
case Constant.SAMPLE_REF: {
processSampleRef();
} break;
case Constant.TYPE_DEF: {
processTypeDef(length);
} break;
case Constant.TYPE_BINDING: {
processTypeBinding(length);
} break;
case Constant.PRAGMA: {
processPragma(length);
} break;
default: {
processSample(tag);
done = true;
}
}
}
}
public void run() throws Exception {
while (true) {
runOne();
}
}
public void register(SampleDispatcher dispatcher,
SampleHandler handler) throws IOException {
def_registry.add(dispatcher, handler);
}
public void registerSampleRef(SampleDispatcher dispatcher) throws IOException {
ref_registry.add(dispatcher, null);
}
private void ReadBytes(byte[] result, int length) throws IOException {
int offset = 0;
while (offset < length) {
int count = in.read(result, offset, length - offset);
if (count <= 0) {
throw new EOFException(
"End of stream reached with " +
(length - offset) + " bytes left to read");
}
offset += count;
}
}
public boolean decodeBoolean() throws IOException {
return in.readBoolean();
}
public byte decodeByte() throws IOException {
return in.readByte();
}
public short decodeShort() throws IOException {
return in.readShort();
}
public int decodeInt() throws IOException {
return in.readInt();
}
public long decodeLong() throws IOException {
return in.readLong();
}
public float decodeFloat() throws IOException {
return in.readFloat();
}
public double decodeDouble() throws IOException {
return in.readDouble();
}
public String decodeString() throws IOException {
//in.readShort(); // HACK
//return in.readUTF();
int len = decodePacked32() & 0xffffffff;
byte[] chars = new byte[len];
for(int i=0; i<len; i++) {
chars[i] = in.readByte();
}
return new String(chars);
}
public int decodePacked32() throws IOException {
long res=0;
byte i=0;
boolean cont=true;
do {
byte c = in.readByte();
res = (res << 7) | (c & 0x7f);
cont = (c & 0x80) != 0;
i++;
} while(cont);
return (int) (res & 0xffffffff);
}
public Class decodeSampleRef() throws IOException {
int index = in.readInt();
try {
DecoderRegistry.Entry e = ref_registry.get(index);
return e.getDispatcher().getSampleClass();
} catch (NullPointerException e) {
return null;
}
}
/* Package visible methods for use from TypeDefParser */
String getSampleName(int idx) {
DecoderRegistry.Entry e = def_registry.get(idx);
return e.getName();
}
byte[] getSampleSignature(int idx) {
DecoderRegistry.Entry e = def_registry.get(idx);
return e.getSignature();
}
}