diff --git a/examples/user_types/Encoder.java b/examples/user_types/ExampleEncoder.java similarity index 75% rename from examples/user_types/Encoder.java rename to examples/user_types/ExampleEncoder.java index cfce51368416313f9f30e92febbd81e60e7540b7..d3cca03d0d8b1ec2f99fcff37672d1c3f9d50911 100644 --- a/examples/user_types/Encoder.java +++ b/examples/user_types/ExampleEncoder.java @@ -2,34 +2,35 @@ import java.io.File; import java.io.FileOutputStream; import java.io.OutputStream; +import se.lth.control.labcomm.Encoder; import se.lth.control.labcomm.EncoderChannel; /** * Simple encoder */ -public class Encoder +public class ExampleEncoder { EncoderChannel encoder; - public Encoder(OutputStream out) + public ExampleEncoder(OutputStream out) throws Exception { encoder = new EncoderChannel(out); twoLines.register(encoder); theint.register(encoder); - //LabCommEncoder.MetaDataTransaction t = encoder.beginMetaData(twoLines.class); - ////LabCommEncoder.MetaDataTransaction t = encoder.beginMetaData(); - //Comment.register(t, false); - //Comment c = new Comment(); + Encoder.PragmaPacketBuilder t = encoder.newPragma("se.lth.cs.sven.pragma"); + Comment.register(t); + Comment c = new Comment(); //c.id = encoder.getTypeId(twoLines.class); - //c.comment = "Test comment"; - //Comment.encode(t,c); - //t.commit(); - //t = encoder.beginMetaData(null); - //afoo.register(t, false); - //afoo.encode(t, new foo()); - //t.commit(); + c.id = 42; + c.comment = "Test comment"; + Comment.encode(t,c); + t.send(); + t = encoder.newPragma(null); + afoo.register(t); + afoo.encode(t, new foo()); + t.send(); } public void doEncode() throws java.io.IOException { @@ -94,7 +95,7 @@ public class Encoder public static void main(String[] arg) throws Exception { FileOutputStream fos = new FileOutputStream(arg[0]); - Encoder example = new Encoder(fos); + ExampleEncoder example = new ExampleEncoder(fos); example.doEncode(); fos.close(); } diff --git a/examples/user_types/Makefile b/examples/user_types/Makefile index 4953342d569b1ede7ebf4fcfa0b86137b9e6f86b..628829274e41460f8bc13f4258a5dc4b48b9be92 100644 --- a/examples/user_types/Makefile +++ b/examples/user_types/Makefile @@ -2,7 +2,7 @@ LCDIR=../.. LCCJAR=${LCDIR}/compiler/labcomm_compiler.jar # the LabComm compiler LCLJAR=${LCDIR}/lib/java/labcomm.jar # the LabComm library -EXECUTABLES=example_encoder example_decoder Encoder.class Decoder.class Encoder.exe Decoder.exe +EXECUTABLES=example_encoder example_decoder ExampleEncoder.class Decoder.class Encoder.exe Decoder.exe include ${LCDIR}/lib/c/os_compat.mk GENDIR=gen @@ -44,7 +44,7 @@ build : mkdir -p ${GENDIR} java -jar ${LCDIR}/compiler/labcomm_compiler.jar --java=${GENDIR} --c=${GENDIR}/test.c --h=${GENDIR}/test.h --python=${GENDIR}/test.py --cs=${GENDIR}/test.cs test.lc - javac -cp ${LCDIR}/lib/java/labcomm.jar:. ${GENDIR}/*.java Encoder.java Decoder.java + javac -cp ${LCDIR}/lib/java/labcomm.jar:. ${GENDIR}/*.java ExampleEncoder.java Decoder.java ${CC} ${CFLAGS} ${LDFLAGS} -Wall -Werror -Wno-unused-function \ -I. -I${LCDIR}/lib/c -L${LCDIR}/lib/c \ @@ -65,7 +65,7 @@ run: @echo "********************************************" @echo - @java -cp .:${LCDIR}/lib/java/labcomm.jar:${GENDIR} Encoder encoded_data_j + @java -cp .:${LCDIR}/lib/java/labcomm.jar:${GENDIR} ExampleEncoder encoded_data_j @echo "************ running Java decoder: *****************" @java -cp .:${LCDIR}/lib/java/labcomm.jar:${GENDIR} Decoder encoded_data_j @@ -108,7 +108,7 @@ runwcs: Encoder.exe Decoder.exe @echo "********************************************" @echo - @java -cp .:${LCDIR}/lib/java/labcomm.jar:${GENDIR} Encoder encoded_data_j + @java -cp .:${LCDIR}/lib/java/labcomm.jar:${GENDIR} ExampleEncoder encoded_data_j @echo "************ running Java decoder: *****************" @java -cp .:${LCDIR}/lib/java/labcomm.jar:${GENDIR} Decoder encoded_data_j diff --git a/lib/java/se/lth/control/labcomm/DecoderChannel.java b/lib/java/se/lth/control/labcomm/DecoderChannel.java index 2397a1609d98326b733cd07fa3f4389f889011f1..b4b561e742f072f2920e31265cd1cd7e8366aa48 100644 --- a/lib/java/se/lth/control/labcomm/DecoderChannel.java +++ b/lib/java/se/lth/control/labcomm/DecoderChannel.java @@ -37,7 +37,7 @@ public class DecoderChannel implements Decoder { // decodeByte(); // } String type = decodeString(); - int plen = len - (type.length()+1); // XXX HERE BE DRAGONS: +1? + int plen = len - Encoder.Util.sizeof_string(type); System.out.println("[ begin pragma ("+type+") ]"); //System.out.println("metadata : "+len + " bytes, ref: " + Integer.toHexString(typeRefId)+"."); byte buf[] = new byte[plen]; diff --git a/lib/java/se/lth/control/labcomm/Encoder.java b/lib/java/se/lth/control/labcomm/Encoder.java index d6ef3e5ff2a08502dcde3c548a36e58aa9a5faf5..b646b6b088159e9f4fdc20ea0e00cc91dc1c3f63 100644 --- a/lib/java/se/lth/control/labcomm/Encoder.java +++ b/lib/java/se/lth/control/labcomm/Encoder.java @@ -1,10 +1,15 @@ package se.lth.control.labcomm; import java.io.IOException; +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; public interface Encoder { public void register(SampleDispatcher dispatcher) throws IOException; + //HERE BE DRAGONS: for internal use, but needs to be public + //in Java interfaces... + public void begin(int tag) throws IOException; public void begin(Class<? extends Sample> c) throws IOException; public void end(Class<? extends Sample> c) throws IOException; public void encodeBoolean(boolean value) throws IOException; @@ -17,4 +22,93 @@ public interface Encoder { public void encodeString(String value) throws IOException; public void encodePacked32(long value) throws IOException; + public PragmaPacketBuilder newPragma(String type) throws IOException; + + static class Util { + /* Aux method to get encoded size of packed32 variable */ + //static int sizeofPacked32(int... vars) + static int sizeof_packed32(int data){ + int result = 0; + //for(int data : vars) { + //XXX fixme... define number range for packed32 + if(data < 0) throw new Error("TODO: emulate unsigned int..."); + int i; + + for (i = 0 ; i == 0 || data != 0 ; i++, data = (data >> 7)) { + result++; + } + // } + return result; + + } + static int sizeof_string(String s){ + int len = s.length(); + return len+sizeof_packed32(len); + } + } + + public static class PragmaPacketBuilder implements Encoder { + private final ByteArrayOutputStream bytes ; + private final DataOutputStream data ; + private final Encoder encoder, tempEncoder ; + private final EncoderRegistry reg; + private final String type; + private boolean sent = false; + //private final int typeRef; + //private Class<? extends LabCommSample> typeRef; + + PragmaPacketBuilder(Encoder e, EncoderRegistry reg, String type) throws IOException { + bytes = new ByteArrayOutputStream(); + data = new DataOutputStream(bytes); + encoder = e; + this.reg = reg; + this.type = (type==null)?"undefined":type; + System.out.println("PragmaPacketBuilder: "+this.type); + tempEncoder = new EncoderChannel(data,e,false); + } + + public void send() throws IOException { + if(sent) throw new IOException("Already sent."); + tempEncoder.end(null); + data.close(); + byte[] b = bytes.toByteArray(); + //System.out.println("LabCommEncoder.MetaDataTransaction committing "+b.length+" bytes"); + //encoder.encodePacked32(Constant.PRAGMA); + //encoder.encodePacked32(b.length); + encoder.begin(Constant.PRAGMA); + encoder.encodeString(this.type); + + for (int i = 0 ; i < b.length ; i++) { + encoder.encodeByte(b[i]); + } + encoder.end(null); + } + // forward everything to tempEncoder + public void register(SampleDispatcher dispatcher) throws IOException {tempEncoder.register(dispatcher);} + + //XXX hack for registration + public void begin(Class<? extends Sample> c) throws IOException{ + System.err.println("begin..."); + try { + tempEncoder.begin(c); + } catch (IOException e) { + System.err.println("trying lookup in enclosing encoder..."); + tempEncoder.encodePacked32(reg.getTag(c)); + } + } + public void begin(int c) throws IOException{ + tempEncoder.begin(c); + } + public void end(Class<? extends Sample> c) throws IOException{tempEncoder.end(c);} + public void encodeBoolean(boolean value) throws IOException{tempEncoder.encodeBoolean(value);} + public void encodeByte(byte value) throws IOException{tempEncoder.encodeByte(value);} + public void encodeShort(short value) throws IOException{tempEncoder.encodeShort(value);} + public void encodeInt(int value) throws IOException{tempEncoder.encodeInt(value);} + public void encodeLong(long value) throws IOException{tempEncoder.encodeLong(value);} + public void encodeFloat(float value) throws IOException{tempEncoder.encodeFloat(value);} + public void encodeDouble(double value) throws IOException{tempEncoder.encodeDouble(value);} + public void encodeString(String value) throws IOException{tempEncoder.encodeString(value);} + public void encodePacked32(long value) throws IOException{tempEncoder.encodePacked32(value);} + public PragmaPacketBuilder newPragma(String type) throws IOException {throw new IOException("PragmaPacketBuilders do not nest");} + } } diff --git a/lib/java/se/lth/control/labcomm/EncoderChannel.java b/lib/java/se/lth/control/labcomm/EncoderChannel.java index 08ef0fc415a064e63b4158e4d52bc82f0e8d86e2..962a04f5f23cac83bf4a9e5fc7af0ccd9a38c376 100644 --- a/lib/java/se/lth/control/labcomm/EncoderChannel.java +++ b/lib/java/se/lth/control/labcomm/EncoderChannel.java @@ -14,20 +14,44 @@ public class EncoderChannel implements Encoder { private int current_tag; public EncoderChannel(Writer writer) throws IOException { - this.writer = writer; - bytes = new ByteArrayOutputStream(); - data = new DataOutputStream(bytes); - registry = new EncoderRegistry(); + this(writer, true); + } - begin(Constant.VERSION); - encodeString(Constant.CURRENT_VERSION); - end(null); + public EncoderChannel(OutputStream writer) throws IOException { + this(writer, true); } - public EncoderChannel(OutputStream writer) throws IOException { - this(new WriterWrapper(writer)); + EncoderChannel(Writer writer, boolean emitVersion) throws IOException { + this(writer, new EncoderRegistry(), emitVersion); + } + + private EncoderChannel(Writer writer, + EncoderRegistry registry, + boolean emitVersion) throws IOException { + this.writer = writer; + this.bytes = new ByteArrayOutputStream(); + this.data = new DataOutputStream(bytes); + this.registry = registry; + + if(emitVersion) { + begin(Constant.VERSION); + encodeString(Constant.CURRENT_VERSION); + end(null); + } } + EncoderChannel(OutputStream writer, boolean emitVersion) throws IOException { + this(new WriterWrapper(writer), emitVersion); + } + + /* for sharing registry with PragmaPacketBuilder */ + EncoderChannel(OutputStream writer, + Encoder e, + boolean emitVersion) throws IOException { + this(new WriterWrapper(writer), (e instanceof EncoderChannel) ? ((EncoderChannel)e).registry : new EncoderRegistry(), emitVersion); + } + + public void register(SampleDispatcher dispatcher) throws IOException { int index = registry.add(dispatcher); begin(Constant.SAMPLE_DEF); @@ -41,7 +65,7 @@ public class EncoderChannel implements Encoder { end(null); } - private void begin(int tag) { + public void begin(int tag) { current_tag = tag; bytes.reset(); } @@ -131,5 +155,9 @@ public class EncoderChannel implements Encoder { encodeByte((byte)(tmp[i] | (i!=0?0x80:0x00))); } } + + public PragmaPacketBuilder newPragma(String type) throws IOException{ + return new PragmaPacketBuilder(this, registry, type); + } }