Skip to content
Snippets Groups Projects
Commit 7e0a91ce authored by Sven Gestegård Robertz's avatar Sven Gestegård Robertz
Browse files

started creating labcomm2006 for legacy interfaces

parent 36753c06
Branches
Tags
No related merge requests found
Showing
with 601 additions and 0 deletions
package se.lth.control.labcomm2006;
public class LabComm {
public static final String VERSION = "LabComm2006";
/*
* Predeclared aggregate type indices
*/
public static final int TYPEDEF = 0x01;
public static final int SAMPLE = 0x02;
public static final int ARRAY = 0x10;
public static final int STRUCT = 0x11;
/*
* Predeclared primitive type indices
*/
public static final int BOOLEAN = 0x20;
public static final int BYTE = 0x21;
public static final int SHORT = 0x22;
public static final int INT = 0x23;
public static final int LONG = 0x24;
public static final int FLOAT = 0x25;
public static final int DOUBLE = 0x26;
public static final int STRING = 0x27;
/*
* Start of user declared types
*/
public static final int FIRST_USER_INDEX = 0x40;
}
package se.lth.control.labcomm2006;
import java.io.IOException;
public interface LabCommDecoder {
public void register(LabCommDispatcher dispatcher,
LabCommHandler handler) throws IOException;
public boolean decodeBoolean() throws IOException;
public byte decodeByte() throws IOException;
public short decodeShort() throws IOException;
public int decodeInt() throws IOException;
public long decodeLong() throws IOException;
public float decodeFloat() throws IOException;
public double decodeDouble() throws IOException;
public String decodeString() throws IOException;
public int decodePacked32() throws IOException;
}
package se.lth.control.labcomm2006;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.InputStream;
import java.io.IOException;
public class LabCommDecoderChannel implements LabCommDecoder {
private DataInputStream in;
private LabCommDecoderRegistry registry;
public LabCommDecoderChannel(InputStream in) throws IOException {
this.in = new DataInputStream(in);
registry = new LabCommDecoderRegistry();
}
public void runOne() throws Exception {
boolean done = false;
while (!done) {
int tag = decodePacked32();
switch (tag) {
case LabComm.TYPEDEF:
case LabComm.SAMPLE: {
int index = decodePacked32();
String name = decodeString();
ByteArrayOutputStream signature = new ByteArrayOutputStream();
collectFlatSignature(new LabCommEncoderChannel(signature, false));
registry.add(index, name, signature.toByteArray());
} break;
default: {
LabCommDecoderRegistry.Entry e = registry.get(tag);
if (e == null) {
throw new IOException("Unhandled tag " + tag);
}
LabCommDispatcher d = e.getDispatcher();
if (d == null) {
throw new IOException("No dispatcher for '" + e.getName() + "'");
}
LabCommHandler 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(LabCommEncoder out) throws IOException {
int type = decodePacked32();
out.encodePacked32(type);
switch (type) {
case LabComm.ARRAY: {
int dimensions = decodePacked32();
out.encodePacked32(dimensions);
for (int i = 0 ; i < dimensions ; i++) {
out.encodePacked32(decodePacked32());
}
collectFlatSignature(out);
} break;
case LabComm.STRUCT: {
int fields = decodePacked32();
out.encodePacked32(fields);
for (int i = 0 ; i < fields ; i++) {
out.encodeString(decodeString());
collectFlatSignature(out);
}
} break;
case LabComm.BOOLEAN:
case LabComm.BYTE:
case LabComm.SHORT:
case LabComm.INT:
case LabComm.LONG:
case LabComm.FLOAT:
case LabComm.DOUBLE:
case LabComm.STRING: {
} break;
default: {
throw new IOException("Unimplemented type=" + type);
}
}
out.end(null);
}
public void register(LabCommDispatcher dispatcher,
LabCommHandler 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);
}
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);
}
}
package se.lth.control.labcomm2006;
import java.io.IOException;
import java.util.HashMap;
public class LabCommDecoderRegistry {
public static class Entry {
private LabCommDispatcher dispatcher;
private LabCommHandler handler;
private int index;
private String name;
private byte[] signature;
public Entry(LabCommDispatcher dispatcher,
LabCommHandler handler) {
this.dispatcher = dispatcher;
this.name = dispatcher.getName();
this.signature = dispatcher.getSignature();
this.handler = handler;
}
public Entry(int index, String name, byte[] signature) {
this.index = index;
this.name = name;
this.signature = signature;
}
public LabCommDispatcher getDispatcher() {
return dispatcher;
}
public void setDispatcher(LabCommDispatcher dispatcher) {
this.dispatcher = dispatcher;
}
public LabCommHandler getHandler() {
return handler;
}
public void setHandler(LabCommHandler handler) {
this.handler = handler;
}
public String getName() {
return name;
}
public int getIndex() {
return index;
}
public void setIndex(int index) throws IOException {
if (this.index != 0 && this.index != index) {
throw new IOException("Index mismatch " +
this.index + " != " + index);
}
this.index = index;
}
public boolean matchName(String name) {
return this.name.equals(name);
}
public boolean matchSignature(byte[] signature) {
boolean result = this.signature.length == signature.length;
for (int i = 0 ; result && i < signature.length ; i++) {
result = this.signature[i] == signature[i];
}
return result;
}
public boolean match(String name, byte[] signature) {
return matchName(name) && matchSignature(signature);
}
public void check(String name, byte[] signature) throws IOException {
if (!matchName(name)) {
throw new IOException("Name mismatch '" +
this.name + "' != '" + name + "'");
}
if (!matchSignature(signature)) {
throw new IOException("Signature mismatch");
}
}
}
private HashMap<Class, Entry> byClass;
private HashMap<Integer, Entry> byIndex;
public LabCommDecoderRegistry() {
byClass = new HashMap<Class, Entry>();
byIndex = new HashMap<Integer, Entry>();
}
public synchronized void add(LabCommDispatcher dispatcher,
LabCommHandler handler) throws IOException{
Entry e = byClass.get(dispatcher.getSampleClass());
if (e != null) {
e.check(dispatcher.getName(), dispatcher.getSignature());
e.setHandler(handler);
} else {
for (Entry e2 : byIndex.values()) {
if (e2.match(dispatcher.getName(), dispatcher.getSignature())) {
e2.setDispatcher(dispatcher);
e2.setHandler(handler);
e = e2;
break;
}
}
if (e == null) {
e = new Entry(dispatcher, handler);
byClass.put(dispatcher.getSampleClass(), e);
}
}
}
public synchronized void add(int index,
String name,
byte[] signature) throws IOException {
Entry e = byIndex.get(Integer.valueOf(index));
if (e != null) {
e.check(name, signature);
} else {
for (Entry e2 : byClass.values()) {
if (e2.match(name, signature)) {
e2.setIndex(index);
e = e2;
break;
}
}
if (e == null) {
e = new Entry(index, name, signature);
}
byIndex.put(Integer.valueOf(index), e);
}
}
public synchronized Entry get(int index) {
return byIndex.get(Integer.valueOf(index));
}
}
\ No newline at end of file
package se.lth.control.labcomm2006;
public interface LabCommDispatcher {
public Class getSampleClass();
public String getName();
public byte[] getSignature();
public void decodeAndHandle(LabCommDecoder decoder,
LabCommHandler handler) throws Exception;
}
package se.lth.control.labcomm2006;
import java.io.IOException;
public interface LabCommEncoder {
public void register(LabCommDispatcher dispatcher) throws IOException;
public void begin(Class<? extends LabCommSample> c) throws IOException;
public void end(Class<? extends LabCommSample> c) throws IOException;
public void encodeBoolean(boolean value) throws IOException;
public void encodeByte(byte value) throws IOException;
public void encodeShort(short value) throws IOException;
public void encodeInt(int value) throws IOException;
public void encodeLong(long value) throws IOException;
public void encodeFloat(float value) throws IOException;
public void encodeDouble(double value) throws IOException;
public void encodeString(String value) throws IOException;
public void encodePacked32(long value) throws IOException;
}
package se.lth.control.labcomm2006;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class LabCommEncoderChannel implements LabCommEncoder {
private LabCommWriter writer;
private ByteArrayOutputStream bytes;
private DataOutputStream data;
private LabCommEncoderRegistry registry;
public LabCommEncoderChannel(LabCommWriter writer,
boolean emitVersion) throws IOException {
this.writer = writer;
bytes = new ByteArrayOutputStream();
data = new DataOutputStream(bytes);
registry = new LabCommEncoderRegistry();
if (emitVersion) {
throw new RuntimeError("Labcomm 2006 does not support emitVersion");
}
}
public LabCommEncoderChannel(LabCommWriter writer) throws IOException {
this(writer, true);
}
public LabCommEncoderChannel(OutputStream writer,
boolean emitVersion) throws IOException {
this(new WriterWrapper(writer), emitVersion);
}
public LabCommEncoderChannel(OutputStream writer) throws IOException {
this(new WriterWrapper(writer), true);
}
public void register(LabCommDispatcher dispatcher) throws IOException {
int index = registry.add(dispatcher);
encodePacked32(LabComm.SAMPLE);
encodePacked32(index);
encodeString(dispatcher.getName());
byte[] signature = dispatcher.getSignature();
for (int i = 0 ; i < signature.length ; i++) {
encodeByte(signature[i]);
}
end(null);
}
public void begin(Class<? extends LabCommSample> c) throws IOException {
encodePacked32(registry.getTag(c));
}
public void end(Class<? extends LabCommSample> c) throws IOException {
data.flush();
//XXX when writer was a stream, it was probably a bit more GC efficient:
//bytes.writeTo(writer);
writer.write(bytes.toByteArray());
bytes.reset();
}
public void encodeBoolean(boolean value) throws IOException{
data.writeBoolean(value);
}
public void encodeByte(byte value) throws IOException {
data.writeByte(value);
}
public void encodeShort(short value) throws IOException {
data.writeShort(value);
}
public void encodeInt(int value) throws IOException {
data.writeInt(value);
}
public void encodeLong(long value) throws IOException {
data.writeLong(value);
}
public void encodeFloat(float value) throws IOException {
data.writeFloat(value);
}
public void encodeDouble(double value) throws IOException {
data.writeDouble(value);
}
public void encodeString(String value) throws IOException {
data.writeShort(0); // HACK...
data.writeUTF(value);
//kludge, to replace above hack with packed length
ByteArrayOutputStream tmpb = new ByteArrayOutputStream();
DataOutputStream tmps = new DataOutputStream(tmpb);
tmps.writeUTF(value);
tmps.flush();
byte[] tmp = tmpb.toByteArray();
encodePacked32(tmp.length-2);
for (int i = 2 ; i < tmp.length ; i++) {
encodeByte(tmp[i]);
}
}
/**
method for API harmonization with labcomm2013.
Labcomm2006 encodes lengths etc as 32 bit ints.
*/
public inline void encodePacked32(long value) throws IOException {
encodeInt(value);
}
}
package se.lth.control.labcomm2006;
import java.io.IOException;
import java.util.HashMap;
public class LabCommEncoderRegistry {
public static class Entry {
private LabCommDispatcher dispatcher;
private int index;
public Entry(LabCommDispatcher dispatcher, int index) {
this.dispatcher = dispatcher;
this.index = index;
}
public LabCommDispatcher getDispatcher() {
return dispatcher;
}
public int getIndex() {
return index;
}
}
private int userIndex = LabComm.FIRST_USER_INDEX;
private HashMap<Class, Entry> byClass;
public LabCommEncoderRegistry() {
byClass = new HashMap<Class, Entry>();
}
public synchronized int add(LabCommDispatcher dispatcher) {
Entry e = byClass.get(dispatcher.getSampleClass());
if (e == null) {
e = new Entry(dispatcher, userIndex);
byClass.put(dispatcher.getSampleClass(), e);
userIndex++;
}
return e.getIndex();
}
public int getTag(Class<? extends LabCommSample> sample) throws IOException {
Entry e = byClass.get(sample);
if (e == null) {
throw new IOException("'" +
sample.getSimpleName() +
"' is not registered");
}
return e.index;
}
}
\ No newline at end of file
package se.lth.control.labcomm2006;
public interface LabCommHandler {
}
\ No newline at end of file
package se.lth.control.labcomm2006;
public interface LabCommReader {
public void handle(byte[] data, int begin, int end);
}
package se.lth.control.labcomm2006;
public interface LabCommSample {
}
\ No newline at end of file
package se.lth.control.labcomm2006;
public interface LabCommType {
}
\ No newline at end of file
package se.lth.control.labcomm2006;
import java.io.IOException;
public interface LabCommWriter {
public void write(byte[] data) throws IOException;
}
package se.lth.control.labcomm2006;
import java.io.OutputStream;
import java.io.IOException;
class WriterWrapper implements LabCommWriter{
private OutputStream os;
public WriterWrapper(OutputStream os) {
this.os = os;
}
public void write(byte[] data) throws IOException {
os.write(data);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment