package se.lth.control.labcomm2006; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.InputStream; import java.io.IOException; public class DecoderChannel implements Decoder { private DataInputStream in; private DecoderRegistry registry; public DecoderChannel(InputStream in) throws IOException { this.in = new DataInputStream(in); registry = new DecoderRegistry(); } public void runOne() throws Exception { boolean done = false; while (!done) { int tag = decodePacked32(); switch (tag) { case Constant.SAMPLE: { int index = decodePacked32(); String name = decodeString(); ByteArrayOutputStream signature = new ByteArrayOutputStream(); collectFlatSignature(new EncoderChannel(signature)); registry.add(index, name, signature.toByteArray()); } break; default: { DecoderRegistry.Entry e = 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() +"'"); } d.decodeAndHandle(this, h); done = true; } } } } public void run() throws Exception { while (true) { runOne(); } } private void collectFlatSignature(Encoder out) throws IOException { int type = decodePacked32(); out.encodePacked32(type); switch (type) { case Constant.ARRAY: { int dimensions = decodePacked32(); out.encodePacked32(dimensions); for (int i = 0 ; i < dimensions ; i++) { out.encodePacked32(decodePacked32()); } collectFlatSignature(out); } break; case Constant.STRUCT: { int fields = decodePacked32(); out.encodePacked32(fields); for (int i = 0 ; i < fields ; i++) { out.encodeString(decodeString()); collectFlatSignature(out); } } break; case Constant.BOOLEAN: case Constant.BYTE: case Constant.SHORT: case Constant.INT: case Constant.LONG: case Constant.FLOAT: case Constant.DOUBLE: case Constant.STRING: { } break; default: { throw new IOException("Unimplemented type=" + type); } } out.end(null); } public void register(SampleDispatcher dispatcher, SampleHandler handler) throws IOException { registry.add(dispatcher, handler); } 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); } /** method for API harmonization with labcomm2014. Labcomm2006 encodes lengths etc as 32 bit ints. */ public int decodePacked32() throws IOException { return in.readInt(); } }